Project import.
diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 0000000..d528f9c --- /dev/null +++ b/ABOUT-NLS
@@ -0,0 +1,435 @@ +Notes on the Free Translation Project +************************************* + + Free software is going international! The Free Translation Project +is a way to get maintainers of free software, translators, and users all +together, so that will gradually become able to speak many languages. +A few packages already provide translations for their messages. + + If you found this `ABOUT-NLS' file inside a distribution, you may +assume that the distributed package does use GNU `gettext' internally, +itself available at your nearest GNU archive site. But you do _not_ +need to install GNU `gettext' prior to configuring, installing or using +this package with messages translated. + + Installers will find here some useful hints. These notes also +explain how users should proceed for getting the programs to use the +available translations. They tell how people wanting to contribute and +work at translations should contact the appropriate team. + + When reporting bugs in the `intl/' directory or bugs which may be +related to internationalization, you should tell about the version of +`gettext' which is used. The information can be found in the +`intl/VERSION' file, in internationalized packages. + +Quick configuration advice +========================== + + If you want to exploit the full power of internationalization, you +should configure it using + + ./configure --with-included-gettext + +to force usage of internationalizing routines provided within this +package, despite the existence of internationalizing capabilities in the +operating system where this package is being installed. So far, only +the `gettext' implementation in the GNU C library version 2 provides as +many features (such as locale alias, message inheritance, automatic +charset conversion or plural form handling) as the implementation here. +It is also not possible to offer this additional functionality on top +of a `catgets' implementation. Future versions of GNU `gettext' will +very likely convey even more functionality. So it might be a good idea +to change to GNU `gettext' as soon as possible. + + So you need _not_ provide this option if you are using GNU libc 2 or +you have installed a recent copy of the GNU gettext package with the +included `libintl'. + +INSTALL Matters +=============== + + Some packages are "localizable" when properly installed; the +programs they contain can be made to speak your own native language. +Most such packages use GNU `gettext'. Other packages have their own +ways to internationalization, predating GNU `gettext'. + + By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system already +provides the GNU `gettext' functions. If not, the GNU `gettext' own +library will be used. This library is wholly contained within this +package, usually in the `intl/' subdirectory, so prior installation of +the GNU `gettext' package is _not_ required. Installers may use +special options at configuration time for changing the default +behaviour. The commands: + + ./configure --with-included-gettext + ./configure --disable-nls + +will respectively bypass any pre-existing `gettext' to use the +internationalizing routines provided within this package, or else, +_totally_ disable translation of messages. + + When you already have GNU `gettext' installed on your system and run +configure without an option for your new package, `configure' will +probably detect the previously built and installed `libintl.a' file and +will decide to use this. This might be not what is desirable. You +should use the more recent version of the GNU `gettext' library. I.e. +if the file `intl/VERSION' shows that the library which comes with this +package is more recent, you should use + + ./configure --with-included-gettext + +to prevent auto-detection. + + The configuration process will not test for the `catgets' function +and therefore it will not be used. The reason is that even an +emulation of `gettext' on top of `catgets' could not provide all the +extensions of the GNU `gettext' library. + + Internationalized packages have usually many `po/LL.po' files, where +LL gives an ISO 639 two-letter code identifying the language. Unless +translations have been forbidden at `configure' time by using the +`--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable `LINGUAS' +may be set, prior to configuration, to limit the installed set. +`LINGUAS' should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +Using This Package +================== + + As a user, if your language has been installed for this package, you +only have to set the `LANG' environment variable to the appropriate +`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, +and `CC' is an ISO 3166 two-letter country code. For example, let's +suppose that you speak German and live in Germany. At the shell +prompt, merely execute `setenv LANG de_DE' (in `csh'), +`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). +This can be done from your `.login' or `.profile' file, once and for +all. + + You might think that the country code specification is redundant. +But in fact, some languages have dialects in different countries. For +example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The +country code serves to distinguish the dialects. + + The locale naming convention of `LL_CC', with `LL' denoting the +language and `CC' denoting the country, is the one use on systems based +on GNU libc. On other systems, some variations of this scheme are +used, such as `LL' or `LL_CC.ENCODING'. You can get the list of +locales supported by your system for your country by running the command +`locale -a | grep '^LL''. + + Not all programs have translations for all languages. By default, an +English message is shown in place of a nonexistent translation. If you +understand other languages, you can set up a priority list of languages. +This is done through a different environment variable, called +`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' +for the purpose of message handling, but you still need to have `LANG' +set to the primary language; this is required by other parts of the +system libraries. For example, some Swedish users who would rather +read translations in German than English for when Swedish is not +available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. + + In the `LANGUAGE' environment variable, but not in the `LANG' +environment variable, `LL_CC' combinations can be abbreviated as `LL' +to denote the language's main dialect. For example, `de' is equivalent +to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' +(Portuguese as spoken in Portugal) in this context. + +Translating Teams +================= + + For the Free Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list. The up-to-date list of +teams can be found at the Free Translation Project's homepage, +`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" +area. + + If you'd like to volunteer to _work_ at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is _not_ the same as the list itself, it has +`-request' appended. For example, speakers of Swedish can send a +message to `sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate +_actively_ in translations, or at solving translational difficulties, +rather than merely lurking around. If your team does not exist yet and +you want to start one, or if you are unsure about what to do or how to +get started, please write to `translation@iro.umontreal.ca' to reach the +coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing +the terminology in use. Proven linguistic skill are praised more than +programming skill, here. + +Available Packages +================== + + Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of August +2002. The matrix shows, in regard of each package, for which languages +PO files have been submitted to translation coordination, with a +translation percentage of at least 50%. + + Ready PO files be bg ca cs da de el en eo es et fi fr + +----------------------------------------+ + a2ps | [] [] [] [] | + ap-utils | | + bash | [] [] [] [] | + bfd | [] [] | + binutils | [] [] | + bison | [] [] [] [] | + clisp | | + clisp | [] [] [] [] | + clisplow | | + cpio | [] [] [] [] | + darkstat | () | + diffutils | [] [] [] [] [] [] | + enscript | [] [] | + error | [] [] [] | + fetchmail | [] () [] [] [] () | + fileutils | [] [] [] [] [] | + findutils | [] [] [] [] [] [] | + flex | [] [] [] [] [] | + gas | [] [] | + gawk | [] [] [] | + gcal | [] [] | + gcc | [] [] | + gettext | [] [] [] [] [] | + gnupg | [] [] [] [] [] [] [] | + gprof | [] [] | + gpsdrive | () () () () () | + grep | [] [] [] [] [] [] [] [] | + gretl | [] | + gthumb | () () () | + hello | [] [] [] [] [] [] [] [] [] | + id-utils | [] [] [] | + indent | [] [] [] [] [] | + jpilot | () [] [] [] | + jwhois | [] [] | + kbd | [] [] [] | + ld | [] [] | + libc | [] [] [] [] [] [] [] [] | + libiconv | [] [] [] [] | + lifelines | () () | + lilypond | [] [] | + lingoteach | [] [] | + lingoteach_lessons| () () | + lynx | [] [] [] [] [] | + m4 | [] [] [] [] [] | + make | [] [] [] [] | + man-db | [] () () [] () () | + mysecretdiary | [] [] [] | + nano | [] () [] [] [] [] | + nano_1_0 | [] () [] [] [] [] | + opcodes | [] [] [] | + parted | [] [] [] [] [] | + ptx | [] [] [] [] [] [] [] | + python | | + recode | [] [] [] [] [] [] | + sed | [] [] [] [] [] [] [] [] [] [] | + sh-utils | [] [] [] [] | + sharutils | [] [] [] [] [] [] [] | + sketch | () [] () | + soundtracker | [] [] [] | + sp | [] | + tar | [] [] [] [] [] [] | + texinfo | [] [] [] [] [] | + textutils | [] [] [] [] [] | + util-linux | [] [] [] [] [] [] | + vorbis-tools | [] | + wastesedge | | + wdiff | [] [] [] [] [] [] | + wget | [] [] [] [] [] [] [] [] [] [] | + +----------------------------------------+ + be bg ca cs da de el en eo es et fi fr + 0 2 19 10 30 44 9 1 12 44 17 6 53 + + gl he hr hu id it ja ko lv nb nl nn + +-------------------------------------+ + a2ps | () () [] | + ap-utils | | + bash | [] | + bfd | [] | + binutils | [] | + bison | [] [] [] [] | + clisp | | + clisp | [] | + clisplow | | + cpio | [] [] [] [] | + darkstat | | + diffutils | [] [] [] [] [] | + enscript | [] [] | + error | [] | + fetchmail | [] | + fileutils | [] [] [] | + findutils | [] [] [] [] [] [] [] [] | + flex | [] | + gas | | + gawk | [] | + gcal | | + gcc | [] | + gettext | [] [] | + gnupg | [] [] [] [] | + gprof | [] | + gpsdrive | [] () () | + grep | [] [] [] [] [] [] [] | + gretl | | + gthumb | () () | + hello | [] [] [] [] [] [] [] [] [] [] [] [] | + id-utils | [] [] | + indent | [] [] [] [] | + jpilot | () () | + jwhois | [] [] | + kbd | | + ld | | + libc | [] [] [] [] | + libiconv | [] [] [] | + lifelines | | + lilypond | [] | + lingoteach | [] | + lingoteach_lessons| | + lynx | [] [] [] [] | + m4 | [] [] [] [] | + make | [] [] [] [] [] [] | + man-db | () () | + mysecretdiary | [] | + nano | [] [] [] [] | + nano_1_0 | [] [] [] [] [] | + opcodes | [] [] | + parted | [] [] [] | + ptx | [] [] [] [] [] | + python | | + recode | [] [] [] | + sed | [] [] [] [] [] [] [] [] | + sh-utils | [] [] [] | + sharutils | [] [] [] | + sketch | () | + soundtracker | [] [] | + sp | | + tar | [] [] [] [] [] [] | + texinfo | [] [] [] | + textutils | [] [] [] [] | + util-linux | () [] | + vorbis-tools | [] | + wastesedge | | + wdiff | [] [] [] | + wget | [] [] [] [] [] [] | + +-------------------------------------+ + gl he hr hu id it ja ko lv nb nl nn + 23 9 12 19 16 13 26 9 1 7 19 3 + + no pl pt pt_BR ru sk sl sv tr uk zh_CN zh_TW + +----------------------------------------------+ + a2ps | () () () [] [] [] [] [] | 10 + ap-utils | () | 0 + bash | [] | 6 + bfd | [] [] | 5 + binutils | [] [] | 5 + bison | [] [] [] [] | 12 + clisp | | 0 + clisp | | 5 + clisplow | | 0 + cpio | [] [] [] [] | 12 + darkstat | [] [] () () | 2 + diffutils | [] [] [] [] [] [] | 17 + enscript | [] [] [] [] | 8 + error | [] [] [] | 7 + fetchmail | () () [] | 6 + fileutils | [] [] [] [] [] [] | 14 + findutils | [] [] [] [] [] [] [] | 21 + flex | [] [] [] | 9 + gas | [] | 3 + gawk | [] [] | 6 + gcal | [] [] | 4 + gcc | [] | 4 + gettext | [] [] [] [] [] [] | 13 + gnupg | [] [] [] | 14 + gprof | [] [] | 5 + gpsdrive | [] [] | 3 + grep | [] [] [] [] [] | 20 + gretl | | 1 + gthumb | () () [] | 1 + hello | [] [] [] [] [] [] [] | 28 + id-utils | [] [] [] [] | 9 + indent | [] [] [] [] [] | 14 + jpilot | () () [] [] | 5 + jwhois | [] () () [] [] | 7 + kbd | [] [] | 5 + ld | [] [] | 4 + libc | [] [] [] [] [] [] | 18 + libiconv | [] [] [] [] [] | 12 + lifelines | [] | 1 + lilypond | [] | 4 + lingoteach | [] [] | 5 + lingoteach_lessons| () | 0 + lynx | [] [] [] [] | 13 + m4 | [] [] [] [] | 13 + make | [] [] [] [] [] | 15 + man-db | | 3 + mysecretdiary | [] [] [] | 7 + nano | [] [] [] [] | 13 + nano_1_0 | [] [] [] [] | 14 + opcodes | [] [] [] | 8 + parted | [] [] [] [] | 12 + ptx | [] [] [] [] [] [] [] | 19 + python | | 0 + recode | [] [] [] [] [] [] | 15 + sed | [] [] [] [] [] [] | 24 + sh-utils | [] [] | 9 + sharutils | [] [] [] [] | 14 + sketch | [] () [] | 4 + soundtracker | [] | 6 + sp | | 1 + tar | [] [] [] [] [] [] [] | 19 + texinfo | [] [] | 10 + textutils | [] [] [] [] [] | 14 + util-linux | [] [] [] | 10 + vorbis-tools | [] | 3 + wastesedge | | 0 + wdiff | [] [] [] [] [] | 14 + wget | [] [] [] [] [] [] [] [] | 24 + +----------------------------------------------+ + 37 teams no pl pt pt_BR ru sk sl sv tr uk zh_CN zh_TW + 68 domains 4 15 2 28 28 12 10 49 43 4 1 9 609 + + Some counters in the preceding matrix are higher than the number of +visible blocks let us expect. This is because a few extra PO files are +used for implementing regional variants of languages, or language +dialects. + + For a PO file in the matrix above to be effective, the package to +which it applies should also have been internationalized and +distributed as such by its maintainer. There might be an observable +lag between the mere existence a PO file and its wide availability in a +distribution. + + If August 2002 seems to be old, you may fetch a more recent copy of +this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date +matrix with full percentage details can be found at +`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. + +Using `gettext' in new packages +=============================== + + If you are writing a freely available program and want to +internationalize it you are welcome to use GNU `gettext' in your +package. Of course you have to respect the GNU Library General Public +License which covers the use of the GNU `gettext' library. This means +in particular that even non-free programs can use `libintl' as a shared +library, whereas only free software can use `libintl' as a static +library or use modified versions of `libintl'. + + Once the sources are changed appropriately and the setup can handle +to use of `gettext' the only thing missing are the translations. The +Free Translation Project is also available for packages which are not +developed inside the GNU project. Therefore the information given above +applies also for every other Free Software Project. Contact +`translation@iro.umontreal.ca' to make the `.pot' files available to +the translation teams. +
diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..dd1227b --- /dev/null +++ b/COPYING
@@ -0,0 +1,849 @@ +This package, the EXT2 filesystem utilities, are made available under +the GNU Public License version 2, with the exception of the lib/ext2fs +and lib/e2p libraries, which are made available under the GNU Library +General Public License Version 2, the lib/uuid library which is made +available under a BSD-style license and the lib/et and lib/ss +libraries which are made available under an MIT-style license. Please +see lib/uuid/COPYING for more details for the license for the files +comprising the libuuid library, and the source file headers of the +libet and libss libraries for more information. + +The most recent officially distributed version can be found at +http://e2fsprogs.sourceforge.net. If you need to make a distribution, +that's the one you should use. If there is some reason why you'd like +a more recent version that is still in ALPHA testing (i.e., either +using the "WIP" test distributions or one from the hg or git +repository from the development branch, please contact me +(tytso@mit.edu) before you ship. The release schedules for this +package are flexible, if you give me enough lead time. + + + Theodore Ts'o + 23-June-2007 + +---------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +---------------------------------------------------------------------- + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library 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 Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it!
diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..b5afd2f --- /dev/null +++ b/INSTALL
@@ -0,0 +1,69 @@ + To install the second extended file system management programs, +just follow the steps: + +1) Change directory into the top of the e2fsprogs source tree + +2) Create a build directory and cd into it: + + mkdir build; cd build + +3) Run the configure script + + ../configure + + If you wish to turn on ELF shared libraries, add the option +--enable-elf-shlibs. If you wish to build profiling libraries, add +the option --enable-profile. + + Note that if you are building on an older system (i.e., a 2.4 +kernel and/or glibc 2.2), the use of thread local storage will probably +cause programs that use the uuid library to core dump. To disable +thread local storage, use the configure option --disable-tls. + +4) Compile the programs + + make + +5) Check to make sure the installation built correctly: + + make check + +6) Install the programs + + Run `make install' + +7) Install the include files and libraries + + You can run `make install-libs' to install the include files and +libraries. Please note that this installation is not needed for the +programs to work. It is only needed if you expect to develop other +programs using the libraries or if you want to compile other program +using these libraries (like the 4.4BSD dump and restore port). + +8) Remove any pre-formatted man pages. + + Some distributions will have pre-formatted manual pages which +will always be displayed in preference to newer man pages in /usr/man. +If this is the case, you may need to manually remove them in order to +see the correct manual pages. The shell script in +install-utils/remove_preformat_manpages may be helpful in doing so. + +9) Make sure your /etc/fstab file is correct. + + Some distributions install an /etc/fstab which is missing the +fifth and sixth field of filesystem entry, which are the dump +frequency, and the fsck pass number, respectively. The problem with +this is that the getmntent() library routine interprets those missing +fields as "0", and a pass number of 0 is documented as meaning that +fsck should not check that particular filesystem. If your entries in +your /etc/fstab file look liks this: + +/dev/hda4 / ext2 defaults + +you should add "1 1" at the end of each line, so that they look like this: + +/dev/hda4 / ext2 defaults 1 1 + + There is a script in install-utils/convfstab (donated by +Michael Weller) that may help you correct your /etc/fstab file. +
diff --git a/INSTALL.elfbin b/INSTALL.elfbin new file mode 100644 index 0000000..3f54aa1 --- /dev/null +++ b/INSTALL.elfbin
@@ -0,0 +1,53 @@ +NOTE: This is the ELF version of the binary distribution. If you have +a DLL system, please compile e2fsprogs from sources yourself. (In +fact, in general you're better off compiling e2fsprogs from sources +instead of using precompiled binaries.) + +Also please note that these binaries assume the use of the GNU Libc. +If you're still using libc5, you'll need build e2fsprogs from source. + + To install the binary distribution of the second extended file +system management programs, just follow the steps: + +1) Install this tar file using the following command: + + gunzip < e2fsprogs-1.13-elfbin.tar.gz | (cd /; tar Sxvpf - ) + +2) Run ldconfig to update the shared library pointers. + + As root, type /sbin/ldconfig. This will update the links to +the shared libraries included in the distribution. You can then remove +the old versions of the libraries from /lib. + +3) Remove any pre-formatted man pages. + + Some distributions will have pre-formatted manual pages which +will always be displayed in preference to newer man pages in /usr/man. +If this is the case, you may need to manually remove them in order to +see the correct manual pages. The shell script in +install-utils/remove_preformat_manpages may be helpful in doing so. + +4) Make sure your /etc/fstab file is correct. + + Some distributions install an /etc/fstab which is missing the +fifth and sixth field of filesystem entry, which are the dump +frequency, and the fsck pass number, respectively. The problem with +this is that the getmntent() library routine interprets those missing +fields as "0", and a pass number of 0 is documented as meaning that +fsck should not check that particular filesystem. If your entries in +your /etc/fstab file look liks this: + +/dev/hda4 / ext2 defaults + +you should add "1 1" at the end of each line, so that they look like this: + +/dev/hda4 / ext2 defaults 1 1 + + There is a script in install-utils/convfstab (donated by +Michael Weller) that may help you correct your /etc/fstab file. + +5) Cleanup files from the installation. + + When you're done with the installation, you will probably want +to remove /INSTALL (this file), /README, and /install-utils from your +root directory
diff --git a/MCONFIG.in b/MCONFIG.in new file mode 100644 index 0000000..f1003cf --- /dev/null +++ b/MCONFIG.in
@@ -0,0 +1,292 @@ +# Beginning of file MCONFIG + +all:: + +check:: + +SHELL = /bin/sh + +COMPRESS_EXT = gz bz2 bz Z + +prefix = @prefix@ +root_prefix = @root_prefix@ +exec_prefix = @exec_prefix@ +root_bindir = @root_bindir@ +root_sbindir = @root_sbindir@ +root_libdir = @root_libdir@ +datarootdir = @datarootdir@ +bindir = @bindir@ +sbindir = @sbindir@ +libdir = @libdir@ +datadir= @datadir@ +localedir = $(datadir)/locale +root_sysconfdir= @root_sysconfdir@ +includedir = @includedir@ +mandir = @mandir@ +man1dir = $(mandir)/man1 +man3dir = $(mandir)/man3 +man5dir = $(mandir)/man5 +man8dir = $(mandir)/man8 +infodir = @infodir@ +datadir = @datadir@ +pkgconfigdir = $(libdir)/pkgconfig + +@SET_MAKE@ + +@ifGNUmake@ V = +@ifGNUmake@ ifeq ($(strip $(V)),) +@ifGNUmake@ # E = @echo +@ifGNUmake@ # ES = echo +@ifGNUmake@ # Q = @ +@ifGNUmake@ E = @E@ +@ifGNUmake@ ES = @ES@ +@ifGNUmake@ Q = @Q@ +@ifGNUmake@ else +@ifGNUmake@ E = @\# +@ifGNUmake@ ES = \# +@ifGNUmake@ Q = +@ifGNUmake@ endif + +@ifNotGNUmake@ E = @E@ +@ifNotGNUmake@ ES = @ES@ +@ifNotGNUmake@ Q = @Q@ + +@ifGNUmake@ CHECK=sparse +@ifGNUmake@ CHECK_OPTS=-Wsparse-all -Wno-transparent-union -Wno-return-void -Wno-undef -Wno-non-pointer-null +@ifGNUmake@ ifeq ("$(C)", "2") +@ifGNUmake@ CHECK_CMD=$(CHECK) $(CHECK_OPTS) -Wbitwise -D__CHECK_ENDIAN__ +@ifGNUmake@ else +@ifGNUmake@ ifeq ("$(C)", "1") +@ifGNUmake@ CHECK_CMD=$(CHECK) $(CHECK_OPTS) +@ifGNUmake@ else +@ifGNUmake@ CHECK_CMD=@true +@ifGNUmake@ endif +@ifGNUmake@ endif + +@ifNotGNUmake@ CHECK_CMD=@true + +CC = @CC@ +BUILD_CC = @BUILD_CC@ +CFLAGS = @CFLAGS@ @DEFS@ +CPPFLAGS = @INCLUDES@ +ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS) +LDFLAGS = @LDFLAGS@ +ALL_LDFLAGS = $(LDFLAGS) @LDFLAG_DYNAMIC@ +LDFLAGS_STATIC = $(LDFLAGS) @LDFLAG_STATIC@ +BUILD_CFLAGS = @BUILD_CFLAGS@ +BUILD_LDFLAGS = @BUILD_LDFLAGS@ +RDYNAMIC = @RDYNAMIC@ +LINK_BUILD_FLAGS = @LINK_BUILD_FLAGS@ +LINK_INSTALL_FLAGS = @LINK_INSTALL_FLAGS@ +RM = @RM@ +LN = @LN@ +LN_S = @LN_S@ +MV = @MV@ +CP = @CP@ +CHMOD = @CHMOD@ +AR = @AR@ +AWK = @AWK@ +SED = @SED@ +PERL = @PERL@ +RANLIB = @RANLIB@ +STRIP = @STRIP@ +LD = $(PURE) @CC@ +ARUPD = $(AR) r +ARGEN = $(AR) rc +LDCONFIG = @LDCONFIG@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +MKINSTALLDIRS = @MKINSTALLDIRS@ + +# +# Library definitions +# +LIB = $(top_builddir)/lib +LIBSS = $(LIB)/libss@LIB_EXT@ @PRIVATE_LIBS_CMT@ @DLOPEN_LIB@ +LIBCOM_ERR = $(LIB)/libcom_err@LIB_EXT@ @PRIVATE_LIBS_CMT@ @SEM_INIT_LIB@ +LIBE2P = $(LIB)/libe2p@LIB_EXT@ +LIBEXT2FS = $(LIB)/libext2fs@LIB_EXT@ +LIBUUID = @LIBUUID@ @SOCKET_LIB@ +LIBQUOTA = @STATIC_LIBQUOTA@ +LIBBLKID = @LIBBLKID@ @PRIVATE_LIBS_CMT@ $(LIBUUID) +LIBINTL = @LIBINTL@ +SYSLIBS = @LIBS@ +DEPLIBSS = $(LIB)/libss@LIB_EXT@ +DEPLIBCOM_ERR = $(LIB)/libcom_err@LIB_EXT@ +DEPLIBUUID = @DEPLIBUUID@ +DEPLIBQUOTA = @DEPSTATIC_LIBQUOTA@ +DEPLIBBLKID = @DEPLIBBLKID@ @PRIVATE_LIBS_CMT@ $(DEPLIBUUID) +TESTENV = LD_LIBRARY_PATH="$(LIB):$${LD_LIBRARY_PATH}" DYLD_LIBRARY_PATH="$(LIB):$${DYLD_LIBRARY_PATH}" + +STATIC_LIBSS = $(LIB)/libss@STATIC_LIB_EXT@ @DLOPEN_LIB@ +STATIC_LIBCOM_ERR = $(LIB)/libcom_err@STATIC_LIB_EXT@ @SEM_INIT_LIB@ +STATIC_LIBE2P = $(LIB)/libe2p@STATIC_LIB_EXT@ +STATIC_LIBEXT2FS = $(LIB)/libext2fs@STATIC_LIB_EXT@ +STATIC_LIBUUID = @STATIC_LIBUUID@ @SOCKET_LIB@ +STATIC_LIBQUOTA = @STATIC_LIBQUOTA@ +STATIC_LIBBLKID = @STATIC_LIBBLKID@ $(STATIC_LIBUUID) +DEPSTATIC_LIBSS = $(LIB)/libss@STATIC_LIB_EXT@ +DEPSTATIC_LIBCOM_ERR = $(LIB)/libcom_err@STATIC_LIB_EXT@ +DEPSTATIC_LIBUUID = @DEPSTATIC_LIBUUID@ +DEPSTATIC_LIBQUOTA = @DEPSTATIC_LIBQUOTA@ +DEPSTATIC_LIBBLKID = @DEPSTATIC_LIBBLKID@ $(DEPSTATIC_LIBUUID) + +PROFILED_LIBSS = $(LIB)/libss@PROFILED_LIB_EXT@ @DLOPEN_LIB@ +PROFILED_LIBCOM_ERR = $(LIB)/libcom_err@PROFILED_LIB_EXT@ @SEM_INIT_LIB@ +PROFILED_LIBE2P = $(LIB)/libe2p@PROFILED_LIB_EXT@ +PROFILED_LIBEXT2FS = $(LIB)/libext2fs@PROFILED_LIB_EXT@ +PROFILED_LIBUUID = @PROFILED_LIBUUID@ @SOCKET_LIB@ +PROFILED_LIBQUOTA = @PROFILED_LIBQUOTA@ +PROFILED_LIBBLKID = @PROFILED_LIBBLKID@ $(PROFILED_LIBUUID) +DEPPROFILED_LIBSS = $(LIB)/libss@PROFILED_LIB_EXT@ +DEPPROFILED_LIBCOM_ERR = $(LIB)/libcom_err@PROFILED_LIB_EXT@ +DEPPROFILED_LIBUUID = @PROFILED_LIBUUID@ +DEPPROFILED_LIBQUOTA = @PROFILED_LIBQUOTA@ +DEPPROFILED_LIBBLKID = @PROFILED_LIBBLKID@ $(DEPPROFILED_LIBUUID) + +# +# A fast substitution command for fixing up man pages, shell scripts, etc. +# +SUBST_CONF=$(top_builddir)/util/subst.conf +SUBSTITUTE= $(top_builddir)/util/subst -f $(SUBST_CONF) +SUBSTITUTE_UPTIME= $(top_builddir)/util/subst -t -f $(SUBST_CONF) +DEP_SUBSTITUTE= $(top_builddir)/util/subst $(SUBST_CONF) + +$(top_builddir)/util/subst: + cd $(top_builddir)/util ; $(MAKE) subst + +# +# Script for installing symlinks (for shared libraries) +# +$(top_builddir)/util/install-symlink: $(top_srcdir)/util/install-symlink.in \ + $(top_builddir)/config.status + cd $(top_builddir); CONFIG_FILES=util/install-symlink ./config.status + chmod +x $(top_builddir)/util/install-symlink + +$(top_builddir)/util/symlinks: + cd $(top_builddir)/util ; $(MAKE) symlinks + +INSTALL_SYMLINK = /bin/sh $(top_builddir)/util/install-symlink \ + @SYMLINK_RELATIVE@ \ + --symlinks=$(top_builddir)/util/symlinks +DEP_INSTALL_SYMLINK = $(top_builddir)/util/install-symlink \ + $(top_builddir)/util/symlinks + +# +# Warning flags +# +# Run make gcc-wall to do a build with warning messages. +# +# +WFLAGS= -std=c99 -D_XOPEN_SOURCE=600 -D_GNU_SOURCE \ + -pedantic $(WFLAGS_EXTRA) \ + -Wall -W -Wwrite-strings -Wpointer-arith \ + -Wcast-qual -Wcast-align -Wno-variadic-macros \ + -Wstrict-prototypes -Wmissing-prototypes \ + -Wformat-security -Wformat-nonliteral \ + -Wmissing-format-attribute -O2 -Wstrict-aliasing \ + -Wnested-externs -Winline -DNO_INLINE_FUNCS -Wshadow \ + -UENABLE_NLS + +gcc-wall-new: + (make CFLAGS="@CFLAGS@ $(WFLAGS)" > /dev/null) 2>&1 | sed -f $(top_srcdir)/util/gcc-wall-cleanup + +gcc-wall: + make clean > /dev/null + make gcc-wall-new + +# +# Installation user and groups +# +BINGRP= bin +BINOWN= bin +BINMODE= 555 +INCGRP= bin +INCOWN= bin +INCMODE= 444 +LIBOWN= bin +LIBGRP= bin +LIBMODE= 444 +MANGRP= bin +MANOWN= bin +MANMODE= 444 + +# +# Autoconf magic... +# + +DEP_LIB_MAKEFILES = $(top_srcdir)/lib/Makefile.library \ + $(top_srcdir)/lib/Makefile.elf-lib \ + $(top_srcdir)/lib/Makefile.bsd-lib \ + $(top_srcdir)/lib/Makefile.darwin-lib \ + $(top_srcdir)/lib/Makefile.solaris-lib \ + $(top_srcdir)/lib/Makefile.profile + +$(top_builddir)/config.status: $(top_srcdir)/configure + cd $(top_builddir); ./config.status --recheck + +$(top_builddir)/MCONFIG: $(top_srcdir)/MCONFIG.in $(top_builddir)/config.status + cd $(top_builddir); CONFIG_FILES=MCONFIG ./config.status + +$(top_builddir)/lib/config.h: $(top_srcdir)/lib/config.h.in \ + $(top_builddir)/config.status + cd $(top_builddir); CONFIG_FILES=lib/config.h ./config.status + +$(top_builddir)/lib/dirpaths.h: $(DEP_SUBSTITUTE) $(top_srcdir)/lib/dirpaths.h.in + $(E) " SUBST $@" + $(Q) $(SUBSTITUTE) $(top_srcdir)/lib/dirpaths.h.in $@ + +$(top_builddir)/lib/substitute_sh: $(top_srcdir)/lib/substitute_sh.in \ + $(top_builddir)/config.status + cd $(top_builddir); CONFIG_FILES=lib/substitute_sh ./config.status + +$(top_builddir)/util/subst.conf: $(top_srcdir)/util/subst.conf.in \ + $(top_builddir)/config.status + cd $(top_builddir); CONFIG_FILES=util/subst.conf ./config.status + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/MCONFIG \ + $(DEP_MAKEFILE) $(top_builddir)/config.status + cd $(top_builddir); CONFIG_FILES=$(my_dir)/Makefile ./config.status + +@MAINTAINER_CMT@$(top_srcdir)/configure: $(top_srcdir)/configure.in +@MAINTAINER_CMT@ cd $(top_srcdir) && autoheader && autoconf + +coverage.txt: Makefile $(SRCS) + if test -n "$(SRCS)"; then \ + gcov -s $(top_srcdir) -o . $(SRCS) > coverage.txt 2>&1 ; \ + fi + +clean:: + $(RM) -f *.gcda *.gcov *.gcno coverage.txt + +# +# Make depend magic... +# + +.depend: Makefile $(SRCS) $(top_srcdir)/depfix.sed $(top_srcdir)/wordwrap.pl + if test -n "$(SRCS)" ; then \ + $(CC) -M $(ALL_CFLAGS) $(DEPEND_CFLAGS) $(SRCS) | \ + $(SED) -f $(top_srcdir)/depfix.sed \ + -e 's; $(srcdir)/; $$(srcdir)/;g' \ + -e 's; $(top_srcdir)/; $$(top_srcdir)/;g' \ + -e 's; $(top_builddir)/; $$(top_builddir)/;g' \ + -e 's; \./; ;g' \ + -e '/^#/d' \ + -e '/^ *\\$$/d' | \ + $(PERL) $(top_srcdir)/wordwrap.pl > .depend; \ + else :; fi + +depend:: .depend + if test -n "$(SRCS)" ; then \ + sed -e '/^# +++ Dependency line eater +++/,$$d' \ + < $(srcdir)/Makefile.in | cat - .depend \ + > $(srcdir)/Makefile.in.new; \ + if cmp -s $(srcdir)/Makefile.in $(srcdir)/Makefile.in.new ; then \ + $(RM) $(srcdir)/Makefile.in.new ; \ + else \ + $(MV) $(srcdir)/Makefile.in $(srcdir)/Makefile.in.old; \ + $(MV) $(srcdir)/Makefile.in.new $(srcdir)/Makefile.in; \ + fi ; else :; fi + +# End of file MCONFIG
diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..f5727a8 --- /dev/null +++ b/Makefile.in
@@ -0,0 +1,151 @@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +top_builddir = . +my_dir = . +INSTALL = @INSTALL@ + +@MCONFIG@ + +% : %.sh + +@RESIZER_CMT@RESIZE_DIR= resize +@DEBUGFS_CMT@DEBUGFS_DIR= debugfs +@UUID_CMT@UUID_LIB_SUBDIR= lib/uuid +@BLKID_CMT@BLKID_LIB_SUBDIR= lib/blkid +QUOTA_LIB_SUBDIR= lib/quota + +LIB_SUBDIRS=lib/et lib/ss lib/e2p $(UUID_LIB_SUBDIR) $(BLKID_LIB_SUBDIR) $(QUOTA_LIB_SUBDIR) lib/ext2fs intl +PROG_SUBDIRS=e2fsck $(DEBUGFS_DIR) misc $(RESIZE_DIR) tests/progs po +SUBDIRS=util $(LIB_SUBDIRS) $(PROG_SUBDIRS) tests + +SUBS= util/subst.conf lib/config.h lib/dirpaths.h \ + lib/ext2fs/ext2_types.h lib/blkid/blkid_types.h lib/uuid/uuid_types.h + +TAR=tar + +all:: subs + $(MAKE) libs + $(MAKE) progs + $(MAKE) docs + +subs: $(DEP_SUBSTITUTE) + @for i in $(SUBS) ; do if test -d `dirname $$i` ; \ + then $(MAKE) $$i || exit $$? ; fi ; done + @(if test -d lib/et ; then cd lib/et && $(MAKE) compile_et; fi) + @(if test -d lib/ext2fs ; then cd lib/ext2fs && $(MAKE) ext2_err.h; fi) + +progs: all-progs-recursive +libs: all-libs-recursive +all-progs-recursive all-libs-recursive: subs + +e2fsprogs.spec: $(DEP_SUBSTITUTE) e2fsprogs.spec.in + cd $(top_builddir); CONFIG_FILES=./e2fsprogs.spec ./config.status + +rpm: e2fsprogs.spec + sh contrib/build-rpm + +docs: + -@test -d doc && cd doc && $(MAKE) libext2fs.info + +install-doc-libs: + -@test -d doc && cd doc && $(MAKE) install-doc-libs + +uninstall-doc-libs: + -@test -d doc && cd doc && $(MAKE) uninstall-doc-libs + +clean-doc: + -@test -d doc && cd doc && $(MAKE) clean + +distclean-doc: + -test -d doc && cd doc && $(MAKE) distclean + +install: subs all-libs-recursive install-progs-recursive \ + install-shlibs-libs-recursive install-doc-libs + if test ! -d e2fsck && test ! -d debugfs && test ! -d misc && test ! -d ext2ed ; then $(MAKE) install-libs ; fi + +install-strip: subs all-libs-recursive install-strip-progs-recursive \ + install-shlibs-strip-libs-recursive install-doc-libs + +uninstall: uninstall-progs-recursive uninstall-shlibs-libs-recursive uninstall-doc-libs + +install-libs: install-libs-recursive + +uninstall-libs: uninstall-libs-recursive + +coverage.txt: coverage.txt-recursive + +check-recursive: all + +TAGS clean-recursive distclean-recursive depend-recursive check-recursive \ + mostlyclean-recursive realclean-recursive coverage.txt-recursive: + @for subdir in $(SUBDIRS); do \ + if test -d $$subdir ; then \ + target=`echo $@|$(SED) 's/-recursive//'`; \ + echo making $$target in $$subdir; \ + (cd $$subdir && $(MAKE) $$target) || exit 1; \ + fi ; \ + done + +all-progs-recursive install-progs-recursive install-strip-progs-recursive \ + uninstall-progs-recursive coverage.txt-progs-recursive: all-libs-recursive + @for subdir in $(PROG_SUBDIRS); do \ + if test -d $$subdir ; then \ + target=`echo $@|$(SED) 's/-progs-recursive//'`; \ + echo making $$target in $$subdir; \ + (cd $$subdir && $(MAKE) $$target) || exit 1; \ + fi ; \ + done + +all-libs-recursive install-libs-recursive install-strip-libs-recursive \ + uninstall-libs-recursive install-shlibs-libs-recursive \ + install-shlibs-strip-libs-recursive uninstall-shlibs-libs-recursive \ + coverage.txt-libs-recursive: + @for subdir in $(LIB_SUBDIRS); do \ + if test -d $$subdir ; then \ + target=`echo $@|$(SED) 's/-libs-recursive//'`; \ + echo making $$target in $$subdir; \ + (cd $$subdir && $(MAKE) $$target) || exit 1; \ + fi ; \ + done + +mostlyclean: mostlyclean-recursive mostlyclean-local + +clean:: clean-recursive clean-local clean-doc + $(RM) -f $(SUBS) + +distclean: distclean-doc distclean-recursive + $(RM) -rf autom4te.cache e2fsprogs.spec ext2ed/Makefile po/stamp-po + $(MAKE) distclean-local + +realclean: realclean-recursive realclean-local + +depend:: depend-recursive + +lib/ext2fs/ext2_types.h: $(DEP_SUBSTITUTE) asm_types.h \ + $(srcdir)/lib/ext2fs/ext2_types.h.in + cd $(top_builddir); CONFIG_FILES=./lib/ext2fs/ext2_types.h ./config.status + +lib/blkid/blkid_types.h: $(DEP_SUBSTITUTE) asm_types.h \ + $(srcdir)/lib/blkid/blkid_types.h.in + cd $(top_builddir); CONFIG_FILES=./lib/blkid/blkid_types.h ./config.status + +lib/uuid/uuid_types.h: $(DEP_SUBSTITUTE) asm_types.h \ + $(srcdir)/lib/uuid/uuid_types.h.in + cd $(top_builddir); CONFIG_FILES=./lib/uuid/uuid_types.h ./config.status + +mostlyclean-local: + $(RM) -f \#* *~ *.orig core MAKELOG + +clean-local: mostlyclean-local + +distclean-local: clean-local + $(RM) -f $(SUBS) $(SUBST_CONF) \ + config.status config.log config.cache MCONFIG Makefile \ + $(srcdir)/TAGS $(srcdir)/Makefile.in.old + +realclean-local: distclean-local + $(RM) -f configure + +check:: all check-recursive +
diff --git a/README b/README new file mode 100644 index 0000000..bfefae8 --- /dev/null +++ b/README
@@ -0,0 +1,19 @@ + This is the new version (1.42.13) of the second extended file +system management programs. + + From time to time, I release new versions of e2fsprogs, to fix +bugs and to make the utilities more robust. You can always find +information about the latest version at the the e2fsprogs web page, +which is: + + http://e2fsprogs.sourceforge.net + + The INSTALL file has instructions on building and installing +e2fsprogs. Provisions for building Red Hat RPMs and Debian dpkg files +are supplied as well. + + In case of bugs in these programs, please contact Ted Ts'o at +tytso@mit.edu or tytso@alum.mit.edu. See the e2fsck man page for +suggestions of what sort of information to include when submitting bug +reports for these programs. +
diff --git a/RELEASE-NOTES b/RELEASE-NOTES new file mode 100644 index 0000000..557e950 --- /dev/null +++ b/RELEASE-NOTES
@@ -0,0 +1,7923 @@ +E2fsprogs 1.42.13 (May 17, 2015) +================================ + +Fixed a potential buffer overflow while closing a file system in +libext2fs. (CVE-2015-1572, Addresses Debian Bug: #778948) + +Fixed a bug which could cause e2fsck to corrupt Hurd file systems. +(Addresses Debian Bug: #760275) + +Fixed a deadlock which occurs when using systemd and e2fsck.conf's +logging feature. (Addresses Debian Bug: #775234) + +Fixed a bug which could cause programs using libext2's inode table +scanning functions from crashing on certain corrupted file systems. +(Addresses Debian Bug: #773795) + +Fixed dumpe2fs so it won't crash if the user doesn't specify a block +device (file system). (Addresses Debian Bug: #764293) + +Fixed e2fsck so if it notices unexpected HTREE blocks in pass 2, it +will report the correct directory inode containing the inconsistency. + +If e2fsck fails to grow the dir_info structure due realloc(3) not +having enough memory, it will now fail with explanatory message +instead of staggering on failing with a confusing internal error +messages. + +The tune2fs program will zero out the superblock journal backup +information when removing a journal from a file system. + +The mke2fs program now enables the large_file feature by default. + +Fixed a bug which could cause badblocks to crash if there are millions +and millions of bad blocks. + +Fixed some use-after-free bug in resize2fs and e2fsck. + +Fixed a memory leak in tune2fs. + +Fixed some bigendian bugs that had crept into both indirect and extent +handling inside libext2fs. + +Updated/fixed various man pages. + +Update Esperanto, German, and Spanish translations. Added Danish +translation. + +Programmer's Notes +------------------ + +Fixed coverity, sparce gcc -Wall, and clang warnings/nits. + +Clean up some build system problems (build failures with various +configure options, fix Posix portability issues, etc.) + +The functions ext2fs_inode_alloc_stats[2]() and +ext2fs_block_alloc_stats[2]() now check the inode and block numbers +passed to them, to avoid crashes caused by buggy callers. + +The libext2fs directory iterator will now check for an invalid +directory entry length instead of possibly walking off the end of the +directory buffer. + + +E2fsprogs 1.42.12 (August 25, 2014) +=================================== + +Fix various e2fsck bugs when trying to repair bigalloc file systems. + +E2fsck can now repair a file system with an overly large +s_first_meta_bg field, which had previously caused all e2fsprogs +programs to crash when trying to open such a file system. + +Fix e2fsck so that it can correctly fix a number of rare file system +corruptions that were discovered when using a file system fuzzer. + +Fix e2fsck so it does not try to write back block group descriptors if +they have not been modified. + +Mke2fs program will now place metadata blocks in the last flex_bg so +they are contiguous. This reduces free space fragmentation in a +freshly created file system, as well as allowing mke2fs commands which +request extremely large flex_bg size to succeed. + +Mke2fs now creates hugefiles more efficiently (with fewer extent tree +blocks). + +Fix a 32/64-bit overflow bug that could cause resize2fs to loop +forever. (Addresses-Launchpad-Bug: #1321958) + +The resize2fs program will now use much less memory when resizing very +large file systems. + +Fix a bug which could cause resize2fs to get confused and produce a +corrupted file system when shrinking a file system that had been +previously expanded and converted to use the meta_bg file system +format, but which no longer needs to use the meta_bg file system +format any longer. This typically happened with large (> 16TB) file +systems. (Addresses Debian Bug: #756922) + +The e4defrag program will now defrag backwards-allocated files. + +Fix tune2fs updating UUID's when manipulating file systems with +external journals (both the file system and journal UUID). + +Fix tune2fs so it can remove an external journal for file systems with +a 1k block size. + +Add a new debugfs command, "inode_dump", which prints the inode in hex +and ASCII format. + +The debugfs's "set_inode_field" will now automatically allocate blocks +for indirect blocks and extent tree blocks. + +Fix debugfs's "set_inode_field" so can properly handle +"block[IND|DIND|TIND]". + +The debugfs "rdump" command will now take multiple source arguments. + +Fixed a double close(2) bug in "rdump" and "rdump -p". + +Fix debugfs's argument parsing for the freefrag command. + +Fix filefrag to properly handle using the FIBMAP ioctl (with -B). +(Addresses Launchpad Bug: #1356496) + +Clarified messages that were confusing users in debugfs, e2fsck, +mke2fs, and resize2fs (Addresses Debian Bugs: #758029, #757543, +#757544) + +Dumpe2fs will now complain if extra arguments are given to it. +(Addresses Debian Bug: #758074) + +Updated/fixed various man pages. (Addresses-Debian-Bug: #726760) + +Update Czech, Dutch, French, Polish, Spanish, Sweedish, Ukrainian, and +Vietnamese translations. + +Programmer's Notes +------------------ + +The Unix I/O layer will now use pread[64]/pwrite[64] to reduce the +number of system calls issued. + +Fixed profiled build. + +The libext2fs library will now more efficiently split an extent tree +index block when appending to an end of a file. + +Fixed free block accounting for 64-bit file systems. + +Add a new function ext2s_inode_size_set() which takes care of all of +the required feature flag modifications. + +The regression tests no longer require the presence of the md5sum +program. + +Fix build failure on MIPS platforms on Debian (Addresses Debian Bug: +#754605) + +Fix various Coverity warnings (#1225003, #1229243, #1252003) + + +E2fsprogs 1.42.11 (July 9, 2014) +================================ + +Add support so that mke2fs can create hugefiles so that they are +aligned relative to the beginning of the disk, instead of relative to +the beginning of the partition, using the mke2fs.conf configuration +parameter "hugefiles_align_disk". + +Fix a bug which causes e2fsck to abort a journal replay on a file +system with bigalloc enabled. (Addresses Debian Bug: #744953) + +Add sanity checks so that mke2fs will refuse insanely large flex_bg +counts specified by the -G option. Insanely large flex_bg sizes can +result in a file system which can't be unmounted, or with extremely +pessimal metadata layouts. + +The mke2fs program will provide a better metadata layout for +moderately large (but believable) flex_bg counts, such as 133,072. + +The mke2fs progam will also check the kernel version number to +determine whether the lazy_itable_init option is supported, so that +lazy inode table initialization can be used even if the ext4 is +compiled as a module which isn't loaded at the time that mke2fs is +run. + +Add description of ext4's mount options to the ext4 section 5 man +page. + +Improve the chattr man page and clean up the chattr usage message. + +E2fsck will now automatically fix a last mount time or last write time +which is in the future in preen mode, instead of aborting the fsck +check. + +Mke2fs will now check the file system revision number requested by the +command line, and reject it if it is too large. A file system with an +unsupported revision number will not be accepted by any of the other +file system tools, and this command line option is rarely used, so +let's try to help the user not shoot their own foot off. + +The debugfs progam can now set the error count and associated +first_error and last_error fields in the superblock using the +set_super_value command. + +Resize2fs will not try to calculate the minimum size of a file system +if it contains errors. Otherwise a very badly corrupted file system +image can cause the minimum size calculation to loop forwever. Since +resize2fs will not allow a file system marked as containing errors to +be resized. It's pointless to calculate the minimum size, so just +skip it. + +Fixed a typo in one of mke2fs's error message. + +If filefrag runs into an error, it will continue processing the rest +of the files specified on thec ommand line, but then exit with an +error code. + +Filefrag now prints some additional new flags (such as +FIEMAP_EXTENT_ENCODED), and print unknown flags as hex values. + +Fixed support in filefrag for files with > 2**32 blocks on 32-bit +platforms. + +Fixed a file descriptor leak in debugfs when copying files. + +Fixed a regression introduced in 1.42.10 which caused mke2fs to fail +to create file systems larger than 2GB on 32-bit platforms. +(Addresses Red Hat Bugzilla: #1099892, Debian Bug: #752107) + +Add Esparanto and Ukrainian translations, and update Czech, Dutch, +French, German, Italian, Polish, Sweedish, and Vietnamese +translations. + +Fixed various compiler warnings. + + +Programmer's Notes +------------------ + +The gcc "-checker" option has been long deprecated, so remove support +from e2fsprogs. It was causing a few people to be confused when they +tried enabling the configure option. + +Update to the latest version of the config.status and config.rpath +files, as well as newer versions of the autoconf files in aclocal.m4. +Also, move the e2fsprogs-specific macros to acinclude.m4, which allows +people who want to use autoreconf to do so. + +Make the use of strptime() function in debugfs to be more portable to +fix regression test failures for FreeBSD and MacOS. + +A few miscellaneous changes designed to make life easier for +translators. + +Fix the f_quota test and some Makefile dependencies if quota support +is not enabled. + +Fix cross-compilation support, which got broken in 1.42.10. +(Addresses Debian Bug: #753375) + +Delete lib/ext2_types.h on a make clean, and build it as necessary. + +Add a debug program used for libext2fs unit tests. + +Clean up the tests so that it avoids using GNU-specific behaviour in +mktemp. Make sure the temporary files are cleaned up if the tests are +interrupted. + +Add a new ext2fs_close_free() helper function which automatically +takes care of freeing the ext2_filsys structure even if ext2fs_close() +returns an error. + + +E2fsprogs 1.42.10 (May 18, 2014) +================================ + +Mke2fs now creates file systems in regular files (which is very often +used when maintaining virtual machine images) without requiring the +user to use the force option. In addition, the mke2fs output has been +made much less verbose and only displays information that users will +be more likely to find useful by default. + +Mke2fs now will ask the user to confirm that they want to continue +before wiping out a pre-existing file system, partition table, or LVM +physical volume. + +Mke2fs now has the ability to create file systems where all the +metadata is located at the very beginning of the device. This can be +useful for flash devices which have SLC flash at the beginning of the +disk, for FAT compatibility, for example. As part of this, mke2fs and +tune2fs can control the location of the data blocks used by the +journal inode. In addition, the new sparse_super2 feature allows for +even fewer (anywhere from zero to two) backup superblocks. + +Mke2fs now uses much less CPU when allocating the blocks used for very +large file systems. + +Mke2fs can now support creating a file system at an offset. This can +be useful when creating a disk image for virtual machines (Addresses +Debian Bug: #497984) + +Previously, e2fsck had a number of very serious bugs when checking a +file system wich used the new the quota file system option (where the +quota inodes were stored in hidden inodes) and the quota inode was +inconsistent with the actual usage data. This problem was documented +in https://ext4.wiki.kernel.org/index.php/Quota. These problems have +been fixed in 1.42.10, so the quota should be safe to use with +e2fsprogs 1.42.10. + +Fixed in a bug in resize2fs which could cause shrink operation fail in +the unlikely situation when the inode table needs to be moved to a +location before the current location. + +Resize2fs now has a much more accurate (and less conservative) +estimation of how far the file system can be shrunk. This allows a +mostly empty filesystem which is a few terabytes, to be shrunk to a +few megabytes in a single resize2fs -M operation. + +E2fsck will now force a full file system check if there are any file +system inconsistencies detected in the super block. + +The filefrag program will now display hte shared extent flag, which is +used by file systems such as btrfs. + +If the number of inodes in the file systems is larger than the time +that file sytem was created (as measured by the number of seconds +since January 1, 1970) e2fsck would print a scary (but otherwise +harmless) warning of file system corruption for each inode in the +orphan list. This false positive has been fixed. + +The e4defrag program has been fixed so it will no longer refuse with +filesystem with the 64-bit or the bigalloc feature enabled. + +The logsave progam will print a much less scary message which could +lead users to believe something has gone very wrong with e2fsck exits +with a non-zero exit status (since this is normal after e2fsck has +automatically fixed a file system corruption during a preen +operation). (Addresses Debian Bug: #468821) + +When creating a file system which is larger than 16TB, the +resize_inode option must be disabled -- since the resize_inode simply +doesn't support reserving metadata block numbers which is larger than +32 bits. The mke2fs program does this automatically if the file +system size is determined automatically. It will now also do this if +the file size is specified explicitly. + +Fixed bugs associated with resize2fs and shrinking bigalloc file +systems. + +The e2fsck program will no longer try to add a UUID on a mounted file +system with checksums enabled, since this could leave the file system +checksums broken. + +Tune2fs will allow the removal of an external journal from file system +which is marked as needing the journal replayed when the force ("-f") +option is given twice. (Addresses Debian Bug: #559301) + +Tune2fs will no longer support enabling sparse_super if the meta_bg +file system feature is enabled, since it could result in data loss. +In practice, all modern file systems have sparse_super is enabled, so +it's not worth trying to change how tune2fs handles enabling the +sparse_super feature. + +Fixed support for 1k block file systems with the meta_bg feature. + +When the superblock is corrupt, e2fsck can't figure out the location +of the alternate superblock. Unfortunately, the routine that +calculates the location of the alternate superblock uses 8193 if it +can't figure this out, so the message printed by e2fsck always +suggests using "e2fsck -b 8193". This message has been fixed to +suggest both the superblock location of 8193 and and 32768. +(Addresses Debian Bug: #719185) + +The lookback mount detection code that was introduced in 1.42.9 wasn't +actually compiled in due to an autoconf oops, so it's fixed now in +1.42.10. (Addresses Debian Bug: #497984) + +A bug introduced in 1.42.9 would cause debugfs to print two error +messages if it found an error while parsing a user-supplied block +number. This has been fixed in 1.42.10. + +Update Czech, Dutch, French, German, Polish, Spanish, Sweedish, and +Vietnamese translations. (Addresses Debian Bug: #703048) + +Updated/fixed various man pages. (Addresses Debian Bugs: #719189, +#719184) + +Fixed various Debian Packaging Issues. (Addresses Debian Bug: #718725) + + +Programmer's Notes +------------------ + +Fixed a lot of coverity, sparce gcc -Wall, and clang warnings/nits. + +Allow the location of pkg-config files to be specified independent of +the libdir location via a makefile variable. + +Fixed parse-types.sh not to complain when cross-compiling and the +sizes of types are different between the target architecture and the +architecture of the build system + +Allow the regression test suite to work correctly on systems which do +not have the "truncate" or "mksawp" programs. + +Allow e2fsck to build correctly on systems (such as Android) that do +not have the signal.h file. + +E2fsprogs now has code coverage testing which can be enbled using +"configure --enable-gcov". + +The libe2p.h header file can now be used included by C++ programs. + +The profile/config file used by e2fsck and mke2fs will interpret +numbers with a leading 0 character to mean that they should be +interpreted as an octal integer. + +The extent handling functions in libext2fs have been improved so they +have proper rollback when there is an error splitting an extent. Also +fix a number of bugs when punching holes in files, and fix an +off-by-one bug when inserting an extent into an empty inode. + +The libext2fs library now handles the support of BLOCK_UNINIT by +clearing the portion of block bitmap when it is loaded, instead of +when it is used. This reduces the chances of bugs, and and simplifies +the code. It also means that debugfs will properly show that blocks +in uninitialized block groups as being unused when using the testb +command. + +The e4defrag program will try to use fadvise64 or posix_fadvise64() if +it is present, which allows 64-bit offsets on 32-bit systems. + + +E2fsprogs 1.42.9 (December 28, 2013) +==================================== + +Mke2fs will detect an attempt to create a file system on a loop +mounted file and complain without the -FF option. Also fixed mke2fs +so it allows the creation of a file system on a mounted device with +two -F options, as documented in the man page, instead of three -F +options. + +Fixed a large number of bugs in resize2fs, e2fsck, debugfs, and +libext2fs to correctly handle bigalloc and 64-bit file systems. There +were many corner cases that had not been noticed in previous uses of +these file systems, since they are not as common. Some of the bugs +could cause file system corruption or data loss, so users of 64-bit or +bigalloc file systems are strongly urged to upgrade to e2fsprogs +1.42.9. + +The tune2fs program will now not allow changing the uuid on a mounted +file system which has the uninit_bg feature enabled. This avoids a +nasty race where the kernel and tune2fs are both retrying rewrite the +group descriptors at the same time, with different ideas about what +the UUID should be. + +When e2fsck is rehashing an extent-mapped directory, it's possible +(although very rare) that an extent block will need to be allocated; +fix e2fsck to make sure that the block gets marked as used. + +Mke2fs will now properly set the LARGE_FILE feature when creating a +journal >= 2GB --- which can happen when using 64k block size. + +Fixed debugfs so that its freei command will correctly handle a request +to free a range of consecutive inodes. + +Fixed 2fsck so it will not erroneously complain that an external journal +is invalid if it is exactly 2**32 blocks. + +Fixed e2fsck so it won't try checking for, and adding, a missing +lost+found directory when running in read-only mode. + +Fixed e2image to avoid some buffer overruns which would cause it to when +creating a "standard (non-raw, non-qcow2) image file. Standard +e2image files are actually very rarely used, so we didn't notice when +the changes to enable the qcow2 format broke this e2image mode. + +Fixed mke2fs so that the extended option "-E resize=NNN" will not turn +on the resize_inode feature when the meta_bg feature is set, since +these two features can not be set at the same time. + +Fixed tune2fs so that when it disables the quota feature, it updates all +of the backup superblocks. + +Fixed dumpe2fs that would cause it to abort when run using an image file +when trying to print the journal information (which is not present in +an e2image created image file). + +Fixed a potential integer overflow in e2reefrag. +(Addresses-Debian-Bug: #718205) + +Enhance debugfs so that when copying a sparse file from a native file +system into the file system image using the "write" command, it will +create a sparse file into the destination file system. + +Enhanced debugfs so it can support a command line which is up to 8k +long. + +E2image will refuse (unless the -f option is specified to force the +issue) to create a raw or qcow image using a mounted file system, +unless the -f option is specified to force the issue. + +E2image has been optimized for using it to efficiently copy a file +system by only copying the allocated blocks, by using the options -ra. +New options (-o and -O) have been added so that a source and +destination offset can be given. The -p option will print progress +information so the user will know how far along the copy is going. +And finally, the new option -c is useful for updating a file system on +an SSD, by avoiding unnecessary writes. E2image can also shift a file +system image by doing an in place move. + +Fix a regression introduced in 1.42.8 which would cause e2fsck to +erroneously report uninitialized extents past the EOF (as determined by +i_size) to be invalid. + +Fixed resize2fs so under a corner case when an inode has a complex +extent tree, it will not corrupt an interior node in the extent tree. + +Fixed resize2fs which would sometimes corrupt a file system when +shrinking a file system to a minimum size using resize2fs -M. +(Addresses Debian Bug: #660793) + +Fixed resize2fs so that it will relocate inode table blocks if this +becomes necessary when shrinking the file system. + +Fixed resize2fs and e2fsck so they will not crash when hit a failure +while operating on a file system with the MMP feature enabled. + +Fixed a bug in debugfs which caused it create an invalid inode when +trying to write a zero-length file. + +E2fsck will no longer crash if it tries to delete an invalid +extent-mapped symlink. + +E2fsck will no longer crash if it comes across an directory which is +larger than 2GB (which is not allowed in valid file systems). + +Fixed debugfs's help texts to fully document all options and otherwise +be more helpful. + +Updated/fixed various man pages. (Addresses Debian Bugs: #586218, +#669730, #698076) + +Fixed various Debian Packaging Issues (#698879, #721365) + + +Programmer's Notes +------------------ + +Fix sparse, gcc -Wall and clang nits. + +Update config.{guess,sub} to the latest version + +Fixed various memory and file descriptor leaks on various error paths, +as well as some missing error return checks, which were found using +Coverity. + +Run sparse against source files when building e2fsprogs with 'make +C=1'. If instead C=2, it configures basic ext2 types for bitwise +checking with sparse, which can help find the (many many) spots where +conversion errors are (possibly) happening. + +Allow the regression test to be run in chrooted environments where +/etc/mtab might be missing. + +The ext2fs_punch() function, which was introduced in 1.42, was broken +in many ways, but this was never noticed since it wasn't used for +anything significant. Some of the bugs include failing when trying to +punch a completely sparse file, failing when punching an extent-mapped +inode when the starting block was at the beginning of the inode, and +not being able to punch a single block (where start_blk == end_block). +It also didn't handle being passed an invalid, too-large ending block +number, and didn't handle properly terminate at the right place when +operating on an indirect-mapped inode. + +Fixed some minor typo's in the error catalog for libext2fs. + +Fixed ext2fs_file_set_size2() so that if it truncates an inode by +setting the file size, to zero the rest of the block to the end of the +file, so that if an ext4 FUSE driver tries to extended the file, that +we don't avoid stale data from being returned. + +Fixed ext2fs_bmap() to disallow clients from trying to map or set +logical blocks which are larger than what an extent-mapped or indirect +block-mapped inode can allow. + +If debugfs (or some userspace program using libext2fs) creates a file +which is larger than 2GB, make sure the large_file feature flag gets +set. + +Fix a bug in ext2fs_link() where if there is multiple empty slots in the +directory which are large enough, the directory entry could get +inserted more than once in the directory. + +If quota support is disabled (which is the default), make sure that +all traces of the quota support is removed from usage messages, man +pages, and tune2fs must not be able to enable the quota file system +feature. (Addresses Red Hat Bugzilla: #1010709) + +The ext2fs_file_write() now updates i_size on a successful write, +instead of only updating i_size wen the file is closed via +ext2fs_file_close(). + +Added a shell script, populate-extfs.sh which uses debugfs to populate +an ext2/3/4 file system image from a given directory. It is similar +to the genext2fs program, but it supports ext3 and ext4 file system. + +Add changes to the libext2fs library to support block group +descriptors larger than 64 bytes (for future compatibility). + +Fixed an off-by-one bug in ext2fs_file_set_size2() so that it will not +leave an extra block in the file when truncating the file down to +size. + +The html version info pages are now built using makeinfo --html +instead of the unmaintained and now-obsolete texi2html program. + + +E2fsprogs 1.42.8 (June 20, 2013) +================================ + +As a part of mke2fs's option parsing cleanup, the use of the -R option +will give a warning that it is depreated (it has been so documented +since 2005) and -E should be used instead. + +Mke2fs will not give warnings about the bigalloc and quota options in +quiet mode. + +If an invalid journal size is given to mke2fs, it will now complain +and exit sooner. + +Debugfs was erroneously giving spurious error messages for certain +extent_inode subcommands which take arguments (split_node, +replace_node, and insert_node). This has been fixed. + +Fix the parsing of the 's' (sectors) in parse_num_blocks2, which among +other programs is used by mke2fs. + +Change mke2fs so that it does not set the root directory to the real +uid/gid of the mke2fs process. Add the extended option root_owner to +override this behavior. + +Fix resize2fs when shrinking file systems to make sure that bitmap +blocks aren't left outside the bounds of the shrunken file system. +This could happen with flex_bg file systems that were grown using +the old online resizing algorithm. + +E2fsck will now detect and repair corrupted extent trees which contain +invalid extents at the end of the extent tree leaf block. + +E2fsck will now longer complain about zero length extended attribute +values. + +Fix a regression introduced in e2fsprogs v1.42 which caused e2image -s +to crash. + +Add safety check so tune2fs will not attempt to set the inode size to +be larger than the block size. + +Fix e2fsck so it can check a read-only root file system with an +external journal. (Addresses Debian Bug: #707030 + +Fix off-line resizing of file systems with flex_bg && !resize_inode +(Addresses Debian Bug: #696746) + +Fix e2image with large (> 32-bit) file systems (Addresses Debian Bug: +#703067) + +Enhance chattr to allow clearing the extent flag if the kernel allows +migrating extent based files to use indirect blocks. + +Update German translation. + +Updated/fixed various man pages. (Addresses Debian Bugs: #712429, +#712430, #707609) + +Fixed various Debian Packaging Issues (Addresses Debian Bug #708307) + +Programmer's Notes +------------------ + +Use secure_getenv() in preference to __secure_getenv(). + +Optimize CPU utilization of ext2fs_bg_has_super(). + +Fix ext2fs_llseek() on 32-bit i386 systems to work correctly when +SEEK_CUR is used with large files. + +The ext2fs_read_inode_full() function will no longer use +fs->read_inode() if the caller has requested more than the base 128 +byte inode structure and the inode size is greater than 128 bytes. + +Fix build failure with --enable-jbd-debug. + +Clean up filtering of outputs for the regression tests by using a +common sed script. + +Fix gcc -Wall and clang nits. + + +E2fsprogs 1.42.7 (January 21, 2013) +=================================== + +Add warnings to mke2fs, resize2fs, and tune2fs that the bigalloc and +quota features are still under development. For more information +please see: + * https://ext4.wiki.kernel.org/index.php/Bigalloc + * https://ext4.wiki.kernel.org/index.php/Quota + +Add some new options to filefrag from Lustre's patches to e2fsprogs: + * add -k option to print extents in kB-sized units (like df -k) + * add -b {blocksize} to print extents in blocksize units + * add -e option to print extent format, even when FIBMAP is used + * add -X option to print extents in hexadecimal format + +Fix resize2fs so that it can handle off-line resizes of file systems +with the flex_bg feature but without a resize_inode (or if we run out +of reserved gdt blocks). This also fixes a problem where if the user +creates a filesystem with a restricted number of reserved gdt blocks, +an off-line resize which grows the file system could potentially +result in file system corruption. + +Fix a resize2fs bug which could cause it to corrupt bigalloc file +systems when doing an off-line resize. + +Further optimize resize2fs so it doesn't use quite as much CPU when +resizing very large file systems. + +Fixed 32-bit overflow bugs which could cause resize2fs to fail and +possibly corrupt the file system while resizing 64-bit file systems. + +Fix a bug in mke2fs where parsing "-E resize=NNN" will result in a +mke2fs crash due to a divide-by-zero if the 64bit file system feature +is enabled. + +Add better error checking to mke2fs to check for invalid parameters +when creating bigalloc file system. + +When creating bigalloc filesystems, the -g option to mke2fs will now +specify the number of clusters per block group. + +Add to debugfs the functionality to corrupt a specific file system +block via the "zap_block" command. + +Add to debugfs the functionality to print out a hex dump of a block in +the file system via the "block_dump" command. + +Add to debugfs the functionality to manipulate the extent tree +directly via the "extent_open" command. + +Fixed debugfs's mknod command so that it updates the block group +statistics. + +Fix e2fsck so it can detect and fix inconsistencies in the interior +nodes of an inode's extent tree. + +Fix a potential memory corruption failure in e2fsck's error path if +the call to ext2fs_open2() fails. + +Fix e2fsck if its logging function is enabled in e2fsck.conf, and the +resulting file name for the log file is longer than 100 bytes, that it +properly handles this situation instead of crashing. + +E2fsck will now report the amount of memory that it attempted to +allocate when a memory allocation request fails, to make it easier to +track down the problem. + +Fix mke2fs's handling of the mmp_update_interval option. (Addresses +Lustre Bug: LU-1888) + +E2image can now include all data blocks in the e2image output file +when the user specifies the -a option. + +If e2fsprogs is compiled without --enable-quota, make sure that +tune2fs can not turn on the feature for new-style quota support, since +afterwards, none of the e2fsprogs tools will be willing to touch that +file system. + +Optimize e2fsck's so that it uses much less CPU for large file +systems. This can result in significant speedups, especially on +CPU-constrained systems. This was primarily done by optimizing +libext2fs's bitmap functions. (Addresses Google Bug: #7534813) + +Fix debugfs's htree command so that all its messages are sent through +the pager. + +Fixed debugfs's "dump_file" and "cat" functions work correctly +on file systems whose block size is greater than 8k. + +Fix e2freefrag so it works on 64-bit file systems, and so it uses much +less memory. (Addresses Google Bug: 7269948) + +Update the spd_readdir.c file in the contrib directory to include some +additions which were made in 2008 that didn't get folded into the +version which we checked into the e2fsprogs source tree. These +enhancements include thread safety, support for readdir64_r(), and +safe_getenv() support in case spd_readdir.so is used for setuid binaries. + +Update Czech, Dutch, French, German, Polish, Sweedish, and Vietnamese +translations + +Add a command to debugfs to create symlinks. + +Document the bigalloc feature in the mke2fs man page. (Addresses +Debian Bug: #669730) + + +Programmer's Notes +------------------ + +Fix gcc -Wall nits. + +Fix a spelling typo in the libext2fs texinfo documentation. + +Change the output from "make check" so that tools such as emacs's "M-x +compile" does not mistake the output as containing a compiler error. + +Export two new functions from libext2fs: ext2fs_extent_node_split() +and ext2fs_extent_goto2(). + +The ext2fs_extents_fix_parents() was fixed so it does not modify the +location of the extent handle if its current location is at an +interior node, rather than a leaf node of an inode's extent tree. + +Add a regression test to assure that e2fsck can correctly fix an +inconsistent interior node in an inode's extent tree. + +The ext2fs_{mark,unmark,test}_block_bitmap_range2() functions now +correctly support bigalloc file systems which use store block usage +information in units of clusters. + +Fixed the help text in the configure script for --enable-quota. + +The m68k-specific bitops code has been removed since they were +incorrectly treating bit numbers with the high bit set as signed +integers. Furthermore, modern compilers do a good enough job +optimizing the generic code there is no point in having the m68k +specific asm statements. + +Fixed how we link the test programs so they always use the static +libraries, so that we test using the libraries which we have just +built. + +Update config.guess and config.sub to the latest versions from the GNU +project. + +Fixed the com_err.texinfo file so that it can produce a valid +postscript/pdf printed output. + +Add a regression test which checks debugfs's ability to create +symlinks, named FIFO's, and device nodes. + +Add a function ext2fs_symlink(), which creates symlinks to the +libext2fs library. + +Add debugging code so we can test old kernel interfaces for online +resize to resize2fs. This backwards compatibility checking is keyed +off of the RESIZE2FS_KERNEL_VERSION, which is designed to allow us to +test the functionality of the kernel's older resize ioctls without +needing to install an old version of resize2fs, and to also test a +modern resize2fs's ability to work with older kernels without having +to install an older version of the kernel. + + +E2fsprogs 1.42.6 (September 21, 2012) +===================================== + +When mke2fs creates file systems with lazy itable initialization, the +progress updates for writing the inode table happens so quickly that +on a serial console, the time to write the progress updates can be the +bottleneck. So mke2fs will now only update its progress indicators +once a second. + +Resize2fs will skip initializing the inode tables if the kernel +supports lazy_itable_init, which speeds up growing off-line growth of +uninit_bg file systems significantly. Resize2fs will now also +correctly set the itable_unused field in the block group descriptor to +speed up the first e2fsck after the file system is grown. + +Resize2fs has been fixed so that on-line resizing of meta_bg file +systems work correctly. This is needed to grow file system which are +larger than 16T. + +Resize2fs will now correctly handle resizing file systems to 16TB on +32-bit file systems when "16TB" is specified on the command line. + +Fix mke2fs so that it will be careful to set the reserved blocks ratio +larger than 50%; this can happen when creating small file systems and +when the last block group is dropped because there are not enough +blocks to support the metadata blocks in the last block group. + +Fixed spelling mistake in debugfs's help message. + +Fixed a potential seg fault in e2fsck when there is an I/O error while +reading the superblock. + +Fixed various Debian Packaging Issues (Addresses Debian Bug #677497) + +Updated/fixed various man pages. (Addresses Sourceforge Bug: +#3559210) + +Programmer's Notes +------------------ + +The configure option --enable-relative-symlink was broken so that it +needed to be --enable-symlink-relative-symlinks. We will support both +for at least two years, but then the worng configure option will be +removed. + +Fixed a regression introduced in 1.42.5 so the link order for +e2fsprogs' libraries will be correct for both static and shared +linking. (Addresses Sourceforge Bug: #3554345) + +Add support for e2fsprogs to be compiled using clang/LLVM. + +Fix portability problems on non-Linux systems: avoid compile failures +on systems that don't have malloc.h + +Fix f_mmp regression test suite so that debugfs gets killed if the +test is interrupted. + + + +E2fsprogs 1.42.5 (July 29, 2012) +================================ + +Fixed a bug with mke2fs where if there is only 8 inodes per block +group, the calculation of the number of uninitialized inodes in the +first block group would go negative. This resulted in "mke2fs -N 256 +-t ext4 /tmp/foo.img 256m" trying to write so many blocks that /tmp +would run out of space. (Addresses Sourceforge Bug: #3528892) + +Fixed a bug in how e2fsck would uniquify directory entry names. +(AddressesSourceforge Bug: #3540545) + +Previously, e2fsck would only allow a mounted file system to be +checked if it was the root file system and it was mounted read-only. +Now it will allow any file system mounted read-only to be checked if +the -f option is specified. This makes it easier to test how e2fsck +handles checking file systems which are mounted without having to test +on the root file system. + +Fixed a problem if e2fsck where if the root file system is mounted +read-only, e2fsck would not clear an error indication in the journal +superblock. Combined with a kernel bug, this would cause the e2fsck +to check the file system after every single boot. + +The e4defrag program can now handle device symlinks, such as +/dev/mapper/testvg-testlv, instead of insisting on a less +human-friendly name such as /dev/dm-2. (Addresses Red Hat Bugzilla: +#707209) + +Fixed filefrag so it will not crash with a segfault on files from a +virtual file system such as /proc. (e.g., "filefrag +/proc/partitions") + +Fixed filefrag so that it correctly reports the number of extents. +(Addresses Red Hat Bugzilla: #840848) + +Fixed a file descriptor leak in logsave which could cause it to hang. +(Addresses Debian Bug: #682592) + +Fixed e2fsck so that the file system is marked as containing an error +if the user chooses not to fix the quota usage information. + +Fixed tune2fs so that it correctly removes the quota feature when the +last quota inode is removed. + +Fix tune2fs so that after removing a quota inode, the block bitmap is +updated; otherwise, e2fsck would complain after running 'tune2fs -O +^quota <dev>'. + +Fix tune2fs so that when converting a file system from using legacy +quota files to the new quota file system feature with hidden quota +files, the accounting for these files is handled correctly so that +e2fsck doesn't complain. + +Improved e2fsck's verbose reporting statistics, and allow the more +verbose reporting to be enabled via /etc/e2fsck.conf. + +Fixed various Debian Packaging Issues (Addresses Debian Bug #678395) + +Updated/fixed various man pages. (Addresses Debian Bugs: #680114) + + +Programmer's Notes +------------------ + +Fixed portability problems on other operating systems (e.g., Hurd and +FreeBsd) caused by the attempted inclusion of <sys/quota.h>. + +Make sure that shared libraries link with the shared libraries built +in the build tree, instead of the system provided libraries. +Previously, libraries and executables were linked with the system +libraries if present, and possibly using static archives instead of +shared libraries. This was also problematic since if libext2fs.so is +linked with a static libcom_err.a from system, the build system would +attempt to link without -lpthread. (Addresses Sourceforge Bug: +#3542572) + + +E2fsprogs 1.42.4 (June 12, 2012) +================================ + +Fixed more 64-bit block number bugs (which could end up corrupting +file systems!) in e2fsck, debugfs, and libext2fs. + +Fixed e2fsck's handling of the journal's s_errno field. E2fsck was +not properly propagating the journal's s_errno field to the superblock +field; it was not checking this field if the journal had already been +replayed, and if the journal *was* being replayed, the "error bit" +wasn't getting flushed out to disk. + +Fixed a false positive complaint by e2fsck if all of the extents in +the last extent tree block are uninitalized and located after the end +of the file as defined by i_size. + +The dumpe2fs will now display the journal's s_errno field if it is +non-zero, and it will also display the journal's 64-bit feature flag +if present. + +Fix e2fsck so that it always opens the device file in exclusive mode +when it might need to modify the file system, and never if the -n +option is specified. (Previously, there were a few corner cases where +it might get things wrong in either direction.) + +E2fsck now correctly truncates or deallocates extent-mapped inodes on +the orphan list. The root cause was a bug in libext2fs's block +iterator which could end up skipping an extent when the last block in +an extent is removed, causing the current extent to be removed from +the extent tree. + +E2fsck now correctly sets the global free block and inode counts when +truncating or removing inodes on the orphan list in preen mode. +Previously, it would leave these values would be set incorrectly, +which is largely a cosmetic issue since the kernel no longer pays +attention to those fields, but it can cause spurious complaints in +subsequent e2fsck runs. + +Fix i_blocks accounting when the libext2fs library needs to add or +remove an extent tree block on bigalloc file systems. + +The lsattr and chattr programs now support the No_COW flag for the +benefit of btrfs. + +Debugfs now interprets date strings of the form @ddd as ddd seconds +after the beginning of the epoch. This is handy when setting an inode +number into the d_time field when debugging orphan list handling. + +Fix a precedence bug with built-in quota support which might result in +e2fsck paying attention to the quota inode field even if the built-in +quota feature flag is not set. Fortunately, in practice that +superblock field should be zero for non-built-in quota file systems, +so it's unlikely this bug would have caused problems. + +Updated/fixed various man pages. (Addresses Debian Bugs: #674453, +#674694) + +Programmer's Notes +------------------ + +The regression test suite can now run the integration tests in the +tests directory in parallel, via "make -jN check". + +Add new test, f_zero_extent_length which tests e2fsck's handling of +the case where all of the extents in the last extent tree block are +uninitialized extents after i_size. + +Add a new test, f_jnl_errno, which checks handling of an error +indication set in the journal superblock. + +Fix the test f_jnl_64bit so that it properly checks e2fsck's handling +of a 64-bit journal. + +Add two tests, f_orphan_indirect_inode and f_orphan_extent_inode which +tests e2fsck's handling of orphan inodes in preen mode, and truncation +of extent inodes on the orphan list. + +Fixed more OS X portability issues. + + +E2fsprogs 1.42.3 (May 14, 2012) +=============================== + +Fix a bug in the Unix I/O manager which could cause corruption of file +systems with more than 16TB when e2fsprogs is compiled in 32-bit mode +(i.e., when unsigned long is 32-bits). Also fix a bug which caused +dumpe2fs to incorrectly display block numbers > 32-bits. + +Improve the support for integrated quota files (where quota is a first +class supported feature using hidden files in the ext4 file system). +Previously the quota file was getting rewritten even when it was not +necessary, and e2fsck would erroneously try to hide quota files which +were already hidden. + +Quiet complaints in e2fsck when the total free blocks or inodes are +incorrect in the superblock after an system crash, since we don't +update nor depend on the superblock summaries at each commit boundary. + +Fixed a regression introduced in 1.42.2 which would cause applications +outside of e2fsprogs which did not pass the EXT2_FLAG_64BIT (and so +would were still using the legacy 32-bit bitmaps) to crash. This was +due to missing 32-bit compat code in side the function +ext2fs_find_first_zero_generic_bmap(). (Addresses Red Hat Bugzilla: +#808421) + +Fix a bug which would cause mke2fs to fail creating the journal if +/etc/mtab and /proc/mounts are missing. (Addresses Sourceforge Bug: +#3509398) + +Updated/fixed various man pages. + +Update Czech, Dutch, French, German, Polish, Sweedish, and Vietnamese +translations + +Fixed various Debian Packaging issues. + + +Programmer's Notes +------------------ + +Change the nonsensically wrong types in the function signature of the +inline function ext2fs_find_first_zero_block_bitmap2(). This was +caused by a cut and paste error; fortunately no code in e2fsprogs used +this inline function, and there are any users of this functions +outside of e2fsprogs. + +Add support for systems which have valloc(), but which do have +posix_memalign() nor memalign() (such as MacOS 10.5). + +Refactor and clean up the allocation of aligned buffers for Direct I/O +support. Previously some allocations were requesting a greater +alignment factor that what was strictly necessary. Also optimize +reading and writing bitmaps using Direct I/O when the size of the +bitmap did not fully cover the file system blocksize. + +Reserve the codepoints for the INCOMPAT features LARGEDATA and +INLINEDATA. + +Improved the regression test suite by adding some new integration +tests (f_jnl_32bit, f_jnl_64bit) which detect breakage of the on-disk +jbd2 format, as well as f_eofblocks which tests the new handling of +uninitialized and initialized blocks beyond i_size. Also add a new +unit test which verifies 32-bit bitmaps support and the new +find_first_zero primitives. + +Add a few dependencies to fix parallel (make -j) builds. + +Removed bash'isms which were breaking the regression test suite on +systems where /bin/sh is not bash. + +The config.guess and config.sub have been updated to the 2012-02-10 +version. + +Fix a portability problem caused by assuming the present of mntent.h +means that setmntent() exists. Instead, explicitly test for this in +the configure script. + +If the sys/signal.h header file does not exist, don't try to include +it, since it's not available on all systems. + +Add support for systems that do not support getpwuid_r() + +The configure script now supports a new option, +--enable-relative-symlinks, which will install relative symlinks for +the ELF shared library files. (Addresses Sourceforge Bug: #3520767). + +When building BSD shared libraries make sure the LDFLAGS variable is +passed to the linker. Fixing this allows, for example, e2fsprogs to +be built in 32-bit mode on Mac OS X Lion (Addresses Sourceforge Bug: +#3517272) + +Fix gcc -Wall nitpicks + + +E2fsprogs 1.42.2 (March 27, 2012) +================================= + +The resize2fs program uses much less CPU and is much faster for very +large file systems. (Addresses Debian Bug: #663237) + +The seti and freei commands in debugfs can now take an optional length +argument to set and clear a contiguous range of inodes. + +E2fsck will now make explicit checks for the EOFBLOCKS_FL, since we +plan to remove support for it from the kernel file system driver. It +really wasn't very useful and was causing more problems than it +solves. Since e2fsck will complain if inodes that should have +EOFBLOCKS_FL do not have the flag set, we are going to remove this +check from e2fsprogs first, and then only remove the flag from the +kernel much later. + +The mke2fs program can now use direct I/O via "mke2fs -D". This will +slow down the mke2fs, but it makes it more polite on a loaded server +by limiting the amount of memory that gets dirtied by mke2fs when it +is using buffered I/O. + +E2fsck was needlessly closing and re-opening the file system as a side +effect of adding Multiple Mount Protection (MMP). This isn't +necessary for non-MMP file systems, so drop it. + +Print errors returned by ext2fs_open2() and ext2fs_check_desc() so we +can more easily diagnose memory allocation failures caused by +insufficient memory. E2fsck will now abort if there are memory +allocation failures when the file system is initially opened and +during the block group descriptor checks. (Addresses Google Bug: +#6208183) + +If there are incorrect block group checks, e2fsck will now report the +incorrect and corrected checksum values. + +The e2fsck progam can now write log files containing the details of +the problems that were found and fixed directly, via configuration +parameters in /etc/e2fsck.conf. + +Added the ability to limit the number of messages reported by e2fsck +for a given problem type. This avoids a potential bottleneck if there +is a serial console which can cause a boot sequence to take a long +time if e2fsck needs to report many, many file system errors. + +The dumpe2fs, debugfs, and tune2fs now use rbtree bitmaps, which cause +them to use much less memory for large file systems. + +The dumpe2fs program will now print the expected block group checksum +if it is incorrect. This helps to diagnose problems caused by +incorrect block group checksums. + +E2fsck now checks for extents with a zero length, since the kernel +will oops if it comes accross such a corrupted data structure. (See +https://bugzilla.kernel.org/show_bug.cgi?id=42859) + +E2fsck has a number of bugs relating to discard that have been fixed. +(1) Fixed a bug which could cause e2fsck to discard portions of the +inode table which were actually in use. (2) E2fsck will now avoid +using discard if the block device doesn't zero data on discard, since +otherwise this could cause problems if the file system gets corrupted +in the future. (3) E2fsck will now avoid using discard when it is run +in read-only mode. (4) Fixed a bug which caused e2fsck to not issue +discards in the last block group. + +E2fsck's CPU utilization in pass 5 has been optimized, which will +speed up e2fsck slightly. + +E2image will now skip copying uninitialized bitmap and inode table +blocks. + +Fixed mke2fs -S so it does not corrupt the first block group's +information. + +E2fsck will now check the new sysfs interface to determine if we are +using the battery or AC mains. (Addresses SourceForge Bug: #3439277) + +Updated/fixed various man pages. (Addresses Debian Bug: #665427) + +Fixed various Debian Packaging issues. (Addresses Debian Bug: #665885) + +Programmer's Notes +------------------ + +Fixed various portability issues for non-Linux systems, particularly +MacOS X, as well as Linux systems running with the just-released glibc +2.15. + +Fix file descriptor leak in ext2fs_close() if the file system with +uninit_bg is opened read/only with a backup superblock. (Addresses +SourceForge Bug: #3444351) + +Fixed an invalid return in a non-void function in the quota code. +(Addresses SourceForge Bug: #3468423) + +Fixed the debian rules file so that the calls to dpkg-buildflags works +when the shell is dash. + +The debian package build now uses V=1 so that there is more +information about potential build failures in debian buildd logs. + +If the uninit flags get cleared by functions such as +ext2fs_new_inode() or ext2fs_new_block2(), we now make sure the +superblock is marked dirty and the block group descriptor checksum is +updated if necessary. + +The debian rules file will now try to load debian/rules.custom of it +exists. This flie can skip various builds for speed reasons if there +is no need for the e2fsck-static or udeb packages. Available +customizations in the rules file includes SKIP_STATIC=yes, +SKIP_BF=yes, and SKIP_DIETLIBC=yes. + +In addition, if the file misc/mke2fs.conf.custom.in exists in the +source tree, it will be used instead of the standard misc.conf file in +the upstream sources. This makes it easier for Debian-derived systems +to distribute a custom mke2fs.conf file without having to worry about +merge issues if future versions of e2fsprogs makes changes in the +upstream default version of mke2fs.conf. + + +E2fsprogs 1.42.1 (February 17, 2012) +=================================== + +The mke2fs and e2fsck now use significantly less memory when creating +or checking very large file systems. This was enabled by adding +extent-based bitmaps which are stored using a red-block tree, since +block and inode allocations tend to be contiguous. + +The command mke2fs -S is used as a last ditch recovery command to +write new superblock and block group descriptors, but _not_ to destroy +the inode table in hopes of recovering from a badly corrupted file +system. So if the uninit_bg feature is enabled, mke2fs -S will now +set the unused inodes count field to zero. Otherwise, e2fsck -fy +after using mke2fs -S would leave the file system completely empty. + +Since mke2fs recognizes mke3fs in argv[0] to mean "mkfs.ext3", also +honor "mke4fs" to work the same as "mke2fs.ext4", since RHEL5 has +installed an mke2fs binary using that name. + +The usage and help messages for the -G, -t and -T options in mke2fs +have been fixed. + +If e2fsck needs to use the backup group descriptors, the +ext2fs_open2() function clears the UNINIT bits to ensure all of the +inodes in the file systems get scanned. However, the code which reset +the UNINIT flags did not also recalculate the checksum, which produced +many spurious (and scary) e2fsck messages. This has been fixed by +resetting cheksums when the UNINIT bits are cleared. + +Relax a check in e2fsck which required that the block bitmap to be +initialized when the inode bitmap is in use. This will allow us to +eventually eliminate code from the kernel which forcibly initialized +the block bitmap when the inode bitmap is first used, requiring an +extra journal credit and disk write. (Addresses Google Bug: #5944440) + +Make sure rdebugfs (which may be installed setuid or setgid disk) does +not honor environment variables if euid != uid or egid != gid. + +Debugfs's ncheck command has been optimized and now is much more +robust with faced with corrupted file systems. The ncheck command +also now has a -c option which will verify the file type information +in the directory entry to see if matches the inode's mode bits. This +is extremely useful when trying to use debugsfs to determine which +parts of the file system metadata can be trusted. + +E2image will try to use ftruncate64() to set the i_size for raw +images, instead of writing a single null byte. This avoid allocating +an extra block to the raw image, for those file systems and/or +operating systems that support this. (Linux does.) In addition, fix +a logic bug that caused the file to not be properly extended if the +size of the last hole was exactly an multiple of a megabyte. + +Fixed a bug in resize2fs where for 1k and 2k file systems, where +s_first_data_block is non-zero, this wasn't taken into account when +calculate the minimum file system size for use with the -M option. + +Fixed the badblocks program to honor the -s flag when in read-only -t +mode. (Addresses Debian Bug #646629) + +Update Czech, Dutch, French, Polish, and Sweedish translation from the +Translation Project. + +Fixed various Debian Packaging issues so that dpkg-buildflags is used +if present, which allows e2fsprogs to be built with security hardening +flags. (Addresses Debian Bugs: #654457) + +Programmer's Notes +------------------ + +Fix a bug in ext2fs_clear_generic_bmap() when used for 32-bit bitmaps. +This was only an issue for programs compiled against e2fsprogs 1.41 +that manipulate bitmaps directly. (Addresses Sourceforge Bugs: +#3451486) + +The libext2fs library now uses sysconf() to fetch the page size, instead +of the deprecated getpagesize(). + +The ext2fs_get_pathname() function will return a partial path if an a +directory in the path is not a directory, displaying it as an inode +number in angle brackets instead of giving up and displaying an error. +This is much more helpful when a user is trying to debug a corrupted +file system. + +Codepoints for the RO_COMPAT_REPLICA feature has been reserved. + +Added a new library function, ext2fs_file_get_inode_num(), for use by +fuse2fs. + +Fixed a bug in ext2fs_file_set_size2() so that when it is truncating a +file, it actually works. + +The block iterator now properly honors the BLOCK_ABORT flag for +extent-based flags. Previously, it didn't, which generally made code +be less efficient, but it could cause bugs in ext2fs_link(), for +example, by causing it to insert multiple directory entries. + +Fixed an (harmless other than causing a compiler warning) use of an +uninitialized variable in e2fsck's MMP code. + + +E2fsprogs 1.42 (November 29, 2011) +================================== + +This release of e2fsprogs has support for file systems > 16TB. Online +resize requires kernel support which will hopefully be in Linux +version 3.2. Offline support is not yet available for > 16TB file +systems, but will be coming. + +This release of e2fsprogs has support for clustered allocation. This +reduces the number of block (now cluster) bitmaps by allocating and +deallocating space in contiguous power-of-2 collections of blocks, +which are called clustered. This is a file system level feature, +called 'bigalloc', which must be enabled when the file system is +initially formatted. It is not backwards compatible with older +kernels. + +Added support for the Multi-Mount Protection (MMP) feature. + +E2fsck more efficiently uses scratch files for really big file +systems. (This is a feature that has to be turned on explicitly; see +[scratch_files] in the e2fsck.conf man page.) + +Fix a bug in e2fsck where if the free blocks and inodes counts are +incorrect, e2fsck would fix them without printing an error message. +This would cause a "*** FILE SYSTEM WAS MODIFIED ***" message without +any explanation of what was fixed. + +E2fsck will no longer attempt to clone an extended attribute block in +pass1b handling if the file system does not support extended +attributes. + +E2fsck will be more careful accidentally asking the user to continue +if the file system is mounted, so that an escape sequence won't cause +a false positive. (Addresses Debian Bug: #619859) + +E2fsck now uses less cpu time in pass 5 when large portions of the +bitmaps are uninitialized. + +E2fsck will no longer segault when a corrupted file system has a bad +extent, and removing it leads to a block needing to be deallocated. +(Addresses SourceForge Bug: #2971800) + +E2fsck will catch termination signals (segfaults, bus errors, sigfpe) +and print debugging information to make it easier to find potential +problems. + +E2fsck will check to see if the bad block inode looks insane, and will +skip trying to use if it certain fields which should be zero look +non-zero. This is to avoid a corrupted bad block inode causing e2fsck +to get confused and do more harm than good. + +If e2fsck modifies certain superblock fields which the kernel doesn't +look at, it will now mark the superblock as dirty without marking the +file system as changed. This avoids signalling the init scripts that +a reboot is necessary, since the kernel isn't going to look at those +fields, so it won't care if they have been changed. + +Fixed a bug in the libext2fs library (in the binary search routine of +the icount abstraction) that could (very, very rarely) cause e2fsck to +die in the middle of pass 1 or pass 2 processing. + +E2fsck will not try to do a discard operation if the -n option was +specified on the command line. + +E2fsck now supports an extended "discard" option which will cause +e2fsck to attempt discard all unused blocks after a full, successful +file system check. + +E2fsck will check for the bad block inode to make sure it looks sane +before trusting it, to avoid causing more harm than good to the file +system. + +E2fsck now returns additional status bits in its exit code if it +aborts early in the e2fsck run. + +E2fsck now correctly calculates the maximum file size in the case of +the huge_file file system feature enabled without extents. + +The mke2fs and e2fsck programs now tries to use the punch hole command +as a "discard" when operating on normal files. + +The e2image program now supports the qcow2 format, which is a more +efficient way of capturing file system dumps. + +Mke2fs now supports the [devices] stanza in mke2fs.conf which allows +per-device defaults to be specified in the configuration file. + +Mke2fs now supports the reserved_ratio relation in the [defaults] and +[fs_types] section in mke2fs.conf. + +Mke2fs now creates extent-mapped directories for the root and +lost+found directories. + +Mke2fs will skip zero'ing the journal if the extended option +"lazy_journal_init" is specified. This can save a lot of time, but it +does add a small amount of risk if the system crashes before the +journal is overwritten entirely once. It is epsecially useful for +testing. + +Mke2fs will now create file systems that enable user namespace +extended attributes and with time- and mount count-based file +system checks disabled. + +Mke2fs will not set a stride or strip size of one block based on block +device attributes obtained from sysfs. + +Mke2fs now displays a progress report during the discard process. + +Mke2fs now handles extreme file system parameters correctly which +previously caused the inodes per group to drop below 8, leading to a +segfault. (The inodes per group must be a multiple of 8, but the code +didn't correctly deal with an inodes per group count less than 8.) + +Mke2fs and tune2fs previously would give an error if the user tried +setting the stride and stripe-width parameters to zero; but this is +necessary to disable the stride and stripe-width settings. So allow +setting these superblock fields to zero. (Addresses Google Bug: +#4988557) + +Mke2fs now gives a warning if the auto-detected block size exceeds the +system's page size. + +If the enable_periodic_fsck option is false in /etc/mke2fs.conf (which +is the default), mke2fs will now set the s_max_mnt_count superblock +field to -1, instead of 0. Kernels older then 3.0 will print a +spurious message on each mount then they see a s_max_mnt_count set to +0, which will annoy users. (Addresses Debian Bug: #632637) + +The default mke2fs.conf now has entries for "big" and "huge", which +are needed for very big file systems. + +The resize2fs program now has support for a new online resize ioctl +that can support file systems > 16TB, once it arrives in v3.x kernels. + +Fixed bug which caused resize2fs to fail when shrinking an empty file +system down to its minimal size. (Addresses Sourceforge Bug #3404051) + +Fixed tune2fs's mount options parsing. (Addresses Debian Bug: #641667) + +Allow tune2fs to remove external journals if the device can not be +found. + +Debugfs's icheck will now correctly find inodes which use the +searched-for block as an extended attribute block. + +Debugfs now has a new "punch" command which remove blocks from the +middle of an inode. + +Debugfs now has a new "e2freefrag" command which analyzes the free +space fragmentation of the file system, using the same code as the +e2freefrag program. + +Debugfs now has a "filefrag" command which displays information about +a file's fragmentation. + +Add support to build a metadata-only, read-only, stripped-down version +of debugfs called rdebugfs. + +Fixed a potential stack overrun bug in debugfs. + +The badblocks program now correctly recovers from I/O errors when +direct I/O is being used. The badblocks command now also supports a +-B option which forces the use of buffered I/O, and the -v option will +provide a more detailed breakdown of read, write, and failed +comparison errors. + +Added e4defrag tool which uses the EXT4_IOC_MOVE_EXT ioctl. + +Added support for journals larger than 2GB. + +Support using both hard links and symlinks when installing e2fsprogs. + +Add overflow checking to tune2fs -i's fsck interval, which must fit in +a 32-bit field. + +The debugfs command now has a new 'blocks' command which prints out +data blocks of a particular inode in a format which is useful for +scripting. + +Filefrag will report 0 extents correctly in verbose mode. (Addresses +RedHat Bugzilla: #653234) + +Filefrag has been fixed so its -v report prints the correct expected +block number (previously there had been an off-by-one error). In +addition, it will now display the number of contiguous extents when -v +is not specified. This makes it consistent with the number of extents +printed when the -v option was specified. In addition, the number of +contiguous extents is far more interesting/useful than the number of +physical extents for very large files. (Addresses Debian Bug: +#631498, #644792) + +Logsave's usage message has been fixed. (Addresses Debian Bug: +#619788) + +Avoid an infinite loop in ext2fs_find_block_device() if there are +symlink loops in /dev caused by a buggy udev. + +Added a useful "fallocate" program to the contrib directory. + +Fixed an ABI compatibility problem in libext2fs which broke the dump +program. Also added back some macros which dump needed so it could +compile against the latest version of ext2_fs.h (Addresses Debian Bug: +#636418) + +Fixed parsing of MNTOPT_ options for tune2fs and debugfs (Addresses +Debian Bug: #641667) + +Added internationalization support for libcom_err error table strings. + +Fixed various spelling mistakes found in various output strings found +by I18N translators. + +Update translations: French, Chinese, Germany, Indonesian, Swedish, +Vietnamese, Polish, Dutch, Czech. (Addresses Debian Bugs: #520985, +#620659) + +Fixed various Debian Packaging issues. (Addresses Debian Bugs: +#614662, #632169, #641838, #627535, #629355) + +Updated/clarified man pages. (Addresses Debian Bugs: #639411, +#642193, #634883) + +Programmer's Notes +------------------ + +Initial support for quota as an integrated feature, where the quota +files are hidden system files that are automatically maintained by +e2fsck is present, although disabled by default. It must be enabled +by using the configure option --enable-quota. + +Reserved the on-disk fields for the metadata checksum and snapshot +features, which are currently in development. + +The ext2fs library now has the new functions ext2fs_punch(), +ext2fs_get_memzero() and ext2fs_file_get_inode(). + +The ext2fs library now has support for calculating the crc32c checksum +(via the new functions ext2fs_crc32c_be and ext2fs_crc32c_le). + +The I/O manager now supports the discard operation. + +Reserved file system code points for new 1st class quota feature. + +Shortened the compilation lines by moving the autoconf defines to +a config.h header file. + +Fixed a potential free of an unitialized pointer in +ext2fs_update_bb_inode(). + +Fixed miscellaneous gcc -Wall and coverity warnings. + +Fixed portability issues for Mac OS X, Hurd, and FreeBSD. + +Fixed a build failure when OMIT_COM_ERR is defined. + +Improved error checking and fixed memory leaks caused by error return +paths. + +Add ext2fs_flush2() and ext2fs_close2() which takes a flag to allow +the fsync() to be skipped. + +Added a test for extent-mapped journals by mke2fs and tune2fs. + +Added a test for creating a large (over 4GB) journal using mke2fs. + +Added a test to make sure the inode size remains constant. + +The regression test script now prints the list of which tests failed. + +The regression test system now uses /tmp for its scratch files, which +is often a tmpfs mounted file system and hence much faster. + +The i_e2image test was fixed so it works with valgrind. + +Tests that rely on debugfs are now skipped if debugfs wasn't built. + +Fixed the dependencies for "make check" so all required dependencies +are built before running the gression tests. + +A link to com_err.h is installed in $(includedir) during a "make install". + +The po/*.gmo files are automatically rebuilt if they are missing or +out of date. This helps out Debian packaging. + +Allow ext2fs_get_memalign() to compile on systems that don't have +posix_memalign(). + +Fixed a namespace leak in libext2fs (tdb_null). + + +E2fsprogs 1.41.14 (December 22, 2010) +===================================== + +Fix spurious complaint in mke2fs where it would complain if the file +system type "default" is not defined in mke2fs.conf. + +The resize2fs program will no longer clear the resize_inode feature +when the number reserved group descriptor blocks reaches zero. This +allows for subsequent shrinks of the file system to work cleanly for +flex_bg file systems. + +The resize2fs program now handles devices which are exactly 16T; +previously it would give an error saying that the file system was too +big. + +E2fsck (and the libext2fs library) will not use the extended rec_len +encoding for file systems whose block size is less than 64k, for +consistency with the kernel. + +Programming notes +----------------- + +E2fsprogs 1.41.13 would not compile on big-endian systems. This has +been fixed. (Addresses Sourceforge Bug: #3138115) + +The ext2fs_block_iterator2() function passed an incorrect ref_offset +to its callback function in the case of sparse files. (Addresses +Sourceforge Bug: #3081087) + +Fix some type-punning warnings generated by newer versions of gcc. + + +E2fsprogs 1.41.13 (December 13, 2010) +===================================== + +E2fsck now supports the extended option "-E journal_only", which +causes it to only do a journal replay. This is useful for scripts +that want to first replay the journal and then check to see if it +contains errors. + +E2fsck will now support UUID= and LABEL= specifiers for the -j option +(which specifies where to find the external journal). (Addresses +Debian Bug #559315) + +E2fsck now has support for the problems/<problem code>/force_no +configuration option in e2fsck.conf, which forces a problem to not be +fixed. + +Dumpe2fs will now avoid printing large negative offsets for the bitmap +blocks and instead print a message which is a bit more helpful for +flex_bg file systems. + +Mke2fs will now check the file system type (specified with the -t +option) to make sure it is defined in the mke2fs.conf file; if it is +not, it will print an error and abort. If the usage type (specified +with the -T option) is not defined in mke2fs.conf, mke2fs will print a +warning but will continue. (Addresses Debian Bug #594609) + +Clarified error message from resize2fs clarifying that on-line +shrinking is not supported at all. (Addresses Debian Bug #599786) + +Fix an e2fsck bug that could cause a PROGRAMMING BUG error to be +displayed. (Addresses Debian Bug #555456) + +E2fsck will open the external journal in exclusive mode, to prevent +the journal from getting truncated while it is in use due to a user +accidentally trying to run e2fsck on a snapshotted file system volume. +(Addresses Debian Bug #587531) + +Fix a bug in e2fsck so it has the correct test for the EOFBLOCKS_FL +flag. + +The tune2fs program can now set the uninit_bg feature without +requiring an fsck. + +The tune2fs, dumpe2fs, and debugfs programs now support the new ext4 +default mount options settings which were added in 2.6.35. + +The e2fsck and dumpe2fs programs now support the new ext4 superblock +fields which track where and when the first and most recent file +system errors occurred. These fields are displayed by dumpe2fs and +cleared by e2fsck. These new superblock fields were added in 2.6.36. + +Debugfs now uses a more concicse format for listing extents in its +stat command. This format also includes the interior extent tree +blocks, which previously was missing from stat's output for +extent-based files. + +Debugfs has a new option, -D, which will request Direct I/O access of +the file system. + +Mke2fs will skip initializing the inode table if a device supports +discard and the discard operation will result in zero'ed blocks. + +Badblocks will now correctly backspace over UTF-8 characters when +displaying its progress bar. (Addresses Gentoo Bug #309909; Addresses +Debian Bugs #583782 and #587834) + +E2freefrag will now display the total number of free extents. + +Resize2fs -P no longer requires a freshly checked filesystem before +printing the minimum resize size. + +Fixed a floating point precision error in a binary tree search routine +that can lead to seg fault in e2fsck and resize2fs. + +Fixed a bug in e2fsck where if both the original and backup superblock +are invalid in some way, e2fsck will fail going back to the original +superblock because it didn't close the backup superblock first, and +the exclusive open prevented the file system from being reopened. + +Fixed a big in e2freefrag which caused getopt parsing to fail on +architectures with unsigned chars. (Addresses Gentoo Bug: #299386) + +Clarified an mke2fs error message so a missed common in an -E option +(i.e., mke2fs -t ext4 -E stride=128 stripe-width=512 /dev/sda1") +results in a more understandable explanation to the user. + +Mke2fs now displays the correct valid inode ratio range when +complaining about an invalid inode ratio specified by the user. + +Mke2fs now understands the extended option "discard" and "nodiscard", +and the older option -K is deprecated. The default of whether +discards are enabled by default can be controled by the mke2fs.conf +file. + +Mke2fs's handling of logical and physical sector sizes has been +improved to reflect the fact that there will be some SSD's with 8k and +16k physical sectors arriving soon. Mke2fs will no longer force block +size to be the physical sector size, since there will be devices where +the physical sector size is larger than the system's page size, and +hence larger than the maximal supported block size. In addition, if +the minimal and optimal io size are not exported by the device, and +the physical sector size is larger than the block size, the physical +sector size will be used to set the Raid I/O optimization hints in the +superblock. + +E2fsck will now display a better, more specific error message when the +user enters a typo'ed device name, instead of blathering on about +alternate superblocks. + +Fixed various Debian Packaging Issues + +Updated/clarified man pages (Addresses Debian Bugs: #580236, #594004, +#589345, #591083; Addresses Launchpad Bug: #505719) + +Update the Chinese, Chzech, Dutch, French, Germany, Indonesian, +Polish, Swedish, and Vietnamese translations. + + +Programmer's Notes +------------------ + +Fix a dependency definition for the static and profiled blkid +libraries which could cause compile failures in some configurations. +(Addresses Debian Bug: #604629) + +Add support for Direct I/O in the Unix I/O access layer. + +Fixed a memory leak in the Unix I/O layer when changing block sizes. + +Fixed minor memory leaks in mke2fs. + +Added a new function to the ext2fs library, ext2fs_get_memalign(). + +The tst_super_size test program will check to make sure the superblock +fields are correctly aligned and will print them out so they can be +manually checked for correctness. + +Fixed some makefile dependencies for test programs in lib/ext2fs. + +Reserved the feature flags and superblock fields needed for the Next3 +snapshot feature. + +Reserved the feature flags for EXT4_FEATURE_INCOMPAT_DIRDATA and +EXT4_INCOMPAT_EA_INODE. + + +E2fsprogs 1.41.12 (May 17, 2010) +================================ + +Mke2fs now gives a correct error message if the external journal +device is not found. (Addresses Red Hat Bug #572935) + +Resize2fs -P will now refuse to print a minimum size if the file +system is not clean. Previously it would go ahead and print a minimum +size anyway, which might not be correct, leading to user confusion. + +E2fsck now tests for extents that begin at physical block 0 and +rejects them as invalid. (Addresses Google Bug: #2573806) + +Fixed a bug in e2fsck which could cause it to crash when trying to +remove an invalid extent and the block bitmaps hadn't yet been loaded. +(Addresses SourceForge Bug: #2971800) + +E2fsck now will completely skip time-based checks if the system clock +looks insane or the option broken_system_clock is set in +/etc/e2fsck.conf. + +E2fsck would previously report an i_blocks corruption for a 4T file +created using posix_fallocate; this bug has been fixed. + +E2fsck will now correctly mark a sparse journal as invalid and will +delete and recreate the journal to address the problem. + +E2fsck would previously incorrectly ask the user whether she would +like to abort the file system check after finding a problem --- and +then abort regardless of the user's answer. This is annoying, and +has been fixed. + +E2fsck can now continue even if it fails to recreate the resize +inode; previously it would just abort the file system check +altogether. + +E2fsck could potentially remove directory entries for inodes found in +the unused region of the inode table; this would generally happen on +ext4 file systems that do not use journaling. This bug has been fixed +by not clearing these directory entries once it has been established +that bg_unused_inodes may not be trustworthy; once pass #2 has been +completed, e2fsck will restart the file system check from the +beginning, and then it will be safe to delete any directory entries +pointing to inodes that appear to be deleted. (Addresses Google Bug: +#2642165) + +E2fsck will not try to set the block group checksums if the user +cancels the fsck with a control-C. It's a bad idea to set the +checksums if e2fsck hasn't been completed, and it often results an the +error message, "Inode bitmap not loaded while setting block group +checksum info". (Addresses Launchpad Bug: #582035) + +The mke2fs program now queries the kernel for the physical as well as +the logical sector size, and will not allow a blocksize below the +logical, and will strongly encourage a blocksize at least as big as +the physical blocksize. This is needed for 4k sector drives that +emulate 512 byte sector sizes. + +Mke2fs will now allow a flex_bg size of 1. This is unusual, and +rarely needed, but it is a legal value. + +E2fsck will check for cases where the EOFBLOCKS_FL is set when it is +not needed, and offer to clear it; this is a sign of a kernel bug, but +more importantly, some released kernels may crash when this situation +is encountered on ext4 file systems. (Addresses Google Bug: #2604224) + +E2fsck will use the EOFBLOCKS_FL flag exclusively to check whether +i_size is correct. (Kernels starting with 2.6.34 will set +EOFBLOCKS_FL.) + +The com_err library will now only output ^M (a CR character) when the +tty is in raw mode. + +Update the Czech, Chinese, Dutch, French, Germany, Indonesian, Polish, +and Vietnamese translations. + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs: #571247, #563487) + + +Programmer's Notes +------------------ + +The regression test suite now uses its own mke2fs.conf file, so that +downstream distributions want change the mke2fs.conf file which is +distributed in the RPM or dpkg file, without worrying about screwing +up the regression test results. + +Always build namei.o so that building with configure --disable-debugfs +works correctly. Long-term, if we care about reduced e2fsprogs +builds, we need a more general solution for deciding what .o files are +needed for a particular build. Given that install floppies are going +(gone?) the way the dodo bird, we probably don't care, though. +(Addresses Sourceforge Bug: #2911433) + +Add configure options --enable-symlink-build and +--enable-symlink-install, which allow e2fsprogs be built using +symlinks instad of hard links, and to be installed using symlinks +instead of hard links, respectively. It is useful when the file +system where the build is taking place, or the file system where +e2fsprogs is installed, can't handle hard links for some reason. +(Addresses Sourceforge Bug: #1436294) + +Fixed compile warning in mke2fs.c. + + +E2fsprogs 1.41.11 (March 14, 2010) +================================== + +E2fsck will no longer give a fatal error and abort if the physical +device has been resized beyond 2**32 blocks. (Addresses Launchpad +Bug: #521648) + +Debugfs has a bug fixed so that "logdump -b <blk>" now properly shows +the allocation status of the block <blk>. (Addresses Debian Bug: +#564084) + +E2fsck now prints a much more emphatic and hopefully scary message +when a file system is detected as mounted while doing a read/write +check of the filesystem. Hopefully this will dissuade users from +thinking, "surely that message doesn't apply to *me*" :-( + +E2fsck -n will now always open the file system read-only. We now +disallow certain combination of options which previously were manual +exceptions; this is bad because it causes users to think they are +smarter than they really are. So "-n -c", "-n -l", "-n -L", and "-n +-D" are no longer supported. (Addresses Launchpad Bug: #537483) + +In e2fsprogs 1.41.10, mke2fs would ask for confirmation to proceed if +it detected a badly aligned partition. Unfortunately, this broke some +distribution installation scripts, so it now just prints the warning +message and proceeds. (Addresses Red Hat Bug: #569021. Addresses +Launchpad Bug: #530071) + +Mke2fs would take a long time to create very large journal files for +ext4. This was caused by a bug in ext2fs_block_iterate2(), which is +now fixed. + +E2fsck now understands the EOFBLOCKS_FL flag which will be used in +2.6.34 kernels to make e2fsck not complain about blocks deliberately +fallocated() beyond an inode's i_size. + +E2fsprogs 1.41.10 introduced a regression (in commit b71e018) where +e2fsck -fD can corrupt non-indexed directories when are exists one or +more file names which alphabetically sort before ".". This can happen +with ext2 filesystems or for small directories (take less than a lock) +which contain filenames that begin with a space or some other +punctuation mark. (Addresses Debian Bug: #573923, Addresses Launchpad +Bug: #525114) + + +Programmer's Notes +------------------ + +Add new test, f_rehash_dir, which checks to make sure e2fsck -D works +correctly. + +The libcom_err function now has support for Heimdal's com_right_r +function(). (Addresses Sourceforge Bug: #2963865, Addresses Debian +Bug: #558910) + + +E2fsprogs 1.41.10 (February 7, 2010) +==================================== + +Fix resize2fs bug which causes it to access invalid memory. + +Add libss support for libreadline.so.6. + +Fix e2fsck's check for extent-mapped directory with an incorrect file +type. + +Add new e2fsck.conf configuration option, default/broken_system_clock +to support systems with broken CMOS hardware clocks. Also, since too +many distributions seem to have broken virtualization scripts now, +e2fsck will by default accept dates which are off by up to 24 hours by +default. (Addresses Debian Bugs: #559776, #557636) + +Fix a bug where mke2fs may not use the best placement of the inode +table when there is only room for a single block group in the last +flex_bg. + +E2fsck is now smarter when it needs to allocate blocks in the course +of fixing file system problems. This reduces the number of spurious +differences found in pass #5. + +E2fsck will no longer rehash directories which fit in a single +directory block. + +E2fsck now correctly handles holes in extent-mapped directories (i.e., +sparse directories which use extents). + +Fix big-endian problems with ext2fs_bmap() and ext2fs_bmap2(). + +Fix a bug in filefrag where on platforms which can allow file systems +with 8k blocks, that it doesn't core dump when it sees a file system +with 8k block sizes. (Thanks to Mikulas Patocka for pointing this +out.) + +E2fsck will correctly fix directories that are have an inaccurate +i_size as well as other problems in a single pass, instead of +requiring two e2fsck runs before the file system is fully fixed. + +Fix e2fsck so it will correctly find and detect duplicate directory +entries for non-indexed directories. ( Addresses Sourceforge Bug: +#2862551) + +Mke2fs will use BLKDISCARD to pre-discard all blocks on an SSD or +thinly-provisioned storage device. This can be disabled using the -K +option. + +Enhance libext2fs so it works around bug in Linux version 2.6.19 +and earlier where the /proc/swaps file was missing the header on +the first line. + +Fix bug in Linux version 2.6.19 and earlier where the /proc/swaps file +was missing the header on the first line. + +Fix some big-endian bugs in e2fsck and libext2fs. + +Fix resize2fs so it works correctly on file systems with external +journals instead of failing early with the error "Illegal inode +number". + +Fix libss so that it does not seg fault when using a readline library +which does not supply a readline_shutdown() function. + +Updated dumpe2fs's usage message so it correctly gives the right +arguments summary for "-o superblock=<num>" and "-o blocksize=<num>". +(Addresses Launchpad Bug: #448099) + +Teach libext2fs to ignore the high 32 bits of the i_blocks field +when huge_file file system feature is set, but the inode does not +have the HUGE_FILE_FL flag set. + +Fix e2fsck's handling of 64-bit i_blocks fields. + +E2fsck will now print "Illegal indirect block", "Illegal +double-indirect block", etc., instead of "Illegal block #-1" or +"Illegal block #-2", etc. This makes it easier for users to +understand what has gone wrong. (Addresses SourceForge Bug: #2871782) + +Mke2fs now will obtain get device topology information from blkid and +use it to populate the superblock stride and stripe sizes. It will +also warn if the block device is misaligned + +Fix file descriptor leaks in fsck and debugfs. (Addresses Novell Bug: +##524526) + +Fix the libext2fs library code to round up the bitmap size to a 4-byte +boundary, to prevent spurious seg faults caused by the x86 +architecture. This doesn't affect Linux systems, but was a major +problem on a number of *BSD systems. (Addresses Sourceforge Bug: +#2328708) + +Fix resize2fs's minimum size required for a file system so it doesn't +fail when "resize2fs -M" is run. (Addresses RedHat Bugzilla: #519131) + +Dumpe2fs now prints summary information about the contents of the +journal. + +Avoid printing scary error messages when e2fsck starts running +problems on low-memory systems, as it tends to panic and mislead the +user. (Addresses Debian Bug: #509529) + +Fix blkid's modules.dep parser so it handles compressed (.ko.gz) +modules files. (Address Red Hat Bug: #518572) + +Fix tune2fs so it can add a journal when an extent-enabled file system +is mounted. (Addresses Launchpad bug: #416648) + +Update Czech, Indonesian, Polish and Vietnamese translations (from the +Translation Project). + +Update/clarify man pages. (Addresses Sourceforge Bug: #2822186) + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs: #540111) + +Programmer's Notes +------------------ + +The configure script supports the --with-cc, --with-ccopts, and +--with-ldopts options. Instead, the more standard use of CC=, +CCFLAGS=, and LDFLAGS= in the configure command line is used instead. +Also, --with-ld, which never worked, was also removed. +(Addresses Sourceforge Bug: #2843248) + +The in-tree header files are only used if the in-tree uuid or blkid +libraries are used. Otherwise, use the system-provided uuid or blkid +header files if using the system-provided libraries. + +Fix some build failures caused by --disable-* configure options. + +Work around a bug in autoconf 2.64. + + +E2fsprogs 1.41.9 (August 22, 2009) +================================== + +Fix a bug in e2fsck routines for reallocating an inode table which +could cause it to loop forever on an ext4 filesystem with the FLEX_BG +filesystem feature with a relatively rare (and specific) filesystem +corruption. This fix causes e2fsck to try to find space for a new +portion of the inode table in the containing flex_bg, and if that +fails, the new portion of the inode table will be allocated in any +free space available in the filesystem. + +Make e2fsck less annoying by only asking for permission to relocate a +block group's inode table once, instead of for every overlapping +block. Similarly, only ask once to recompute the block group +checksums, instead of once for each corrupted block group's checksum. + +Fix filefrag to avoid print the extent header if the FIEMAP ioctl is +not present, and it needs to fall back to using the FIBMAP ioctl. + +Fix filefrag to correctly print the number of extents for zero-length +files. (Addresses Debian Bug: #540376) + +Filefrag now has a -B option which forces the use of the FIBMAP ioctl +to more easily debug the FIBMAP code. + +Fixed filefrag for non-extent based files. + +Add a new program, e2freefrag, which displays information about the +free space fragmentation in an ext2/3/4 filesystem. + +Fix inode resizing via tune2fs -I so that it works correctly in the +face of non-empty bad blocks inodes, and if the filesystem was +formatted using the "mke2fs -E stride=N" option for RAID arrays. + +Fix regression in ext2fs_extent_set_bmap() caused e2fsck -fD to fail +and corrupt large directories if the directory needs to shrink by more +than one block. (Addresses Debian Bug: #537510) + +Fix e2fsck's buggy_init_scritps=1 so that the if the last write and/or +last mount times are in the future, they are corrected even if +buggy_init_scripts is set. This is needed because otherwise resize2fs +will refuse to resize the filesystem, even after running "e2fsck -f". +(Addresses Launchpad bug: #373409) + +E2fsck will now print much fuller information when the last mount time +or last written time is in the future, since most people can't seem to +believe their distribution has buggy init scripts, or they have a +failed CMOS/RTS clock battery. + +Enhance dumpe2fs to dump the extent information via the 'stat' +command, and more detailed extent information via the new command +'dump_extents'. + +Update French, Polish, Czech, and Sweedish translation from the +Translation Project. + +Fixed various Debian packaging issues --- see debian/changelog for +details. + +Programmer's Notes +------------------ + +Fixed miscellaneous gcc -Wall warnings. + +Fixed memory leak in error path in ext2fs_block_iterate2() + +Fixed non-Linux build of the intl directory by adding support for the +E/Q/V macros. + +The bitmap read/write functions now treat uninitialized bitmaps as +unallocated; this fixes a number of problems in all e2fsprogs for ext4 +filesystems when there is a need to allocate new blocks or inodes, and +there aren't any free blocks or inodes in the already-used block +groups. + +Improve ext2fs_extent_set_bmap() to avoid creating new extents which +get inserted into the extent tree when they are not needed. + + +E2fsprogs 1.41.8 (July 11, 2009) +================================ + +Fix resize2fs's online resizing, fixing a regression which in +e2fpsrogs 1.41.7. (Addresses Debian Bug: #535452) + +Fix potential filesystem corruptions caused by using resize2fs to +shrinking ext4 filesystems with extents enabled. (Addresses Red Hat +Bug: #510379) + +Optimize uuid_generate() to avoid running uuidd if it is not setuid or +setgid and the currently running program doesn't have write access to +the uuidd work directory. + +Add safety checks (for non-Linux systems) so that uuidd isn't run with +file descriptors 0, 1, and 2 closed; and if they are closed, uuidd +will be careful not to close the file descriptor for its unix domain +socket when it detaches itself from the controlling tty. Also add +safety checks so that if the unix domain socket between the uuid +library and uuidd program is closed for any reason, both the library +and the uuidd will return an appropriate error code instead of looping +in an infinite loop. + +The e2croncheck script, which creates an LVM snapshot and then checks +the ext3/4 filesystem via the LVM snapshot, has been added to the +contrib directory. + +Fix filefrag program for files that have more than 144 extents. + +Update French, Polish, Czech, Indonsian, and Sweedish translation from +the Translation Project. + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bug #535530) + +Update/clarify man pages. + +Programmer's Notes +------------------ + +Fix compilation problem when configured with --disable-uuid. + +Don't build uuidgen if configured with --disable-uuid. + +Add the new library function ext2fs_test_inode_bitmap_range(), and +optimized ext2fs_test_block_bitmap_range(), which will be needed for +future optimizations for e2fsck. + +Fix makefile dependencies for libcom_err so that the Makefiles work +well on non-GNU make program. (Addresses Sourceforge Patches: #2813809) + +Enhance the build system so that the full set of commands executed by +the Makefiles are displayed, instead of the Linux kernel summary +output, if the build was configured with --enable-verbose-makecmds, or +if GNU make is in use and the V variable is non-null, i.e., via "make +V=1". + + +E2fsprogs 1.41.7 (June 29, 2009) +================================ + +Fix a bug in libext2fs which can cause e2fsck and resize2fs to write +uninitalized data into the portion of the inode beyond the first 128 +bytes when operating on inodes mapped via extents; potentially +corrupting filesystems. + +Fix memory leaks in e2fsprogs, including a very large memory leak +which can cause e2fsck to run out of memory when checking very large +filesystems using extents. + +The logsave program will now filter out the ^A and ^B characters when +writing to the console. + +Harden ext2fs_validate_entry() so that lsdel will not read beyond the +end of the block even if the directory block is corrupted. + +Fix debugfs from core dumping if the logdump command fails to open the +output file. + +Enhance badblocks to print the currently tested block number when +interrupted with ^C. + +Fix lsattr to exit with a non-zero status when it encounters errors. +(Addresses RedHat Bugzilla #489841) + +Fix e2fsprogs to use the same encoding for rec_len in 64k (and larger) +filesystems as the kernel when encoding rec_len >= 64k. For 64k +filesystems (currently all that is supported by e2fsprogs, this is +only a minor corner case). + +Resize2fs will now update the journal backup fileds in the sup0erblock +if the journal is moved; this avoids an unnecessary full fsck after +resizing the filesystem. (Addresses RedHat Bugzilla: #505339) + +Fix libext2fs to properly initialize i_extra_size when creating the +journal and resize inodes. + +Change badblocks to allow block sizes larger than 4k. + +Fix filefrag progam so it correctly checks for errors from the fiemap ioctl. + +Update Chinese and Czech translation from the Translation Project. + +Clean up various man pages. (Addresses Debian Bug #531385 and #523063) + + +Programmer's Notes +------------------ + +Add --disable-libuuid option to configure which uses an in-system +installed version of libuuid; the private version is enabled by +default. + +Add --valgrind-leakcheck option to the test_script program which runs +valgrind with the appropriate options to find memory leaks. + + +E2fsprogs 1.41.6 (May 30, 2009) +=============================== + +Fix a critical regression in e2fsck introduced version 1.41.5 which +can undo updates to the block group descriptors after a journal replay. + +If e2fsck receives an I/O error while replaying the journal, prompt +the user whether they want to ignore the error or not; if e2fsck is +run in preen mode, force fsck to abort the preen pass. + +Fix a bug which would cause e2fsck to core dump if the filesystem +contains a corrupt extent header, and the user declines to clear the +inode. (Addresses Sourceforge Bug: #2791794) + +Fix e2fsck to restart only once in the case of multiple block groups +which inodes in use that are in the uninitialized part of the block +group's inode table. + +To reduce user confusion, if the /etc/mtab file is missing +ext2fs_check_mount_point and ext2fs_check_if_mounted will return a +new, explicit error code to indicate this case. This will cause +e2fsck to give a clearer error message when the user is using buggy +rescue CD's that don't properly set up /etc/mtab. (Addresses Debian +Bug: #527859) + +Fix e2fsck so that if the primary group descriptors are corrupted, but +the backup superblock is entirely invalid, to go back to using (and +fixing) the priary group descriptors instead of completely giving up +on the filesystem. (Addresses Debian Bug: #516820) + +Change e2fsck to not abort a preen pass if an inode is found to have +i_file_acl_hi non-zero. Ext3 filesystems don't care, and newer +kernels (post 2.6.29) will ignore this field. So let's fix it +automatically during the preen pass instead of forcing the user to fix +this up manually. (Addresses Debian Bug: #526524) + +Add resource tracking for e2fsck passes 1b through 1d. + +Speed up e2fsck by eliminating unnecessary journal checks if the +filesystem is already mounted and doesn't need recovery (since the +kernel would have run the journal when the filesystem was mounted.) +Also speed up e2fsck by avoiding unnecessary block group descriptor +updates in ext2fs_close(). + +Add support to chattr to migrate inodes from using direct/indirect +blocks to extents. + +Avoid corrupting the filesystem if there is an attempt to shrink a +filesystem using resize2fs smaller than posible by making +ext2fs_set_bmap() more careful not to delete the old block until the +new block can be inserted. In addition, fix a bug in how the minimum +size of the filesystem (plus a safety margin) is calculated, and +modify resize2fs to refuse to shrink the filesystem below that minimum +size without the force flag. + +Teach blkid to try to figure out DM device names using take advantage +of information in sysfs when running on kernels (2.6.29 and later) +which provide this information in /sys/block/dm-<N>/dm/name; this is +much faster than scanning for the devncie number in /dev/mapper. + +Fix blkid to prefer /dev/mapper/<name> device names instad of the +private /dev/dm-X names. + +Add an -a option to debugfs's close_filesys command which writes any +changes to the superblock or block group descriptors to all of the +backup superblock locations. + +Add support to the filefrag program to use the FIEMAP ioctl. + +Update Chinese translation from the Translation Project. + +Clean up various man pages. (Addresses Red Hat Bugzilla: #502971 and +Launchpad Bug: #381854) + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bug #506064) + + +Programmer's Notes +------------------ + +Add test code to make sure e2fsck's problem.c doesn't have two problem +codes assigned to duplicate values. + +Avoid using a hard-coded path for /bin/rm in block's test_probe.in. +(Addresses Sourceforge Bug: #2780205) + +Clean up e2fsck by removing #ifdef RESOURCE_TRACK by adding an empty +function declaration for init_resource_track() and +print_resource_track() when RESOURCE_TRACK is not defined. + +The test code which is used to build the tst_csum progam has been +moved from from tst_csum.c into csum.c under an #ifdef DEBUG to to +avoid compile problems caused by not having a prototype for +ext2fs_group_desc_csum(). (Addresses Sourceforge Bug #2484331) + +Update the config.guess and config.sub file to the latest from the +FSF, to allow e2fsprogs to build on the avr32 platform. (Addresses +Debian Bug: #528330) + +Add a new function, ext2fs_extent_open2(), which behaves like +pext2fs_extent_open(), but uses the user-supplied inode structure +when opening an extent instead of reading the inode from disk. + + +E2fsprogs 1.41.5 (April 23, 2009) +================================= + +Fix a number of filesystem corruption bugs in resize2fs when growing +or shrinking ext4 filesystems off-line (i.e., when the ext4 filesystem +is not mounted). + +Debugfs can now set i_file_acl_high via the set_inodes_field command, +and print a 64-bit file acl. This is useful for debugging filesystem +corruptions where the high bits of i_file_acl_high are set. E2fsck +will detect and fix non-zero i_file_acl_high on 32-bit filesystems +since some Linux kernel versions pay attention to this field even when +they shouldn't. + +Speed up e2fsck when checking clean filesystems by avoiding +unnecessary block reads, and coalescing the block group descriptor +blocks so they are read using a single read operation. + +The libuuid library will now close all file descriptors before running +uuidd. This avoids problems when the calling program has open sockets +which then never get closed because uuidd is a long-running helper +daeomn. (Addresses Launchpad bug: #305057) + +In order to avoid unnecessary full filesystem checks by e2fsck after +an on-line resize, e2fsck will ignore the NEEDS_RECOVERY flag set on +the backup superblocks. (Addresses Red Hat Bugzilla: #471925) + +Mke2fs will avoid trying to create the journal when run in +superblock-only mode (mke2fs -S), since the left-over journal in the +inode table will cause mke2fs to fail. + +Fix a bug in libext2fs functions that check to see if a particular +device or filesystem image is mounted, which would cause these +functions to report that a file identical to the (relative) pathname +used by a pseudo-filesystem was mounted when in fact it was not. + +Update Czech translation from the Translation Project. + +Add Chinese (simplified) translation from the Translation Project. + +Fix support for external journals (which was broken in e2fsprogs +1.41.4). + +Fix a regression in debugfs where the "stat" command when no +filesystem was open would cause debugfs to crash with a segmentation +violation. + +Starting in the 2.6.29 linux kernel, the ext4 filesystem driver can be +used to support filesystems without a journal. Update the blkid +library so it understands this. + +The blkid library will remove an entry from the blkid cache +representing the entire disk if partitions are found, since presuambly +the device previously had no partition table, but has now transitioned +to using a partition table. + +Add a check to mke2fs and tune2fs that the argument to the -m option +(which specifies the reserved ratio) must be greater than zero. +(Addresses Debian Bug: #517015) + +Add support for tracking the number kilobytes written to the +filesystem via the superblock field s_kbytes_written. It will be +updated by the kernel as well as by e2fsprogs programs which write to +the filesystem. This is useful for tracking the wear to filesystems +on Solid Sstate Drives. + +Fix compatibility issue in the libext2fs info file and makeinfo +version 4.12. (Addresses Red Hat Bugzilla: #481620) + +Update/clarify man pages. (Addresses Debian Bug: #515693, #365619) + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bug: #506279) + +Programmer's Notes +------------------ + +Fix Hurd compilation problem in e2fsck and tune2fs (Addresses Debian +Bug: #521602) + +Fix various gcc compilation warnings and other programming cleanups. +(Addresses Red Hat Bugzilla: #486997) + +Add support for building the blkid command statically. + +Add support for disabling the built-in blkid library in favor of a +system-installed blkid implementation via the configure option +--disable-libblkid. + + +E2fsprogs 1.41.4 (January 27, 2009) +=================================== + +Fixed a bug which could sometimes cause blkid to return an exit value +of zero for a non-existent device (Addresses Debian Bug: #502541) + +Blkid will now recognize ext3 filesystems that have the test_fs flag +set as ext3 filesystems. + +The blkid library will now recognize btrfs filesystems and swap +devices currently used by user-level software suspend. + +Tune2fs now updates the block group checksums when changing the UUID +to avoid causing e2fsck to complain vociferously at the next reboot. + +Tune2fs's inode size resizing algorithms have been fixed so it is not +vastly inefficient for moderate-to-large filesystems, due to some +O(n**2) and O(n*m) algorithms that didn't scale well at all. + +Fix tune2fs's inode resizing algorithm so it will not corrupt +filesystems laid out for RAID filesystems; in addition, tune2fs will +refuse to change the inode size for filesystems that have the flex_bg +feature enabled. (This is a limitation in the current implementation +of tune2fs -I.) + +E2fsprogs 1.41 broke debugfs's logdump command for normal ext3/4 +filesystems with 32-bit block numbers, when the headers for 64-bit +block numbers was added. This regression has been fixed. + +Debugfs's ncheck command has been fixed to avoid printing garbage +characters at the end of file names. + +Fix resize2fs for ext4 filesystems. Some blocks that that need moving +when shrinking filesystems with uninit_bg feature would not be moved. +In addition, blocks and inode table blocks were not being correctly +freed when shrinking filesystems with the flex_bg feable, which caused +resize2fs -M to fail. Finally, when blocks are moved, make sure the +uninitialized flag in extents is preserved. + +Fix bug which caused dumpe2fs to abort with an error if run on a +filesystem that contained an external journal. + +Some distributions used "mke3fs" as an alias for "mkfs.ext3"; check +for this in argv[0] to provide better legacy support for these +distributions. This is a practice that should NOT be continued, +however. + +Mke2fs now has a new option -U, which allows the user to specify the +UUID that should be used for the new filesystem. + +Mke2fs will treat devices that are exactly 16TB as if they were 16TB +minus one block. This allows users who have read that ext3 supports +up to 16TB filesystems and who create a 16TB LVM to not get confused, +since the true limit is really 16TB minus one block. + +E2fsck will no longer abort an fsck run if block group has an errant +INODE_UNINIT flag. + +E2fsck now distinguishes between fragmented directories and fragmented +files in verbose mode statistics and in the fragcheck report. + +Fix a bug in e2fsck which casued it double count non-contiguous +extent-based inodes. + +E2fsck will leave some slack space when repacking directories to allow +room for a few directory entries to be added without causing leaf +nodes to be split right away. + +Fix a bug which caused e2fsck to crash when it comes across a +corrupted interior node in an extent tree with the error message: +"Error1: Corrupt extent header on inode XXXXXX" + +E2fsck problem descriptions involving the journal are no longer +referred to as "ext3" problems, since ext4 filesystems also have +journals. + +Fix a long-standing bug in e2fsck which would cause it to crash when +replying journals for filesystems with block sizes greater than 8k. + +Update Catalan translation from the Translation Project. + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs: #503057, #502323, #511207) + +Programmer's Notes +------------------ + +Fix build of e2fsck.profiled, and add support for building profiled +binaries in the misc directory if configured with --enable-profile. + +The ext2fs_open() function now performs more sanity checks on the +superblock to avoid potential divide by zero errors by other parts of +library. + +The ext2fs_read_inode_full() function now has a safety check to avoid +a segmentation fault on corrupted filesystems. + +The ext2fs_new_inode() function now has a sanity check so that if the +s_first_inode field in the superblock is insane, it will return +EXT2_ET_INODE_ALLOC_FAIL instead of returning an invalid inode number. + +To avoid segmentation faults, ext2fs_block_alloc_stats() and +ext2fs_inode_alloc_stats() now validates the passed inode or block +number to avoid overrunning an array boundary. + +Various signed/unsigned errors for variables containing block numbers +have been fixed. + +Accomodations for gcc's stupidity in not realizing that constant +strings that do not contain a '%' character are safe to use in format +strings have been made so that distributions that want to compile +e2fsprogs with -Werror=format-security have an easier time doing so. + +Added a new 64-bit getsize interface, ext2fs_get_device_size2(). + +Added the utility make-sparse.c to the contrib directory. + +The ext2fs_block_iterate2() function now reflects errors from +ext2fs_extent_set_bmap() to the caller, if the callback tries to +change a block on an extent-based file, and ext2fs_extent_set_bmap() +fails for some reason (for example, there isn't enough disk space to +split a node and expand the extent tree. + +The ext2fs_block_iterate2() function will preserve the uninit flag in +extents when the callback function modifies a block in an extent-based +file. + +E2fsck will now flag filesystems that have an insane s_first_ino field +in their superblock, and attempt to use a backup superblock to repair +the filesystem. + + +E2fsprogs 1.41.3 (October 12, 2008) +=================================== + +E2fsck has been fixed so it prints the correct inode number for +uinit_bg related problems. + +E2fsck will now offer to clear the test_fs flag if the ext4 filesystem +is available on linux. This can be disabled via a configuration +option in /etc/e2fsck.conf. + +Fix a file descriptor leak in libblkid when checking to see if an ext4 +or ext4dev module exists. + +Fix a bug in e2fsck where in preen mode, if there are disk I/O errors +while trying to close a filesystem can lead to infinite loops. +(Addresses Red Hat Bugzilla #465679) + +Fix a bug in resize2fs where passing in a bogus new size of 0 blocks +will cause resize2fs to drop into an infinite loop. (Addresses Red +Hat Bugzilla: #465984) + +Add a check in the Unix I/O functions in libext2fs so that when a +device is opened read/write, return an error if the device is +read-only using the BLKROGET ioctl. + +Fix debugfs's ncheck command so that it prints all of the names of +hardlinks in the same directory. + +Fix a bug in libblkid so it correctly detects whether the ext4 and +ext4dev filesystems are available, so that the ext4dev->ext4 +fallback code works correctly. + +Programmer's Notes +------------------ + +Fix a parallel build problem by making sure util/subst is built before +trying to build the lib/et directory. (Addresses Sourceforge Bug: +#2143281) + +Updated "make depend" information for crc16.o + + +E2fsprogs 1.41.2 (October 2, 2008) +================================== + +Fix e2fsck's automatic blocksize detection. This fixes a regression +from e2fsprogs 1.40.7 which caused e2fsck to fail if the user +specifies a block number using the -b option if the blocksize option +isn't also specified using -B. Unfortunately, users very commonly +invoke e2fsck using "e2fsck -b 32768 /dev/hdXXX" to use the backup +superblock; in fack e2fsck will often suggest this kind of command +line. Oops. + +Enhance the debugfs's "ncheck" command so it will print all of the +pathnames for the specified inodes. (Previously, in some cases ncheck +might not print a pathname for an inode at all if some of the other +inodes had multiple hard links.) + +Enhance debugfs's "hash" command so the hash seed can be specified via +a command-line option. In addition, allow the hash algorithm to be +specified by name instead of just by number. + +Fix e2fsck so that we don't accidentally print the translation file's +header when asking the user a custom question so there is no prompt +defined for a particular problem record. For example, the question +"Run journal anyway" will get the PO header tacked on because e2fsck +erroneously passed the null string to _(). (Addresses Launchpad Bug: +#246892) + +Enhance badblocks so that it can test a normal file which is greater +than 2GB. + +Enhance the badblocks command so that it displays the time and +percentage complete when in verbose mode. (Addresses Debian Bug: +#429739) + +Fix a potential memory leak in a error handling path in debugfs's +ncheck function. + +Fix a potential memory corruption problem if a memory allocation fails +in resize2fs. + +Fix the usage message for debugfs's logdump command to be consistent +with its man manpage. + +Update Polish, French, Vietnamese, Dutch, Indonesian, German, Czech, +and Sweedish translation from the Translation Project. + +Add documentation for the file I/O functions to the libext2fs.texinfo +file. (Addresses Debian Bug: #484877) + +Update and clarified various man pages. (Addresses Launchpad Bug +#275272; Addresses Debian Bugs: #498100, #498101, #498102, #498103) + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bug: #497619) + +Programmer's Notes +------------------ + +Fix a potential file descriptor leack in libcom_err by setting the +close-on-exec flag for a fd used for debugging. (Addresses Red Hat +Bugzilla #464689) + +Fix a potential race in libcom_err by using sem_post/sem_init. SuSE +has been carrying a patch for a long time to prevent a largely +theoretical race condition if a multi-threaded application adds and +removes error tables in multiple threads. Unfortunately SuSE's +approach breaks compatibility by forcing applications to link and +compile with the -pthread option; using pthread mutexes has +historically been problematic. We fix this by using sem_post/sem_init +instead. + +Fix e2fsprogs-libs build failure due to 'subs' target. (Addresses +Sourceforge Bug: #2087502) + +Avoid linking e2initrd_helper, debugfs, blkid, and fsck with unneeded +libraries when using ELF shared libraries. + +Fix ELF shared library when building on systems that don't already +have the e2fsprogs shared libraries already installed. (Addresses +Sourceforge Bug: #2088537) + +Fix the pkg-config files so they work correctly when linking with +static libraries and fix the include directory so programs don't have +to use #include <ext2fs/ext2fs.h>, but can use #include <ext2fs.h> +instead. (Addresses Sourceforge Bug: #2089537) + +Make sure ext2fs_swab64() is compiled for all platforms, and not just +for x86. (Addresses Debian Bug: #497515) + +Remove the unused ext2fs_find_{first,ext}_bit_set() functions for all +non-x86 platforms. (They had been removed for x86 earlier.) + +Fix diet libc compilation support, which had bitrotted due to lack of +TLC. Fixing this improves general portability. + +When installing the link library when using ELF shared libraries, +avoid using absolute pathnames if the link library and the shared +library are installed in the same directory. (Addresses Sourceforge +Bug: #1782913) + +Fix gen-tarball so it will work even if the top-level directory has +been renamed to something other than "e2fsprogs". Also make +gen-tarball print the size of the resulting tar.gz file. + + +E2fsprogs 1.41.1 (September 1, 2008) +==================================== + +Many people are forgetting to update their mke2fs.conf file, and this +causes ext3, ext4, and ext4dev filesystems won't get created with the +proper features enabled. We address this in two ways. First, mke2fs +will issue a warning if there is not definition for an ext3, ext4, or +ext4dev filesystem and the user is trying to create such a filesystem +type. Secondly, when installing from a source build, "make install" +will provide basic configuration file handling for /etc/mke2fs.conf. +If it exists, and does not mention ext4dev, it will be moved aside to +/etc/mke2fs.conf.e2fpsrogs-old and the new /etc/mke2fs.conf file will +be installed. If the existing /etc/mke2fs.conf file does mention +ext4dev, then "make install" will install official mke2fs.conf file as +/etc/mke2fs.conf.e2fsprogs-new and issue a message to the user that +they should look to see if any changes need to be merged. + +The mke2fs program will now create the journal in the middle of the +filesystem, since this minimizes seek times on average for fsync-heavy +workloads. In addition, mke2fs will now create journals using extents +for filesystems that support them. This results in a more efficient +encoding for the journal since it eliminates the need for using +indirect blocks. + +The mke2fs program will avoid allocating an extra block to the +journal. (Addresses Sourceforge Bug: #1483791) + +Mke2fs will correctly enforce the prohibition against features +(specifically read-only features) in revision 0 filesystems. (Thanks +to Benno Schulenberg for noticing this problem.) + +Mke2fs previously would occasionaly create some slightly non-optimally +placed inode tables; this bug has been fixed. + +The mke2fs and tune2fs programs now print the correct usage message +describing the maximum journal size. (Addresses Debian Bug: #491620) + +Add support for setting the default hash algorithm used in b-tree +directories in tune2fs (from a command-line option) or mke2fs (via +mke2fs.conf). In addition, change the default hash algorithm to +half_md4, since it is faster and better. + +The blkid library will now recognize MacOS hfsx filesystems, and +correctly extract the label and uuid for hfs, hfsx, and hfsplus +filesystems. (Addresses Sourceforge Feature Requests: #2060292) + +The blkid library has improved detection of JFS and HPFS filesystems. +(Addresses Launchpad Bug: #255255) + +The blkid library is now much more efficiently handling devicemapper +devices, mainly by no longer using the devicemapper library. This can +speed up access for systems with a large number of device mapper +devices. + +Blkid had a number of cache validation bugs in libblkid that have been +fixed. (Addresses Debian Bug: #493216) + +Resize2fs will now properly close out the "updating inode references" +progress bar so there is a newline printed before printing the final +"resize is successful" message. + +Resize2fs will now correctly handle filesystems with extents and/o +uninitialized block groups correctly when file/directory blocks need +to relocated (i.e., when shrinking a filesystem or if the resize_inode +is not present). To support this, the ext2fs library now supports +initializing inode and block bitmaps that are not yet initialized when +allocating them using ext2fs_new_block() and ext2fs_new_inode(). In +addition, e2fs_block_iterate2() can now support changing the location +of interior nodes of an extent tree, and ext2fs_extent_set_bmap() has +been optimized to avoid creating unnecessary new extents when updating +the location of blocks in the extent tree. This will also help out +e2fsck's recovery of obscurely corrupted filesystems with extents, +when blocks are claimed by multiple inodes. + +Add support for on-line resizing ext4 filesystem with the flex_bg +filesystem feature. The method for doing so is not optimal, but to do +a better job will require kernel support. + +E2fsprogs 1.41.0 intrduced a bug in libext2fs which casued e2image and +debugfs programs to not be able to read e2image files; the signed +vs. unsigned bug in the code which read bitmaps from the e2image has +been fixed. (Addresses Debian Bug: #495830) + +Resize2fs is now correctly managing the directory in-use counts when +shrinking filesystems and directory inodes needed to be moved from one +block group to another. This bug has been around since e2fsprogs +1.26, and is largely harmless, but does cause a filesystem corruption +which will be flagged by e2fsck after the filesystem has been shrunk. + +E2fsck will no longer issue spurious complaints about the inode size +caused by very large extent-based files, and by blocks reallocated +using fallocate() with the FALLOC_FL_KEEP_SIZE option. (Addresses +Kernel Bugzilla: #11341) + +Mke2fs will now set the creation timestamp on the lost+found directory +and the root directory. (More generally, all new inodes created using +the ext2fs library will correctly set the creation timestamp.) + +E2fsck now correctly calculates ind/dind/tind statistics in the +presence of extent-based files. In addition, "e2fsck -v" will report +statistics of the depth of extent trees in the filesystem. E2fsck can +also give an inode fragmentation report using "e2fsck -E fragcheck" +which can be useful when debugging the kernel block allocation +routines. + +Fix support for empty directory blocks in ext4 filesystems with 64k +blocksize filesystems. + +E2fsck will now print the depth of corrupt htree directories. + +Debugfs's htree command now correctly understands extent-based +directories. It will also print out the minor hash as well as the +major hash. + +Debugfs has a new command which will print the supported features of +e2fsprogs, to enable scripts to know whether the installed version of +e2fsprogs can support a specific feature. + +Debugfs will now write files using extents for filesystems that +support them. + +The error message printed by "tune2fs -I" if the inode size was too +small was rather confusing, so it has been improved. Also, we won't +try to create an undo log until we know that command-line-specified +parameters such as "tune2fs -I <inode size>" are valid. + +Given some filesystems found "in the wild" that had non-zero block +group checksums even though the uninit_bg/gdt_sum feature was not +enabled, e2fsck would issue spurious error messages. Teach +ext2fs_group_desc_csum_verify() to ignore the block group checksum +entirely if the feature flag is not set. (Addresses Debian Bug: +#490637) + +The blkid program will now print out a user-friendly listing of all of +the block devices in the system and what they contain when given the +-L option. (Addresses Debian Bug: #490527) + +The filefrag program now has a more accurate calculation for the +number of ideal extents. (Addresses Debian Bug: #458306) + +The test I/O manager is now enabled by default, but its overhead is +only incurred when it would be enabled via the TEST_IO_FLAGS or +TEST_IO_BLOCK environment variables. + +Typographical errors in various program strings and usage messages +have been fixed; most of these were pointed out by the e2fsprogs +message catalog translators. (Thanks, translators!) + +Update and clarified various man pages, as well as some typographical +errors in the libext2fs texinfo file. + +Fixed various Debian packaging issues --- see debian/changelog for +details. + +Add Indonesian and update French, Polish, Dutch, German, Sweedish, +Czech, and Vietnamese Translations. (Addresses Debian Bugs: #313697, +#401092) + +Programmer's Notes +------------------ + +Fix portability problem with the badblocks group; for systems that +don't have nanosleep(), try using usleep() instead. + +The "make check" target in the e2fsck directory now sets +LD_LIBRARY_PATH before running the various e2fsck internal library +regression tests. + +The crc32 regression test in the e2fsck library is now portable to +greater varienty of environments, including big-endian systems and +when cross-building e2fsprogs for embedded systems. (Addresses +Sourceforge Bug: #2019287) + +The ext2fs_extent_set_bmap() had some bugs when setting the first +block in a file, or when replacing a single block extent. Those cases +fortunately were came up relatively rarely when e2fsck was checking +files, but caused some problems when resize2fs was shrinking +extent-based files. + +Fix a potential core-dumping bug in libe2p's iterate_on_dir() +function. + +Various ext2fs library functions --- ext2fs_block_iterate2(), +ext2fs_initialize() and ext2fs_extent_open() --- now correctly free +allocated memory to avoid memory leaks in all of their error return +paths. + +Ext2ed was failing to build because masix support had been removed in +the rest of e2fsprogs, so ext2ed no longer has masix support, either. + +The configure script now respects the LDFLAGS environment variable if +it is set when configure is called. (Addresses Sourceforge Feature +Request: #1937287) + +Libuuid is now more portable to the Windows platform. (Addresses +Sourceforge Feature Request: #1937287) + +The configure script now uses AC_MSG_{RESULT,WARN,ERROR} instead of +bare echo commands so that configure flags such as --quiet work +correctly. (Addresses Sourceforge Patches: #2058794) + +A few uses of sprintf have been removed from the ext2fs library to +make life easier for bootloaders with a limited libc environment. +(Addresses Sourceforge Bug: #2049120) + +The ext2fs_read_inode() checks the validity of the inode number passed +to it earlier, to avoid doing some needless work when it would fail +anyway. + +The ext2fs_open() checks the validity of the blocksize parameter +passed to it earlier, to avoid doing some needless work when it would +fail anyway. + +Disable a very annoying automatic "%.sh -> %" GNU make rule in the +top-level Makefile. That automatic rule is used to better support +SCCS, but it caused problems for a particular niche distribution which +likes to use configure.sh files to store the configure options used to +build a package. Unfortuntaely GNU make will use the configure.sh to +replace the configure script, resulting in a self-inflicted fork bomb +leading to an out-of-memory crash. + +To support old GNU C compilers don't use C99/C++ comments, but only +K&R style comments, and don't try to use __builtin_expect if __GNUC__ +is less than 3. (__builtin_expect is only supported for gcc versions +2.96 and up, and it's tricky to check for gcc 2.95 vs gcc 2.96; since +this is an optimization, we only try to use __builtin_expect for gcc 3 +and up.) + +In e2fsck's crc routines, make sure we use WORDS_BIGENDIAN instead of +__LITTLE_ENDIAN, which are only defined by glibc's header files and +hence isn't portable. + +For the convenience for some distributions that need a static tune2fs, +the Makefile for misc/ now has a tune2fs.static target. + +The ext2fs_block_iterate2() function now supports BLOCK_FLAG_APPEND +for extent-based files + +The ext2fs_bmap() function now supports BMAP_ALLOC for extent-based +files. + +All source files no longer have any trailing white space. + +The io_channel_read_blk64() and io_channel_write_blk64() functions are +now functions instead of C preprocessor macros to provide better +forward compatibility. + +The e2fpsrogs translation template now expands the @x abbrevation. + +Various namespace leackages in libblkid, libe2p, and libext2fs have +been fixed. + +Fix a parallel build problem in e2fsprogs. + +E2fsprogs is now more portable to Solaris. + * blkid no longer assumes that the TIOCGSIZE and TIOCGWINSZ ioctl's + are always present. + * Scripts do not assume that /bin/true is always in /bin + * Don't use __FUNCTION__ since Solaris's C99 doesn't support it. + * Flush stdio handles before calling setbuf(), since Solaris will + discard any pending output to the stream. + * Define _XOPEN_SOURCE to 600 since Solaris's header files are very + picky about which C compiler can beused for SUSv3 conformance. + Use of C99 is not compatible with SUSv2 (_XOPEN_SOURCE=500), + and C89 is not compatible with SUSv3 (_XOPEN_SOURCE=600). + Since we need some SUSv3 functions, consistently use SUSv3 so + that e2fsprogs will build on Solaris using c99. + * Solaris C99 does not support varargs C preprocessor macros + * Solaris header files pollute the C namespace if in/netinet.h + is included, which conflicts with e2fsprogs' use of the kmem_cache_t + typedef. + * Solaris ships with a pathetically ancient shell in /bin/sh so we + avoid the use of various more avanced shell constructs such as $(). + +The "make rpm" command will now take some extra configure optiosn from +the build environment without needing to patch the source tree. + +The ext2fs_add_dir_block() function will now grow the dblist more +aggressively as an optimization to avoid copying the array too often. + +The e2fsck_write_bitmaps() will write the block and inode bitmaps +together instead of in two passes. + + +E2fsprogs 1.41 (July 10, 2008) +============================== + +Add support for ext4 filesystem features, in particular extents, +uninit_bg, flex_bg, huge_file, and dir_nlink features. Also add +support for checking journal checksums. Debugfs will print new +superblock and inode fields that were defined for ext4. For example, +the nanosecond and i_version fields of an inode, and the +s_min_extra_isize and s_wanted_extra_isize fields from the superblock. +Note: Resize2fs doesn't currently support the combination of flex_bg +and !resize_inode. (Addresses Debian Bug: #388452, #425477) + +Tune2fs can support migrating a filesystem from using 128 byte inodes +to 256 byte inodes, so it can take advantage of the full features of +ext4. + +Add support for "undo" support. E2fsck and mke2fs can optionally +record an undo log which can replayed by the program e2undo. + +E2fsck could damage a filesystem by trying to relocate inode tables +due to corrupted block group descriptors, where the attempted inode +table relocation would do far more harm than good. E2fsck has been +fixed to detect this these sorts of corrupted block group descriptors +much earlier in e2fsck processing, so it can try to use the backup +superblock and block group descriptors first. This should be a much +better strategy for recovering these types of corrupted filesystems. +(Addresses Sourceforge Bug: #1840291) + +E2fsck will display a more understandable message when the last check +field in the superblock is in the future. (Addresses Debian Bug: +#446005). + +E2fsck now performs more extensive and careful checks of extended +attributes stored in the inode. + +Enhance mke2fs to print a more explanatory error message when +ext2fs_get_device_size() returns EFBIG. (Addresses Debian Bug: +#488663) + +Fix mke2fs to use a default block size of 4k when formatting an +external journal device. This is done by using a fixed filesystem +type list that consists only of the single filesystem type "journal" +when looking up configuration keys in /etc/mke2fs.conf. (Addresses +Debian Bug: #488663) + +Speed up how mke2fs writes the journal data blocks by writing the disk +blocks in larger chunks. + +Fix blkid handling of stale devices. Fix a bug which could cause a +core dump while garbage collecting the blkid cache, and assure that +blkid_find_dev_with_tag() never returns a non-existent device. Also, +if a filesystem is found at a new /dev location, eliminate any +duplicate stale entries which can not be verified. +(Addresses Debian Bugs: #487758, #487783) + +Add more paranoid checks for LVM volumes and swap partitions in +blkid's probe function, to reduce the chances of false positives. + +The mke2fs program now has a much more sophisticated system for +controlling configuration parameters of a newly created filesystem +based on a split filesystem and usage type system. The -t option to +mke2fs was a deprecated alias to -c; it now specifies a filesystem +type (ext2, ext3, ext4, etc.), while the -T option can now be a comma +separated usage list. The filesystem type information and type +information is used to extract configuration parameters from the +/etc/mke2fs.conf file. + +The mke2fs program will no longer complain and request the -f option +when the user tries to create a filesystem with greater than 2**31 +blocks. + +When creating a filesystem for the GNU Hurd use a fs-type of Hurd and +adjust the mke2fs.conf file so filesystems for the Hurd are created +with a blocksize of 4096 and inode size of 128, which is all it knows +how to handle. (Addresses Debian Bug: #471977) + +Mke2fs will always make sure that lost+found always has at least 2 +blocks, even for filesystems with very large blocksizes (i.e., 64kb). + +Resize2fs will now print the minimum needed filesystem size if given +the -P option, and will resize the filesystem to the smallest possible +size if given the -M option. + +Fix resize2fs to clean up the resize_inode if all of the reserved gdt +blocks are consumed during an off-line resize. + +The "ls" command in debugfs now supports the -p option, which causes +it to quote the filenames so that spaces or tabs in directory entries +are easily visible. (Addresses Red Hat Bugzilla: #149480; Addresses +Sourceforge Feature Request: #1201667) + +Fix a potential off-by-one buffer oveflow in the fs_device_name in an +e2image file. + +The chattr program will return a non-zero exit code in case of +failures, and error messages can be suppressed with the -f option. +(Addresses Red Hat Bugzilla: #180596) + +Fix a bug in badblocks which caused it to overrun an array and likely +crash if more than 8 test patterns are specified using the -t option. +(Addresses Debian Bug: #487298) + +Add support to badblocks to limit how quickly it reads from the disk +drive (so it can be used for background scrubbing), and so it will +abort after finding a given number of errors. + +Remove support for the legacy big-endian filesystem format which only +existed on extremely long-dead PowerPC kernels almost a decade ago. + +Remove MASIX support from e2fsprogs. + +Add I/O statistics reporting to e2fsck. + +Update Vietnamese, Polish, French, Spanish, German, Catalan, Dutch, +Czech translations. + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs: #487443, #487675, #490003) + +Fixed spelling mistakes, typos, and otherwise clarified man pages. +(Addresses Debian Bugs: #393313, #487849, #440983, #440981) + +Programmer's Notes +------------------ + +Factor out bitmap code in preparation for adding 64-bit new-style +bitmaps. + +Fix gcc -Wall warnings + +Fix the pkg-config files so that private librares are specified in +"Libs.private:". + +Fix the libext2fs.texinfo manual so it builds with modern versions of +texinfo. + +Silence the makefile from showing the awk command used to build the + +Clean up the badblocks group so to make it more portable and robust. + +Avoid using predictable filenames in /tmp in blkid's regression test +suite. Also remove bashism's in the regression test script. + +If the configure script is given --with-diet-libc, don't use thread +local storage, since diet libc doesn't support TLS. (Addresses +Sourceforge Bug: #2000654) + +Fix the blkid regression test suite to tolerate older versions of +mkswap that don't support the -U option. + +A few library routines have been converted to support 64-bit block +numbers; in particular, the I/O manager functions, the test_io, +inode_io, and unix_io managers have all be converted to support 64-bit +operation. + +Debugfs can now be extended for use by test programs. See +lib/ext2fs/extents.c for an example for how it can be used. The test +program links against the debugfs object files, and provides +additional commands by defining an auxiliary libss command table. + +The lazy_bg filesystem feature, which was only used by developer's +testing, has been removed since it has been largely supplanted by +uninit_bg. This also simplifies the code. + + +E2fsprogs 1.40.11 (June 17, 2008) +================================= + +Mke2fs, tune2fs, and resize2fs now use floating point to calculate the +percentage of reserved blocks. (Addresses Debian Bug: #452639) + +Updated Spanish and Catalan translations. + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs: #483962, #483023) + +Add detection for ZFS volumes to the libblkid library. + +Fixed spelling mistakes, typos, and otherwise clarified man pages. +(Addresses Debian Bug: #486463) + +Programmer's notes: +------------------- + +Fix marginal C code in probe_lvm2() function to the blkid library more +portable for older compilers. + +Fix build problems on MacOS X. (Addresses Sourceforge Bug: #1972473) + +Fix ext2fs_swap{16,32,64} functions so they can be used by external +applications on big-endian machines. (Addresses Debian Bug: #484879) + + +E2fsprogs 1.40.10 (May 21, 2008) +================================ + +When deciding whether or not to revalidate a blkid cache entry, if the +device's mtime is newer than the last time the cached entry was +validated, force a revalidation. + +Fix a potential data corruption bug in e2fsck in the journal replay. +The chances of this is happening is extremely remote, especially the +default data=ordered or data=writeback modes. However, if a block +which has been journalled starts with the first four bytes 0xc03b3998, +when e2fsck replays the journal, those four bytes will be replaced +with zero's. Fortunately, it is highly, highly unlikely for e2fsck +metadata to begin with those fatal 4 byte sequence, and unless +data=ordered mode is in use, data blocks are never journaled. + +Updated German, Dutch, Sweedish, and Vietnamese translations. + +Programmer's notes: +------------------- + +Fixed various Debian packaging issues --- see debian/changelog for +details. + +Remove default sizes of types when cross compiling, since autoconf +2.50 can figure this out automatically now. + + +E2fsprogs 1.40.9 (April 27, 2008) +================================= + +SuSE's security team audited uuidd and came up with a few minor +issues. None of them are serious given that uuidd runs setuid as a +unprivileged user which has no special access other than libuuid +directory, but it's good to get them fixed. + +One additional fix in ext2fs_swap_inode_full() needed for resize2fs to +work correctly with in-inode extended attributes. + +Updated German, Czech, Dutch, French, Polish, Sweedish, and Vietnamese +translations. + +Debugfs will avoid using a pager if the standard output is not a tty. + +Fix debugfs and tune2fs to correctly handle daylight savings time when +parsing a time string. + +Fixed spelling mistakes, typos, and otherwise clarified man pages. + +Fix fsck completion bars when multiple filesystems were being checked +in parallel. (Addresses Debian Bug: #432865, Addresses Launchpad Bug: +#203323, Addresses Sourceforge Bug: #1926023) + +Fix fsck so that progress information is sent back correctly when +multiple filesystems are being check and the output of fsck is being +redirected to a file descriptor. Also, include the device name (w/o +spaces) in the progress information sent back via a file descriptor. +(Addresses Launchpad Bug: #203323, Addresses Sourceforge Bug: +#1926023) + +Teach fsck to treat "ext4" and "ext4dev" as ext* filesystems. + +If logsave receives a SIGTERM or SIGINT signal, it will now pass that +signal to its child process. + +Fix mke2fs's creation of are resize inode when there is a non-standard +s_first_data_block setting. + +Fix bug in blkid when run by an unprivileged user; most devices were +not reported correctly. 9Addresses Launchpad Bug: #220275) + +Mke2fs will not allow the logically incorect combination of +resize_inode and meta_bg, which had previously caused mke2fs to create +a corrupt fileystem. + +Fix fsck in German locales so that a 'j' means yes. +(Addresses Sourceforge Bug: #1947683) + + +Programmer's notes: +------------------- + +Fixed various Debian packaging issues --- see debian/changelog for +details. + +Update valgrind options in test_script to work with valgrind 3.2.3 + +Update texinfo.tex to a much newer version from the FSF. + +Remove bashism for configure script and from the lib/ss Makefile. +Addresses Sourceforge Bug: 1921969 + +Fix some silently broken tests: m_no_opt, m_meta_bg, and m_raid_opt. + +Fix build system so that if texinfo is not installed, it won't print a +(harmless) error message. + + +E2fsprogs 1.40.8 (March 13, 2008) +================================= + +Fixed e2image -I so it works on image files which are larger than 2GB. + +Fixed e2fsck's handling of directory inodes with a corrupt size field. If +the size is larger than the number of blocks found in the inode, don't +try to allocate extra empty blocks at the end of the directory to make +up the difference; there's no point to doing that. In addition, if +the size is not a multiple of a blocksize, always fix it. + +E2fsck handled a pass 2 "should never happen error" by not giving +enough information and then core dumping. Unfortunately, it was all +too easy to trigger the "should never happen" situation if a +directory's inode size was not correct. This has been fixed, but +e2fsck has also been taught how to handle this situation more +gracefully, by simply removing the inode hash tree information, so +that it can be rebuilt again after e2fsck's pass 3. (Addresses +Launchpad Bug: #129395) + +Resize2fs had a bug resizing large inodes with extended attributes +that was fixed in 1.40.6; unfortunately, it turned out it wasn't fixed +completely on big-endian systems such as PowerPC. The bug should be +completely fixed now. Yay for regression test suites. (Addresses Red +Hat Bugzilla: #434893) + +Updated German, Czech, Dutch, Polish, Sweedish, and Vietnamese +translations. Many thanks to Philipp Thomas from Novell for stepping +up to become the new German translation maintainer! (Addresses Debian +Bugs: #302512, #370247, #401092, #412882). + +When e2fsck is clearing a corrupt inode's HTREE directory information, +make it clear that it is just clearing the HTREE information, not the +entire inode. + +Fixed spelling mistakes, typos, and otherwise clarified man pages. + +Programmer's notes +------------------ + +Add new functions, ext2fs_dblist_get_last() and +ext2fs_dblist_drop_last(), which allows the caller to examine the last +directory block entry added to the list, and to drop if it necessary. + +Fixed a portability problem in libblkid with DJGPP. + +Fix an obvious typo in an "internal error" message in e2fsck. Thanks +to Philipp Thomas for pointing this out. + +If the info files are not built, change "make install" so it doesn't +fail with an error code. + + +E2fsprogs 1.40.7 (February 28, 2008) +==================================== + +Remove support for clearing the SPARSE_SUPER feature from tune2fs, and +depreciate the -s option, since it can result in filesystems which +e2fsck can't fix easily. There are very good reasons for wanting to +disable sparse_super; users who wants to turn off sparse_super can use +debugfs. (Addresses Sourceforge Bug: #1840286) + +Add missing options to mke2fs's usage message. (Addresses Sourceforge +Bug: #1751393) + +Fix bug in resize2fs when large (greater than 128 byte) inodes are +moved when a filesystem is shrunk; it was only moving the first 128 +bytes, so extended attributes were not getting moved. (Addresses Red +Hat Bugzilla: #434893) + +E2fsck now prints an explicit message when the bad block inode is +updated, to avoid confusion about why the filesystem was modified. +(Addresses Sourceforge Bug: #756460) + +Allow mke2fs and tune2fs manipulate the large_file feature. +Previously we just let the kernel and e2fsck do this automatically, +but e2fsck will no longer automatically clear the large_file feature. +It still isn't really necessary to worry about this feature flag +explicitly, but some users seem to care. (Addresses Red Hat Bugzilla: +#258381) + +Suppress message about an old-style fstab if the fstab file is empty. +(Addresses Debian Bug: #468176) + +Fix (really minor) bug in debugfs's find_free_block so it avoids +reporting a free block more than once if there are too few free blocks +in the filesystem. (Addresses Sourceforge Bug: #1096315) + +Change e2fsck to no longer clear the LARGE_FILES feature flag +automatically, when there are no more > 2GB files in the filesystem. +It's been almost a decade since there have been kernels that don't +support this flag, and e2fsck clears it quietly without telling the +user why the filesystem has been changed. + +Fix bug which could cause libblkid to seg fault if a device mapper +volume disappears while it is being probed. (Addresses RedHat +Bugzilla: #433857) + +Inhance e2fsck's reporting of unsupported filesystem feature flags. +(Addresses Sourceforge Feature Request: #1175808) + +Fix option syntax in dumpe2fs for explicit superblock and blocksize +parameters. What was currently documented in the man page has been +broken for some time, due to getopt() implementation changes. The +option sytax has been changed to one which is can be more portable +supported and which is consistent with the format for extended options +in mke2fs and tune2fs. (Addresses Sourceforge Bug: #1830994) + +Add support to tune2fs to clear the resize_inode feature. This +requires an fsck afterwards. (Addresses Red Hat Bugzilla: #167816) + +Teach blkid to detect LVM2 physical volumes. (Addresses Red Hat +Bugzilla: #409321) + +Add support for setting RAID stride and stripe-width via mke2fs and +tune2fs. Teach dumpe2fs to print the RAID parameters. + +Add support for setting new superblock fields to debugfs's +set_super_value. + +Add support for printing "mostly-printable" extended attributes in +Debugfs. + +Add support for the -M option to fsck, which causes it to ignore +mounted filesystem. + +Fix uuidd so that it creates the pid file with the correct pid number. +(Addresses Sourceforge Bug: #1893244) + +Fix various gcc -Wall warnings. + +Update Czech, Dutch, Polish, Sweedish, and Vietnamese translations + +Fixed spelling mistakes, typos, and otherwise clarified man pages. +(Addresses Sourceforge Patch: #1399325) + + +Programmer's notes: +------------------- + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bug: #466929) + +Add new flag EXT2_FLAG_NONFREE_ON_ERROR ext2fs_open2() which returns a +partially filled-in filesystem object on an error, so that e2fsck can +print more intelligent error messages. + +Add a new function e2p_edit_feature2() which allows the caller to +specify which feature flags are OK to set or clear, and which returns +more specific information about feature flags which are not allowed to +be set/cleared. + +Set the C locale in the test_script driver since it uses [A-Za-z]. +(Addresses Sourceforge Bug: #1890526) + +Use fcntl locking instead of lockf in libuuid since Cygwin doesn't +support lockf(). + +Change configure.in to avoid using the 'dc' command unless it is +absolutely needed. (i.e., when using parsing a WIP-style version +number) (Addresses Sourceforge Bug: #1893024) + +Add portability checks to support compilation under DJGPP. + +Update to the latest samba tdb code before the LGPLv3 change, which +fixes a realloc() leak on failure. + +Fix memory leak in ext2fs_alloc_block(). + +Fix makefile dependency issues for various install targets. +(Addresses-Sourceforge-Patches: #1903484, #1903466, #1903456) + +Improve descriptions for the r_move_itable and r_resize_inode tests. + + +E2fsprogs 1.40.6 (February 9, 2008) +=================================== + +Add support for returning labels for UDF filesystems in the blkid +library. + +Fix bug in the blkid library where cached filesystems was not being +flushed when opening USB devices returned the error ENOMEDIUM. +(Addresses Debian Bug: #463787) + +Added logic to the blkid library to automatically choose whether a +filesystem should be mounted as ext4 or ext4dev, as appropriate. + +Allow tune2fs to set and clear the test_fs flag on ext4 filesystems. + +Fix a bug in e2fsck which caused it to core dump if e2fsprogs had been +configured with --enable-jbd-debug. + +Document the BLKID_FILE environment variable in the libblkid man page + +Programmer's Notes: +------------------- + +Update e2fsprogs translation template and Vietnamese and Czech translations + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs: #436058) + +Don't try to create $DESTDIR/etc/init.d as part of make install as we +don't install the init.d script (and it's not the recommended way to +start uuidd anyway). (Addresses Sourceforge Bug: #1885085) + +Use thread local storage to fix a theoretical race condition if two +threads try to format an unknown error code at the same time in the +com_err library. + + +E2fsprogs 1.40.5 (January 27, 2008) +=================================== + +Fix a potential overflow big in e2image if the device name is too +long. + +Mke2fs will now create new filesystems with 256 byte inodes and the +ext_attr feature flag by default. This allows for much better future +compatibity with ext4 and speeds up extended attributes even on ext3 +filesystems. + +Teach e2fsck to ignore certain "safe" filesystem features which are +set automatically by the kernel. Having the kernel set features +automagically behind the user's back is a bad idea, and we should try +to break the kernel of this habit, especially for the newer ext4 +feature flags. But for now, we will try to avoid needless full checks +which can annoy users who are doing fresh installs. + +Add support in tune2fs and mke2fs for making a filesystem as being "ok +to be used with test kernel code". This will be needed for using test +filesystems with the latest ext4 kernel code. + +Change e2fsck -fD so that it sorts non-htree directories by inode +numbers instead of by name, since that optimizes performances much +more significantly. (Addresses-Sourceforge-Feature-Request: #532439) + +If e2image fills the disk, fix it so it exits right away instead of +spewing large numbers of error messages. +(Addresses-Sourceforge-Feature-Request: #606508) + +If ftruncate64() is not available for resize2fs, let it use ftrucate() +instead, but have it check to see if the size would get truncated, and +skip calling ftruncate in that case. + +Add support for detecting HFS+ filesystems in the blkid library. + +Add supprt in the blkid library for ext4/ext4dev filesystems. + +Fix a bug in blkid where it could die on a floating point exception +when presented with a corrupt reiserfs image. + +Fix blkid's handling of ntfs UUID's so that leading zeros are printed +such that UUID string is a fixed length. + +Add sample python bindings for the uuid library to the contrib +directory. (Addresses-Sourceforge-Patches: #778817) + +Fix debugfs's 'lsdel' command so it uses ext2fs_block_iterate2 so it +will work with large files. (Addresses Sourceforge Feature Request: +#1257500 and Sourceforge Support Request: #1253511) + +Allow the debugfs 'undel' command to undelete an inode without linking +it to a specific destination directory, since this might require +allocating blocks that could overwrite some yet-to-be-recovered +deleted files. (Addresses-Sourceforge-Feature-Request: #967141) + +Update Swedish translations from the Translation Project. + +Programmer's Notes: +------------------- + +Fix configure handling of --sbindir (which should rarely be used, but +someone did complain, so let's fix it). (Addresses Sourceforge Bug: +#498381) + +Updated e2fsprogs.spec file to include a new uuidd package + +Use pkg-config to determine where to find the devmapper library so we +can find out where it is located on different distributions. + +Fix Makefile race so that "make -j3 distclean" works correctly + +Fix portability problems on non-Linux/non-Hurd/non-Masix systems, +especially on MacOS X systems. (Addresses Sourceforge Bugs: #1861633, +#1819034, #1863819) + +Fixed spelling mistakes, typos, and otherwise clarified man pages. + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs: #459403, #459475, #459614) + +Remove the --enable-dynamic-static configure option, and build e2fsck +dynamically by default. If the user wants e2fsck.static, he/she will +need to build it via "make -C e2fsck e2fsck.static" + +Fix various build warnings due to missing prototypes. +(Addresses Sourceforge Patch: #1861663, #1861659) + + +E2fsprogs 1.40.4 (December 31, 2007) +==================================== + +Improve time-based UUID generation. A new daemon uuidd, is started +automatically by libuuid if necessary. This daemon is setuid to allow +updates to /var/lib/libuuid, so the clock sequence number can be +stored and so if the clock is set backwards, it can be detected. +(Addresses Sourceforge Bug: #1529672, Addresses Red Hat Bugzilla: +#233471) + +Filter out the NEEDS_RECOVERY feature flag when writing out the backup +superblocks. This avoids e2fsck from concluding that a full +filesystem check is required before backing up the superblock due to +changes in the feature flags. (Addresses Debian Bug: #454926) + +Fix fsck to only treat the '#' character as a comment at the beginning +of the line in /etc/fstab. Otherwise fstabs for the fuse filesystem +will cause fsck to issue an bogus warning message. +(Addresses Gentoo bug: #195405, Addresses Sourceforge bug: #1826147) + +Format control characters and characters with the high eighth bit set +when printing the contents of the blkid cache, to prevent filesystems +with garbage labels from sending escape sequences to the user's screen +that might, for example place it in graphics mode. (Addresses Ubuntu +Bug: #78087) + +Fix sign-extension problem on 64-bit systems in in the com_err +library. (Addresses Sourceforge Bug: #1809658) + +Avoid division by zero error when probing an invalid FAT filesystem in +the blkid library. (Addresses Sourceforge Bug: #1831627) + +Update Dutch, Polish, and Vietnamese translations from the Translation +Project. Remove the Rwandan translation upon advice of the +Translation Project. + +Programmer's Notes: +------------------- + +Fix the libss "make check" regression test so that it works if the +current directory is not in the user's path or if the libss shared +library is not installed. (Addresses Sourceforge Bug: #1848974) + +Fixed spelling mistakes, typos, and otherwise clarified man pages. +(Addresses Debian Bugs: #444883, #441872) + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs: #437720, #451172, #458017) + +Fix build failure on non-Linux/non-Hurd/non-Masix systems. +(Addresses Sourceforge Bug: #1859778) + +Fix Hurd portability issues. (Addresses Debian Bug: #437720) + + +E2fsprogs 1.40.3 (December 5, 2007) +=================================== + +Fix a potential security vulnerability where an untrusted filesystem +can be corrupted in such a way that a program using libext2fs will +allocate a buffer which is far too small. This can lead to either a +crash or potentially a heap-based buffer overflow crash. No known +exploits exist, but main concern is where an untrusted user who +possesses privileged access in a guest Xen environment could corrupt a +filesystem which is then accessed by the pygrub program, running as +root in the dom0 host environment, thus allowing the untrusted user to +gain privileged access in the host OS. Thanks to the McAfee AVERT +Research group for reporting this issue. (Addresses CVE-2007-5497.) + +Fix hueristics in blkid which could cause a disk without partitions to +be incorrectly skipped when a loopback device is present. (Addresses +Red Hat Bugzilla #400321.) + +Fix e2image so that in raw mode it does not create an image file which +is one byte too large. + +Change mke2fs's usage message so it recommends the preferred -E option +instead of the deprecated -R option. + +Enhance the blkid library so it will recognize squashfs filesystems. +(Addresses Red Hat Bugzilla #305151.) + +Enhance e2fsck so it will force the backup superblocks to be backed up +if the filesystem is consistent and key constants have been changed +(i.e., by an on-line resize) or by e2fsck in the course of its +operations. + +Enhance blkid's detection of FAT filesystems; so that USB disks with +only a single bootable partition will not get missed. + +E2fsck will no longer mark a filesystem as invalid if it has time +errors (i.e., if superblock mount time or last write time is in the +future) and the user refuses to fix the problem. + +The Ubuntu init scripts don't properly set the system time correctly +from hardware clock if the hardware clock is configured to tick local +time instead of GMT time. Work around this as best as we can by +providing an option, buggy_init_scripts, in /etc/e2fsck.conf which can +be set on Ubuntu systems. (Addresses Debian Bug #441093, and Ubuntu +Bug #131201.) + +Fix fsck to ignore /etc/fstab entries for bind mounts. (Addresses Red +Hat Bugzilla #151533.) + +Fix e2fsck so that if the superblock is corrupt, but still looks +vaguely like an ext2/3/4 superblock, that it automatically tries to +fall back to the backup superblock, instead of failing with a hard +error. + +Make the e2fsprogs program more robust so that they will not crash +when opening a corrupt filesystem where s_inode_size is zero. + +Change e2fsck so it uses sscanf() instead of atoi() so it non-numeric +arguments are detected as such and the parse error is reported to the +user. (Addresses Debian Bug #435381.) + +Change e2fsck so it will not complain if a file has blocks reallocated +up to the next multiple of a system's page size. + +Fix bug in ext2fs_check_desc() which will cause e2fsck to complain +about (valid) filesystems where the inode table extends to the last +block of the block group. (Addresses Red Hat Bugzilla #214765.) + +Fix a bug in ext2fs_initialize() which causes mke2fs to fail while +allocating inode tables for some relatively rare odd disk sizes. +(Addresses Red Hat Bugzilla #241767.) + +Add Catalan translation and update Dutch and Swedish translations +from the Translation Project. + +Fix big-endian byte-swapping bug in ext2fs_swap_inode_full(). We +still had an issue when trying to figure out whether we need to +byte-swap fast symlinks that contained extended attributes. + +Fixed spelling mistakes, typos, and otherwise clarified man pages. +(Addresses SourceForge Bug #1821333.) + + +Programmer's Notes: +------------------- + +Fix mke2fs tests to avoid needing any significant ^M (CR) characters + +Add "make check" to the RPM spec file + +Fix "make install" and 'make unstall" in misc/Makefile.in so that it +works correctly when the prefix is not the root directory. + +Fix the resize2fs tests, r_move_itable and r_resize_inode, so they +clena up after themselves by deleting the test.img temporary file +after completing the test. + +Fixed a corner case bug ext2fs_unlink() when trying to delete the +first directory entry in a directory block and the last directory +entry in the previous directory block is not in use. Fortunately +ext2fs_unlink() is only used by debugfs and e2fsck, and in e2fsck in +places where it is extremely unlikely to run into this corner case. + +Fix missing dependency which would cuase parallel builds to fail. +(Addresses Sourceforge Bug #1842331.) + +Fix a build error on newer gcc caused by lib/ext2fs/ismounted.c +calling open(O_CREATE) with a missing mode parameter. + +Fix the test_ss.c in lib/ss so it can be used as an example +application program for the library as well as a regression test +suite. + +Fix ext2fs_dblist_dir_iterate() so that error codes and abort codes +are properly passed back up through the call stack. + +E2fsprogs 1.40.2 (July 12, 2007) +================================ + +A recent change to e2fsck_add_dir_info() to use tdb files to check +filesystems with a very large number of filesystems had a typo which +caused us to resize the wrong data structure. This would cause a +array overrun leading to malloc pointer corruptions and segfaults. +Since we normally can very accurately predict how big the the dirinfo +array needs to be, this bug only got triggered on very badly corrupted +filesystems. + +Fix a bug in e2fsck which caused it to incorrectly salvange +directories when the last entry's rec_len is bogusly too big. This +resulted in a nonsense filesystem corruption to be reported, and +required a second run of e2fsck to fully fix up the directory. + +Update tune2fs man page to include more discussion of reserved blocks +(Addresses Launchpad bug #47817) + +Update Turkish, Polish, Dutch, and Vietnamese PO files from the +Translation Project + + +E2fsprogs 1.40.1 (July 7, 2007) +=============================== + +Fix bug which could cause libblkid to loop forever. When revalidating +a partition where there is obsolete information in /etc/blkid.tab, we +end up freeing a the type tag without clearing dev->bid_type, causing +blkid_verify() to loop forever. (Addresses Debian Bug: #432052) + +The Turkish translation has a bug in it where it has the translation +of "E@e '%Dn' in %p (%i)" to "E@E". This causes @E to be expanded at +@E, recursively, forever, until the stack fills up and e2fsck core +dumps. We fix this by making e2fsck stop @-expansions after a +recursive depth of 10, which is far more than we need. +(Addresses Sourceforge Bug: #1646081) + +Compile the default mke2fs.conf into mke2fs program. People are +getting surprised by mke2fs creating filesystems with different +defaults than earlier versions of mke2fs if mke2fs.conf is not +present. So we now create a built in version of mke2fs.conf file +which is used by mke2fs if the /etc/mke2fs.conf is not present. +(Addresses SourceforgeBug: #1745818) + +Improve the config/parse_types.sh helper script. Fix a potential +security problem if e2fsprogs is built as root (as Gentoo does!). In +addition fix the script and how it is called from the configure script +so that it does the right thing when cross-compiling. (Fixes Gentoo +bug: #146903) + +Update Vietnamese, French, and Dutch PO files from the Translation +Project. Also created a new e2fsprogs.pot file for translator. + +Fix bogus strip permission errors when building under Debian. When +building the e2fsprogs dpkg's, the dh_strip command emits a large +number of error messages caused by the permissions not being right. +So run dh_fixperms before running dh_strip. + +Programmer's Notes: +------------------- + +Add new function: profile_set_default(). This function sets the value +of the pseudo file "<default>". If the file "<default>" had +previously been passed to profile_init(), then def_string parameter +will be parsed and used as the profile information for the "<default>" +file. + +Fix mk_cmds's error reporting so that it is unambiguous that it is the +mk_cmds script which is generating the error. (Obviates Gentoo patch: +e2fsprogs-1.32-mk_cmds-cosmetic.patch) + +Fix the test suite to use LC_ALL instead of LANG. LC_ALL is the "high +priority" environment variable that overrides all others, where as +LANG is the lowest priorty environment variable. If LC_ALL is set, it +doesn't matter whether LANG, LANGUAGE, LC_COLLATE, LC_MESSAGES, and +the all the rest are set. This will assure that the locale when +running the test suites is the "C" locale. (Obviates Gentoo patch: +e2fsprogs-1.38-tests-locale.patch) + + +E2fsprogs 1.40 (June 29, 2007) +============================== + +Fix divide by zero error in blkid's NTFS probing logic. + +Add new blkid -g option which causes the blkid cache to be garbage +collected. + +Fix a bug in libblkid which could cause the internal field bid_type to +become corrupted. Fortunately bid_type isn't used much, and bid_label +and bid_uuid is only used by debugging code, so the impact of this bug +was very minor. + +Mke2fs will now store the RAID stride value when a filesystem is +created with a requested RAID stride, and then use it automatically in +resize2fs. + +Mke2fs has a sanity check added to make sure (inode_size * num_inodes) +isn't too big. In some cases Lustre users have tried specifying an +inode size of 4096 bytes, while keeping an inode ratio of one inode +per 4096 bytes. + +Improve sanity check in e2fsck's algorithm for finding a backup +superblock, so that it won't accidentally find a superblock that was +located in the journal, and then later reject it as being not a valid +backup superblock. + +Fix e2fsck get_size logic so that it will work with the Linux floppy +driver. The Linux floppy driver is a bit different from the other +block device drivers, in that if the device has been opened with +O_EXCL, it disallows another open(), even if the second open() does +not have the O_EXCL flag. (Addresses Debian Bug: #410569) + +Fix error checking of badblock's last-block and start-block arguments. +(Addresses Debian Bug: #416477) + +Fix e2fsck so that it doesn't overwrite the backup superblocks when +recovering a journal until the master superblock has been confirmed as +being sane. + +Change the blkid library to be much more paranoid about concluding +that a partition contains an NTFS filesystem, and fetch the UUID and +LABEL information from NTFS filesystems. (Addresses Launchpad Bug: +#110138) + +Factor out the code which sets the default journal size and move it +into libext2fs. + +Enhance e2fsck so it will recreate the ext3 journal if the original +journal inode was cleared to due it being corrupt after finishing the +filesystem check. + +Fix e2fsck so that it updates the journal inode if it is corrupted and +the backup journal information from the superblock was successfully +used to recover the filesystem. + +Fix e2fsck so that it checks all of the blocks in the journal inode +for validity. The original code only checked the direct blocks to +make sure the journal inode was sane. Unfortunately, if some or all +of the indirect or doubly indirect blocks were corrupted, this would +not be caught. + +Add support in blkid to detect LUKS encrypted partitions. + +Add extra sanity checks for extended attributes in the case where the +size is zero but the offset is very large. + +Fix byte-swapping issues for large inodes in ext2fs_read_inode_full() +and ext2fs_get_next_inode_full(). + +Clarify the copyright licenses used by the various libraries in +the top-level COPYING file (Red Hat Bugzilla: 166058) + +Make mke2fs's defaults when /etc/mke2fs.conf doesn't exist more sane. + +Fix mke2fs and debugfs to support large (> 16 bit) uid's and gid's. + +Remove check in e2fsck which requires EA's in inodes to be sorted; +they don't need to be sorted, and e2fsck was previously wrongly +clearing unsorted EA's stored in the inode structure. + +Allow mke2fs or tune2fs to create a substantially larger journal (up +to 10,240,000 blocks). + +Fix MD superblock detection, and make sure the correct UUID is +reported from the MD superblock. + +Fix a signed vs. unsigned bug in debugfs. + +Enhance debugfs's date parser so that it accepts integer values. + +Fix e2fsck's pass1c accounting so it doesn't terminate too early if a +file with multiply claimed blocks is hard linked. or not at all if the +root directory contains shared blocks + +Enhance debugfs so it can modify the block group descriptors using the +command set_block_group_descriptor. + +Improve e2fsck's reporting of I/O errors so it's clearer what it was +trying to do when an error happens + +Fix a bug in in how e2fsprogs byte swaps inodes containing fast +symlinks that have extended attributes. (Addresses Red Hat Bugzilla: +#232663 and LTC Bugzilla: #27634) + +Fix potential file descriptor leak in ext2fs_get_device_size() in an +error case. + +Add libreadline.so.5 support to libss. + +Impove badblocks -n/-w exclusive usage message. + +Fix dump_unused segfault in debugfs when a filesystem is not open + +Fix memory leak in blkid library. (Addresses Debian Bug: #413661) + +Allow the debugfs lcd command to work w/o a filesystem being open. +(Addresses LTC Bugzilla #27513) + +Fix e2fsck to clear i_size for special devices with a bogus i_blocks +field on the first pass. + +Fix e2fsck to set the file type of the '..' entry when connecting +a directory to lost+found. (Addresses Lustre Bug: #11645) + +Enhance e2fsck to recover directories whose modes field were corrupted +to look like special files. This is probably only useful in +artificial test cases, but it will be useful if we ever do the "inodes +in directory" idea for ext4. + +Allow debugfs to dump (and rdump) > 2GB files. (Addresses Debian Bug: +#412614) + +Fix resize2fs parsing of size parameter (in sector units). This was +actually a bug in libe2p's parse_num_blocks() function. When handling +the 's' suffix, it was ignoring the blocksize information passed in +from the caller and always interpreting the number in terms of a 1k +blocksize. (Addresses Debian Bug: #408298) + +There was a floating point precision error which could cause e2fsck to +loop forever on really big filesystems with a large inode count. +(Addresses Debian Bug: #411838) + +Fix memory leak in ext2fs_write_new_inode() + +Add support for using a scratch files directory to reduce e2fsck's +memory utilization on really big filesystems. This uses the TDB +library. See the [scratch_files] section of the e2fsck.conf man page +for more details. + +Fixed type-punning bug which caused dumpe2fs to crash on the Arm +platform (Addresses Debian Bug: #397044) + +Add explanatory message to badblocks that -n and -w are mutually exclusive +(Addresses Debian Bug: #371869) + +Allow debugfs and dumpe2fs to support fs features under development. + +Add support for the new flag EXT2_FLAG_SOFTSUPP_FEATURES flag to +ext2fs_open() , which allows application to open filesystes with features +which are currently only partially supported by e2fsprogs. + +Allow unix_io to support offsets greater than 2G (Addresses +SourceForge Bug: #1547922) + +Fixed overflow and signed/unsigned problems caused by the number of +blocks or inodes exceeding 2**31 or being close to 2**32-1. + +Add support for unsigned directory hash calculations with hints in the +superblock to fix cross-architectural portability for htree +directories with filenames where the high 8th bit is set. (Addresses +Debian: #389772) + +Fix resize2fs so that it gives user-intelligible error messages if the +filesystem or the kernel does not support on-line resizing. +(Addresses Debian Bug: #380548) + +Require mke2fs -F -F for really dangerous operations, since -F is +needed for less dangerous operations such as creating filesystems +images in regular files, or creating filesystems on whole block +devices. These relatively innocuous usages should NOT be confused +with running mke2fs on an apparently-mounted or in-use filesystem. + +Allow the default inode size to be specified into the mke2fs.conf +file. + +Make the smallest default journal size is big enough so that on-line +resizing should always work. + +Fix silly spelling error in e2fsck. (Addresses SourceForge bug: +#1531372) + +Fix debugfs coredump when lsdel is run without an open filesystem +(Addresses Debian Bug: #378335) + +Fix debugfs display bug us that bytes that have the high bit set are +displayed as "ec" instead of "ffffffec". + +Add support in lsattr so it will display the EXT4_EXTENTS_FL flag. + +Device mapper scanning wasn't working in the blkid library because the +pathnames had an extra "/dev" when they were being probed. + +Add GFS/GFS2 support to the blkid library. + +Fix blkid support of empty FAT filesystem labels. + +Avoid recursing forever (or for a long time) when the blkid library +searches for a device and there are symlinks to directories in /dev. + +Avoid unaligned halfword access in blkid when accessing FAT +superblocks, as this will cause Sparc/Solaris systems to throw a +SIGBUS error. + +The latest devmapper libraries requires pthreads, add -lpthreads to +the static link libraries for e2fsck.static if devmapper is enabled. +(Addresses Debian bug: #388718) + +Improve the (non-installed, for experts only) findsuper program by +printing the uuid and label from the superblocks, as well as the +starting and ending offsets of the filesystem given the information in +the superblock. Omit by default printing superblocks that are likely +found in located in an ext3 journal unless an explicit -j option is +given. + +Updated Spanish, French and Dutch translations and added Catalan +translation. (Addresses Debian bug: #411562) + +Use FreeBSD's DIOCGMEDIASIZE and DIOCGDINFO ioctls if available when +determining a partition's size, since binary searching to determine +the device doesn't work on FreeBSD. + +Documentation about UUID's is available in enough places, and it's +awkward to deal with debian-legal's insanities. So I'm caving in the +"more-lunatic-than-RMS" wing of Debian by removing RFC-4122 so we +don't have do the dfsg tarball. Also remove the rule that only tried +to install RFC-4122 on Ubuntu, since Ubuntu seems to want to fetch +e2fsprogs exclusively from Debian. (Addresses Debian Bug: #407107) + +Fix the info-dir line so that the menu name does not contain a .info +prefix. First of all, it's ugly, secondly, it causes the install-info +command to fail to remove the com_err info file from the +/usr/share/info/dir file when the comerr-dev package is removed and +purged. (Addresses Debian Bug: #401711) + +Fixed spelling mistakes, typos, and otherwise clarified man pages. +(Addresses Debian Bug: #369761, #373004, #379695) + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs #389554, #390664, #413208, #419605, +#408352, #415560, #399155) + + +Programmer's notes: +------------------- + +E2fsck now supports the %It expansion when printing a problem report. +It will print the type of the inode in the problem context. + +Fix misc/Makefile.in so that it builds even if e2fsck hasn't been built yet +(Addresses Sourceforge Bug: #1565561) + +Remove unused variables and other lint/gcc -Wall cleanups + +Add check to ext2fs_get_device_size() so it will return EFBIG for for +filesystems contained in regular files where the filesystem image size +is returned by stat64(). + +Set local environment variables to C so mk_cmds and compile_et always +work. (Addresses SourceForge Bug: #1532177) + +Added the 64-bit byte swapping function ext2fs_swab64(). + +Added two new helper functions to prevent 2**31/2**32-1 overflow +problems: ext2fs_div_ceil() and e2p_percent(). + +Create new ext2fs library inline functions ext2fs_group_first_block() +and ext2fs_group_last_block() in order to calculate the starting and +ending blocks in a block group. + +Create the generated files read-only to remind developers not to edit them. + +Add support for autoconf 2.60 (with backwards compatibility for older +versions of autoconf). + +Added an "make rpm" target to top-level Makefile + +Added various FreeBSD portability fixes. + +Exclude mercurial files from the RPM build tree to speed up copy/build. + +Use root_sysconfdir to define the locations of mke2fs.conf and +e2fsck.conf instead of using a hard-coded /etc pathname. + +Prevent e2fsck.h and ext2_ext_attr.h from getting included multiple times. + +Fixed "make clean" in blkid's Makefile.in file from removing tst_*.c files. + +If diff -u is supported, use it to report test failures. + +Updates/improvements to RPM spec file + +Add on-disk format definitions for the following new features: +EXT4_FEATURE_RO_COMPAT_HUGE_FILE, EXT4_FEATURE_RO_COMPAT_GDT_CSUM, +EXT4_FEATURE_RO_COMPAT_DIR_NLINK, EXT4_FEATURE_INCOMPAT_64BIT, +EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE + +Add a new make target "checked-failed" in the tests directory which +reruns any failed tests + +Update draft-leach-uuids-guids-01.txt with rfc4122.txt + +Fix miscellaneous bugs reported by Coverity: Dead code, potential nul +pointer dereferences, memory leaks, etc. None were security-criticial +problems. + +Fix up usage and decrement error messages in the test_icount program + +Add debugging code to the com_err library; if the environment variable +COMERR_DEBUG is set to 1, print out debugging messages as error tables +are added and removed from the com_err library. If the +COMERR_DEBUG_FILE environment variable is set (and the process is not +setuid) the debugging messages may be redirected to a file. + +Change all of the e2fsprogs programs to use the newer add_error_table() +and remove_error_table() interfaces instead of the much older +initialize_*_error_table() function. + +Add TDB support into the ext2fs library. This allows us to have a +guaranteed library we can count on always being present so we can +store data in an on-disk database. + +Add support for using TDB to store the icount data, so we don't run out +of memory when checking really large filesystems. + +Change the regression test suite so that it skips empty test directories. + +Define the l_i_iversion field in ext2_inode. The l_i_version field is +now defined from the old l_i_reserved1 field in the ext2 inode. This +field will be used to store high 32 bits of the 64-bit inode version +number. + +Add Makefile production rule for e2fsprogs.spec in case it gets +deleted. + +Add new function profile_get_uint() to allow for a clean way to fetch +unsigned integers from the context. + +Add test to make sure the ext2 superblock structure is 1024 bytes. + +Fix typo in name of f_dup4 regression test + +Add new function blkid_gc_cache() which performs a garbage collection +pass on the /etc/blkid.tab file. + +The ext2fs_open() function now sets EXT2_FLAG_MASTER_SB_ONLY. In +general, only e2fsck (after the filesystem is clean), tune2fs, and +resize2fs should change the backup superblocks by default. Most +callers of ext2fs_open() should not be touching any superblock fields +which require the backups to be touched. + +Add new function to libext2fs, ext2fs_default_journal_size(), which +returns the default journal size. + + +E2fsprogs 1.39 (May 29, 2006) +============================= + +Fix 32-bit cleanliness in e2fsprogs so that we can support filesystems +between 2**31 and 2**32 blocks. + +Change mke2fs to use /etc/mke2fs.conf as a configuration file to +configure the filesystem features, blocksize, and inode_ratio for +different filesystem types. + +Mke2fs will now create filesystems hash trees and on-line resizing +enabled by default, based on the new /etc/mke2fs.conf file. + +The e2fsprogs tools (resize2fs, e2fsck, mke2fs) will open the +filesystem device node in exclusive mode to prevent accidents by +system administrators. In the case of resize2fs and mke2fs, it will +only use exclusive mode if the filesystem is not mounted. + +Fixed a bug in mke2fs which caused it to to fail when creating the +resize inode for large filesystems. (Addresses Debian Bug #346580) + +When allocating space for the RAID filesystems with the stride +parameter, mke2fs will now place each portion of the group's inode +table right up after the superblock (if present) in order to minimize +fragmentation of the freespace. + +Speed up mke2fs and e2fsck by writing inode and block bitmaps more +efficiently by writing the inode and block bitmaps in one pass, thus +reducing the number of disk seeks required. + +Add support for on-line resizing to resize2fs. + +Fix blkid library so that logic to determine whether or not a device's +cached information in /etc/blkid.tab needs to be verified or not +doesn't get confused by a system clock which is insane (for example, +if the battery is dead on a Macintosh running PPC Linux. (Addresses +Red Hat Bug: #182188) + +The blkid library will now store the UUID of the external journal used +by ext3 filesystems, so that in the future, the userspace mount binary +can use this to find the location of the external journal and pass +this information to the kernel. + +E2fsck will now consult a configuration file, /etc/e2fsck.conf to +control how various options should be handled. See the e2fsck.conf +man page for more details. (Addresses Debian Bug: #150295) + +E2fsck now prints an explanatory message when delaying a filesystem +check when the system is running on battery. (Addresses Debian Bug: +#350306) + +E2fsck will detect if the superblock's last mount field or last write +field is in the future, and offer to fix if so. (Addresses Debian Bug +#327580) These problems will be fixed automatically in preen mode +since Debian's boot sequence bogusly doesn't set the time correctly +until potentially very late in the bootup process, and this can cause +false positives which will cause users' systems to fail to boot. +(Addresses Debian Bugs #343662 and #343645) + +E2fsck now checks to see if the superblock hint for the location of +the external journal is incorrect, and if so, offer to update it. +(Addresses Debian Bug: #355644) + +Fix e2fsck from segfaulting on disconnected inodes that contain one or +more extended attributes. (Addresses Debian Bug: #316736, #318463) + +E2fsck will stop and print a warning if the user tries running a +read/write badblocks test on a read-only mounted root filesystem. + +Fix a memory leak in e2fsck's error paths. (Thanks to Michael +C. Thompson for pointing these out; they were originally found using +Coverity.) + +When resizing a file containing a filesystem, resize2fs will expand or +truncate a file as necessary. (Addresses Debian Bug: #271607) + +Resize2fs will now automatically determine the RAID stride parameter that +had been used to create the filesystem, and use that for newly created +block groups. The RAID stride parameter may also be manually specified +on the command line using the new -S option to resize2fs. + +Fix mke2fs so that it correctly creates external journals on +big-endian machines (such as a S/390). + +Fix a bug in the e2p library which could cause dumpe2fs to (rarely) +fail to print out the journal or hash seed UUID. (Thanks to Guillaume +Chambraud for pointing this out.) + +Dumpe2fs will now print the size of the journal (if present). + +Fix debugfs's set_inode_field command so it can properly set the frag, +fsize, uid_high, gid_high, and author fields in the inode instead of +silently failing, and so that setting the i_size actually sets i_size +correctly. + +Add a new debugfs command, set_current_time, which sets fs->now so +that regression test suites can repeatedly modify the filesystem's +last_write fields. + +Fix a bug in debugfs's icheck which would incorrectly report the owner +of an extended attribute block. + +Fix the debugfs commands htree_dump, dx_hash, and list_dir so they print a +print a usage message when an illegal option character is given. + +Fix debugfs's dump_unsued command on filesystems with a 64k blocksize +so it won't core dump. (Addresses SourceForge bug #1424311) + +Fix mklost+found so that it creates a full-sized directory on +filesystems with larger block sizes. + +Fix a file descriptor leak in blkid library. + +Fix a display bug in "badblocks -sv" so that the done message properly +clears the block number at the end of the test. (Addresses Debian Bug +#322231) + +Allow fractional percentages to the -m option in mke2fs and tune2fs +(Addresses Debian Bug: #80205) + +Use fstat/fstat64 in getsize.c if the the target is a regular file, +instead of attempting to do a binary search. Fix some fd leaks in +error cases. + +Add support for device mapper library to the blkid library to ensure +that the "best" (i.e., leaf) device is probed by the blkid library. + +Fix the blkid library so that it notices when an ext2 filesystem is +upgraded to ext3. + +Improve the blkid's library VFAT/FAT detection; it now understands +labels stored in the root directory, and is more paranoid about +checking the FAT superblock values. + +Fixed a fd leak in the uuid library which was causing problems for the +LVM tools. (Addresses Debian Bug: #345832) + +Add support for the reiser4 and software suspend partitions to the +blkid library. Also add support for extract the label from iso9660 +filesystems. + +Fix a compile_et bug which miscount the number of error messages if +continuations are used in the .et file. + +Add extra sanity checks to protect users from unusual cirucmstances +where /etc/mtab may not be sane, by checking to see if the device is +reported busy (works on Linux 2.6) kernels. (Addresses Debian Bug +#319002) + +Updated French, Dutch, Polish, and Swedish translations. (Addresses Debian +Bug: #343149, #341911, #300871, #316604, #316782, #330789) + +Fix use-after-free bug in e2fsck when finishing up the use of the +e2fsck context structure. + +Fixed spelling mistakes, typos, and otherwise clarified man pages and +documentation. (Addresses Debian Bugs: #329859, #322188, #316811, +#312515, #351268, #357951, #347295, #316040, #368392, #368393, #368394, +#368179) + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs #317862, #320389, #290429, #310950, +#310428, #330737, #330736, #329074, #356293, #360046, #366017, #364516, +#362544, #362970) + + +Programmer's notes: +------------------- + +Update config.guess and config.sub to latest version (2006-02-23) from +FSF. + +Fix asm_types.h type conflicts on AMD 64 platforms. (Addresses Debian +Bugs: #360661, #360317) + +Fixed the Makefile so that they work correctly on newer versions of +GNU make (i.e., 3.81). + +Add valgrind support to the regression test suites, and eliminate +false positives from valgrind. + +Add a regression test suite for the blkid library. + +Fix a fencepost error in resize2fs caught by valgrind. + +Fix compiler warnings about missing memcpy prototypes. + +We no longer have the sparc assembly code in the header file any more, +so we shouldn't set _EXT2_HAVE_HAS_BITOPS_ for the sparc. This would +break compiles on the sparc architectures when using gcc. + +In the libext2fs library, add the new field fs->now which if non-zero +is used instead of the system time when setting various filesystem +fields (last modified time, last write time, etc.) + +Fix gcc 4.01 complaints by adding a missing #include <string.h> to +ext2fs.h which is needed since the inline functions use memcpy(). +(Addresses Sourceforge Bug #1251062) + +Use BUILD_CFLAGS and BUILD_LDFLAGS instead of CFLAGS and LDFLAGS in +the build system when building files in the util directory which are +needed during the build process. This avoids potential problems when +cross-compiling and some of the options specified in CFLAGS or LDFLAGS +are not recognized as valid by the host compiler. (Addresses +Sourceforge Bug #1261547) + +Clean up the blkid library by making the superblock and generic i/o +functions to be more generic. Clean up interface to the probe +function, and fix memory leak. Finallly, remove an unneeded reference +to probe.h in the lib/blkid/resolve.c + +Add an ext2fs_read_bb_FILE regression test to confirm proper detection +of invalid block #'s. + +The x86 asm constraints for ext2fs_{set/clear}_bit have been fixed to +indicate that the the function read/writes the memory location. + +Fix various gcc -Wall complaints. + +Add a dependency to make sure that the subdirectories are created +before creating all of the object files, in order to address parallel +build problem in the library Makefiles. (Addresses Sourceforge Bug: +#1261553) + +Add $(LDFLAGS) to the command line argument when generating an ELF or +Solaris shared library, to allow cross-compile and other builds that +might need to specify -L paths to needed libraries. (Addresses +Sourceforge Bug #1261549) + +Add a new feature, EXT2_FEATURE_COMPAT_LAZY_BG, which is initially +intended for testing purposes. It allows an ext2/ext3 developer to +create very large filesystems using sparse files where most of the +block groups are not initialized and so do not require much disk +space. Eventually it could be used as a way of speeding up mke2fs and +e2fsck for large filesystem, but that would be best done by adding an +RO_COMPAT extension to the filesystem to allow the inode table to be +lazily initialized on a per-block basis, instead of being entirely +initialized or entirely unused on a per-blockgroup basis. + +Fix backwards compatibility so e2fsprogs will better compile on Linux +2.0.35 systems. + +Make test scripts more robust against locale-related environment variables + +Fix type warning problem with sizeof() in ext2fs_open2(). + +Fix type warning problem with time_t in debugfs. + + +E2fsprogs 1.38 (June 30, 2005) +============================== + +Fix blkid's test programs (built with "make check") compile correctly +even without "configure --enable-blkid-debug". + +Fix ia64 core dump bug caused by e2fsprogs running afoul of C99 strict +type aliasing rules on newer gcc compilers. (Addresses Red Hat +Bugzilla ##161183.) + +Fix com_err library to make it more compatible with recent changes +made to the com_err library in MIT Kerberos V5 version 1.4. +(Addresses Sourcefroge Bug #1150146) + +General cleanup of messages printed by e2fsprogs programs for grammar, +consistency, and to make life easier for translators. Fixed a few +strings containing English that had not been marked as needing +translations. Removed strings that do not need to be translated, to +make life easier for translators. + +Mke2fs and badblocks will take advantage of a feature in Linux 2.6 to +test to see if a device appears to be in use instead of just relying +on /proc/mounts and /etc/mtab. (Addresses Debian Bug #308594). + +Fix portability problem in the filefrag program affecting platforms +where the size of an integer is smaller than the size of a long. +(Addresses Debian Bug #309655) + +Mke2fs will now use a larger journal by default for filesystems +greater than 4GB. (128 MB instead of 32MB). + +Mke2fs will refuse to create filesystems greater than 2**31-1 blocks, +unless forced. This is to avoid signed vs. unsigned kernel bugs in +block numbers that still need to be fixed. + +The blkid program has a new option which will more efficiently search +for device when it is known (or expected) that only one matching +device will be found in the system, such as when doing a lookup by +UUID. + +Debian's e2fsprogs-specific initrd fragment will avoid including +unnecessary libraries into the initrd ramdisk by unsetting LD_PRELOAD +and LD_LIBRARY_PATH, and filtering out libraries found in +/etc/ld.so.preload. (Addresses Debian Bug: #304003) + +Fixed a potential portability issue in the blkid programs for +architectures where the char type is unsigned. (Addresses Sourceforge +Bug: #1180585) + +Fix a bug in filefrag so that it doesn't falsely count an extra +discontinuity when the first block found is an indirect block. +(Addresses Debian Bug #307607). + +Fix blkid's recognition of cramfs filesystems, and enhance it to be +able to handle cramfs labels. + +Fix debugfs's stat command to not core dump when a filesystem is not +open. + +Fix e2fsck's handling of error conditions caused by the resize inode +claiming blocks that are also used by other inodes, a filesystem +corruption which was commonly caused by a bug in Fedora Core 3's +resize2fs program. + +Fixed bug in filefrag which caused it to fail on non-ext2/3 +filesystems. (Addresses Debian Bug: #303509) + +If the superblock last mount time indicates that the system clock may +not be accurate, then e2fsck will omit checking inodes' deletion time +field for indications of a potential corrupted orphaned inode list. +(Previously e2fsck only ommited these LOW_DTIME checks when the +superblock's last write time looked insane.) + +Fixed a IA64 core dump bug in the e2p library which affected dumpe2fs. +(Addresses Debian bug #302200) + +Make the blkid library more paranoid about being run from setgid +programs, and to use __secure_getenv() from libc if it is available. + +Fixed spelling mistakes, typos, and otherwise clarified man pages. +(Addresses Debian Bugs: #304591, #304592, #304594, #304597, #304593 +and Sourceforge Bug: #1189803) + +Updated and fixed translations. + +Fixed various Debian packaging issues --- see debian/changelog for +details. + +Programmer's notes: +------------------- + +Ext2fs_set_bit(), ext2fs_clear_bit(), and ext2fs_test_bit( have been +changed to take an unsigned int for the bit number. Negative bit +numbers were never allowed (and didn't make any sense), so this should +be a safe change. This is needed to allow safe use of block numbers +greater than or equal to 2**31. + +The compile_et program will avoid recreating generated foo_err.c and +foo_err.h files if no changes are necessary. The compile_et program +will also atomically replace these files to avoid a potential parallel +build race problem on SMP systems. (Addresses Sourceforge Bug: +#1157933) + +Added a new function to the blkid library, blkid_probe_all_new(), +which only probes newly added disk devices, and change +blkid_find_dev_with_tag() to use this function so that when a +requested tag is not found, devices that were previously not checked +are searched before searching all devices in the system. + +Added new functions to the blkid library, blkid_dev_set_search() and +blkid_dev_has_tag(). + +E2fsck's problem strings can now use @m and @n as abbrevations for +"multiply-claimed" and "invalid", respectively. + +The e2fsprog.pot file now has an explanation of how the @-expansion +and %-expansion works, and strings in e2fsck/problem.c which contain @ +characters now have comments in e2fsprogs.pot with the @-expansion to +make life easier for translators. + +Fixed missing return values in the ext2fs library which could cause it +to return random garbage in certain error conditions. + +Allow the current time to be overriden via the E2FSCK_TIME environment +variable for use in regression tests. + +The test scrpit driver program now exits with a non-zero status if +there any of its test that it ran failed. + +Fixed problems with parabuilds on SMP systems. (Addresses Sourceforge +Bug: #1157933) + +Fixed "make check" so that it compiles correctly even when e2fsprogs' +header files have not be installed in the system include directories. +(Addresses Sourceforge Bug: #1180572) + +Fixed gcc -Wall nits. + + +E2fsprogs 1.37 (March 21, 2005) +=============================== + +Add support for checking the validity of Extended Attributes stored in +inodes to e2fsck. + +Add support for dumping the contents of large inodes to debugfs, +including the extended attributes stored in inodes. + +Fix mke2fs, e2fsck, debugfs, and the ext2fs_mkdir function so that +when we create a new inode we make sure that the extra information in +the inode (any extra fields in a large inode and any ea-in-inode +information) is initialized correctly. This can take place when +mke2fs creates the root and lost+found directory, when e2fsck creates +a new root inode or a new lost+found directory, and when the user uses +the debugfs write, mknod, or mkdir commands. Otherwise, the newly +create inode could inherit garbage (or old EA information) from a +previously deleted inode. + +Fixed a bug in e2fsck so it would notice if a file with an extended +attribute block was exactly 2**32 blocks, such that i_blocks wrapped +to zero. + +Added support to filefrag to detect files which are using the new +experimental file extents format, and use the non-ext2 algorithm in +that case. Fixed a bug to avoid reporting a false discontinuity if +there is one or more unallocated blocks at the beginning of a file. + +Duplicated a check for noticing whether or not the number of blocks +(given a certain blocksize) is greater than 2**32 when the +BLKGETSIZE64 ioctl is not available to ext2fs_get_device_size(). This +allows mke2fs to automatically use a larger blocksize when creating a +filesystem on a very large device when run on systems that do not +support BLKGETSIZE64. + +Fix the I18N build which was broken in e2fsprogs 1.36 because the +build system had been switched to treat the .gmo files as shipped +files (for backwards compatibility with systems that have older GNU +I18N tools installed), but the gen_tarball.in script was still +removing the .gmo files from the official source distribution. + +Fixed various Debian packaging issues --- see debian/changelog for +details. (Addresses Debian Bugs ##296769, #299341) + +Programmer's notes: +------------------- + +Added new functions to the e2p library which convert between a string +and os_type: e2p_os2string() and e2p_string2os(), and used them to +make the generated binaries more compact. + +Fixed a compile-time error on Darwin systems. + +Cleaned up the lib/ext2fs Makefile slightly. + + +E2fsprogs 1.36 (February 4, 2005) +================================= + +All of the patches that were applied to Fedore Core 3's +e2fsprogs-1.35-11.2 have been integrated, although sometimes with a +lot of bug fixes first. Users of Fedora Core 3 are strongly +encouraged to upgrade to e2fsprogs 1.36 as soon as possible. + +Add support for filesystem with the online resizing via resize inode +feature. Fixed numerous bugs from the Fedora patches. The Fedora +patches also didn't bother to do any consistency checking on the +resize inode, or add any tests to the regression test suite. The "-R +resize=4g" option to mke2fs was a no-op in the Fedora patches, despite +being listed in mke2fs's usage message. All of these shortcomings +have been corrected. + +E2fsck can also also fix filesystems trashed by Fedora's resize2fs +program. In order to do this, the user must run the commands: + + debugfs -w /dev/hdXXX -R "features ^resize_inode" + e2fsck -f /dev/hdXXX + +Optionally, the ext2prepare command can be used to re-enable online +resizing after the filesystem has been fixed. + +The fsck program will now accept an optional filedescriptor argument +to the -C option. (The Fedora version of this patch would sometimes +cause fsck to ignore a parameter on fsck's command line in some rare +cases, sigh.) + +Make sure e2fsprogs doesn't write garbage into the reserved portion of +large inodes. + +Make sure resize2fs releases the blocks belonging to the old inode +table blocks when moving the inode table. (Addresses Debian Bug: +#290894) + +Skip the r_resize_inode test if resize2fs is not compiled (due to +configure --disable-resizer) + +E2fsck now checks the summary filesystem accounting information, and +if any of the information is obviously wrong, it will force a full +filesystem check. (Addresses Debian Bug #291571) + +Fix e2fsck to not complain when the resize_inode feature is enabled, +s_reserved_gdt_blocks is zero, and there is no DIND block allocated in +the resize inode. + +Fix e2fsck to note delete symlinks that contain an extended attribute +after the ext_attr feature flag has been cleared. (Addresses Red Hat +Bugzilla #146284). + +Add new utility program, copy_sparse.c, which is very useful +for dealing with large sparse files (such as e2image files). + +Add support for jnl_blocks[] for debugfs's set_super_value. + +Fix filefrag so that it works correctly with sparse files. + +Filefrag -v will print first and last blocks. + +Add interpretation of OS Creator values for FreeBSD and Lites in mke2fs +and dumpe2fs. + +Add mke2fs support so that it can support filesystems larger than 4TB +automatically, by retrying with a 4k blocksize if the device size is +too big to be expressed using a 1k blocksize. (Addresses Sourceforge +bug #1106631) + +Change blkid to test for NTFS first because Windows sometimes doesn't +clear enough of the parition to confuse the probing routines into +thinking the old filesystem type is still valid. (Addresses Debian +Bug #291990) + +Add support for swap partition label and uuid's in the blkid library. + +Add support to the blkid library to recognize Oracle ASM volumes. + +Make blkid -t display all devices that match the specified criteria, +not just the first one, and work more consistently when the blkid +cache file is not available or set to /dev/null. (Addresses Debian +Bug #290530 and #292425) + +Badblocks will now correctly display block numbers greater than +999,999,999 in its progress display. + +The tune2fs program will not allow the user from setting a ridiculous +number of reserved blocks which would cause e2fsck to assume the +superblock was corrupt. E2fsck's standards for what is a ridiculous +number of reserved block has also been relaxed to 50% of the blocks in +the filesystem. + +The blkid library will return vfat in preference to msdos, and ext3 in +preference to ext2 (if the journalling flag is set) so that mount will +do the right thing. (Addresses Debian bug #287455) + +Mke2fs will now use the -E option for extended options; the old -R +(raid options) option is still accepted for backwards compatibility. +Fix a double-free problem in resize2fs. (Red Hat Bugzilla #132707) + +Mke2fs will now accept a size in megabytes, gigabytes, and other units +(via "32m" or "4g" on the command line) if the user finds this more +convenient than specifying a block count. + +Fix an obscure, hard-to find bug in "e2fsck -S" caused by an inode +cache conherency problem. + +Debugfs now supports a new command, set_inode_field, which allows a +user to manually set a specific inode field more conveniently, as well +as set entries in the indirect block map. + +Debugfs's set_super_value command has been enhanced so that the user +can set most superblock fields, including the date/time fields and +some of the more newsly added superblock fields. + +E2fsprogs programs now accept an offset to be passed to the file +specifiers, via the syntax: "/tmp/test.img?offset=1024". + +E2fsprogs programs will now accept blocksizes up to 65536; kernel +support on the x86 doesn't exist for now, but it can be useful on +other architectures with page sizes greater than 4k. There are 2.6 +kernel patches out there which enable this, but they are of this +writing still experimental. + +The e2image command now takes the -s option which will scramble +directory entries for raw image files. + +Fix a file descriptor leak in the filefrag program. + +Make sure e2fsck doesn't crash when /proc/acpi/ac_adapter is not +present. + +Fix bug in debugfs where kill_file would lead to errors when deleting +devices and symlinks. (Sourceforge Bugs #954741 and #957244) + +Fix bug in the blkid library when detecting the ocfs1 filesystem + +Remove obsolete EVMS 1.x and a.out DLL support. + +E2fsck will attempt to recover from a journal containing illegal blocks. + +Fixed two potential ordering constraint problems in e2fsck which might +cause the filesystem to be corrupted if e2fsck is interrupted during a +(extremely narrow) race window. Thanks to Junfeng Yang from the +Stanford Metacompilation group for pointing this out. + +Fixed bug in e2fsck where it would not accurately detect whether or +not the system is running on adaptor if the ACPI device representing +the AC adapter didn't correspond to the what was used on IBM +Thinkpads. + +Change e2fsck to accept directories greater than 32MB. + +Fix e2fsck so that a checkinterval of zero disables a time-based check +of the filesystem. + +Debugfs will check the DEBUGFS_PAGER enviroment variable in preference +to the PAGER environment variable. (Addresses Debian Bug #239547) + +Tune2fs will not mark rewrite the superblock if the feature bitmasks +are not modified. + +The debugfs program will set the filetype information when creating a +link. + +Add debugfs -d option to use a separate source of data blocks when +reading from an e2image file. + +Add e2image -I option which allows the e2image metadata to be +installed into a filesystem. + +Fixed bug in the badblocks program which caused "done" to always +appear in english even when a translation was available. (Addresses +Debian Bug #252836) + +The blkid program has a new option -o which controls the output format +of the blkid program; this is makes blkid more convenient to use in +shell scripts. + +Fix a minor bug in uuid library, which was not using the full 14 bits +of clock sequence when generating UUID's. + +Fix a Y8.8888K problem in the uuid library. + +Logsave now creates a new session id for itself to avoid getting +killed by init whan transitioning between init levels. + +Change the licensing of the UUID library to be the 3-clause BSD-style +license; this allows Apple to use the uuid library in Darwin. + +Add ocfs and ocfs2 probe support into the blkid library. + +Fix a memory and file descriptor leak in the blkid library. + +The blkid library will revalidate the device if the system time is +earlier than last verification time of the device, since that +indicates that the system time is probably nottrustworthy. + +The blkid library will override the default location of the blkid.tab +file by the BLKID_FILE environment variable, if it is available. + +Change the getsize functions to use the BLKGETSIZE64 ioctl on Linux 2.6. + +Add various portability fixes for lame new versions of glibc, Darwin +and GNU/KFreeBSD, as well as removing XSI:ism's. (Addresses Debian +Bugs #239934, #264630, #269044, #255589, #289133) + +Add support for Windows 9x/NT under Cygwin. + +Updated and clarified various man pages. (Addresses Debian Bugs #236383, + #241940, #238741, #242995, #256669, #268148, #256760, #273679) + +Updated and fixed translations. (Addresses Debian bugs #244105, #262836) + +Update the rpm spec files so that it works better with Fedora core 2 +and RH9. + +Fixed various Debian packaging issues (see debian/changelog). In +particular, fixed the Debian initrd scripts. (#241183, #248050, +#253595, #247775) + + +Programmer's notes: +------------------- + +Fixed various gcc -Wall warnings. + +The uuid library now has new functions uuid_unparse_upper() and +uuid_unparse_lower() which forces the case of the hex digits to be +upper case, or lower case. + +The build process has been speeded up by enhancing the subst program +to update the modtime on the generated files even when the generated +file hasn't changed. + +The uuid library now uses C99 stdint.h types instead of custom types. + +Updated config.guess and config.sub with newer versions from the FSF. + +Removed out of date .cvsignore files from the source distribution. + +The ext2fs_unlink() function will return an error if both the name and +inode number are unspecified, to avoid doing something surprising +(such as unconditionally deleting the first directory entry). +Directory entries are now deleted by coalescing them with the previous +directory entry if possible, to avoid directory fragmentation. This +is not an issue with the e2fsprogs suite, but may be a problem for +some of the users of libext2fs, such as e2tools. + +Add support for version numbers of the form "1.36-rc1". + +Fix build of mke2fs.static. + +Add basic ext2fs library support for large (EA in inode) inodes. + +The test_io mechanism can now abort after n reads or writes to a +particular block. The block is specified by TEST_IO_BLOCK environment +variable, and the read/write count by the TEST_IO_READ_ABORT and +TEST_IO_WRITE_ABORT environment variables. The block data is now only +dumped if the 0x10 bit is set in TEST_IO_FLAGS. + +UUID_DEFINE() in the uuid library now creates a static variable, with +__attribute__ ((unused)) if we are using GCC, so that UUID_DEFINE can +be used in header files. + +Add support for the install-strip and install-shlibs-strip targets, as +suggested by the GNU coding guielines. "make install" no longer +strips the binaries which are installed. + +Remove support for the --enable-old-bitops configure option which was +only for very old sparc systems. + +Remove support for --enable-clear-htree; this was only needed during +the early development of the htree patch. + +Use Linux-kernel-style makefile output so it is easier to see compiler +warnings. + +Update gettext files to version 0.14.1. + +Update to use autoconf 2.5x. + +Improved support for compiling e2fsprogs under dietlibc. + +Make e2fsprogs portable to Solaris and FreeBSD systems. + +Add blkid_verify(), blkid_get_library_version(), and +blkid_parse_version_string() functions to the blkid library. + +Add pkg-config files for e2fsprogs's libraries. + +Fix "make uninstall" to so that it removes everything that is installed. + +Add a configure --enable-maintainer-mode option which enables the +makefile rules to rebuild the configure script from configure.in, and +to reubuild the .gmo files in po directory. + +Drop the sparc assembly bitwise operations; it's less efficient +than the GCC 3.4 compile code and triggers compiler warnings on +sparc64. Thanks to Matthias Andree for his analysis and suggestions. +(Addresses Debian Bug #232326) + + +E2fsprogs 1.35 (February 28, 2004) +================================== + +E2fsck has a new -k option, which in conjunction with the -c options, +preserves the existing badblocks list. + +Cleaned up e2fsck's preen-mode messages during the passes 1b, 1c, and 1d. + +E2fsprogs will now deal correctly with symlinks that contain +extended attribute information, which can be created using SE Linux. +(Addresses Debian Bug #232328) + +Remove a double longjump into an invalid stack frame bug in e2fsck. +(This was during an abort sequence, which normally worked on Linux and +caused a core dump on other operating systems.) + +Fix NLS bug in e2fsck, by avoiding trying to expand an empty string +(the NLS library will replace "" with the .po header information). + +Fix a bug in mke2fs which caused -T largefile or -T largefile4 to core +dump due to a division by zero error. (Addresses Debian bug #207082) + +Fixed a bug in e2fsck which caused it to incorrectly fix a filesystem +when reconnecting a directory requires creating a lost+found +directory. (Addresses Debian bug #219640). + +Fixed a bug where e2fsck would bomb out if a journal needed to be +replayed when using an alternate superblock. + +E2fsck will give an extra grace period before actually forcing a check +if the laptop is running on battery. The next time fsck runs while +the system is on the AC mains, or after the grace period is exceeded, +the filesystem will be checked. (Addresses Debian bug #205177) + +E2fsck will inform the user when there are 5 or fewer mounts before a +filesystem check will be forced. (Addresses Debian bug #157194) + +Fix e2fsck's handling of corrupted indirect blocks in the bad block. +We now correctly handle the case where there is an overlap between a +block group descriptor or a superblock and a bad block indirect block. +In the case where the indirect block is corrupted, we now suggest +"e2fsck -c". + +Fix byte swap bugs in e2fsck that caused the journal backup location +in the superblock and symlinks created by SE Linux to be cleared +by e2fsck on big-endian machines. (Addresses Debian bug #228723) + +E2fsck -c now replaces the current list of bad blocks with the ones +found by badblocks. + +Fix bugs in e2fsck and tune2fs which could cause a core dump if a +non-existent LABEL or UUID specifier is to e2fsck or tune2fs. + +Fix a potential bug in e2fsck which could cause it to core dump when +trying to print the location of the backup superblock. + +Protect against a potential core dump in e2fsck when printing a +message about backup superblocks. + +Add support for backing up the journal inode location in the +superblock. E2fsck will automatically save the journal information in +the superblock if it is not there already, and will use it if the +journal inode appears to be corrupted. ext2fs_add_journal_inode() +will also save the backup information, so that new filesystems created +by mke2fs and filesystems that have journals added via tune2fs will +also have journal location written to the superblock as well. +Debugfs's logdump command has been enhanced so that it can use the +journal information in the superblock. + +E2fsck will now update all superblocks when moving the journal inode. + +Shrink the size of the e2fsck executable by moving some initialized +variables to the BSS segment. + +E2fsck will avoid printing the ^A and ^B characters which bracket the +progress bar when stdout and stdin are a tty device instead of a pipe +to another program. (Addresses Debian bug #204137) + +Debugfs's mkdir command will automatically expand the directory if +necessary. (Addresses Debian Bug: #217892) + +Fixed a bug in debugfs so that copying a file from /dev/null uses the +correct mode bits. (Addresses Debian Bug: #217456) + +If the environment variables DEBUFS_PAGER and PAGER are not set, +debugfs now searches for the appropriate pager to use, beginning with +/usr/bin/pager, and then falling back to 'more' and 'less'. +(Addresses Debian bug #221977) + +Debugfs will now support 2.6 device numbers where the major or minor +number may be larger than 255. (Addresses Sourceforge bug #865289) + +Fix debugging printf in resize2fs. (Addresses Debian Bug #271605) + +Chattr now stops processing options when it sees '--'. (Addresses +Debian bug #225188) + +Fix regression tests so they work correctly when e2fsprogs is compiled +with configure --disable-htree. + +Fix bug in uuid library when there is no network card and the library +is generating a time-based uuid. The random MAC address was not +correctly generated to be a multicast address. + +Add compile_et extensions from Heimdall that were missed the first time +around. + +Fix bug in badblocks when using O_DIRECT; we need to make sure that +we're reading from an offset which is page aligned. For read-only and +read-write tests, we try to recover after an error so that we can +continue reading on page-aligned boundaries. (Addresses Debian Bug +#203713) + +Badblocks now checks 64 blocks at a time instead of 16. (Addresses +Debian bug #232240) + +Updated and clarified various man pages. (Addresses Debian Bug +#206845, #222606, #214920, #232406) + +Updated and fixed translations. (Addresses Debian bugs #200086, #214633) + +Fixed various Debian packaging issues (see debian/changelog). + +Programmer's notes: +------------------- + +Fixed a build problem so that e2fsprogs would compile with the +--enable-profile option to configure selected. (Addresses Sourceforge +bug #811408) + +Fixed C++ problems with the ext2fs.h header. (Addresses Red Hat +Bugzilla Bug #112448) + +Centralize code which calculates the location of the superblock +and block group descriptors so that it is in a single library routine. + +Added two new functions, ext2fs_file_open2() and +ext2fs_inode_io_intern2() which take a pointer to an inode structure. + +Fix compile_et to output the correct prototype for +initialize_xxx_err_table_r() in the header file. (Addresses Debian +bug #204332) + +In the lib/et makefile, make sure com_err.info is deleted on "make clean". + +Fix 64-bit warnings in e2fsprogs pass1b by using inttypes.h if +present. This is for when we try stuffing an int into void * pointer. + +Fix type-punning which can cause gcc 3.x to miscompile code by getting +confused about pointer aliasing. ext2fs_getmem(), ext2fs_free_mem(), +and ext2fs_resize_mem() all now take a 'void *' instead of a 'void +**'. The EVMS code uses an ugly union approach since we don't want to +modify the EVMS interfaces. + +Make sure all Makefiles use $(MAKE) rather than hardcoded "make", to +aid build process on systems can use invoke GNU make as "gmake". + +Added regression testing for mke2fs. + +Fixed gcc -Wall nitpicks. + +Fixed various compiler warnings. + +Add portability fixes for FreeBSD and for using fsctl under Darwin to +support ext2 ioctl's. + + +E2fsprogs 1.34 (July 25, 2003) +=============================== + +Fixed a bug introduced in E2fsprogs 1.30 which caused fsck to spin in +a tight loop while waiting for a child fsck to exit in some cases. +This burns CPU times which slows down the low-level filesystem check. + +Added code to mke2fs to assure that the default block size for a +filesystem is at least as big as the sector size of the device, if it +can be determined. + +Changed mke2fs and resize2fs to round the default size of a filesystem +to be an even multiple of the VM pagesize in order to avoid a Linux +kernel bug introduced when the storage of the buffer cache was moved +into the page cache. + +Mke2fs will warn the user when creating a filesystem with journaling +and a blocksize greater than 4096. (Addresses Debian bug #193773) + +Fixed a bug in resize2fs which caused it to fail on filesystems with a +non-empty bad block list. Resize2fs now discards any blocks on the +badblock list which are no longer part of the filesystem as the result +of a filesystem shrink. (Note: this means that shrinking and then +enlarging a filesystem is no longer a reversible operation; +information about bad blocks in the part of the filesystem which is to +be chopped off will be lost.) + +Changed resize2fs so the user can use prefixes to specify the units of +the new filesystem size (sectors, kilobytes, megabytes, or gigabytes), +and to make the error and informational messages explicitly display +the blocksize used by the filesystem, in order to avoid confusion. +(Addresses Debian bug: #189814) + +Added a new debugfs command, dump_unused, which dumps the contents of +all unused blocks to stdout. (Useful as an emergency try-to-find +deleted data command.) + +Added a new debugfs command, imap, which prints the location of a +specified inode in the inode table. + +Fixed a bug in the badblocks program which caused it to use one bit of +randomness in its non-destructive read/write test, instead of using a +full 8 bits of randomness. + +Added a new option (-t) to badblocks, which allows the user to control +the test pattern(s) used when checking a disk. + +The blkid probe function now more correctly detects UDF filesystems. + +Fixed a bug in the blkid library which caused it to not update its +cache if a filesystem changes from having a label to not having a +label. + +Fixed a bug in the blkid library wihch could avoid an infinite loop +in blkid_find_dev_with_tag() if /proc is not mounted and there the +/etc/blkid.tab file has not yet been created. + +Fixed the badblocks program so that the destructive read/write test +honors the -c option, and to use O_DIRECT when possible to avoid +thrashing the system block buffer cache. + +Fixed various NLS issues. + - Added Czech and Swedish translations + - Removed testing NYC translation + - Fixed NLS support for message abbrevations in e2fsck + - Remove de-utf.po, since we shouldn't have two versions using different + charset encodings. + - Used ngettext() (abbreivated with the macro P_(str1, str2, n)) to + simplify the statistics reporting in e2fsck. + +Changed configure.in so that its defaults for *BSD systems no longer +build an fsck wrapper, and not to install in /usr/local by default. + +Fixed some minor spelling errors/typo's in e2fsck and the configure +script. + +Fixed various Debian packaging issues (see debian/changelog). + +Updated and clarified man pages. (Addresses Debian Bug #195616) + +Programmer's notes: +------------------- + +Fix gcc -Wall nitpicks. + +Updated gettext implementation used by e2fsprogs to 0.11.5, and enable +NLS support by default. (Added partial workaround for gettext/Darwin +incompatibility problems.) + +Added full MIT KRB5 and Himdall compaibility support to the com_err +library and the compile_et program. (Addresses Debian bug #191900) + +Added the blkid_known_fstype() function to the blkid library, which +returns true if it is passed a filesystem type which is recognized by +the blkid probing functions. + +Improved the documentation for the blkid library. + +Added the ext2fs_get_device_sectsize() function the the ext2fs library, which +returns the hardware sector size of a device, if it is available. + +Added a dependency in the blkid library's .so file to the uuid +library, since the former uses the latter. (Addresses Debian bug +#194094) + +Added --with-diet-libc and --disable-evms to the configure script. + +Fixed a minor memory leak in the badblocks program. + +Fixed a portability problem in tune2fs --- not all systems have strptime(). + +Fixed a portability problem in debugfs with the use of getopt() more +than once. Old-style BSD, new-style BSD, and Linux C libraries all do +things differently. + +Add support Windows support to ext2fs_get_device_size(). + +Added (normally disabled) debugging code to the Unix I/O manager which +causes it to disable all userspace caching if the NO_IO_CACHE is +defined. + +Changed the test I/O manager so it can always be linked into e2fsck, +mke2fs, and tune2fs if enabled via --enable-test-io-debug to the +configure script. The test I/O manager will only print any debugging +information if the TEST_IO_FLAGS or TEST_IO_BLOCK environment +variables are set, which specifies which I/O operations are logged and +a block number to watch, respectively. The log messages are sent to +stderr by default, unless a filename is specified via the +TEST_IO_LOGFILE environment variable. + + +E2fsprogs 1.33 (April 21, 2003) +=============================== + +Added a new utility program, logsave, which captures the output of a +command in a log file, even if the containing directory hasn't been +mounted yet (in which case the it saves the output in memory until it +can write out the logfile). This is useful for capturing the +output of fsck during the boot sequence. + +Fixed some portability problems that were causing problems under +the Cygwin32 environment. + +Mke2fs now interprets a negative number to the -b option as a minimum +block size. + +Fixed a bug in mke2fs which was incorrectly checking the argument to +the -g option if the default block size was used. (Addresses Debian +bug #188319) + +Fsck now explicitly ignores tmpfs and devpts, and it will complain if +it can not find filesystem checkers for jfs, reseirfs, and xfs. + +E2fsck now updates the global free block and inode counters from the +block group specific counters quietly. This is needed for an +experimental patch which eliminates locking the entire filesystem when +allocating blocks or inodes; if the filesystem is not unmounted +cleanly, the global counts may not be accurate. + +Imported bug fixes to the EVMS plugin from the EVMS 2.0 tree. (EVMS +2.0 is not yet supported; this only pulled in the bug fixes: fixed +possible hangs caused by bugs in calling waitpid, and not setting the +pipe to non-blocking mode; also fixed a file descriptor leak; made +sure all functions call log entry/exit functions.) + +Badblocks now flushes its output file as bad blocks are discovered. + +The uuid library is now more paranoid about assuming the correctness +of the /dev/random device; it mixes in a stream of bytes from +random/srandom, just in case. + +Update Debian files to reflect the fact that I am now the Debian +maintainer of e2fsprogs. Other various Debian-specific packaging +cleanups. + +Move the source tarball generation functions from the top-level +makefile to the util/gen-tarball script. + +Updated the Turkish .po translation file. + +Added Heimdal and MIT krb5 extensions to the com_err library to make +it more compatible with com_err libraries from those distributions. + +Changed dumpe2fs to always display the superblock fields relating to +the journalling and/or directory indexing feature even if those +features are not enabled. + +Updated and clarify copyright statement vis-a-vis alpha releases of +e2fsprogs. + +The ss library will now try to dynamically link to the readline +library and use it if it is present in the system. This means that +the debugfs program now has line editing and history features. The +SS_READLINE_PATH environment variable is used to find a readline or +readline-compatible library. + +E2fsck now finds most duplicate filenames (all when rebuilding all +directories via the -D option) and offers to delete or rename +duplicate filenames/directory entries. (Addresses Debian Bug #176814). + +Fix bug in e2image. When writing out a raw image file, include data +blocks from symlinks that do not store the symlink within the inode. + +Fix bug in resize2fs which incorrectly moved the block and inode +bitmaps for sparse superblock filesystems and incorrectly marked +blocks as in use. (Addresses Debian bug #174766) + +Added a new shared library, the blkid library, which efficiently +allows fsck, mke2fs, e2fsck, and tune2fs to be able to look up LABEL +and UUID filesystem specifiers without needing to search all of the +devices in the system. Instead, the device is looked up in a cache +file, and then verified to make sure the blkid cache is correct. + +Tune2fs and e2label will accept LABEL=xxx and UID=yyy specifiers for +the device name, using the blkid library. (Addresses Debian bugs +#166048, #179671) + +Fsck now supports backslash escapes in /etc/fstab so that \040 can be +used for spaces in device labels. + +Removed 32-bit limitations for debugfs's dump command. + +If the user specifies a large number of inodes, Mke2fs will +automatically adjust the number of blocks per group to find a valid +set of filesystem parameters. + +Add workaround to detect broken MD devices where when some of the +underlying devices are marked read-only, writes to the MD device are +silently dropped. E2fsck will detect if there is an attempt to run +the journal twice, and abort with an error if this is the case. +(Addresses IBM Bugzilla bug #1226) + +E2fsck will print an error if more than one of the -p/-a, -n or -y +options are specified. + +E2fsck will fix HTREE corruptions in preen mode, without stopping the +boot process. This is needed because the 2.4 ext2 filesystem +accidentally had the INDEX_FL backwards compatibility code removed. + +Mke2fs no longer creates filesystems with the dir_index flag set by +default; the user has to specifically request it. + +Update and clarified various man pages. (Addresses Debian bugs +#173612, #175233, #175113, and #170497, #185945, #188318) + +Created man page for the mk_cmds program (from the libss library). + +Programmer's notes: +------------------- + +Fix various gcc -Wall nits. + +Fixed a lot of portability problems that caused e2fsprogs not to build +successfully under Solaris and Apple/Darwin. + +Fixed a Makefile dependency to allow building e2fsprogs using parallel +make jobs. + +Changes to create a subset distribution which consists only of the +et, ss, uuid, and blkid libraries. The configure script and top-level +makefile were changed to support working with a subset distribution. + +Removed EXT2_FEATURE_RO_COMPAT_BTREE_DIR mention of since it's not +actually used, and might people who are looking for +EXT2_FEATURE_COMPAT_DIR_INDEX, which is in use. + +Updated debian files to fix a number of Lintian warnings. + +Updated config.guess and config.sub with newer versions from the FSF. + +Removed unnecessary libraries from being linked into the fsck, lsattr, +chattr, and blkid executables. + +E2fsprogs 1.32 (Nomvember 9, 2002) +================================== + +Fixed a bug in the Unix I/O routines which caused needless writebacks +of clean blocks from the unix_io cache (they were erroneously marked +as being dirty, so they were getting written back to disk before +getting evicted from the disk cache). This was harmless, but it +significantly slowed down e2fsck. + +Made some other minor optimizations to the Unix I/O routines to save a +small amount of CPU time. + +Updated internationalization files. + + +E2fsprogs 1.31 (Nomvember 8, 2002) +================================== + +Update EVMS ext2fsim plugin with EVMS 1.2. (We still support +compiling the fsim plugin with EVMS 1.0 and 1.1.) Add better error +handling for child process that die unexpectly. Add a hack to force +mkfs to create filesystems that won't cause problems with hardware +that has 2k or 4k minimum blocksize requirements. Read from child +processes in non-blocking mode, so that the GUI continues to update. + +Fix e2fsck so that it returns the appropriate exit code when the root +filesystem has been changed, so that system's rc scripts will be told that +the system needs to be rebooted. + +Fix a bug in ext2fs_flush/ext2fs_close; when the MASTER_SB_ONLY flag +was set, some of the descriptor blocks that should have been written +out were getting skipped. + +Changed e2fsck to force out changes to the backup copies of the +superblock and block group descriptors when important changes are made +to those data structures. + +Fix a bug where e2fsck could erroneously mark a filesystem as being +clean if a check of dirty filesystem is interrupted with a ^C. (Bug +introduced in e2fsprogs 1.28.) + +If journal debuging is enabled using --enable-jbd-debug, the debugging +level is now set via the E2FSCK_JBD_DEBUG environment variable. + +If byteswapping support is disabled using configure --disable-swapfs, +skip the tests which depend on byte-swapping, so that "make check" +won't bomb out. + +Lshattr will now display the indexed directory flag. Also, some of +the more esoteric compression flags are supressed unless compression +support has been enabled. + +Update man pages. + + +E2fsprogs 1.30 (October 31, 2002) +================================= + +When resizing a filesystem, and inodes need to moved, resize2fs will +update the inode's ctime field, and the mtime field of the containing +directories, so that incremental backups using dump/restore will work +correctly. + +In order to avoid spurious errors, e2fsck wil check the last +superblock write time to determine whether or not it can safely use +the LOW_DTIME checks to determine if there are inodes on the orphan +inode linked list that had somehow gotten disconnected. (Addresses +Sourceforge bug #620980) + +Partition in /proc/partitions that being with the string "lvm" are +considered real partitions even if they do not end with a number. + +Fixed a bug in the the uuid generation function, where if /dev/urandom +is not present, but /dev/random is, and there isn't sufficient +entropy, the get_random_byte function could spin a loop forever. + +E2fsck, mke2fs, etc. will now reliably notice when image files are +mounted using the loopback interface. (Addresses Sourceforge bug +#619119) + +When flushing buffers (as is done by badblocks, for example) check to +see if the BLKFLSBUF ioctl succeeds, and if so, avoid using the +FDFLUSH ioctl which causes the MD device driver which causes confusing +syslog messages about obselete ioctl messages. (Addresses Sourceforge +bug #545832). + +Debugfs's write command now checks to see if the destination filename +exists before creating it. (Addresses Sourceforge bug #478195.) + +When installing man pages, search for compressed man pages using all +commonly used compression extensions (i.e., .Z, .gz, .bz2, etc.) + +Fixed a bug in fsck where multiple filesystems specified on the +command were not being checked in parallel due to a logic bug +introduced to support the FSCK_MAX_INST environment variable. + +We have added a new superblock field, s_mkfs_time, which indicates +when a filesystem was created. It is set via mke2fs, and printed out +by dumpe2fs, but is not actually touched by the kernel. + +Dumpe2fs has been made more robust by not aborting if there is an +error reading the block/inode bitmaps; instead it will still print out +the location of the block/inode bitmaps and inode table. + +Add support for the an alternative block group descriptor layout which +allows for on-line resizing without needing to prepare the filesystem +in advance. (This is the incomat feature flag meta_bg.) + +Add support for storing default mount options in the superblock, so +that the filesystem can be mounted with specific mount options without +needing to specify them on the mount command line or in the /etc/fstab +file. + +Add support for a new inode flag, which is to be used for indicating +the top of directory hierarchies for the Orlov block allocator. + +Fix e2fsck so that if it creates the lost+found directory, it does so +with the more apporpriate permissions of 0700. Also change +mklost+found so that it also creates the directory 0700. + +Fixed format bug in e2fsck if NLS is in use. + +Add a German translation for e2fsprogs's NLS support. + +Fixed e2fsck so that it more handles BAD_BLOCK_IN_INODE_TABLE even at +the beginning of the inode table. This won't matter much, since if +there is a bad block at the beginning of the inode table, the root +directory won't be available. But at least e2fsck won't crash in this +case. + +Fixed endian problems in the htree code for e2fsck and debugfs. + +When byte-swapping a filesystem on a PPC architecture, byte-swap the +bitmaps since the historical big-endian ext2 variant had byte-swapped +bitmaps, and the ext2fs library assumes this. This fixes the +regression test suite on PPC machines. + +Fix e2image so that it handles a bad block in the inode table +appropriately. + +E2fsck now uses a more sophisticated algorithm to salvage corrupted +directories that recovers more information in the corrupted directory +block. + +E2fsck now performs additional consistency checks on indexed (HTREE) +directories. + +Fix bug where efsck might get confused about whether a completely +empty directory block is an empty leaf block or an interior htree +node. This could cause e2fsck to get confused into think that a valid +indexed directory was corrupted. + +E2fsck no longer creates an empty directory entry at the end of a +directory block when optimizing a directory. This would cause some +earlier versions of the dxdir kernel code to corrupt the directory +when attempting to split a node containing an empty directory entry. + +E2fsck could sometimes in rare circumstances leave the indexed flag +set after a small directory was optimized by compressing it instead of +indexing it. (This should never happen in real life, since +directories that small wouldn't have been indexed, but better safe +than sorry.) + +E2fsck now only updates the master superblock in all cases. This +slightly shortens its run time. + +Ext2ed can deal with directory entries of length 0; previously it +would get stuck in an infinite loop. + +Fsck now has support for reiserfs volumes when parsing LABEL= and UUID= +specifiers. (Sourceforge patch #613447) + +Badblocks will now work correctly on read-only devices such as +CD-ROM's. (Sourceforge patch #600451) + +Updated and clarified man pages. (Addresses Debian bug #167108) + + +E2fsprogs 1.29 (September 24, 2002) +=================================== + +Fixed a bug in e2fsck which could corrupt a directory when optimizing +it (via the -D option) or rebuiliding the hash tree index with a 1 in +512 probability, due to a fence post error. + +Fixed a bug in the LVM support code which caused LABEL='xxx' not to +work correctly. + +Mke2fs now enables the directory indexing flag by default. (Since +this is a compatible feature flag, it's safe to do so.) + +Tune2fs will support setting the directory indexing feature flag. It +will automatically set up the default hash algorithm and hash seed +fields in the superblock. + +If the bone-headed user enters the root filesystem twice in +/etc/fstab, the -R option which skips the root filesystem will skip +all of them. (Addresses Debian bug #159423). Note! This is not a +precedent for dealing intelligently with any other kind of doubled +entry in /etc/fstab! + + +Programmer's notes: +------------------- + +Removed perror declaration in lib/et/internal.h. All modern systems +can be expected to define perror() these days. Besides, the lib/et +code wasn't using perror at all anyway. :-) + + +E2fsprogs 1.28 (August 31, 2002) +================================ + +Add support for the Hashed-Tree Directory Indexing to e2fsck. Support +for setting the htree flag is not included yet, although it can be +manually turned on via the debugfs program. + +Clarified e2fsck error message which is printed when it cannot find +sufficient contiguous block when relcating filesystem metadata. + +Added support for building an EVMS plugin module for ext2/3. This +module is substantially the same as the EVMS module shipping with EVMS +1.1, with one or two bugfixes. E2fsprogs can also build this plugin +for use with EVMS 1.0 (which did not include the ext2 plugin module), +if the configure --enable-old-evms flag is given. + +Fsck will search through EVMS volumes when trying to resolve +filesystem specifications such as LABEL=xxx or UUID=xxx. + +Added a new utility program, /sbin/findfs, which will return +filesystem specifications such as LABEL=xxx or UUID=xxx, and prints +the device name. + +Update and clarified various man pages. (addresses Debian Bug #145044, +#146437, #131350, #151990, #144621, #141938) + +If there are no filesystems specified on fsck's command line, fsck now +treat that as if the -As options were given. Previously it would +simply do nothing. (Addresses Debian Bug #153102) + +Mke2fs no longer treats a failure to be able to clear the MD signature +at the end of the filesystem as a fatal error. (Addresses Debian Bug +#155007) + +The e2p library functions (which are used by lsattr and chattr) now +double check to make sure the file is a regular file or directory +before attempting to use the ext2 ioctls. Some device drivers +unfortunately respond to the ext2 ioctl's with unknown behaviour. +(Addresses Debian Bug #152029). + +The extended attribute handling has been updated to correspond with +the latest V2 bestbits ACL code. + +Fixed bug in e2fsck which caused it to not clear the dtime field when +processing truncated inodes on the orphan list. This could cause data +loss(!) if a filesystem is rebooted before a truncate has been +committed. + +E2fsck now uses red/black trees in pass1b, which removes some O(n**2) +algorithms. This makes e2fsck much faster in the case of severely +corrupted filesystems where a large number of blocks are claimed by a +large number of inodes. (Thanks to the 2.5 IDE device driver for +inspiring this work.) + +Resize2fs has been significantly sped up when shrinking and expanding +a filesystem by a very small number of blocks (for example, when EVMS +is converting a partition to be an EVMS legacy volume). + +Added a new option to e2fsck, -D, which will optimize or compress all +of the directories in the filesystem. + +E2fsck now catches SIGINT and SIGTERM to make sure it will can +properly clean up and only exit at safe points. Fsck will pass +SIGINT/SIGTERM to its child processes, and wait until they have all +exited before it exits. + +The uuid parsing code in the uuid library now properly complains when +an illegally formated uuid is presented to it. (Addresses Debian bug +#152891) + +Restrict use of the 2.4 setrlimit ABI f*ckup to kernels between 2.4.10 +and 2.4.17, since the workaround can cause problems when using a 2.4 +kernel with an old version of glibc built with the 2.2 headers. + +Fixed a bug in mke2fs where it wasn't properly clearing the initial +superblock used by other filesystems. (Addresses Debian bug #147256.) + +Added support for the synchronous directory feature written by Andrew +Morton. + +The debugfs program can delete directories using the rmdir command. + +Add support for 8k and 16k filesystems (for systems with page sizes +that are greater or equal to 8k or 16k, respectively). Note that +these filesystems can not be mounted on x86 systems, or other systems +with only 4k page sizes, due to limitations in the current Linux VM +code. + +Resize2fs requires that the filesystem state be valid and have no +errors; otherwise, e2fsck -f must be run first. (Previously it simply +required that the last fsck time be greater than the last mount time.) + +Configure now defaults the man pages directory to /usr/share/man on +Linux systems. + +E2fsck now offers to truncate inodes which contain too many blocks (so +that i_blocks would overflow. Also fixed handling of large sparse +files. + +E2fsck now more completely checks for symlink validity, including +requiring NULL termination and length checks. + +E2fsck will offer to try forcing a disk write to remap a bad block +after finding a read error when reading a filesystem metadata block. + +Fixed a bug in debugfs which caused the -b and -s options to crash +debugfs, as well as breaking the testb, setb, and clearb functions. + +Added a bmap command to debugfs which calculates the logical to +physical block mapping for a particular inode. + +Fixed a bug in code which checked to see if a device was mounted which +sometimes (rarely) failed in the case of a plain file. + +Fixed a bug in resize2fs where when it reported an error, it would +print a message erroneously indicating that the filesystem had been +resized before it aborted. + +When resizing a plain file which is smaller than the requested size, +resize2fs will attempt to extended the file so that programs like +e2fsck will not complain that the file is too small. + +Resize2fs will print the actual new size of the filesystem when it is +finished resizing. + +Fixed a bug in debugfs where "ls -l" would report incorrectl file type +information on big-endian systems. + + +Programmer's notes: +------------------- + +Fixed collisions with C++ reserved words. + +Added portability fixes for building e2fsprogs on the HURD and AIX. + +Added the ext2ed program for creation of test cases. (ext2ed has many +limitations and bugs which make it unsuitable for production use.) + +The ext2fs_read_dir_block2 and ext2fs_write_dir_block now take a new +flag, EXT2_DIRBLOCK_V2_STRUCT, which will will reverse when the +name_len field is byte swampped on big-endian machines, since in the +V2 structure, name_len is a char field which is doesn't need to be +byte swapped --- except if an old-style kernel had byte-swapped the +name_len field as part of the V1 structure. + + +E2fsprogs 1.27 (March 8, 2002) +============================== + +The warning messages for mke2fs now go to standard error. + +Fixed to make sure "make check" runs all of the test programs with +LD_LIBRARY_PATH set, so that we test the libraries in the build tree. + +The mke2fs program checks the boot sector for the BSD disk label, and +avoids erasing it if it is there. + +Fixed a bug in e2fsck which caused it to core dump if the journal +inode was missing when it was supposed to be there. + +E2fsck now prints ranges in pass 5 when printing deltas for the block +and inode bitmaps. + +Debugfs's "ls -l" command now will print out the file type information +in the directory entry. + +Create man pages and hard links for fsck.ext3 and mkfs.ext3. If +mke2fs is invoked as mkfs.ext3, create the filesystem with a journal. + +Debugfs can now examine the experimental directory indexing +information. + +Fixed bug in debugfs which caused it to core dump if modify_inode is +called without an open filesystem. + +The debugfs lsdel command now runs its output through a pager first. + +When installing manual pages, remove the compressed manual pages first. + +Synchronized with Debian's packaging information for e2fsprogs-1.26-1. + +Fix the 2.4 resource limitation workaround introduced in 1.26 which +actually broke things on mips32, sparc32, and Alpha platforms. + +Updated the I18N code so that calls to setlocate(LC_CTYPE, 0) are made +(which is required by the newer libintl libraries). + +Programmer's notes: +------------------- + +Fixed various gcc -Wall complaints. + +Fixed a few memory leaks in the e2fsck journaling code, and in the +ismounted code checking for a swap device. + +Add new inode I/O abstraction interface which exports an inode as +an I/O object. + +Exported ext2_file_flush as a public interface. + +In ext2_file_write, we now mark the buffer void * argument as a const, since ext2_file_write doesn't modify the buffer. + +Lots of small random portability fixes to make e2fsprogs build under +AIX --- even without the 5L compatibility toolkit, and even using the +uber-crippled AIX native C compiler. + + +E2fsprogs 1.26 (February 3, 2002) +================================= + +Dumpe2fs will keep going now if the bad block inode can't be read. +(Previously it stopped with a fatal error.) + +E2fsck will now give an opportunity to run the journal even if the +recovery flag is not set. This is the default behaviour if e2fsck is +using a backup superblock, since the needs_recovery flag will never be +set in the backup superblock copies. + +E2fsck now automatically finds the backup superblock/group descriptors +even when the primary superblock is completely destroyed for 2k and 4k +filesystems. (Previously it just guessed/assumed that we were dealing +with a 1k filesystem in that case, and users had to manually specify +the backup superblock number.) + +Fixed a bug in e2fsck where it dereferences a null pointer when there +is a problem opening a filesystem in preen mode. + +E2fsck now handles external journals correctly; previously it trashed +the external journal device if the journal needed to be replayed. + +Work around ulimit incompatibility problem caused by recent 2.4 +kernels; the unix IO module will automatically try to set any resource +limits to be infinite on startup. + +Fixed a bug in e2fsck where it wasn't allocating a new block or inode +bitmap if it wasn't present and the blocksize was 2k or 4k. + (Addresses Debian Bug #116975) + +E2fsck will check and fix botched ext3 V1 to V2 superblock updates by +clearing the new V2 fields if they do not make sense or if the ext3 +superblock is version 1 superblock. + +E2fsck will automatically relocate the ext3 journal from a visible +file (i.e., /.journal) to an hidden inode if the filesystem has been +opened read/write. This allows the users to add a journal while the +filesystem is mounted, but the next time the system is rebooted, the +journal file will disappear. This avoids problems with backups, +stupid operators with superuser bits, etc. + +Fix a bug in fsck where it would not support a filesystem type of +"auto" if the device was specified in terms of LABEL=xxx or UUID=xxx. + +Fsck now supports fstab entries of the form "ext3,ext2". It will also +automatically identify reiserfs filesystems. + +The number of processes spawned by fsck can now be limited using the +FSCK_MAX_INST environment variable. + +Fsck now searchs the LVM proc hierarchy to find logical volumes which +should be searched for UUID and label information. + +Work around a bug in 2.4.10+ kernels by trying to unset the filesize +limit if at all possible, when opening a block device. (The filesize +limit shouldn't be applied against writes to a block device.) + +In mke2fs and e2fsck, specifying the -c option twice will now do +a read/write test on the disk. Update the man pages to encourage +using the -c option, and to discouraging running badblocks separately, +since users tend to forget to set the blocksize when running +badblocks. + +Mke2fs now automatically clears the immutable attribute on a +pre-existing .journal file left over from a previous failed attempt to +add a journal to an alreadyy-mounted filesystem. + +Fixed mke2fs's exit codes to consistently indicate when the mke2fs +operation failed. + +Mke2fs now creates the lost+found directory with permissions of 0700, +so that files that had previously lived in protected directory are +safe if they get dropped in lost+found and the system administrator +doesn't deal with immediately. (Addresses Debian #bug 118443) + +Mke2fs and e2fsck (and all programs that use the +ext2fs_check_if_mounted function) will now properly identify that a +device is mounted, even in cases where devfs has confused things with +multiple devices names with the same identity, or if a dim-witted +system administrator has done something stupid like creating device +file aliases in their home directory. Also now checks for swap devices +by using /proc/swaps. (Addresses Debian bug #106622) + +Added a new option (-T) to tune2fs which sets the time a filesystem +was last checked. + +Speed up e2image when creating sparse raw image files by optimizing +away excess lseek() system calls. + +Fix support of large (> 2GB) files when used as a filesystem in +mke2fs, tune2fs, debugfs, and findsuper. + +Debugfs's stat and icheck commands now properly deals with large (> +2GB) files. + +Debugfs's set_super_value command now prints out the list of valid +superblock fields which can be set using the command. + +Debugfs's rm and kill_file command now updates the superblock free block +and inode counts, thus keeping the filesystem consistent. + +Debugfs's lsdel command now takes an optional argument which allows +the user to only see the most recently deleted files. + +A new command (undel) was added to debugfs which automates +undeleting a deleted inode and linking it back to a directory. + +Debugfs's ls command now takes a new option, -d, which lists +deleted directory entries. + +Debugfs's testb, freeb, setb, and find_free_block commands now take an +optional count argument. + +Add support for a new ext2 file attribute, EXT2_NOTAIL_FL, which will +be used to signal that a particular inode should not be eligible for +tail-merging --- this is needed for programs like LILO. + +The findsuper (an unreleased, uninstalled utility program) has been +improved to add extra validity checks and to add a progress meter. +(It is still an unsupported program; the officially supported way to +recover from a trashed partition table is to use gpart; findsuper is +for wizards only. :-) + +Debugfs was fixed to compile with "configure --disable-swapfs". + +Cleaned up various manual pages. (Addresses Debian bug #119624, #120171) + +Added new translation file for Turkish. + +Programmer's notes: +------------------- + +Fix general gcc -Wall complaints. + +E2fsprogs (mostly) works with the dietlibc. + +The programming texinfo file has been expanded to include description +of additional libext2fs functions. (Still not compeltely done, but a +lot of the more important functions have been documented.) + +Added a umask structure to struct_ext2_filsys, which currently only +modifies the behaviour of ext2fs_mkdir(), but if we add any file +creation functions to libext2fs, we should also make sure they respect +the umask setting. + +The build-rpm script was fixed to be a bit more safe. + +The tests' Makefile now has a way of automating test case creation +for e2fsck, using "make testnew". + +Created a new function, ext2fs_dir_iterate2 which passes more +information to the callback function (identical to the one used by +ext2fs_dblist_dir_iterate). The directory iterator functions take a +new flag, DIRENT_FLAG_INCLUDE_REMOVED, which will return deleted +directory entries. If the directory entry is deleted, the callback +function will be called with the entry paraemter set to +DIRENT_DELETED_FILE. + +Added new functions, ext2fs_inode_alloc_stats and +ext2fs_block_alloc_stats, which takes updates block/inode allocation +statistics in the bitmaps, block group descriptors, and superblock +when inodes or blocks are allocated or deallocated. + + +E2fsprogs 1.25 (September 20, 2001) +=================================== + +This is primarily a bug-fix release; no new features were added, but +there are a number of embarassing bug fixes and cleanups applied. + +Fix a bug mke2fs which causes stack garbage to be written to disk when +zapping disk sectors. (This bug could cause mke2fs to core dump for +some kernels, I suspect with security enhancement patches.) + +Remove unneeded #include of <linux/config.h> which was breaking +building e2fsprogs on the Hurd. (Addresses Debian bug #112414.) + +Updated tune2fs man page to reflect the fact that adding or removing a +journal doesn't require running e2fsck. + +Remove use of AC_REQUIRE from autoconf which had been used to prevent +AC_CANONICAL_HOST from being called twice; unfortunately this causes +recent autoconf to bomb out since they don't allow AC_REQUIRE to be +used outside of autoconf macros. Fortunately, it doesn't seem to be +necessary any more, anyway. + +E2fsck will now not fall back to an alternate superblock if the user +specifies the superblock location explicitly on the command-line. +This allows easier recovery from a situation where the primary +superblock and block groups are slightly corrupted, but the backup +superblocks are completely broken. + +Fix problem which caused compile_et and mk_cmds to blow up if +e2fsprogs was in a directory with a pathname that contained spaces. + +We are now more paranoid about checking the entry in /etc/mtab to make +sure the filesystem is really mounted, since some broken distributions +(read: Slackware) don't initialize /etc/mtab before checking non-root +filesystems. (Slackware also doesn't check the root filesystem +separately, and reboot if the root filesystem had changes applied to +it, which is dangerous and broken, but there's nothing I can do about +that.) + +Make UUID library C++ friendly by adding appropriate extern "C" +declarations and using const in the function declarations. + +Fix up the com_err texinfo file so that it can product a valid info +file (previously, it could only be used to generate paper +documentation using texinfo.tex). + + +E2fsprogs 1.24a (September 2, 2001) +=================================== + +Fix brown-paper bug in mke2fs which caused it to segfault when +printing the version string. + + +E2fsprogs 1.24 (August 30, 2001) +================================ + +Revert the BLKGETSIZE64 support, since for some distributions, this +ioctl has been used by an unofficial kernel patch to update the last +sector on the disk, and this was causing disk corruption problems as a +result. + +Mke2fs is now more careful about zapping swap space signatures and +other filesystem/raid superblock magic values so that programs like +mount who try to use hueristics to determine the filesystem type of a +partition are less likely to be confused. + +E2fsck will no longer complain if the the mode of EXT2_RESIZE_INO is a +regular file (since Andreas Dilger's on-line resizing tools will set +its mode bits). + +Fixed some minor texinfo, man pages nits for spelling errors, +texinfo warnings, etc. (Addresses Debian bug #110621.) + +E2fsprogs program no longer print the filesystem version number +(i.e. 0.5b), since it only confuses people and doesn't serve any real +purpose. + +E2fsck will once again compile under libc5, since it will supply its +own version of strnlen if necesssary. + +mke2fs and tune2fs will allow the use of UUID= or LABEL= specifiers +when specifying the external journal device. tune2fs will also search +devices looking for the externla journal debice when removing. + +E2fsprogs 1.23 (August 15, 2001) +================================ + +Add initial support for extended attributes (EA); e2fsck will +correctly handle a filesystem with EA's and check the EA blocks for +corruptions. + +E2fsck's symlink sanity checking has been cleaned up. It now checks +the i_size value of fast symlinks, and checks for immutable flags +being set of symlinks, etc. + +E2fsck now offers to clear inodes which are special files that have a +non-zero i_blocks or i_size field. (The i_size field check was in the +previous version of the code, but due to a bug it didn't offer to +clear the inode unless i_size and i_size_high were both non-zero.) + +E2image can now create "raw" image files, which only contain the +filesystem metadata placed in a spare file so that e2fsck, dumpe2fs, +debugfs, etc., can be run directly on the raw image file. + +Add support for the 64-bit block device patches. + +Fixed bugs in creating external journals with a 1k blocksize. + +Add initial support for external journals (so long as the external +journal only supports a single filesystem) in e2fsck. + +Remove requirement for needing to run fsck on a filesystem after +removing a journal (either internal or external). + +The man pages now document how to create and manage external journals. + +Speed up the check of an ext3 filesystems by avoiding a needless flush +of all of the superblock and block group descriptors. + +Speed up creating an internal journal using tune2fs in the case where +the filesystem has a lot blocks already allocated. + +Tune2fs has been fixed to make sure that only error messages go to +stderr, and normal message go to stdout. (Addresses Debian bug #108555) + +Fixed a minor bug in mke2fs; if -O none is passed to mke2fs, it will +now not set the sparse_super feature. (Addresses Debian bug #108165) + +Add support in fsck for the filesystem type "auto". + +Fsck -A will not try to interpret device names for filesystems which +have a pass number is 0. (Addresses Debian bug #106696). + +Fsck prints a warning message if now valid filesystems are passed to +it. (Addresses Debian Bug #107458.) + +E2fsck now gives an explicit warning if there filesystem still has +errors at the end of the run. (Addresses Debian bug #104502) + +E2fsck will set the EXT2_ERROR_FS flag if the journal superblock +reflects an error. E2fsck will also not run the orphan list if the +filesystem contains errors, since the orphan list might be corrupted. + +E2fsck now prints the number of large files when given the -v option. + +Fixed minor memory leaks in e2fsck. + +Some minor man pages updates. (Addresses Debian bug #30833, #108174) + + +E2fsprogs 1.22 (June 22, 2001) +============================== + +Fixed a bug in e2fsck's handling of orphan inodes which are special +files (i.e., block/character device files, named FIFO's, etc.). + +Fixed a bug accidentally introduced in e2fsprogs 1.21 which caused +tune2fs to fail at adding a journal to a mounted filesystem. + +Fixed a few big-endian bugs in e2fsprogs + * The directory block functions were accidentally reporting + some directories as corrupted when they weren't. + * If e2fsprogs is compiled --disable-swapfs, the C language + equivalents weren't being included for big-endian platforms. + (Fixes Debian bug #101686). + +Fixed a Hurd compilation problem. (Addresses Debian bug #101361) + +Programmer's notes: +------------------- + +Use platform independent method of defining the BLKFLSBUF and FDFLUSH +ioctls, and allow them to be defined for non-i386 platforms. + +The uuid.h header file is now protected against multiple inclusions. + +E2fsprogs is now being developed using BitKeeper. Changed the test +scripts to deal with BK's stripping CR characgters from text files, +and changed the top-level Makefile.in to avoid including BitKeeper +files when generating the source tarball. + + +E2fsprogs 1.21 (June 15, 2001) +============================== + +Added new configure flags which allow a subset e2fsprogs to be built; +this is most useful for boot floopies, since the resulting shared +libraries and programs are slimmed down by removing features that +aren't necessary for a boot floppy. The new flags that were added +are: --disable-swapfs, which removes support for byte swapping old +legacy PPC/68k filesystems, --disable-debugfs, which removes support +for debugfs from the libext2fs library, --disable-imager, which +removes support for the e2image program, and --disable-resizer, which +removes support for resize2fs. + +E2fsck now prints the number of mounts or days elapsed since the last +check when e2fsck is forced to check an otherwise clean filesystem. + +Tune2fs now prints an informative message about how often a filesystem +will be checked when adding a journal to the filesystem, to remind the +user that he/she may want to adjust those parameters using tune2fs +-c/-i. + +Worked around hurd brain-damage which causes e2fsck to sometimes +believe a filesystem is the root filesystem based on device numbers +(since Hurd doesn't have dev_t's, which is arguably a POSIX.1 +violation). + +Fixed a bug introduced in 1.20 which caused e2fsck to abort with an +erroneous error with the -F option was specified. + +Fixed a ext3 recovery bug in the revoke handling; synchronized with +ext3 0.7a. + +Fixed two bugs in e2fsck's handling of dup block handling, dealing +with relatively uncommon edge cases: a directory with an indirect +block which is claimed by another file, and when the last inode in the +filesystem has blocks claimed by another file. + +E2fsck now checks to see if the i_size field of a fast symlink is too +big, and offers to clear the symlink if so. + +E2fsck now checks to see if i_size_high of special files is non-zero, +and offers to clear i_size_high. + +Fix e2fsck's handling of incompatible journal flags so that the user +has chance to abort, and then has the option to clear out the journal +entirely. (Addresses Debian bug #98527.) + +Fixed a bug in fsck which could cause it to core dump if a mix of +standard and non-standard device names are used in /etc/fstab. +(Debian bug #100559) + +Fixed a bug in debugfs which caused read errors when copying a file to +not be noticed. + +The debugfs set_super_value command can now modify the s_lastcheck field. + +Fixed a bug in lsattr and chattr which was accidentally introduced in +1.20 to support > 2GB files; both lsattr and chattr wasn't reading +directories correctly because the change modified the layout of struct +dirent to be incompatible with the libe2p shared library. + +Cleaned up the mke2fs manual page and included a discussion about why +it's good to periodically check the filesystem even when journaling is +enabled. + +Programmer's notes: +------------------- + +Fix general gcc -Wall complaints. + +The types needed by the ext2 header files are now provided by +lib/ext2fs/ext2_types.h, instead of include/asm/types.h. + +Integers are now preferred to longs when trying to find a 32-bit type +in ext2_types.h. Also, if linux/types.h has already been defined, +don't try to redefine the types. + +Fixed make depend script so that it automatically corrects the +pathname cleanups performed by make -M, so I don't have to fix them up +by hand. + +Fixed the d_loaddump test case to be more robust, and not depend on +bash'isms. + +Removed debugfs's dependence on pread(), which was accidentally +intrudced in e2fsprogs 1.20 + +Fixed a performance bug in the libext2fs's icount routine; the size +estimate of the icount array was incorrectly being calculated. + +Removed use of the badblocks compatibility functions in the e2fsprogs +programs. + +Added paranoia code which protects against strange cases where /etc +isn't on the root filesystem, or if /etc/mtab doesn't exist. + +The header file ext2_types.h is now installed. + +Autoconf is used to determine when we are on big-endian machines, +instead of doing run-time tests, to save a few bytes of code. + +The ext2fs_mark_generic_bitmap and ext2fs_unmark_generic_bitmap +functions are no longer inline functions, which saves space and +doesn't really cost any real performance. + +The ext2fs library no longer depends on the e2p library. (What need +there was of it --- namely, fsetflags, was coded in-line). + +Fixed the makefile so that lib/ext2fs/ext2_types.h is generated even +when the user is stupid and tries compiling the package using "make +install" as root. + +Miscellaneous code cleanups: + * Added missing files from Makefile.in's SRCS file, so that + their dependencies would be properly calculated. + * Removed redundant code + * Fixed comments in code + * Removed no-longer unneeded argsused #pragma. + + +E2fsprogs 1.20 (May 20, 2001) +============================= + +Add support for replaying the ext3 journal purely in user mode, +including handling the orphaned inode list. Used code contributed by +Andreas Dilger, with bug fixes and the orphaned inode handling done +by Theodore Ts'o. + +The mke2fs and tune2fs programs can create or modify a filesystem to +include an ext3 journal. Tune2fs also can be used to remove an ext3 +journal from a filesystem. + +E2fsck will now check for the existence of a linked list of orphan +inodes in the superblock, and clear those inodes before starting the +rest of the filesystem check (but after the journal playback). + +E2fsck now validates the file descriptor passed to the -C option, +which saves against the completion bar getting written to an +unexpected location, such as the disk being checked. (Debian +bug/wishlist #55220) + +E2fsck will now bump the filesystem revision number from zero to one +if any of the compatibility bits are set. + +Fixed a bug where a badly corrupted directory on a big endian system +could cause e2fsck to die with a bus error. The +ext2fs_read_dir_block() and ext2fs_process_dir_block() functions in +the ext2 library now does alignment sanity checks on the rec_len field +of the directory entry before using it. + +The ext2 library has been enhanced to make tune2fs safe to run on +mounted filesystems. (Users could usually get away with using tune2fs +on mounted filesystems before, but with the advent of ext3 and +journaling, it became important to make tune2fs was *really* safe for +use even when the filesystem being modified is mounted.) E2label is +now implemented by tune2fs using an argv[0] dispatch, so that e2label +is also now safe for use on mounted filesystems. + +Added a new program, e2image, which creates a backup of critical ext2 +filesystem data structures. The generated image file can be examined +using dumpe2fs and debugfs. In the future, e2fsck will be able to use +the image file to help recover very badly damaged filesystems. + +Fixed a number of LFS bugs in e2fsck; very, very large (> 2**42) files +no longer cause e2fsck to bomb out. Also treat files > 2GB as being +large file when deciding whether or not the filesystem has large files. + +Fixed lsattr and chattr so that they work correctly on large files. +(Fixes Debian bug #72690.) + +Removed limitation in get_device_size() which imposed a one terrabyte +filesystem limitation. (Most 2.2 kernels still have a signed int +problem which cause 1 TB block device limitation. Fortunately, the +kernel patches to fix this are much easier than fixing the 2TB +limitation in the kernel. :-) + +A max_mount_count of zero is now treated as if no mount count were +set. (Previously, no mount count was indicated by using -1, and a +mount count of zero caused e2fsck to always be run.) + +Mke2fs supports two new filesystem types largefile and largefile4. + +Mke2fs now adds some randomness in s_max_mount_count so that multiple +filesystems won't be all checked at the same time under normal +operations. + +Fixed bug in the progress bar printing code which could cause e2fsck +to core dump on an illegal filesystem. + +Fixed bug in fsck which could allow more than one instance of e2fsck +to be printing a progress bar. (Debian bug #65267) + +Fsck using a UUID or a LABEL specifier will work even if devfs is +compiled into the kernel and not mounted. If the pathnames in +/proc/partitions are incorrect, fsck will search /dev for the correct +device (using the new ext2fs_find_block_device library function). +Fsck now also checks the RAID devices first so that they are properly +found when they are in use. Support has also been added to support +additional IDE disks and the DAC 960 device names. (Debian bug #94159) + +Fixed a bug in fsck which caused it not deal properly with 16 +byte long filesystem labels. + +Fsck's -t option has been made a lot more flexible. The semantics for +what happens if a comma-separated list to fsck has been regularized, +and it is now possible to filter what filesystems will get checked +based what is in the filesystem's fstab entry's option field. (Debian +bug #89483.) + +The dumpe2fs program can now print out the group description +information in hex, and also prints the location of the superblock and +block group descriptor for those block groups that have them. + +Mke2fs now clears the ext2 superblock before it starts creating a +filesystem, so that the superblock magic number is only written if the +filesystem creation process successfully completes. + +The debugfs program's stat command now pretty-prints the blocks used +by an inode so that it's more compact and informative. + +The debugfs stats command now uses the same libe2p code (which is used +by dumpe2fs) to print the superblock header information. This is more +complete, and it avoids a bit of code duplication. + +Added a new debugfs command, set_super_value (ssv) which allows the +user to set arbitrary superblock fields. + +Debugfs was extended to support inode numbers in hex (by prefixing +them with 0x), and so that modify_inode can set the inode generation +number. Also, there is now a new function command called logdump +which will dump an ext3 journal. + +Fixed a bug in debugfs so that quitting out of the pager doesn't kill +debugfs. + +Debugfs's dump command now stops immediately upon reporting a disk +read error. (Fixed a bug in ext2fs_file_read library routine which +caused debugfs not to stop.) (Debian bug #79163) + +On systems with /proc/mounts (mainly Linux systems), /proc/mounts is +checked before /etc/mtab is used, since /proc/mounts is more likely to +be accurate. + +Added portability fixes for Solaris and Linux/ia64. + +Various manual pages were clarified and cleaned up. (Fixed debian +bugs #63442, #67446, and #87216) + + +Programmer's notes: +------------------- + +The e2fsck message printer now supports %Iu and %Ig, which will print +out the inode's user and group owners, respectively. + +E2fsprogs now includes its own version of include/linux/ext2_fs.h, so +that no longer dependent on the system having the correct version of +the kernel header files. + +Added a new function to libext2, ext2fs_find_block_device(), which +searches the system (i.e., /dev, /devfs, /devices) for a pathname to a +device given its device number. + +Added a new function to libext2, ext2fs_sync_device, which centralizes +all of the places which might try to use the BLKFLSBUF or FDFLUSH +ioctls (and usually failing to define them since the system header +files don't usually do this for us, and we're trying to avoid usage of +kernel include files now). + +Added new utility programs in tests/progs: random_exercise and +hold_inode. They aren't built by default; they're useful for +exercising ext3 filesystem code. + +Added a new ext2 filesystem flag, EXT2_FLAG_SUPER_ONLY, which causes +the filesystem close functions to only update the superblock, and to +not touch the block group descriptors. Needed by tune2fs when +modifying a mounted filesystem. + +Got rid of struct ext2fs_sb and replaced it with the standard struct +ext2_super_block from include/linux/ext2_fs.h. Note: this may break +source (but not binary) compatibility of some users of the ext2 +library. Those applications should just simply do a global search and +replace of struct ext2fs_sb with struct ext2_super_block, and include +the new header file <ext2fs/ext2_fs.h> which defines it. + +The ino_t type has been renamed ext2_ino_t to protect applications +that attempt to compile -D_FILE_OFFSET_BITS=64, since this +inexplicably changes ino_t(!?). So we use ext2_ino_t to avoid an +unexpected ABI change. + +The Makefiles have been reworked so that "make check" can be run from +the top-level Makefile. + +Fix general gcc -Wall complaints and removed dead code. + +Remove use of NOARGS, because we assume everyone does ANSI C these +days. + +Added build-rpm script from sct. + +New functions ext2fs_image_{inode,super,bitmap}_{read,write} added +to support e2image. + +New function ext2fs_flush_icache which must be called if the +application program modifies the inode table blocks without going +through ext2fs_write_inode() interface. + +New ext2fs_check_mount_point() function, which will return the mount +point of a device if mounted. + +The io_channel abstraction now has an optional interface, +io_channel_write_range, which allows specific byte ranges to be +written. + +The unix_io IO channel now supports write-through caching, so that +journal creation is more efficient. + +Added x86 assembly language routines to support byte swapping, to +reduce executable size. + +Fixed bug in the utility program subst so that it's possible to +replace a substitution variable with a zero-length string. + +Fixed numbering e2fsck pass1 problem numbers; an extra zero had +slipped into some of the problem number. + +E2fsprogs 1.19 (July 13, 2000) +============================== + +Release the resize2fs program since the timeout before it could +be released under the GPL has finally expired. + +Add experimental support needed for the ext2 compression patches. +This requires compiling e2fsprogs with the --enable-compression flag +to the configure script. + +Added ext3 journalling support. E2fsck will run the journal (if +necessary) by temporarily mounting the filesystem. /sbin/fsck.ext3 is +installed as a symlink to e2fsck. Fsck has been taught about ext3, +and treats it the same as ext2 in terms of the progress bar logic. +Dumpe2fs will display the superblock journaling information if the +filesystem has a journal. The ext2 library will now permit opening an +ext3 filesystem with the recovery flag set. This is necessary for +on-line dump's to work correctly, but there may be issues with this +working well since ext3 is much less agressive about syncing blocks to +the filesystem, since they're safe on the journal. + +Tune2fs and e2fsck have been changed to allow the mount_count check to +be disabled by setting max_mount_count to -1. (This was already +supported by the kernel.) + +Create a symbolic link for fsck.ext3, since the e2fsprogs utilities +are used for ext3 as well. + +Added internationalization support for e2fsprogs; must be enabled +by passing --enable-nls to configure. + +Always use the provided ext2fs header files to insulate ourselves from +kernel version changes. Which include files are used by e2fsprogs +have also been cleaned up to improve portability. + +Limit the number of times that e2fsck updates the progress bar so that +people who are booting using a 9600 baud console don't get swampped by +too many updates. + +Improved the loop detection algorithm in e2sck's pass #3 so that it is +much, much faster for large filesystems with a large number of +directories. + +The memory footprint for e2fsck is now slightly smaller than before. + +E2fsck now checks if special devices have a non-zero size, and offers +to clear the size field if it finds such an inode. + +E2fsck now checks if special devices have the append-only flag set, +and offers to clear the inode. + +E2fsck now properly handles some "should never fail" cases during a +bitmap copy in pass5. + +E2fsck now properly prints control characters in filenames as ^A .. ^Z. + +E2fsck now calculates the correct location of the backup superblock in +the case of filesystem blocksizes > 1k. + +Fixed a bug in e2fsck's calculation of the number of inodes_per_block +which normally didn't cause problems under most filesystem parameters, +but could cause a valid superblock to be rejected in extreme cases. +Other checks for validating superblock values were made more +stringent. + +Added non-destructive write testing to the badblocks program, courtesy +of David Beattie. The badblocks also now has an option to input the +current set of bad blocks, so that known bad blocks are skipped to +speed up the badblocks test. There is also a persistent rescan +feature which causes badblocks to run until it has completed some +number of passes without discovering any new bad blocks. + +Badblocks now checks to see if the device is mounted and refuses to do +the tests involving writing to the device if it is mounted. Also, +badblocks now allows the number of blocks to be checked to be +defaulted to the size of the partition. + +Fixed a bug in fsck which didn't allow non-root users to be able to +check filesystems if there were any LABEL= or UUID= entries in +/etc/fstab. + +The Hurd doesn't support the filetype filesystem feature. The mke2fs +program now makes sure that for the Hurd, the filestype feature is +turned off. E2fsck will check to see if the filetype feature is +turned on for Hurd filesystems, and offer to turn off the feature. + +Mke2fs now has a safety check to make sure the number of blocks do not +exceed 32 bits even on a 64 bit platform. + +Really fixed a bug in fsck to allow "fsck -As" to run interactive +fsck's. (For those people who like to do interactive fsck's in the +/etc/rc scripts!?!) + +Debugfs has a few new features: the rdump command, which will do a +recursive dump of a directory and all of its contents, and the lcd +command which does a local chdir (much like the ftp command of the +same name). In addition, the debugfs program and the open_filesystem +command now takes three new options: -b and -s, which allows the +blocksize and superblock location to be specified, and the -c option +which is used in catastrophic situations where the block group +descriptors are corrupt. If the -c option is specified, debugfs will +skip trying to read in the block and inode bitmaps. + +Debufs's lsdel command was fixed to handle bad blocks in the inode +table. + +A Y2K bug in debugfs's "ls -l" handling was fixed by switching to use +4 digit years. + +General improvements in error messages + + - Mke2fs prints a sane error message if the partition size is zero + (usually because the partition table wasn't reread by the + kernel due to the partition being busy), instead of "invalid + argument passed to ext2 library while initializing superblock". + + - Fsck now prints more self-explanatory message if an invalid UUID= + or LABEL= specification is passed to it. + +UUID library changed to use the LGPL. + +Fixed a bug in the UUID library where very rapid calls to the +time-based UUID generator could cause duplicate UUID's to be returned. +This was not a problem for e2fsprogs, but it could be a problem for +other users of the library. + +Make the UUID library more robust in the face of missing or an +improper /dev/urandom or /dev/random files. + +Added some random portability fixes for Solaris. + +Some minor man page updates. + +Fixed a memory leak in the ss library. + + +Programmer's notes: +------------------- + +We now try to use lseek64 and open64 from the LFS if possible. + +The 3rd parameter in e2p's print_flags is now a flags word, instead of +a boolean option. + +The mark and unmark bitmap functions now return the previous state of +the bit that was being changed, which is useful for some speed +optimizations. + +The following functions have been added to enhance the badblocks list +handling in libext2fs: ext2fs_write_bb_FILE, ext2fs_read_bb_FILE2, and +ext2fs_badblocks_equal. + +The ext2 header files now have the latest journalling fields to the +superblock. + +The ext2fs_mkdir function in libext2fs now properly backs out of error +conditions robustly. + +Cleaned up makefiles: + - to cleanly compile with the -j flag. + - so distclean removes all generated files. + - so in case of an error while installing header files, the make aborts. + +Fix test_script so that it works correctly when compiling in the +source directory. + +The random UUID generation routine has been made slightly better in +the case where /dev/random doesn't exist. (Use of randomly-based UUID +is still not recommended if /dev/random doesn't exist, however; it's +better to use the time/ethernet MAC address UUID in this case.) + +Clean up the build process so it's more friendly in case of missing +directories. + +The ext2fs header file can now be #include'd into C++ programs. + +The e2p.h header file is now installed. + +Added workaround to a gawk 3.0.5 bug in lib/ss/mk_cmds. + + + +E2fsprogs 1.18 (November 10, 1999) +================================== + +Fix a core dumping bug in e2fsck if an imagic inode is present or +(more rarely) if the filesystem is badly corrupted enough that e2fsck +has to restart pass 1 processing. E2fsck now closes the filesystem +before freeing a large number of its data structures, so in the case +of future memory faults, at least the fixed filesystem will be fully +written out. + +If a filesystem doesn't support imagic inodes, and e2fsck discovers an +imagic inode, it will offer to clear the imagic flag. + +E2fsck will now offer to clear the immutable flag on special files +(device/socket/fifos) when running it in non-preen mode. + +E2fsck will now set the filetype when creating /lost+found, and when +connected orphaned inodes to /lost+found. + +Debugfs's ncheck and icheck commands now handles the case where there +are bad blocks in the inode table without bombing out. + +The badblocks list processing code has been made more efficiently for +appending a large number of (ordered) badblocks to the badblocks list. + +Some minor man page updates. + +Fsck now allows interactive e2fsck's when using fsck -As (not a common +mode, but some people like to do this in boot scripts for silly reasons). + +Programmer's notes: +------------------- + +The internal e2fsck problem code for PR_2_SPLIT_DOT was fixed to meet +with the problem code convention. + +The badblocks list regression test program has been updated to work +with previously made API name changes. + +The ext2fs_free() command now uses the new badblocks API to avoid +using the compatibility layer. + +Added new regression test cases; the run_e2fsck test script now +supports the ability for a test case to run a prepratory command +before running e2fsck. + +E2fsprogs 1.17 (October 26, 1999) +================================= + +Fixed nasty typo in fsck which caused parallelized fsck's to go into an +infinite loop. + +Fixed a bug in fsck where it used strncmp to compare a binary UUID, +thus potentially causing problems if a binary UUID contained a NULL +character. + +E2fsck now uses stricter checks for directory entries in pass 2: +zero-length filenames are not allowed; neither are 8 byte long +directory entries. + +The debugfs "dirty" command now clears the filesystem valid bit. +(Previously this just set the dirty-as-in-needs-writing-out-to-disk +bit in the in-core superblock image. The new functionality is more +what the user expects, and is more useful.) + +Added a debugging hook to test parallel fsck; if the environment +variable FSCK_FORCE_ALL_PARALLEL, then filesystems on the same drive +will be checked in parallel when they normally would not be. + +Programmer's notes: +------------------- + +Fixed some #ifdef's for compilation under the Hurd OS. + +Fixed minor W2K compatibility problems. + +Fixed some miscellaneous GCC warnings. + + +E2fsprogs 1.16 (October 22, 1999) +================================= + +Fixed a race condition bug in fsck; when printing a progress bar, if +checking multiple filesystems in parallel, it was possible for fsck to +send e2fsck a SIGUSR1 signal before e2fsck had installed its signal +handler, which would cause it to terminate with a signal 10. + +E2fsck now properly handles filesystems that have the +INCOMPAT_FILETYPE feature turned on. It can be used to convert a +filesystem into using or not using FILETYPE feature. + +E2fsck now properly handles filesystems that have the IMAGIC feature +turned on (this is used on Linux AFS servers). + +The mke2fs program now creates filesystems that have the filetype and +sparse_superblock features enabled by default, unless it is run on a +pre-2.2 kernel. These features are not supported by a pre-2.2 kernel, +so there is now a new flag -O which allows the user to specify with +which features she would like to create the filesystem; "mke2fs -O +none" will create a filesystsem compatible with 2.0 kernels. + +The tune2fs program now has a -O option which allows the user to set +and reset "safe" filesystem features. Currently, the only ones which +allows to be modified are the filetype and sparse_superblock features. +Note setting or clearing either feature will require running e2fsck on +the filesystem afterwards. (n.b. Clearing the sparse_superblock feature +requires that there is enough free space on the filesystem for the +extra superblocks which will be created by e2fsck.) + +Debugfs can now set and print filesystem features in the superblock +using the "features" command. Dumpe2fs will print out the complete +set of features when listing the superblock. + +Dumpe2fs has new options -f (force) and -h (header-only). + +Fixed a bug in e2fsck which could cause the PROGRAMMING ERROR/bonehead +message to come up. This could happen when decrementing or +incrementing a link count could result in an overflow. + +Fixed a bug in e2fsck where the block count on the lost+found +directory would not be properly incremented when the directory was +expanded to the point where an indirect block needed to be allocated. + +E2fsck now makes some additional sanity checks on the superblock to +avoid crashing or giving a memory allocation error if some of the +values in the superblock are unresonable (but the superblock otherwise +looks valid). + +Fixed a bug in e2fsck where a very badly corrupted filesystem might +require two passes to completely fix the filesystem. This happened if +an inode claimed blocks that was part of the filesystem metadata +(typically, when garbage was written into an inode table or indirect +block, since this kind of filesystem corruption normally doesn't +happen otherwise). + +On the Alpha, glibc declares st_flags although it isn't actually used; +the configure script was improved to detect this case so that +e2fsprogs can avoid using the non-functional stat field. + +The manual pages were updated to use a more consistent formatting +style consistent with standard Unix man pages. Mke2fs's man page +added documentation for a few previously undocumented options. + +Fixed minor display bugs in tune2fs and mke2fs. + +Programmer's notes: +------------------- + +Improved portability of e2fsprogs to non-Unix systems (in particular, NT). + +Added features to parse and print feature strings into the e2p library. +(e2p_feature2string, e2p_string2feature, e2p_edit_feature). + +ext2fs_mkdir() and ext2fs_new_dir_block() now creates directories +whose directory entries contain proper filetype information if the +filesystem supports it. + +ext2fs_link() now uses the low 3 bits of its flags parameter to pass +the directory entry filetype information. This is used to set the +directory entry filetype information if the filesystem supports it. + +Fixed a bug in ext2fs_expand_dir() where the block count in a +directory's inode would not be properly incremented when the directory +was expanded to the point where an indirect block needed to be +allocated. + + +E2fsprogs 1.15 (July 18, 1999) +============================== + +Add configuration checks so that e2fsprogs will compile cleanly on +Linux 2.3 kernels that have renamed i_version to i_generation. + +E2fsck now prints a progress/completion bar (and not just a simple +spinner) if the -C0 option is requested or if it receives a SIGUSR1 +signal. Fsck will automatically manage the (potentially muliple) +e2fsck processes to print completion bars if it is given a -C option, +with the right thing happening if multiple filesystems are being +checked in parallel. + +Mke2fs now has better automatic hueristics to determine the filesystem +parameters to be used for a particular filesystem. Added a new option +-T which allows the user to specify how the filesystem is to be used, +which helps mke2fs do a better job selecting the filesystem parameters. + +Mke2fs now creates revision 1 filesystems by default, and with the +sparse superblock feature enabled. The sparse superblock feature is +not understood by Linux 2.0 kernels, so they will only allow read-only +mounts of filesystems with this sparse superblocks. + +Fix bug where if /dev/null couldn't be opened (should never happen), +e2fsck would hang in a tight loop. + +Make e2fsck handle the case where /lost+found isn't a directory. + +E2fsck now uses mallinfo if it exists to get accurate statistics about +its memory usage. + +Fix bug in e2fsck where it wouldn't check to see if a disconnected +inode had any problems before connecting it to /lost+found. + +Add check to e2fsck so it makes sure that total number of inodes in +the filesystem is a sane number. + +Fix fencepost error when clearing an the end of the block bitmap which +caused the last block in the bitmap not to get cleared. + +Cleaned up a number of messages in e2fsck: + * The message "Group's #'s copy of the group descriptor..." + was fixed so that the correct number would be displayed. + * Added missing space in the "disk write-protected" error messsage + * Cleaned up the error message printed when a non-interactive + e2fsck needs to abort a check because the filesystem + appears to be mounted. + +Added a new command-line utility, uuidgen, which will create and print +a UUID. + +Make debugfs's icheck command more robust by checking to make sure an +inode has valid blocks before interarting over the inode's blocks. + +UUID generation now uses a random-based scheme whenever possible to +prevent potential privacy problems. + +Man pages for all of the UUID functions in the lirbary were added. + +Fixed bug in fsck so it won't coredump if a filesystem not in +/etc/fstab is given to it. + +Fsck now understands the UUID=xxxx and LABEL=yyyy forms in /etc/fstab +that most of the other mount utilities understands. + +Mke2fs will make a filesystem even if it appears mounted if the force +option is given. + +Dumpe2fs has new command-line options which allow a filesystem expert +to specify the superblock and blocksize when opening a filesystem. +This is mainly useful when examining the remains of a toasted +filesystem. + +The badblocks program has been updated to display correctly on disks +with large block numbers. + +The badblocks program no longer gives spurious errors when errors +occur on non-block boundaries, which is common if the blocksize is +larger than 1k. + +Mke2fs will sync the disk device every MKE2FS_SYNC block groups if the +MKE2FS_SYNC environment variable is set. This is to work around a VM +bug in the 2.0 kernel. I've heard a report that a RAID user was able +to trigger it even using a 2.2 kernel, but hopefully it will not be +needed for most Linux 2.2 users. + +Fixed miscellaneous documentation and man pages. + +Programmer's notes: +------------------- + +Cleaned up functions such as pass1_get_blocks, pass1_read_inode which +in e2fsck's pass1.c really should have been static. + +The return value of the uuid_compare() function was changed to make it +match with the convetions used by strcmp, memcmp, and Paul Leach's +UUID sample document. + +The "make depend" process has now been made more automated; it now +automatically word-wraps the dependencies, and only replaces source +Makefile.in if there has been a change in the dependencies. Also, a +top-level "make depend" now recurses through all the subdirectories +automatically. + +The Makefile in .../util has been changed so that subst is built using +the native C compiler during a cross-compilation, since the subst +program is only used during the build process. Also add an explicit +rule to build util/subst by cd'ing to the correct directory and +running Makefile. + +The man directories are defined in terms mandir, so that the configure +script can override the location of the manual pages. + +The config files have been updated to recognize new machine types for +both the i386 and alpha families. + +Fsck has been modified so that it will accurately create an +fsck_instance even when the noexecute flag is set. This allows for +accurate debugging of the fsck pass structure. Also, when the verbose +flag is given twice, fsck will print debugging information about when +fsck is waiting for jobs to finish. + + +E2fsprogs 1.14 (January 9, 1999) +================================ + +Fix the fstab parsing code so that it can handle blank lines and +comment characters. Also, missing pass numbers need to be treated as +zero. + +Fixed a bug in e2fsck where under some circumstances (when e2fsck +needs to restart processing after fixing an egregious inconsistency) +it would try to access already freed memory. + +E2fsck now prints non-printable characters in directory entries and +pathnames using '^' and 'M-' notation. + +Fixed chattr so that it will ignore symbolic links when doing +recursive descent traversals. For both chattr and lsattr, no longer +print the version string unless the -V option is given. + +Allow the system administrator to directly specify the number of +inodes desired in the filesystem, for some special cases where this is +necessary. + +Fix portability problems so that e2fsprogs can be compiled under Linux +1.2 systems and Solaris systems. + +Update the config.guess file with a more recent version that will +identify newer Linux platforms. + +Programmer's notes +------------------ + +Ext2fs_read_inode and ext2fs_write_inode will now return an error if +an inode number of zero is passed to them. + +E2fsprogs 1.13 (December 15, 1998) +================================== + +Fixed a bug in debugfs where an error messages weren't getting printed +when the ext2 library routines to read inodes returned errors in the +stat, cmri and rm commands. + +Fixed a bug in mke2fs so that if a ridiculous inode ratio parameter is +provided, it won't create an inode table smaller than the minimum +number of inodes required for a proper ext2 filesystem. + +Fsck now parses the /etc/fstab file directly (instead of using +getmntent()), so that it can distinguish between a missing pass number +field and pass number field of zero. This caused problems for +diskless workstations where all of the filesystems in /etc/fstab have +an explicit pass number of zero, and fsck could not distinguish this +from a /etc/fstab file with missing pass numbers. + +E2fsck will create a /lost+found directory if there isn't one in the +filesystem, since it's safer to create the lost+found directory before +it's needed. + +Fixed e2fsck so that it would detect bogus immutable inodes which +happen to be sockets and FIFO files, and offer to clear them. + +If a filesystem has multiple reasons why it needs to be checked, and +one of the reasons is that it is uncleanly mounted, e2fsck will print +that as the reason why the filesystem is being checked. + +Cleaned up the output routines of mke2fs so that it doesn't overflow +an 80 column display when formating really big filesystems. + +Added a sanity check to e2fsck to make sure that file descriptors 0, +1, 2 are open before opening the hard disk. This avoids a problem +where a broken program might exec e2fsck with those file descriptors +closed, which would cause disastrous results if the kernel returns a +file descriptor for the block device which is also used by FILE * +stdout. + +Fixed up the e2fsck progress reporting functions so that the values +reliably reach 100% at the completion of all of the e2fsck passes. + +Fixed minor documentation bugs in man pages and usage messages. + +Programmer's notes: +------------------- + +Fixed a number of lint warnings in the ext2fs library and potential +portability problems from other OS's header files that might define +CPP macros for names like "max" and "min". + +ext2fs_badblocks_list_add() has been made more efficient when it needs +to grow the bad blocks list. + +Fixed a bug in e2fsck which caused it to dereference a freed pointer +just before exiting. + +Fixed the substition process for generating the mk_cmds and compile_et +scripts so that they will work outside of the build tree. + +Add sanity check to e2fsck so that if an internal routine +(ext2fs_get_dir_info) returns NULL, avoid dereferencing the pointer +and causing a core dump. This should never happen, but... + +E2fsprogs 1.12 (July 9, 1998) +================================== + +E2fsprogs now works with glibc (at least with the version shipped wtih +RedHat 5.0). The ext2fs_llseek() function should now work even with +i386 ELF shared libraries and if llseek() is not present. We also +explicitly do a configure test to see if (a) llseek is in libc, and +(b) if llseek is declared in the system header files. (See standard +complaints about libc developers don't understand the concept of +compatibility with previous versions of libc.) + +The ext2fs library now writes out the block group number in each of +the superblock copies. This makes it easier to automatically +determine the starting block group of the filesystem when the block +group information is trashed. + +Added support for the EXT2_FEATURE_INCOMPAT_FILETYPE feature, +which means that e2fsprogs will ignore the high 8 bits of the +directory entry's name_len field, so that it can be used for other +purposes. + +Added support for the EXT2_FEATURE_RO_COMPAT_LARGE_FILE feature. +E2fsprogs will now support filesystems with 64-bit sized files. + +Added support for the EXT2_FEATURE_COMPAT_DIR_PREALLOC feature. + +Added new program "e2label", contributed by Andries Brouwer. E2label +provides an easy-to-use interface to modify the filesystem label. + +Fixed bug so that lsattr -v works instead of producing a core dump. + +Fixed a minor bug in mke2fs so that all groups with bad superblock +backup blocks are printed (not just the first one). + +Mke2fs will check the size of the device, and if the user specifies a +filesystem size larger than the apparent size of the device it will +print a warning message and ask if the user wants to proceed. + +E2fsck has a new option -C, which sends completion information to the +specified file descriptor. For the most part, this is intended for +programs to use, although -C 0 will print a spinning character to the +stdout device, which may be useful for users who want to see something +happening while e2fsck goes about its business. + +Fixed a bug in e2fsck which could cause a core dump when it needs to +expand the /lost+found directory, and sometimes the bitmaps haven't +been merged in. Also fixed a related bug where ext2fs_write_dir_block +was used to write out a non-directory block. (Which would be bad on a +non-Intel platform with byte swapping going on.) + +Fixed bug in e2fsck where it would print a "programming error" message +instead of correctly identifying where a bad block was in used when +the bad block was in a non-primary superblock or block group +descriptor. Also fixed a related bug when sparse superblocks are in +use and there is a bad block where a superblock or block group +descriptor would have been in a group that doesn't include a +superblock. + +Fixed a bug in e2fsck (really in libext2fs's dblist function) where if +the block group descriptor table is corrupt, it was possible to try to +allocate a huge array, fail, and then abort e2fsck. +ext2fs_get_num_dirs() now sanity checks the block group descriptor, +and subsitutes reasonable values if the descriptors are obviously bogus. + +If e2fsck finds a device file which has the immutable flag set and the +i_blocks beyond the normal device number are non-zero, e2fsck will +offer to remove it, since it's probably caused by garbage in the inode +table. + +When opening a filesystem, e2fsck specially checks for the EROFS error +code, and prints a specific error message to the user which is more +user friendly. + +If the filesystem revision is too high, change the e2fsck to print +that this is either because e2fsck is out of date, or because the +superblock is corrupt. + +E2fsck now checks for directories that have duplicate '.' and '..' +entries, and fixes this corruption. + +E2fsck no longer forces a sync of the filesystem (with attendant sleep +calls) at all times. The ext2fs_flush() function now performs a sync +only if it needed to write data blocks to disk. + +Fixed a minor bug in e2fsck's pass1b's file cloning function, where +certain errors would not be properly reported. + +Updated and expanded a few points in the man pages which users +complained wheren't explicit enough. + +Added special case byte-swapping code if compiling on the PowerPC, to +accomodate the strange big-endian variant of the ext2 filesystem that +was previously used on the PowerPC port. + + +Programmer's notes: +------------------- + +Removed C++ keywords from the ext2fs libraries so that it could be +compiled with C++. + +E2fsck's internal organization has now been massively reorganized so +that pass*.c don't have any printf statements. Instead, all problems +are reported through the fix_problem() abstraction interface. E2fsck +has also been revamped so that it can be called as a library from a +application. + +Added new fileio primitives in libext2fs for reading and writing +files on an unmounted ext2 filesystem. This interface is now used by +debugfs. + +Added a new libext2fs function for mapping logical block numbers of +a file to a physical block number. + +Added a new libext2fs function, ext2fs_alloc_block(), which allocates +a block, zeros it, and updates the filesystem accounting records +appropriately. + +Added a new libext2fs function, ext2fs_set_bitmap_padding(), which +sets the padding of the bitmap to be all one's. Used by e2fsck pass 5. + +The libext2fs functions now use a set of memory allocation wrapper +functions: ext2fs_get_mem, ext2fs_free_mem, and ext2fs_resize_mem, +instead of malloc, free, and resize. This makes it easier for us to +be ported to strange environments where malloc, et. al. aren't +necessarily available. + +Change the libext2fs fucntion to return ext2-specific error codes +(EXT2_DIR_EXISTS and EXT2_DB_NOT_FOUND, for example) instead of using +and depending on the existence of system error codes (such as EEXIST +and ENOENT). + +Renamed io.h to ext2_io.h to avoid collision with other OS's header +files. + +Add protection against ext2_io.h and ext2fs.h being included multiple +times. + +The types used for memory lengths, etc. have been made more portable. +In generla, the code has been made 16-bit safe. Added Mark +Habersack's contributed DOS disk i/o routines. + +Miscellaneous portability fixes, including not depending on char's +being signed. + +The io_channel structure has a new element, app_data, which is +initialized by the ext2fs routines to contain a copy of the filesystem +handle. + +ext2fs_check_directory()'s callback function may now return the error +EXT2_ET_CALLBACK_NOTHANDLED if it wishes ext2fs_check_directory() to +really do the checking, despite the presence of the callback function. + + +E2fsprosg 1.11 (June 17, 1997) +============================== + +Fixed e2fsck to detect (previously ignored) conflicts between the +superblock or block group descriptors and block bitmaps, inode +bitmaps, and inode tables. + +Fixed bug in e2fsck so that when the message printed out when a block +or inode bitmap conflicts with other data, it has the correct group +number. + +Fixed bug in e2fsck and mke2fs where the blocksize wasn't being passed +to badblocks. This meant that not all of the filesystem was being +tested for bad blocks! + +Fixed an array boundary overrun case which cropped up in +ext2fs_badblocks_list_test when a user tried running "mke2fs -c +-b 4096". + +Adjusted the number of columns printed by mke2fs when displaying the +superblock backups to avoid running over 80 columns when making a +really big filesystem. + +Fixed up the man pages for e2fsck, debugfs, badblocks, chattr, +dumpe2fs, fsck, mke2fs, and tune2fs (typos and other minor grammar +fixes), thanks to some suggestions from Bill Hawes (whawes@star.net). + +Programmer's notes: +------------------- + +Fixed install rule in lib/ss so that ss_err.h is actually getting +installed. + +Fixed bug in ext2fs_copy_bitmap; the destination bitmap wasn't getting +bassed back to the caller. + +Fixed bug in ext2fs_inode_scan_goto_blockgroup; it had not been +setting the current inode number (which meant this function wasn't +working at all). + +Fixed bug in ext2fs_resize_generic_bitmap; it had not be zeroing all +blocks in the bitmap when increasing the size of the bitmap. + +Changed the initial number of blocks allocated by ext2fs_init_dblist() +to be more realistic. + +Added a new function ext2fs_allocate_group_table, which sets up the +group descriptor information (and allocates inode and block bitmaps, +and inode tables for a particular group). The function was created by +factoring out code form ext2fs_allocate_tables(). + +Added a new function ext2fs_move_blocks which takes a bitmap of the +blocks to be moved, and moves them to another location on the +boardboard. + +Make the unix_io channel's io_channel_flush implementation calls sync() +to to flush the kernel buffers to disk. + +Added a new function ext2fs_dblist_count returns the number of +directory blocks in dblist. + + +E2fsprogs 1.10 (April 24, 1997) +=============================== + +Mke2fs once again defaults to creating revision #0 filesystems, since +people were complaining about breaking compatibility with 1.2 kernels. +Warning messages were added to the mke2fs and tune2fs man pages that +the sparse superblock option isn't supported by most kernels yet (1.2 +and 2.0 both don't support parse superblocks.) + +Added new flag to mke2fs, -R <raid options>, which allows the user to +tell mke2fs about the RAID configuration of the filesystem. Currently +the only supported raid option is "stride" which specifies the width +of the RAID stripe. + +Fixed bug in e2fsck where pass1b would bomb out if there were any +blocks marked bad in the inode table. + +Fixed rare bug in mke2fs where if the user had a very unlucky number +of blocks in a filesystem (probability less than .002) the resulting +filesystem would be corrupt in the last block group. + +Fixed bug where if e2fsck tried to allocate a block to fix a +filesystem corruption problem and the filesystem had no free blocks, +ext2fs_new_block() would loop forever. + +The configure script now checks explicitly to see if "-static" works, +since that can't be assumed to be true --- RedHat doesn't install +libc-static by default. + +Fixed bug in libext2's block iterator functions where under some +cirmcustances, file with holes would cause the bcount parameter to the +callback function to be incorrect. This bug didn't affect any of +e2fsprogs programs, but it was discovered by Paul Mackerras, the +author of the PPC boot loader. + +Removed use of static variables to store the inode cache in libext2fs. +This caused problems if more than one filesystem was accessed via +libext2fs (static variables in libraries are generally a bad idea). +Again, this didn't affect e2fsprogs programs, but it was discovered by +Paul Mackerras. + +Fixed minor bugs and version code drift to assure that e2fsprogs 1.10 +will compile cleanly with 1.2.13 kernels (even with a.out shared +libraries!) + +Programmer's notes: +------------------- + +Added new functions to duplicate an ext2 filesystem handle, and its +associated substructure. New functions: ext2fs_dup_handle(), +ext2fs_copy_dblist(), ext2fs_badblocks_copy(), ext2fs_copy_bitmap(). +Other structures, such as the io_channel and the inode_cache, now have +a ref count so that they only get freed when they are no longer used +by any filesystem handle. (These functions were added as part of the +development effort for an ext2 resizer). + +E2fsprogs 1.09 (April 14, 1997) +=============================== + +Fixed bug in mke2fs (really in lib/ext2fs/initialize.c) which was +accidentally introduced in the 1.08 release. The overhead calculation +was accidentally removed, which caused ext2fs_initialize() to not +notice when the filesystem size needed to be adjusted down because +there wasn't enough space in the last block group. + +Fixed bug in version parsing library routine; it was always parsing +the library version string, instead of using the passed-in string. + +Clarified chattr man page. + +E2fsprogs 1.08 (April 10, 1997) +=============================== + +E2fsck 1.07 was very slow when checking very large filesystems with a +lot of files that had hard links (i.e., news spools). This was fixed +by seriously revamping the icount abstraction. Added a formal test +suite for the icount abstraction. + +Debugfs now has a "-l" option to the "ls" command, which lists the +inode number, permissions, owner, group, size, and name of the files +in the directory. + +Fix a bug in e2fsck where when a directory had its blocks moved to +another location during the pass 1b processing, the directory block +list wasn't updated, so pass 2 wouldn't check (and correct) the +correct directory block. + +E2fsck will now treat inodes which contain blocks which are claimed by +the filesystem metadata by treating them as multiply claimed blocks. +This way, the data in those blocks can be copied to a new block during +the pass 1b--1d processing. + +E2fsck will attempt to determine the correct superblock number and +display it in the diagnostic and warning messages if possible. + +Add support for a new (incompatible) feature, "sparse_super". This +feature reduces the number of blocks which contain copies of backup +superblocks and block group descriptors. (It is only an incompatible +feature because of a bug in ext2_free_blocks.) mke2fs and tune2fs now +support a new -s option; e2fsck will recognize filesystems built with +this feature turned on. + +E2fsck now checks the library to make sure is the correct version, +using new library functions. (This helps to diagnose incorrectly +installed e2fsprogs distributions.) + +Dumpe2fs now prints more information; its now prints the the +filesystem revision number, the filesystem sparse_super feature (if +present), the block ranges for each block group, and the offset from +the beginning of the block group. + +Mke2fs now distributes the inode and block bitmap blok so that the +won't be concentrated in one or two disks in RAID/striping setups. +Also, if the user chooses a 2k or 4k block group, mke2fs will try to +choose the largest blocks per group that be chosen. (For 2k blocks, +you can have up to 16384 blocks/group; for 4k blocks, you can have up +to 32768 blocks/group.) Previously mke2fs would not allow +specification of more than 8192 blocks per group, even if you were +using a 2k or 4k block group. + +Programmer's notes: +------------------- + +Added a new function ext2fs_create_icount2() which takes a "hint" +argument. This hint argument presets the icount array with the list +of inodes which actually need to be in the icount array. This really +helps to speed up e2fsck. + +Added a new function ext2fs_icount_validate() which checks the rep +invariant for the icount structure. This is used mostly for testing. + +The error mesasage given when a bad inode number is passed to +test_generic_bitmap to reflect EXT2FS_TEST_ERROR (instead of +EXT2FS_UNMARK_ERROR). + +Added a new function ext2fs_set_dir_block which sets the block of a +dblist entry, given the directory inode and blockcnt. + +Added a new function ext2fs_get_library_version() which returns the +current library version, and ext2fs_parse_version_string() which +returns a version number based on a e2fsprogs version string. + +The icount functions will return EINVAL if the passed in inode number +is out of bounds. + +E2fsprogs 1.07 (March 9, 1997) +============================== + +E2fsck is now uses much less memory when checking really large +filesystems (or rather, filesystems with a large number of inodes). +Previously a filesystem with 1 million inodes required 4 megabytes of +memory to store inode count statistics; that storage requirement has +now been reduced to roughly half a megabyte. + +E2fsck can now properly deal with bad blocks appearing inside the +inode table. Instead of trying to relocate the inode table (which +often failed because there wasn't enough space), the inodes in the bad +block are marked as in use. + +E2fsck will automatically try to use the backup superblocks if the +primary superblocks have a bad magic number or have missing meta-data +blocks (or meta-data blocks which are out of range). + +E2fsck's pass 3 has been made more efficient; most noticeable on +filesystems with a very large number of directories. + +Completely revamped e2fsck's system of printing problem reports. It +is now table driven, to make them more easily customizeable and +extendable. Error messages which can be printed out during preen mode +are now one line long. + +Fixed e2fsck's filesystem swapping code so that it won't try to swap +fast symbolic links or deleted files. + +Fixed e2fsck core dumping when fixing a filesystem which has no +directories (not even a root directory). + +Added a check to e2fsck to make sure that the length of every +directory entry is a multiple of 4 (since the kernel complains if it +isn't). + +Added a check to e2fsck to make sure that a directory entry isn't a +link to the root directory, since that isn't allowed. + +Added a check to e2fsk to now make sure the '.' and '..' directory +entries are null terminated, since the 2.0 kernel requires it. + +Added check to write_bitmaps() to make sure the superblock doesn't get +trashed if the inode or block bitmap is marked as being block zero. + +Added checking of the new feature set fields in the superblock, to +avoid dealing with new filesystem features that this package wasn't +set up to handle. + +Fixed a fencepost error in ext2fs_new_block() which would occasionally +try to allocate a block beyond the end of a filesystem. + +When the UUID library picks a random IEEE 802 address (because it +can't find one from a network card), it sets the multicast bit, to +avoid conflicting with a legitimate IEEE 802 address. + +Mke2fs now sets the root directory's owner to be the real uid of the +user running mke2fs. If the real uid is non-zero, it also sets +the group ownership of the root directory to be the real group-id of +the user running mke2fs. + +Mke2fs now has more intelligent error checking when it is given a +non-existent device. + +When badblocks is given the -vv option, it now updates the block that +it is currently testing on every block. + +Fixed a bug in fsck where it wouldn't modify the PATH envirnoment +currently correctly if PATH wasn't already set. + +Shared libraries now built with dependencies. This allows the shared +library files to be used with dlopen(); it also makes the transition +to libc 6 easier, since ld.so can tell which libc a particular shared +library expects to use. + +Programmer's notes: +------------------- + +Added new abstraction (defined in dblist.c) for maintaining a list of +blocks which belongs to directories. This is used in e2fsck and other +programs which need to iterate over all directories. + +Added new functions which test to see if a contiguous range of blocks +(or inodes) are available. (ext2fs_*_bitmap_range). + +Added new function (ext2_inode_has_valid_blocks) which returns true if +an inode has valid blocks. (moved from e2fsck code). + +Added new function (ext2fs_allocate_tables) which allocates the +meta-data blocks as part of initializing a filesystem. (moved from +mke2fs code). + +Added a new I/O manager for testing purposes. It will either allow a +program to intercept I/O requests, or print debugging messages to +trace the activity of a program using the I/O manager. + +The badblocks_list functions now store the bad blocks in a sorted +order, and use a binary search to speed up badblocks_list_test. + +The inode scan function ext2fs_get_next_inode() may now return a soft +error returns: MISSING_INODE_TABLE and BAD_BLOCK_IN_INODE_TABLE in +those cases where part of an inode table is missing or there is a bad +block in the inode table. + +Added a new function (ext2fs_block_iterate2) which adds new arguments to +the callback function to return a pointer (block and offset) to the +reference of the block. + +Added new function (ext2fs_inode_scan_goto_blockgroup) which allows an +application to jump to a particular block group while doing an inode +scan. + +The badblocks list functions were renamed from badblocks_* to +ext2fs_badblocks_*. Backwards compatibility functions are available +for now, but programs should be modified to use the new interface. + +Some of the library functions were reorganized into separate files to +reduce the size of some programs which statically link against the +ext2 library. + +Put in some miscellaneous fixes for the Alpha platform. + + +E2fsprogs 1.06 (October 7, 1996) +================================ + +Fixed serious bug in e2fsck: if the block descriptors are bad, don't +smash the backup copies in ext2fs_close(). (The problem was that when +e2fsck -p discovered the problem, while it was closing the filesystem +and exiting, it was also blowing away the backup superblocks on the +disk, which was less than friendly.) We now make it the case that we +only write out the backup superblock and the back block descriptors if +the filesystem is completely free from problems. + +Fixed a bug in block_interate in the lib/ext2fs library which caused +e2fsck to fail on GNU Hurd-created filesystems. + +Add support for Linux/FT's bootloader, which actually uses +EXT2_BOOT_LOADER, and sets its mode bits which caused e2fsck to want +to clear the inode. + +Add support for the "A" (no atime update) attribute. (Note: this +attribute is not yet in production kernels.) + +The test suite is not automatically run when doing a "make all" from +the top level directory. Users should manually run "make check" if +they wish to run the test suite. + +Upon a preenhalt(), make the printed message more explicit that +running e2fsck "MANAULLY" means without the -p or -a options. + +In e2fsck, if a disconnected inode is zero-length, offer to clear it +instead of offering to connect it to lost+found. + +In e2fsck, if a filesystem was just unmounted uncleanly, and needs +e2fsck to be run over it, change e2fsck to explicitly display this +fact. + +For dumpe2fs and e2fsck, cause the -V option to print out which +version of the ext2fs library is actually getting used. (This will +help detect mismatches of using a 1.06 utility with a 1.05 library, +etc.) + +Programmers' notes: +------------------- + +EXT2_SWAP_BYTES was changed to EXT2_FLAG_SWAP_BYTES, which better fits +the naming convention. + +In ext2fs_initialize(), make sure the description for the inode bitmap +is correctly initialize. + +Fixed minor type typo in ext2fs_allocate_generic_bitmap(); + +E2fsprogs 1.05 (September 7, 1996) +================================== + +Add support for new fields in the ext2 superblock --- volume name, +volume UUID, and last mounted field. Dumpe2fs displays these fields, +tune2fs and mke2fs allows you to set them. E2fsck will automatically +generate a UUID for those volumes that don't have them. + +Put in support for e2fsck to recognize HURD specific ext2 features --- +most notably, the translator block. The e2fsprogs tools will now use +the creator_os field in the superblock to correctly handle different +OS-specific variants of the ext2 filesystem. + +E2fsck now fixes inodes which have a the deletion time set, but which +have a non-zero i_link_count field by offering to clear the deletion +time. Previously e2fsck assumed that the inode was deleted (per 0.3c +ext2 kernel behavior) and offered to unlink the file. + +If e2fsck sets the clean bit, but nothing else, set the exit code +FSCK_NONDESTRUCT. After all, e2fsck did fix a filesystem error --- it +set the filesystem valid bit when it was previously cleared. :-) This +was needed to make the HURD fsck driver happy. + +If the user refuses to attach an unattached inode, e2fsck will no +longer set the inode's link count. Otherwise, the inode would end up +getting marked as unused, which might cause loss of data later. + +Make the message issued by e2fsck when the superblock is corrupt less +confusing for users. It now mentions that another reason for the +"corrupt superblock" message might be that the partition might not be +an ext2 filesystem at all (it might swap, msdos filesystem, ufs, etc.) + +Make the libext2 library more robuest so that e2fsck won't coredump on +an illegal superblock where the blocksize is zero. (f_crashdisk is +the test case). + +By default, create filesystems where the default checkinterval is 6 +months (180 days). Linux servers can be robust enough that 20 reboots +can be a long, long time. + +Added configure flag --enable-old-bitops, which forces the bitops to +use the old (native) bitmask operations. By default on the sparc +platform, the standard ext2 bit ordering is now used. + +Added a new feature to e2fsck to byte-swap filesystems; this can be +used to convert old m68k filesystems to use the standard byte-order +storage for the superblock, inodes, and directory blocks. This +function is invoked by using the '-s' option to e2fsck. + +Debugfs's "dump" command has been enhanced so that it writes out the +exact size of the file so that the nulls at the end of the file are +eliminated. The command also accept a new "-p" option which will +attempt preserve to preserve the ownernship, permissions, and +file modification/access times. + +Debugfs has two new options, -f and -R. The -R option allows the user +to execute a single debugfs command from the command line. The -f +option allows the user to specify a "command file" containing debugfs +commands which will get executed. + +Dumpe2fs now pretty prints the check interval, instead of just +printing the check interval as a number of seconds. + +Fix bugs in debugfs: the params command when no filesystem is opened +no longer causes a core dump. It is now possible to unlink a file +when a pathame containing a '/' is specified. + +Tune2fs has a new -C option which sets the number of times the +filesystem has been mounted. + +Fix the chattr '-v' option so that it actually works. Chattr was +being buggy about the -v option parsing. + +Programmers' notes: +------------------- + +The directory lib/uuid contains a set of library routines to generate +DCE compatible UUIDs. + +Extended ext2fs_namei() to handle symbolic links. Added new function +ext2fs_nami_follow() which will follow last symbolic link in the case +where the pathname points to a sym link. + +The ext2fs_block_iterate function will now return the HURD translator +block, if present. The new flag BLOCK_FLAG_DATA_ONLY will cause the +iterator to return data blocks only. The ext2fs.h file now defines +constants BLOCK_COUNT_IND, BLOCK_COUNT_DIND, BLOCK_COUNT_TIND, and +BLOCK_COUNT_TRANSLATOR, which are the magic values passed in the block +count field of the iterator callback function. + +The test script driver now takes an optional second argument, which is +the test case to be run. This allows you to run a test case without +needing to run the entire test suite. + +On Linux ELF systems, install the .so files in the correct places +(/usr/lib). The .so files must be stored in the same directory as the +.a files. + +Fixed miscellaneous HURD compilation issues with header file being +included in the right order. + +Fixed debugfs so that it resets optind to zero, not one, since setting +optind to zero is more correct. + + +E2fsprogs 1.04 (May 16, 1996) +============================= + +First "official" (1.03 was a limited release only) to support building +e2fsprogs under Linux 2.0 kernels (as well as late model 1.3 and 1.99 +kernels). + +This package includes a RPM specs file, that it can be built using the +RedHat Package Manager. + +E2fsck now prints a hint that if there are lots of incorrectly located +inode bitmaps, block bitmaps, and inode table blocks, the user might +want to try using e2fsck -b 8193 first, to see if that fares any +better. + +For ext2 filesystem written with the hurd, debugfs will now print out +the translator field when printing an inode structure. + +Lots of miscellaneous linking/installation cleanups: + + Libraries are now linked using a relative pathname, instead of + relying on -L working correct. It doesn't, in many cases, including + current versions of GNU ld. This guarantees that the build tree is + linking with the right libraries, instead of the ones installed in + /usr/lib. + + Header files, man pages, and the et/ss shell scripts are now + generated using a custom substitution script, instead of relying on + the configure script. This prevents needless recompilation of + files; in addition, the custom substitution script is much faster. + + e2fsck may now be linked dynamically, by using the + --enable-dynamic-e2fsck flag to configure. This is not recommended, + since it increases e2fsck's dependence on other files, but some + people need to save disk space, and other critical programs on their + systems were being linked dynamically anyway. + + Programs such as fsck which didn't need to be linked against + libext2fs (or mke2fs which didn't need to be linked against libe2p) + only link against libraries they actually need. Otherwise, those + programs would require the presense of libraries that otherwise + could be removed from a rescuse diskette. + + The ss include files are now installed correctly so they can + actually be used by another package. + + If the profiling libraries are built, they are now installed on a + "make install-libs". + + +E2fsprogs 1.03 (March 27, 1996) +=============================== + +Change the m68k bit numbering for bitmasks to match the bit numbering +used by all other ext2 implementations. (This change was requested by +the m68k kernel development team.) + +Support (in-development) filesystem format revision which supports +(among other things) dynamically sized inodes. + +Fixed a bug in the ext2 library so that an intelligent error is +returned if mke2fs is run with a ridiculously small number of blocks +for a partition. + +Fixed a bug in the ext2 library which required that the device be +openable in read/write mode in order to determine its size. This +caused e2fsck -n to require read/write access when it was not +previously necessary. + +Fixed a bug in e2fsck which casued it to occasionally fail the test +suite depending on which version of the floating point library it was +using. + +Fixed a bug in e2fsck so that it now halts with a fatal error when +certain superblock consistency checks fail. Previously it continued +running e2fsck, with some potential confusing/damaging consequences. + +Added new flag to fsck which allows the root to be checked in parallel +with other filesytems. This is not the safest thing in the world to +do, but some system administrators really wanted it. + +Fixed -Wall flames in lib/ss. + + +E2fsprogs 1.02 (January 16, 1996) +================================= + +Fix to allow e2fsprogs to be compiled on recent 1.3 (pl45+) kernels. + +Change e2fsck to print statistics of how many non-contiguous files are +on the system. Note that a file which is larger than 8k blocks, it is +guaranteed to be non-contiguous. + +In mke2fs, print a warning message if a user tries to format a whole +disk (/dev/hda versus /dev/hda1). If a user really wants to format a +whole disk, the -F (force) option forces mke2fs to format a whole disk +as a filesytem. + +Fix a bug in fsck where in some cases it might start checking +partitions in the next pass before it finishes checking partitions in +the current pass. This still won't cause two partitions on the same +disk will be checked, so it's rarely a problem in real life. + +Patch lsattr so that it won't hang when checking a named pipe. + +Minor compilation fixes: + * Fix the order of libraries that were linked in debugfs. + * Allow the sources to be compiled with -ansi turned on.
diff --git a/SHLIBS b/SHLIBS new file mode 100644 index 0000000..2fcbbc3 --- /dev/null +++ b/SHLIBS
@@ -0,0 +1,35 @@ +Library:libcom_err.o +Description: Common error code library +Maintainer: Theodore Ts'o +Email: tytso@mit.edu +Start: 0x66800000 +End: 0x6687ffff + +Library:libss.o +Description: Generic Subsystem library (Simple tty UI) +Maintainer: Theodore Ts'o +Email: tytso@mit.edu +Start: 0x66880000 +End: 0x668fffff + +Library:libext2fs.so +Description: The ext2fs (raw interface) library +Maintainer: Theodore Ts'o +Email: tytso@mit.edu +Start: 0x66900000 +End: 0x6697ffff + +Library:libe2p.so +Description: The e2p (ext2fs's programmers) library +Maintainer: Theodore Ts'o +Email: tytso@mit.edu +Start: 0x66980000 +End: 0x669fffff + +Library:libuuid.so +Description: DCE Universally Unique ID (UUID) library +Maintainer: Theodore Ts'o +Email: tytso@mit.edu +Start: 0x67900000 +End: 0x679fffff +
diff --git a/SUBMITTING-PATCHES b/SUBMITTING-PATCHES new file mode 100644 index 0000000..189deb3 --- /dev/null +++ b/SUBMITTING-PATCHES
@@ -0,0 +1,39 @@ + +Like the Linux kernel, submitted e2fsprogs patches now require the +following "sign-off" procedure: + +The sign-off is a simple line at the end of the explanation for the +patch, which certifies that you wrote it or otherwise have the right to +pass it on as a open-source patch. The rules are pretty simple: if you +can certify the below: + + Developer's Certificate of Origin 1.1 + + By making a contribution to this project, I certify that: + + (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + + (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + + (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + + (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + +then you just add a line saying + + Signed-off-by: Random J Developer <random@developer.example.org> +
diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..4c8a77c --- /dev/null +++ b/acinclude.m4
@@ -0,0 +1,148 @@ +# from http://autoconf-archive.cryp.to/ax_tls.html +# +# This was licensed under the GPL with the following exception: +# +# As a special exception, the respective Autoconf Macro's copyright +# owner gives unlimited permission to copy, distribute and modify the +# configure scripts that are the output of Autoconf when processing +# the Macro. You need not follow the terms of the GNU General Public +# License when using or distributing such scripts, even though +# portions of the text of the Macro appear in them. The GNU General +# Public License (GPL) does govern all other use of the material that +# constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you make +# and distribute a modified version of the Autoconf Macro, you may +# extend this special exception to the GPL to apply to your modified +# version as well. +# +AC_DEFUN([AX_TLS], [ + AC_MSG_CHECKING(for thread local storage (TLS) class) + AC_CACHE_VAL(ac_cv_tls, [ + ax_tls_keywords="__thread __declspec(thread) none" + for ax_tls_keyword in $ax_tls_keywords; do + case $ax_tls_keyword in + none) ac_cv_tls=none ; break ;; + *) + AC_TRY_COMPILE( + [#include <stdlib.h> + static void + foo(void) { + static ] $ax_tls_keyword [ int bar; + exit(1); + }], + [], + [ac_cv_tls=$ax_tls_keyword ; break], + ac_cv_tls=none + ) + esac + done +]) + + if test "$ac_cv_tls" != "none"; then + dnl AC_DEFINE([TLS], [], [If the compiler supports a TLS storage class define it to that here]) + AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here]) + fi + AC_MSG_RESULT($ac_cv_tls) +]) + +# =========================================================================== +# http://www.nongnu.org/autoconf-archive/check_gnu_make.html +# =========================================================================== +# +# SYNOPSIS +# +# CHECK_GNU_MAKE() +# +# DESCRIPTION +# +# This macro searches for a GNU version of make. If a match is found, the +# makefile variable `ifGNUmake' is set to the empty string, otherwise it +# is set to "#". This is useful for including a special features in a +# Makefile, which cannot be handled by other versions of make. The +# variable _cv_gnu_make_command is set to the command to invoke GNU make +# if it exists, the empty string otherwise. +# +# Here is an example of its use: +# +# Makefile.in might contain: +# +# # A failsafe way of putting a dependency rule into a makefile +# $(DEPEND): +# $(CC) -MM $(srcdir)/*.c > $(DEPEND) +# +# @ifGNUmake@ ifeq ($(DEPEND),$(wildcard $(DEPEND))) +# @ifGNUmake@ include $(DEPEND) +# @ifGNUmake@ endif +# +# Then configure.in would normally contain: +# +# CHECK_GNU_MAKE() +# AC_OUTPUT(Makefile) +# +# Then perhaps to cause gnu make to override any other make, we could do +# something like this (note that GNU make always looks for GNUmakefile +# first): +# +# if ! test x$_cv_gnu_make_command = x ; then +# mv Makefile GNUmakefile +# echo .DEFAULT: > Makefile ; +# echo \ $_cv_gnu_make_command \$@ >> Makefile; +# fi +# +# Then, if any (well almost any) other make is called, and GNU make also +# exists, then the other make wraps the GNU make. +# +# LICENSE +# +# Copyright (c) 2008 John Darrington <j.darrington@elvis.murdoch.edu.au> +# +# 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. +# +# Note: Modified by Ted Ts'o to add @ifNotGNUMake@ + +AC_DEFUN( + [CHECK_GNU_MAKE], [ AC_CACHE_CHECK( for GNU make,_cv_gnu_make_command, + _cv_gnu_make_command='' ; +dnl Search all the common names for GNU make + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then + _cv_gnu_make_command=$a ; + break; + fi + done ; + ) ; +dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, '#' otherwise + if test "x$_cv_gnu_make_command" != "x" ; then + ifGNUmake='' ; + ifNotGNUmake='#' ; + else + ifGNUmake='#' ; + ifNotGNUmake='' ; + AC_MSG_RESULT("Not found"); + fi + AC_SUBST(ifGNUmake) + AC_SUBST(ifNotGNUmake) +] ) +# was originally from nls.m4 serial 1 (gettext-0.12) +AC_DEFUN([AM_MKINSTALLDIRS], +[ + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but $(top_srcdir). + dnl Try to locate it. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + case "$ac_aux_dir" in + /*) MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" ;; + *) MKINSTALLDIRS="\$(top_builddir)/$ac_aux_dir/mkinstalldirs" ;; + esac + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) +])
diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..4cf123a --- /dev/null +++ b/aclocal.m4
@@ -0,0 +1,4330 @@ +# generated automatically by aclocal 1.14.1 -*- Autoconf -*- + +# Copyright (C) 1996-2013 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +# codeset.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2006, 2008-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_LANGINFO_CODESET], +[ + AC_CACHE_CHECK([for nl_langinfo and CODESET], [am_cv_langinfo_codeset], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include <langinfo.h>]], + [[char* cs = nl_langinfo(CODESET); return !cs;]])], + [am_cv_langinfo_codeset=yes], + [am_cv_langinfo_codeset=no]) + ]) + if test $am_cv_langinfo_codeset = yes; then + AC_DEFINE([HAVE_LANGINFO_CODESET], [1], + [Define if you have <langinfo.h> and nl_langinfo(CODESET).]) + fi +]) + +dnl 'extern inline' a la ISO C99. + +dnl Copyright 2012-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_EXTERN_INLINE], +[ + AH_VERBATIM([extern_inline], +[/* Please see the Gnulib manual for how to use these macros. + + Suppress extern inline with HP-UX cc, as it appears to be broken; see + <http://lists.gnu.org/archive/html/bug-texinfo/2013-02/msg00030.html>. + + Suppress extern inline with Sun C in standards-conformance mode, as it + mishandles inline functions that call each other. E.g., for 'inline void f + (void) { } inline void g (void) { f (); }', c99 incorrectly complains + 'reference to static identifier "f" in extern inline function'. + This bug was observed with Sun C 5.12 SunOS_i386 2011/11/16. + + Suppress the use of extern inline on Apple's platforms, as Libc at least + through Libc-825.26 (2013-04-09) is incompatible with it; see, e.g., + <http://lists.gnu.org/archive/html/bug-gnulib/2012-12/msg00023.html>. + Perhaps Apple will fix this some day. */ +#if ((__GNUC__ \ + ? defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ \ + : (199901L <= __STDC_VERSION__ \ + && !defined __HP_cc \ + && !(defined __SUNPRO_C && __STDC__))) \ + && !defined __APPLE__) +# define _GL_INLINE inline +# define _GL_EXTERN_INLINE extern inline +#elif (2 < __GNUC__ + (7 <= __GNUC_MINOR__) && !defined __STRICT_ANSI__ \ + && !defined __APPLE__) +# if __GNUC_GNU_INLINE__ + /* __gnu_inline__ suppresses a GCC 4.2 diagnostic. */ +# define _GL_INLINE extern inline __attribute__ ((__gnu_inline__)) +# else +# define _GL_INLINE extern inline +# endif +# define _GL_EXTERN_INLINE extern +#else +# define _GL_INLINE static _GL_UNUSED +# define _GL_EXTERN_INLINE static _GL_UNUSED +#endif + +#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__) +# if defined __GNUC_STDC_INLINE__ && __GNUC_STDC_INLINE__ +# define _GL_INLINE_HEADER_CONST_PRAGMA +# else +# define _GL_INLINE_HEADER_CONST_PRAGMA \ + _Pragma ("GCC diagnostic ignored \"-Wsuggest-attribute=const\"") +# endif + /* Suppress GCC's bogus "no previous prototype for 'FOO'" + and "no previous declaration for 'FOO'" diagnostics, + when FOO is an inline function in the header; see + <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54113>. */ +# define _GL_INLINE_HEADER_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wmissing-prototypes\"") \ + _Pragma ("GCC diagnostic ignored \"-Wmissing-declarations\"") \ + _GL_INLINE_HEADER_CONST_PRAGMA +# define _GL_INLINE_HEADER_END \ + _Pragma ("GCC diagnostic pop") +#else +# define _GL_INLINE_HEADER_BEGIN +# define _GL_INLINE_HEADER_END +#endif]) +]) + +# fcntl-o.m4 serial 4 +dnl Copyright (C) 2006, 2009-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Written by Paul Eggert. + +# Test whether the flags O_NOATIME and O_NOFOLLOW actually work. +# Define HAVE_WORKING_O_NOATIME to 1 if O_NOATIME works, or to 0 otherwise. +# Define HAVE_WORKING_O_NOFOLLOW to 1 if O_NOFOLLOW works, or to 0 otherwise. +AC_DEFUN([gl_FCNTL_O_FLAGS], +[ + dnl Persuade glibc <fcntl.h> to define O_NOATIME and O_NOFOLLOW. + dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes + dnl AC_GNU_SOURCE. + m4_ifdef([AC_USE_SYSTEM_EXTENSIONS], + [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])], + [AC_REQUIRE([AC_GNU_SOURCE])]) + + AC_CHECK_HEADERS_ONCE([unistd.h]) + AC_CHECK_FUNCS_ONCE([symlink]) + AC_CACHE_CHECK([for working fcntl.h], [gl_cv_header_working_fcntl_h], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sys/types.h> + #include <sys/stat.h> + #if HAVE_UNISTD_H + # include <unistd.h> + #else /* on Windows with MSVC */ + # include <io.h> + # include <stdlib.h> + # defined sleep(n) _sleep ((n) * 1000) + #endif + #include <fcntl.h> + #ifndef O_NOATIME + #define O_NOATIME 0 + #endif + #ifndef O_NOFOLLOW + #define O_NOFOLLOW 0 + #endif + static int const constants[] = + { + O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND, + O_NONBLOCK, O_SYNC, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY + }; + ]], + [[ + int result = !constants; + #if HAVE_SYMLINK + { + static char const sym[] = "conftest.sym"; + if (symlink ("/dev/null", sym) != 0) + result |= 2; + else + { + int fd = open (sym, O_WRONLY | O_NOFOLLOW | O_CREAT, 0); + if (fd >= 0) + { + close (fd); + result |= 4; + } + } + if (unlink (sym) != 0 || symlink (".", sym) != 0) + result |= 2; + else + { + int fd = open (sym, O_RDONLY | O_NOFOLLOW); + if (fd >= 0) + { + close (fd); + result |= 4; + } + } + unlink (sym); + } + #endif + { + static char const file[] = "confdefs.h"; + int fd = open (file, O_RDONLY | O_NOATIME); + if (fd < 0) + result |= 8; + else + { + struct stat st0; + if (fstat (fd, &st0) != 0) + result |= 16; + else + { + char c; + sleep (1); + if (read (fd, &c, 1) != 1) + result |= 24; + else + { + if (close (fd) != 0) + result |= 32; + else + { + struct stat st1; + if (stat (file, &st1) != 0) + result |= 40; + else + if (st0.st_atime != st1.st_atime) + result |= 64; + } + } + } + } + } + return result;]])], + [gl_cv_header_working_fcntl_h=yes], + [case $? in #( + 4) gl_cv_header_working_fcntl_h='no (bad O_NOFOLLOW)';; #( + 64) gl_cv_header_working_fcntl_h='no (bad O_NOATIME)';; #( + 68) gl_cv_header_working_fcntl_h='no (bad O_NOATIME, O_NOFOLLOW)';; #( + *) gl_cv_header_working_fcntl_h='no';; + esac], + [gl_cv_header_working_fcntl_h=cross-compiling])]) + + case $gl_cv_header_working_fcntl_h in #( + *O_NOATIME* | no | cross-compiling) ac_val=0;; #( + *) ac_val=1;; + esac + AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOATIME], [$ac_val], + [Define to 1 if O_NOATIME works.]) + + case $gl_cv_header_working_fcntl_h in #( + *O_NOFOLLOW* | no | cross-compiling) ac_val=0;; #( + *) ac_val=1;; + esac + AC_DEFINE_UNQUOTED([HAVE_WORKING_O_NOFOLLOW], [$ac_val], + [Define to 1 if O_NOFOLLOW works.]) +]) + +# gettext.m4 serial 66 (gettext-0.18.2) +dnl Copyright (C) 1995-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 2000-2006, 2008-2010. + +dnl Macro to add for using GNU gettext. + +dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]). +dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The +dnl default (if it is not specified or empty) is 'no-libtool'. +dnl INTLSYMBOL should be 'external' for packages with no intl directory, +dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory. +dnl If INTLSYMBOL is 'use-libtool', then a libtool library +dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static, +dnl depending on --{enable,disable}-{shared,static} and on the presence of +dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library +dnl $(top_builddir)/intl/libintl.a will be created. +dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext +dnl implementations (in libc or libintl) without the ngettext() function +dnl will be ignored. If NEEDSYMBOL is specified and is +dnl 'need-formatstring-macros', then GNU gettext implementations that don't +dnl support the ISO C 99 <inttypes.h> formatstring macros will be ignored. +dnl INTLDIR is used to find the intl libraries. If empty, +dnl the value '$(top_builddir)/intl/' is used. +dnl +dnl The result of the configuration is one of three cases: +dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled +dnl and used. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 2) GNU gettext has been found in the system's C library. +dnl Catalog format: GNU --> install in $(datadir) +dnl Catalog extension: .mo after installation, .gmo in source tree +dnl 3) No internationalization, always use English msgid. +dnl Catalog format: none +dnl Catalog extension: none +dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur. +dnl The use of .gmo is historical (it was needed to avoid overwriting the +dnl GNU format catalogs when building on a platform with an X/Open gettext), +dnl but we keep it in order not to force irrelevant filename changes on the +dnl maintainers. +dnl +AC_DEFUN([AM_GNU_GETTEXT], +[ + dnl Argument checking. + ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], , + [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT +])])])])]) + ifelse(ifelse([$1], [], [old])[]ifelse([$1], [no-libtool], [old]), [old], + [AC_DIAGNOSE([obsolete], [Use of AM_GNU_GETTEXT without [external] argument is deprecated.])]) + ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], , + [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT +])])])]) + define([gt_included_intl], + ifelse([$1], [external], + ifdef([AM_GNU_GETTEXT_][INTL_SUBDIR], [yes], [no]), + [yes])) + define([gt_libtool_suffix_prefix], ifelse([$1], [use-libtool], [l], [])) + gt_NEEDS_INIT + AM_GNU_GETTEXT_NEED([$2]) + + AC_REQUIRE([AM_PO_SUBDIRS])dnl + ifelse(gt_included_intl, yes, [ + AC_REQUIRE([AM_INTL_SUBDIR])dnl + ]) + + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Sometimes libintl requires libiconv, so first search for libiconv. + dnl Ideally we would do this search only after the + dnl if test "$USE_NLS" = "yes"; then + dnl if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT + dnl the configure script would need to contain the same shell code + dnl again, outside any 'if'. There are two solutions: + dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'. + dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE. + dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not + dnl documented, we avoid it. + ifelse(gt_included_intl, yes, , [ + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + ]) + + dnl Sometimes, on Mac OS X, libintl requires linking with CoreFoundation. + gt_INTL_MACOSX + + dnl Set USE_NLS. + AC_REQUIRE([AM_NLS]) + + ifelse(gt_included_intl, yes, [ + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + ]) + LIBINTL= + LTLIBINTL= + POSUB= + + dnl Add a version number to the cache macros. + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + ifelse(gt_included_intl, yes, [ + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH([included-gettext], + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT([$nls_cv_force_use_gnu_gettext]) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + ]) + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If GNU gettext is available we use this. Else we have + dnl to fall back to GNU NLS library. + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +changequote(,)dnl +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +changequote([,])dnl +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + AC_CACHE_CHECK([for GNU gettext in libc], [$gt_func_gnugettext_libc], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include <libintl.h> +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + ]])], + [eval "$gt_func_gnugettext_libc=yes"], + [eval "$gt_func_gnugettext_libc=no"])]) + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + dnl Sometimes libintl requires libiconv, so first search for libiconv. + ifelse(gt_included_intl, yes, , [ + AM_ICONV_LINK + ]) + dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL + dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv]) + dnl because that would add "-liconv" to LIBINTL and LTLIBINTL + dnl even if libiconv doesn't exist. + AC_LIB_LINKFLAGS_BODY([intl]) + AC_CACHE_CHECK([for GNU gettext in libintl], + [$gt_func_gnugettext_libintl], + [gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + dnl Now see whether libintl exists and does not depend on libiconv. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include <libintl.h> +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ]])], + [eval "$gt_func_gnugettext_libintl=yes"], + [eval "$gt_func_gnugettext_libintl=no"]) + dnl Now see whether libintl exists and depends on libiconv. + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include <libintl.h> +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + ]], + [[ +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + ]])], + [LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + ]) + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS"]) + fi + + dnl If an already present or preinstalled GNU gettext() is found, + dnl use it. But if this macro is used in GNU gettext, and GNU + dnl gettext is already preinstalled in libintl, we update this + dnl libintl. (Cf. the install rule in intl/Makefile.in.) + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + dnl Reset the values set by searching for libintl. + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + ifelse(gt_included_intl, yes, [ + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + dnl GNU gettext is not found in the C library. + dnl Fall back on included GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV $LIBTHREAD" + LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions to use GNU gettext tools. + CATOBJEXT=.gmo + fi + ]) + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Some extra flags are needed during linking. + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + AC_DEFINE([ENABLE_NLS], [1], + [Define to 1 if translation of program messages to the user's native language + is requested.]) + else + USE_NLS=no + fi + fi + + AC_MSG_CHECKING([whether to use NLS]) + AC_MSG_RESULT([$USE_NLS]) + if test "$USE_NLS" = "yes"; then + AC_MSG_CHECKING([where the gettext function comes from]) + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + AC_MSG_RESULT([$gt_source]) + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + AC_MSG_CHECKING([how to link with libintl]) + AC_MSG_RESULT([$LIBINTL]) + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL]) + fi + + dnl For backward compatibility. Some packages may be using this. + AC_DEFINE([HAVE_GETTEXT], [1], + [Define if the GNU gettext() function is already present or preinstalled.]) + AC_DEFINE([HAVE_DCGETTEXT], [1], + [Define if the GNU dcgettext() function is already present or preinstalled.]) + fi + + dnl We need to process the po/ directory. + POSUB=po + fi + + ifelse(gt_included_intl, yes, [ + dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL + dnl to 'yes' because some of the testsuite requires it. + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + dnl Make all variables we use known to autoconf. + AC_SUBST([BUILD_INCLUDED_LIBINTL]) + AC_SUBST([USE_INCLUDED_LIBINTL]) + AC_SUBST([CATOBJEXT]) + + dnl For backward compatibility. Some configure.ins may be using this. + nls_cv_header_intl= + nls_cv_header_libgt= + + dnl For backward compatibility. Some Makefiles may be using this. + DATADIRNAME=share + AC_SUBST([DATADIRNAME]) + + dnl For backward compatibility. Some Makefiles may be using this. + INSTOBJEXT=.mo + AC_SUBST([INSTOBJEXT]) + + dnl For backward compatibility. Some Makefiles may be using this. + GENCAT=gencat + AC_SUBST([GENCAT]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + AC_SUBST([INTLOBJS]) + + dnl Enable libtool support if the surrounding package wishes it. + INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix + AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX]) + ]) + + dnl For backward compatibility. Some Makefiles may be using this. + INTLLIBS="$LIBINTL" + AC_SUBST([INTLLIBS]) + + dnl Make all documented variables known to autoconf. + AC_SUBST([LIBINTL]) + AC_SUBST([LTLIBINTL]) + AC_SUBST([POSUB]) +]) + + +dnl gt_NEEDS_INIT ensures that the gt_needs variable is initialized. +m4_define([gt_NEEDS_INIT], +[ + m4_divert_text([DEFAULTS], [gt_needs=]) + m4_define([gt_NEEDS_INIT], []) +]) + + +dnl Usage: AM_GNU_GETTEXT_NEED([NEEDSYMBOL]) +AC_DEFUN([AM_GNU_GETTEXT_NEED], +[ + m4_divert_text([INIT_PREPARE], [gt_needs="$gt_needs $1"]) +]) + + +dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version]) +AC_DEFUN([AM_GNU_GETTEXT_VERSION], []) + +# glibc2.m4 serial 3 +dnl Copyright (C) 2000-2002, 2004, 2008, 2010-2013 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.0 or newer. +# From Bruno Haible. + +AC_DEFUN([gt_GLIBC2], + [ + AC_CACHE_CHECK([whether we are using the GNU C Library 2 or newer], + [ac_cv_gnu_library_2], + [AC_EGREP_CPP([Lucky GNU user], + [ +#include <features.h> +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) && !defined __UCLIBC__ + Lucky GNU user + #endif +#endif + ], + [ac_cv_gnu_library_2=yes], + [ac_cv_gnu_library_2=no]) + ] + ) + AC_SUBST([GLIBC2]) + GLIBC2="$ac_cv_gnu_library_2" + ] +) + +# glibc21.m4 serial 5 +dnl Copyright (C) 2000-2002, 2004, 2008, 2010-2013 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +# Test for the GNU C Library, version 2.1 or newer, or uClibc. +# From Bruno Haible. + +AC_DEFUN([gl_GLIBC21], + [ + AC_CACHE_CHECK([whether we are using the GNU C Library >= 2.1 or uClibc], + [ac_cv_gnu_library_2_1], + [AC_EGREP_CPP([Lucky], + [ +#include <features.h> +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif +#ifdef __UCLIBC__ + Lucky user +#endif + ], + [ac_cv_gnu_library_2_1=yes], + [ac_cv_gnu_library_2_1=no]) + ] + ) + AC_SUBST([GLIBC21]) + GLIBC21="$ac_cv_gnu_library_2_1" + ] +) + +# iconv.m4 serial 18 (gettext-0.18.2) +dnl Copyright (C) 2000-2002, 2007-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([AM_ICONV_LINKFLAGS_BODY], +[ + dnl Prerequisites of AC_LIB_LINKFLAGS_BODY. + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([iconv]) +]) + +AC_DEFUN([AM_ICONV_LINK], +[ + dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and + dnl those with the standalone portable GNU libiconv installed). + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + + dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV + dnl accordingly. + AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY]) + + dnl Add $INCICONV to CPPFLAGS before performing the following checks, + dnl because if the user has installed libiconv and not disabled its use + dnl via --without-libiconv-prefix, he wants to use it. The first + dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed. + am_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV]) + + AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [ + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include <stdlib.h> +#include <iconv.h> + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_func_iconv=yes]) + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include <stdlib.h> +#include <iconv.h> + ]], + [[iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);]])], + [am_cv_lib_iconv=yes] + [am_cv_func_iconv=yes]) + LIBS="$am_save_LIBS" + fi + ]) + if test "$am_cv_func_iconv" = yes; then + AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [ + dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11, + dnl Solaris 10. + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include <iconv.h> +#include <string.h> +int main () +{ + int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\263"; + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + const char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; +}]])], + [am_cv_func_iconv_works=yes], + [am_cv_func_iconv_works=no], + [ +changequote(,)dnl + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac +changequote([,])dnl + ]) + LIBS="$am_save_LIBS" + ]) + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + AC_DEFINE([HAVE_ICONV], [1], + [Define if you have the iconv() function and it works.]) + fi + if test "$am_cv_lib_iconv" = yes; then + AC_MSG_CHECKING([how to link with libiconv]) + AC_MSG_RESULT([$LIBICONV]) + else + dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV + dnl either. + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + AC_SUBST([LIBICONV]) + AC_SUBST([LTLIBICONV]) +]) + +dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to +dnl avoid warnings like +dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required". +dnl This is tricky because of the way 'aclocal' is implemented: +dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN. +dnl Otherwise aclocal's initial scan pass would miss the macro definition. +dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions. +dnl Otherwise aclocal would emit many "Use of uninitialized value $1" +dnl warnings. +m4_define([gl_iconv_AC_DEFUN], + m4_version_prereq([2.64], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [m4_ifdef([gl_00GNULIB], + [[AC_DEFUN_ONCE( + [$1], [$2])]], + [[AC_DEFUN( + [$1], [$2])]])])) +gl_iconv_AC_DEFUN([AM_ICONV], +[ + AM_ICONV_LINK + if test "$am_cv_func_iconv" = yes; then + AC_MSG_CHECKING([for iconv declaration]) + AC_CACHE_VAL([am_cv_proto_iconv], [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include <stdlib.h> +#include <iconv.h> +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + ]], + [[]])], + [am_cv_proto_iconv_arg1=""], + [am_cv_proto_iconv_arg1="const"]) + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"]) + am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + AC_MSG_RESULT([ + $am_cv_proto_iconv]) + AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1], + [Define as const if the declaration of iconv() needs const.]) + dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>. + m4_ifdef([gl_ICONV_H_DEFAULTS], + [AC_REQUIRE([gl_ICONV_H_DEFAULTS]) + if test -n "$am_cv_proto_iconv_arg1"; then + ICONV_CONST="const" + fi + ]) + fi +]) + +# intdiv0.m4 serial 6 (gettext-0.18.2) +dnl Copyright (C) 2002, 2007-2008, 2010-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gt_INTDIV0], +[ + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + + AC_CACHE_CHECK([whether integer division by zero raises SIGFPE], + gt_cv_int_divbyzero_sigfpe, + [ + gt_cv_int_divbyzero_sigfpe= +changequote(,)dnl + case "$host_os" in + macos* | darwin[6-9]* | darwin[1-9][0-9]*) + # On Mac OS X 10.2 or newer, just assume the same as when cross- + # compiling. If we were to perform the real test, 1 Crash Report + # dialog window would pop up. + case "$host_cpu" in + i[34567]86 | x86_64) + gt_cv_int_divbyzero_sigfpe="guessing yes" ;; + esac + ;; + esac +changequote([,])dnl + if test -z "$gt_cv_int_divbyzero_sigfpe"; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include <stdlib.h> +#include <signal.h> + +static void +sigfpe_handler (int sig) +{ + /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ + exit (sig != SIGFPE); +} + +int x = 1; +int y = 0; +int z; +int nan; + +int main () +{ + signal (SIGFPE, sigfpe_handler); +/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ +#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) + signal (SIGTRAP, sigfpe_handler); +#endif +/* Linux/SPARC yields signal SIGILL. */ +#if defined (__sparc__) && defined (__linux__) + signal (SIGILL, sigfpe_handler); +#endif + + z = x / y; + nan = y / y; + exit (2); +} +]])], + [gt_cv_int_divbyzero_sigfpe=yes], + [gt_cv_int_divbyzero_sigfpe=no], + [ + # Guess based on the CPU. +changequote(,)dnl + case "$host_cpu" in + alpha* | i[34567]86 | x86_64 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac +changequote([,])dnl + ]) + fi + ]) + case "$gt_cv_int_divbyzero_sigfpe" in + *yes) value=1;; + *) value=0;; + esac + AC_DEFINE_UNQUOTED([INTDIV0_RAISES_SIGFPE], [$value], + [Define if integer division by zero raises signal SIGFPE.]) +]) + +# intl.m4 serial 25 (gettext-0.18.3) +dnl Copyright (C) 1995-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 2000-2009. + +AC_PREREQ([2.60]) + +dnl Checks for all prerequisites of the intl subdirectory, +dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS, +dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL. +AC_DEFUN([AM_INTL_SUBDIR], +[ + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AC_PROG_MKDIR_P])dnl + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_CANONICAL_HOST])dnl + AC_REQUIRE([gt_GLIBC2])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([gl_VISIBILITY])dnl + AC_REQUIRE([gt_INTL_SUBDIR_CORE])dnl + AC_REQUIRE([AC_TYPE_LONG_LONG_INT])dnl + AC_REQUIRE([gt_TYPE_WCHAR_T])dnl + AC_REQUIRE([gt_TYPE_WINT_T])dnl + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gt_TYPE_INTMAX_T]) + AC_REQUIRE([gt_PRINTF_POSIX]) + AC_REQUIRE([gl_GLIBC21])dnl + AC_REQUIRE([gl_XSIZE])dnl + AC_REQUIRE([gl_FCNTL_O_FLAGS])dnl + AC_REQUIRE([gt_INTL_MACOSX])dnl + AC_REQUIRE([gl_EXTERN_INLINE])dnl + + dnl Support for automake's --enable-silent-rules. + case "$enable_silent_rules" in + yes) INTL_DEFAULT_VERBOSITY=0;; + no) INTL_DEFAULT_VERBOSITY=1;; + *) INTL_DEFAULT_VERBOSITY=1;; + esac + AC_SUBST([INTL_DEFAULT_VERBOSITY]) + + AC_CHECK_TYPE([ptrdiff_t], , + [AC_DEFINE([ptrdiff_t], [long], + [Define as the type of the result of subtracting two pointers, if the system doesn't define it.]) + ]) + AC_CHECK_HEADERS([features.h stddef.h stdlib.h string.h]) + AC_CHECK_FUNCS([asprintf fwprintf newlocale putenv setenv setlocale \ + snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb]) + + dnl Use the _snprintf function only if it is declared (because on NetBSD it + dnl is defined as a weak alias of snprintf; we prefer to use the latter). + AC_CHECK_DECLS([_snprintf, _snwprintf], , , [#include <stdio.h>]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + AC_CHECK_DECLS([getc_unlocked], , , [#include <stdio.h>]) + + case $gt_cv_func_printf_posix in + *yes) HAVE_POSIX_PRINTF=1 ;; + *) HAVE_POSIX_PRINTF=0 ;; + esac + AC_SUBST([HAVE_POSIX_PRINTF]) + if test "$ac_cv_func_asprintf" = yes; then + HAVE_ASPRINTF=1 + else + HAVE_ASPRINTF=0 + fi + AC_SUBST([HAVE_ASPRINTF]) + if test "$ac_cv_func_snprintf" = yes; then + HAVE_SNPRINTF=1 + else + HAVE_SNPRINTF=0 + fi + AC_SUBST([HAVE_SNPRINTF]) + if test "$ac_cv_func_newlocale" = yes; then + HAVE_NEWLOCALE=1 + else + HAVE_NEWLOCALE=0 + fi + AC_SUBST([HAVE_NEWLOCALE]) + if test "$ac_cv_func_wprintf" = yes; then + HAVE_WPRINTF=1 + else + HAVE_WPRINTF=0 + fi + AC_SUBST([HAVE_WPRINTF]) + + AM_LANGINFO_CODESET + gt_LC_MESSAGES + + dnl Compilation on mingw and Cygwin needs special Makefile rules, because + dnl 1. when we install a shared library, we must arrange to export + dnl auxiliary pointer variables for every exported variable, + dnl 2. when we install a shared library and a static library simultaneously, + dnl the include file specifies __declspec(dllimport) and therefore we + dnl must arrange to define the auxiliary pointer variables for the + dnl exported variables _also_ in the static library. + if test "$enable_shared" = yes; then + case "$host_os" in + mingw* | cygwin*) is_woe32dll=yes ;; + *) is_woe32dll=no ;; + esac + else + is_woe32dll=no + fi + WOE32DLL=$is_woe32dll + AC_SUBST([WOE32DLL]) + + dnl On mingw and Cygwin, we can activate special Makefile rules which add + dnl version information to the shared libraries and executables. + case "$host_os" in + mingw* | cygwin*) is_woe32=yes ;; + *) is_woe32=no ;; + esac + WOE32=$is_woe32 + AC_SUBST([WOE32]) + if test $WOE32 = yes; then + dnl Check for a program that compiles Windows resource files. + AC_CHECK_TOOL([WINDRES], [windres]) + fi + + dnl Determine whether when creating a library, "-lc" should be passed to + dnl libtool or not. On many platforms, it is required for the libtool option + dnl -no-undefined to work. On HP-UX, however, the -lc - stored by libtool + dnl in the *.la files - makes it impossible to create multithreaded programs, + dnl because libtool also reorders the -lc to come before the -pthread, and + dnl this disables pthread_create() <http://docs.hp.com/en/1896/pthreads.html>. + case "$host_os" in + hpux*) LTLIBC="" ;; + *) LTLIBC="-lc" ;; + esac + AC_SUBST([LTLIBC]) + + dnl Rename some macros and functions used for locking. + AH_BOTTOM([ +#define __libc_lock_t gl_lock_t +#define __libc_lock_define gl_lock_define +#define __libc_lock_define_initialized gl_lock_define_initialized +#define __libc_lock_init gl_lock_init +#define __libc_lock_lock gl_lock_lock +#define __libc_lock_unlock gl_lock_unlock +#define __libc_lock_recursive_t gl_recursive_lock_t +#define __libc_lock_define_recursive gl_recursive_lock_define +#define __libc_lock_define_initialized_recursive gl_recursive_lock_define_initialized +#define __libc_lock_init_recursive gl_recursive_lock_init +#define __libc_lock_lock_recursive gl_recursive_lock_lock +#define __libc_lock_unlock_recursive gl_recursive_lock_unlock +#define glthread_in_use libintl_thread_in_use +#define glthread_lock_init_func libintl_lock_init_func +#define glthread_lock_lock_func libintl_lock_lock_func +#define glthread_lock_unlock_func libintl_lock_unlock_func +#define glthread_lock_destroy_func libintl_lock_destroy_func +#define glthread_rwlock_init_multithreaded libintl_rwlock_init_multithreaded +#define glthread_rwlock_init_func libintl_rwlock_init_func +#define glthread_rwlock_rdlock_multithreaded libintl_rwlock_rdlock_multithreaded +#define glthread_rwlock_rdlock_func libintl_rwlock_rdlock_func +#define glthread_rwlock_wrlock_multithreaded libintl_rwlock_wrlock_multithreaded +#define glthread_rwlock_wrlock_func libintl_rwlock_wrlock_func +#define glthread_rwlock_unlock_multithreaded libintl_rwlock_unlock_multithreaded +#define glthread_rwlock_unlock_func libintl_rwlock_unlock_func +#define glthread_rwlock_destroy_multithreaded libintl_rwlock_destroy_multithreaded +#define glthread_rwlock_destroy_func libintl_rwlock_destroy_func +#define glthread_recursive_lock_init_multithreaded libintl_recursive_lock_init_multithreaded +#define glthread_recursive_lock_init_func libintl_recursive_lock_init_func +#define glthread_recursive_lock_lock_multithreaded libintl_recursive_lock_lock_multithreaded +#define glthread_recursive_lock_lock_func libintl_recursive_lock_lock_func +#define glthread_recursive_lock_unlock_multithreaded libintl_recursive_lock_unlock_multithreaded +#define glthread_recursive_lock_unlock_func libintl_recursive_lock_unlock_func +#define glthread_recursive_lock_destroy_multithreaded libintl_recursive_lock_destroy_multithreaded +#define glthread_recursive_lock_destroy_func libintl_recursive_lock_destroy_func +#define glthread_once_func libintl_once_func +#define glthread_once_singlethreaded libintl_once_singlethreaded +#define glthread_once_multithreaded libintl_once_multithreaded +]) +]) + + +dnl Checks for the core files of the intl subdirectory: +dnl dcigettext.c +dnl eval-plural.h +dnl explodename.c +dnl finddomain.c +dnl gettextP.h +dnl gmo.h +dnl hash-string.h hash-string.c +dnl l10nflist.c +dnl libgnuintl.h.in (except the *printf stuff) +dnl loadinfo.h +dnl loadmsgcat.c +dnl localealias.c +dnl log.c +dnl plural-exp.h plural-exp.c +dnl plural.y +dnl Used by libglocale. +AC_DEFUN([gt_INTL_SUBDIR_CORE], +[ + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([gt_INTDIV0])dnl + AC_REQUIRE([gl_AC_TYPE_UINTMAX_T])dnl + AC_REQUIRE([gt_INTTYPES_PRI])dnl + AC_REQUIRE([gl_LOCK])dnl + + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; }]], + [[]])], + [AC_DEFINE([HAVE_BUILTIN_EXPECT], [1], + [Define to 1 if the compiler understands __builtin_expect.])]) + + AC_CHECK_HEADERS([argz.h inttypes.h limits.h unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd getegid geteuid getgid getuid mempcpy munmap \ + stpcpy strcasecmp strdup strtoul tsearch uselocale argz_count \ + argz_stringify argz_next __fsetlocking]) + + dnl Use the *_unlocked functions only if they are declared. + dnl (because some of them were defined without being declared in Solaris + dnl 2.5.1 but were removed in Solaris 2.6, whereas we want binaries built + dnl on Solaris 2.5.1 to run on Solaris 2.6). + AC_CHECK_DECLS([feof_unlocked, fgets_unlocked], , , [#include <stdio.h>]) + + AM_ICONV + + dnl intl/plural.c is generated from intl/plural.y. It requires bison, + dnl because plural.y uses bison specific features. It requires at least + dnl bison-1.26 because earlier versions generate a plural.c that doesn't + dnl compile. + dnl bison is only needed for the maintainer (who touches plural.y). But in + dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put + dnl the rule in general Makefile. Now, some people carelessly touch the + dnl files or have a broken "make" program, hence the plural.c rule will + dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not + dnl present or too old. + AC_CHECK_PROGS([INTLBISON], [bison]) + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + dnl Found it, now check the version. + AC_MSG_CHECKING([version of bison]) +changequote(<<,>>)dnl + ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) +changequote([,])dnl + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + esac + AC_MSG_RESULT([$ac_prog_version]) + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi +]) + +# intlmacosx.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2004-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Checks for special options needed on Mac OS X. +dnl Defines INTL_MACOSX_LIBS. +AC_DEFUN([gt_INTL_MACOSX], +[ + dnl Check for API introduced in Mac OS X 10.2. + AC_CACHE_CHECK([for CFPreferencesCopyAppValue], + [gt_cv_func_CFPreferencesCopyAppValue], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include <CoreFoundation/CFPreferences.h>]], + [[CFPreferencesCopyAppValue(NULL, NULL)]])], + [gt_cv_func_CFPreferencesCopyAppValue=yes], + [gt_cv_func_CFPreferencesCopyAppValue=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + AC_DEFINE([HAVE_CFPREFERENCESCOPYAPPVALUE], [1], + [Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in the CoreFoundation framework.]) + fi + dnl Check for API introduced in Mac OS X 10.3. + AC_CACHE_CHECK([for CFLocaleCopyCurrent], [gt_cv_func_CFLocaleCopyCurrent], + [gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include <CoreFoundation/CFLocale.h>]], + [[CFLocaleCopyCurrent();]])], + [gt_cv_func_CFLocaleCopyCurrent=yes], + [gt_cv_func_CFLocaleCopyCurrent=no]) + LIBS="$gt_save_LIBS"]) + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + AC_DEFINE([HAVE_CFLOCALECOPYCURRENT], [1], + [Define to 1 if you have the Mac OS X function CFLocaleCopyCurrent in the CoreFoundation framework.]) + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + AC_SUBST([INTL_MACOSX_LIBS]) +]) + +# intmax.m4 serial 6 (gettext-0.18.2) +dnl Copyright (C) 2002-2005, 2008-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether the system has the 'intmax_t' type, but don't attempt to +dnl find a replacement if it is lacking. + +AC_DEFUN([gt_TYPE_INTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + AC_CACHE_CHECK([for intmax_t], [gt_cv_c_intmax_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include <stddef.h> +#include <stdlib.h> +#if HAVE_STDINT_H_WITH_UINTMAX +#include <stdint.h> +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include <inttypes.h> +#endif + ]], + [[intmax_t x = -1; + return !x;]])], + [gt_cv_c_intmax_t=yes], + [gt_cv_c_intmax_t=no])]) + if test $gt_cv_c_intmax_t = yes; then + AC_DEFINE([HAVE_INTMAX_T], [1], + [Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>.]) + fi +]) + +# inttypes-pri.m4 serial 7 (gettext-0.18.2) +dnl Copyright (C) 1997-2002, 2006, 2008-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ([2.53]) + +# Define PRI_MACROS_BROKEN if <inttypes.h> exists and defines the PRI* +# macros to non-string values. This is the case on AIX 4.3.3. + +AC_DEFUN([gt_INTTYPES_PRI], +[ + AC_CHECK_HEADERS([inttypes.h]) + if test $ac_cv_header_inttypes_h = yes; then + AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken], + [gt_cv_inttypes_pri_broken], + [ + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include <inttypes.h> +#ifdef PRId32 +char *p = PRId32; +#endif + ]], + [[]])], + [gt_cv_inttypes_pri_broken=no], + [gt_cv_inttypes_pri_broken=yes]) + ]) + fi + if test "$gt_cv_inttypes_pri_broken" = yes; then + AC_DEFINE_UNQUOTED([PRI_MACROS_BROKEN], [1], + [Define if <inttypes.h> exists and defines unusable PRI* macros.]) + PRI_MACROS_BROKEN=1 + else + PRI_MACROS_BROKEN=0 + fi + AC_SUBST([PRI_MACROS_BROKEN]) +]) + +# inttypes_h.m4 serial 10 +dnl Copyright (C) 1997-2004, 2006, 2008-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists, +# doesn't clash with <sys/types.h>, and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_INTTYPES_H], +[ + AC_CACHE_CHECK([for inttypes.h], [gl_cv_header_inttypes_h], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include <sys/types.h> +#include <inttypes.h> + ]], + [[uintmax_t i = (uintmax_t) -1; return !i;]])], + [gl_cv_header_inttypes_h=yes], + [gl_cv_header_inttypes_h=no])]) + if test $gl_cv_header_inttypes_h = yes; then + AC_DEFINE_UNQUOTED([HAVE_INTTYPES_H_WITH_UINTMAX], [1], + [Define if <inttypes.h> exists, doesn't clash with <sys/types.h>, + and declares uintmax_t. ]) + fi +]) + +# lcmessage.m4 serial 7 (gettext-0.18.2) +dnl Copyright (C) 1995-2002, 2004-2005, 2008-2013 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1995. + +# Check whether LC_MESSAGES is available in <locale.h>. + +AC_DEFUN([gt_LC_MESSAGES], +[ + AC_CACHE_CHECK([for LC_MESSAGES], [gt_cv_val_LC_MESSAGES], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include <locale.h>]], + [[return LC_MESSAGES]])], + [gt_cv_val_LC_MESSAGES=yes], + [gt_cv_val_LC_MESSAGES=no])]) + if test $gt_cv_val_LC_MESSAGES = yes; then + AC_DEFINE([HAVE_LC_MESSAGES], [1], + [Define if your <locale.h> file defines LC_MESSAGES.]) + fi +]) + +# lib-ld.m4 serial 6 +dnl Copyright (C) 1996-2003, 2009-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl Subroutines of libtool.m4, +dnl with replacements s/_*LT_PATH/AC_LIB_PROG/ and s/lt_/acl_/ to avoid +dnl collision with libtool.m4. + +dnl From libtool-2.4. Sets the variable with_gnu_ld to yes or no. +AC_DEFUN([AC_LIB_PROG_LD_GNU], +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld], +[# I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + acl_cv_prog_gnu_ld=yes + ;; +*) + acl_cv_prog_gnu_ld=no + ;; +esac]) +with_gnu_ld=$acl_cv_prog_gnu_ld +]) + +dnl From libtool-2.4. Sets the variable LD. +AC_DEFUN([AC_LIB_PROG_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld [default=no]])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + 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 + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'` + while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL([acl_cv_path_LD], +[if test -z "$LD"; then + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$acl_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$acl_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$acl_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT([$LD]) +else + AC_MSG_RESULT([no]) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_LIB_PROG_LD_GNU +]) + +# lib-link.m4 serial 26 (gettext-0.18.2) +dnl Copyright (C) 2001-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_PREREQ([2.54]) + +dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and +dnl augments the CPPFLAGS variable. +dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname +dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + pushdef([Name],[m4_translit([$1],[./+-], [____])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [ + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + ac_cv_lib[]Name[]_libs="$LIB[]NAME" + ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME" + ac_cv_lib[]Name[]_cppflags="$INC[]NAME" + ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX" + ]) + LIB[]NAME="$ac_cv_lib[]Name[]_libs" + LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs" + INC[]NAME="$ac_cv_lib[]Name[]_cppflags" + LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + AC_SUBST([LIB]NAME[_PREFIX]) + dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the + dnl results of this search when this library appears as a dependency. + HAVE_LIB[]NAME=yes + popdef([NAME]) + popdef([Name]) +]) + +dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message]) +dnl searches for libname and the libraries corresponding to explicit and +dnl implicit dependencies, together with the specified include files and +dnl the ability to compile and link the specified testcode. The missing-message +dnl defaults to 'no' and may contain additional hints for the user. +dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} +dnl and LTLIB${NAME} variables and augments the CPPFLAGS variable, and +dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs +dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty. +dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname +dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_HAVE_LINKFLAGS], +[ + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + AC_REQUIRE([AC_LIB_RPATH]) + pushdef([Name],[m4_translit([$1],[./+-], [____])]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + + dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME + dnl accordingly. + AC_LIB_LINKFLAGS_BODY([$1], [$2]) + + dnl Add $INC[]NAME to CPPFLAGS before performing the following checks, + dnl because if the user has installed lib[]Name and not disabled its use + dnl via --without-lib[]Name-prefix, he wants to use it. + ac_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME) + + AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [ + ac_save_LIBS="$LIBS" + dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS, + dnl because these -l options might require -L options that are present in + dnl LIBS. -l options benefit only from the -L options listed before it. + dnl Otherwise, add it to the front of LIBS, because it may be a static + dnl library that depends on another static library that is present in LIBS. + dnl Static libraries benefit only from the static libraries listed after + dnl it. + case " $LIB[]NAME" in + *" -l"*) LIBS="$LIBS $LIB[]NAME" ;; + *) LIBS="$LIB[]NAME $LIBS" ;; + esac + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[$3]], [[$4]])], + [ac_cv_lib[]Name=yes], + [ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])']) + LIBS="$ac_save_LIBS" + ]) + if test "$ac_cv_lib[]Name" = yes; then + HAVE_LIB[]NAME=yes + AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.]) + AC_MSG_CHECKING([how to link with lib[]$1]) + AC_MSG_RESULT([$LIB[]NAME]) + else + HAVE_LIB[]NAME=no + dnl If $LIB[]NAME didn't lead to a usable library, we don't need + dnl $INC[]NAME either. + CPPFLAGS="$ac_save_CPPFLAGS" + LIB[]NAME= + LTLIB[]NAME= + LIB[]NAME[]_PREFIX= + fi + AC_SUBST([HAVE_LIB]NAME) + AC_SUBST([LIB]NAME) + AC_SUBST([LTLIB]NAME) + AC_SUBST([LIB]NAME[_PREFIX]) + popdef([NAME]) + popdef([Name]) +]) + +dnl Determine the platform dependent parameters needed to use rpath: +dnl acl_libext, +dnl acl_shlibext, +dnl acl_libname_spec, +dnl acl_library_names_spec, +dnl acl_hardcode_libdir_flag_spec, +dnl acl_hardcode_libdir_separator, +dnl acl_hardcode_direct, +dnl acl_hardcode_minus_L. +AC_DEFUN([AC_LIB_RPATH], +[ + dnl Tell automake >= 1.10 to complain if config.rpath is missing. + m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])]) + AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS + AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host + AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir + AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [ + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + ]) + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + dnl Determine whether the user wants rpath handling at all. + AC_ARG_ENABLE([rpath], + [ --disable-rpath do not hardcode runtime library paths], + :, enable_rpath=yes) +]) + +dnl AC_LIB_FROMPACKAGE(name, package) +dnl declares that libname comes from the given package. The configure file +dnl will then not have a --with-libname-prefix option but a +dnl --with-package-prefix option. Several libraries can come from the same +dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar +dnl macro call that searches for libname. +AC_DEFUN([AC_LIB_FROMPACKAGE], +[ + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_frompackage_]NAME, [$2]) + popdef([NAME]) + pushdef([PACK],[$2]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + define([acl_libsinpackage_]PACKUP, + m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1]) + popdef([PACKUP]) + popdef([PACK]) +]) + +dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and +dnl the libraries corresponding to explicit and implicit dependencies. +dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables. +dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found +dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem. +AC_DEFUN([AC_LIB_LINKFLAGS_BODY], +[ + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])]) + pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-], + [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])]) + pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])]) + dnl Autoconf >= 2.61 supports dots in --with options. + pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_ARG_WITH(P_A_C_K[-prefix], +[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib + --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi +]) + dnl Search the library and its dependencies in $additional_libdir and + dnl $LDFLAGS. Using breadth-first-seach. + LIB[]NAME= + LTLIB[]NAME= + INC[]NAME= + LIB[]NAME[]_PREFIX= + dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been + dnl computed. So it has to be reset here. + HAVE_LIB[]NAME= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='$1 $2' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + dnl See if it was already located by an earlier AC_LIB_LINKFLAGS + dnl or AC_LIB_HAVE_LINKFLAGS call. + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value" + else + dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined + dnl that this library doesn't exist. So just drop it. + : + fi + else + dnl Search the library lib$name in $additional_libdir and $LDFLAGS + dnl and the already constructed $LIBNAME/$LTLIBNAME. + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + dnl The same code as in the loop below: + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + dnl First look for a shared library. + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + dnl Then look for a static library. + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + dnl Found the library. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + dnl Linking with a shared library. We attempt to hardcode its + dnl directory into the executable's runpath, unless it's the + dnl standard /usr/lib. + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + dnl No hardcoding is needed. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + dnl The hardcoding into $LIBNAME is system dependent. + if test "$acl_hardcode_direct" = yes; then + dnl Using DIR/libNAME.so during linking hardcodes DIR into the + dnl resulting binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode DIR into the resulting + dnl binary. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + dnl Rely on "-L$found_dir". + dnl But don't add it if it's already contained in the LDFLAGS + dnl or the already constructed $LIBNAME + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" + else + dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH + dnl here, because this doesn't fit in flags passed to the + dnl compiler. So give up. No hardcoding. This affects only + dnl very old systems. + dnl FIXME: Not sure whether we should use + dnl "-L$found_dir -l$name" or "-L$found_dir $found_so" + dnl here. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + dnl Linking with a static library. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a" + else + dnl We shouldn't come here, but anyway it's good to have a + dnl fallback. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" + fi + fi + dnl Assume the include files are nearby. + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = '$1'; then + LIB[]NAME[]_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + dnl Potentially add $additional_includedir to $INCNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's /usr/local/include and we are using GCC on Linux, + dnl 3. if it's already present in $CPPFLAGS or the already + dnl constructed $INCNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INC[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $INCNAME. + INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + dnl Look for dependencies. + if test -n "$found_la"; then + dnl Read the .la file. It defines the variables + dnl dlname, library_names, old_library, dependency_libs, current, + dnl age, revision, installed, dlopen, dlpreopen, libdir. + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + dnl We use only dependency_libs. + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's /usr/local/lib and we are using GCC on Linux, + dnl 3. if it's already present in $LDFLAGS or the already + dnl constructed $LIBNAME, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LIBNAME. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIB[]NAME; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LTLIBNAME. + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + dnl Potentially add DIR to rpathdirs. + dnl The rpathdirs will be appended to $LIBNAME at the end. + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + dnl Potentially add DIR to ltrpathdirs. + dnl The ltrpathdirs will be appended to $LTLIBNAME at the end. + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + dnl Handle this in the next round. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + dnl Handle this in the next round. Throw away the .la's + dnl directory; it is already contained in a preceding -L + dnl option. + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + dnl Most likely an immediate library name. + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep" + ;; + esac + done + fi + else + dnl Didn't find the library; assume it is in the system directories + dnl known to the linker and runtime loader. (All the system + dnl directories known to the linker should also be known to the + dnl runtime loader, otherwise the system is severely misconfigured.) + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name" + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user must + dnl pass all path elements in one option. We can arrange that for a + dnl single library, but not when more than one $LIBNAMEs are used. + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl. + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + else + dnl The -rpath options are cumulative. + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + dnl When using libtool, the option that works for both libraries and + dnl executables is -R. The -R options are cumulative. + for found_dir in $ltrpathdirs; do + LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir" + done + fi + popdef([P_A_C_K]) + popdef([PACKLIBS]) + popdef([PACKUP]) + popdef([PACK]) + popdef([NAME]) +]) + +dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR, +dnl unless already present in VAR. +dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes +dnl contains two or three consecutive elements that belong together. +AC_DEFUN([AC_LIB_APPENDTOVAR], +[ + for element in [$2]; do + haveit= + for x in $[$1]; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + [$1]="${[$1]}${[$1]:+ }$element" + fi + done +]) + +dnl For those cases where a variable contains several -L and -l options +dnl referring to unknown libraries and directories, this macro determines the +dnl necessary additional linker options for the runtime path. +dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL]) +dnl sets LDADDVAR to linker options needed together with LIBSVALUE. +dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed, +dnl otherwise linking without libtool is assumed. +AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS], +[ + AC_REQUIRE([AC_LIB_RPATH]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + $1= + if test "$enable_rpath" != no; then + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + dnl Use an explicit option to hardcode directories into the resulting + dnl binary. + rpathdirs= + next= + for opt in $2; do + if test -n "$next"; then + dir="$next" + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= + else + case $opt in + -L) next=yes ;; + -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'` + dnl No need to hardcode the standard /usr/lib. + if test "X$dir" != "X/usr/$acl_libdirstem" \ + && test "X$dir" != "X/usr/$acl_libdirstem2"; then + rpathdirs="$rpathdirs $dir" + fi + next= ;; + *) next= ;; + esac + fi + done + if test "X$rpathdirs" != "X"; then + if test -n ""$3""; then + dnl libtool is used for linking. Use -R options. + for dir in $rpathdirs; do + $1="${$1}${$1:+ }-R$dir" + done + else + dnl The linker is used for linking directly. + if test -n "$acl_hardcode_libdir_separator"; then + dnl Weird platform: only the last -rpath option counts, the user + dnl must pass all path elements in one option. + alldirs= + for dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="$flag" + else + dnl The -rpath options are cumulative. + for dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + $1="${$1}${$1:+ }$flag" + done + fi + fi + fi + fi + fi + AC_SUBST([$1]) +]) + +# lib-prefix.m4 serial 7 (gettext-0.18) +dnl Copyright (C) 2001-2005, 2008-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and +dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't +dnl require excessive bracketing. +ifdef([AC_HELP_STRING], +[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])], +[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])]) + +dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed +dnl to access previously installed libraries. The basic assumption is that +dnl a user will want packages to use other packages he previously installed +dnl with the same --prefix option. +dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate +dnl libraries, but is otherwise very convenient. +AC_DEFUN([AC_LIB_PREFIX], +[ + AC_BEFORE([$0], [AC_LIB_LINKFLAGS]) + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_REQUIRE([AC_LIB_PREPARE_MULTILIB]) + AC_REQUIRE([AC_LIB_PREPARE_PREFIX]) + dnl By default, look in $includedir and $libdir. + use_additional=yes + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + AC_LIB_ARG_WITH([lib-prefix], +[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib + --without-lib-prefix don't search for libraries in includedir and libdir], +[ + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + AC_LIB_WITH_FINAL_PREFIX([ + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + ]) + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + fi + fi +]) + if test $use_additional = yes; then + dnl Potentially add $additional_includedir to $CPPFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/include, + dnl 2. if it's already present in $CPPFLAGS, + dnl 3. if it's /usr/local/include and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + for x in $CPPFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + dnl Really add $additional_includedir to $CPPFLAGS. + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir" + fi + fi + fi + fi + dnl Potentially add $additional_libdir to $LDFLAGS. + dnl But don't add it + dnl 1. if it's the standard /usr/lib, + dnl 2. if it's already present in $LDFLAGS, + dnl 3. if it's /usr/local/lib and we are using GCC on Linux, + dnl 4. if it doesn't exist as a directory. + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + for x in $LDFLAGS; do + AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"]) + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux*) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + dnl Really add $additional_libdir to $LDFLAGS. + LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir" + fi + fi + fi + fi + fi +]) + +dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix, +dnl acl_final_exec_prefix, containing the values to which $prefix and +dnl $exec_prefix will expand at the end of the configure script. +AC_DEFUN([AC_LIB_PREPARE_PREFIX], +[ + dnl Unfortunately, prefix and exec_prefix get only finally determined + dnl at the end of configure. + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the +dnl variables prefix and exec_prefix bound to the values they will have +dnl at the end of the configure script. +AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX], +[ + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + $1 + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" +]) + +dnl AC_LIB_PREPARE_MULTILIB creates +dnl - a variable acl_libdirstem, containing the basename of the libdir, either +dnl "lib" or "lib64" or "lib/64", +dnl - a variable acl_libdirstem2, as a secondary possible value for +dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or +dnl "lib/amd64". +AC_DEFUN([AC_LIB_PREPARE_MULTILIB], +[ + dnl There is no formal standard regarding lib and lib64. + dnl On glibc systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine + dnl the compiler's default mode by looking at the compiler's library search + dnl path. If at least one of its elements ends in /lib64 or points to a + dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI. + dnl Otherwise we use the default, namely "lib". + dnl On Solaris systems, the current practice is that on a system supporting + dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under + dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or + dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib. + AC_REQUIRE([AC_CANONICAL_HOST]) + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment + dnl <http://docs.sun.com/app/docs/doc/816-5138/dev-env?l=en&a=view>. + dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link." + dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the + dnl symlink is missing, so we set acl_libdirstem2 too. + AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit], + [AC_EGREP_CPP([sixtyfour bits], [ +#ifdef _LP64 +sixtyfour bits +#endif + ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no]) + ]) + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" +]) + +# lock.m4 serial 13 (gettext-0.18.2) +dnl Copyright (C) 2005-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_LOCK], +[ + AC_REQUIRE([gl_THREADLIB]) + if test "$gl_threads_api" = posix; then + # OSF/1 4.0 and Mac OS X 10.1 lack the pthread_rwlock_t type and the + # pthread_rwlock_* functions. + AC_CHECK_TYPE([pthread_rwlock_t], + [AC_DEFINE([HAVE_PTHREAD_RWLOCK], [1], + [Define if the POSIX multithreading library has read/write locks.])], + [], + [#include <pthread.h>]) + # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM( + [[#include <pthread.h>]], + [[ +#if __FreeBSD__ == 4 +error "No, in FreeBSD 4.0 recursive mutexes actually don't work." +#elif (defined __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ \ + && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070) +error "No, in Mac OS X < 10.7 recursive mutexes actually don't work." +#else +int x = (int)PTHREAD_MUTEX_RECURSIVE; +return !x; +#endif + ]])], + [AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], [1], + [Define if the <pthread.h> defines PTHREAD_MUTEX_RECURSIVE.])]) + fi + gl_PREREQ_LOCK +]) + +# Prerequisites of lib/glthread/lock.c. +AC_DEFUN([gl_PREREQ_LOCK], [:]) + +# longlong.m4 serial 17 +dnl Copyright (C) 1999-2007, 2009-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_LONG_LONG_INT if 'long long int' works. +# This fixes a bug in Autoconf 2.61, and can be faster +# than what's in Autoconf 2.62 through 2.68. + +# Note: If the type 'long long int' exists but is only 32 bits large +# (as on some very old compilers), HAVE_LONG_LONG_INT will not be +# defined. In this case you can treat 'long long int' like 'long int'. + +AC_DEFUN([AC_TYPE_LONG_LONG_INT], +[ + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + AC_CACHE_CHECK([for long long int], [ac_cv_type_long_long_int], + [ac_cv_type_long_long_int=yes + if test "x${ac_cv_prog_cc_c99-no}" = xno; then + ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int + if test $ac_cv_type_long_long_int = yes; then + dnl Catch a bug in Tandem NonStop Kernel (OSS) cc -O circa 2004. + dnl If cross compiling, assume the bug is not important, since + dnl nobody cross compiles for this platform as far as we know. + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[@%:@include <limits.h> + @%:@ifndef LLONG_MAX + @%:@ define HALF \ + (1LL << (sizeof (long long int) * CHAR_BIT - 2)) + @%:@ define LLONG_MAX (HALF - 1 + HALF) + @%:@endif]], + [[long long int n = 1; + int i; + for (i = 0; ; i++) + { + long long int m = n << i; + if (m >> i != n) + return 1; + if (LLONG_MAX / 2 < m) + break; + } + return 0;]])], + [], + [ac_cv_type_long_long_int=no], + [:]) + fi + fi]) + if test $ac_cv_type_long_long_int = yes; then + AC_DEFINE([HAVE_LONG_LONG_INT], [1], + [Define to 1 if the system has the type 'long long int'.]) + fi +]) + +# Define HAVE_UNSIGNED_LONG_LONG_INT if 'unsigned long long int' works. +# This fixes a bug in Autoconf 2.61, and can be faster +# than what's in Autoconf 2.62 through 2.68. + +# Note: If the type 'unsigned long long int' exists but is only 32 bits +# large (as on some very old compilers), AC_TYPE_UNSIGNED_LONG_LONG_INT +# will not be defined. In this case you can treat 'unsigned long long int' +# like 'unsigned long int'. + +AC_DEFUN([AC_TYPE_UNSIGNED_LONG_LONG_INT], +[ + AC_CACHE_CHECK([for unsigned long long int], + [ac_cv_type_unsigned_long_long_int], + [ac_cv_type_unsigned_long_long_int=yes + if test "x${ac_cv_prog_cc_c99-no}" = xno; then + AC_LINK_IFELSE( + [_AC_TYPE_LONG_LONG_SNIPPET], + [], + [ac_cv_type_unsigned_long_long_int=no]) + fi]) + if test $ac_cv_type_unsigned_long_long_int = yes; then + AC_DEFINE([HAVE_UNSIGNED_LONG_LONG_INT], [1], + [Define to 1 if the system has the type 'unsigned long long int'.]) + fi +]) + +# Expands to a C program that can be used to test for simultaneous support +# of 'long long' and 'unsigned long long'. We don't want to say that +# 'long long' is available if 'unsigned long long' is not, or vice versa, +# because too many programs rely on the symmetry between signed and unsigned +# integer types (excluding 'bool'). +AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET], +[ + AC_LANG_PROGRAM( + [[/* For now, do not test the preprocessor; as of 2007 there are too many + implementations with broken preprocessors. Perhaps this can + be revisited in 2012. In the meantime, code should not expect + #if to work with literals wider than 32 bits. */ + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63;]], + [[/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull));]]) +]) + +# nls.m4 serial 5 (gettext-0.18) +dnl Copyright (C) 1995-2003, 2005-2006, 2008-2013 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003. + +AC_PREREQ([2.50]) + +AC_DEFUN([AM_NLS], +[ + AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE([nls], + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT([$USE_NLS]) + AC_SUBST([USE_NLS]) +]) + +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 1 (pkg-config-0.24) +# +# Copyright © 2004 Scott James Remnant <scott@netsplit.com>. +# +# 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. +# +# 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. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +# only at the first occurence in configure.ac, so if the first place +# it's called might be skipped (such as if it is within an "if", you +# have to call PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])# PKG_CHECK_MODULES + + +# PKG_INSTALLDIR(DIRECTORY) +# ------------------------- +# Substitutes the variable pkgconfigdir as the location where a module +# should install pkg-config .pc files. By default the directory is +# $libdir/pkgconfig, but the default can be changed by passing +# DIRECTORY. The user can override through the --with-pkgconfigdir +# parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +]) dnl PKG_INSTALLDIR + + +# PKG_NOARCH_INSTALLDIR(DIRECTORY) +# ------------------------- +# Substitutes the variable noarch_pkgconfigdir as the location where a +# module should install arch-independent pkg-config .pc files. By +# default the directory is $datadir/pkgconfig, but the default can be +# changed by passing DIRECTORY. The user can override through the +# --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +]) dnl PKG_NOARCH_INSTALLDIR + + +# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# ------------------------------------------- +# Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])# PKG_CHECK_VAR + +# po.m4 serial 21 (gettext-0.18.3) +dnl Copyright (C) 1995-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000. +dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003. + +AC_PREREQ([2.60]) + +dnl Checks for all prerequisites of the po subdirectory. +AC_DEFUN([AM_PO_SUBDIRS], +[ + AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl + AC_REQUIRE([AC_PROG_MKDIR_P])dnl + AC_REQUIRE([AC_PROG_SED])dnl + AC_REQUIRE([AM_NLS])dnl + + dnl Release version of the gettext macros. This is used to ensure that + dnl the gettext macros and po/Makefile.in.in are in sync. + AC_SUBST([GETTEXT_MACRO_VERSION], [0.18]) + + dnl Perform the following tests also if --disable-nls has been given, + dnl because they are needed for "make dist" to work. + + dnl Search for GNU msgfmt in the PATH. + dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions. + dnl The second test excludes FreeBSD msgfmt. + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [$ac_dir/$ac_word --statistics /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + AC_PATH_PROG([GMSGFMT], [gmsgfmt], [$MSGFMT]) + + dnl Test whether it is GNU msgfmt >= 0.15. +changequote(,)dnl + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([MSGFMT_015]) +changequote(,)dnl + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac +changequote([,])dnl + AC_SUBST([GMSGFMT_015]) + + dnl Search for GNU xgettext 0.12 or newer in the PATH. + dnl The first test excludes Solaris xgettext and early GNU xgettext versions. + dnl The second test excludes FreeBSD xgettext. + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)], + :) + dnl Remove leftover from FreeBSD xgettext call. + rm -f messages.po + + dnl Test whether it is GNU xgettext >= 0.15. +changequote(,)dnl + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac +changequote([,])dnl + AC_SUBST([XGETTEXT_015]) + + dnl Search for GNU msgmerge 0.11 or newer in the PATH. + AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge, + [$ac_dir/$ac_word --update -q /dev/null /dev/null >&]AS_MESSAGE_LOG_FD[ 2>&1], :) + + dnl Installation directories. + dnl Autoconf >= 2.60 defines localedir. For older versions of autoconf, we + dnl have to define it here, so that it can be used in po/Makefile. + test -n "$localedir" || localedir='${datadir}/locale' + AC_SUBST([localedir]) + + dnl Support for AM_XGETTEXT_OPTION. + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + AC_SUBST([XGETTEXT_EXTRA_OPTIONS]) + + AC_CONFIG_COMMANDS([po-directories], [[ + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + done]], + [# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + ]) +]) + +dnl Postprocesses a Makefile in a directory containing PO files. +AC_DEFUN([AM_POSTPROCESS_PO_MAKEFILE], +[ + # When this code is run, in config.status, two variables have already been + # set: + # - OBSOLETE_ALL_LINGUAS is the value of LINGUAS set in configure.in, + # - LINGUAS is the value of the environment variable LINGUAS at configure + # time. + +changequote(,)dnl + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + # Find a way to echo strings without interpreting backslash. + if test "X`(echo '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='echo' + else + if test "X`(printf '%s\n' '\t') 2>/dev/null`" = 'X\t'; then + gt_echo='printf %s\n' + else + echo_func () { + cat <<EOT +$* +EOT + } + gt_echo='echo_func' + fi + fi + + # A sed script that extracts the value of VARIABLE from a Makefile. + tab=`printf '\t'` + sed_x_variable=' +# Test if the hold space is empty. +x +s/P/P/ +x +ta +# Yes it was empty. Look if we have the expected variable definition. +/^['"${tab}"' ]*VARIABLE['"${tab}"' ]*=/{ + # Seen the first line of the variable definition. + s/^['"${tab}"' ]*VARIABLE['"${tab}"' ]*=// + ba +} +bd +:a +# Here we are processing a line from the variable definition. +# Remove comment, more precisely replace it with a space. +s/#.*$/ / +# See if the line ends in a backslash. +tb +:b +s/\\$// +# Print the line, without the trailing backslash. +p +tc +# There was no trailing backslash. The end of the variable definition is +# reached. Clear the hold space. +s/^.*$// +x +bd +:c +# A trailing backslash means that the variable definition continues in the +# next line. Put a nonempty string into the hold space to indicate this. +s/^.*$/P/ +x +:d +' +changequote([,])dnl + + # Set POTFILES to the value of the Makefile variable POTFILES. + sed_x_POTFILES=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/POTFILES/g'` + POTFILES=`sed -n -e "$sed_x_POTFILES" < "$ac_file"` + # Compute POTFILES_DEPS as + # $(foreach file, $(POTFILES), $(top_srcdir)/$(file)) + POTFILES_DEPS= + for file in $POTFILES; do + POTFILES_DEPS="$POTFILES_DEPS "'$(top_srcdir)/'"$file" + done + POMAKEFILEDEPS="" + + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # Set ALL_LINGUAS to the value of the Makefile variable LINGUAS. + sed_x_LINGUAS=`$gt_echo "$sed_x_variable" | sed -e '/^ *#/d' -e 's/VARIABLE/LINGUAS/g'` + ALL_LINGUAS_=`sed -n -e "$sed_x_LINGUAS" < "$ac_file"` + fi + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + # Compute PROPERTIESFILES + # as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).properties) + # Compute CLASSFILES + # as $(foreach lang, $(ALL_LINGUAS), $(top_srcdir)/$(DOMAIN)_$(lang).class) + # Compute QMFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).qm) + # Compute MSGFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang)).msg) + # Compute RESOURCESDLLFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(frob $(lang))/$(DOMAIN).resources.dll) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + PROPERTIESFILES= + CLASSFILES= + QMFILES= + MSGFILES= + RESOURCESDLLFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + PROPERTIESFILES="$PROPERTIESFILES \$(top_srcdir)/\$(DOMAIN)_$lang.properties" + CLASSFILES="$CLASSFILES \$(top_srcdir)/\$(DOMAIN)_$lang.class" + QMFILES="$QMFILES $srcdirpre$lang.qm" + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + MSGFILES="$MSGFILES $srcdirpre$frobbedlang.msg" + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + RESOURCESDLLFILES="$RESOURCESDLLFILES $srcdirpre$frobbedlang/\$(DOMAIN).resources.dll" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + JAVACATALOGS= + QTCATALOGS= + TCLCATALOGS= + CSHARPCATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + JAVACATALOGS="$JAVACATALOGS \$(DOMAIN)_$lang.properties" + QTCATALOGS="$QTCATALOGS $lang.qm" + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + TCLCATALOGS="$TCLCATALOGS $frobbedlang.msg" + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + CSHARPCATALOGS="$CSHARPCATALOGS $frobbedlang/\$(DOMAIN).resources.dll" + done + fi + + sed -e "s|@POTFILES_DEPS@|$POTFILES_DEPS|g" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@PROPERTIESFILES@|$PROPERTIESFILES|g" -e "s|@CLASSFILES@|$CLASSFILES|g" -e "s|@QMFILES@|$QMFILES|g" -e "s|@MSGFILES@|$MSGFILES|g" -e "s|@RESOURCESDLLFILES@|$RESOURCESDLLFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@JAVACATALOGS@|$JAVACATALOGS|g" -e "s|@QTCATALOGS@|$QTCATALOGS|g" -e "s|@TCLCATALOGS@|$TCLCATALOGS|g" -e "s|@CSHARPCATALOGS@|$CSHARPCATALOGS|g" -e 's,^#distdir:,distdir:,' < "$ac_file" > "$ac_file.tmp" + tab=`printf '\t'` + if grep -l '@TCLCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/\..*$//' -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` + cat >> "$ac_file.tmp" <<EOF +$frobbedlang.msg: $lang.po +${tab}@echo "\$(MSGFMT) -c --tcl -d \$(srcdir) -l $lang $srcdirpre$lang.po"; \ +${tab}\$(MSGFMT) -c --tcl -d "\$(srcdir)" -l $lang $srcdirpre$lang.po || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; } +EOF + done + fi + if grep -l '@CSHARPCATALOGS@' "$ac_file" > /dev/null; then + # Add dependencies that cannot be formulated as a simple suffix rule. + for lang in $ALL_LINGUAS; do + frobbedlang=`echo $lang | sed -e 's/_/-/g' -e 's/^sr-CS/sr-SP/' -e 's/@latin$/-Latn/' -e 's/@cyrillic$/-Cyrl/' -e 's/^sr-SP$/sr-SP-Latn/' -e 's/^uz-UZ$/uz-UZ-Latn/'` + cat >> "$ac_file.tmp" <<EOF +$frobbedlang/\$(DOMAIN).resources.dll: $lang.po +${tab}@echo "\$(MSGFMT) -c --csharp -d \$(srcdir) -l $lang $srcdirpre$lang.po -r \$(DOMAIN)"; \ +${tab}\$(MSGFMT) -c --csharp -d "\$(srcdir)" -l $lang $srcdirpre$lang.po -r "\$(DOMAIN)" || { rm -f "\$(srcdir)/$frobbedlang.msg"; exit 1; } +EOF + done + fi + if test -n "$POMAKEFILEDEPS"; then + cat >> "$ac_file.tmp" <<EOF +Makefile: $POMAKEFILEDEPS +EOF + fi + mv "$ac_file.tmp" "$ac_file" +]) + +dnl Initializes the accumulator used by AM_XGETTEXT_OPTION. +AC_DEFUN([AM_XGETTEXT_OPTION_INIT], +[ + XGETTEXT_EXTRA_OPTIONS= +]) + +dnl Registers an option to be passed to xgettext in the po subdirectory. +AC_DEFUN([AM_XGETTEXT_OPTION], +[ + AC_REQUIRE([AM_XGETTEXT_OPTION_INIT]) + XGETTEXT_EXTRA_OPTIONS="$XGETTEXT_EXTRA_OPTIONS $1" +]) + +# printf-posix.m4 serial 6 (gettext-0.18.2) +dnl Copyright (C) 2003, 2007, 2009-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether the printf() function supports POSIX/XSI format strings with +dnl positions. + +AC_DEFUN([gt_PRINTF_POSIX], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_CACHE_CHECK([whether printf() supports POSIX/XSI format strings], + gt_cv_func_printf_posix, + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include <stdio.h> +#include <string.h> +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +}]])], + [gt_cv_func_printf_posix=yes], + [gt_cv_func_printf_posix=no], + [ + AC_EGREP_CPP([notposix], [ +#if defined __NetBSD__ || defined __BEOS__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ + notposix +#endif + ], + [gt_cv_func_printf_posix="guessing no"], + [gt_cv_func_printf_posix="guessing yes"]) + ]) + ]) + case $gt_cv_func_printf_posix in + *yes) + AC_DEFINE([HAVE_POSIX_PRINTF], [1], + [Define if your printf() function supports format strings with positions.]) + ;; + esac +]) + +# progtest.m4 serial 7 (gettext-0.18.2) +dnl Copyright (C) 1996-2003, 2005, 2008-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. +dnl +dnl This file can can be used in projects which are not available under +dnl the GNU General Public License or the GNU Library General Public +dnl License but which still want to provide support for the GNU gettext +dnl functionality. +dnl Please note that the actual code of the GNU gettext library is covered +dnl by the GNU Library General Public License, and the rest of the GNU +dnl gettext package package is covered by the GNU General Public License. +dnl They are *not* in the public domain. + +dnl Authors: +dnl Ulrich Drepper <drepper@cygnus.com>, 1996. + +AC_PREREQ([2.50]) + +# Search path for a program which passes the given test. + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST], +[ +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + 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 + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL([ac_cv_path_$1], +[case "[$]$1" in + [[\\/]]* | ?:[[\\/]]*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in ifelse([$5], , $PATH, [$5]); do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&AS_MESSAGE_LOG_FD + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$][$1]) +else + AC_MSG_RESULT([no]) +fi +AC_SUBST([$1])dnl +]) + +# size_max.m4 serial 10 +dnl Copyright (C) 2003, 2005-2006, 2008-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +AC_DEFUN([gl_SIZE_MAX], +[ + AC_CHECK_HEADERS([stdint.h]) + dnl First test whether the system already has SIZE_MAX. + AC_CACHE_CHECK([for SIZE_MAX], [gl_cv_size_max], [ + gl_cv_size_max= + AC_EGREP_CPP([Found it], [ +#include <limits.h> +#if HAVE_STDINT_H +#include <stdint.h> +#endif +#ifdef SIZE_MAX +Found it +#endif +], [gl_cv_size_max=yes]) + if test -z "$gl_cv_size_max"; then + dnl Define it ourselves. Here we assume that the type 'size_t' is not wider + dnl than the type 'unsigned long'. Try hard to find a definition that can + dnl be used in a preprocessor #if, i.e. doesn't contain a cast. + AC_COMPUTE_INT([size_t_bits_minus_1], [sizeof (size_t) * CHAR_BIT - 1], + [#include <stddef.h> +#include <limits.h>], [size_t_bits_minus_1=]) + AC_COMPUTE_INT([fits_in_uint], [sizeof (size_t) <= sizeof (unsigned int)], + [#include <stddef.h>], [fits_in_uint=]) + if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then + if test $fits_in_uint = 1; then + dnl Even though SIZE_MAX fits in an unsigned int, it must be of type + dnl 'unsigned long' if the type 'size_t' is the same as 'unsigned long'. + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <stddef.h> + extern size_t foo; + extern unsigned long foo; + ]], + [[]])], + [fits_in_uint=0]) + fi + dnl We cannot use 'expr' to simplify this expression, because 'expr' + dnl works only with 'long' integers in the host environment, while we + dnl might be cross-compiling from a 32-bit platform to a 64-bit platform. + if test $fits_in_uint = 1; then + gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" + else + gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" + fi + else + dnl Shouldn't happen, but who knows... + gl_cv_size_max='((size_t)~(size_t)0)' + fi + fi + ]) + if test "$gl_cv_size_max" != yes; then + AC_DEFINE_UNQUOTED([SIZE_MAX], [$gl_cv_size_max], + [Define as the maximum value of type 'size_t', if the system doesn't define it.]) + fi + dnl Don't redefine SIZE_MAX in config.h if config.h is re-included after + dnl <stdint.h>. Remember that the #undef in AH_VERBATIM gets replaced with + dnl #define by AC_DEFINE_UNQUOTED. + AH_VERBATIM([SIZE_MAX], +[/* Define as the maximum value of type 'size_t', if the system doesn't define + it. */ +#ifndef SIZE_MAX +# undef SIZE_MAX +#endif]) +]) + +dnl Autoconf >= 2.61 has AC_COMPUTE_INT built-in. +dnl Remove this when we can assume autoconf >= 2.61. +m4_ifdef([AC_COMPUTE_INT], [], [ + AC_DEFUN([AC_COMPUTE_INT], [_AC_COMPUTE_INT([$2],[$1],[$3],[$4])]) +]) + +# stdint_h.m4 serial 9 +dnl Copyright (C) 1997-2004, 2006, 2008-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +# Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists, +# doesn't clash with <sys/types.h>, and declares uintmax_t. + +AC_DEFUN([gl_AC_HEADER_STDINT_H], +[ + AC_CACHE_CHECK([for stdint.h], [gl_cv_header_stdint_h], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sys/types.h> + #include <stdint.h>]], + [[uintmax_t i = (uintmax_t) -1; return !i;]])], + [gl_cv_header_stdint_h=yes], + [gl_cv_header_stdint_h=no])]) + if test $gl_cv_header_stdint_h = yes; then + AC_DEFINE_UNQUOTED([HAVE_STDINT_H_WITH_UINTMAX], [1], + [Define if <stdint.h> exists, doesn't clash with <sys/types.h>, + and declares uintmax_t. ]) + fi +]) + +# threadlib.m4 serial 10 (gettext-0.18.2) +dnl Copyright (C) 2005-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl gl_THREADLIB +dnl ------------ +dnl Tests for a multithreading library to be used. +dnl If the configure.ac contains a definition of the gl_THREADLIB_DEFAULT_NO +dnl (it must be placed before the invocation of gl_THREADLIB_EARLY!), then the +dnl default is 'no', otherwise it is system dependent. In both cases, the user +dnl can change the choice through the options --enable-threads=choice or +dnl --disable-threads. +dnl Defines at most one of the macros USE_POSIX_THREADS, USE_SOLARIS_THREADS, +dnl USE_PTH_THREADS, USE_WINDOWS_THREADS +dnl Sets the variables LIBTHREAD and LTLIBTHREAD to the linker options for use +dnl in a Makefile (LIBTHREAD for use without libtool, LTLIBTHREAD for use with +dnl libtool). +dnl Sets the variables LIBMULTITHREAD and LTLIBMULTITHREAD similarly, for +dnl programs that really need multithread functionality. The difference +dnl between LIBTHREAD and LIBMULTITHREAD is that on platforms supporting weak +dnl symbols, typically LIBTHREAD="" whereas LIBMULTITHREAD="-lpthread". +dnl Adds to CPPFLAGS the flag -D_REENTRANT or -D_THREAD_SAFE if needed for +dnl multithread-safe programs. + +AC_DEFUN([gl_THREADLIB_EARLY], +[ + AC_REQUIRE([gl_THREADLIB_EARLY_BODY]) +]) + +dnl The guts of gl_THREADLIB_EARLY. Needs to be expanded only once. + +AC_DEFUN([gl_THREADLIB_EARLY_BODY], +[ + dnl Ordering constraints: This macro modifies CPPFLAGS in a way that + dnl influences the result of the autoconf tests that test for *_unlocked + dnl declarations, on AIX 5 at least. Therefore it must come early. + AC_BEFORE([$0], [gl_FUNC_GLIBC_UNLOCKED_IO])dnl + AC_BEFORE([$0], [gl_ARGP])dnl + + AC_REQUIRE([AC_CANONICAL_HOST]) + dnl _GNU_SOURCE is needed for pthread_rwlock_t on glibc systems. + dnl AC_USE_SYSTEM_EXTENSIONS was introduced in autoconf 2.60 and obsoletes + dnl AC_GNU_SOURCE. + m4_ifdef([AC_USE_SYSTEM_EXTENSIONS], + [AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])], + [AC_REQUIRE([AC_GNU_SOURCE])]) + dnl Check for multithreading. + m4_ifdef([gl_THREADLIB_DEFAULT_NO], + [m4_divert_text([DEFAULTS], [gl_use_threads_default=no])], + [m4_divert_text([DEFAULTS], [gl_use_threads_default=])]) + AC_ARG_ENABLE([threads], +AC_HELP_STRING([--enable-threads={posix|solaris|pth|windows}], [specify multithreading API])m4_ifdef([gl_THREADLIB_DEFAULT_NO], [], [ +AC_HELP_STRING([--disable-threads], [build without multithread safety])]), + [gl_use_threads=$enableval], + [if test -n "$gl_use_threads_default"; then + gl_use_threads="$gl_use_threads_default" + else +changequote(,)dnl + case "$host_os" in + dnl Disable multithreading by default on OSF/1, because it interferes + dnl with fork()/exec(): When msgexec is linked with -lpthread, its + dnl child process gets an endless segmentation fault inside execvp(). + dnl Disable multithreading by default on Cygwin 1.5.x, because it has + dnl bugs that lead to endless loops or crashes. See + dnl <http://cygwin.com/ml/cygwin/2009-08/msg00283.html>. + osf*) gl_use_threads=no ;; + cygwin*) + case `uname -r` in + 1.[0-5].*) gl_use_threads=no ;; + *) gl_use_threads=yes ;; + esac + ;; + *) gl_use_threads=yes ;; + esac +changequote([,])dnl + fi + ]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # For using <pthread.h>: + case "$host_os" in + osf*) + # On OSF/1, the compiler needs the flag -D_REENTRANT so that it + # groks <pthread.h>. cc also understands the flag -pthread, but + # we don't use it because 1. gcc-2.95 doesn't understand -pthread, + # 2. putting a flag into CPPFLAGS that has an effect on the linker + # causes the AC_LINK_IFELSE test below to succeed unexpectedly, + # leading to wrong values of LIBTHREAD and LTLIBTHREAD. + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + ;; + esac + # Some systems optimize for single-threaded programs by default, and + # need special flags to disable these optimizations. For example, the + # definition of 'errno' in <errno.h>. + case "$host_os" in + aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;; + solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; + esac + fi +]) + +dnl The guts of gl_THREADLIB. Needs to be expanded only once. + +AC_DEFUN([gl_THREADLIB_BODY], +[ + AC_REQUIRE([gl_THREADLIB_EARLY_BODY]) + gl_threads_api=none + LIBTHREAD= + LTLIBTHREAD= + LIBMULTITHREAD= + LTLIBMULTITHREAD= + if test "$gl_use_threads" != no; then + dnl Check whether the compiler and linker support weak declarations. + AC_CACHE_CHECK([whether imported symbols can be declared weak], + [gl_cv_have_weak], + [gl_cv_have_weak=no + dnl First, test whether the compiler accepts it syntactically. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[extern void xyzzy (); +#pragma weak xyzzy]], + [[xyzzy();]])], + [gl_cv_have_weak=maybe]) + if test $gl_cv_have_weak = maybe; then + dnl Second, test whether it actually works. On Cygwin 1.7.2, with + dnl gcc 4.3, symbols declared weak always evaluate to the address 0. + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include <stdio.h> +#pragma weak fputs +int main () +{ + return (fputs == NULL); +}]])], + [gl_cv_have_weak=yes], + [gl_cv_have_weak=no], + [dnl When cross-compiling, assume that only ELF platforms support + dnl weak symbols. + AC_EGREP_CPP([Extensible Linking Format], + [#ifdef __ELF__ + Extensible Linking Format + #endif + ], + [gl_cv_have_weak="guessing yes"], + [gl_cv_have_weak="guessing no"]) + ]) + fi + ]) + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that + # it groks <pthread.h>. It's added above, in gl_THREADLIB_EARLY_BODY. + AC_CHECK_HEADER([pthread.h], + [gl_have_pthread_h=yes], [gl_have_pthread_h=no]) + if test "$gl_have_pthread_h" = yes; then + # Other possible tests: + # -lpthreads (FSU threads, PCthreads) + # -lgthreads + gl_have_pthread= + # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist + # in libc. IRIX 6.5 has the first one in both libc and libpthread, but + # the second one only in libpthread, and lock.c needs it. + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include <pthread.h>]], + [[pthread_mutex_lock((pthread_mutex_t*)0); + pthread_mutexattr_init((pthread_mutexattr_t*)0);]])], + [gl_have_pthread=yes]) + # Test for libpthread by looking for pthread_kill. (Not pthread_self, + # since it is defined as a macro on OSF/1.) + if test -n "$gl_have_pthread"; then + # The program links fine without libpthread. But it may actually + # need to link with libpthread in order to create multiple threads. + AC_CHECK_LIB([pthread], [pthread_kill], + [LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread + # On Solaris and HP-UX, most pthread functions exist also in libc. + # Therefore pthread_in_use() needs to actually try to create a + # thread: pthread_create from libc will fail, whereas + # pthread_create will actually create a thread. + case "$host_os" in + solaris* | hpux*) + AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], [1], + [Define if the pthread_in_use() detection is hard.]) + esac + ]) + else + # Some library is needed. Try libpthread and libc_r. + AC_CHECK_LIB([pthread], [pthread_kill], + [gl_have_pthread=yes + LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread]) + if test -z "$gl_have_pthread"; then + # For FreeBSD 4. + AC_CHECK_LIB([c_r], [pthread_kill], + [gl_have_pthread=yes + LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r + LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r]) + fi + fi + if test -n "$gl_have_pthread"; then + gl_threads_api=posix + AC_DEFINE([USE_POSIX_THREADS], [1], + [Define if the POSIX multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_POSIX_THREADS_WEAK], [1], + [Define if references to the POSIX multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then + gl_have_solaristhread= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lthread" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[ +#include <thread.h> +#include <synch.h> + ]], + [[thr_self();]])], + [gl_have_solaristhread=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_solaristhread"; then + gl_threads_api=solaris + LIBTHREAD=-lthread + LTLIBTHREAD=-lthread + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_SOLARIS_THREADS], [1], + [Define if the old Solaris multithreading library can be used.]) + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_SOLARIS_THREADS_WEAK], [1], + [Define if references to the old Solaris multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + if test "$gl_use_threads" = pth; then + gl_save_CPPFLAGS="$CPPFLAGS" + AC_LIB_LINKFLAGS([pth]) + gl_have_pth= + gl_save_LIBS="$LIBS" + LIBS="$LIBS $LIBPTH" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[#include <pth.h>]], [[pth_self();]])], + [gl_have_pth=yes]) + LIBS="$gl_save_LIBS" + if test -n "$gl_have_pth"; then + gl_threads_api=pth + LIBTHREAD="$LIBPTH" + LTLIBTHREAD="$LTLIBPTH" + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + AC_DEFINE([USE_PTH_THREADS], [1], + [Define if the GNU Pth multithreading library can be used.]) + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + AC_DEFINE([USE_PTH_THREADS_WEAK], [1], + [Define if references to the GNU Pth multithreading library should be made weak.]) + LIBTHREAD= + LTLIBTHREAD= + fi + fi + else + CPPFLAGS="$gl_save_CPPFLAGS" + fi + fi + if test -z "$gl_have_pthread"; then + case "$gl_use_threads" in + yes | windows | win32) # The 'win32' is for backward compatibility. + if { case "$host_os" in + mingw*) true;; + *) false;; + esac + }; then + gl_threads_api=windows + AC_DEFINE([USE_WINDOWS_THREADS], [1], + [Define if the native Windows multithreading API can be used.]) + fi + ;; + esac + fi + fi + AC_MSG_CHECKING([for multithread API to use]) + AC_MSG_RESULT([$gl_threads_api]) + AC_SUBST([LIBTHREAD]) + AC_SUBST([LTLIBTHREAD]) + AC_SUBST([LIBMULTITHREAD]) + AC_SUBST([LTLIBMULTITHREAD]) +]) + +AC_DEFUN([gl_THREADLIB], +[ + AC_REQUIRE([gl_THREADLIB_EARLY]) + AC_REQUIRE([gl_THREADLIB_BODY]) +]) + + +dnl gl_DISABLE_THREADS +dnl ------------------ +dnl Sets the gl_THREADLIB default so that threads are not used by default. +dnl The user can still override it at installation time, by using the +dnl configure option '--enable-threads'. + +AC_DEFUN([gl_DISABLE_THREADS], [ + m4_divert_text([INIT_PREPARE], [gl_use_threads_default=no]) +]) + + +dnl Survey of platforms: +dnl +dnl Platform Available Compiler Supports test-lock +dnl flavours option weak result +dnl --------------- --------- --------- -------- --------- +dnl Linux 2.4/glibc posix -lpthread Y OK +dnl +dnl GNU Hurd/glibc posix +dnl +dnl FreeBSD 5.3 posix -lc_r Y +dnl posix -lkse ? Y +dnl posix -lpthread ? Y +dnl posix -lthr Y +dnl +dnl FreeBSD 5.2 posix -lc_r Y +dnl posix -lkse Y +dnl posix -lthr Y +dnl +dnl FreeBSD 4.0,4.10 posix -lc_r Y OK +dnl +dnl NetBSD 1.6 -- +dnl +dnl OpenBSD 3.4 posix -lpthread Y OK +dnl +dnl Mac OS X 10.[123] posix -lpthread Y OK +dnl +dnl Solaris 7,8,9 posix -lpthread Y Sol 7,8: 0.0; Sol 9: OK +dnl solaris -lthread Y Sol 7,8: 0.0; Sol 9: OK +dnl +dnl HP-UX 11 posix -lpthread N (cc) OK +dnl Y (gcc) +dnl +dnl IRIX 6.5 posix -lpthread Y 0.5 +dnl +dnl AIX 4.3,5.1 posix -lpthread N AIX 4: 0.5; AIX 5: OK +dnl +dnl OSF/1 4.0,5.1 posix -pthread (cc) N OK +dnl -lpthread (gcc) Y +dnl +dnl Cygwin posix -lpthread Y OK +dnl +dnl Any of the above pth -lpth 0.0 +dnl +dnl Mingw windows N OK +dnl +dnl BeOS 5 -- +dnl +dnl The test-lock result shows what happens if in test-lock.c EXPLICIT_YIELD is +dnl turned off: +dnl OK if all three tests terminate OK, +dnl 0.5 if the first test terminates OK but the second one loops endlessly, +dnl 0.0 if the first test already loops endlessly. + +# uintmax_t.m4 serial 12 +dnl Copyright (C) 1997-2004, 2007-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Paul Eggert. + +AC_PREREQ([2.13]) + +# Define uintmax_t to 'unsigned long' or 'unsigned long long' +# if it is not already defined in <stdint.h> or <inttypes.h>. + +AC_DEFUN([gl_AC_TYPE_UINTMAX_T], +[ + AC_REQUIRE([gl_AC_HEADER_INTTYPES_H]) + AC_REQUIRE([gl_AC_HEADER_STDINT_H]) + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + AC_REQUIRE([AC_TYPE_UNSIGNED_LONG_LONG_INT]) + test $ac_cv_type_unsigned_long_long_int = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + AC_DEFINE_UNQUOTED([uintmax_t], [$ac_type], + [Define to unsigned long or unsigned long long + if <stdint.h> and <inttypes.h> don't define.]) + else + AC_DEFINE([HAVE_UINTMAX_T], [1], + [Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>.]) + fi +]) + +# visibility.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2005, 2008, 2010-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. + +dnl Tests whether the compiler supports the command-line option +dnl -fvisibility=hidden and the function and variable attributes +dnl __attribute__((__visibility__("hidden"))) and +dnl __attribute__((__visibility__("default"))). +dnl Does *not* test for __visibility__("protected") - which has tricky +dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on +dnl Mac OS X. +dnl Does *not* test for __visibility__("internal") - which has processor +dnl dependent semantics. +dnl Does *not* test for #pragma GCC visibility push(hidden) - which is +dnl "really only recommended for legacy code". +dnl Set the variable CFLAG_VISIBILITY. +dnl Defines and sets the variable HAVE_VISIBILITY. + +AC_DEFUN([gl_VISIBILITY], +[ + AC_REQUIRE([AC_PROG_CC]) + CFLAG_VISIBILITY= + HAVE_VISIBILITY=0 + if test -n "$GCC"; then + dnl First, check whether -Werror can be added to the command line, or + dnl whether it leads to an error because of some other option that the + dnl user has put into $CC $CFLAGS $CPPFLAGS. + AC_MSG_CHECKING([whether the -Werror option is usable]) + AC_CACHE_VAL([gl_cv_cc_vis_werror], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[]], [[]])], + [gl_cv_cc_vis_werror=yes], + [gl_cv_cc_vis_werror=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_vis_werror]) + dnl Now check whether visibility declarations are supported. + AC_MSG_CHECKING([for simple visibility declarations]) + AC_CACHE_VAL([gl_cv_cc_visibility], [ + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fvisibility=hidden" + dnl We use the option -Werror and a function dummyfunc, because on some + dnl platforms (Cygwin 1.7) the use of -fvisibility triggers a warning + dnl "visibility attribute not supported in this configuration; ignored" + dnl at the first function definition in every compilation unit, and we + dnl don't want to use the option in this case. + if test $gl_cv_cc_vis_werror = yes; then + CFLAGS="$CFLAGS -Werror" + fi + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[extern __attribute__((__visibility__("hidden"))) int hiddenvar; + extern __attribute__((__visibility__("default"))) int exportedvar; + extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); + extern __attribute__((__visibility__("default"))) int exportedfunc (void); + void dummyfunc (void) {} + ]], + [[]])], + [gl_cv_cc_visibility=yes], + [gl_cv_cc_visibility=no]) + CFLAGS="$gl_save_CFLAGS"]) + AC_MSG_RESULT([$gl_cv_cc_visibility]) + if test $gl_cv_cc_visibility = yes; then + CFLAG_VISIBILITY="-fvisibility=hidden" + HAVE_VISIBILITY=1 + fi + fi + AC_SUBST([CFLAG_VISIBILITY]) + AC_SUBST([HAVE_VISIBILITY]) + AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY], + [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.]) +]) + +# wchar_t.m4 serial 4 (gettext-0.18.2) +dnl Copyright (C) 2002-2003, 2008-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether <stddef.h> has the 'wchar_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WCHAR_T], +[ + AC_CACHE_CHECK([for wchar_t], [gt_cv_c_wchar_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <stddef.h> + wchar_t foo = (wchar_t)'\0';]], + [[]])], + [gt_cv_c_wchar_t=yes], + [gt_cv_c_wchar_t=no])]) + if test $gt_cv_c_wchar_t = yes; then + AC_DEFINE([HAVE_WCHAR_T], [1], [Define if you have the 'wchar_t' type.]) + fi +]) + +# wint_t.m4 serial 5 (gettext-0.18.2) +dnl Copyright (C) 2003, 2007-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl From Bruno Haible. +dnl Test whether <wchar.h> has the 'wint_t' type. +dnl Prerequisite: AC_PROG_CC + +AC_DEFUN([gt_TYPE_WINT_T], +[ + AC_CACHE_CHECK([for wint_t], [gt_cv_c_wint_t], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[ +/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before + <wchar.h>. + BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be included + before <wchar.h>. */ +#include <stddef.h> +#include <stdio.h> +#include <time.h> +#include <wchar.h> + wint_t foo = (wchar_t)'\0';]], + [[]])], + [gt_cv_c_wint_t=yes], + [gt_cv_c_wint_t=no])]) + if test $gt_cv_c_wint_t = yes; then + AC_DEFINE([HAVE_WINT_T], [1], [Define if you have the 'wint_t' type.]) + fi +]) + +# xsize.m4 serial 5 +dnl Copyright (C) 2003-2004, 2008-2013 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_XSIZE], +[ + dnl Prerequisites of lib/xsize.h. + AC_REQUIRE([gl_SIZE_MAX]) + AC_CHECK_HEADERS([stdint.h]) +]) + +m4_include([acinclude.m4])
diff --git a/config/config.guess b/config/config.guess new file mode 100644 index 0000000..1f5c50c --- /dev/null +++ b/config/config.guess
@@ -0,0 +1,1420 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2014 Free Software Foundation, Inc. + +timestamp='2014-03-23' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches with a ChangeLog entry to config-patches@gnu.org. + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2014 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include <features.h> + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End:
diff --git a/config/config.rpath b/config/config.rpath new file mode 100755 index 0000000..c38b914 --- /dev/null +++ b/config/config.rpath
@@ -0,0 +1,690 @@ +#! /bin/sh +# Output a system dependent set of variables, describing how to set the +# run time search path of shared libraries in an executable. +# +# Copyright 1996-2013 Free Software Foundation, Inc. +# Taken from GNU libtool, 2001 +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# 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. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld +# should be set by the caller. +# +# The set of defined variables is at the end of this script. + +# Known limitations: +# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer +# than 256 bytes, otherwise the compiler driver will dump core. The only +# known workaround is to choose shorter directory names for the build +# directory and/or the installation directory. + +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +shrext=.so + +host="$1" +host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +# Code taken from libtool.m4's _LT_CC_BASENAME. + +for cc_temp in $CC""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` + +# Code taken from libtool.m4's _LT_COMPILER_PIC. + +wl= +if test "$GCC" = yes; then + wl='-Wl,' +else + case "$host_os" in + aix*) + wl='-Wl,' + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) + ;; + hpux9* | hpux10* | hpux11*) + wl='-Wl,' + ;; + irix5* | irix6* | nonstopux*) + wl='-Wl,' + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + ecc*) + wl='-Wl,' + ;; + icc* | ifort*) + wl='-Wl,' + ;; + lf95*) + wl='-Wl,' + ;; + nagfor*) + wl='-Wl,-Wl,,' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + wl='-Wl,' + ;; + ccc*) + wl='-Wl,' + ;; + xl* | bgxl* | bgf* | mpixl*) + wl='-Wl,' + ;; + como) + wl='-lopt=' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + wl= + ;; + *Sun\ C*) + wl='-Wl,' + ;; + esac + ;; + esac + ;; + newsos6) + ;; + *nto* | *qnx*) + ;; + osf3* | osf4* | osf5*) + wl='-Wl,' + ;; + rdos*) + ;; + solaris*) + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + wl='-Qoption ld ' + ;; + *) + wl='-Wl,' + ;; + esac + ;; + sunos4*) + wl='-Qoption ld ' + ;; + sysv4 | sysv4.2uw2* | sysv4.3*) + wl='-Wl,' + ;; + sysv4*MP*) + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + wl='-Wl,' + ;; + unicos*) + wl='-Wl,' + ;; + uts4*) + ;; + esac +fi + +# Code taken from libtool.m4's _LT_LINKER_SHLIBS. + +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no + +case "$host_os" in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + # Unlike libtool, we use -rpath here, not --rpath, since the documented + # option of GNU ld is called -rpath, not --rpath. + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + case "$host_os" in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + fi + ;; + amigaos*) + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + cygwin* | mingw* | pw32* | cegcc*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + haiku*) + ;; + interix[3-9]*) + hardcode_direct=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + netbsd*) + ;; + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + else + ld_shlibs=no + fi + ;; + esac + ;; + sunos4*) + hardcode_direct=yes + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + : + else + ld_shlibs=no + fi + ;; + esac + if test "$ld_shlibs" = no; then + hardcode_libdir_flag_spec= + fi +else + case "$host_os" in + aix3*) + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + else + aix_use_runtimelinking=no + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + fi + hardcode_direct=yes + hardcode_libdir_separator=':' + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + fi + # Begin _LT_AC_SYS_LIBPATH_AIX. + echo 'int main () { return 0; }' > conftest.c + ${CC} ${LDFLAGS} conftest.c -o conftest + aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` + fi + if test -z "$aix_libpath"; then + aix_libpath="/usr/lib:/lib" + fi + rm -f conftest.c conftest + # End _LT_AC_SYS_LIBPATH_AIX. + if test "$aix_use_runtimelinking" = yes; then + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + else + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + fi + fi + ;; + amigaos*) + case "$host_cpu" in + powerpc) + ;; + m68k) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + bsdi[45]*) + ;; + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + libext=lib + ;; + darwin* | rhapsody*) + hardcode_direct=no + if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then + : + else + ld_shlibs=no + fi + ;; + dgux*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + freebsd2.2*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + freebsd2*) + hardcode_direct=yes + hardcode_minus_L=yes + ;; + freebsd* | dragonfly*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + hpux9*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + hpux10*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + hpux11*) + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + ;; + *) + hardcode_direct=yes + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + irix5* | irix6* | nonstopux*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + netbsd*) + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + ;; + newsos6) + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + *nto* | *qnx*) + ;; + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + else + case "$host_os" in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + osf3*) + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + osf4* | osf5*) + if test "$GCC" = yes; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + # Both cc and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + solaris*) + hardcode_libdir_flag_spec='-R$libdir' + ;; + sunos4*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + sysv4) + case $host_vendor in + sni) + hardcode_direct=yes # is this really true??? + ;; + siemens) + hardcode_direct=no + ;; + motorola) + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + ;; + sysv4.3*) + ;; + sysv4*MP*) + if test -d /usr/nec; then + ld_shlibs=yes + fi + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + ;; + sysv5* | sco3.2v5* | sco5v6*) + hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + hardcode_libdir_separator=':' + ;; + uts4*) + hardcode_libdir_flag_spec='-L$libdir' + ;; + *) + ld_shlibs=no + ;; + esac +fi + +# Check dynamic linker characteristics +# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. +# Unlike libtool.m4, here we don't care about _all_ names of the library, but +# only about the one the linker finds when passed -lNAME. This is the last +# element of library_names_spec in libtool.m4, or possibly two of them if the +# linker has special search rules. +library_names_spec= # the last element of library_names_spec in libtool.m4 +libname_spec='lib$name' +case "$host_os" in + aix3*) + library_names_spec='$libname.a' + ;; + aix[4-9]*) + library_names_spec='$libname$shrext' + ;; + amigaos*) + case "$host_cpu" in + powerpc*) + library_names_spec='$libname$shrext' ;; + m68k) + library_names_spec='$libname.a' ;; + esac + ;; + beos*) + library_names_spec='$libname$shrext' + ;; + bsdi[45]*) + library_names_spec='$libname$shrext' + ;; + cygwin* | mingw* | pw32* | cegcc*) + shrext=.dll + library_names_spec='$libname.dll.a $libname.lib' + ;; + darwin* | rhapsody*) + shrext=.dylib + library_names_spec='$libname$shrext' + ;; + dgux*) + library_names_spec='$libname$shrext' + ;; + freebsd* | dragonfly*) + case "$host_os" in + freebsd[123]*) + library_names_spec='$libname$shrext$versuffix' ;; + *) + library_names_spec='$libname$shrext' ;; + esac + ;; + gnu*) + library_names_spec='$libname$shrext' + ;; + haiku*) + library_names_spec='$libname$shrext' + ;; + hpux9* | hpux10* | hpux11*) + case $host_cpu in + ia64*) + shrext=.so + ;; + hppa*64*) + shrext=.sl + ;; + *) + shrext=.sl + ;; + esac + library_names_spec='$libname$shrext' + ;; + interix[3-9]*) + library_names_spec='$libname$shrext' + ;; + irix5* | irix6* | nonstopux*) + library_names_spec='$libname$shrext' + case "$host_os" in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; + *) libsuff= shlibsuff= ;; + esac + ;; + esac + ;; + linux*oldld* | linux*aout* | linux*coff*) + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + library_names_spec='$libname$shrext' + ;; + knetbsd*-gnu) + library_names_spec='$libname$shrext' + ;; + netbsd*) + library_names_spec='$libname$shrext' + ;; + newsos6) + library_names_spec='$libname$shrext' + ;; + *nto* | *qnx*) + library_names_spec='$libname$shrext' + ;; + openbsd*) + library_names_spec='$libname$shrext$versuffix' + ;; + os2*) + libname_spec='$name' + shrext=.dll + library_names_spec='$libname.a' + ;; + osf3* | osf4* | osf5*) + library_names_spec='$libname$shrext' + ;; + rdos*) + ;; + solaris*) + library_names_spec='$libname$shrext' + ;; + sunos4*) + library_names_spec='$libname$shrext$versuffix' + ;; + sysv4 | sysv4.3*) + library_names_spec='$libname$shrext' + ;; + sysv4*MP*) + library_names_spec='$libname$shrext' + ;; + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + library_names_spec='$libname$shrext' + ;; + tpf*) + library_names_spec='$libname$shrext' + ;; + uts4*) + library_names_spec='$libname$shrext' + ;; +esac + +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' +escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` +shlibext=`echo "$shrext" | sed -e 's,^\.,,'` +escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` +escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` + +LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF + +# How to pass a linker flag through the compiler. +wl="$escaped_wl" + +# Static library suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally "so"). +shlibext="$shlibext" + +# Format of library name prefix. +libname_spec="$escaped_libname_spec" + +# Library names that the linker finds when passed -lNAME. +library_names_spec="$escaped_library_names_spec" + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="$hardcode_libdir_separator" + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct="$hardcode_direct" + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L="$hardcode_minus_L" + +EOF
diff --git a/config/config.sub b/config/config.sub new file mode 100644 index 0000000..d654d03 --- /dev/null +++ b/config/config.sub
@@ -0,0 +1,1794 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2014 Free Software Foundation, Inc. + +timestamp='2014-05-01' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2014 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End:
diff --git a/config/install-sh b/config/install-sh new file mode 100755 index 0000000..89fc9b0 --- /dev/null +++ b/config/install-sh
@@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# 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. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +tranformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# 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 $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0
diff --git a/config/mkinstalldirs b/config/mkinstalldirs new file mode 100755 index 0000000..4f58503 --- /dev/null +++ b/config/mkinstalldirs
@@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman <friedman@prep.ai.mit.edu> +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here
diff --git a/config/parse-types.sh b/config/parse-types.sh new file mode 100755 index 0000000..24d2a99 --- /dev/null +++ b/config/parse-types.sh
@@ -0,0 +1,127 @@ +#!/bin/sh + +cat > sed.script << "EOF" +/^#/d +/^$/d +s/__extension__ // +s/typedef \(.*\) __u\([1-9]*\);/#define __U\2_TYPEDEF \1/ +s/typedef \(.*\) __s\([1-9]*\);/#define __S\2_TYPEDEF \1/ +EOF + +if test -z "$CC"; then + CC=gcc +fi + +if test -z "$CPP"; then + CPP="$CC -E" +fi + +/bin/echo -n "checking for __uNN types... " +# can't check [ -f /usr/include/asm/types.h ] directly, since +# the include path might be different if cross-compiling +if echo '#include <asm/types.h>' | $CPP - 2> parse-types.log | \ + sed -f sed.script | grep '^#' > asm_types.h; then + echo "using <asm/types.h>" +else + echo "using generic types" +fi + +rm sed.script + +cp asm_types.h asm_types.c + +cat >> asm_types.c <<EOF +#include <stdio.h> +#include <stdlib.h> +int main(int argc, char **argv) +{ +#ifdef __U8_TYPEDEF + if (sizeof(__U8_TYPEDEF) != 1) { + printf("Sizeof(__U8__TYPEDEF) is %d should be 1\n", + (int) sizeof(__U8_TYPEDEF)); + exit(1); + } +#elif defined(__linux__) +#warning __U8_TYPEDEF not defined +#endif +#ifdef __S8_TYPEDEF + if (sizeof(__S8_TYPEDEF) != 1) { + printf("Sizeof(_S8__TYPEDEF) is %d should be 1\n", + (int) sizeof(__S8_TYPEDEF)); + exit(1); + } +#elif defined(__linux__) +#warning __S8_TYPEDEF not defined +#endif +#ifdef __U16_TYPEDEF + if (sizeof(__U16_TYPEDEF) != 2) { + printf("Sizeof(__U16__TYPEDEF) is %d should be 2\n", + (int) sizeof(__U16_TYPEDEF)); + exit(1); + } +#elif defined(__linux__) +#warning __U16_TYPEDEF not defined +#endif +#ifdef __S16_TYPEDEF + if (sizeof(__S16_TYPEDEF) != 2) { + printf("Sizeof(__S16__TYPEDEF) is %d should be 2\n", + (int) sizeof(__S16_TYPEDEF)); + exit(1); + } +#elif defined(__linux__) +#warning __S16_TYPEDEF not defined +#endif + +#ifdef __U32_TYPEDEF + if (sizeof(__U32_TYPEDEF) != 4) { + printf("Sizeof(__U32__TYPEDEF) is %d should be 4\n", + (int) sizeof(__U32_TYPEDEF)); + exit(1); + } +#elif defined(__linux__) +#warning __U32_TYPEDEF not defined +#endif +#ifdef __S32_TYPEDEF + if (sizeof(__S32_TYPEDEF) != 4) { + printf("Sizeof(__S32__TYPEDEF) is %d should be 4\n", + (int) sizeof(__S32_TYPEDEF)); + exit(1); + } +#elif defined(__linux__) +#warning __S32_TYPEDEF not defined +#endif + +#ifdef __U64_TYPEDEF + if (sizeof(__U64_TYPEDEF) != 8) { + printf("Sizeof(__U64__TYPEDEF) is %d should be 8\n", + (int) sizeof(__U64_TYPEDEF)); + exit(1); + } +#elif defined(__linux__) +#warning __U64_TYPEDEF not defined +#endif +#ifdef __S64_TYPEDEF + if (sizeof(__S64_TYPEDEF) != 8) { + printf("Sizeof(__S64__TYPEDEF) is %d should be 8\n", + (int) sizeof(__S64_TYPEDEF)); + exit(1); + } +#elif defined(__linux__) +#warning __S64_TYPEDEF not defined +#endif + return 0; +} +EOF + +${BUILD_CC-${CC-gcc}} -o asm_types asm_types.c +if ./asm_types +then + true +else + if [ "${CROSS_COMPILE}" != "1" ]; then + echo "Problem detected with asm_types.h" + echo "" > asm_types.h + fi +fi +rm asm_types.c asm_types +
diff --git a/configure b/configure new file mode 100755 index 0000000..f9de3f6 --- /dev/null +++ b/configure
@@ -0,0 +1,14903 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 </dev/null +exec 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="version.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +gt_needs= +ac_header_list= +gl_use_threads_default= +ac_func_list= +ac_subst_vars='LTLIBOBJS +LIBOBJS +BUILD_LDFLAGS +BUILD_CFLAGS +MKINSTALLDIRS +INCLUDES +DO_TEST_SUITE +ET_DIR +SS_DIR +LDFLAG_STATIC +root_sysconfdir +root_libdir +root_sbindir +root_bindir +root_prefix +UNIX_CMT +CYGWIN_CMT +LINUX_CMT +UNI_DIFF_OPTS +SEM_INIT_LIB +SOCKET_LIB +SIZEOF_OFF_T +SIZEOF_LONG_LONG +SIZEOF_LONG +SIZEOF_INT +SIZEOF_SHORT +BUILD_CC +MAKEINFO +STRIP +AR +LDCONFIG +PERL +AWK +CHMOD +RM +CP +MV +LN_S +LN +ifNotGNUmake +ifGNUmake +BINARY_TYPE +POSUB +LTLIBINTL +LIBINTL +INTLLIBS +INTL_LIBTOOL_SUFFIX_PREFIX +INTLOBJS +GENCAT +INSTOBJEXT +DATADIRNAME +CATOBJEXT +USE_INCLUDED_LIBINTL +BUILD_INCLUDED_LIBINTL +LTLIBC +WINDRES +WOE32 +WOE32DLL +HAVE_WPRINTF +HAVE_NEWLOCALE +HAVE_SNPRINTF +HAVE_ASPRINTF +HAVE_POSIX_PRINTF +INTL_DEFAULT_VERBOSITY +INTL_MACOSX_LIBS +GLIBC21 +INTLBISON +LTLIBICONV +LIBICONV +LTLIBMULTITHREAD +LIBMULTITHREAD +LTLIBTHREAD +LIBTHREAD +LIBPTH_PREFIX +LTLIBPTH +LIBPTH +PRI_MACROS_BROKEN +ALLOCA +HAVE_VISIBILITY +CFLAG_VISIBILITY +RANLIB +GLIBC2 +XGETTEXT_EXTRA_OPTIONS +MSGMERGE +XGETTEXT_015 +XGETTEXT +GMSGFMT_015 +MSGFMT_015 +GMSGFMT +MSGFMT +GETTEXT_MACRO_VERSION +USE_NLS +SED +MKDIR_P +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +SET_MAKE +VERSION +PACKAGE +GETTEXT_PACKAGE +UUIDD_CMT +E2INITRD_MAN +E2INITRD_PROG +FSCK_MAN +FSCK_PROG +DEFRAG_CMT +RESIZER_CMT +IMAGER_CMT +DEBUGFS_CMT +QUOTA_CMT +DEPPROFILED_LIBQUOTA +PROFILED_LIBQUOTA +DEPSTATIC_LIBQUOTA +STATIC_LIBQUOTA +DEPLIBQUOTA +LIBQUOTA +QUOTA_MAN_COMMENT +BLKID_CMT +DEPPROFILED_LIBBLKID +PROFILED_LIBBLKID +DEPSTATIC_LIBBLKID +STATIC_LIBBLKID +DEPLIBBLKID +LIBBLKID +UUID_CMT +DEPPROFILED_LIBUUID +PROFILED_LIBUUID +DEPSTATIC_LIBUUID +STATIC_LIBUUID +DEPLIBUUID +LIBUUID +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +TEST_IO_CMT +PRIVATE_LIBS_CMT +LDFLAG_DYNAMIC +PROFILED_LIB_EXT +STATIC_LIB_EXT +LIB_EXT +PROFILE_CMT +BSDLIB_CMT +ELF_CMT +HTREE_CMT +Q +ES +E +LINK_BUILD_FLAGS +SYMLINK_RELATIVE +LINK_INSTALL_FLAGS +MAINTAINER_CMT +EGREP +GREP +CPP +RDYNAMIC +DLOPEN_LIB +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +E2FSPROGS_PKGVER +E2FSPROGS_VERSION +E2FSPROGS_DAY +E2FSPROGS_MONTH +E2FSPROGS_YEAR +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='MCONFIG +MAKEFILE_ELF +MAKEFILE_BSDLIB +MAKEFILE_PROFILE +MAKEFILE_LIBRARY +ASM_TYPES_HEADER +PUBLIC_CONFIG_HEADER' +ac_user_opts=' +enable_option_checking +with_diet_libc +with_cc +with_ccopts +with_ldopts +with_root_prefix +enable_maintainer_mode +enable_symlink_install +enable_relative_symlinks +enable_symlink_relative_symlinks +enable_symlink_build +enable_verbose_makecmds +enable_compression +enable_htree +enable_elf_shlibs +enable_bsd_shlibs +enable_profile +enable_gcov +enable_jbd_debug +enable_blkid_debug +enable_testio_debug +enable_libuuid +enable_libblkid +enable_quota +enable_backtrace +enable_debugfs +enable_imager +enable_resizer +enable_defrag +enable_fsck +enable_e2initrd_helper +enable_tls +enable_uuidd +enable_nls +enable_threads +with_gnu_ld +enable_rpath +with_libpth_prefix +with_libiconv_prefix +with_included_gettext +with_libintl_prefix +with_multiarch +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR' + + +# 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= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures 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 + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + 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 makefile rules useful for maintainers + --enable-symlink-install use symlinks when installing instead of hard links + --enable-relative-symlinks use relative symlinks when installing + + --enable-symlink-build use symlinks while building instead of hard links + --enable-verbose-makecmds enable verbose make command output + --enable-compression enable EXPERIMENTAL compression support + --enable-htree enable EXPERIMENTAL htree directory support + --enable-elf-shlibs select ELF shared libraries + --enable-bsd-shlibs select BSD shared libraries + --enable-profile build profiling libraries + --enable-gcov build for coverage testing using gcov + --enable-jbd-debug enable journal debugging + --enable-blkid-debug enable blkid debugging + --disable-testio-debug disable the use of the test I/O manager for debugging + --disable-libuuid do not build private uuid library + --disable-libblkid do not build private blkid library + --enable-quota enable quota support + --disable-backtrace disable use backtrace + --disable-debugfs disable support of debugfs program + --disable-imager disable support of e2image program + --disable-resizer disable support of e2resize program + --disable-defrag disable support of e4defrag program + --enable-fsck build fsck wrapper program + --enable-e2initrd-helper build e2initrd-helper program + --disable-tls disable use of thread local support + --disable-uuidd disable building the uuid daemon + --disable-nls do not use Native Language Support + --enable-threads={posix|solaris|pth|windows} + specify multithreading API + --disable-threads build without multithread safety + --disable-rpath do not hardcode runtime library paths + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-diet-libc use diet libc + --with-cc no longer supported, use CC= instead + --with-ccopts no longer supported, use CFLAGS= instead + --with-ldopts no longer supported, use LDFLAGS= instead + --with-root-prefix=PREFIX override prefix variable for files to be placed in the root + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-libpth-prefix[=DIR] search for libpth in DIR/include and DIR/lib + --without-libpth-prefix don't search for libpth in includedir and libdir + --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib + --without-libiconv-prefix don't search for libiconv in includedir and libdir + --with-included-gettext use the GNU gettext library included here + --with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib + --without-libintl-prefix don't search for libintl in includedir and libdir + --with-multiarch=ARCH specify the multiarch triplet + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + CPP C preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + +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.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include <stdio.h> +#include <stdlib.h> +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 <conftest.val; ac_retval=0 +else + ac_retval=1 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f conftest.val + + fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_compute_int + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member +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.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +gt_needs="$gt_needs " +as_fn_append ac_header_list " stdlib.h" +as_fn_append ac_header_list " unistd.h" +as_fn_append ac_header_list " sys/param.h" +as_fn_append ac_func_list " symlink" +# 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 + + + +ac_aux_dir= +for ac_dir in config "$srcdir"/config; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in config \"$srcdir\"/config" "$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. + + +ac_config_headers="$ac_config_headers lib/config.h" + + +MCONFIG=./MCONFIG + +BINARY_TYPE=bin +E2FSPROGS_VERSION=`grep E2FSPROGS_VERSION ${srcdir}/version.h \ + | awk '{print $3}' | tr \" " " | awk '{print $1}'` +DATE=`grep E2FSPROGS_DATE ${srcdir}/version.h | awk '{print $3}' \ + | tr \" " "` +E2FSPROGS_DAY=`echo $DATE | awk -F- '{print $1}'` +MONTH=`echo $DATE | awk -F- '{print $2}'` +YEAR=`echo $DATE | awk -F- '{print $3}'` + +if expr $YEAR ">" 1900 > /dev/null ; then + E2FSPROGS_YEAR=$YEAR +elif expr $YEAR ">" 90 >/dev/null ; then + E2FSPROGS_YEAR=19$YEAR +else + E2FSPROGS_YEAR=20$YEAR +fi + +case $MONTH in +Jan) MONTH_NUM=01; E2FSPROGS_MONTH="January" ;; +Feb) MONTH_NUM=02; E2FSPROGS_MONTH="February" ;; +Mar) MONTH_NUM=03; E2FSPROGS_MONTH="March" ;; +Apr) MONTH_NUM=04; E2FSPROGS_MONTH="April" ;; +May) MONTH_NUM=05; E2FSPROGS_MONTH="May" ;; +Jun) MONTH_NUM=06; E2FSPROGS_MONTH="June" ;; +Jul) MONTH_NUM=07; E2FSPROGS_MONTH="July" ;; +Aug) MONTH_NUM=08; E2FSPROGS_MONTH="August" ;; +Sep) MONTH_NUM=09; E2FSPROGS_MONTH="September" ;; +Oct) MONTH_NUM=10; E2FSPROGS_MONTH="October" ;; +Nov) MONTH_NUM=11; E2FSPROGS_MONTH="November" ;; +Dec) MONTH_NUM=12; E2FSPROGS_MONTH="December" ;; +*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unknown month $MONTH??" >&5 +$as_echo "$as_me: WARNING: Unknown month $MONTH??" >&2;} ;; +esac + +base_ver=`echo $E2FSPROGS_VERSION | \ + sed -e 's/-WIP//' -e 's/pre-//' -e 's/-PLUS//'` + +date_spec=${E2FSPROGS_YEAR}.${MONTH_NUM}.${E2FSPROGS_DAY} + +case $E2FSPROGS_VERSION in +*-WIP|pre-*) + E2FSPROGS_PKGVER="$base_ver~WIP-$E2FSPROGS_YEAR-$MONTH_NUM-$E2FSPROGS_DAY" + ;; +*) + E2FSPROGS_PKGVER="$base_ver" + ;; +esac + +unset DATE MONTH YEAR base_ver pre_vers date_spec +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Generating configuration file for e2fsprogs version $E2FSPROGS_VERSION" >&5 +$as_echo "Generating configuration file for e2fsprogs version $E2FSPROGS_VERSION" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Release date is ${E2FSPROGS_MONTH}, ${E2FSPROGS_YEAR}" >&5 +$as_echo "Release date is ${E2FSPROGS_MONTH}, ${E2FSPROGS_YEAR}" >&6; } + + + + + +WITH_DIET_LIBC= + +# Check whether --with-diet-libc was given. +if test "${with_diet_libc+set}" = set; then : + withval=$with_diet_libc; CC="diet cc -nostdinc" +WITH_DIET_LIBC=yes +if test -z "$LIBS" +then + LIBS="-lcompat" +else + LIBS="$LIBS -lcompat" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CC=$CC" >&5 +$as_echo "CC=$CC" >&6; } +fi +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +DLOPEN_LIB='' +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + DLOPEN_LIB=-ldl + +$as_echo "#define HAVE_DLOPEN 1" >>confdefs.h + +fi + + + +# Check whether --with-cc was given. +if test "${with_cc+set}" = set; then : + withval=$with_cc; as_fn_error $? "--with-cc no longer supported; use CC= instead" "$LINENO" 5 +fi + + +# Check whether --with-ccopts was given. +if test "${with_ccopts+set}" = set; then : + withval=$with_ccopts; as_fn_error $? "--with-ccopts no longer supported; use CFLAGS= instead" "$LINENO" 5 +fi + + +# Check whether --with-ldopts was given. +if test "${with_ldopts+set}" = set; then : + withval=$with_ldopts; as_fn_error $? "--with-ldopts no longer supported; use LDFLAGS= instead" "$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 +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +if test "$GCC" = yes; then + RDYNAMIC="-rdynamic" + +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 ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> 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 <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> 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 <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for additional special compiler flags" >&5 +$as_echo_n "checking for additional special compiler flags... " >&6; } +if test "$GCC" = yes +then + case "$host_cpu" in + alpha) addcflags="-mieee" ;; + esac +fi +if test "x$addcflags" != x +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $addcflags" >&5 +$as_echo "$addcflags" >&6; } + CFLAGS="$addcflags $CFLAGS" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: (none)" >&5 +$as_echo "(none)" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +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 <string.h> + +_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 <stdlib.h> + +_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 <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + +LIB_EXT=.a +STATIC_LIB_EXT=.a +PROFILED_LIB_EXT=.a + +# Check whether --with-root-prefix was given. +if test "${with_root_prefix+set}" = set; then : + withval=$with_root_prefix; root_prefix=$withval +else + root_prefix=NONE +fi +# Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; if test "$enableval" = "no" +then + MAINTAINER_CMT=# + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling maintainer mode" >&5 +$as_echo "Disabling maintainer mode" >&6; } +else + MAINTAINER_CMT= + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling maintainer mode" >&5 +$as_echo "Enabling maintainer mode" >&6; } +fi + +else + MAINTAINER_CMT=# +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling maintainer mode by default" >&5 +$as_echo "Disabling maintainer mode by default" >&6; } + +fi + + +# Check whether --enable-symlink-install was given. +if test "${enable_symlink_install+set}" = set; then : + enableval=$enable_symlink_install; if test "$enableval" = "no" +then + LINK_INSTALL_FLAGS=-f + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling symlinks for install" >&5 +$as_echo "Disabling symlinks for install" >&6; } +else + LINK_INSTALL_FLAGS=-sf + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling symlinks for install" >&5 +$as_echo "Enabling symlinks for install" >&6; } +fi + +else + LINK_INSTALL_FLAGS=-f +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling symlinks for install by default" >&5 +$as_echo "Disabling symlinks for install by default" >&6; } + +fi + + +relative_symlink_defined= +# Check whether --enable-relative-symlinks was given. +if test "${enable_relative_symlinks+set}" = set; then : + enableval=$enable_relative_symlinks; if test "$enableval" = "no" +then + SYMLINK_RELATIVE= + relative_symlink_defined=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling relative symlinks for install" >&5 +$as_echo "Disabling relative symlinks for install" >&6; } +else + SYMLINK_RELATIVE=--relative + relative_symlink_defined=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling relative symlinks for install" >&5 +$as_echo "Enabling relative symlinks for install" >&6; } +fi +fi + +# Check whether --enable-symlink-relative-symlinks was given. +if test "${enable_symlink_relative_symlinks+set}" = set; then : + enableval=$enable_symlink_relative_symlinks; if test "$enableval" = "no" +then + SYMLINK_RELATIVE=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling relative symlinks for install" >&5 +$as_echo "Disabling relative symlinks for install" >&6; } +else + SYMLINK_RELATIVE=--relative + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling relative symlinks for install" >&5 +$as_echo "Enabling relative symlinks for install" >&6; } +fi + +else + if test -z "$relative_symlink_defined" +then + SYMLINK_RELATIVE= +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling relative symlinks for install by default" >&5 +$as_echo "Disabling relative symlinks for install by default" >&6; } +fi + +fi + + +# Check whether --enable-symlink-build was given. +if test "${enable_symlink_build+set}" = set; then : + enableval=$enable_symlink_build; if test "$enableval" = "no" +then + LINK_BUILD_FLAGS= + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling symlinks for build" >&5 +$as_echo "Disabling symlinks for build" >&6; } +else + LINK_BUILD_FLAGS=-s + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling symlinks for build" >&5 +$as_echo "Enabling symlinks for build" >&6; } +fi + +else + LINK_BUILD_FLAGS= +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling symlinks for build by default" >&5 +$as_echo "Disabling symlinks for build by default" >&6; } + +fi + + +# Check whether --enable-verbose-makecmds was given. +if test "${enable_verbose_makecmds+set}" = set; then : + enableval=$enable_verbose_makecmds; if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling verbose make commands" >&5 +$as_echo "Disabling verbose make commands" >&6; } + E=@echo + ES=echo + Q=@ +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling verbose make commands" >&5 +$as_echo "Enabling verbose make commands" >&6; } + E=@\\# + ES=\\# + Q= +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling verbose make commands" >&5 +$as_echo "Disabling verbose make commands" >&6; } +E=@echo +ES=echo +Q=@ + +fi + + + + +# Check whether --enable-compression was given. +if test "${enable_compression+set}" = set; then : + enableval=$enable_compression; if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling compression support" >&5 +$as_echo "Disabling compression support" >&6; } +else + +$as_echo "#define ENABLE_COMPRESSION 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling compression support" >&5 +$as_echo "Enabling compression support" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Compression support is experimental" >&5 +$as_echo "$as_me: WARNING: Compression support is experimental" >&2;} +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling compression support by default" >&5 +$as_echo "Disabling compression support by default" >&6; } + +fi + + +# Check whether --enable-htree was given. +if test "${enable_htree+set}" = set; then : + enableval=$enable_htree; if test "$enableval" = "no" +then + HTREE_CMT=# + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling htree directory support" >&5 +$as_echo "Disabling htree directory support" >&6; } +else + HTREE_CMT= + $as_echo "#define ENABLE_HTREE 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling htree directory support" >&5 +$as_echo "Enabling htree directory support" >&6; } +fi + +else + HTREE_CMT= +$as_echo "#define ENABLE_HTREE 1" >>confdefs.h + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling htree directory support by default" >&5 +$as_echo "Enabling htree directory support by default" >&6; } + +fi + + +E2_PKG_CONFIG_STATIC=--static +LDFLAG_DYNAMIC= +PRIVATE_LIBS_CMT= +# Check whether --enable-elf-shlibs was given. +if test "${enable_elf_shlibs+set}" = set; then : + enableval=$enable_elf_shlibs; if test "$enableval" = "no" +then + ELF_CMT=# + MAKEFILE_ELF=/dev/null + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling ELF shared libraries" >&5 +$as_echo "Disabling ELF shared libraries" >&6; } +else + E2_PKG_CONFIG_STATIC= + ELF_CMT= + MAKEFILE_ELF=$srcdir/lib/Makefile.elf-lib + case "$host_os" in + solaris2.*) + MAKEFILE_ELF=$srcdir/lib/Makefile.solaris-lib + ;; + esac + BINARY_TYPE=elfbin + LIB_EXT=.so + PRIVATE_LIBS_CMT=# + LDFLAG_DYNAMIC='-Wl,-rpath-link,$(top_builddir)/lib' + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling ELF shared libraries" >&5 +$as_echo "Enabling ELF shared libraries" >&6; } +fi + +else + MAKEFILE_ELF=/dev/null +ELF_CMT=# +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling ELF shared libraries by default" >&5 +$as_echo "Disabling ELF shared libraries by default" >&6; } + +fi + + + +# Check whether --enable-bsd-shlibs was given. +if test "${enable_bsd_shlibs+set}" = set; then : + enableval=$enable_bsd_shlibs; if test "$enableval" = "no" +then + BSDLIB_CMT=# + MAKEFILE_BSDLIB=/dev/null + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling BSD shared libraries" >&5 +$as_echo "Disabling BSD shared libraries" >&6; } +else + E2_PKG_CONFIG_STATIC= + BSDLIB_CMT= + MAKEFILE_BSDLIB=$srcdir/lib/Makefile.bsd-lib + LIB_EXT=.so + case "$host_os" in + darwin*) + MAKEFILE_BSDLIB=$srcdir/lib/Makefile.darwin-lib + LIB_EXT=.dylib + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling BSD shared libraries" >&5 +$as_echo "Enabling BSD shared libraries" >&6; } +fi + +else + MAKEFILE_BSDLIB=/dev/null +BSDLIB_CMT=# +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling BSD shared libraries by default" >&5 +$as_echo "Disabling BSD shared libraries by default" >&6; } + +fi + + + +# Check whether --enable-profile was given. +if test "${enable_profile+set}" = set; then : + enableval=$enable_profile; if test "$enableval" = "no" +then + PROFILE_CMT=# + MAKEFILE_PROFILE=/dev/null + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling profiling libraries" >&5 +$as_echo "Disabling profiling libraries" >&6; } +else + PROFILE_CMT= + MAKEFILE_PROFILE=$srcdir/lib/Makefile.profile + PROFILED_LIB_EXT=_p.a + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Building profiling libraries" >&5 +$as_echo "Building profiling libraries" >&6; } +fi + +else + PROFILE_CMT=# +MAKEFILE_PROFILE=/dev/null +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling profiling libraries by default" >&5 +$as_echo "Disabling profiling libraries by default" >&6; } + +fi + + + +# Check whether --enable-gcov was given. +if test "${enable_gcov+set}" = set; then : + enableval=$enable_gcov; if test "$enableval" = "yes" +then + CFLAGS="-g -fprofile-arcs -ftest-coverage" + LDFLAGS="-fprofile-arcs -ftest-coverage" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling gcov support" >&5 +$as_echo "Enabling gcov support" >&6; } +fi + +fi + + + + + + + +# Check whether --enable-jbd-debug was given. +if test "${enable_jbd_debug+set}" = set; then : + enableval=$enable_jbd_debug; if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling journal debugging" >&5 +$as_echo "Disabling journal debugging" >&6; } +else + +$as_echo "#define CONFIG_JBD_DEBUG 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling journal debugging" >&5 +$as_echo "Enabling journal debugging" >&6; } +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling journal debugging by default" >&5 +$as_echo "Disabling journal debugging by default" >&6; } + +fi + +# Check whether --enable-blkid-debug was given. +if test "${enable_blkid_debug+set}" = set; then : + enableval=$enable_blkid_debug; if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling blkid debugging" >&5 +$as_echo "Disabling blkid debugging" >&6; } +else + +$as_echo "#define CONFIG_BLKID_DEBUG 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling blkid debugging" >&5 +$as_echo "Enabling blkid debugging" >&6; } +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling blkid debugging by default" >&5 +$as_echo "Disabling blkid debugging by default" >&6; } + +fi + +# Check whether --enable-testio-debug was given. +if test "${enable_testio_debug+set}" = set; then : + enableval=$enable_testio_debug; +if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling testio debugging" >&5 +$as_echo "Disabling testio debugging" >&6; } + TEST_IO_CMT="#" +else + TEST_IO_CMT= + $as_echo "#define CONFIG_TESTIO_DEBUG 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling testio debugging" >&5 +$as_echo "Enabling testio debugging" >&6; } +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling testio debugging by default" >&5 +$as_echo "Enabling testio debugging by default" >&6; } +$as_echo "#define CONFIG_TESTIO_DEBUG 1" >>confdefs.h + +TEST_IO_CMT= + +fi + + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$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 + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$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 + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + 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 + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; 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" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi +LIBUUID= +DEPLIBUUID= +STATIC_LIBUUID= +DEPSTATIC_LIBUUID= +PROFILED_LIBUUID= +DEPPROFILED_LIBUUID= +UUID_CMT= +# Check whether --enable-libuuid was given. +if test "${enable_libuuid+set}" = set; then : + enableval=$enable_libuuid; if test "$enableval" = "no" +then + if test -z "$PKG_CONFIG"; then + as_fn_error $? "pkg-config not installed; please install it." "$LINENO" 5 + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate in -luuid" >&5 +$as_echo_n "checking for uuid_generate in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uuid_generate (); +int +main () +{ +return uuid_generate (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_uuid_uuid_generate=yes +else + ac_cv_lib_uuid_uuid_generate=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_generate" >&6; } +if test "x$ac_cv_lib_uuid_uuid_generate" = xyes; then : + LIBUUID=`$PKG_CONFIG --libs uuid`; + STATIC_LIBUUID=`$PKG_CONFIG --static --libs uuid` +else + as_fn_error $? "external uuid library not found" "$LINENO" 5 +fi + + PROFILED_LIBUUID=$LIBUUID + UUID_CMT=# + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling private uuid library" >&5 +$as_echo "Disabling private uuid library" >&6; } +else + LIBUUID='$(LIB)/libuuid'$LIB_EXT + DEPLIBUUID=$LIBUUID + STATIC_LIBUUID='$(LIB)/libuuid'$STATIC_LIB_EXT + DEPSTATIC_LIBUUID=$STATIC_LIBUUID + PROFILED_LIBUUID='$(LIB)/libuuid'$PROFILED_LIB_EXT + DEPPROFILED_LIBUUID=$PROFILED_LIBUUID + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling private uuid library" >&5 +$as_echo "Enabling private uuid library" >&6; } +fi + +else + LIBUUID='$(LIB)/libuuid'$LIB_EXT +DEPLIBUUID=$LIBUUID +STATIC_LIBUUID='$(LIB)/libuuid'$STATIC_LIB_EXT +DEPSTATIC_LIBUUID=$STATIC_LIBUUID +PROFILED_LIBUUID='$(LIB)/libuuid'$PROFILED_LIB_EXT +DEPPROFILED_LIBUUID=$PROFILED_LIBUUID +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling private uuid library by default" >&5 +$as_echo "Enabling private uuid library by default" >&6; } + +fi + + + + + + + + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$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 + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$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 + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + 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 + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; 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" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi +LIBBLKID= +DEPLIBBLKID= +STATIC_LIBBLKID= +DEPSTATIC_LIBBLKID= +PROFILED_LIBBLKID= +DEPPROFILED_LIBBLKID= +BLKID_CMT= + +# Check whether --enable-libblkid was given. +if test "${enable_libblkid+set}" = set; then : + enableval=$enable_libblkid; if test "$enableval" = "no" +then + if test -z "$PKG_CONFIG"; then + as_fn_error $? "pkg-config not installed; please install it." "$LINENO" 5 + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for blkid_get_cache in -lblkid" >&5 +$as_echo_n "checking for blkid_get_cache in -lblkid... " >&6; } +if ${ac_cv_lib_blkid_blkid_get_cache+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lblkid -luuid $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char blkid_get_cache (); +int +main () +{ +return blkid_get_cache (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_blkid_blkid_get_cache=yes +else + ac_cv_lib_blkid_blkid_get_cache=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_blkid_blkid_get_cache" >&5 +$as_echo "$ac_cv_lib_blkid_blkid_get_cache" >&6; } +if test "x$ac_cv_lib_blkid_blkid_get_cache" = xyes; then : + LIBBLKID=`$PKG_CONFIG --libs blkid`; + STATIC_LIBBLKID=`$PKG_CONFIG --static --libs blkid` +else + as_fn_error $? "external blkid library not found" "$LINENO" 5 +fi + + BLKID_CMT=# + PROFILED_LIBBLKID=$LIBBLKID + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling private blkid library" >&5 +$as_echo "Disabling private blkid library" >&6; } +else + LIBBLKID='$(LIB)/libblkid'$LIB_EXT + DEPLIBBLKID=$LIBBLKID + STATIC_LIBBLKID='$(LIB)/libblkid'$STATIC_LIB_EXT + DEPSTATIC_LIBBLKID=$STATIC_LIBBLKID + PROFILED_LIBBLKID='$(LIB)/libblkid'$PROFILED_LIB_EXT + DEPPROFILED_LIBBLKID=$PROFILED_LIBBLKID + $as_echo "#define CONFIG_BUILD_FINDFS 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling private blkid library" >&5 +$as_echo "Enabling private blkid library" >&6; } +fi + +else + LIBBLKID='$(LIB)/libblkid'$LIB_EXT +DEPLIBBLKID=$LIBBLKID +STATIC_LIBBLKID='$(LIB)/libblkid'$STATIC_LIB_EXT +DEPSTATIC_LIBBLKID=$STATIC_LIBBLKID +PROFILED_LIBBLKID='$(LIB)/libblkid'$PROFILED_LIB_EXT +DEPPROFILED_LIBBLKID=$PROFILED_LIBBLKID +$as_echo "#define CONFIG_BUILD_FINDFS 1" >>confdefs.h + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling private blkid library by default" >&5 +$as_echo "Enabling private blkid library by default" >&6; } + +fi + + + + + + + + +QUOTA_MAN_COMMENT='.\"' +QUOTA_CMT= + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$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 + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$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 + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + 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 + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; 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" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +# Check whether --enable-quota was given. +if test "${enable_quota+set}" = set; then : + enableval=$enable_quota; if test "$enableval" = "no" +then + QUOTA_CMT=# + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling quota support" >&5 +$as_echo "Disabling quota support" >&6; } +else + QUOTA_CMT= + $as_echo "#define CONFIG_QUOTA 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling quota support" >&5 +$as_echo "Enabling quota support" >&6; } + QUOTA_MAN_COMMENT="" + +fi + +else + QUOTA_CMT=# +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling quota support by default" >&5 +$as_echo "Disabling quota support by default" >&6; } + +fi + +LIBQUOTA='$(LIB)/libquota'$LIB_EXT +DEPLIBQUOTA=$LIBQUOTA +STATIC_LIBQUOTA='$(LIB)/libquota'$STATIC_LIB_EXT +DEPSTATIC_LIBQUOTA=$STATIC_LIBQUOTA +PROFILED_LIBQUOTA='$(LIB)/libquota'$PROFILED_LIB_EXT +DEPPROFILED_LIBQUOTA=$PROFILED_LIBQUOTA + + + + + + + + +# Check whether --enable-backtrace was given. +if test "${enable_backtrace+set}" = set; then : + enableval=$enable_backtrace; if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling use of backtrace" >&5 +$as_echo "Disabling use of backtrace" >&6; } + $as_echo "#define DISABLE_BACKTRACE 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling use of backtrace" >&5 +$as_echo "Enabling use of backtrace" >&6; } +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling use of backtrace by default" >&5 +$as_echo "Enabling use of backtrace by default" >&6; } + +fi + +# Check whether --enable-debugfs was given. +if test "${enable_debugfs+set}" = set; then : + enableval=$enable_debugfs; if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling debugfs support" >&5 +$as_echo "Disabling debugfs support" >&6; } + DEBUGFS_CMT="#" +else + DEBUGFS_CMT= + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling debugfs support" >&5 +$as_echo "Enabling debugfs support" >&6; } +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling debugfs support by default" >&5 +$as_echo "Enabling debugfs support by default" >&6; } +DEBUGFS_CMT= + +fi + + +# Check whether --enable-imager was given. +if test "${enable_imager+set}" = set; then : + enableval=$enable_imager; if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling e2image support" >&5 +$as_echo "Disabling e2image support" >&6; } + IMAGER_CMT="#" +else + IMAGER_CMT= + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling e2image support" >&5 +$as_echo "Enabling e2image support" >&6; } +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling e2image support by default" >&5 +$as_echo "Enabling e2image support by default" >&6; } +IMAGER_CMT= + +fi + + +# Check whether --enable-resizer was given. +if test "${enable_resizer+set}" = set; then : + enableval=$enable_resizer; if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling e2resize support" >&5 +$as_echo "Disabling e2resize support" >&6; } + RESIZER_CMT="#" +else + RESIZER_CMT= + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling e2resize support" >&5 +$as_echo "Enabling e2resize support" >&6; } +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling e2resize support by default" >&5 +$as_echo "Enabling e2resize support by default" >&6; } +RESIZER_CMT= + +fi + + +# Check whether --enable-defrag was given. +if test "${enable_defrag+set}" = set; then : + enableval=$enable_defrag; if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling e4defrag support" >&5 +$as_echo "Disabling e4defrag support" >&6; } + DEFRAG_CMT="#" +else + DEFRAG_CMT= + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling e4defrag support" >&5 +$as_echo "Enabling e4defrag support" >&6; } +fi + +else + if test -z "$WITH_DIET_LIBC" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling e4defrag support by default" >&5 +$as_echo "Enabling e4defrag support by default" >&6; } + DEFRAG_CMT= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling e4defrag support by default" >&5 +$as_echo "Disabling e4defrag support by default" >&6; } + DEFRAG_CMT="#" +fi + +fi + + +# Check whether --enable-fsck was given. +if test "${enable_fsck+set}" = set; then : + enableval=$enable_fsck; if test "$enableval" = "no" +then + FSCK_PROG='' FSCK_MAN='' + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Not building fsck wrapper" >&5 +$as_echo "Not building fsck wrapper" >&6; } +else + FSCK_PROG=fsck FSCK_MAN=fsck.8 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Building fsck wrapper" >&5 +$as_echo "Building fsck wrapper" >&6; } +fi + +else + case "$host_os" in + gnu*) + FSCK_PROG='' FSCK_MAN='' + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Not building fsck wrapper by default" >&5 +$as_echo "Not building fsck wrapper by default" >&6; } + ;; + *) + FSCK_PROG=fsck FSCK_MAN=fsck.8 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Building fsck wrapper by default" >&5 +$as_echo "Building fsck wrapper by default" >&6; } +esac + +fi + + + +# Check whether --enable-e2initrd-helper was given. +if test "${enable_e2initrd_helper+set}" = set; then : + enableval=$enable_e2initrd_helper; if test "$enableval" = "no" +then + E2INITRD_PROG='' E2INITRD_MAN='' + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Not building e2initrd helper" >&5 +$as_echo "Not building e2initrd helper" >&6; } +else + E2INITRD_PROG=e2initrd_helper E2INITRD_MAN=e2initrd_helper.8 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Building e2initrd helper" >&5 +$as_echo "Building e2initrd helper" >&6; } +fi + +else + E2INITRD_PROG=e2initrd_helper E2INITRD_MAN=e2initrd_helper.8 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Building e2initrd helper by default" >&5 +$as_echo "Building e2initrd helper by default" >&6; } + +fi + + + +# Check whether --enable-tls was given. +if test "${enable_tls+set}" = set; then : + enableval=$enable_tls; if test "$enableval" = "no" +then + try_tls="" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling thread local support" >&5 +$as_echo "Disabling thread local support" >&6; } +else + try_tls="yes" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling thread local support" >&5 +$as_echo "Enabling thread local support" >&6; } +fi + +else + if test -n "$WITH_DIET_LIBC" +then + try_tls="" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Diet libc does not support thread local support" >&5 +$as_echo "Diet libc does not support thread local support" >&6; } +else + try_tls="yes" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Try using thread local support by default" >&5 +$as_echo "Try using thread local support by default" >&6; } +fi + +fi + +if test "$try_tls" = "yes" +then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for thread local storage (TLS) class" >&5 +$as_echo_n "checking for thread local storage (TLS) class... " >&6; } + if ${ac_cv_tls+:} false; then : + $as_echo_n "(cached) " >&6 +else + + ax_tls_keywords="__thread __declspec(thread) none" + for ax_tls_keyword in $ax_tls_keywords; do + case $ax_tls_keyword in + none) ac_cv_tls=none ; break ;; + *) + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + static void + foo(void) { + static $ax_tls_keyword int bar; + exit(1); + } +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_tls=$ax_tls_keyword ; break +else + ac_cv_tls=none + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + esac + done + +fi + + + if test "$ac_cv_tls" != "none"; then + +cat >>confdefs.h <<_ACEOF +#define TLS $ac_cv_tls +_ACEOF + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_tls" >&5 +$as_echo "$ac_cv_tls" >&6; } + +fi + +# Check whether --enable-uuidd was given. +if test "${enable_uuidd+set}" = set; then : + enableval=$enable_uuidd; if test "$enableval" = "no" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Not building uuidd" >&5 +$as_echo "Not building uuidd" >&6; } + UUIDD_CMT="#" +else + $as_echo "#define USE_UUIDD 1" >>confdefs.h + + UUIDD_CMT="" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Building uuidd" >&5 +$as_echo "Building uuidd" >&6; } +fi + +else + $as_echo "#define USE_UUIDD 1" >>confdefs.h + +if test -z "$UUID_CMT" +then + UUIDD_CMT="" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Building uuidd by default" >&5 +$as_echo "Building uuidd by default" >&6; } +else + UUIDD_CMT="#" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling uuidd by default" >&5 +$as_echo "Disabling uuidd by default" >&6; } +fi + +fi + + +MAKEFILE_LIBRARY=$srcdir/lib/Makefile.library + +GETTEXT_PACKAGE=e2fsprogs +PACKAGE=e2fsprogs +VERSION="$E2FSPROGS_VERSION" +VERSION=0.14.1 + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_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 +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_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 '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "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_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_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_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5 +$as_echo_n "checking whether NLS is requested... " >&6; } + # Check whether --enable-nls was given. +if test "${enable_nls+set}" = set; then : + enableval=$enable_nls; USE_NLS=$enableval +else + USE_NLS=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + + + + + GETTEXT_MACRO_VERSION=0.18 + + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + 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 + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGFMT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --statistics /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_MSGFMT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test "$MSGFMT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +$as_echo "$MSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_GMSGFMT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $GMSGFMT in + [\\/]* | ?:[\\/]*) + ac_cv_path_GMSGFMT="$GMSGFMT" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_GMSGFMT="$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_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT=$ac_cv_path_GMSGFMT +if test -n "$GMSGFMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 +$as_echo "$GMSGFMT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + case `$MSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) MSGFMT_015=: ;; + *) MSGFMT_015=$MSGFMT ;; + esac + + case `$GMSGFMT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) GMSGFMT_015=: ;; + *) GMSGFMT_015=$GMSGFMT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + 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 + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_XGETTEXT+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$XGETTEXT" in + [\\/]* | ?:[\\/]*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >&5 2>&1 && + (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test "$XGETTEXT" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 +$as_echo "$XGETTEXT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + rm -f messages.po + + case `$XGETTEXT --version | sed 1q | sed -e 's,^[^0-9]*,,'` in + '' | 0.[0-9] | 0.[0-9].* | 0.1[0-4] | 0.1[0-4].*) XGETTEXT_015=: ;; + *) XGETTEXT_015=$XGETTEXT ;; + esac + + + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + 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 + +# Find out how to test for executable files. Don't use a zero-byte file, +# as systems may use methods other than mode bits to determine executability. +cat >conf$$.file <<_ASEOF +#! /bin/sh +exit 0 +_ASEOF +chmod +x conf$$.file +if test -x conf$$.file >/dev/null 2>&1; then + ac_executable_p="test -x" +else + ac_executable_p="test -f" +fi +rm -f conf$$.file + +# Extract the first word of "msgmerge", so it can be a program name with args. +set dummy msgmerge; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MSGMERGE+:} false; then : + $as_echo_n "(cached) " >&6 +else + case "$MSGMERGE" in + [\\/]* | ?:[\\/]*) + ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. + ;; + *) + ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$ac_save_IFS" + test -z "$ac_dir" && ac_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then + echo "$as_me: trying $ac_dir/$ac_word..." >&5 + if $ac_dir/$ac_word --update -q /dev/null /dev/null >&5 2>&1; then + ac_cv_path_MSGMERGE="$ac_dir/$ac_word$ac_exec_ext" + break 2 + fi + fi + done + done + IFS="$ac_save_IFS" + test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" + ;; +esac +fi +MSGMERGE="$ac_cv_path_MSGMERGE" +if test "$MSGMERGE" != ":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 +$as_echo "$MSGMERGE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$localedir" || localedir='${datadir}/locale' + + + test -n "${XGETTEXT_EXTRA_OPTIONS+set}" || XGETTEXT_EXTRA_OPTIONS= + + + ac_config_commands="$ac_config_commands po-directories" + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C Library 2 or newer" >&5 +$as_echo_n "checking whether we are using the GNU C Library 2 or newer... " >&6; } +if ${ac_cv_gnu_library_2+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <features.h> +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ >= 2) && !defined __UCLIBC__ + Lucky GNU user + #endif +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "Lucky GNU user" >/dev/null 2>&1; then : + ac_cv_gnu_library_2=yes +else + ac_cv_gnu_library_2=no +fi +rm -f conftest* + + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_gnu_library_2" >&5 +$as_echo "$ac_cv_gnu_library_2" >&6; } + + GLIBC2="$ac_cv_gnu_library_2" + + +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 ${ac_cv_prog_RANLIB+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_ac_ct_RANLIB+:} false; 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 as_fn_executable_p "$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 + + + + CFLAG_VISIBILITY= + HAVE_VISIBILITY=0 + if test -n "$GCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the -Werror option is usable" >&5 +$as_echo_n "checking whether the -Werror option is usable... " >&6; } + if ${gl_cv_cc_vis_werror+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_cc_vis_werror=yes +else + gl_cv_cc_vis_werror=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$gl_save_CFLAGS" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_cc_vis_werror" >&5 +$as_echo "$gl_cv_cc_vis_werror" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for simple visibility declarations" >&5 +$as_echo_n "checking for simple visibility declarations... " >&6; } + if ${gl_cv_cc_visibility+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fvisibility=hidden" + if test $gl_cv_cc_vis_werror = yes; then + CFLAGS="$CFLAGS -Werror" + fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +extern __attribute__((__visibility__("hidden"))) int hiddenvar; + extern __attribute__((__visibility__("default"))) int exportedvar; + extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void); + extern __attribute__((__visibility__("default"))) int exportedfunc (void); + void dummyfunc (void) {} + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_cc_visibility=yes +else + gl_cv_cc_visibility=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$gl_save_CFLAGS" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_cc_visibility" >&5 +$as_echo "$gl_cv_cc_visibility" >&6; } + if test $gl_cv_cc_visibility = yes; then + CFLAG_VISIBILITY="-fvisibility=hidden" + HAVE_VISIBILITY=1 + fi + fi + + + +cat >>confdefs.h <<_ACEOF +#define HAVE_VISIBILITY $HAVE_VISIBILITY +_ACEOF + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint.h" >&5 +$as_echo_n "checking for stdint.h... " >&6; } +if ${gl_cv_header_stdint_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <stdint.h> +int +main () +{ +uintmax_t i = (uintmax_t) -1; return !i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_header_stdint_h=yes +else + gl_cv_header_stdint_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_header_stdint_h" >&5 +$as_echo "$gl_cv_header_stdint_h" >&6; } + if test $gl_cv_header_stdint_h = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_STDINT_H_WITH_UINTMAX 1 +_ACEOF + + fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 +$as_echo_n "checking for working alloca.h... " >&6; } +if ${ac_cv_working_alloca_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <alloca.h> +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + if (p) return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_working_alloca_h=yes +else + ac_cv_working_alloca_h=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5 +$as_echo "$ac_cv_working_alloca_h" >&6; } +if test $ac_cv_working_alloca_h = yes; then + +$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5 +$as_echo_n "checking for alloca... " >&6; } +if ${ac_cv_func_alloca_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# ifdef HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +void *alloca (size_t); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + if (p) return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_func_alloca_works=yes +else + ac_cv_func_alloca_works=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5 +$as_echo "$ac_cv_func_alloca_works" >&6; } + +if test $ac_cv_func_alloca_works = yes; then + +$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h + +else + # The SVR3 libPW and SVR4 libucb both contain incompatible functions +# that cause trouble. Some versions do not even contain alloca or +# contain a buggy version. If you still want to use their alloca, +# use ar to extract alloca.o from them instead of compiling alloca.c. + +ALLOCA=\${LIBOBJDIR}alloca.$ac_objext + +$as_echo "#define C_ALLOCA 1" >>confdefs.h + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5 +$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } +if ${ac_cv_os_cray+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined CRAY && ! defined CRAY2 +webecray +#else +wenotbecray +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "webecray" >/dev/null 2>&1; then : + ac_cv_os_cray=yes +else + ac_cv_os_cray=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5 +$as_echo "$ac_cv_os_cray" >&6; } +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5 +$as_echo_n "checking stack direction for C alloca... " >&6; } +if ${ac_cv_c_stack_direction+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_c_stack_direction=0 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +find_stack_direction (int *addr, int depth) +{ + int dir, dummy = 0; + if (! addr) + addr = &dummy; + *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; + dir = depth ? find_stack_direction (addr, depth - 1) : 0; + return dir + dummy; +} + +int +main (int argc, char **argv) +{ + return find_stack_direction (0, argc + !argv + 20) < 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_stack_direction=1 +else + ac_cv_c_stack_direction=-1 +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_c_stack_direction" >&5 +$as_echo "$ac_cv_c_stack_direction" >&6; } +cat >>confdefs.h <<_ACEOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +_ACEOF + + +fi + + + + + for ac_header in $ac_header_list +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + +for ac_func in getpagesize +do : + ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" +if test "x$ac_cv_func_getpagesize" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETPAGESIZE 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mmap" >&5 +$as_echo_n "checking for working mmap... " >&6; } +if ${ac_cv_func_mmap_fixed_mapped+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_mmap_fixed_mapped=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +/* malloc might have been renamed as rpl_malloc. */ +#undef malloc + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the file system buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propagated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ + +#include <fcntl.h> +#include <sys/mman.h> + +#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H +char *malloc (); +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include <sys/param.h> +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +int +main () +{ + char *data, *data2, *data3; + const char *cdata2; + int i, pagesize; + int fd, fd2; + + pagesize = getpagesize (); + + /* First, make a file with some known garbage in it. */ + data = (char *) malloc (pagesize); + if (!data) + return 1; + for (i = 0; i < pagesize; ++i) + *(data + i) = rand (); + umask (0); + fd = creat ("conftest.mmap", 0600); + if (fd < 0) + return 2; + if (write (fd, data, pagesize) != pagesize) + return 3; + close (fd); + + /* Next, check that the tail of a page is zero-filled. File must have + non-zero length, otherwise we risk SIGBUS for entire page. */ + fd2 = open ("conftest.txt", O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd2 < 0) + return 4; + cdata2 = ""; + if (write (fd2, cdata2, 1) != 1) + return 5; + data2 = (char *) mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L); + if (data2 == MAP_FAILED) + return 6; + for (i = 0; i < pagesize; ++i) + if (*(data2 + i)) + return 7; + close (fd2); + if (munmap (data2, pagesize)) + return 8; + + /* Next, try to mmap the file at a fixed address which already has + something else allocated at it. If we can, also make sure that + we see the same garbage. */ + fd = open ("conftest.mmap", O_RDWR); + if (fd < 0) + return 9; + if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + return 10; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + return 11; + + /* Finally, make sure that changes to the mapped area do not + percolate back to the file as seen by read(). (This is a bug on + some variants of i386 svr4.0.) */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = (char *) malloc (pagesize); + if (!data3) + return 12; + if (read (fd, data3, pagesize) != pagesize) + return 13; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + return 14; + close (fd); + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_mmap_fixed_mapped=yes +else + ac_cv_func_mmap_fixed_mapped=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_mmap_fixed_mapped" >&5 +$as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; } +if test $ac_cv_func_mmap_fixed_mapped = yes; then + +$as_echo "#define HAVE_MMAP 1" >>confdefs.h + +fi +rm -f conftest.mmap conftest.txt + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether integer division by zero raises SIGFPE" >&5 +$as_echo_n "checking whether integer division by zero raises SIGFPE... " >&6; } +if ${gt_cv_int_divbyzero_sigfpe+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gt_cv_int_divbyzero_sigfpe= + case "$host_os" in + macos* | darwin[6-9]* | darwin[1-9][0-9]*) + # On Mac OS X 10.2 or newer, just assume the same as when cross- + # compiling. If we were to perform the real test, 1 Crash Report + # dialog window would pop up. + case "$host_cpu" in + i[34567]86 | x86_64) + gt_cv_int_divbyzero_sigfpe="guessing yes" ;; + esac + ;; + esac + if test -z "$gt_cv_int_divbyzero_sigfpe"; then + if test "$cross_compiling" = yes; then : + + # Guess based on the CPU. + case "$host_cpu" in + alpha* | i[34567]86 | x86_64 | m68k | s390*) + gt_cv_int_divbyzero_sigfpe="guessing yes";; + *) + gt_cv_int_divbyzero_sigfpe="guessing no";; + esac + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <stdlib.h> +#include <signal.h> + +static void +sigfpe_handler (int sig) +{ + /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */ + exit (sig != SIGFPE); +} + +int x = 1; +int y = 0; +int z; +int nan; + +int main () +{ + signal (SIGFPE, sigfpe_handler); +/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */ +#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP) + signal (SIGTRAP, sigfpe_handler); +#endif +/* Linux/SPARC yields signal SIGILL. */ +#if defined (__sparc__) && defined (__linux__) + signal (SIGILL, sigfpe_handler); +#endif + + z = x / y; + nan = y / y; + exit (2); +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gt_cv_int_divbyzero_sigfpe=yes +else + gt_cv_int_divbyzero_sigfpe=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: $gt_cv_int_divbyzero_sigfpe" >&5 +$as_echo "$gt_cv_int_divbyzero_sigfpe" >&6; } + case "$gt_cv_int_divbyzero_sigfpe" in + *yes) value=1;; + *) value=0;; + esac + +cat >>confdefs.h <<_ACEOF +#define INTDIV0_RAISES_SIGFPE $value +_ACEOF + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inttypes.h" >&5 +$as_echo_n "checking for inttypes.h... " >&6; } +if ${gl_cv_header_inttypes_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <sys/types.h> +#include <inttypes.h> + +int +main () +{ +uintmax_t i = (uintmax_t) -1; return !i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gl_cv_header_inttypes_h=yes +else + gl_cv_header_inttypes_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_header_inttypes_h" >&5 +$as_echo "$gl_cv_header_inttypes_h" >&6; } + if test $gl_cv_header_inttypes_h = yes; then + +cat >>confdefs.h <<_ACEOF +#define HAVE_INTTYPES_H_WITH_UINTMAX 1 +_ACEOF + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5 +$as_echo_n "checking for unsigned long long int... " >&6; } +if ${ac_cv_type_unsigned_long_long_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_type_unsigned_long_long_int=yes + if test "x${ac_cv_prog_cc_c99-no}" = xno; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + /* For now, do not test the preprocessor; as of 2007 there are too many + implementations with broken preprocessors. Perhaps this can + be revisited in 2012. In the meantime, code should not expect + #if to work with literals wider than 32 bits. */ + /* Test literals. */ + long long int ll = 9223372036854775807ll; + long long int nll = -9223372036854775807LL; + unsigned long long int ull = 18446744073709551615ULL; + /* Test constant expressions. */ + typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll) + ? 1 : -1)]; + typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1 + ? 1 : -1)]; + int i = 63; +int +main () +{ +/* Test availability of runtime routines for shift and division. */ + long long int llmax = 9223372036854775807ll; + unsigned long long int ullmax = 18446744073709551615ull; + return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i) + | (llmax / ll) | (llmax % ll) + | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i) + | (ullmax / ull) | (ullmax % ull)); + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +else + ac_cv_type_unsigned_long_long_int=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5 +$as_echo "$ac_cv_type_unsigned_long_long_int" >&6; } + if test $ac_cv_type_unsigned_long_long_int = yes; then + +$as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h + + fi + + + + + if test $gl_cv_header_inttypes_h = no && test $gl_cv_header_stdint_h = no; then + + test $ac_cv_type_unsigned_long_long_int = yes \ + && ac_type='unsigned long long' \ + || ac_type='unsigned long' + +cat >>confdefs.h <<_ACEOF +#define uintmax_t $ac_type +_ACEOF + + else + +$as_echo "#define HAVE_UINTMAX_T 1" >>confdefs.h + + fi + + + for ac_header in inttypes.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" +if test "x$ac_cv_header_inttypes_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_INTTYPES_H 1 +_ACEOF + +fi + +done + + if test $ac_cv_header_inttypes_h = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the inttypes.h PRIxNN macros are broken" >&5 +$as_echo_n "checking whether the inttypes.h PRIxNN macros are broken... " >&6; } +if ${gt_cv_inttypes_pri_broken+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <inttypes.h> +#ifdef PRId32 +char *p = PRId32; +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gt_cv_inttypes_pri_broken=no +else + gt_cv_inttypes_pri_broken=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_inttypes_pri_broken" >&5 +$as_echo "$gt_cv_inttypes_pri_broken" >&6; } + fi + if test "$gt_cv_inttypes_pri_broken" = yes; then + +cat >>confdefs.h <<_ACEOF +#define PRI_MACROS_BROKEN 1 +_ACEOF + + PRI_MACROS_BROKEN=1 + else + PRI_MACROS_BROKEN=0 + fi + + + + + + + + # Check whether --enable-threads was given. +if test "${enable_threads+set}" = set; then : + enableval=$enable_threads; gl_use_threads=$enableval +else + if test -n "$gl_use_threads_default"; then + gl_use_threads="$gl_use_threads_default" + else + case "$host_os" in + osf*) gl_use_threads=no ;; + cygwin*) + case `uname -r` in + 1.[0-5].*) gl_use_threads=no ;; + *) gl_use_threads=yes ;; + esac + ;; + *) gl_use_threads=yes ;; + esac + fi + +fi + + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # For using <pthread.h>: + case "$host_os" in + osf*) + # On OSF/1, the compiler needs the flag -D_REENTRANT so that it + # groks <pthread.h>. cc also understands the flag -pthread, but + # we don't use it because 1. gcc-2.95 doesn't understand -pthread, + # 2. putting a flag into CPPFLAGS that has an effect on the linker + # causes the AC_LINK_IFELSE test below to succeed unexpectedly, + # leading to wrong values of LIBTHREAD and LTLIBTHREAD. + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + ;; + esac + # Some systems optimize for single-threaded programs by default, and + # need special flags to disable these optimizations. For example, the + # definition of 'errno' in <errno.h>. + case "$host_os" in + aix* | freebsd*) CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" ;; + solaris*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" ;; + esac + fi + + + + + + if test "X$prefix" = "XNONE"; then + acl_final_prefix="$ac_default_prefix" + else + acl_final_prefix="$prefix" + fi + if test "X$exec_prefix" = "XNONE"; then + acl_final_exec_prefix='${prefix}' + else + acl_final_exec_prefix="$exec_prefix" + fi + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + eval acl_final_exec_prefix=\"$acl_final_exec_prefix\" + prefix="$acl_save_prefix" + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +# Prepare PATH_SEPARATOR. +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which + # contains only /bin. Note that ksh looks also at the FPATH variable, + # so we have to set that as well for the test. + 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 + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'` + while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${acl_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$acl_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + acl_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$acl_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$acl_save_ifs" +else + acl_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$acl_cv_path_LD" +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${acl_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + acl_cv_prog_gnu_ld=yes + ;; +*) + acl_cv_prog_gnu_ld=no + ;; +esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_prog_gnu_ld" >&5 +$as_echo "$acl_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$acl_cv_prog_gnu_ld + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5 +$as_echo_n "checking for shared library run path origin... " >&6; } +if ${acl_cv_rpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + + CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \ + ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh + . ./conftest.sh + rm -f ./conftest.sh + acl_cv_rpath=done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5 +$as_echo "$acl_cv_rpath" >&6; } + wl="$acl_cv_wl" + acl_libext="$acl_cv_libext" + acl_shlibext="$acl_cv_shlibext" + acl_libname_spec="$acl_cv_libname_spec" + acl_library_names_spec="$acl_cv_library_names_spec" + acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec" + acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator" + acl_hardcode_direct="$acl_cv_hardcode_direct" + acl_hardcode_minus_L="$acl_cv_hardcode_minus_L" + # Check whether --enable-rpath was given. +if test "${enable_rpath+set}" = set; then : + enableval=$enable_rpath; : +else + enable_rpath=yes +fi + + + + + acl_libdirstem=lib + acl_libdirstem2= + case "$host_os" in + solaris*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit host" >&5 +$as_echo_n "checking for 64-bit host... " >&6; } +if ${gl_cv_solaris_64bit+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#ifdef _LP64 +sixtyfour bits +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "sixtyfour bits" >/dev/null 2>&1; then : + gl_cv_solaris_64bit=yes +else + gl_cv_solaris_64bit=no +fi +rm -f conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_solaris_64bit" >&5 +$as_echo "$gl_cv_solaris_64bit" >&6; } + if test $gl_cv_solaris_64bit = yes; then + acl_libdirstem=lib/64 + case "$host_cpu" in + sparc*) acl_libdirstem2=lib/sparcv9 ;; + i*86 | x86_64) acl_libdirstem2=lib/amd64 ;; + esac + fi + ;; + *) + searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'` + if test -n "$searchpath"; then + acl_save_IFS="${IFS= }"; IFS=":" + for searchdir in $searchpath; do + if test -d "$searchdir"; then + case "$searchdir" in + */lib64/ | */lib64 ) acl_libdirstem=lib64 ;; + */../ | */.. ) + # Better ignore directories of this form. They are misleading. + ;; + *) searchdir=`cd "$searchdir" && pwd` + case "$searchdir" in + */lib64 ) acl_libdirstem=lib64 ;; + esac ;; + esac + fi + done + IFS="$acl_save_IFS" + fi + ;; + esac + test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem" + + + + gl_threads_api=none + LIBTHREAD= + LTLIBTHREAD= + LIBMULTITHREAD= + LTLIBMULTITHREAD= + if test "$gl_use_threads" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether imported symbols can be declared weak" >&5 +$as_echo_n "checking whether imported symbols can be declared weak... " >&6; } +if ${gl_cv_have_weak+:} false; then : + $as_echo_n "(cached) " >&6 +else + gl_cv_have_weak=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +extern void xyzzy (); +#pragma weak xyzzy +int +main () +{ +xyzzy(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_cv_have_weak=maybe +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test $gl_cv_have_weak = maybe; then + if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __ELF__ + Extensible Linking Format + #endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "Extensible Linking Format" >/dev/null 2>&1; then : + gl_cv_have_weak="guessing yes" +else + gl_cv_have_weak="guessing no" +fi +rm -f conftest* + + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <stdio.h> +#pragma weak fputs +int main () +{ + return (fputs == NULL); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gl_cv_have_weak=yes +else + gl_cv_have_weak=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: $gl_cv_have_weak" >&5 +$as_echo "$gl_cv_have_weak" >&6; } + if test "$gl_use_threads" = yes || test "$gl_use_threads" = posix; then + # On OSF/1, the compiler needs the flag -pthread or -D_REENTRANT so that + # it groks <pthread.h>. It's added above, in gl_THREADLIB_EARLY_BODY. + ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" +if test "x$ac_cv_header_pthread_h" = xyes; then : + gl_have_pthread_h=yes +else + gl_have_pthread_h=no +fi + + + if test "$gl_have_pthread_h" = yes; then + # Other possible tests: + # -lpthreads (FSU threads, PCthreads) + # -lgthreads + gl_have_pthread= + # Test whether both pthread_mutex_lock and pthread_mutexattr_init exist + # in libc. IRIX 6.5 has the first one in both libc and libpthread, but + # the second one only in libpthread, and lock.c needs it. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <pthread.h> +int +main () +{ +pthread_mutex_lock((pthread_mutex_t*)0); + pthread_mutexattr_init((pthread_mutexattr_t*)0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_have_pthread=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + # Test for libpthread by looking for pthread_kill. (Not pthread_self, + # since it is defined as a macro on OSF/1.) + if test -n "$gl_have_pthread"; then + # The program links fine without libpthread. But it may actually + # need to link with libpthread in order to create multiple threads. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_kill in -lpthread" >&5 +$as_echo_n "checking for pthread_kill in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_kill+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_kill (); +int +main () +{ +return pthread_kill (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_kill=yes +else + ac_cv_lib_pthread_pthread_kill=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_kill" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_kill" >&6; } +if test "x$ac_cv_lib_pthread_pthread_kill" = xyes; then : + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread + # On Solaris and HP-UX, most pthread functions exist also in libc. + # Therefore pthread_in_use() needs to actually try to create a + # thread: pthread_create from libc will fail, whereas + # pthread_create will actually create a thread. + case "$host_os" in + solaris* | hpux*) + +$as_echo "#define PTHREAD_IN_USE_DETECTION_HARD 1" >>confdefs.h + + esac + +fi + + else + # Some library is needed. Try libpthread and libc_r. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_kill in -lpthread" >&5 +$as_echo_n "checking for pthread_kill in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_kill+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_kill (); +int +main () +{ +return pthread_kill (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_kill=yes +else + ac_cv_lib_pthread_pthread_kill=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_kill" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_kill" >&6; } +if test "x$ac_cv_lib_pthread_pthread_kill" = xyes; then : + gl_have_pthread=yes + LIBTHREAD=-lpthread LTLIBTHREAD=-lpthread + LIBMULTITHREAD=-lpthread LTLIBMULTITHREAD=-lpthread +fi + + if test -z "$gl_have_pthread"; then + # For FreeBSD 4. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_kill in -lc_r" >&5 +$as_echo_n "checking for pthread_kill in -lc_r... " >&6; } +if ${ac_cv_lib_c_r_pthread_kill+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc_r $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_kill (); +int +main () +{ +return pthread_kill (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_c_r_pthread_kill=yes +else + ac_cv_lib_c_r_pthread_kill=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_kill" >&5 +$as_echo "$ac_cv_lib_c_r_pthread_kill" >&6; } +if test "x$ac_cv_lib_c_r_pthread_kill" = xyes; then : + gl_have_pthread=yes + LIBTHREAD=-lc_r LTLIBTHREAD=-lc_r + LIBMULTITHREAD=-lc_r LTLIBMULTITHREAD=-lc_r +fi + + fi + fi + if test -n "$gl_have_pthread"; then + gl_threads_api=posix + +$as_echo "#define USE_POSIX_THREADS 1" >>confdefs.h + + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + +$as_echo "#define USE_POSIX_THREADS_WEAK 1" >>confdefs.h + + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + fi + if test -z "$gl_have_pthread"; then + if test "$gl_use_threads" = yes || test "$gl_use_threads" = solaris; then + gl_have_solaristhread= + gl_save_LIBS="$LIBS" + LIBS="$LIBS -lthread" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <thread.h> +#include <synch.h> + +int +main () +{ +thr_self(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_have_solaristhread=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gl_save_LIBS" + if test -n "$gl_have_solaristhread"; then + gl_threads_api=solaris + LIBTHREAD=-lthread + LTLIBTHREAD=-lthread + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + +$as_echo "#define USE_SOLARIS_THREADS 1" >>confdefs.h + + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + +$as_echo "#define USE_SOLARIS_THREADS_WEAK 1" >>confdefs.h + + LIBTHREAD= + LTLIBTHREAD= + fi + fi + fi + fi + if test "$gl_use_threads" = pth; then + gl_save_CPPFLAGS="$CPPFLAGS" + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libpth" >&5 +$as_echo_n "checking how to link with libpth... " >&6; } +if ${ac_cv_libpth_libs+:} false; then : + $as_echo_n "(cached) " >&6 +else + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libpth-prefix was given. +if test "${with_libpth_prefix+set}" = set; then : + withval=$with_libpth_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi + +fi + + LIBPTH= + LTLIBPTH= + INCPTH= + LIBPTH_PREFIX= + HAVE_LIBPTH= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='pth ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBPTH="${LIBPTH}${LIBPTH:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBPTH; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + LIBPTH="${LIBPTH}${LIBPTH:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBPTH="${LIBPTH}${LIBPTH:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBPTH="${LIBPTH}${LIBPTH:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBPTH; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBPTH="${LIBPTH}${LIBPTH:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBPTH="${LIBPTH}${LIBPTH:+ }$found_so" + else + LIBPTH="${LIBPTH}${LIBPTH:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBPTH="${LIBPTH}${LIBPTH:+ }$found_a" + else + LIBPTH="${LIBPTH}${LIBPTH:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = 'pth'; then + LIBPTH_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = 'pth'; then + LIBPTH_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCPTH; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCPTH="${INCPTH}${INCPTH:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBPTH; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBPTH="${LIBPTH}${LIBPTH:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBPTH; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBPTH="${LIBPTH}${LIBPTH:+ }$dep" + LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }$dep" + ;; + esac + done + fi + else + LIBPTH="${LIBPTH}${LIBPTH:+ }-l$name" + LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBPTH="${LIBPTH}${LIBPTH:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBPTH="${LIBPTH}${LIBPTH:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBPTH="${LTLIBPTH}${LTLIBPTH:+ }-R$found_dir" + done + fi + + + + + + + ac_cv_libpth_libs="$LIBPTH" + ac_cv_libpth_ltlibs="$LTLIBPTH" + ac_cv_libpth_cppflags="$INCPTH" + ac_cv_libpth_prefix="$LIBPTH_PREFIX" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_libpth_libs" >&5 +$as_echo "$ac_cv_libpth_libs" >&6; } + LIBPTH="$ac_cv_libpth_libs" + LTLIBPTH="$ac_cv_libpth_ltlibs" + INCPTH="$ac_cv_libpth_cppflags" + LIBPTH_PREFIX="$ac_cv_libpth_prefix" + + for element in $INCPTH; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + + + HAVE_LIBPTH=yes + + + + gl_have_pth= + gl_save_LIBS="$LIBS" + LIBS="$LIBS $LIBPTH" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <pth.h> +int +main () +{ +pth_self(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gl_have_pth=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gl_save_LIBS" + if test -n "$gl_have_pth"; then + gl_threads_api=pth + LIBTHREAD="$LIBPTH" + LTLIBTHREAD="$LTLIBPTH" + LIBMULTITHREAD="$LIBTHREAD" + LTLIBMULTITHREAD="$LTLIBTHREAD" + +$as_echo "#define USE_PTH_THREADS 1" >>confdefs.h + + if test -n "$LIBMULTITHREAD" || test -n "$LTLIBMULTITHREAD"; then + if case "$gl_cv_have_weak" in *yes) true;; *) false;; esac; then + +$as_echo "#define USE_PTH_THREADS_WEAK 1" >>confdefs.h + + LIBTHREAD= + LTLIBTHREAD= + fi + fi + else + CPPFLAGS="$gl_save_CPPFLAGS" + fi + fi + if test -z "$gl_have_pthread"; then + case "$gl_use_threads" in + yes | windows | win32) # The 'win32' is for backward compatibility. + if { case "$host_os" in + mingw*) true;; + *) false;; + esac + }; then + gl_threads_api=windows + +$as_echo "#define USE_WINDOWS_THREADS 1" >>confdefs.h + + fi + ;; + esac + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for multithread API to use" >&5 +$as_echo_n "checking for multithread API to use... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_threads_api" >&5 +$as_echo "$gl_threads_api" >&6; } + + + + + + + + + + + + if test "$gl_threads_api" = posix; then + # OSF/1 4.0 and Mac OS X 10.1 lack the pthread_rwlock_t type and the + # pthread_rwlock_* functions. + ac_fn_c_check_type "$LINENO" "pthread_rwlock_t" "ac_cv_type_pthread_rwlock_t" "#include <pthread.h> +" +if test "x$ac_cv_type_pthread_rwlock_t" = xyes; then : + +$as_echo "#define HAVE_PTHREAD_RWLOCK 1" >>confdefs.h + +fi + + # glibc defines PTHREAD_MUTEX_RECURSIVE as enum, not as a macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include <pthread.h> +int +main () +{ + +#if __FreeBSD__ == 4 +error "No, in FreeBSD 4.0 recursive mutexes actually don't work." +#elif (defined __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ \ + && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070) +error "No, in Mac OS X < 10.7 recursive mutexes actually don't work." +#else +int x = (int)PTHREAD_MUTEX_RECURSIVE; +return !x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_PTHREAD_MUTEX_RECURSIVE 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + : + + + + + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libiconv-prefix was given. +if test "${with_libiconv_prefix+set}" = set; then : + withval=$with_libiconv_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi + +fi + + LIBICONV= + LTLIBICONV= + INCICONV= + LIBICONV_PREFIX= + HAVE_LIBICONV= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='iconv ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = 'iconv'; then + LIBICONV_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = 'iconv'; then + LIBICONV_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" + ;; + esac + done + fi + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" + done + fi + + + + + + + + + + + + + am_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCICONV; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 +$as_echo_n "checking for iconv... " >&6; } +if ${am_cv_func_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <stdlib.h> +#include <iconv.h> + +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <stdlib.h> +#include <iconv.h> + +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_lib_iconv=yes + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$am_save_LIBS" + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 +$as_echo "$am_cv_func_iconv" >&6; } + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 +$as_echo_n "checking for working iconv... " >&6; } +if ${am_cv_func_iconv_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + if test "$cross_compiling" = yes; then : + + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <iconv.h> +#include <string.h> +int main () +{ + int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static const char input[] = "\263"; + char buf[10]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + const char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + const char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + (char **) &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + if (/* Try standardized names. */ + iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1) + /* Try IRIX, OSF/1 names. */ + && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1) + /* Try AIX names. */ + && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1) + /* Try HP-UX names. */ + && iconv_open ("utf8", "eucJP") == (iconv_t)(-1)) + result |= 16; + return result; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + am_cv_func_iconv_works=yes +else + am_cv_func_iconv_works=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + LIBS="$am_save_LIBS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 +$as_echo "$am_cv_func_iconv_works" >&6; } + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then + +$as_echo "#define HAVE_ICONV 1" >>confdefs.h + + fi + if test "$am_cv_lib_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 +$as_echo_n "checking how to link with libiconv... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 +$as_echo "$LIBICONV" >&6; } + else + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + + + + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5 +$as_echo_n "checking for iconv declaration... " >&6; } + if ${am_cv_proto_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <stdlib.h> +#include <iconv.h> +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + am_cv_proto_iconv_arg1="" +else + am_cv_proto_iconv_arg1="const" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" +fi + + am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: + $am_cv_proto_iconv" >&5 +$as_echo " + $am_cv_proto_iconv" >&6; } + +cat >>confdefs.h <<_ACEOF +#define ICONV_CONST $am_cv_proto_iconv_arg1 +_ACEOF + + + fi + + + + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (int a) { a = __builtin_expect (a, 10); return a == 10 ? 0 : 1; } +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +$as_echo "#define HAVE_BUILTIN_EXPECT 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + for ac_header in argz.h inttypes.h limits.h unistd.h sys/param.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + for ac_func in getcwd getegid geteuid getgid getuid mempcpy munmap \ + stpcpy strcasecmp strdup strtoul tsearch uselocale argz_count \ + argz_stringify argz_next __fsetlocking +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + ac_fn_c_check_decl "$LINENO" "feof_unlocked" "ac_cv_have_decl_feof_unlocked" "#include <stdio.h> +" +if test "x$ac_cv_have_decl_feof_unlocked" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FEOF_UNLOCKED $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "fgets_unlocked" "ac_cv_have_decl_fgets_unlocked" "#include <stdio.h> +" +if test "x$ac_cv_have_decl_fgets_unlocked" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_FGETS_UNLOCKED $ac_have_decl +_ACEOF + + + + + for ac_prog in bison +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_INTLBISON+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$INTLBISON"; then + ac_cv_prog_INTLBISON="$INTLBISON" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_INTLBISON="$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 +INTLBISON=$ac_cv_prog_INTLBISON +if test -n "$INTLBISON"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INTLBISON" >&5 +$as_echo "$INTLBISON" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$INTLBISON" && break +done + + if test -z "$INTLBISON"; then + ac_verc_fail=yes + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking version of bison" >&5 +$as_echo_n "checking version of bison... " >&6; } + ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; + 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*) + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prog_version" >&5 +$as_echo "$ac_prog_version" >&6; } + fi + if test $ac_verc_fail = yes; then + INTLBISON=: + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5 +$as_echo_n "checking for long long int... " >&6; } +if ${ac_cv_type_long_long_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_type_long_long_int=yes + if test "x${ac_cv_prog_cc_c99-no}" = xno; then + ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int + if test $ac_cv_type_long_long_int = yes; then + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + #ifndef LLONG_MAX + # define HALF \ + (1LL << (sizeof (long long int) * CHAR_BIT - 2)) + # define LLONG_MAX (HALF - 1 + HALF) + #endif +int +main () +{ +long long int n = 1; + int i; + for (i = 0; ; i++) + { + long long int m = n << i; + if (m >> i != n) + return 1; + if (LLONG_MAX / 2 < m) + break; + } + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_type_long_long_int=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 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5 +$as_echo "$ac_cv_type_long_long_int" >&6; } + if test $ac_cv_type_long_long_int = yes; then + +$as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wchar_t" >&5 +$as_echo_n "checking for wchar_t... " >&6; } +if ${gt_cv_c_wchar_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stddef.h> + wchar_t foo = (wchar_t)'\0'; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gt_cv_c_wchar_t=yes +else + gt_cv_c_wchar_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_c_wchar_t" >&5 +$as_echo "$gt_cv_c_wchar_t" >&6; } + if test $gt_cv_c_wchar_t = yes; then + +$as_echo "#define HAVE_WCHAR_T 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wint_t" >&5 +$as_echo_n "checking for wint_t... " >&6; } +if ${gt_cv_c_wint_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before + <wchar.h>. + BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be included + before <wchar.h>. */ +#include <stddef.h> +#include <stdio.h> +#include <time.h> +#include <wchar.h> + wint_t foo = (wchar_t)'\0'; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gt_cv_c_wint_t=yes +else + gt_cv_c_wint_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_c_wint_t" >&5 +$as_echo "$gt_cv_c_wint_t" >&6; } + if test $gt_cv_c_wint_t = yes; then + +$as_echo "#define HAVE_WINT_T 1" >>confdefs.h + + fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for intmax_t" >&5 +$as_echo_n "checking for intmax_t... " >&6; } +if ${gt_cv_c_intmax_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <stddef.h> +#include <stdlib.h> +#if HAVE_STDINT_H_WITH_UINTMAX +#include <stdint.h> +#endif +#if HAVE_INTTYPES_H_WITH_UINTMAX +#include <inttypes.h> +#endif + +int +main () +{ +intmax_t x = -1; + return !x; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gt_cv_c_intmax_t=yes +else + gt_cv_c_intmax_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_c_intmax_t" >&5 +$as_echo "$gt_cv_c_intmax_t" >&6; } + if test $gt_cv_c_intmax_t = yes; then + +$as_echo "#define HAVE_INTMAX_T 1" >>confdefs.h + + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether printf() supports POSIX/XSI format strings" >&5 +$as_echo_n "checking whether printf() supports POSIX/XSI format strings... " >&6; } +if ${gt_cv_func_printf_posix+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if test "$cross_compiling" = yes; then : + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined __NetBSD__ || defined __BEOS__ || defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ + notposix +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "notposix" >/dev/null 2>&1; then : + gt_cv_func_printf_posix="guessing no" +else + gt_cv_func_printf_posix="guessing yes" +fi +rm -f conftest* + + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <stdio.h> +#include <string.h> +/* The string "%2$d %1$d", with dollar characters protected from the shell's + dollar expansion (possibly an autoconf bug). */ +static char format[] = { '%', '2', '$', 'd', ' ', '%', '1', '$', 'd', '\0' }; +static char buf[100]; +int main () +{ + sprintf (buf, format, 33, 55); + return (strcmp (buf, "55 33") != 0); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gt_cv_func_printf_posix=yes +else + gt_cv_func_printf_posix=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: $gt_cv_func_printf_posix" >&5 +$as_echo "$gt_cv_func_printf_posix" >&6; } + case $gt_cv_func_printf_posix in + *yes) + +$as_echo "#define HAVE_POSIX_PRINTF 1" >>confdefs.h + + ;; + esac + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C Library >= 2.1 or uClibc" >&5 +$as_echo_n "checking whether we are using the GNU C Library >= 2.1 or uClibc... " >&6; } +if ${ac_cv_gnu_library_2_1+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <features.h> +#ifdef __GNU_LIBRARY__ + #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2) + Lucky GNU user + #endif +#endif +#ifdef __UCLIBC__ + Lucky user +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "Lucky" >/dev/null 2>&1; then : + ac_cv_gnu_library_2_1=yes +else + ac_cv_gnu_library_2_1=no +fi +rm -f conftest* + + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_gnu_library_2_1" >&5 +$as_echo "$ac_cv_gnu_library_2_1" >&6; } + + GLIBC21="$ac_cv_gnu_library_2_1" + + + + for ac_header in stdint.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" +if test "x$ac_cv_header_stdint_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDINT_H 1 +_ACEOF + +fi + +done + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SIZE_MAX" >&5 +$as_echo_n "checking for SIZE_MAX... " >&6; } +if ${gl_cv_size_max+:} false; then : + $as_echo_n "(cached) " >&6 +else + + gl_cv_size_max= + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <limits.h> +#if HAVE_STDINT_H +#include <stdint.h> +#endif +#ifdef SIZE_MAX +Found it +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "Found it" >/dev/null 2>&1; then : + gl_cv_size_max=yes +fi +rm -f conftest* + + if test -z "$gl_cv_size_max"; then + if ac_fn_c_compute_int "$LINENO" "sizeof (size_t) * CHAR_BIT - 1" "size_t_bits_minus_1" "#include <stddef.h> +#include <limits.h>"; then : + +else + size_t_bits_minus_1= +fi + + if ac_fn_c_compute_int "$LINENO" "sizeof (size_t) <= sizeof (unsigned int)" "fits_in_uint" "#include <stddef.h>"; then : + +else + fits_in_uint= +fi + + if test -n "$size_t_bits_minus_1" && test -n "$fits_in_uint"; then + if test $fits_in_uint = 1; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stddef.h> + extern size_t foo; + extern unsigned long foo; + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + fits_in_uint=0 +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $fits_in_uint = 1; then + gl_cv_size_max="(((1U << $size_t_bits_minus_1) - 1) * 2 + 1)" + else + gl_cv_size_max="(((1UL << $size_t_bits_minus_1) - 1) * 2 + 1)" + fi + else + gl_cv_size_max='((size_t)~(size_t)0)' + fi + fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_size_max" >&5 +$as_echo "$gl_cv_size_max" >&6; } + if test "$gl_cv_size_max" != yes; then + +cat >>confdefs.h <<_ACEOF +#define SIZE_MAX $gl_cv_size_max +_ACEOF + + fi + + + + + for ac_header in stdint.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" +if test "x$ac_cv_header_stdint_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDINT_H 1 +_ACEOF + +fi + +done + + + + + + for ac_func in $ac_func_list +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fcntl.h" >&5 +$as_echo_n "checking for working fcntl.h... " >&6; } +if ${gl_cv_header_working_fcntl_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + gl_cv_header_working_fcntl_h=cross-compiling +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/stat.h> + #if HAVE_UNISTD_H + # include <unistd.h> + #else /* on Windows with MSVC */ + # include <io.h> + # include <stdlib.h> + # defined sleep(n) _sleep ((n) * 1000) + #endif + #include <fcntl.h> + #ifndef O_NOATIME + #define O_NOATIME 0 + #endif + #ifndef O_NOFOLLOW + #define O_NOFOLLOW 0 + #endif + static int const constants[] = + { + O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC, O_APPEND, + O_NONBLOCK, O_SYNC, O_ACCMODE, O_RDONLY, O_RDWR, O_WRONLY + }; + +int +main () +{ + + int result = !constants; + #if HAVE_SYMLINK + { + static char const sym[] = "conftest.sym"; + if (symlink ("/dev/null", sym) != 0) + result |= 2; + else + { + int fd = open (sym, O_WRONLY | O_NOFOLLOW | O_CREAT, 0); + if (fd >= 0) + { + close (fd); + result |= 4; + } + } + if (unlink (sym) != 0 || symlink (".", sym) != 0) + result |= 2; + else + { + int fd = open (sym, O_RDONLY | O_NOFOLLOW); + if (fd >= 0) + { + close (fd); + result |= 4; + } + } + unlink (sym); + } + #endif + { + static char const file[] = "confdefs.h"; + int fd = open (file, O_RDONLY | O_NOATIME); + if (fd < 0) + result |= 8; + else + { + struct stat st0; + if (fstat (fd, &st0) != 0) + result |= 16; + else + { + char c; + sleep (1); + if (read (fd, &c, 1) != 1) + result |= 24; + else + { + if (close (fd) != 0) + result |= 32; + else + { + struct stat st1; + if (stat (file, &st1) != 0) + result |= 40; + else + if (st0.st_atime != st1.st_atime) + result |= 64; + } + } + } + } + } + return result; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gl_cv_header_working_fcntl_h=yes +else + case $? in #( + 4) gl_cv_header_working_fcntl_h='no (bad O_NOFOLLOW)';; #( + 64) gl_cv_header_working_fcntl_h='no (bad O_NOATIME)';; #( + 68) gl_cv_header_working_fcntl_h='no (bad O_NOATIME, O_NOFOLLOW)';; #( + *) gl_cv_header_working_fcntl_h='no';; + esac +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: $gl_cv_header_working_fcntl_h" >&5 +$as_echo "$gl_cv_header_working_fcntl_h" >&6; } + + case $gl_cv_header_working_fcntl_h in #( + *O_NOATIME* | no | cross-compiling) ac_val=0;; #( + *) ac_val=1;; + esac + +cat >>confdefs.h <<_ACEOF +#define HAVE_WORKING_O_NOATIME $ac_val +_ACEOF + + + case $gl_cv_header_working_fcntl_h in #( + *O_NOFOLLOW* | no | cross-compiling) ac_val=0;; #( + *) ac_val=1;; + esac + +cat >>confdefs.h <<_ACEOF +#define HAVE_WORKING_O_NOFOLLOW $ac_val +_ACEOF + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 +$as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; } +if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <CoreFoundation/CFPreferences.h> +int +main () +{ +CFPreferencesCopyAppValue(NULL, NULL) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFPreferencesCopyAppValue=yes +else + gt_cv_func_CFPreferencesCopyAppValue=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 +$as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + +$as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 +$as_echo_n "checking for CFLocaleCopyCurrent... " >&6; } +if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <CoreFoundation/CFLocale.h> +int +main () +{ +CFLocaleCopyCurrent(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFLocaleCopyCurrent=yes +else + gt_cv_func_CFLocaleCopyCurrent=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 +$as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; } + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + +$as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h + + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + + + + + + + + + + + case "$enable_silent_rules" in + yes) INTL_DEFAULT_VERBOSITY=0;; + no) INTL_DEFAULT_VERBOSITY=1;; + *) INTL_DEFAULT_VERBOSITY=1;; + esac + + + ac_fn_c_check_type "$LINENO" "ptrdiff_t" "ac_cv_type_ptrdiff_t" "$ac_includes_default" +if test "x$ac_cv_type_ptrdiff_t" = xyes; then : + +else + +$as_echo "#define ptrdiff_t long" >>confdefs.h + + +fi + + for ac_header in features.h stddef.h stdlib.h string.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + for ac_func in asprintf fwprintf newlocale putenv setenv setlocale \ + snprintf strnlen wcslen wcsnlen mbrtowc wcrtomb +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + ac_fn_c_check_decl "$LINENO" "_snprintf" "ac_cv_have_decl__snprintf" "#include <stdio.h> +" +if test "x$ac_cv_have_decl__snprintf" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL__SNPRINTF $ac_have_decl +_ACEOF +ac_fn_c_check_decl "$LINENO" "_snwprintf" "ac_cv_have_decl__snwprintf" "#include <stdio.h> +" +if test "x$ac_cv_have_decl__snwprintf" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL__SNWPRINTF $ac_have_decl +_ACEOF + + + ac_fn_c_check_decl "$LINENO" "getc_unlocked" "ac_cv_have_decl_getc_unlocked" "#include <stdio.h> +" +if test "x$ac_cv_have_decl_getc_unlocked" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GETC_UNLOCKED $ac_have_decl +_ACEOF + + + case $gt_cv_func_printf_posix in + *yes) HAVE_POSIX_PRINTF=1 ;; + *) HAVE_POSIX_PRINTF=0 ;; + esac + + if test "$ac_cv_func_asprintf" = yes; then + HAVE_ASPRINTF=1 + else + HAVE_ASPRINTF=0 + fi + + if test "$ac_cv_func_snprintf" = yes; then + HAVE_SNPRINTF=1 + else + HAVE_SNPRINTF=0 + fi + + if test "$ac_cv_func_newlocale" = yes; then + HAVE_NEWLOCALE=1 + else + HAVE_NEWLOCALE=0 + fi + + if test "$ac_cv_func_wprintf" = yes; then + HAVE_WPRINTF=1 + else + HAVE_WPRINTF=0 + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_langinfo and CODESET" >&5 +$as_echo_n "checking for nl_langinfo and CODESET... " >&6; } +if ${am_cv_langinfo_codeset+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <langinfo.h> +int +main () +{ +char* cs = nl_langinfo(CODESET); return !cs; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + am_cv_langinfo_codeset=yes +else + am_cv_langinfo_codeset=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_langinfo_codeset" >&5 +$as_echo "$am_cv_langinfo_codeset" >&6; } + if test $am_cv_langinfo_codeset = yes; then + +$as_echo "#define HAVE_LANGINFO_CODESET 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LC_MESSAGES" >&5 +$as_echo_n "checking for LC_MESSAGES... " >&6; } +if ${gt_cv_val_LC_MESSAGES+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <locale.h> +int +main () +{ +return LC_MESSAGES + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_val_LC_MESSAGES=yes +else + gt_cv_val_LC_MESSAGES=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_val_LC_MESSAGES" >&5 +$as_echo "$gt_cv_val_LC_MESSAGES" >&6; } + if test $gt_cv_val_LC_MESSAGES = yes; then + +$as_echo "#define HAVE_LC_MESSAGES 1" >>confdefs.h + + fi + + + if test "$enable_shared" = yes; then + case "$host_os" in + mingw* | cygwin*) is_woe32dll=yes ;; + *) is_woe32dll=no ;; + esac + else + is_woe32dll=no + fi + WOE32DLL=$is_woe32dll + + + case "$host_os" in + mingw* | cygwin*) is_woe32=yes ;; + *) is_woe32=no ;; + esac + WOE32=$is_woe32 + + if test $WOE32 = yes; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. +set dummy ${ac_tool_prefix}windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_WINDRES+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$WINDRES"; then + ac_cv_prog_WINDRES="$WINDRES" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_WINDRES="${ac_tool_prefix}windres" + $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 +WINDRES=$ac_cv_prog_WINDRES +if test -n "$WINDRES"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINDRES" >&5 +$as_echo "$WINDRES" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_WINDRES"; then + ac_ct_WINDRES=$WINDRES + # Extract the first word of "windres", so it can be a program name with args. +set dummy windres; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_WINDRES+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_WINDRES"; then + ac_cv_prog_ac_ct_WINDRES="$ac_ct_WINDRES" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_WINDRES="windres" + $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_WINDRES=$ac_cv_prog_ac_ct_WINDRES +if test -n "$ac_ct_WINDRES"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_WINDRES" >&5 +$as_echo "$ac_ct_WINDRES" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_WINDRES" = x; then + WINDRES="" + 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 + WINDRES=$ac_ct_WINDRES + fi +else + WINDRES="$ac_cv_prog_WINDRES" +fi + + fi + + case "$host_os" in + hpux*) LTLIBC="" ;; + *) LTLIBC="-lc" ;; + esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFPreferencesCopyAppValue" >&5 +$as_echo_n "checking for CFPreferencesCopyAppValue... " >&6; } +if ${gt_cv_func_CFPreferencesCopyAppValue+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <CoreFoundation/CFPreferences.h> +int +main () +{ +CFPreferencesCopyAppValue(NULL, NULL) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFPreferencesCopyAppValue=yes +else + gt_cv_func_CFPreferencesCopyAppValue=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFPreferencesCopyAppValue" >&5 +$as_echo "$gt_cv_func_CFPreferencesCopyAppValue" >&6; } + if test $gt_cv_func_CFPreferencesCopyAppValue = yes; then + +$as_echo "#define HAVE_CFPREFERENCESCOPYAPPVALUE 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CFLocaleCopyCurrent" >&5 +$as_echo_n "checking for CFLocaleCopyCurrent... " >&6; } +if ${gt_cv_func_CFLocaleCopyCurrent+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_LIBS="$LIBS" + LIBS="$LIBS -Wl,-framework -Wl,CoreFoundation" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <CoreFoundation/CFLocale.h> +int +main () +{ +CFLocaleCopyCurrent(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gt_cv_func_CFLocaleCopyCurrent=yes +else + gt_cv_func_CFLocaleCopyCurrent=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$gt_save_LIBS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_CFLocaleCopyCurrent" >&5 +$as_echo "$gt_cv_func_CFLocaleCopyCurrent" >&6; } + if test $gt_cv_func_CFLocaleCopyCurrent = yes; then + +$as_echo "#define HAVE_CFLOCALECOPYCURRENT 1" >>confdefs.h + + fi + INTL_MACOSX_LIBS= + if test $gt_cv_func_CFPreferencesCopyAppValue = yes || test $gt_cv_func_CFLocaleCopyCurrent = yes; then + INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation" + fi + + + + + + + BUILD_INCLUDED_LIBINTL=no + USE_INCLUDED_LIBINTL=no + + LIBINTL= + LTLIBINTL= + POSUB= + + case " $gt_needs " in + *" need-formatstring-macros "*) gt_api_version=3 ;; + *" need-ngettext "*) gt_api_version=2 ;; + *) gt_api_version=1 ;; + esac + gt_func_gnugettext_libc="gt_cv_func_gnugettext${gt_api_version}_libc" + gt_func_gnugettext_libintl="gt_cv_func_gnugettext${gt_api_version}_libintl" + + if test "$USE_NLS" = "yes"; then + gt_use_preinstalled_gnugettext=no + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether included gettext is requested" >&5 +$as_echo_n "checking whether included gettext is requested... " >&6; } + +# Check whether --with-included-gettext was given. +if test "${with_included_gettext+set}" = set; then : + withval=$with_included_gettext; nls_cv_force_use_gnu_gettext=$withval +else + nls_cv_force_use_gnu_gettext=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nls_cv_force_use_gnu_gettext" >&5 +$as_echo "$nls_cv_force_use_gnu_gettext" >&6; } + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + + + if test $gt_api_version -ge 3; then + gt_revision_test_code=' +#ifndef __GNU_GETTEXT_SUPPORTED_REVISION +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1) +#endif +typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1]; +' + else + gt_revision_test_code= + fi + if test $gt_api_version -ge 2; then + gt_expression_test_code=' + * ngettext ("", "", 0)' + else + gt_expression_test_code= + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libc" >&5 +$as_echo_n "checking for GNU gettext in libc... " >&6; } +if eval \${$gt_func_gnugettext_libc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <libintl.h> +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern int *_nl_domain_bindings; + +int +main () +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_domain_bindings + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$gt_func_gnugettext_libc=yes" +else + eval "$gt_func_gnugettext_libc=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$gt_func_gnugettext_libc + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" != "yes"; }; then + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libintl-prefix was given. +if test "${with_libintl_prefix+set}" = set; then : + withval=$with_libintl_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "$acl_libdirstem2" != "$acl_libdirstem" \ + && ! test -d "$withval/$acl_libdirstem"; then + additional_libdir="$withval/$acl_libdirstem2" + fi + fi + fi + +fi + + LIBINTL= + LTLIBINTL= + INCINTL= + LIBINTL_PREFIX= + HAVE_LIBINTL= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='intl ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBINTL="${LIBINTL}${LIBINTL:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no \ + || test "X$found_dir" = "X/usr/$acl_libdirstem" \ + || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_so" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }$found_a" + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + if test "$name" = 'intl'; then + LIBINTL_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + */$acl_libdirstem2 | */$acl_libdirstem2/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'` + if test "$name" = 'intl'; then + LIBINTL_PREFIX="$basedir" + fi + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCINTL="${INCINTL}${INCINTL:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \ + && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \ + || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBINTL="${LIBINTL}${LIBINTL:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBINTL; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBINTL="${LIBINTL}${LIBINTL:+ }$dep" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }$dep" + ;; + esac + done + fi + else + LIBINTL="${LIBINTL}${LIBINTL:+ }-l$name" + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBINTL="${LIBINTL}${LIBINTL:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBINTL="${LTLIBINTL}${LTLIBINTL:+ }-R$found_dir" + done + fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU gettext in libintl" >&5 +$as_echo_n "checking for GNU gettext in libintl... " >&6; } +if eval \${$gt_func_gnugettext_libintl+:} false; then : + $as_echo_n "(cached) " >&6 +else + gt_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCINTL" + gt_save_LIBS="$LIBS" + LIBS="$LIBS $LIBINTL" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <libintl.h> +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + +int +main () +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$gt_func_gnugettext_libintl=yes" +else + eval "$gt_func_gnugettext_libintl=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" != yes; } && test -n "$LIBICONV"; then + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <libintl.h> +$gt_revision_test_code +extern int _nl_msg_cat_cntr; +extern +#ifdef __cplusplus +"C" +#endif +const char *_nl_expand_alias (const char *); + +int +main () +{ + +bindtextdomain ("", ""); +return * gettext ("")$gt_expression_test_code + _nl_msg_cat_cntr + *_nl_expand_alias ("") + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + LIBINTL="$LIBINTL $LIBICONV" + LTLIBINTL="$LTLIBINTL $LTLIBICONV" + eval "$gt_func_gnugettext_libintl=yes" + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + CPPFLAGS="$gt_save_CPPFLAGS" + LIBS="$gt_save_LIBS" +fi +eval ac_res=\$$gt_func_gnugettext_libintl + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + fi + + if { eval "gt_val=\$$gt_func_gnugettext_libc"; test "$gt_val" = "yes"; } \ + || { { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; } \ + && test "$PACKAGE" != gettext-runtime \ + && test "$PACKAGE" != gettext-tools; }; then + gt_use_preinstalled_gnugettext=yes + else + LIBINTL= + LTLIBINTL= + INCINTL= + fi + + + if test "$gt_use_preinstalled_gnugettext" != "yes"; then + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + BUILD_INCLUDED_LIBINTL=yes + USE_INCLUDED_LIBINTL=yes + LIBINTL="\${top_builddir}/intl/libintl.a $LIBICONV $LIBTHREAD" + LTLIBINTL="\${top_builddir}/intl/libintl.a $LTLIBICONV $LTLIBTHREAD" + LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'` + fi + + CATOBJEXT= + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + CATOBJEXT=.gmo + fi + + + if test -n "$INTL_MACOSX_LIBS"; then + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + LIBINTL="$LIBINTL $INTL_MACOSX_LIBS" + LTLIBINTL="$LTLIBINTL $INTL_MACOSX_LIBS" + fi + fi + + if test "$gt_use_preinstalled_gnugettext" = "yes" \ + || test "$nls_cv_use_gnu_gettext" = "yes"; then + +$as_echo "#define ENABLE_NLS 1" >>confdefs.h + + else + USE_NLS=no + fi + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use NLS" >&5 +$as_echo_n "checking whether to use NLS... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_NLS" >&5 +$as_echo "$USE_NLS" >&6; } + if test "$USE_NLS" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where the gettext function comes from" >&5 +$as_echo_n "checking where the gettext function comes from... " >&6; } + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + gt_source="external libintl" + else + gt_source="libc" + fi + else + gt_source="included intl directory" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_source" >&5 +$as_echo "$gt_source" >&6; } + fi + + if test "$USE_NLS" = "yes"; then + + if test "$gt_use_preinstalled_gnugettext" = "yes"; then + if { eval "gt_val=\$$gt_func_gnugettext_libintl"; test "$gt_val" = "yes"; }; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libintl" >&5 +$as_echo_n "checking how to link with libintl... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBINTL" >&5 +$as_echo "$LIBINTL" >&6; } + + for element in $INCINTL; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + fi + + +$as_echo "#define HAVE_GETTEXT 1" >>confdefs.h + + +$as_echo "#define HAVE_DCGETTEXT 1" >>confdefs.h + + fi + + POSUB=po + fi + + + if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then + BUILD_INCLUDED_LIBINTL=yes + fi + + + + + + nls_cv_header_intl= + nls_cv_header_libgt= + + DATADIRNAME=share + + + INSTOBJEXT=.mo + + + GENCAT=gencat + + + INTLOBJS= + if test "$USE_INCLUDED_LIBINTL" = yes; then + INTLOBJS="\$(GETTOBJS)" + fi + + + INTL_LIBTOOL_SUFFIX_PREFIX= + + + + INTLLIBS="$LIBINTL" + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU make" >&5 +$as_echo_n "checking for GNU make... " >&6; } +if ${_cv_gnu_make_command+:} false; then : + $as_echo_n "(cached) " >&6 +else + _cv_gnu_make_command='' ; + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then + _cv_gnu_make_command=$a ; + break; + fi + done ; + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_cv_gnu_make_command" >&5 +$as_echo "$_cv_gnu_make_command" >&6; } ; + if test "x$_cv_gnu_make_command" != "x" ; then + ifGNUmake='' ; + ifNotGNUmake='#' ; + else + ifGNUmake='#' ; + ifNotGNUmake='' ; + { $as_echo "$as_me:${as_lineno-$LINENO}: result: \"Not found\"" >&5 +$as_echo "\"Not found\"" >&6; }; + 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 ${ac_cv_path_LN+:} false; 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 as_fn_executable_p "$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 + +# Extract the first word of "mv", so it can be a program name with args. +set dummy mv; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MV+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MV in + [\\/]* | ?:[\\/]*) + ac_cv_path_MV="$MV" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_MV="$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_MV" && ac_cv_path_MV="mv" + ;; +esac +fi +MV=$ac_cv_path_MV +if test -n "$MV"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MV" >&5 +$as_echo "$MV" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "cp", so it can be a program name with args. +set dummy cp; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CP in + [\\/]* | ?:[\\/]*) + ac_cv_path_CP="$CP" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CP="$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_CP" && ac_cv_path_CP="cp" + ;; +esac +fi +CP=$ac_cv_path_CP +if test -n "$CP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CP" >&5 +$as_echo "$CP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "rm", so it can be a program name with args. +set dummy rm; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_RM+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $RM in + [\\/]* | ?:[\\/]*) + ac_cv_path_RM="$RM" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_RM="$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_RM" && ac_cv_path_RM="rm" + ;; +esac +fi +RM=$ac_cv_path_RM +if test -n "$RM"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RM" >&5 +$as_echo "$RM" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "chmod", so it can be a program name with args. +set dummy chmod; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CHMOD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CHMOD in + [\\/]* | ?:[\\/]*) + ac_cv_path_CHMOD="$CHMOD" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CHMOD="$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_CHMOD" && ac_cv_path_CHMOD=":" + ;; +esac +fi +CHMOD=$ac_cv_path_CHMOD +if test -n "$CHMOD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CHMOD" >&5 +$as_echo "$CHMOD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +# Extract the first word of "sed", so it can be a program name with args. +set dummy sed; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SED in + [\\/]* | ?:[\\/]*) + ac_cv_path_SED="$SED" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SED="$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_SED" && ac_cv_path_SED="sed" + ;; +esac +fi +SED=$ac_cv_path_SED +if test -n "$SED"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 +$as_echo "$SED" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_PERL="$PERL" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PERL="$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_PERL" && ac_cv_path_PERL="perl" + ;; +esac +fi +PERL=$ac_cv_path_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "ldconfig", so it can be a program name with args. +set dummy ldconfig; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_LDCONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $LDCONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_LDCONFIG="$LDCONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_LDCONFIG="$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_LDCONFIG" && ac_cv_path_LDCONFIG=":" + ;; +esac +fi +LDCONFIG=$ac_cv_path_LDCONFIG +if test -n "$LDCONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LDCONFIG" >&5 +$as_echo "$LDCONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + $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 +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="ar" + $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_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="ar" + 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 + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +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 ${ac_cv_prog_RANLIB+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_ac_ct_RANLIB+:} false; 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 as_fn_executable_p "$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 + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +# Extract the first word of "makeinfo", so it can be a program name with args. +set dummy makeinfo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MAKEINFO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MAKEINFO"; then + ac_cv_prog_MAKEINFO="$MAKEINFO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MAKEINFO="makeinfo" + $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 +MAKEINFO=$ac_cv_prog_MAKEINFO +if test -n "$MAKEINFO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKEINFO" >&5 +$as_echo "$MAKEINFO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "_$MAKEINFO" = "_"; then + MAKEINFO="@echo Makeinfo is missing. Info documentation will not be built.;true" +else + case "$MAKEINFO" in + */missing.*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: +*** Makeinfo is missing. Info documentation will not be built." >&5 +$as_echo "$as_me: WARNING: +*** Makeinfo is missing. Info documentation will not be built." >&2;} + ;; + *) + ;; + esac +fi + + +# See if we need a separate native compiler. +if test $cross_compiling = no; then + BUILD_CC="$CC" + +else + for ac_prog in gcc cc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_BUILD_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$BUILD_CC"; then + ac_cv_prog_BUILD_CC="$BUILD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_BUILD_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 +BUILD_CC=$ac_cv_prog_BUILD_CC +if test -n "$BUILD_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BUILD_CC" >&5 +$as_echo "$BUILD_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$BUILD_CC" && break +done + +fi +for ac_header in dirent.h errno.h execinfo.h getopt.h malloc.h mntent.h paths.h semaphore.h setjmp.h signal.h stdarg.h stdint.h stdlib.h termios.h termio.h unistd.h utime.h linux/falloc.h linux/fd.h linux/major.h linux/loop.h net/if_dl.h netinet/in.h sys/disklabel.h sys/disk.h sys/file.h sys/ioctl.h sys/mkdev.h sys/mman.h sys/mount.h sys/prctl.h sys/resource.h sys/select.h sys/socket.h sys/sockio.h sys/stat.h sys/syscall.h sys/sysmacros.h sys/time.h sys/types.h sys/un.h sys/wait.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in net/if.h +do : + ac_fn_c_check_header_compile "$LINENO" "net/if.h" "ac_cv_header_net_if_h" " +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#if HAVE_SYS_SOCKET +#include <sys/socket.h> +#endif + +" +if test "x$ac_cv_header_net_if_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NET_IF_H 1 +_ACEOF + +fi + +done + +for ac_func in vprintf +do : + ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf" +if test "x$ac_cv_func_vprintf" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VPRINTF 1 +_ACEOF + +ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt" +if test "x$ac_cv_func__doprnt" = xyes; then : + +$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h + +fi + +fi +done + + +ac_fn_c_check_member "$LINENO" "struct dirent" "d_reclen" "ac_cv_member_struct_dirent_d_reclen" "#include <dirent.h> +" +if test "x$ac_cv_member_struct_dirent_d_reclen" = xyes; then : + +$as_echo "#define HAVE_RECLEN_DIRENT 1" >>confdefs.h + +fi + +ac_fn_c_check_member "$LINENO" "struct stat" "st_atim" "ac_cv_member_struct_stat_st_atim" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_atim" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_ATIM 1 +_ACEOF + + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "#include <sys/types.h> +" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +$as_echo "#define HAVE_TYPE_SSIZE_T 1" >>confdefs.h + +fi + +ac_fn_c_check_decl "$LINENO" "llseek" "ac_cv_have_decl_llseek" "#include <unistd.h> +" +if test "x$ac_cv_have_decl_llseek" = xyes; then : + +$as_echo "#define HAVE_LLSEEK_PROTOTYPE 1" >>confdefs.h + +fi + +ac_fn_c_check_decl "$LINENO" "lseek64" "ac_cv_have_decl_lseek64" "#define _LARGEFILE_SOURCE + #define _LARGEFILE64_SOURCE + #include <unistd.h> +" +if test "x$ac_cv_have_decl_lseek64" = xyes; then : + +$as_echo "#define HAVE_LSEEK64_PROTOTYPE 1" >>confdefs.h + +fi + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 +$as_echo_n "checking size of short... " >&6; } +if ${ac_cv_sizeof_short+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_short" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (short) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_short=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 +$as_echo "$ac_cv_sizeof_short" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT $ac_cv_sizeof_short +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 +$as_echo_n "checking size of int... " >&6; } +if ${ac_cv_sizeof_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_int" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (int) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_int=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 +$as_echo "$ac_cv_sizeof_int" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5 +$as_echo_n "checking size of long long... " >&6; } +if ${ac_cv_sizeof_long_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5 +$as_echo "$ac_cv_sizeof_long_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of off_t" >&5 +$as_echo_n "checking size of off_t... " >&6; } +if ${ac_cv_sizeof_off_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (off_t))" "ac_cv_sizeof_off_t" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_off_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (off_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_off_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_off_t" >&5 +$as_echo "$ac_cv_sizeof_off_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_OFF_T $ac_cv_sizeof_off_t +_ACEOF + + +SIZEOF_SHORT=$ac_cv_sizeof_short +SIZEOF_INT=$ac_cv_sizeof_int +SIZEOF_LONG=$ac_cv_sizeof_long +SIZEOF_LONG_LONG=$ac_cv_sizeof_long_long +SIZEOF_OFF_T=$ac_cv_sizeof_off_t + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + +if test $cross_compiling = no; then + BUILD_CC="$BUILD_CC" CPP="$CPP" /bin/sh $ac_aux_dir/parse-types.sh +else + CROSS_COMPILE="1" BUILD_CC="$BUILD_CC" CPP="$CPP" /bin/sh $ac_aux_dir/parse-types.sh +fi +ASM_TYPES_HEADER=./asm_types.h + +echo "/* These defines are needed for the public ext2fs.h header file */" \ + > public_config.h +if grep HAVE_SYS_TYPES_H confdefs.h > tmp_config.$$; then + uniq tmp_config.$$ >> public_config.h +else + echo "#undef HAVE_SYS_TYPES_H" >> public_config.h +fi +if grep WORDS_BIGENDIAN confdefs.h > tmp_config.$$; then + uniq tmp_config.$$ >> public_config.h +else + echo "#undef WORDS_BIGENDIAN" >> public_config.h +fi +rm -f tmp_config.$$ +PUBLIC_CONFIG_HEADER=./public_config.h + +for ac_header in inttypes.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" +if test "x$ac_cv_header_inttypes_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_INTTYPES_H 1 +_ACEOF + +fi + +done + +ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default" +if test "x$ac_cv_type_intptr_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_INTPTR_T 1 +_ACEOF + + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct stat has a st_flags field" >&5 +$as_echo_n "checking whether struct stat has a st_flags field... " >&6; } +if ${e2fsprogs_cv_struct_st_flags+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +struct stat stat; stat.st_flags = 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + e2fsprogs_cv_struct_st_flags=yes +else + e2fsprogs_cv_struct_st_flags=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $e2fsprogs_cv_struct_st_flags" >&5 +$as_echo "$e2fsprogs_cv_struct_st_flags" >&6; } +if test "$e2fsprogs_cv_struct_st_flags" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether st_flags field is useful" >&5 +$as_echo_n "checking whether st_flags field is useful... " >&6; } + if ${e2fsprogs_cv_struct_st_flags_immut+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/stat.h> +int +main () +{ +struct stat stat; stat.st_flags |= UF_IMMUTABLE; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + e2fsprogs_cv_struct_st_flags_immut=yes +else + e2fsprogs_cv_struct_st_flags_immut=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $e2fsprogs_cv_struct_st_flags_immut" >&5 +$as_echo "$e2fsprogs_cv_struct_st_flags_immut" >&6; } + if test "$e2fsprogs_cv_struct_st_flags_immut" = yes; then + +$as_echo "#define HAVE_STAT_FLAGS 1" >>confdefs.h + + fi +fi +ac_fn_c_check_member "$LINENO" "struct sockaddr" "sa_len" "ac_cv_member_struct_sockaddr_sa_len" "#include <sys/types.h> + #include <sys/socket.h> +" +if test "x$ac_cv_member_struct_sockaddr_sa_len" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_SA_LEN 1 +_ACEOF + +fi + +if test -n "$BLKID_CMT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing blkid_probe_all" >&5 +$as_echo_n "checking for library containing blkid_probe_all... " >&6; } +if ${ac_cv_search_blkid_probe_all+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char blkid_probe_all (); +int +main () +{ +return blkid_probe_all (); + ; + return 0; +} +_ACEOF +for ac_lib in '' blkid; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_blkid_probe_all=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_blkid_probe_all+:} false; then : + break +fi +done +if ${ac_cv_search_blkid_probe_all+:} false; then : + +else + ac_cv_search_blkid_probe_all=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_blkid_probe_all" >&5 +$as_echo "$ac_cv_search_blkid_probe_all" >&6; } +ac_res=$ac_cv_search_blkid_probe_all +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi +for ac_func in __secure_getenv backtrace blkid_probe_get_topology blkid_probe_enable_partitions chflags fadvise64 fallocate fallocate64 fchown fdatasync fstat64 ftruncate64 futimes getcwd getdtablesize getmntinfo getpwuid_r getrlimit getrusage jrand48 llseek lseek64 mallinfo mbstowcs memalign mempcpy mmap msync nanosleep open64 pathconf posix_fadvise posix_fadvise64 posix_memalign prctl pread pwrite pread64 pwrite64 secure_getenv setmntent setresgid setresuid snprintf srandom stpcpy strcasecmp strdup strnlen strptime strtoull sync_file_range sysconf usleep utime utimes valloc +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +SOCKET_LIB='' +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 +$as_echo_n "checking for socket in -lsocket... " >&6; } +if ${ac_cv_lib_socket_socket+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char socket (); +int +main () +{ +return socket (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_socket=yes +else + ac_cv_lib_socket_socket=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 +$as_echo "$ac_cv_lib_socket_socket" >&6; } +if test "x$ac_cv_lib_socket_socket" = xyes; then : + SOCKET_LIB=-lsocket +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for optreset" >&5 +$as_echo_n "checking for optreset... " >&6; } +if ${ac_cv_have_optreset+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <unistd.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "optreset" >/dev/null 2>&1; then : + ac_cv_have_optreset=yes +else + ac_cv_have_optreset=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_optreset" >&5 +$as_echo "$ac_cv_have_optreset" >&6; } +if test $ac_cv_have_optreset = yes; then + +$as_echo "#define HAVE_OPTRESET 1" >>confdefs.h + +fi + +SEM_INIT_LIB='' +ac_fn_c_check_func "$LINENO" "sem_init" "ac_cv_func_sem_init" +if test "x$ac_cv_func_sem_init" = xyes; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sem_init in -lpthread" >&5 +$as_echo_n "checking for sem_init in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_sem_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sem_init (); +int +main () +{ +return sem_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_sem_init=yes +else + ac_cv_lib_pthread_sem_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_sem_init" >&5 +$as_echo "$ac_cv_lib_pthread_sem_init" >&6; } +if test "x$ac_cv_lib_pthread_sem_init" = xyes; then : + $as_echo "#define HAVE_SEM_INIT 1" >>confdefs.h + + SEM_INIT_LIB=-lpthread +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sem_init in -lrt" >&5 +$as_echo_n "checking for sem_init in -lrt... " >&6; } +if ${ac_cv_lib_rt_sem_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sem_init (); +int +main () +{ +return sem_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_sem_init=yes +else + ac_cv_lib_rt_sem_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_sem_init" >&5 +$as_echo "$ac_cv_lib_rt_sem_init" >&6; } +if test "x$ac_cv_lib_rt_sem_init" = xyes; then : + $as_echo "#define HAVE_SEM_INIT 1" >>confdefs.h + + SEM_INIT_LIB=-lrt +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sem_init in -lposix4" >&5 +$as_echo_n "checking for sem_init in -lposix4... " >&6; } +if ${ac_cv_lib_posix4_sem_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lposix4 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sem_init (); +int +main () +{ +return sem_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_posix4_sem_init=yes +else + ac_cv_lib_posix4_sem_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix4_sem_init" >&5 +$as_echo "$ac_cv_lib_posix4_sem_init" >&6; } +if test "x$ac_cv_lib_posix4_sem_init" = xyes; then : + $as_echo "#define HAVE_SEM_INIT 1" >>confdefs.h + + SEM_INIT_LIB=-lposix4 +fi + +fi + +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for unified diff option" >&5 +$as_echo_n "checking for unified diff option... " >&6; } +if diff -u $0 $0 > /dev/null 2>&1 ; then + UNI_DIFF_OPTS=-u +else + UNI_DIFF_OPTS=-c +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $UNI_DIFF_OPTS" >&5 +$as_echo "$UNI_DIFF_OPTS" >&6; } + +case "$host_os" in +linux*) + +$as_echo "#define HAVE_EXT2_IOCTLS 1" >>confdefs.h + + ;; +esac +LINUX_CMT="#" +CYGWIN_CMT="#" +UNIX_CMT= +case "$host_os" in +linux*) + LINUX_CMT= + ;; +cygwin) + CYGWIN_CMT= + UNIX_CMT="#" + ;; +esac + + + +case "$host_os" in +linux* | gnu* | k*bsd*-gnu) + if test "$prefix" = NONE -a "$root_prefix" = NONE ; then + root_prefix=""; + { $as_echo "$as_me:${as_lineno-$LINENO}: result: On $host_os systems, root_prefix defaults to ''" >&5 +$as_echo "On $host_os systems, root_prefix defaults to ''" >&6; } + fi + ;; +esac +case "$host_os" in +linux* | gnu* | k*bsd*-gnu) + if test "$prefix" = NONE ; then + prefix="/usr"; + { $as_echo "$as_me:${as_lineno-$LINENO}: result: On $host_os systems, prefix defaults to /usr" >&5 +$as_echo "On $host_os systems, prefix defaults to /usr" >&6; } + if test "$mandir" = '${prefix}/man' ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ...and mandir defaults to /usr/share/man" >&5 +$as_echo "...and mandir defaults to /usr/share/man" >&6; } + mandir=/usr/share/man + fi + fi +;; +esac +if test "$root_prefix" = NONE ; then + if test "$prefix" = NONE ; then + root_prefix="$ac_default_prefix" + else + root_prefix="$prefix" + fi + root_bindir=$bindir + root_sbindir=$sbindir + root_libdir=$libdir + root_sysconfdir=$sysconfdir +else + root_bindir='${root_prefix}/bin' + root_sbindir='${root_prefix}/sbin' + root_libdir='${root_prefix}/lib' + root_sysconfdir='${root_prefix}/etc' +fi +if test "$bindir" != '${exec_prefix}/bin'; then + root_bindir=$bindir + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Setting root_bindir to $root_bindir" >&5 +$as_echo "Setting root_bindir to $root_bindir" >&6; } +fi +if test "$sbindir" != '${exec_prefix}/sbin'; then + root_sbindir=$sbindir + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Setting root_sbindir to $root_sbindir" >&5 +$as_echo "Setting root_sbindir to $root_sbindir" >&6; } +fi +if test "$libdir" != '${exec_prefix}/lib'; then + root_libdir=$libdir + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Setting root_libdir to $root_libdir" >&5 +$as_echo "Setting root_libdir to $root_libdir" >&6; } +fi +if test "$sysconfdir" != '${prefix}/etc'; then + root_sysconfdir=$sysconfdir + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Setting root_sysconfdir to $root_sysconfdir" >&5 +$as_echo "Setting root_sysconfdir to $root_sysconfdir" >&6; } +fi + + + + + + +# Check whether --with-multiarch was given. +if test "${with_multiarch+set}" = set; then : + withval=$with_multiarch; if test "$withval" = "lib64"; then + libdir=/usr/lib64 + root_libdir=/lib64 +else + libdir=$libdir/$withval + root_libdir=$root_libdir/$withval +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can link with -static" >&5 +$as_echo_n "checking whether we can link with -static... " >&6; } +if ${ac_cv_e2fsprogs_use_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + SAVE_LDFLAGS=$LDFLAGS; LDFLAGS="$LDFLAGS -static" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdio.h> +int +main () +{ +fflush(stdout); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_e2fsprogs_use_static=yes +else + ac_cv_e2fsprogs_use_static=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LDFLAGS=$SAVE_LDFLAGS +fi + +case "$host_os" in +solaris2.*) + ac_cv_e2fsprogs_use_static=no +;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_e2fsprogs_use_static" >&5 +$as_echo "$ac_cv_e2fsprogs_use_static" >&6; } +LDFLAG_STATIC= +if test $ac_cv_e2fsprogs_use_static = yes; then + LDFLAG_STATIC=-static +fi + +case "$host_os" in +darwin*) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using Apple Darwin / GNU libintl workaround" >&5 +$as_echo "Using Apple Darwin / GNU libintl workaround" >&6; } + +$as_echo "#define _INTL_REDIRECT_MACROS 1" >>confdefs.h + + ;; +esac +SS_DIR=`cd ${srcdir}/lib/ss; pwd` +ET_DIR=`cd ${srcdir}/lib/et; pwd` + + +if test "$cross_compiling" = yes ; then + DO_TEST_SUITE= +else + DO_TEST_SUITE=check +fi + +INCLUDES='-I. -I$(top_builddir)/lib -I$(top_srcdir)/lib' +if test -n "$CPPFLAGS" ; then + INCLUDES="$INCLUDES $CPPFLAGS" +fi +if test "$USE_INCLUDED_LIBINTL" = "yes" ; then + INCLUDES=$INCLUDES' -I$(top_builddir)/intl -I$(top_srcdir)/intl' +fi +if test -n "$WITH_DIET_LIBC" ; then + INCLUDES="$INCLUDES -D_REENTRANT" +fi + + + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + case "$ac_aux_dir" in + /*) MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" ;; + *) MKINSTALLDIRS="\$(top_builddir)/$ac_aux_dir/mkinstalldirs" ;; + esac + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + + +if test $cross_compiling = no; then + BUILD_CFLAGS="$CFLAGS $CPPFLAGS $INCLUDES -DHAVE_CONFIG_H" + BUILD_LDFLAGS="$LDFLAGS" +fi + + +test -d lib || mkdir lib +test -d include || mkdir include +test -d include/linux || mkdir include/linux +test -d include/asm || mkdir include/asm +for i in MCONFIG Makefile e2fsprogs.spec \ + util/Makefile util/subst.conf util/gen-tarball util/install-symlink \ + lib/et/Makefile lib/ss/Makefile lib/e2p/Makefile \ + lib/ext2fs/Makefile lib/ext2fs/ext2_types.h \ + lib/uuid/Makefile lib/uuid/uuid_types.h \ + lib/blkid/Makefile lib/blkid/blkid_types.h lib/quota/Makefile \ + lib/ss/ss.pc lib/uuid/uuid.pc lib/et/com_err.pc \ + lib/e2p/e2p.pc lib/blkid/blkid.pc lib/ext2fs/ext2fs.pc \ + misc/Makefile ext2ed/Makefile e2fsck/Makefile \ + debugfs/Makefile tests/Makefile tests/progs/Makefile \ + resize/Makefile doc/Makefile intl/Makefile \ + intl/libgnuintl.h po/Makefile.in ; do + if test -d `dirname ${srcdir}/$i` ; then + outlist="$outlist $i" + fi +done +ac_config_files="$ac_config_files $outlist" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +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.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +# Capture the value of obsolete ALL_LINGUAS because we need it to compute + # POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES, CATALOGS. But hide it + # from automake < 1.5. + eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"' + # Capture the value of LINGUAS because we need it to compute CATALOGS. + LINGUAS="${LINGUAS-%UNSET%}" + + +_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 + "lib/config.h") CONFIG_HEADERS="$CONFIG_HEADERS lib/config.h" ;; + "po-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS po-directories" ;; + "$outlist") CONFIG_FILES="$CONFIG_FILES $outlist" ;; + + *) 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= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + +if $AWK 'BEGIN { getline <"/dev/null" }' </dev/null 2>/dev/null; then + ac_cs_awk_getline=: + ac_cs_awk_pipe_init= + ac_cs_awk_read_file=' + while ((getline aline < (F[key])) > 0) + print(aline) + close(F[key])' + ac_cs_awk_pipe_fini= +else + ac_cs_awk_getline=false + ac_cs_awk_pipe_init="print \"cat <<'|#_!!_#|' &&\"" + ac_cs_awk_read_file=' + print "|#_!!_#|" + print "cat " F[key] " &&" + '$ac_cs_awk_pipe_init + # The final `:' finishes the AND list. + ac_cs_awk_pipe_fini='END { print "|#_!!_#|"; print ":" }' +fi +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 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + +# Create commands to substitute file output variables. +{ + echo "cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1" && + echo 'cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&' && + echo "$ac_subst_files" | sed 's/.*/F["&"]="$&"/' && + echo "_ACAWK" && + echo "_ACEOF" +} >conf$$files.sh && +. ./conf$$files.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +rm -f conf$$files.sh + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + \$ac_cs_awk_pipe_init +} +{ + 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 + } + if (nfields == 3 && !substed) { + key = field[2] + if (F[key] != "" && line ~ /^[ ]*@.*@[ ]*$/) { + \$ac_cs_awk_read_file + next + } + } + print line +} +\$ac_cs_awk_pipe_fini +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' <confdefs.h | sed ' +s/'"$ac_delim"'/"\\\ +"/g' >>$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="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | +if $ac_cs_awk_getline; then + $AWK -f "$ac_tmp/subs.awk" +else + $AWK -f "$ac_tmp/subs.awk" | $SHELL +fi \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + :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 + "po-directories":C) + for ac_file in $CONFIG_FILES; do + # Support "outfile[:infile[:infile...]]" + case "$ac_file" in + *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + esac + # PO directories have a Makefile.in generated from Makefile.in.in. + case "$ac_file" in */Makefile.in) + # Adjust a relative srcdir. + ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'` + ac_dir_suffix=/`echo "$ac_dir"|sed 's%^\./%%'` + ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'` + # In autoconf-2.13 it is called $ac_given_srcdir. + # In autoconf-2.50 it is called $srcdir. + test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir" + case "$ac_given_srcdir" in + .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;; + /*) top_srcdir="$ac_given_srcdir" ;; + *) top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + # Treat a directory as a PO directory if and only if it has a + # POTFILES.in file. This allows packages to have multiple PO + # directories under different names or in different locations. + if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then + rm -f "$ac_dir/POTFILES" + test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES" + gt_tab=`printf '\t'` + cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ${gt_tab}]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES" + POMAKEFILEDEPS="POTFILES.in" + # ALL_LINGUAS, POFILES, UPDATEPOFILES, DUMMYPOFILES, GMOFILES depend + # on $ac_dir but don't depend on user-specified configuration + # parameters. + if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then + # The LINGUAS file contains the set of available languages. + if test -n "$OBSOLETE_ALL_LINGUAS"; then + test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete" + fi + ALL_LINGUAS_=`sed -e "/^#/d" -e "s/#.*//" "$ac_given_srcdir/$ac_dir/LINGUAS"` + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$ALL_LINGUAS_' + POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS" + else + # The set of available languages was given in configure.in. + # Hide the ALL_LINGUAS assignment from automake < 1.5. + eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS' + fi + # Compute POFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).po) + # Compute UPDATEPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).po-update) + # Compute DUMMYPOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(lang).nop) + # Compute GMOFILES + # as $(foreach lang, $(ALL_LINGUAS), $(srcdir)/$(lang).gmo) + case "$ac_given_srcdir" in + .) srcdirpre= ;; + *) srcdirpre='$(srcdir)/' ;; + esac + POFILES= + UPDATEPOFILES= + DUMMYPOFILES= + GMOFILES= + for lang in $ALL_LINGUAS; do + POFILES="$POFILES $srcdirpre$lang.po" + UPDATEPOFILES="$UPDATEPOFILES $lang.po-update" + DUMMYPOFILES="$DUMMYPOFILES $lang.nop" + GMOFILES="$GMOFILES $srcdirpre$lang.gmo" + done + # CATALOGS depends on both $ac_dir and the user's LINGUAS + # environment variable. + INST_LINGUAS= + if test -n "$ALL_LINGUAS"; then + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "$LINGUAS"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + INST_LINGUAS="$INST_LINGUAS $presentlang" + fi + done + fi + CATALOGS= + if test -n "$INST_LINGUAS"; then + for lang in $INST_LINGUAS; do + CATALOGS="$CATALOGS $lang.gmo" + done + fi + test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile" + sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile" + for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do + if test -f "$f"; then + case "$f" in + *.orig | *.bak | *~) ;; + *) cat "$f" >> "$ac_dir/Makefile" ;; + esac + fi + done + fi + ;; + esac + 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 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + +if test -f util/gen-tarball; then chmod +x util/gen-tarball; fi
diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..0146bfe --- /dev/null +++ b/configure.in
@@ -0,0 +1,1346 @@ +AC_INIT(version.h) +AC_PREREQ(2.54) +AC_CONFIG_AUX_DIR(config) +AC_CONFIG_HEADERS([lib/config.h]) +AH_BOTTOM([#include <dirpaths.h>]) +MCONFIG=./MCONFIG +AC_SUBST_FILE(MCONFIG) +BINARY_TYPE=bin +dnl +dnl This is to figure out the version number and the date.... +dnl +E2FSPROGS_VERSION=`grep E2FSPROGS_VERSION ${srcdir}/version.h \ + | awk '{print $3}' | tr \" " " | awk '{print $1}'` +DATE=`grep E2FSPROGS_DATE ${srcdir}/version.h | awk '{print $3}' \ + | tr \" " "` +E2FSPROGS_DAY=`echo $DATE | awk -F- '{print $1}'` +MONTH=`echo $DATE | awk -F- '{print $2}'` +YEAR=`echo $DATE | awk -F- '{print $3}'` + +if expr $YEAR ">" 1900 > /dev/null ; then + E2FSPROGS_YEAR=$YEAR +elif expr $YEAR ">" 90 >/dev/null ; then + E2FSPROGS_YEAR=19$YEAR +else + E2FSPROGS_YEAR=20$YEAR +fi + +case $MONTH in +Jan) MONTH_NUM=01; E2FSPROGS_MONTH="January" ;; +Feb) MONTH_NUM=02; E2FSPROGS_MONTH="February" ;; +Mar) MONTH_NUM=03; E2FSPROGS_MONTH="March" ;; +Apr) MONTH_NUM=04; E2FSPROGS_MONTH="April" ;; +May) MONTH_NUM=05; E2FSPROGS_MONTH="May" ;; +Jun) MONTH_NUM=06; E2FSPROGS_MONTH="June" ;; +Jul) MONTH_NUM=07; E2FSPROGS_MONTH="July" ;; +Aug) MONTH_NUM=08; E2FSPROGS_MONTH="August" ;; +Sep) MONTH_NUM=09; E2FSPROGS_MONTH="September" ;; +Oct) MONTH_NUM=10; E2FSPROGS_MONTH="October" ;; +Nov) MONTH_NUM=11; E2FSPROGS_MONTH="November" ;; +Dec) MONTH_NUM=12; E2FSPROGS_MONTH="December" ;; +*) AC_MSG_WARN([Unknown month $MONTH??]) ;; +esac + +base_ver=`echo $E2FSPROGS_VERSION | \ + sed -e 's/-WIP//' -e 's/pre-//' -e 's/-PLUS//'` + +date_spec=${E2FSPROGS_YEAR}.${MONTH_NUM}.${E2FSPROGS_DAY} + +case $E2FSPROGS_VERSION in +*-WIP|pre-*) + E2FSPROGS_PKGVER="$base_ver~WIP-$E2FSPROGS_YEAR-$MONTH_NUM-$E2FSPROGS_DAY" + ;; +*) + E2FSPROGS_PKGVER="$base_ver" + ;; +esac + +unset DATE MONTH YEAR base_ver pre_vers date_spec +AC_MSG_RESULT([Generating configuration file for e2fsprogs version $E2FSPROGS_VERSION]) +AC_MSG_RESULT([Release date is ${E2FSPROGS_MONTH}, ${E2FSPROGS_YEAR}]) +AC_SUBST(E2FSPROGS_YEAR) +AC_SUBST(E2FSPROGS_MONTH) +AC_SUBST(E2FSPROGS_DAY) +AC_SUBST(E2FSPROGS_VERSION) +AC_SUBST(E2FSPROGS_PKGVER) +dnl +dnl Use diet libc +dnl +WITH_DIET_LIBC= +AC_ARG_WITH([diet-libc], +[ --with-diet-libc use diet libc], +CC="diet cc -nostdinc" +WITH_DIET_LIBC=yes +if test -z "$LIBS" +then + LIBS="-lcompat" +else + LIBS="$LIBS -lcompat" +fi +AC_MSG_RESULT(CC=$CC))dnl +dnl +AC_CANONICAL_HOST +dnl +dnl Check to see if libdl exists for the sake of dlopen +dnl +DLOPEN_LIB='' +AC_CHECK_LIB(dl, dlopen, +[DLOPEN_LIB=-ldl +AC_DEFINE(HAVE_DLOPEN, 1, [Define to 1 if dlopen/libdl exists])]) +AC_SUBST(DLOPEN_LIB) +dnl +AC_ARG_WITH([cc], +AC_HELP_STRING([--with-cc],[no longer supported, use CC= instead]), +AC_MSG_ERROR([--with-cc no longer supported; use CC= instead])) +dnl +AC_ARG_WITH([ccopts], +AC_HELP_STRING([--with-ccopts],[no longer supported, use CFLAGS= instead]), +AC_MSG_ERROR([--with-ccopts no longer supported; use CFLAGS= instead])) +dnl +AC_ARG_WITH([ldopts], +AC_HELP_STRING([--with-ldopts],[no longer supported, use LDFLAGS= instead]), +AC_MSG_ERROR([--with-ldopts no longer supported; use LDFLAGS= instead])) +dnl +AC_PROG_CC +if test "$GCC" = yes; then + RDYNAMIC="-rdynamic" + AC_SUBST(RDYNAMIC) +fi +AC_PROG_CPP +dnl +dnl Alpha computers use fast and imprecise floating point code that may +dnl miss exceptions by default. Force sane options if we're using GCC. +AC_MSG_CHECKING(for additional special compiler flags) +if test "$GCC" = yes +then + case "$host_cpu" in + alpha) addcflags="-mieee" ;; + esac +fi +if test "x$addcflags" != x +then + AC_MSG_RESULT($addcflags) + CFLAGS="$addcflags $CFLAGS" +else + AC_MSG_RESULT([[(none)]]) +fi +AC_USE_SYSTEM_EXTENSIONS +dnl +dnl Set default values for library extentions. Will be dealt with after +dnl parsing configuration opions, which may modify these +dnl +LIB_EXT=.a +STATIC_LIB_EXT=.a +PROFILED_LIB_EXT=.a +dnl +dnl Allow separate `root_prefix' to be specified +dnl +AC_ARG_WITH([root-prefix], +[ --with-root-prefix=PREFIX override prefix variable for files to be placed in the root], +root_prefix=$withval, +root_prefix=NONE)dnl +dnl +dnl handle --enable-maintainer-mode +dnl +AC_ARG_ENABLE([maintainer-mode], +[ --enable-maintainer-mode enable makefile rules useful for maintainers], +if test "$enableval" = "no" +then + MAINTAINER_CMT=# + AC_MSG_RESULT([Disabling maintainer mode]) +else + MAINTAINER_CMT= + AC_MSG_RESULT([Enabling maintainer mode]) +fi +, +MAINTAINER_CMT=# +AC_MSG_RESULT([Disabling maintainer mode by default]) +) +AC_SUBST(MAINTAINER_CMT) +dnl +dnl handle --enable-symlink-install +dnl +AC_ARG_ENABLE([symlink-install], +[ --enable-symlink-install use symlinks when installing instead of hard links], +if test "$enableval" = "no" +then + LINK_INSTALL_FLAGS=-f + AC_MSG_RESULT([Disabling symlinks for install]) +else + LINK_INSTALL_FLAGS=-sf + AC_MSG_RESULT([Enabling symlinks for install]) +fi +, +LINK_INSTALL_FLAGS=-f +AC_MSG_RESULT([Disabling symlinks for install by default]) +) +AC_SUBST(LINK_INSTALL_FLAGS) +dnl +dnl handle --enable-relative-symlinks +dnl +relative_symlink_defined= +AC_ARG_ENABLE([relative-symlinks], +[ --enable-relative-symlinks use relative symlinks when installing], +if test "$enableval" = "no" +then + SYMLINK_RELATIVE= + relative_symlink_defined=yes + AC_MSG_RESULT([Disabling relative symlinks for install]) +else + SYMLINK_RELATIVE=--relative + relative_symlink_defined=yes + AC_MSG_RESULT([Enabling relative symlinks for install]) +fi) +AC_ARG_ENABLE([symlink-relative-symlinks],, +if test "$enableval" = "no" +then + SYMLINK_RELATIVE=yes + AC_MSG_RESULT([Disabling relative symlinks for install]) +else + SYMLINK_RELATIVE=--relative + AC_MSG_RESULT([Enabling relative symlinks for install]) +fi +, +if test -z "$relative_symlink_defined" +then + SYMLINK_RELATIVE= +AC_MSG_RESULT([Disabling relative symlinks for install by default]) +fi +) +AC_SUBST(SYMLINK_RELATIVE) +dnl +dnl handle --enable-symlink-build +dnl +AC_ARG_ENABLE([symlink-build], +[ --enable-symlink-build use symlinks while building instead of hard links], +if test "$enableval" = "no" +then + LINK_BUILD_FLAGS= + AC_MSG_RESULT([Disabling symlinks for build]) +else + LINK_BUILD_FLAGS=-s + AC_MSG_RESULT([Enabling symlinks for build]) +fi +, +LINK_BUILD_FLAGS= +AC_MSG_RESULT([Disabling symlinks for build by default]) +) +AC_SUBST(LINK_BUILD_FLAGS) +dnl +dnl handle --enable-verbose-makecmds +dnl +AC_ARG_ENABLE([verbose-makecmds], +[ --enable-verbose-makecmds enable verbose make command output], +if test "$enableval" = "no" +then + AC_MSG_RESULT([Disabling verbose make commands]) + E=@echo + ES=echo + Q=@ +else + AC_MSG_RESULT([Enabling verbose make commands]) + E=@\\# + ES=\\# + Q= +fi +, +AC_MSG_RESULT([Disabling verbose make commands]) +E=@echo +ES=echo +Q=@ +) +AC_SUBST(E) +AC_SUBST(ES) +AC_SUBST(Q) +dnl +dnl handle --enable-compression +dnl +AC_ARG_ENABLE([compression], +[ --enable-compression enable EXPERIMENTAL compression support], +if test "$enableval" = "no" +then + AC_MSG_RESULT([Disabling compression support]) +else + AC_DEFINE(ENABLE_COMPRESSION, 1, + [Define to 1 if ext2 compression enabled]) + AC_MSG_RESULT([Enabling compression support]) + AC_MSG_WARN([Compression support is experimental]) +fi +, +AC_MSG_RESULT([Disabling compression support by default]) +) +dnl +dnl handle --enable-htree +dnl +AH_TEMPLATE([ENABLE_HTREE], [Define to 1 if ext3/4 htree support enabled]) +AC_ARG_ENABLE([htree], +[ --enable-htree enable EXPERIMENTAL htree directory support], +if test "$enableval" = "no" +then + HTREE_CMT=# + AC_MSG_RESULT([Disabling htree directory support]) +else + HTREE_CMT= + AC_DEFINE(ENABLE_HTREE, 1) + AC_MSG_RESULT([Enabling htree directory support]) +fi +, +HTREE_CMT= +AC_DEFINE(ENABLE_HTREE, 1) +AC_MSG_RESULT([Enabling htree directory support by default]) +) +AC_SUBST(HTREE_CMT) +dnl +dnl This needs to be before all of the --enable-*-shlibs options +dnl +E2_PKG_CONFIG_STATIC=--static +LDFLAG_DYNAMIC= +PRIVATE_LIBS_CMT= +dnl +dnl handle --enable-elf-shlibs +dnl +AC_ARG_ENABLE([elf-shlibs], +[ --enable-elf-shlibs select ELF shared libraries], +if test "$enableval" = "no" +then + ELF_CMT=# + MAKEFILE_ELF=/dev/null + AC_MSG_RESULT([Disabling ELF shared libraries]) +else + E2_PKG_CONFIG_STATIC= + ELF_CMT= + MAKEFILE_ELF=$srcdir/lib/Makefile.elf-lib + [case "$host_os" in + solaris2.*) + MAKEFILE_ELF=$srcdir/lib/Makefile.solaris-lib + ;; + esac] + BINARY_TYPE=elfbin + LIB_EXT=.so + PRIVATE_LIBS_CMT=# + LDFLAG_DYNAMIC=['-Wl,-rpath-link,$(top_builddir)/lib'] + AC_MSG_RESULT([Enabling ELF shared libraries]) +fi +, +MAKEFILE_ELF=/dev/null +ELF_CMT=# +AC_MSG_RESULT([Disabling ELF shared libraries by default]) +) +AC_SUBST(ELF_CMT) +AC_SUBST_FILE(MAKEFILE_ELF) +dnl +dnl handle --enable-bsd-shlibs +dnl +AC_ARG_ENABLE([bsd-shlibs], +[ --enable-bsd-shlibs select BSD shared libraries], +if test "$enableval" = "no" +then + BSDLIB_CMT=# + MAKEFILE_BSDLIB=/dev/null + AC_MSG_RESULT([Disabling BSD shared libraries]) +else + E2_PKG_CONFIG_STATIC= + BSDLIB_CMT= + MAKEFILE_BSDLIB=$srcdir/lib/Makefile.bsd-lib + LIB_EXT=.so + [case "$host_os" in + darwin*) + MAKEFILE_BSDLIB=$srcdir/lib/Makefile.darwin-lib + LIB_EXT=.dylib + ;; + esac] + AC_MSG_RESULT([Enabling BSD shared libraries]) +fi +, +MAKEFILE_BSDLIB=/dev/null +BSDLIB_CMT=# +AC_MSG_RESULT([Disabling BSD shared libraries by default]) +) +AC_SUBST(BSDLIB_CMT) +AC_SUBST_FILE(MAKEFILE_BSDLIB) +dnl +dnl handle --enable-profile +dnl +AC_ARG_ENABLE([profile], +[ --enable-profile build profiling libraries], +if test "$enableval" = "no" +then + PROFILE_CMT=# + MAKEFILE_PROFILE=/dev/null + AC_MSG_RESULT([Disabling profiling libraries]) +else + PROFILE_CMT= + MAKEFILE_PROFILE=$srcdir/lib/Makefile.profile + PROFILED_LIB_EXT=_p.a + AC_MSG_RESULT([Building profiling libraries]) +fi +, +PROFILE_CMT=# +MAKEFILE_PROFILE=/dev/null +AC_MSG_RESULT([Disabling profiling libraries by default]) +) +AC_SUBST(PROFILE_CMT) +AC_SUBST_FILE(MAKEFILE_PROFILE) +dnl +dnl handle --enable-gcov +dnl +AC_ARG_ENABLE([gcov], +[ --enable-gcov build for coverage testing using gcov], +if test "$enableval" = "yes" +then + CFLAGS="-g -fprofile-arcs -ftest-coverage" + LDFLAGS="-fprofile-arcs -ftest-coverage" + AC_MSG_RESULT([Enabling gcov support]) +fi +) + +dnl +dnl Substitute library extensions +dnl +AC_SUBST(LIB_EXT) +AC_SUBST(STATIC_LIB_EXT) +AC_SUBST(PROFILED_LIB_EXT) +AC_SUBST(LDFLAG_DYNAMIC) +AC_SUBST(PRIVATE_LIBS_CMT) +dnl +dnl handle --enable-jbd-debug +dnl +AC_ARG_ENABLE([jbd-debug], +[ --enable-jbd-debug enable journal debugging], +if test "$enableval" = "no" +then + AC_MSG_RESULT([Disabling journal debugging]) +else + AC_DEFINE(CONFIG_JBD_DEBUG, 1, + [Define to 1 if debugging ext3/4 journal code]) + AC_MSG_RESULT([Enabling journal debugging]) +fi +, +AC_MSG_RESULT([Disabling journal debugging by default]) +) +dnl +dnl handle --enable-blkid-debug +dnl +AC_ARG_ENABLE([blkid-debug], +[ --enable-blkid-debug enable blkid debugging], +if test "$enableval" = "no" +then + AC_MSG_RESULT([Disabling blkid debugging]) +else + AC_DEFINE(CONFIG_BLKID_DEBUG, 1, + [Define to 1 if debugging the blkid library]) + AC_MSG_RESULT([Enabling blkid debugging]) +fi +, +AC_MSG_RESULT([Disabling blkid debugging by default]) +) +dnl +dnl handle --enable-testio-debug +dnl +AC_ARG_ENABLE([testio-debug], +[ --disable-testio-debug disable the use of the test I/O manager for debugging], +AH_TEMPLATE([CONFIG_TESTIO_DEBUG], + [Define to 1 if the testio I/O manager should be enabled]) +if test "$enableval" = "no" +then + AC_MSG_RESULT([Disabling testio debugging]) + TEST_IO_CMT="#" +else + TEST_IO_CMT= + AC_DEFINE(CONFIG_TESTIO_DEBUG, 1) + AC_MSG_RESULT([Enabling testio debugging]) +fi +, +AC_MSG_RESULT([Enabling testio debugging by default]) +AC_DEFINE(CONFIG_TESTIO_DEBUG, 1) +TEST_IO_CMT= +) +AC_SUBST(TEST_IO_CMT) +dnl +dnl handle --disable-libuuid +dnl +PKG_PROG_PKG_CONFIG +LIBUUID= +DEPLIBUUID= +STATIC_LIBUUID= +DEPSTATIC_LIBUUID= +PROFILED_LIBUUID= +DEPPROFILED_LIBUUID= +UUID_CMT= +AC_ARG_ENABLE([libuuid], +[ --disable-libuuid do not build private uuid library], +if test "$enableval" = "no" +then + if test -z "$PKG_CONFIG"; then + AC_MSG_ERROR([pkg-config not installed; please install it.]) + fi + + AC_CHECK_LIB(uuid, uuid_generate, + [LIBUUID=`$PKG_CONFIG --libs uuid`; + STATIC_LIBUUID=`$PKG_CONFIG --static --libs uuid`], + [AC_MSG_ERROR([external uuid library not found])]) + PROFILED_LIBUUID=$LIBUUID + UUID_CMT=# + AC_MSG_RESULT([Disabling private uuid library]) +else + LIBUUID='$(LIB)/libuuid'$LIB_EXT + DEPLIBUUID=$LIBUUID + STATIC_LIBUUID='$(LIB)/libuuid'$STATIC_LIB_EXT + DEPSTATIC_LIBUUID=$STATIC_LIBUUID + PROFILED_LIBUUID='$(LIB)/libuuid'$PROFILED_LIB_EXT + DEPPROFILED_LIBUUID=$PROFILED_LIBUUID + AC_MSG_RESULT([Enabling private uuid library]) +fi +, +LIBUUID='$(LIB)/libuuid'$LIB_EXT +DEPLIBUUID=$LIBUUID +STATIC_LIBUUID='$(LIB)/libuuid'$STATIC_LIB_EXT +DEPSTATIC_LIBUUID=$STATIC_LIBUUID +PROFILED_LIBUUID='$(LIB)/libuuid'$PROFILED_LIB_EXT +DEPPROFILED_LIBUUID=$PROFILED_LIBUUID +AC_MSG_RESULT([Enabling private uuid library by default]) +) +AC_SUBST(LIBUUID) +AC_SUBST(DEPLIBUUID) +AC_SUBST(STATIC_LIBUUID) +AC_SUBST(DEPSTATIC_LIBUUID) +AC_SUBST(PROFILED_LIBUUID) +AC_SUBST(DEPPROFILED_LIBUUID) +AC_SUBST(UUID_CMT) +dnl +dnl handle --disable-libblkid +dnl +PKG_PROG_PKG_CONFIG +LIBBLKID= +DEPLIBBLKID= +STATIC_LIBBLKID= +DEPSTATIC_LIBBLKID= +PROFILED_LIBBLKID= +DEPPROFILED_LIBBLKID= +BLKID_CMT= +AH_TEMPLATE([CONFIG_BUILD_FINDFS], [Define to 1 to compile findfs]) +AC_ARG_ENABLE([libblkid], +[ --disable-libblkid do not build private blkid library], +if test "$enableval" = "no" +then + if test -z "$PKG_CONFIG"; then + AC_MSG_ERROR([pkg-config not installed; please install it.]) + fi + + AC_CHECK_LIB(blkid, blkid_get_cache, + [LIBBLKID=`$PKG_CONFIG --libs blkid`; + STATIC_LIBBLKID=`$PKG_CONFIG --static --libs blkid`], + [AC_MSG_ERROR([external blkid library not found])], -luuid) + BLKID_CMT=# + PROFILED_LIBBLKID=$LIBBLKID + AC_MSG_RESULT([Disabling private blkid library]) +else + LIBBLKID='$(LIB)/libblkid'$LIB_EXT + DEPLIBBLKID=$LIBBLKID + STATIC_LIBBLKID='$(LIB)/libblkid'$STATIC_LIB_EXT + DEPSTATIC_LIBBLKID=$STATIC_LIBBLKID + PROFILED_LIBBLKID='$(LIB)/libblkid'$PROFILED_LIB_EXT + DEPPROFILED_LIBBLKID=$PROFILED_LIBBLKID + AC_DEFINE(CONFIG_BUILD_FINDFS, 1) + AC_MSG_RESULT([Enabling private blkid library]) +fi +, +LIBBLKID='$(LIB)/libblkid'$LIB_EXT +DEPLIBBLKID=$LIBBLKID +STATIC_LIBBLKID='$(LIB)/libblkid'$STATIC_LIB_EXT +DEPSTATIC_LIBBLKID=$STATIC_LIBBLKID +PROFILED_LIBBLKID='$(LIB)/libblkid'$PROFILED_LIB_EXT +DEPPROFILED_LIBBLKID=$PROFILED_LIBBLKID +AC_DEFINE(CONFIG_BUILD_FINDFS, 1) +AC_MSG_RESULT([Enabling private blkid library by default]) +) +AC_SUBST(LIBBLKID) +AC_SUBST(DEPLIBBLKID) +AC_SUBST(STATIC_LIBBLKID) +AC_SUBST(DEPSTATIC_LIBBLKID) +AC_SUBST(PROFILED_LIBBLKID) +AC_SUBST(DEPPROFILED_LIBBLKID) +AC_SUBST(BLKID_CMT) +dnl +dnl handle --enable-quota +dnl +QUOTA_MAN_COMMENT='.\"' +QUOTA_CMT= +AC_SUBST(QUOTA_MAN_COMMENT) +PKG_PROG_PKG_CONFIG +AH_TEMPLATE([CONFIG_QUOTA], [Define to 1 to enable quota support]) +AC_ARG_ENABLE([quota], +[ --enable-quota enable quota support], +if test "$enableval" = "no" +then + QUOTA_CMT=# + AC_MSG_RESULT([Disabling quota support]) +else + QUOTA_CMT= + AC_DEFINE(CONFIG_QUOTA, 1) + AC_MSG_RESULT([Enabling quota support]) + QUOTA_MAN_COMMENT="" + AC_SUBST(QUOTA_MAN_COMMENT) +fi +, +QUOTA_CMT=# +AC_MSG_RESULT([Disabling quota support by default]) +) +dnl +dnl Define stuff expected for quota library +dnl +LIBQUOTA='$(LIB)/libquota'$LIB_EXT +DEPLIBQUOTA=$LIBQUOTA +STATIC_LIBQUOTA='$(LIB)/libquota'$STATIC_LIB_EXT +DEPSTATIC_LIBQUOTA=$STATIC_LIBQUOTA +PROFILED_LIBQUOTA='$(LIB)/libquota'$PROFILED_LIB_EXT +DEPPROFILED_LIBQUOTA=$PROFILED_LIBQUOTA +AC_SUBST(LIBQUOTA) +AC_SUBST(DEPLIBQUOTA) +AC_SUBST(STATIC_LIBQUOTA) +AC_SUBST(DEPSTATIC_LIBQUOTA) +AC_SUBST(PROFILED_LIBQUOTA) +AC_SUBST(DEPPROFILED_LIBQUOTA) +AC_SUBST(QUOTA_CMT) +dnl +dnl handle --disable-backtrace +dnl +AH_TEMPLATE([DISABLE_BACKTRACE], [Define to 1 to disable use of backtrace]) +AC_ARG_ENABLE([backtrace], +[ --disable-backtrace disable use backtrace], +if test "$enableval" = "no" +then + AC_MSG_RESULT([Disabling use of backtrace]) + AC_DEFINE(DISABLE_BACKTRACE, 1) +else + AC_MSG_RESULT([Enabling use of backtrace]) +fi +, +AC_MSG_RESULT([Enabling use of backtrace by default]) +) +dnl +dnl handle --enable-debugfs +dnl +AC_ARG_ENABLE([debugfs], +[ --disable-debugfs disable support of debugfs program], +if test "$enableval" = "no" +then + AC_MSG_RESULT([Disabling debugfs support]) + DEBUGFS_CMT="#" +else + DEBUGFS_CMT= + AC_MSG_RESULT([Enabling debugfs support]) +fi +, +AC_MSG_RESULT([Enabling debugfs support by default]) +DEBUGFS_CMT= +) +AC_SUBST(DEBUGFS_CMT) +dnl +dnl handle --enable-imager +dnl +AC_ARG_ENABLE([imager], +[ --disable-imager disable support of e2image program], +if test "$enableval" = "no" +then + AC_MSG_RESULT([Disabling e2image support]) + IMAGER_CMT="#" +else + IMAGER_CMT= + AC_MSG_RESULT([Enabling e2image support]) +fi +, +AC_MSG_RESULT([Enabling e2image support by default]) +IMAGER_CMT= +) +AC_SUBST(IMAGER_CMT) +dnl +dnl handle --enable-resizer +dnl +AC_ARG_ENABLE([resizer], +[ --disable-resizer disable support of e2resize program], +if test "$enableval" = "no" +then + AC_MSG_RESULT([Disabling e2resize support]) + RESIZER_CMT="#" +else + RESIZER_CMT= + AC_MSG_RESULT([Enabling e2resize support]) +fi +, +AC_MSG_RESULT([Enabling e2resize support by default]) +RESIZER_CMT= +) +AC_SUBST(RESIZER_CMT) +dnl +dnl handle --enable-defrag +dnl +AC_ARG_ENABLE([defrag], +[ --disable-defrag disable support of e4defrag program], +if test "$enableval" = "no" +then + AC_MSG_RESULT([Disabling e4defrag support]) + DEFRAG_CMT="#" +else + DEFRAG_CMT= + AC_MSG_RESULT([Enabling e4defrag support]) +fi +, +if test -z "$WITH_DIET_LIBC" +then + AC_MSG_RESULT([Enabling e4defrag support by default]) + DEFRAG_CMT= +else + AC_MSG_RESULT([Disabling e4defrag support by default]) + DEFRAG_CMT="#" +fi +) +AC_SUBST(DEFRAG_CMT) +dnl +dnl See whether to install the `fsck' wrapper program (that calls e2fsck) +dnl +AC_ARG_ENABLE([fsck], +[ --enable-fsck build fsck wrapper program], +[if test "$enableval" = "no" +then + FSCK_PROG='' FSCK_MAN='' + AC_MSG_RESULT([Not building fsck wrapper]) +else + FSCK_PROG=fsck FSCK_MAN=fsck.8 + AC_MSG_RESULT([Building fsck wrapper]) +fi] +, +[case "$host_os" in + gnu*) + FSCK_PROG='' FSCK_MAN='' + AC_MSG_RESULT([Not building fsck wrapper by default]) + ;; + *) + FSCK_PROG=fsck FSCK_MAN=fsck.8 + AC_MSG_RESULT([Building fsck wrapper by default]) +esac] +) +AC_SUBST(FSCK_PROG) +AC_SUBST(FSCK_MAN) +dnl +dnl See whether to install the `e2initrd-helper' program +dnl +AC_ARG_ENABLE([e2initrd-helper], +[ --enable-e2initrd-helper build e2initrd-helper program], +[if test "$enableval" = "no" +then + E2INITRD_PROG='' E2INITRD_MAN='' + AC_MSG_RESULT([Not building e2initrd helper]) +else + E2INITRD_PROG=e2initrd_helper E2INITRD_MAN=e2initrd_helper.8 + AC_MSG_RESULT([Building e2initrd helper]) +fi] +, +E2INITRD_PROG=e2initrd_helper E2INITRD_MAN=e2initrd_helper.8 +AC_MSG_RESULT([Building e2initrd helper by default]) +) +AC_SUBST(E2INITRD_PROG) +AC_SUBST(E2INITRD_MAN) +dnl +dnl +dnl +AC_ARG_ENABLE([tls], +[ --disable-tls disable use of thread local support], +[if test "$enableval" = "no" +then + try_tls="" + AC_MSG_RESULT([Disabling thread local support]) +else + try_tls="yes" + AC_MSG_RESULT([Enabling thread local support]) +fi] +, +if test -n "$WITH_DIET_LIBC" +then + try_tls="" + AC_MSG_RESULT([Diet libc does not support thread local support]) +else + try_tls="yes" + AC_MSG_RESULT([Try using thread local support by default]) +fi +) +if test "$try_tls" = "yes" +then +AX_TLS +fi +dnl +dnl +dnl +AH_TEMPLATE([USE_UUIDD], [Define to 1 to build uuidd]) +AC_ARG_ENABLE([uuidd], +[ --disable-uuidd disable building the uuid daemon], +[if test "$enableval" = "no" +then + AC_MSG_RESULT([Not building uuidd]) + UUIDD_CMT="#" +else + AC_DEFINE(USE_UUIDD, 1) + UUIDD_CMT="" + AC_MSG_RESULT([Building uuidd]) +fi] +, +AC_DEFINE(USE_UUIDD, 1) +if test -z "$UUID_CMT" +then + UUIDD_CMT="" + AC_MSG_RESULT([Building uuidd by default]) +else + UUIDD_CMT="#" + AC_MSG_RESULT([Disabling uuidd by default]) +fi +) +AC_SUBST(UUIDD_CMT) +dnl +dnl +dnl +MAKEFILE_LIBRARY=$srcdir/lib/Makefile.library +AC_SUBST_FILE(MAKEFILE_LIBRARY) +dnl +dnl Add internationalization support, using gettext. +dnl +GETTEXT_PACKAGE=e2fsprogs +PACKAGE=e2fsprogs +VERSION="$E2FSPROGS_VERSION" +VERSION=0.14.1 +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [package name for gettext]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [version for gettext]) +AC_SUBST(GETTEXT_PACKAGE) +AC_SUBST(PACKAGE) +AC_SUBST(VERSION) + +AM_GNU_GETTEXT +dnl +dnl End of configuration options +dnl +AC_SUBST(BINARY_TYPE) +AC_PROG_MAKE_SET +CHECK_GNU_MAKE +AC_PATH_PROG(LN, ln, ln) +AC_PROG_LN_S +AC_PATH_PROG(MV, mv, mv) +AC_PATH_PROG(CP, cp, cp) +AC_PATH_PROG(RM, rm, rm) +AC_PATH_PROG(CHMOD, chmod, :) +AC_PROG_AWK +AC_PROG_EGREP +AC_PATH_PROG(SED, sed, sed) +AC_PATH_PROG(PERL, perl, perl) +AC_PATH_PROG(LDCONFIG, ldconfig, :) +AC_CHECK_TOOL(AR, ar, ar) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) +AC_CHECK_PROG(MAKEINFO, makeinfo, makeinfo, ) +if test "_$MAKEINFO" = "_"; then + MAKEINFO="@echo Makeinfo is missing. Info documentation will not be built.;true" +else + case "$MAKEINFO" in + */missing.*) + AC_MSG_WARN([ +*** Makeinfo is missing. Info documentation will not be built.]) + ;; + *) + ;; + esac +fi +AC_SUBST(MAKEINFO) +AC_PROG_INSTALL +# See if we need a separate native compiler. +if test $cross_compiling = no; then + BUILD_CC="$CC" + AC_SUBST(BUILD_CC) +else + AC_CHECK_PROGS(BUILD_CC, gcc cc) +fi +AC_CHECK_HEADERS(m4_flatten([ + dirent.h + errno.h + execinfo.h + getopt.h + malloc.h + mntent.h + paths.h + semaphore.h + setjmp.h + signal.h + stdarg.h + stdint.h + stdlib.h + termios.h + termio.h + unistd.h + utime.h + linux/falloc.h + linux/fd.h + linux/major.h + linux/loop.h + net/if_dl.h + netinet/in.h + sys/disklabel.h + sys/disk.h + sys/file.h + sys/ioctl.h + sys/mkdev.h + sys/mman.h + sys/mount.h + sys/prctl.h + sys/resource.h + sys/select.h + sys/socket.h + sys/sockio.h + sys/stat.h + sys/syscall.h + sys/sysmacros.h + sys/time.h + sys/types.h + sys/un.h + sys/wait.h +])) +AC_CHECK_HEADERS(net/if.h,,, +[[ +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#if HAVE_SYS_SOCKET +#include <sys/socket.h> +#endif +]]) +AC_FUNC_VPRINTF +dnl Check to see if dirent has member d_reclen. On cygwin those d_reclen +dnl is not decleared. +AC_CHECK_MEMBER(struct dirent.d_reclen,[AC_DEFINE(HAVE_RECLEN_DIRENT, 1, + [Define to 1 if dirent has d_reclen])],, + [#include <dirent.h>]) +AC_CHECK_MEMBERS([struct stat.st_atim]) +dnl Check to see if ssize_t was declared +AC_CHECK_TYPE(ssize_t,[AC_DEFINE(HAVE_TYPE_SSIZE_T, 1, + [Define to 1 if ssize_t declared])],, + [#include <sys/types.h>]) +dnl +dnl Check to see if llseek() is declared in unistd.h. On some libc's +dnl it is, and on others it isn't..... Thank you glibc developers.... +dnl +AC_CHECK_DECL(llseek,[AC_DEFINE(HAVE_LLSEEK_PROTOTYPE, 1, + [Define to 1 if llseek declared in unistd.h])],, + [#include <unistd.h>]) +dnl +dnl Check to see if lseek64() is declared in unistd.h. Glibc's header files +dnl are so convoluted that I can't tell whether it will always be defined, +dnl and if it isn't defined while lseek64 is defined in the library, +dnl disaster will strike. +dnl +dnl Warning! Use of --enable-gcc-wall may throw off this test. +dnl +dnl +AC_CHECK_DECL(lseek64,[AC_DEFINE(HAVE_LSEEK64_PROTOTYPE, 1, + [Define to 1 if lseek64 declared in unistd.h])],, + [#define _LARGEFILE_SOURCE + #define _LARGEFILE64_SOURCE + #include <unistd.h>]) +dnl +dnl Word sizes... +dnl +AC_CHECK_SIZEOF(short) +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(long long) +AC_CHECK_SIZEOF(off_t) +SIZEOF_SHORT=$ac_cv_sizeof_short +SIZEOF_INT=$ac_cv_sizeof_int +SIZEOF_LONG=$ac_cv_sizeof_long +SIZEOF_LONG_LONG=$ac_cv_sizeof_long_long +SIZEOF_OFF_T=$ac_cv_sizeof_off_t +AC_SUBST(SIZEOF_SHORT) +AC_SUBST(SIZEOF_INT) +AC_SUBST(SIZEOF_LONG) +AC_SUBST(SIZEOF_LONG_LONG) +AC_SUBST(SIZEOF_OFF_T) +AC_C_BIGENDIAN +if test $cross_compiling = no; then + BUILD_CC="$BUILD_CC" CPP="$CPP" /bin/sh $ac_aux_dir/parse-types.sh +else + CROSS_COMPILE="1" BUILD_CC="$BUILD_CC" CPP="$CPP" /bin/sh $ac_aux_dir/parse-types.sh +fi +ASM_TYPES_HEADER=./asm_types.h +AC_SUBST_FILE(ASM_TYPES_HEADER) +dnl +dnl Save the configuration #defines needed for the public ext2fs.h +dnl header file +dnl +echo "/* These defines are needed for the public ext2fs.h header file */" \ + > public_config.h +if grep HAVE_SYS_TYPES_H confdefs.h > tmp_config.$$; then + uniq tmp_config.$$ >> public_config.h +else + echo "#undef HAVE_SYS_TYPES_H" >> public_config.h +fi +if grep WORDS_BIGENDIAN confdefs.h > tmp_config.$$; then + uniq tmp_config.$$ >> public_config.h +else + echo "#undef WORDS_BIGENDIAN" >> public_config.h +fi +rm -f tmp_config.$$ +PUBLIC_CONFIG_HEADER=./public_config.h +AC_SUBST_FILE(PUBLIC_CONFIG_HEADER) +dnl +dnl See if we have inttypes.h and if intptr_t is defined +dnl +AC_CHECK_HEADERS([inttypes.h]) +AC_CHECK_TYPES(intptr_t) +dnl +dnl See if struct stat has a st_flags field, in which case we can get file +dnl flags somewhat portably. Also check for the analogous setter, chflags(). +dnl +AC_MSG_CHECKING(whether struct stat has a st_flags field) +AC_CACHE_VAL(e2fsprogs_cv_struct_st_flags, + AC_TRY_COMPILE([#include <sys/stat.h>], + [struct stat stat; stat.st_flags = 0;], + [e2fsprogs_cv_struct_st_flags=yes], + [e2fsprogs_cv_struct_st_flags=no])) +AC_MSG_RESULT($e2fsprogs_cv_struct_st_flags) +if test "$e2fsprogs_cv_struct_st_flags" = yes; then + AC_MSG_CHECKING(whether st_flags field is useful) + AC_CACHE_VAL(e2fsprogs_cv_struct_st_flags_immut, + AC_TRY_COMPILE([#include <sys/stat.h>], + [struct stat stat; stat.st_flags |= UF_IMMUTABLE;], + [e2fsprogs_cv_struct_st_flags_immut=yes], + [e2fsprogs_cv_struct_st_flags_immut=no])) + AC_MSG_RESULT($e2fsprogs_cv_struct_st_flags_immut) + if test "$e2fsprogs_cv_struct_st_flags_immut" = yes; then + AC_DEFINE(HAVE_STAT_FLAGS, 1, + [Define to 1 if struct stat has st_flags]) + fi +fi +dnl +dnl Check for the presence of SA_LEN +dnl +AC_CHECK_MEMBER(struct sockaddr.sa_len, + AC_DEFINE_UNQUOTED(HAVE_SA_LEN,1, + [Define to 1 if if struct sockaddr contains sa_len]),, + [#include <sys/types.h> + #include <sys/socket.h>]) +dnl +dnl This will add -lblkid to the AC_CHECK_FUNCS search if we are using +dnl the system-provided blkid library +dnl +if test -n "$BLKID_CMT"; then + AC_SEARCH_LIBS([blkid_probe_all], [blkid]) +fi +dnl +AC_CHECK_FUNCS(m4_flatten([ + __secure_getenv + backtrace + blkid_probe_get_topology + blkid_probe_enable_partitions + chflags + fadvise64 + fallocate + fallocate64 + fchown + fdatasync + fstat64 + ftruncate64 + futimes + getcwd + getdtablesize + getmntinfo + getpwuid_r + getrlimit + getrusage + jrand48 + llseek + lseek64 + mallinfo + mbstowcs + memalign + mempcpy + mmap + msync + nanosleep + open64 + pathconf + posix_fadvise + posix_fadvise64 + posix_memalign + prctl + pread + pwrite + pread64 + pwrite64 + secure_getenv + setmntent + setresgid + setresuid + snprintf + srandom + stpcpy + strcasecmp + strdup + strnlen + strptime + strtoull + sync_file_range + sysconf + usleep + utime + utimes + valloc +])) +dnl +dnl Check to see if -lsocket is required (solaris) to make something +dnl that uses socket() to compile; this is needed for the UUID library +dnl +SOCKET_LIB='' +AC_CHECK_LIB(socket, socket, [SOCKET_LIB=-lsocket]) +AC_SUBST(SOCKET_LIB) +dnl +dnl See if optreset exists +dnl +AC_MSG_CHECKING(for optreset) +AC_CACHE_VAL(ac_cv_have_optreset, +[AC_EGREP_HEADER(optreset, unistd.h, + ac_cv_have_optreset=yes, ac_cv_have_optreset=no)])dnl +AC_MSG_RESULT($ac_cv_have_optreset) +if test $ac_cv_have_optreset = yes; then + AC_DEFINE(HAVE_OPTRESET, 1, [Define to 1 if optreset for getopt is present]) +fi +dnl +dnl Test for sem_init, and which library it might require: +dnl +AH_TEMPLATE([HAVE_SEM_INIT], [Define to 1 if sem_init() exists]) +SEM_INIT_LIB='' +AC_CHECK_FUNC(sem_init, , + AC_CHECK_LIB(pthread, sem_init, + AC_DEFINE(HAVE_SEM_INIT, 1) + SEM_INIT_LIB=-lpthread, + AC_CHECK_LIB(rt, sem_init, + AC_DEFINE(HAVE_SEM_INIT, 1) + SEM_INIT_LIB=-lrt, + AC_CHECK_LIB(posix4, sem_init, + AC_DEFINE(HAVE_SEM_INIT, 1) + SEM_INIT_LIB=-lposix4))))dnl +AC_SUBST(SEM_INIT_LIB) +dnl +dnl Check for unified diff +dnl +AC_MSG_CHECKING(for unified diff option) +if diff -u $0 $0 > /dev/null 2>&1 ; then + UNI_DIFF_OPTS=-u +else + UNI_DIFF_OPTS=-c +fi +AC_MSG_RESULT($UNI_DIFF_OPTS) +AC_SUBST(UNI_DIFF_OPTS) +dnl +dnl We use the EXT2 ioctls only under Linux +dnl +case "$host_os" in +linux*) + AC_DEFINE(HAVE_EXT2_IOCTLS, 1, [Define to 1 if Ext2 ioctls present]) + ;; +esac +dnl +dnl OS-specific uncomment control +dnl +LINUX_CMT="#" +CYGWIN_CMT="#" +UNIX_CMT= +case "$host_os" in +linux*) + LINUX_CMT= + ;; +cygwin) + CYGWIN_CMT= + UNIX_CMT="#" + ;; +esac +AC_SUBST(LINUX_CMT) +AC_SUBST(CYGWIN_CMT) +AC_SUBST(UNIX_CMT) +dnl +dnl Linux and Hurd places root files in the / by default +dnl +case "$host_os" in +linux* | gnu* | k*bsd*-gnu) + if test "$prefix" = NONE -a "$root_prefix" = NONE ; then + root_prefix=""; + AC_MSG_RESULT([On $host_os systems, root_prefix defaults to '']) + fi + ;; +esac +dnl +dnl On Linux/hurd, force the prefix to be /usr +dnl +case "$host_os" in +linux* | gnu* | k*bsd*-gnu) + if test "$prefix" = NONE ; then + prefix="/usr"; + AC_MSG_RESULT([On $host_os systems, prefix defaults to /usr]) + if test "$mandir" = '${prefix}/man' ; then + AC_MSG_RESULT([...and mandir defaults to /usr/share/man]) + mandir=/usr/share/man + fi + fi +;; +esac +if test "$root_prefix" = NONE ; then + if test "$prefix" = NONE ; then + root_prefix="$ac_default_prefix" + else + root_prefix="$prefix" + fi + root_bindir=$bindir + root_sbindir=$sbindir + root_libdir=$libdir + root_sysconfdir=$sysconfdir +else + root_bindir='${root_prefix}/bin' + root_sbindir='${root_prefix}/sbin' + root_libdir='${root_prefix}/lib' + root_sysconfdir='${root_prefix}/etc' +fi +if test "$bindir" != '${exec_prefix}/bin'; then + root_bindir=$bindir + AC_MSG_RESULT([Setting root_bindir to $root_bindir]) +fi +if test "$sbindir" != '${exec_prefix}/sbin'; then + root_sbindir=$sbindir + AC_MSG_RESULT([Setting root_sbindir to $root_sbindir]) +fi +if test "$libdir" != '${exec_prefix}/lib'; then + root_libdir=$libdir + AC_MSG_RESULT([Setting root_libdir to $root_libdir]) +fi +if test "$sysconfdir" != '${prefix}/etc'; then + root_sysconfdir=$sysconfdir + AC_MSG_RESULT([Setting root_sysconfdir to $root_sysconfdir]) +fi +AC_SUBST(root_prefix) +AC_SUBST(root_bindir) +AC_SUBST(root_sbindir) +AC_SUBST(root_libdir) +AC_SUBST(root_sysconfdir) +dnl +dnl Allow specification of the multiarch arch +dnl +AC_ARG_WITH([multiarch], +[ --with-multiarch=ARCH specify the multiarch triplet], +if test "$withval" = "lib64"; then + libdir=/usr/lib64 + root_libdir=/lib64 +else + libdir=$libdir/$withval + root_libdir=$root_libdir/$withval +fi +)dnl +dnl +dnl See if -static works. This could fail if the linker does not +dnl support -static, or if required external libraries are not available +dnl in static form. +dnl +AC_MSG_CHECKING([whether we can link with -static]) +AC_CACHE_VAL(ac_cv_e2fsprogs_use_static, +[SAVE_LDFLAGS=$LDFLAGS; LDFLAGS="$LDFLAGS -static" +AC_TRY_LINK([#include <stdio.h>],[fflush(stdout);], + ac_cv_e2fsprogs_use_static=yes, ac_cv_e2fsprogs_use_static=no) +LDFLAGS=$SAVE_LDFLAGS]) +dnl +dnl Regardless of how the test turns out, Solaris doesn't handle -static +dnl This is caused by the socket library requiring the nsl library, which +dnl requires the -dl library, which only works for dynamically linked +dnl programs. It basically means you can't have statically linked programs +dnl which use the network under Solaris. +dnl +case "$host_os" in +solaris2.*) + ac_cv_e2fsprogs_use_static=no +;; +esac +AC_MSG_RESULT($ac_cv_e2fsprogs_use_static) +LDFLAG_STATIC= +if test $ac_cv_e2fsprogs_use_static = yes; then + LDFLAG_STATIC=-static +fi +AC_SUBST(LDFLAG_STATIC) +dnl +dnl Work around mysterious Darwin / GNU libintl problem +dnl (__asm__ redirection doesn't work for some mysterious reason. Looks like +dnl Apple hacked gcc somehow?) +dnl +case "$host_os" in +darwin*) + AC_MSG_RESULT([Using Apple Darwin / GNU libintl workaround]) + AC_DEFINE(_INTL_REDIRECT_MACROS, 1, + [Define to 1 if Apple Darwin libintl workaround is needed]) + ;; +esac +dnl +dnl Make the ss and et directories work correctly. +dnl +SS_DIR=`cd ${srcdir}/lib/ss; pwd` +ET_DIR=`cd ${srcdir}/lib/et; pwd` +AC_SUBST(SS_DIR) +AC_SUBST(ET_DIR) +dnl +dnl Only try to run the test suite if we're not cross compiling. +dnl +if test "$cross_compiling" = yes ; then + DO_TEST_SUITE= +else + DO_TEST_SUITE=check +fi +AC_SUBST(DO_TEST_SUITE) +dnl +dnl Only include the intl include files if we're building with them +dnl +INCLUDES='-I. -I$(top_builddir)/lib -I$(top_srcdir)/lib' +if test -n "$CPPFLAGS" ; then + INCLUDES="$INCLUDES $CPPFLAGS" +fi +if test "$USE_INCLUDED_LIBINTL" = "yes" ; then + INCLUDES=$INCLUDES' -I$(top_builddir)/intl -I$(top_srcdir)/intl' +fi +if test -n "$WITH_DIET_LIBC" ; then + INCLUDES="$INCLUDES -D_REENTRANT" +fi +AC_SUBST(INCLUDES) +AM_MKINSTALLDIRS +dnl +dnl Build CFLAGS +dnl +if test $cross_compiling = no; then + BUILD_CFLAGS="$CFLAGS $CPPFLAGS $INCLUDES -DHAVE_CONFIG_H" + BUILD_LDFLAGS="$LDFLAGS" +fi +AC_SUBST(BUILD_CFLAGS) +AC_SUBST(BUILD_LDFLAGS) +dnl +dnl Make our output files, being sure that we create the some miscellaneous +dnl directories +dnl +test -d lib || mkdir lib +test -d include || mkdir include +test -d include/linux || mkdir include/linux +test -d include/asm || mkdir include/asm +for i in MCONFIG Makefile e2fsprogs.spec \ + util/Makefile util/subst.conf util/gen-tarball util/install-symlink \ + lib/et/Makefile lib/ss/Makefile lib/e2p/Makefile \ + lib/ext2fs/Makefile lib/ext2fs/ext2_types.h \ + lib/uuid/Makefile lib/uuid/uuid_types.h \ + lib/blkid/Makefile lib/blkid/blkid_types.h lib/quota/Makefile \ + lib/ss/ss.pc lib/uuid/uuid.pc lib/et/com_err.pc \ + lib/e2p/e2p.pc lib/blkid/blkid.pc lib/ext2fs/ext2fs.pc \ + misc/Makefile ext2ed/Makefile e2fsck/Makefile \ + debugfs/Makefile tests/Makefile tests/progs/Makefile \ + resize/Makefile doc/Makefile intl/Makefile \ + intl/libgnuintl.h po/Makefile.in ; do + if test -d `dirname ${srcdir}/$i` ; then + outlist="$outlist $i" + fi +done +AC_OUTPUT($outlist) +if test -f util/gen-tarball; then chmod +x util/gen-tarball; fi
diff --git a/contrib/build-rpm b/contrib/build-rpm new file mode 100644 index 0000000..0b06071 --- /dev/null +++ b/contrib/build-rpm
@@ -0,0 +1,45 @@ +#!/bin/sh + +# enable xtrace output if requested +if [ -n ${ENABLE_XTRACE:-''} ]; then + set -x +fi + +# Build an e2fsprogs RPM from cvs + +pwd=`pwd` +currdir=`basename $pwd` +pkgname=`grep Name: e2fsprogs.spec | awk '{print $2;}'` +pkgvers=`grep Version: e2fsprogs.spec | awk '{print $2;}'` +builddir=${pkgname}-${pkgvers} + +# ensure that $TMP is set to something +TMP=${TMP:-'/tmp'} + +cd .. +tmpdir=`mktemp -d ${RPM_TMPDIR:-$TMP}/rpmtmp.XXXXXX` + +# We need to build a tarball for the SRPM using $builddir as the +# directory name (since that's what RPM will expect it to unpack +# into). That may require a symlink. + +# Make a recursive-symlink copy of the source dir +cp -sR `pwd`/$currdir $tmpdir/$builddir || exit 1 + +# Remove any build files from the temporary tarball directory +[ -f $tmpdir/$builddir/Makefile ] && make -C $tmpdir/$builddir distclean + +EXCLUDE="--exclude .hg* --exclude .pc*" +(cd $tmpdir && tar czfh ${builddir}.tar.gz $EXCLUDE $builddir) + +[ "`rpmbuild --version 2> /dev/null`" ] && RPM=rpmbuild || RPM=rpm + +$RPM --define "_sourcedir $tmpdir" \ + --define "_topdir ${RPM_TOPDIR:-$(rpm -E %_topdir)}" \ + --define "_tmpdir ${RPM_TMPDIR:-$TMP}" \ + --define "extra_config_flags ${EXTRA_CONFIG_FLAGS:-''}" \ + -ba $currdir/e2fsprogs.spec + +rpm_exit=$? +rm -rf $tmpdir +exit $rpm_exit
diff --git a/contrib/dconf b/contrib/dconf new file mode 100644 index 0000000..cef4cc6 --- /dev/null +++ b/contrib/dconf
@@ -0,0 +1,118 @@ +#!/bin/sh +#$Id$ +# Create Adobe-PostScript file that graphically displays the output of +# dumpe2fs(8). Use "dumpe2fs | dconf" to create a PostScript file on stdout. +# Developed and tested for Linux 1.0. +# Copyright (c) 1994 +# Ulrich Windl +# ALte Regensburger Strasse 11a +# D-93149 Nittenau, Germany +# <Ulrich.Windl@rz.uni-regensburg.de> +SELF=`basename $0` +AWKFILE=/tmp/${SELF}.awk +TEMPFILE=/tmp/${SELF}.tmp +echo ' +BEGIN { + print "B" +} +/^Inode count:/ { + ic=$3; next +} +/^Block count:/ { + bc=$3; next +} +/^First block:/ { + fb=$3; next +} +/^Block size:/ { + bs=$3; next +} +/^Blocks per group:/ { + bpg=$4 + printf("BC %d\n", bpg) + printf("GC %d\n", (bc + bpg - 1) / bpg) + next +} +/^Inodes per group:/ { + ipg=$4; next +} +/^Last write time:/ { + lwtime=$0; gsub("Last write time:[ ]+", "", lwtime) + printf("T %s\n", lwtime) + next +} +/^Group [0-9]+:/ { + group=$2; gsub(":", "", group) + block="" + group_start=group*bpg+fb + group_end=group_start+bpg + printf("G %d : %d - %d\n", group, group_start, group_end) + next +} +/^[ ]+Free blocks: / { + for ( i=3; i < NF; ++i ) { + block=$i; gsub(",", "", block) + if ( index(block, "-") == 0 ) block=block "-" block + pos=index(block, "-") + printf("FB %d-%d\n", + substr(block, 0, pos) - group_start, + substr(block, pos + 1) - group_start) + } + if ( block == "" ) printf("Group %d is full\n", group) + print "----" + next +} +END { + printf("E %s\n", lwtime) +}' >$AWKFILE +awk -f $AWKFILE $* >$TEMPFILE +echo ' +BEGIN { + printf("%%!PS-Adobe\n") + printf("%%%%BoundingBox: 0 0 1 1\n") + printf("/rect {/y2 exch def /x2 exch def /y1 exch def /x1 exch def\n") + printf(" newpath x1 y1 moveto x2 y1 lineto x2 y2 lineto\n") + printf(" x1 y2 lineto closepath} def\n") + printf("/fb {rect gsave 1.0 setgray fill grestore} def\n") + printf("/dg {rect gsave gsave 0.0 setgray fill grestore\n") + printf(" 0.5 setgray stroke grestore} def\n") + printf("/textxy {moveto show} bind def\n") + printf("0.0001 setlinewidth\n") +} +$1 == "GC" && NF == 2 { + number_of_groups=$2 + printf("/Times-Roman findfont %g scalefont setfont\n", + 1.0 / number_of_groups) + next +} +$1 == "BC" && NF == 2 { + blocks_per_group=$2; next +} +$1 == "T" && NF > 1 { + printf("(%s) %g %g textxy\n", + substr($0, 2), 0, 1.02) + next +} +$1 == "G" && NF == 6 && $3 == ":" && $5 == "-" { + group_index=$2 + gs=$4 + ge=$6 + height=1.0 / number_of_groups + vstart=group_index * height + printf("%% group %d of %d:\n0 %g 1 %g dg\n", + group_index, number_of_groups, vstart, vstart + height) + printf("(Group %s) 1.02 %g textxy\n", group_index, vstart) + next +} +$1 == "FB" && NF == 2 { + pos = index($2, "-") + printf("%% hole %s\n%g %g %g %g fb\n", + $2, substr($2, 0, pos) / blocks_per_group, vstart, + (substr($2, pos + 1) + 1) / blocks_per_group, vstart + height) + next +} +END { + printf("%%%%EOF\n") +} +' >$AWKFILE +awk -f $AWKFILE $TEMPFILE
diff --git a/contrib/e2croncheck b/contrib/e2croncheck new file mode 100755 index 0000000..de0b41f --- /dev/null +++ b/contrib/e2croncheck
@@ -0,0 +1,47 @@ +#!/bin/sh +# +# e2croncheck -- run e2fsck automatically out of /etc/cron.weekly +# +# This script is intended to be run by the system administrator +# periodically from the command line, or to be run once a week +# or so by the cron daemon to check a mounted filesystem (normally +# the root filesystem, but it could be used to check other filesystems +# that are always mounted when the system is booted). +# +# Make sure you customize "VG" so it is your LVM volume group name, +# "VOLUME" so it is the name of the filesystem's logical volume, +# and "EMAIL" to be your e-mail address +# +# Written by Theodore Ts'o, Copyright 2007, 2008, 2009. +# +# This file may be redistributed under the terms of the +# GNU Public License, version 2. +# + +VG=ssd +VOLUME=root +SNAPSIZE=100m +EMAIL=sysadmin@example.com + +TMPFILE=`mktemp ${TMPDIR:-/tmp}/e2fsck.log.XXXXXXXXXX` + +OPTS="-Fttv -C0" +#OPTS="-Fttv -E fragcheck" + +set -e +START="$(date +'%Y%m%d%H%M%S')" +lvcreate -s -L ${SNAPSIZE} -n "${VOLUME}-snap" "${VG}/${VOLUME}" +if nice logsave -as $TMPFILE e2fsck -p $OPTS "/dev/${VG}/${VOLUME}-snap" && \ + nice logsave -as $TMPFILE e2fsck -fy $OPTS "/dev/${VG}/${VOLUME}-snap" ; then + echo 'Background scrubbing succeeded!' + tune2fs -C 0 -T "${START}" "/dev/${VG}/${VOLUME}" +else + echo 'Background scrubbing failed! Reboot to fsck soon!' + tune2fs -C 16000 -T "19000101" "/dev/${VG}/${VOLUME}" + if test -n "$RPT-EMAIL"; then + mail -s "E2fsck of /dev/${VG}/${VOLUME} failed!" $EMAIL < $TMPFILE + fi +fi +lvremove -f "${VG}/${VOLUME}-snap" +rm $TMPFILE +
diff --git a/contrib/fallocate.c b/contrib/fallocate.c new file mode 100644 index 0000000..1f9b59a --- /dev/null +++ b/contrib/fallocate.c
@@ -0,0 +1,174 @@ +/* + * fallocate - utility to use the fallocate system call + * + * Copyright (C) 2008 Red Hat, Inc. All rights reserved. + * Written by Eric Sandeen <sandeen@redhat.com> + * + * cvtnum routine taken from xfsprogs, + * Copyright (c) 2003-2005 Silicon Graphics, 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. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT 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 _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> + +// #include <linux/falloc.h> +#define FALLOC_FL_KEEP_SIZE 0x01 +#define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ + +void usage(void) +{ + printf("Usage: fallocate [-npt] [-o offset] -l length filename\n"); + exit(EXIT_FAILURE); +} + +#define EXABYTES(x) ((long long)(x) << 60) +#define PETABYTES(x) ((long long)(x) << 50) +#define TERABYTES(x) ((long long)(x) << 40) +#define GIGABYTES(x) ((long long)(x) << 30) +#define MEGABYTES(x) ((long long)(x) << 20) +#define KILOBYTES(x) ((long long)(x) << 10) + +long long +cvtnum(char *s) +{ + long long i; + char *sp; + int c; + + i = strtoll(s, &sp, 0); + if (i == 0 && sp == s) + return -1LL; + if (*sp == '\0') + return i; + if (sp[1] != '\0') + return -1LL; + + c = tolower(*sp); + switch (c) { + case 'k': + return KILOBYTES(i); + case 'm': + return MEGABYTES(i); + case 'g': + return GIGABYTES(i); + case 't': + return TERABYTES(i); + case 'p': + return PETABYTES(i); + case 'e': + return EXABYTES(i); + } + + return -1LL; +} + +int main(int argc, char **argv) +{ + int fd; + char *fname; + int opt; + loff_t length = -2LL; + loff_t offset = 0; + int falloc_mode = 0; + int error; + int tflag = 0; + + while ((opt = getopt(argc, argv, "npl:o:t")) != -1) { + switch(opt) { + case 'n': + /* do not change filesize */ + falloc_mode = FALLOC_FL_KEEP_SIZE; + break; + case 'p': + /* punch mode */ + falloc_mode = (FALLOC_FL_PUNCH_HOLE | + FALLOC_FL_KEEP_SIZE); + break; + case 'l': + length = cvtnum(optarg); + break; + case 'o': + offset = cvtnum(optarg); + break; + case 't': + tflag++; + break; + default: + usage(); + } + } + + if (length == -2LL) { + printf("Error: no length argument specified\n"); + usage(); + } + + if (length <= 0) { + printf("Error: invalid length value specified\n"); + usage(); + } + + if (offset < 0) { + printf("Error: invalid offset value specified\n"); + usage(); + } + + if (tflag && (falloc_mode & FALLOC_FL_KEEP_SIZE)) { + printf("-n and -t options incompatible\n"); + usage(); + } + + if (tflag && offset) { + printf("-n and -o options incompatible\n"); + usage(); + } + + if (optind == argc) { + printf("Error: no filename specified\n"); + usage(); + } + + fname = argv[optind++]; + + /* Should we create the file if it doesn't already exist? */ + fd = open(fname, O_WRONLY|O_LARGEFILE); + if (fd < 0) { + perror("Error opening file"); + exit(EXIT_FAILURE); + } + + if (tflag) + error = ftruncate(fd, length); + else + error = syscall(SYS_fallocate, fd, falloc_mode, offset, length); + + if (error < 0) { + perror("fallocate failed"); + exit(EXIT_FAILURE); + } + + close(fd); + return 0; +}
diff --git a/contrib/make-sparse.c b/contrib/make-sparse.c new file mode 100644 index 0000000..1b3d550 --- /dev/null +++ b/contrib/make-sparse.c
@@ -0,0 +1,87 @@ +/* + * make-sparse.c --- make a sparse file from stdin + * + * Copyright 2004 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +int full_read(int fd, char *buf, size_t count) +{ + int got, total = 0; + int pass = 0; + + while (count > 0) { + got = read(fd, buf, count); + if (got == -1) { + if ((errno == EINTR) || (errno == EAGAIN)) + continue; + return total ? total : -1; + } + if (got == 0) { + if (pass++ >= 3) + return total; + continue; + } + pass = 0; + buf += got; + total += got; + count -= got; + } + return total; +} + +int main(int argc, char **argv) +{ + int fd, got, i; + int zflag = 0; + char buf[1024]; + + if (argc != 2) { + fprintf(stderr, "Usage: make-sparse out-file\n"); + exit(1); + } + fd = open(argv[1], O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0777); + if (fd < 0) { + perror(argv[1]); + exit(1); + } + while (1) { + got = full_read(0, buf, sizeof(buf)); + if (got == 0) + break; + if (got == sizeof(buf)) { + for (i=0; i < sizeof(buf); i++) + if (buf[i]) + break; + if (i == sizeof(buf)) { + lseek(fd, sizeof(buf), SEEK_CUR); + zflag = 1; + continue; + } + } + zflag = 0; + write(fd, buf, got); + } + if (zflag) { + lseek(fd, -1, SEEK_CUR); + buf[0] = 0; + write(fd, buf, 1); + } + return 0; +} +
diff --git a/contrib/populate-extfs.sh b/contrib/populate-extfs.sh new file mode 100755 index 0000000..b1d3d1f --- /dev/null +++ b/contrib/populate-extfs.sh
@@ -0,0 +1,105 @@ +#!/bin/sh +# +# This script uses debugfs command to populate the ext2/3/4 filesystem +# from a given directory. +# + +do_usage () { + cat << _EOF +Usage: populate-extfs.sh <source> <device> +Create an ext2/ext3/ext4 filesystem from a directory or file + + source: The source directory or file + device: The target device + +_EOF + exit 1 +} + +[ $# -ne 2 ] && do_usage + +SRCDIR=${1%%/} +DEVICE=$2 + +# Find where is the debugfs command if not found in the env. +if [ -z "$DEBUGFS" ]; then + CONTRIB_DIR=$(dirname $(readlink -f $0)) + DEBUGFS="$CONTRIB_DIR/../debugfs/debugfs" +fi + +{ + CWD="/" + find $SRCDIR | while read FILE; do + TGT="${FILE##*/}" + DIR="${FILE#$SRCDIR}" + DIR="${DIR%$TGT}" + + # Skip the root dir + [ ! -z "$DIR" ] || continue + [ ! -z "$TGT" ] || continue + + if [ "$DIR" != "$CWD" ]; then + echo "cd $DIR" + CWD="$DIR" + fi + + # Only stat once since stat is a time consuming command + STAT=$(stat -c "TYPE=\"%F\";DEVNO=\"0x%t 0x%T\";MODE=\"%f\";U=\"%u\";G=\"%g\"" $FILE) + eval $STAT + + case $TYPE in + "directory") + echo "mkdir $TGT" + ;; + "regular file" | "regular empty file") + echo "write $FILE $TGT" + ;; + "symbolic link") + LINK_TGT=$(readlink $FILE) + echo "symlink $TGT $LINK_TGT" + ;; + "block special file") + echo "mknod $TGT b $DEVNO" + ;; + "character special file") + echo "mknod $TGT c $DEVNO" + ;; + "fifo") + echo "mknod $TGT p" + ;; + *) + echo "Unknown/unhandled file type '$TYPE' file: $FILE" 1>&2 + ;; + esac + + # Set the file mode + echo "sif $TGT mode 0x$MODE" + + # Set uid and gid + echo "sif $TGT uid $U" + echo "sif $TGT gid $G" + done + + # Handle the hard links. + # Save the hard links to a file, use the inode number as the filename, for example: + # If a and b's inode number is 6775928, save a and b to /tmp/tmp.VrCwHh5gdt/6775928. + INODE_DIR=`mktemp -d` || exit 1 + for i in `find $SRCDIR -type f -links +1 -printf 'INODE=%i###FN=%p\n'`; do + eval `echo $i | sed 's$###$ $'` + echo ${FN#$SRCDIR} >>$INODE_DIR/$INODE + done + # Use the debugfs' ln and "sif links_count" to handle them. + for i in `ls $INODE_DIR`; do + # The link source + SRC=`head -1 $INODE_DIR/$i` + # Remove the files and link them again except the first one + for TGT in `sed -n -e '1!p' $INODE_DIR/$i`; do + echo "rm $TGT" + echo "ln $SRC $TGT" + done + LN_CNT=`cat $INODE_DIR/$i | wc -l` + # Set the links count + echo "sif $SRC links_count $LN_CNT" + done + rm -fr $INODE_DIR +} | $DEBUGFS -w -f - $DEVICE
diff --git a/contrib/python-uuid/setup.py b/contrib/python-uuid/setup.py new file mode 100755 index 0000000..3934d17 --- /dev/null +++ b/contrib/python-uuid/setup.py
@@ -0,0 +1,11 @@ +#!/usr/bin/python +from distutils.core import setup, Extension + +uuid = Extension('e2fsprogs_uuid', + sources = ['uuid.c'], + libraries = ['uuid']) + +setup (name = 'e2fsprogs_uuid', + version = '1.0', + description = 'This is python uuid interface', + ext_modules = [uuid])
diff --git a/contrib/python-uuid/test.py b/contrib/python-uuid/test.py new file mode 100755 index 0000000..2264f62 --- /dev/null +++ b/contrib/python-uuid/test.py
@@ -0,0 +1,18 @@ +#!/usr/bin/python +import e2fsprogs_uuid +import time + +print "Generating uuid...", +try: + time = time.time() + u = e2fsprogs_uuid.generate() +except: + u = "FAIL" +print u, "...", time + +print "Calling generate with param...", +try: + e2fsprogs_uuid.generate("param") + print "FAIL." +except: + print "OK"
diff --git a/contrib/python-uuid/uuid.c b/contrib/python-uuid/uuid.c new file mode 100644 index 0000000..34dd56a --- /dev/null +++ b/contrib/python-uuid/uuid.c
@@ -0,0 +1,23 @@ +#include <Python.h> +#include <time.h> +#include <uuid/uuid.h> + +static PyObject * _uuid_generate(PyObject *self, PyObject *args) +{ + uuid_t u; + char uuid[37]; + if (!PyArg_ParseTuple(args, "")) return NULL; + uuid_generate(u); + uuid_unparse(u, uuid); + return Py_BuildValue("s", uuid); +} + +static PyMethodDef _uuid_methods[] = { + {"generate", _uuid_generate, METH_VARARGS, "Generate UUID"}, + {NULL, NULL, 0, NULL} +}; + +void inite2fsprogs_uuid(void) +{ + (void) Py_InitModule("e2fsprogs_uuid", _uuid_methods); +}
diff --git a/contrib/spd_readdir.c b/contrib/spd_readdir.c new file mode 100644 index 0000000..8345fa1 --- /dev/null +++ b/contrib/spd_readdir.c
@@ -0,0 +1,458 @@ +/* + * readdir accelerator + * + * (C) Copyright 2003, 2004, 2008 by Theodore Ts'o. + * + * 2008-06-08 Modified by Ross Boylan <RossBoylan stanfordalumni org> + * Added support for readdir_r and readdir64_r calls. Note + * this has not been tested on anything other than GNU/Linux i386, + * and that the regular readdir wrapper will take slightly more + * space than Ted's original since it now includes a lock. + * + * Compile using the command: + * + * gcc -o spd_readdir.so -shared -fpic spd_readdir.c -ldl + * + * Use it by setting the LD_PRELOAD environment variable: + * + * export LD_PRELOAD=/usr/local/sbin/spd_readdir.so + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + */ + +#define ALLOC_STEPSIZE 100 +#define MAX_DIRSIZE 0 + +#define DEBUG +/* Util we autoconfiscate spd_readdir... */ +#define HAVE___SECURE_GETENV 1 +#define HAVE_PRCTL 1 +#define HAVE_SYS_PRCTL_H 1 + +#ifdef DEBUG +#define DEBUG_DIR(x) {if (do_debug) { x; }} +#else +#define DEBUG_DIR(x) +#endif + +#define _GNU_SOURCE +#define __USE_LARGEFILE64 + +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <errno.h> +#include <dlfcn.h> +#ifdef HAVE_SYS_PRCTL_H +#include <sys/prctl.h> +#else +#define PR_GET_DUMPABLE 3 +#endif +#include <pthread.h> + +struct dirent_s { + unsigned long long d_ino; + long long d_off; + unsigned short int d_reclen; + unsigned char d_type; + char *d_name; +}; + +struct dir_s { + DIR *dir; + pthread_mutex_t lock; /* Mutex lock for this structure. */ + int num; + int max; + struct dirent_s *dp; + int pos; + int direct; + struct dirent ret_dir; + struct dirent64 ret_dir64; +}; + +static int (*real_closedir)(DIR *dir) = 0; +static DIR *(*real_opendir)(const char *name) = 0; +static DIR *(*real_fdopendir)(int fd) = 0; +static void *(*real_rewinddir)(DIR *dirp) = 0; +static struct dirent *(*real_readdir)(DIR *dir) = 0; +static int (*real_readdir_r)(DIR *dir, struct dirent *entry, + struct dirent **result) = 0; +static struct dirent64 *(*real_readdir64)(DIR *dir) = 0; +static int (*real_readdir64_r)(DIR *dir, struct dirent64 *entry, + struct dirent64 **result) = 0; +static off_t (*real_telldir)(DIR *dir) = 0; +static void (*real_seekdir)(DIR *dir, off_t offset) = 0; +static int (*real_dirfd)(DIR *dir) = 0; +static unsigned long max_dirsize = MAX_DIRSIZE; +static int num_open = 0; +#ifdef DEBUG +static int do_debug = 0; +#endif + +static char *safe_getenv(const char *arg) +{ + if ((getuid() != geteuid()) || (getgid() != getegid())) + return NULL; +#if HAVE_PRCTL + if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#else +#if (defined(linux) && defined(SYS_prctl)) + if (syscall(SYS_prctl, PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) + return NULL; +#endif +#endif + +#if HAVE___SECURE_GETENV + return __secure_getenv(arg); +#else + return getenv(arg); +#endif +} + +static void setup_ptr() +{ + char *cp; + + real_opendir = dlsym(RTLD_NEXT, "opendir"); + real_fdopendir = dlsym(RTLD_NEXT, "fdopendir"); + real_closedir = dlsym(RTLD_NEXT, "closedir"); + real_rewinddir = dlsym(RTLD_NEXT, "rewinddir"); + real_readdir = dlsym(RTLD_NEXT, "readdir"); + real_readdir_r = dlsym(RTLD_NEXT, "readdir_r"); + real_readdir64 = dlsym(RTLD_NEXT, "readdir64"); + real_readdir64_r = dlsym(RTLD_NEXT, "readdir64_r"); + real_telldir = dlsym(RTLD_NEXT, "telldir"); + real_seekdir = dlsym(RTLD_NEXT, "seekdir"); + real_dirfd = dlsym(RTLD_NEXT, "dirfd"); + if ((cp = safe_getenv("SPD_READDIR_MAX_SIZE")) != NULL) { + max_dirsize = atol(cp); + } +#ifdef DEBUG + if (safe_getenv("SPD_READDIR_DEBUG")) { + printf("initialized!\n"); + do_debug++; + } +#endif +} + +static void free_cached_dir(struct dir_s *dirstruct) +{ + int i; + + pthread_mutex_destroy(&(dirstruct->lock)); + + if (!dirstruct->dp) + return; + + for (i=0; i < dirstruct->num; i++) { + free(dirstruct->dp[i].d_name); + } + free(dirstruct->dp); + dirstruct->dp = 0; + dirstruct->max = dirstruct->num = 0; +} + +static int ino_cmp(const void *a, const void *b) +{ + const struct dirent_s *ds_a = (const struct dirent_s *) a; + const struct dirent_s *ds_b = (const struct dirent_s *) b; + ino_t i_a, i_b; + + i_a = ds_a->d_ino; + i_b = ds_b->d_ino; + + if (ds_a->d_name[0] == '.') { + if (ds_a->d_name[1] == 0) + i_a = 0; + else if ((ds_a->d_name[1] == '.') && (ds_a->d_name[2] == 0)) + i_a = 1; + } + if (ds_b->d_name[0] == '.') { + if (ds_b->d_name[1] == 0) + i_b = 0; + else if ((ds_b->d_name[1] == '.') && (ds_b->d_name[2] == 0)) + i_b = 1; + } + + return (i_a - i_b); +} + +static struct dir_s *alloc_dirstruct(DIR *dir) +{ + struct dir_s *dirstruct; + static pthread_mutexattr_t mutexattr; + mutexattr.__align = PTHREAD_MUTEX_RECURSIVE; + + dirstruct = malloc(sizeof(struct dir_s)); + if (dirstruct) + memset(dirstruct, 0, sizeof(struct dir_s)); + dirstruct->dir = dir; + pthread_mutex_init(&(dirstruct->lock), &mutexattr); + return dirstruct; +} + +static void cache_dirstruct(struct dir_s *dirstruct) +{ + struct dirent_s *ds, *dnew; + struct dirent64 *d; + + while ((d = (*real_readdir64)(dirstruct->dir)) != NULL) { + if (dirstruct->num >= dirstruct->max) { + dirstruct->max += ALLOC_STEPSIZE; + DEBUG_DIR(printf("Reallocating to size %d\n", + dirstruct->max)); + dnew = realloc(dirstruct->dp, + dirstruct->max * sizeof(struct dir_s)); + if (!dnew) + goto nomem; + dirstruct->dp = dnew; + } + ds = &dirstruct->dp[dirstruct->num++]; + ds->d_ino = d->d_ino; + ds->d_off = d->d_off; + ds->d_reclen = d->d_reclen; + ds->d_type = d->d_type; + if ((ds->d_name = malloc(strlen(d->d_name)+1)) == NULL) { + dirstruct->num--; + goto nomem; + } + strcpy(ds->d_name, d->d_name); + DEBUG_DIR(printf("readdir: %lu %s\n", + (unsigned long) d->d_ino, d->d_name)); + } + qsort(dirstruct->dp, dirstruct->num, sizeof(struct dirent_s), ino_cmp); + return; +nomem: + DEBUG_DIR(printf("No memory, backing off to direct readdir\n")); + free_cached_dir(dirstruct); + dirstruct->direct = 1; +} + +DIR *opendir(const char *name) +{ + DIR *dir; + struct dir_s *dirstruct; + struct stat st; + + if (!real_opendir) + setup_ptr(); + + DEBUG_DIR(printf("Opendir(%s) (%d open)\n", name, num_open++)); + dir = (*real_opendir)(name); + if (!dir) + return NULL; + + dirstruct = alloc_dirstruct(dir); + if (!dirstruct) { + (*real_closedir)(dir); + errno = -ENOMEM; + return NULL; + } + + if (max_dirsize && (stat(name, &st) == 0) && + (st.st_size > max_dirsize)) { + DEBUG_DIR(printf("Directory size %ld, using direct readdir\n", + st.st_size)); + dirstruct->direct = 1; + return (DIR *) dirstruct; + } + + cache_dirstruct(dirstruct); + return ((DIR *) dirstruct); +} + +DIR *fdopendir(int fd) +{ + DIR *dir; + struct dir_s *dirstruct; + struct stat st; + + if (!real_fdopendir) + setup_ptr(); + + DEBUG_DIR(printf("fdopendir(%d) (%d open)\n", fd, num_open++)); + dir = (*real_fdopendir)(fd); + if (!dir) + return NULL; + + dirstruct = alloc_dirstruct(dir); + if (!dirstruct) { + (*real_closedir)(dir); + errno = -ENOMEM; + return NULL; + } + + if (max_dirsize && (fstat(fd, &st) == 0) && + (st.st_size > max_dirsize)) { + DEBUG_DIR(printf("Directory size %ld, using direct readdir\n", + st.st_size)); + dirstruct->dir = dir; + dirstruct->direct = 1; + return (DIR *) dirstruct; + } + + cache_dirstruct(dirstruct); + return ((DIR *) dirstruct); +} + +int closedir(DIR *dir) +{ + struct dir_s *dirstruct = (struct dir_s *) dir; + + DEBUG_DIR(printf("Closedir (%d open)\n", --num_open)); + if (dirstruct->dir) + (*real_closedir)(dirstruct->dir); + + free_cached_dir(dirstruct); + free(dirstruct); + return 0; +} + +struct dirent *readdir(DIR *dir) +{ + struct dir_s *dirstruct = (struct dir_s *) dir; + struct dirent_s *ds; + + if (dirstruct->direct) + return (*real_readdir)(dirstruct->dir); + + if (dirstruct->pos >= dirstruct->num) + return NULL; + + ds = &dirstruct->dp[dirstruct->pos++]; + dirstruct->ret_dir.d_ino = ds->d_ino; + dirstruct->ret_dir.d_off = ds->d_off; + dirstruct->ret_dir.d_reclen = ds->d_reclen; + dirstruct->ret_dir.d_type = ds->d_type; + strncpy(dirstruct->ret_dir.d_name, ds->d_name, + sizeof(dirstruct->ret_dir.d_name)); + + return (&dirstruct->ret_dir); +} + +int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result) +{ + struct dir_s *dirstruct = (struct dir_s *) dir; + struct dirent_s *ds; + + if (dirstruct->direct) + return (*real_readdir_r)(dirstruct->dir, entry, result); + + pthread_mutex_lock(&(dirstruct->lock)); + if (dirstruct->pos >= dirstruct->num) { + *result = NULL; + } else { + ds = &dirstruct->dp[dirstruct->pos++]; + entry->d_ino = ds->d_ino; + entry->d_off = ds->d_off; + entry->d_reclen = ds->d_reclen; + entry->d_type = ds->d_type; + strncpy(entry->d_name, ds->d_name, sizeof(entry->d_name)); + *result = entry; + } + pthread_mutex_unlock(&(dirstruct->lock)); + return 0; +} + +struct dirent64 *readdir64(DIR *dir) +{ + struct dir_s *dirstruct = (struct dir_s *) dir; + struct dirent_s *ds; + + if (dirstruct->direct) + return (*real_readdir64)(dirstruct->dir); + + if (dirstruct->pos >= dirstruct->num) + return NULL; + + ds = &dirstruct->dp[dirstruct->pos++]; + dirstruct->ret_dir64.d_ino = ds->d_ino; + dirstruct->ret_dir64.d_off = ds->d_off; + dirstruct->ret_dir64.d_reclen = ds->d_reclen; + dirstruct->ret_dir64.d_type = ds->d_type; + strncpy(dirstruct->ret_dir64.d_name, ds->d_name, + sizeof(dirstruct->ret_dir64.d_name)); + + return (&dirstruct->ret_dir64); +} + +int readdir64_r (DIR *__restrict dir, + struct dirent64 *__restrict entry, + struct dirent64 **__restrict result) +{ + struct dir_s *dirstruct = (struct dir_s *) dir; + struct dirent_s *ds; + + if (dirstruct->direct) + return (*real_readdir64_r)(dir, entry, result); + pthread_mutex_lock(&(dirstruct->lock)); + if (dirstruct->pos >= dirstruct->num) { + *result = NULL; + } else { + ds = &dirstruct->dp[dirstruct->pos++]; + entry->d_ino = ds->d_ino; + entry->d_off = ds->d_off; + entry->d_reclen = ds->d_reclen; + entry->d_type = ds->d_type; + strncpy(entry->d_name, ds->d_name, + sizeof(entry->d_name)); + *result = entry; + } + pthread_mutex_unlock(&(dirstruct->lock)); + return 0; +} + +off_t telldir(DIR *dir) +{ + struct dir_s *dirstruct = (struct dir_s *) dir; + + if (dirstruct->direct) + return (*real_telldir)(dirstruct->dir); + + return ((off_t) dirstruct->pos); +} + +void seekdir(DIR *dir, off_t offset) +{ + struct dir_s *dirstruct = (struct dir_s *) dir; + + if (dirstruct->direct) { + (*real_seekdir)(dirstruct->dir, offset); + return; + } + + dirstruct->pos = offset; +} + +void rewinddir(DIR *dir) +{ + struct dir_s *dirstruct = (struct dir_s *) dir; + + (*real_rewinddir)(dirstruct->dir); + if (dirstruct->direct) + return; + + pthread_mutex_lock(&(dirstruct->lock)); + dirstruct->pos = 0; + free_cached_dir(dirstruct); + cache_dirstruct(dirstruct); + pthread_mutex_unlock(&(dirstruct->lock)); +} + +int dirfd(DIR *dir) +{ + struct dir_s *dirstruct = (struct dir_s *) dir; + int fd = (*real_dirfd)(dirstruct->dir); + + DEBUG_DIR(printf("dirfd %d, %p\n", fd, real_dirfd)); + return fd; +}
diff --git a/debian/attic/comerrg-dev.info b/debian/attic/comerrg-dev.info new file mode 100644 index 0000000..8bd344b --- /dev/null +++ b/debian/attic/comerrg-dev.info
@@ -0,0 +1,4 @@ +DESCR="The Common Error Description library." +SECTION_MATCH="Development" +SECTION_NAME="Development" +FILE=com_err.info
diff --git a/debian/attic/comerrg-dev.menu b/debian/attic/comerrg-dev.menu new file mode 100644 index 0000000..7dddab3 --- /dev/null +++ b/debian/attic/comerrg-dev.menu
@@ -0,0 +1,7 @@ +?package(comerrg-dev):needs="dwww" section="Apps/Programming"\ + title="The com_err library" \ + longtitle="The Common Error Description library"\ + description="libcomerr is an attempt to present a common error-handling mechanism to \ + manipulate the most common form of error code in a fashion that does not \ + have the problems identified with mechanisms commonly in use." \ + command="/usr/doc/comerrg-dev/html-info/com_err_toc.html"
diff --git a/debian/attic/e2fslibsg-dev.info b/debian/attic/e2fslibsg-dev.info new file mode 100644 index 0000000..e1be950 --- /dev/null +++ b/debian/attic/e2fslibsg-dev.info
@@ -0,0 +1,4 @@ +DESCR="Library of routines to manipulate an ext2 filesystem." +SECTION_MATCH="Development" +SECTION_NAME="Development" +FILE=libext2fs.info
diff --git a/debian/attic/e2fslibsg-dev.menu b/debian/attic/e2fslibsg-dev.menu new file mode 100644 index 0000000..7ace8c0 --- /dev/null +++ b/debian/attic/e2fslibsg-dev.menu
@@ -0,0 +1,4 @@ +?package(e2fslibsg-dev):needs="dwww" section="Apps/Programming"\ + title="The ext2fs library." \ + longtitle="A library to handle low-level structures in an ext2 filesystem"\ + command="/usr/doc/e2fslibsg-dev/html-info/libext2fs_toc.html"
diff --git a/debian/attic/libs/comerr2g.files b/debian/attic/libs/comerr2g.files new file mode 100644 index 0000000..4f1f552 --- /dev/null +++ b/debian/attic/libs/comerr2g.files
@@ -0,0 +1,2 @@ +lib/libcom_err.so.?.* +lib/libcom_err.so.?
diff --git a/debian/attic/libs/control b/debian/attic/libs/control new file mode 100644 index 0000000..4205120 --- /dev/null +++ b/debian/attic/libs/control
@@ -0,0 +1,114 @@ +Source: e2fsprogs +Section: base +Priority: required +Maintainer: Yann Dirson <dirson@debian.org> +Standards-Version: 2.4.0.0 + +Package: e2fsprogs +Essential: yes +Depends: ${shlibs:Depends} +Conflicts: e2fsprogsg, dump (<< 0.4b4-4), quota (<< 1.55-8.1) +Architecture: any +Description: The EXT2 file system utilities. + EXT2 stands for "Extended Filesystem", version 2. It's the main + filesystem type used for hard disks on Debian and other Linux systems. + . + This package contains programs for creating, checking, and maintaining EXT2 + filesystems, and the generic `fsck' wrapper. + . + This release may break older versions of dump and quota. + +Package: comerr2g +Depends: ${shlibs:Depends} +Conflicts: e2fsprogs (<< 1.10-6), comerr2 +Architecture: any +Description: The Common Error Description library - shared libraries. + libcomerr is an attempt to present a common error-handling mechanism to + manipulate the most common form of error code in a fashion that does not + have the problems identified with mechanisms commonly in use. + . + It is mainly used by the EXT2-filesystem tools. + +Package: ss2g +Depends: ${shlibs:Depends} +Conflicts: e2fsprogs (<< 1.10-6), ss2 +Architecture: any +Description: "Sub-System" library for simple command-line interface parsing - shared libs + This package contains the shared libs to support command-line + interface parsers generated with the ssg-dev package. + . + It was originally inspired by the Multics SubSystem library. + +Package: e2fslibsg +Depends: ${shlibs:Depends} +Provides: ext2fs2g, e2p2g, uuid1g +Conflicts: e2fsprogs (<= 1.10-7) +Architecture: any +Description: The EXT2 file system shared libs. + EXT2 stands for "Extended Filesystem", version 2. It's the filesystem type + used for hard disks on Debian and other Linux systems. + . + This package contains shared libraries needed by the utility programs. + +Package: comerrg-dev +Section: devel +Priority: extra +Depends: ${libcdev:Depends}, comerr2g +Suggests: doc-base +Conflicts: e2fsprogs (<< 1.10-6), comerr-dev +Architecture: any +Description: The Common Error Description library - headers and static libraries. + libcomerr is an attempt to present a common error-handling mechanism to + manipulate the most common form of error code in a fashion that does not + have the problems identified with mechanisms commonly in use. + +Package: ssg-dev +Section: devel +Priority: extra +Depends: ${libcdev:Depends}, ss2g +Conflicts: e2fsprogs (<< 1.10-6), ss-dev +Architecture: any +Description: "Sub-System" library for simple command-line interface parsing - devel. files + This package includes a tool that parses a command table to generate + a simple command-line interface parser, the include files needed to + compile and use it, and the static libs. + . + It was originally inspired by the Multics SubSystem library. + +Package: e2fslibsg-dev +Section: devel +Priority: extra +Depends: ${libcdev:Depends}, e2fslibsg, comerrg-dev +Suggests: doc-base +Provides: ext2fsg-dev, e2pg-dev, uuidg-dev +Conflicts: e2fsprogs (<< 1.10-6), e2fslibs-dev +Architecture: any +Description: The headers and static libraries for ext2fs-aware tools-development. + EXT2FS stands for "Extended Filesystem", version 2. It's the filesystem + type used for hard disks on Debian and other Linux systems. + . + This package contains the headers and shared libraries needed to compile + ext2fs-aware programs. Only programmers that really manipulate + features specific to the ext2 filesystem will need this. Most + programmers will use the generic filesystem-independent interface + from libc. + . + It also contains dev files for 2 other libs (e2p and uuid) used by + the e2fsprogs, but which are not yet packaged all by themselves + because they lack documentation. They may also lack some support + files, by I can't really know until someone uses them... + . + libe2p is for user-level e2fsprogs commands. It's used by dumpe2fs, + chattr, and lsattr. Functions in libe2p typically have two + characteristics (a) don't require that block device containing the + filesystem be opened directly (functions in libext2fs do), and (b) + libe2p typically contains printf statements or parse user input, and so + have more internationalization issues. + . + libuuid generates and parses 128-bit universally unique id's (UUID's), + using a standard which is blessed by both Microsoft and DCE, and is + being proposed as an internet standard. See the internet-draft: + . + draft-leach-uuids-guids-01.txt + . + for more information.
diff --git a/debian/attic/libs/e2fslibsg.files b/debian/attic/libs/e2fslibsg.files new file mode 100644 index 0000000..c777084 --- /dev/null +++ b/debian/attic/libs/e2fslibsg.files
@@ -0,0 +1,3 @@ +lib/*.so.?.* +lib/*.so.? +usr/doc/e2fslibsg/*
diff --git a/debian/attic/libs/rules b/debian/attic/libs/rules new file mode 100644 index 0000000..3cf3c8d --- /dev/null +++ b/debian/attic/libs/rules
@@ -0,0 +1,182 @@ +#! /usr/bin/make -f +# -*- makefile -*- +# +# Invoke each target with `./debian/rules <target>'. All targets should be +# invoked with the package root as the current directory. +# +# The `binary' target must be run as root, as it needs to install files with +# specific ownerships. + +# Uncomment this to turn on verbose mode. +export DH_VERBOSE=1 + +package = e2fsprogs +ARCH = $(shell dpkg --print-architecture) + +# find the version for the main package, from changelog file +MAIN_VERSION = $(shell head -1 debian/changelog | cut '-d ' -f 2 | sed 's/[()]//g') +# find versions for libraries going into their own packages, from their Makefile.in's +COMERR_VERSION = $(shell grep ELF_VERSION lib/et/Makefile.in | cut '-d ' -f3) +COMERR_MAJOR = $(word 1,$(subst ., ,$(COMERR_VERSION))) +SS_VERSION = $(shell grep ELF_VERSION lib/ss/Makefile.in | cut '-d ' -f3) +SS_MAJOR = $(word 1,$(subst ., ,$(SS_VERSION))) + +topdir = $(shell pwd) +debdir = $(topdir)/debian +maindir = $(debdir)/tmp +builddir = $(topdir)/builddir +docdir = $(maindir)/usr/doc/$(package) + +SUBPACKAGES_DIRS = tmp e2fslibsg e2fslibsg-dev comerr$(COMERR_MAJOR)g comerrg-dev \ + ss$(SS_MAJOR)g ssg-dev + +installdoc = install -m 644 +installbin = install -m 755 + +ifeq ($(ARCH),alpha) +CCOPTS = -g -O2 -fsigned-char -DHAVE_NETINET_IN_H +LIBC-DEV = libc6.1-dev +else +CCOPTS = -g -O2 -fsigned-char +LIBC-DEV = libc6-dev +endif + +build: configured + dh_testdir + make -C $(builddir) + make -C $(builddir)/misc findsuper + cd doc && texi2html -split_chapter libext2fs.texinfo + cd lib/et && texi2html -split_chapter -expandinfo com_err.texinfo + touch build + +configured: + dh_testdir + mkdir -p $(builddir) + cd $(builddir) && CFLAGS="$(CFLAGS)" \ + ../configure --enable-elf-shlibs --enable-dynamic-e2fsck \ + --with-ccopts="$(CCOPTS)" + touch configured + +clean: + dh_testdir + rm -f build configured install + -make -C $(builddir) -i distclean + rm -rf $(builddir) + rm -f doc/libext2fs_*.html lib/et/com_err_*.html + dh_clean + +binary-indep: build + # no arch-independant debs. + +binary-arch: build + dh_testversion 0.56 # == 0.53 + fixes + dh_testdir -a + dh_testroot -a + dh_clean -a -k + dh_installdirs -a + + make -C $(builddir) install DESTDIR=$(maindir) + install -m 755 $(builddir)/misc/findsuper $(maindir)/sbin + # static libs and .h files + make -C $(builddir) install-libs DESTDIR=$(maindir) + install -m 644 $(builddir)/lib/ss/ss_err.h $(maindir)/usr/include/ss/ + +# fix and install compile_et script + sed s%$(topdir)/lib/et%/usr/share/comerr% \ + <$(builddir)/lib/et/compile_et \ + >$(debdir)/comerrg-dev/usr/bin/compile_et + chmod 755 $(debdir)/comerrg-dev/usr/bin/compile_et +# add support files for compile_et + install -m 644 lib/et/et_c.awk lib/et/et_h.awk \ + $(debdir)/comerrg-dev/usr/share/comerr/ + +# fix and install mk_cmds script + sed s%$(topdir)/lib/ss%/usr/share/ss% \ + <$(builddir)/lib/ss/mk_cmds \ + >$(debdir)/ssg-dev/usr/bin/mk_cmds + chmod 755 $(debdir)/ssg-dev/usr/bin/mk_cmds +# add support files for mk_cmds + install -m 644 lib/ss/ct_c.awk lib/ss/ct_c.sed \ + $(debdir)/ssg-dev/usr/share/ss/ + +# docs + mkdir -p $(debdir)/e2fslibsg-dev/usr/doc/e2fslibsg + ln -sf e2fslibsg $(debdir)/e2fslibsg-dev/usr/doc/e2fslibsg-dev + mkdir -p $(maindir)/usr/doc/e2fslibsg + ln -sf e2fslibsg $(maindir)/usr/doc/e2fsprogs + mkdir -p $(debdir)/comerrg-dev/usr/doc/comerr$(COMERR_MAJOR)g + ln -sf comerr$(COMERR_MAJOR)g $(debdir)/comerrg-dev/usr/doc/comerrg-dev + mkdir -p $(debdir)/ssg-dev/usr/doc/ss$(SS_MAJOR)g + ln -sf ss$(SS_MAJOR)g $(debdir)/ssg-dev/usr/doc/ssg-dev + dh_installdocs -a + + # HTML docs + install -d $(debdir)/e2fslibsg-dev/usr/doc/e2fslibsg-dev/html-info/ + install -p $(topdir)/doc/libext2fs_*.html \ + $(debdir)/e2fslibsg-dev/usr/doc/e2fslibsg-dev/html-info/ + install -d $(debdir)/comerrg-dev/usr/doc/comerrg-dev/html-info/ + install -p $(topdir)/lib/et/com_err_*.html \ + $(debdir)/comerrg-dev/usr/doc/comerrg-dev/html-info/ + + # texinfo docs + install -p $(topdir)/doc/libext2fs.texinfo \ + $(debdir)/e2fslibsg-dev/usr/doc/e2fslibsg/libext2fs.texi + install -p $(topdir)/lib/et/com_err.texinfo \ + $(debdir)/comerrg-dev/usr/doc/comerr2g/com_err.texi + + # doc-base support + install -d $(debdir)/e2fslibsg-dev/usr/share/doc-base/ + install -p -m 644 $(debdir)/libext2fs.docbase \ + $(debdir)/e2fslibsg-dev/usr/share/doc-base/libext2fs + install -d $(debdir)/comerrg-dev/usr/share/doc-base/ + install -p -m 644 $(debdir)/com_err.docbase \ + $(debdir)/comerrg-dev/usr/share/doc-base/com_err + + # examples + dh_installexamples -a + + # dh_installmanpages still makes a mess as of 0.54 (see below dh_movefiles) + install -p $(topdir)/lib/et/compile_et.1 $(maindir)/usr/man/man1/ + install -d $(maindir)/usr/man/man3/ + install -p $(topdir)/lib/et/com_err.3 $(maindir)/usr/man/man3/ + ln -s e2fsck.8 $(maindir)/usr/man/man8/fsck.ext2.8 + ln -s mke2fs.8 $(maindir)/usr/man/man8/mkfs.ext2.8 + + dh_movefiles -a + # cleanup empty dirs + cd $(maindir) && rmdir usr/man/cat? bin lib usr/include/* usr/include \ + usr/info usr/lib usr/man/man3 usr/doc/e2fslibsg + +# dh_installmenu -a + + # broken + useless in 0.52 + # dh_installmanpages -a + + dh_undocumented -a + + dh_installchangelogs -pe2fslibsg -pcomerr$(COMERR_MAJOR)g -pss$(SS_MAJOR)g ChangeLog + + dh_strip -a + dh_compress -a + dh_fixperms -a + + echo "libcdev:Depends=$(LIBC-DEV)" > debian/comerrg-dev.substvars + echo "libcdev:Depends=$(LIBC-DEV)" > debian/ssg-dev.substvars + echo "libcdev:Depends=$(LIBC-DEV)" > debian/e2fslibsg-dev.substvars + + dh_installdeb -a + LD_LIBRARY_PATH=$(builddir)/lib:/lib:/usr/lib \ + dh_shlibdeps -a + dh_gencontrol -u '-isp' -pe2fsprogs -pe2fslibsg -pe2fslibsg-dev + dh_gencontrol -u '-isp' -pcomerr$(COMERR_MAJOR)g -pcomerrg-dev \ + -u '-v$(COMERR_VERSION)-$(MAIN_VERSION)' + dh_gencontrol -u '-isp' -pss$(SS_MAJOR)g -pssg-dev \ + -u '-v$(SS_VERSION)-$(MAIN_VERSION)' + dh_makeshlibs -a +# dh_du -a + dh_md5sums -a + dh_builddeb -a + +binary: binary-indep binary-arch + +.PHONY: binary binary-arch binary-indep clean checkroot
diff --git a/debian/attic/libs/ss2g.files b/debian/attic/libs/ss2g.files new file mode 100644 index 0000000..5b717cb --- /dev/null +++ b/debian/attic/libs/ss2g.files
@@ -0,0 +1,2 @@ +lib/libss.so.?.* +lib/libss.so.?
diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..9506939 --- /dev/null +++ b/debian/changelog
@@ -0,0 +1,3723 @@ +e2fsprogs (1.42.13-1) unstable; urgency=low + + * New upstream version + * NMU acknowledge (Closes: #778948) + * Fixed a bug which could cause e2fsck to corrupt Hurd file systems. + (Closes: #760275) + * Fixed a deadlock which occurs when using systemd and e2fsck.conf's + logging feature. (Closes: #775234) + * Fixed a bug which could cause programs using libext2's inode table + scanning functions from crashing on certain corrupted file systems. + (Closes: #773795) + * Fixed dumpe2fs so it won't crash if the user doesn't specify a block + device (file system). (Closes: #764293) + * Fixed e2fsck so if it notices unexpected HTREE blocks in pass 2, it + will report the correct directory inode containing the inconsistency. + * If e2fsck fails to grow the dir_info structure due realloc(3) not + having enough memory, it will now fail with explanatory message + instead of staggering on failing with a confusing internal error + messages. + * The tune2fs program will zero out the superblock journal backup + information when removing a journal from a file system. + * The mke2fs program now enables the large_file feature by default. + * Fixed a bug which could cause badblocks to crash if there are millions + and millions of bad blocks. + * Fixed some use-after-free bug in resize2fs and e2fsck. + * Fixed some bigendian bugs that had crept into both indirect and extent + handling inside libext2fs. + * Updated/fixed various man pages. + * Update Esperanto, German, and Spanish translations. Added Danish + translation. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 17 May 2015 20:38:27 -0400 + +e2fsprogs (1.42.12-1.1) unstable; urgency=high + + * Non-maintainer upload by the Security Team. + * Fix CVE-2015-1572: incomplete fix for CVE-2015-0247 (closes: #778948). + + -- Michael Gilbert <mgilbert@debian.org> Sun, 22 Feb 2015 01:50:57 +0000 + +e2fsprogs (1.42.12-1) unstable; urgency=low + + * New upstream version + * Fix various e2fsck bugs when trying to repair bigalloc file systems. + * E2fsck can now repair a file system with an overly large + s_first_meta_bg field, which had previously caused all e2fsprogs + programs to crash when trying to open such a file system. + * Fix e2fsck so that it can correctly fix a number of rare file system + corruptions that were discovered when using a file system fuzzer. + * Fix e2fsck so it does not try to write back block group descriptors + if they have not been modified. + * The mke2fs program will now place metadata blocks in the last + flex_bg so they are contiguous. This reduces free space + fragmentation in a freshly created file system, as well as allowing + mke2fs commands which request extremely large flex_bg size to succeed. + * Mke2fs now creates hugefiles more efficiently (with fewer extent + tree blocks). + * Fix a 32/64-bit overflow bug that could cause resize2fs to loop + forever. + * Reduce the memory consumption of resize2fs for very large file + systems. + * Fix a bug that could cause resize2fs to create a corrupted file + system when shrinking a very large file system (typically > 16TB) + that had been previously grown using resize2fs. (Closes: #756922) + * Fix tune2fs updating UUID's when manipulating file systems with + external journals (both the file system and journal UUID). + * Fix tune2fs so it can remove an external journal for file systems + with a 1k block size. + * Add a new debugfs command, "inode_dump", which prints the inode in + hex and ASCII format. + * The debugfs command "set_inode_field" will now automatically + allocate blocks for indirect blocks and extent tree blocks. + * Fix debugfs's "set_inode_field" so can properly handle + "block[IND|DIND|TIND]". + * The debugfs "rdump" command will now take multiple source arguments. + * Fix debugfs's argument parsing for the freefrag command. + * Fixed a double close(2) bug in "rdump" and "rdump -p". + * Fix filefrag to properly handle using the FIBMAP ioctl (with -B). + * e4defrag will now defrag backwards-allocated files + * Clarified messages that were confusing users in debugfs, e2fsck, + mke2fs, and resize2fs (Closes: #758029, #757543, #757544) + * Dumpe2fs will now complain if extra arguments are given to it. + (Closes: #758074) + * Update/clarify various man pages (Closes: #726760) + * Update Czech, Dutch, French, Polish, Spanish, Sweedish, Ukrainian, + and Vietnamese translations + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 29 Aug 2014 08:50:48 -0400 + +e2fsprogs (1.42.11-2) unstable; urgency=low + + * Don't try to build lib/ext2fs/tst_ext2fs unless running "make + check"; this fixes a MIPS FTBFS problem because mips has a special + no-pics build needed for bootloaders where we only build libext2fs + but not libss or other libraries (Closes: #754605) + * Update French translation + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 13 Jul 2014 16:18:27 -0400 + +e2fsprogs (1.42.11-1) unstable; urgency=medium + + * New upstream version + * NMU acknowledge (Closes: #752107) + * mke2fs can now create hugefiles which are aligned to the beginning + of the disk (instead of relative to the beginning of the partition), + controlled via a mke2fs.conf configuration parameter. + * Fix a bug which caused e2fsck to abort a journal replay on a file + system with bigalloc enabled. (Closes: #744953) + * Fix mke2fs so it more correctly handles large flex_bg counts + * Mke2fs will check the kernel version number and not just the sysfs + feature flag to determine whether it is safe to enable lazy + inode table initialization, so it won't get faked out if the ext4 is + compiled as a mdoule which hasn't happened to be loaded yet. + * E2fsck will now automatically fix a last mount time or last write time + which is in the future in preen mode. + * Mke2fs will now check the file system revision number requested by the + command line, and reject it if it is too large. + * If filefrag runs into an error, it will continue processing the rest + of the files specified on thec ommand line, but then exit with an + error code. + * Filefrag now prints some additional new flags (such as + FIEMAP_EXTENT_ENCODED), and print unknown flags as hex values. + * Fixed support in filefrag for files with > 2**32 blocks on 32-bit + platforms. + * Fixed a file descriptor leak in debugfs when copying files. + * Add Esparanto and Ukrainian translations, and update Czech, Dutch, + French, German, Italian, Polish, Sweedish, and Vietnamese translations. + * Fixed cross-compilation support. (Closes: #753375) + * Update/fix various man pages + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 9 July 2014 23:43:27 -0400 + +e2fsprogs (1.42.10-1.1) unstable; urgency=medium + + * Non-maintainer upload. + * Add patch from upstream git that fixes creating filesystems in files + larger than 2GB on 32 bit architectures (Closes: #752107) + + -- Hilko Bengen <bengen@debian.org> Sat, 21 Jun 2014 12:57:25 +0200 + +e2fsprogs (1.42.10-1) unstable; urgency=medium + + * New upstream version + * The mke2fs program no longer requires a force (-F) option when + when creating a file system in a regular file, since this is a very + common use case when managing virtual machine images + * The mke2fs program will now ask for confirmation before wiping out a + pre-existing file system, partition label, or physical volume + * Fix e2fsck so that it properly handles an inconsistent quota inode. + Previously the quota inode could be completely corrupted, and + missing quota records could be not noticed + * Fix mke2fs so if packed metadata blocks are enabled that the block + group checksum are set correctly + * Debugfs has new commands to allow the quota inode to be queried directly + * Tune2fs will allow removal of dirty journal with two "-f" options + (Closes: #559301) + * Fixed some off-line resize2fs bugs when relocating metadata blocks + when growing or shrinking bigalloc file systems + * Fixed resize2fs's calculation of the minimum required file system + size. This allows resize2fs -M to shrink the file system more + aggressively + * Fixed resize2fs to properly handle shrinking a very large and empty + file system to a very very small size + * Fixed e4defrag to work with 64-bit and bigalloc file systems + * Fixed e2fsck to not issue a large number of very scary (but + harmless) corruption messages when checking very large file systems + when the file system has more inodes than the number of seconds + since January 1, 1970. + * E2fsck will now check the whole file system if file system problems + are detected durings its initial "pass 0" sanity check + * Filefrag now prints the "shared extent" flag which is used by some + file systems such as btrfs + * The mke2fs program would previously correctly omit the resize_inode + feature when creating a file system > 16TB when the fs size was + determined automatically. It will now also do the right thing when + the user explicitly specifies the file system size. + * The message printed by logsave is now much less scary (Closes: #468821) + * Fix spelling typo in the package descriptions + * Update Czech, Dutch, French, German, Polish, Spanish, Sweedish, and + Vietnamese translations (Closes: #703048) + * Update/fix various man pages + * Fix debian/rules compatibility problem with GNU make 4.0 + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 18 May 2014 22:54:38 -0400 + +e2fsprogs (1.42.9-3) unstable; urgency=medium + + * Add the ability for mke2fs to create hugefiles + * Add support for the sparse_super2 compat feature + * Mke2fs can now force all of the metadata blocks to be at the + beginning of the file system + * Fix loopback mount detection (Closes: #497984) + * Add support to mke2fs to create a file system at an offset + (Closes: #417385) + * Mention badblocks in the package description (Closes: #718725) + * Update/fix various man pages (Closes: #719184, #719189) + * Improve e2fsck's "superblock corrupt" message (Closes: #719185) + * Miscellaneous Coverity clean ups + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 04 Feb 2014 22:17:22 -0500 + +e2fsprogs (1.42.9-2) unstable; urgency=low + + * Fix lintian warning: debian-changelog-has-wrong-weekday + * Fix lintian warning: non-standard-dir-perm by using dh_strip's + --dbg-package option instead of manually managing the debug files + * Fix printf type format mismatch in e2image + * Improved debugfs's error reporting when parsing block numbers + * Use consistent configure options across the multiple e2fsprogs + builds; this means that e2fsck.static will now use the blkid library + shipped with util-linux, instead of the internal one shipped with + the e2fsprogs sources. + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 30 Dec 2013 16:56:50 -0500 + +e2fsprogs (1.42.9-1) unstable; urgency=low + + * New upstream version + * NMU ack (Closes: #698879) + * Fix cross-build support (Closes: #721365) + * mke2fs will detect an attempt to create a file system on a + loop-mounted image file + * Fixed a large number of bugs in resize2fs, e2fsck, debugfs, to + handle bigalloc and 64-bit file systems. + * Tune2fs will no longer allow changing the uuid on a mounted file + system with the uninit_bg feature enabled. + * E2fsck will properly allocate a new extent tree block in the rare + case where one is needed when rehashing an extent-mapped directory. + * Mke2fs wil now properly set the LARGE_FILE feature when creating a + journal > 2GB. + * Debugfs will now correctly handle free a range of inodes using the + freei command. + * E2fsck will no longer complain if an external journal was exactly + 2**32 blocks. + * E2fsck will not longer try to add a missing lost+found directory + when run in read-only mode. + * Fixed some buffer overrun bugs when creating standard e2image files + * Mke2fs will not try to set both the meta_bg and resize_inode feature + when the extended option "-E resize=NNN" is specified by the user. + * Dumpe2fs will no longer abort when trying to print the journal + information from an e2image-created image file. + * Debugfs's "write" command can now create a sparse files + * Debugfs can now support a command line which is up to 8k long + * E2image will refuse to create a raw or qcomw image using a mounted + file system unless the -f option is given. + * E2image has been made more useful for efficiently copying file + systems using the -ra options. New options to help with this use + case that were added: -o, -O, -p, and -c. + * Fixed a regression introduced in 1.42.8 which would cause e2fsck to + erroneously report uninitialized extents past i_size to be invalid. + * Fixed cases where resize2fs could corrupt a file system, especially + when shrinking a file system. (Closes: #660793) + * Fixed resize2fs and e2fsck to not crash when operating on a file + system with the MMP feature enabled. + * Fixed debugfs's write command to properly create a zero-length file + (instead of creating an invalid inode). + * Fixed e2fsck to not crash when trying to delete an invalid + extent-mapped symlink. + * Improved debugfs's help texts + * Fixed a potential integer overflow problem in e2freefrag + (Closes: #718205) + * The config.guess and config.sub files have been updated to the + latest to help with the ppcle port. (Closes: #732076) + * Updated/fixed various man pages. (Closes: #586218, #669730, + #698076, #731329) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 28 Dec 2013 23:18:36 -0500 + +e2fsprogs (1.42.8-1) unstable; urgency=low + + * New upstream version + * Work around Debian Bug #712530 (Closes: #708307) + * Fix e2fsck so it can check a read-only root file system with an + external journal. (Closes: #707030) + * Fix off-line resizing of file systems with flex_bg && !resize_inode + (Closes: #696746) + * Change mke2fs so that it does not set the root directory to the real + uid/gid of the mke2fs process. Add the extended option root_owner to + override this behavior. + * If an invalid journal size is given to mke2fs, it will now complain + and exit sooner. + * Fix resize2fs when shrinking file systems to make sure that bitmap + blocks aren't left outside the bounds of the shrunken file system. + This could happen with flex_bg file systems that were grown using + the old online resizing algorithm. + * E2fsck will now detect and repair corrupted extent trees which contain + invalid extents at the end of the extent tree leaf block. + * E2fsck will now longer complain about zero length extended attribute values. + * Fix a regression introduced in e2fsprogs v1.42 which caused e2image -s + to crash. + * Add safety check so tune2fs will not attempt to set the inode size to + be larger than the block size. + * Enhance chattr to allow clearing the extent flag if the kernel allows it + * Fix e2image with large (> 32-bit) file systems (Closes: #703067) + * Mke2fs will not give warnings about the bigalloc and quota options in + quiet mode. + * Debugfs was erroneously giving spurious error messages for certain + extent_inode subcommands which take arguments (split_node, + replace_node, and insert_node). This has been fixed. + * Fix the parsing of the 's' (sectors) in parse_num_blocks2, which among + other programs is used by mke2fs. + * Fix texinfo incompatibilities (Closes: #712365) + * Updated/fixed various man pages (Closes: #712429, #712430, #707609) + * Update German translation + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 20 Jun 2013 23:09:25 -0500 + +e2fsprogs (1.42.7-1) unstable; urgency=low + + * New upstream version + * Add warning indicating that the quota and bigalloc features are + still under development. + * Added new options to filefrag to be consistent with the version from + Lustre + * Optimized e2fsck's CPU utilization + * Fixed e2fsck so it detects and fixes inconsistencies in the interior + nodes of an inode's extent tree + * Fixed a potential memory corruption failure in e2fsck's error path if + the call to ext2fs_open2() fails. + * Fixed e2fsck if its logging function is enabled in e2fsck.conf, and + the resulting file name for the log file is longer than 100 bytes, + that it properly handles this situation instead of crashing. + * E2fsck will now report the amount of memory that it attempted to + allocate when a memory allocation request fails, to make it easier to + track down the problem. + * Fixed a bug in resize2fs which could cause severe file system + corruption when growing an ext4 file system which was formatted with + fewer-than-normal reserved gdt blocks + * Fixed resize2fs to be able to handle off-line resizes of file + systems with the flex_bg feature and without any reserved gdt + blocks or if the file system did not have the resize_inode feature + * Further optimize resize2fs so it doesn't use quite as much CPU when + resizing very large file systems. + * Fixed 32-bit overflow bugs which could cause resize2fs to fail and + possibly corrupt the file system while resizing 64-bit file systems. + * Fixed a big which could cause resize2fs to corrupt bigalloc file systems. + * Fix a crash while mke2fs is parsing "-E resize=NNN" with the 64bit + file system feature enabled + * Added better error checking to mke2fs to check for invalid + parameters when creating bigalloc file system. + * When creating bigalloc filesystems, the -g option to mke2fs will now + specify the number of clusters per block group. + * Added the "symlink", "zap_block", "block_dump", and "extent_open" + commands to debugfs + * Fixed debugfs's htree command so that all its messages are sent + through the pager. + * Fixed debugfs's dump_file and cat functions so they work correctly + on file systems with a block size greater than 8k. + * Fixed mke2fs's handling of the mmp_update_interval option + * Fixed e2freefrag so it works on 64-bit file systems, and so it uses + much less memory. + * E2image can now include all data blocks in the e2image output + file when the user specifies the -a option. + * Fixed debugfs's mknod command so that it updates the block group + statistics + * Document the bigalloc feature in the mke2fs man page. + (Closes: #669730) + * Update Czech, Dutch, French, German, Polish, Sweedish, and + Vietnamese translations + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 21 Jan 2013 21:52:58 -0500 + +e2fsprogs (1.42.6-1) unstable; urgency=low + + * New upstream version + * Fix build dependencies to avoid requiring dc, and to allow + cross-building to work (Closes: #677497) + * Updated/fixed various man pages + * Mke2fs will now update its progress indicators at most once a second + to avoid overwhelming serial consoles. + * Resize2fs will support lazy_itable_init, speeding up off-line growth + of uninit_bg file systems. + * Resize2fs now supports on-line resizing 64-bit file systems beyond + 16TB. A number of bugs in resize2fs which prevented this have been + fixed. + * Resize2fs now correctly handles resizing 32-bit file systems to 16TB. + * Fixed a potential segfault in e2fsck when there is an I/O error + while reading the superblock. + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 21 Sep 2012 12:14:41 -0400 + +e2fsprogs (1.42.5-1.1) unstable; urgency=low + + * Non-maintainer upload. + * e2fsck-static, e2fsprogs: let preinst remove a symbolic link in + /usr/share/doc, that should have been replaced with a directory since + 1.39+1.40-WIP-2006.10.02+dfsg-1. (Closes: #698879). + + -- Nicolas Boulenguez <nicolas@debian.org> Fri, 22 Feb 2013 23:14:59 +0100 + +e2fsprogs (1.42.5-1) unstable; urgency=low + + * New upstream version + * Mark the e2fsprogs package as Multi-Arch: foreign, so if a package + foo:i386 depends on e2fsprogs and is installed on an amd64 system, + the native e2fsprogs will satisfy the dependency. (Closes: #678395) + * Fix a fd leak which could cause logsave (and hence a boot-time rc + init script) to hang (Closes: #682592) + * Fix a problem if e2fsck where if the root file system is mounted + read-only, e2fsck would not clear an error indication in the journal + superblock. Combined with a kernel bug, this would cause the e2fsck + to check the file system after every single boot + * Fixed filefrag so it would not seg fault on virtual filesystems such + as /proc: e.g., "filefrag /proc/partitions" + * Fix filefrag so that it correctly reports the number of extents + * Fixed a bug which caused "mke2fs -N 256 -t ext4 /tmp/foo.img 256m" + to write blocks out until /tmp filled + * Fixed a bug in how e2fsck would uniquify directory entry names + * Change e2fsck so it will allow file systems mounted read-only to be + checked with the -f option. + * Fix e2fsck so that the file system is marked as containing an + error if the user chooses not to fix the quota usage information. + * Fix tune2fs so that it correctly removes the quota feature when + the last quota inode is removed. + * Fix tune2fs so that after removing a quota inode, the block bitmap + is updated; otherwise, e2fsck would complain after running 'tune2fs + -O ^quota <dev>'. + * Fix tune2fs so that when converting a file system from using legacy + quota files to the new quota file system feature with hidden quota + files, the accounting for these files is handled correctly so that + e2fsck doesn't complain. + * The e4defrag program now allows device symlinks, such as + /dev/mapper/testvg-testlv, instead of insisting on less + human-friendly names such as /dev/dm-2 + * Updated/fixed various man pages (Closes: #680114) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 29 Jul 2012 19:59:56 -0400 + +e2fsprogs (1.42.4-3) unstable; urgency=medium + + * Add the -C option to chattr's usage message + * Fix e2fsprogs so it is blhc (build log hardening check) clean. This + fixed e2fsck.static which previously was not getting built with the + security hardening flags. + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 13 Jun 2012 16:03:24 -0400 + +e2fsprogs (1.42.4-2) unstable; urgency=medium + + * Fix FTBFS problem on the hurd and freebsd platforms + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 12 Jun 2012 18:26:40 -0400 + +e2fsprogs (1.42.4-1) unstable; urgency=medium + + * New upstream version + * Fix 64-bit block number bugs in e2fsck, dumpe2fs, and debugfs which + could corrupt file systems + * Fixed e2fsck's handling of how errors propagate from the journal to + the file system superblock + * Fixed a false positive complaint from e2fsck if all of the extents + in the last extent block are uninitialized and located after the + end of the file. + * dumpe2fs will display the journal's error indicator in the + superblock if it is set + * Fixed a bug which caused e2fsck to incorrectly use O_EXCLUSIVE in + some corner cases. + * Fix truncation of extent-mapped inodes in e2fsck and libext2fs + * Fixed i_blocks accounting in bigalloc file systems. + * Add support for btrfs's No_COW flag to lsattr and chattr + * Debugfs interprets the date strings of the form "@ddd" as ddd + seconds after the epoch + * Updated/fixed various man pages (Closes: #674453, #674694) + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 12 Jun 2012 18:20:55 -0400 + +e2fsprogs (1.42.3-1) unstable; urgency=low + + * New upstream version + * Fix bugs on 32-bit systems which could corrupt > 16TB file systems + * Quiet complaints in e2fsck when the total free blocks or inodes are + incorrect in the superblock after an system crash, since we don't + update nor depend on the superblock summaries at each commit boundary + * Fixed support for (hidden) quota files built into ext4; in + particular, don't rewrite the quota inode unless the quotas are + inconsistent + * Optimized reading and writing bitmaps if direct I/O was enabled + * Update Czech, Dutch, French, German, Polish, Sweedish, and + Vietnamese translations + * Fixed incorrect indentation in tune2fs man page + * Update debian policy compliance to 3.9.3 + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 14 May 2012 14:43:09 -0400 + +e2fsprogs (1.42.2-2) unstable; urgency=low + + * Fixed e2fsck.conf's man page (Closes: #646963) + * Fixed 32-bit binary compatibility problem for the libext2fs shared + library introduced in 1.42.2 + * mke2fs will no longer fail if the /etc/mtab file is not present + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 09 Apr 2012 14:54:33 -0400 + +e2fsprogs (1.42.2-1) unstable; urgency=low + + * New upstream version + * Fixed various man pages (Closes: #665427) + * Speed up resize2fs for large file systems (Closes: #663237) + * Be less strict about the EXT4_EOFBLOCKS_FL flag (which will + eventually be going away in the ext4 file system format) + * Teach mke2fs to use direct I/O if the -D option is given + * Print errors returned by ext2fs_open2() and ext2fs_check_desc() so + we can more easily diagnose memory allocation failures caused by + insufficient memory and abort on memory allocation failures + * E2fsck can now write log files containing the details of the + problems that were found and fixed directly. + * E2fsck can now limit the number of messages issued and printed on + the console + * The dumpe2fs, debugfs, and tune2fs now use rbtree bitmaps, which + cause them to use much less memory for large file systems. + * E2fsck will now check for zero-length extents, since older kernels will + OOPS if they comes across one + * Fix e2fsck's discard behaviour so it does not discard too many + blocks, and it will not use discard if the device advertises + that discard does not persistently zero data. Also, if e2fsck is + run in read-only mode, do not try to discard data. + * Fix mke2fs -S so it does not corrupt the first block group's + information. + * Add pointer for e2fsprogs-udeb to libcomerr2.shlibs (Closes: #665885) + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 27 Mar 2012 15:55:57 -0700 + +e2fsprogs (1.42.1-2) unstable; urgency=low + + * Fix the fact that dpkg-buildflags was being ignored due to a + bash'ism in debian/rules. + * Check the new /sys/class/power_supply/AC/online since + /proc/acpi/ac_adapter/... is deprecated and may not be present on + newer kernels. + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 20 Feb 2012 19:12:20 -0500 + +e2fsprogs (1.42.1-1) unstable; urgency=low + + * New upstream release + * dpkg-buildflags is now used if it is present. This allows Debian + Wheezy to build with security hardened build flags. (Closes: #654457) + * mke2fs and e2fsck now use much less memory for large file systems + * Fixed mke2fs -S so it can be usefully used as a last ditch recovery + command when for ext4 filesystems that have the uninit_bg feature enabled. + * The mke4fs argv[0] is now recognized by mke2fs. + * Fixed usage and help messages for mke2fs. + * Eliminated spurious bad block group checksum warnings when e2fsck + falls back to using the backup group descriptors. + * Debugfs's ncheck command is now much more useful when used to + diagnose badly corrupted file system. Added a new -c option. + * Fixed bug in e2image which could cause it to fail to set i_size + correctly if the last hole in the file is an exact multiple of a + megabyte. + * Fixed a bug with resize2fs where for 1k and 2k file systems, the + minimum file size used for resize2fs -M could be a block too small. + * Fixed the badblocks program to honor the -s flag when in read-only -t + mode. (Closes: #646629) + * Update Czech, Dutch, French, Polish, and Swedish translations + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 17 Feb 2012 15:07:13 -0500 + +e2fsprogs (1.42-1) unstable; urgency=low + + * New upstream release + * Fixed hurd FTBFS (Closes: #649689) + * Optimized e2fsck speed on large file systems when using [scratch_files] + * Fixed e2fsck handling of blocks claimed by multiple inodes in + bigalloc file systems + * Fixed e2fsck's calculation of max file size for non-extent based + files when huge_file is enabled + * Update Czech and Swedish translations + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 29 Nov 2011 15:50:07 -0500 + +e2fsprogs (1.42~WIP-2011-11-20-1) unstable; urgency=low + + * New upstream release + * Fix error checking so resize2fs works when using a 32-bit userspace + and a 64-bit kernel (Closes: #644989) + * e2fsck now returns additional status bits in its exit code if it + aborts early in the e2fsck run + * Fix potential stack overflow in debugfs + * Avoid an infinite loop in ext2fs_find_block_device() if there are + symlink loops in /dev caused by a buggy udev + * Fix test failures on big-endian systems + * Fix gcc -Wall complaints + * Add freefrag and e2freefrag commands to debugfs + * Add a read-only, metadata-only debugfs command called rdebugfs + * Improve first-class quota support + * Fix bigalloc support in e2freefrag + * Clean up mmp handling + * Fix a regression which caused mke2fs to not work correctly on files + > 2GB. (Closes: #647245) + * Fix a namespace leak in libext2fs (tdb_null) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 20 Nov 2011 21:32:49 -0500 + +e2fsprogs (1.42~WIP-2011-10-16-1) unstable; urgency=low + + * New upstream release + * Fix online resizing with resize2fs (Closes: #644989) + * Fix bug which caused shrinking an empty file system file system to + its minimal size to sometimes fail. + * Don't look at the high 16 bits of i_file_acl if the 64-bit feature + is not enabled; this fixes a Hurd compatibility field since this is + used for the high 16 bits of i_mode on Hurd. + * Update Sweedish, Polish, French, German, and Czech translations + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 16 Oct 2011 22:07:03 -0400 + +e2fsprogs (1.42~WIP-2011-10-09-1) unstable; urgency=low + + * New upstream release + * Fixed infinite loop in filefrag (Closes: #644792) + * Fixed various spelling and translation problems + * Fixed various man pages + * Fixed 64-bit block numbers in e2fsck's journal replay + * Fixed mipsel FTBFS that was fixed for mips + * Update Sweedish, French, and Czech translations + * Convert to debian source 3.0 (quilt) format + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 09 Oct 2011 22:24:31 -0400 + +e2fsprogs (1.42~WIP-2011-10-05-2) unstable; urgency=low + + * Fix portability issues with non-Linux platforms and for the mips + platform, which does some really strange things vis-a-vis + 32/64-bit support without actually having a 64-bit version of + the architecture (Closes: #644502) + * Fix dependency problem which causes the newer version of libcom_err2 + to get pulled in when upgrading to e2fsprogs, which needs the new + interface exported by libcom_err2. (Closes: #644425, #644584) + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 07 Oct 2011 18:27:06 -0400 + +e2fsprogs (1.42~WIP-2011-10-05-1) unstable; urgency=low + + * Update translations: German (Closes: #520985) + * Fixed usage and error text for mke2fs -C option + * Updated e2fsprogs.pot file for translators + * Added support for internationalized error strings for libcom_err + * Fixed various portability nits that were causing FTBFS problems on + Hurd and FreeBSD + * Added "big" and "huge" types to mke2fs.conf, since they are needed + for very large file systems + * Fixed on-line resizing which had been broken in the 1.42 series + (Closes: #451388) + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 05 Oct 2011 02:10:53 -0400 + +e2fsprogs (1.42~WIP-2011-10-01-2) unstable; urgency=low + + * Update translations: French, German (Closes: #620659) + * Fix compilation problems in hermetic environments + * Fix on-line resizing in resize2fs (Closes: #451388) + * Add definitions for "big" and "huge" filesystems to /etc/mke2fs.conf + * Fix mke2fs when there are more than 2**32 block groups + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 04 Oct 2011 00:04:25 -0400 + +e2fsprogs (1.42~WIP-2011-10-01-1) unstable; urgency=low + + * New upstream release + * Avoid unnecessary reboots when checking the root fs in some special cases + * Fix an off-by-one error in filefrag -v's output + * Make filefrag display the number of contiguous (not physical) + extents (Closes: #631498) + * Clarify the mke2fs.conf.5 man page (Closes: #634883) + * Add a hurd-specific mke2fs.conf file (Closes: #629355) + * mke2fs will set s_max_mnt_count to -1 instead of 0 by default to + work around a bug in pre-3.0 kernels which caused a spurious + message to be printed when the file system was mounted (Closes: #632637) + * Fixed portability problems which was causing build failures on + non-Linux/non-x86 systems. + * Verify that the bad block inode looks sane before trusting it, to + avoid it causing more harm than good. + * Fixed the debian/rules file so that it build successfully if + DEB_BUILD_OPTIONS contains "nostrip" (Closes: #627535) + * Fixed some big-endian bugs in the MMP code + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 30 Sep 2011 22:33:41 -0400 + +e2fsprogs (1.42~WIP-2011-09-25-1) unstable; urgency=low + + * New upstream release + * Fix FTBFS on big-endian architectures (Closes: #641838) + * Add support for multiarch (Closes: #632169) + * Clarify and update debian/copyright file (Closes: #614662) + * Add support for Multi-Mount Protection (MMP) + * Allow tune2fs to remove the external journal if the device is not found + * Updated/clarified man pages (Closes: #642193) + * Fix a potential FTBFS caused by overly long compile lines (Closes: #629883) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 25 Sep 2011 01:28:34 -0400 + +e2fsprogs (1.42~WIP-2011-09-16-1) unstable; urgency=low + + * New upstream release + * Added support for the integrated quota feature + * Improved 64-bit and bigalloc support + * Mke2fs and tune2fs now allows setting the stride and stripe width to zero + * Fixed tune2fs's mount options parsing (Closes: #641667) + * Fixed an ABI compatibility problem which broke the dump program + (Closes: #636418) + * Resize2fs has forward compatibility for a new on-line resize ioctl + for > 16TB file systems. + * Fixed a (very hard to hit) bug that could cause e2fsck to crash in + pass 1 or pass 2 + * Debugfs has a new 'blocks' command + * Mke2fs now gives a warning if the auto-detected block size exceeds + the page size + * Mke2fs and e2fsck now tries to use the punch hole command as a + "discard" when operating on normal files + * Mke2fs will not try to do any discard operations if -n is specified + on the command line + * Updated/clarified man pages (Closes: #639411) + * Fixed parsing of MNTOPT_ options for tune2fs and debugfs (Closes: #641667) + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 16 Sep 2011 10:33:59 -0400 + +e2fsprogs (1.42~WIP-2011-07-02-1) unstable; urgency=low + + * New upstream release + * Add support for 64-bit file systems + * Add support for bigalloc file systems + * Fixed an e2fsck bug which caused "*** FILE SYSTEM WAS MODIFIED ***" + without an explanation of what was fixed. + * E2fsck will no longer attempt to clone an extended attribute block + in pass1b handling if the file system does not support extended + attributes. + * E2fsck will be more careful accidentally asking the user to continue + if the file system is mounted, so that an escape sequence won't + cause a false positive. (Closes: #619859) + * E2fsck now uses less cpu time in pass 5 + * E2fsck will no longer segault when a corrupted file system has a bad + extent, and removing it leads to a block needing to be deallocated. + * E2fsck now supports an extended "discard" option which will cause + e2fsck to attempt discard all unused blocks after a full check + * The e2image program now supports the qcow2 format, a more efficient + way of capturing file system metadata snapshots. + * Mke2fs now supports the [devices] stanza in mke2fs.conf. + * Mke2fs now supports the reserved_ratio relation in mke2fs.conf. + * Mke2fs now creates extent-mapped directories for the root and + lost+found directories. + * Mke2fs will skip zero'ing the journal if the extended option + "lazy_journal_init" is specified. + * Mke2fs will now create file systems that enable user namespace + extended attributes and with time- and mount count-based file + system checks disabled. + * Mke2fs will not set a stride or strip size of one block based on + block bevice attributes obtained from sysfs. + * Mke2fs now displays a progress report during the discard process. + * Mke2fs now handles extreme file system parameters correctly which + previously caused the inodes per group to drop below 8, leading + to a segfault. + * Debugfs's icheck will now correctly find inodes which use the + searched-for block as an extended attribute block. + * Debugfs now has a new "punch" command which remove blocks from the + middle of an inode. + * The badblocks program now correctly recovers from I/O errors when + direct I/O is being used. The badblocks command now also + supports a -B option which forces the use of buffered I/O, and + the -v option will provide a more detailed breakdown of read, + write, and failed comparison errors. + * Added e4defrag tool which uses the EXT4_IOC_MOVE_EXT ioctl. + * Added support for journals larger than 2GB. + * Support using both hard links and symlinks when installing e2fsprogs. + * Add overflow checking to tune2fs -i's fsck interval, which must fit + in a 32-bit field. + * Filefrag will report 0 extents correctly in verbose mode. + * Logsave's usage message has been fixed. (Closes: #619788) + * Update translations: French, Chinese, Germany, Indonesian, Swedish, + Vietnamese, Polish, Dutch, Czech. + * Updated/clarified man pages. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 02 Jul 2011 22:38:57 -0400 + +e2fsprogs (1.41.14-1) experimental; urgency=low + + * New upstream release + * Fixed a FTBFS on big-endian architectures + * Fixed spurious warning in mke2fs + * resize2fs now works correctly on devices exactly 16TB + * resize2fs will no longer clear the resize_inode feature when the + number of reserved GDT blocks reaches 0. This allows a file + system with the flex_bg feature to be subsequently shrunk. + * e2fsck will no longer use the extended rec_len encoding for file + systems whose blocksize is less than 64k, to catch fs inconsistencies + which the kernel will complain about. + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 22 Dec 2010 18:39:19 -0500 + +e2fsprogs (1.41.13-1) unstable; urgency=low + + * New upstream release + * E2fsck can now do journal-only replays via "e2fsck -E journal_only" + * E2fsck now understands UUID= and LABEL= specifiers for the -j option + (Closes: #559315) + * E2fsck.conf now supports a new config option, which forces the + problem not to be fixed: problems/<problem code/force_no + * Dumpe2fs now prints friendlier offsets for flex_bg file systems + * Mke2fs will now fail if the user uses an file system type not + defined in mke2fs.conf (Closes: #594609) + * Resize now prints a clarified error message explaining that on-line + shrinking is not supported at all. (Closes: #599786) + * Fixed a build error caused by bad static and profiled dependencies + for the blkid library (Closes: #604629) + * Fixed an e2fsck PROGRAMMING BUG error (Closes: #555456) + * Fixed outdated mention of fsck in the e2fsprogs package (Closes: #588726) + * Removed obsolete initrd script (Closes: #585041) + * Fixed bad dependency on libblkid1 due to shlibs.local (Closes: #583551) + * E2fsck now opens the external journal in exclusive mode to prevent + clearing the journal of a mounted, snapshotted volume if the user + accidentally tries to run e2fsck on the snapshot volume (Closes: #587531) + * Fix a big in e2fsck so it correct test for whether the EOFBLOCKS_FL + flag should be set or not. + * Tune2fs can now set uninit_bg without requiring an fsck afterwards + * Add support for the new ext4 default mount options added in 2.6.35 + * Add support for the ext4 error tracking superblock fields added in 2.6.36 + * Debugfs now uses a more concise format for listing extents in its + stat command + * Debugfs can now use direct I/O to access the file system with the -D option + * Mke2fs will skip initializing the inode table if a device supports + discard and the discard operation results in zero'ed blocks + * Mke2fs's handling of logical and physical sector sizes has been + significantly improved. + * Debugfs will correctly show the progress bar even when UTF-8 + characters are used in its translation files (Closes: #583782, #587834) + * E2freefrag will now display the total number of free extents. + * Resize2fs -P now longer requires a freshly checked file system + * Fixed a floating point precision error that can cause segfaults in + e2fsck and resize2fs in extremely rare cases + * Fixed a bug in e2fsck which caused it to fail if both the original + and backup superblocks were invalid in some way + * Fixed a bug in e2freefrag which caused getopt parsing to fail on + architectures with unsigned chars + * Clarified mke2fs and e2fsck error messages when given incorrect + options/values by the user + * Updated/clarified man pages (Closes: #580236, #594004, #589345, #591083) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 22 Nov 2010 16:00:50 -0400 + +e2fsprogs (1.41.12-2) unstable; urgency=high + + * Allow tune2fs to set uninit_bg without requiring an fsck + * Fix test in e2fsck to correctly check for EOFBLOCKS files + * Fix dependencies for libuuid and libblkid (Closes: #583551) + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 03 Jun 2010 09:30:36 -0400 + +e2fsprogs (1.41.12-1) unstable; urgency=low + + * New upstream release + * mke2fs now gives the correct error message if the external journal + is device is not found + * The resize2fs program will refuse to print the minimum size needed + for a file system if it is not clean. + * E2fsck now tests for extents that begin at physical block 0 and + rejects them as invalid. + * Fixed a bug in e2fsck which could cause it to crash when trying to + remove an invalid extent and the block bitmaps hadn't yet been loaded. + * E2fsck will now completely skip time-based checks if the system + clock looks insane or if the broken_system_clock option is set + in /etc/e2fsck.conf. (Closes: #549861, #540152) + * Fixed a bug in e2fsck which caused e2fsck to complain about i_blocks + with a 4T file created using posix_fallocate() + * E2fsck will now correctly mark a sparse journal as invalid and will + delete and recreate the journal to address the problem. + * Fixed e2fsck not to ask permission from the user to abort if it's + going to abort regardless of what the user is going to say... + * E2fsck can now continue even if it fails to recreate the resize inode + * E2fsck will now avoid removing directory entries for inods found in + the unused region of the inode table until after it restarts the fs + check to avoid removing valid data. + * E2fsck will now longer try to set the block group checksums if it + is interrupted. + * Mke2fs will check both the physical and logical blocksizes of a + device to better support 4k sector drives. + * Mke2fs will accept the valid (but rarely useful) flex_bg size of 1 + * E2fsck will check for cases where the EOFBLOCKS_FL is set whe nit is + not needed, and offer to clear it. + * The com_err library will now only output a CR character if the + stderr is connected to a tty in raw mode. + * Update Czech, Chinese, Dutch, French, Germany, Indonesian, Polish, + and Vietnamese translations (from the Translation Project) + * Add an fsck.ext4 symlink in the e2fsprogs-udeb package (Closes: #571247) + * Fix makefile dependency so dpkg-buildpackage -j2 works (Closes: #563487) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 17 May 2010 19:43:52 -0400 + +e2fsprogs (1.41.11-1) unstable; urgency=medium + + * New upstream release + * Add Heimdal function com_right_r() to libcom_err (Closes: #558910) + * Allow e2fsck to run even if the physical device has more than 2**32 blocks + * Debugfs's "logdump -b <blk>" now properly shows the allocation status + of the block <blk>. (Closes: #564084) + * Make e2fsck's "the filesystem is mounted" message is now more scary + to hopefully dissuade users from thinking, "surely that message + doesn't apply to *me*" :-( + * e2fsck -n will now always open the file system read-only. We now + disallow certain combination of options which previously were manual + exceptions; this is bad because it causes users to think they are + smarter than they really are. So "-n -c", "-n -l", "-n -L", and + "-n -D" are no longer supported. + * If the partition is badly aligned, have mke2fs just print a warning + message and continue. Previously mke2fs would ask to confirm, and + this broke distro installation scripts. + * Fix a bug in libext2fs caused the creation of very large journals + for ext4 to be _very_ slow. + * E2fsck now understands the EOFBLOCKS_FL flag which will be used in + 2.6.34 kernels to make e2fsck not complain about blocks deliberately + fallocated() beyond an inode's i_size. + * Fix a bug in e2fsck which could cause e2fsck -D to corrupt + non-indexed directories. (Closes: #572453) + * debian/rules: can be compiled statically with stack protector now. + (Closes: #573923) + * Update debian policy compliance to 3.8.4 + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 15 Mar 2010 00:16:35 -0400 + +e2fsprogs (1.41.10-1) unstable; urgency=low + + * New upstream release + * Fix resize2fs bug which causes it to access invalid memory + * Add libss support for libreadline.so.6 + * Fix e2fsck's check for extent-mapped directory with an incorrect file type + * Add new e2fsck.conf configuration option: + default/broken_system_clock for system with broken CMOS hardware + clocks. (Closes: #559776) + * Fix flex_bg inode table placement algorithm used by mke2fs for + certain specific file system sizes + * Add source lintian overrids for weak-library-dev-dependency + * Fix FTBFS problem caused by texi2html changing (again) its output + location. (Closes: #552934) + * Make e2fsck to avoid rehashing directories which can fit in a + single directory block. + * Fix how e2fsck fixes sparse directories which are extent-mapped. + * Fix some big-endian bugs in e2fsck and libext2fs + * Teach e2fsck to detect and fix sparse extent-mapped directories + * Fix filefrag from core dumping on file systems with 8k block sizes + * E2fsck was depending on i_size to be correct to detect and fix + certain directory problems before actually fixing the + directory's i_size. This caused certain rare corruptions to + require two runs of e2fsck to address. + * Update Czech, Indonesian, Polish and Vietnamese translations + (from the Translation Project) + * Fix e2fsck to find and correct duplicate directory entries in + non-indexed directories. + * Add support for calling BLKDISCARD to mke2fs. + * Enhance libext2fs so it works around bug in Linux version 2.6.19 + and earlier where the /proc/swaps file was missing the header on + the first line. + * Fix resize2fs so it works correctly on file systems with external journals + * Fix libss so that it does not seg fault when using a readline + library which does not supply a readline_shutdown() function. + * Add a pre-depends for util-linux-ng (Closes: #551795) + * Update and clarify various man pages. + * Corrected dumpe2fs's usage message + * Teach libext2fs to ignore the high 32 bits of the i_blocks field + when huge_file file system feature is set, but the inode does not + have the HUGE_FILE_FL flag set. + * Change e2fsck to accept superblock times to be fudged by up to 24 + hours by default. Most distributions have fixed their init scripts, + but apparently now they have buggy virtualization scripts. :-( I + give up, too many buggy user space set ups out there. (Closes: #557636) + * Fix e2fsck to correctly print > 32-bit i_blocks numbers in problem reports + * Improve e2fsck so it prints "Illegal indirect block" instead of + "Illegal block #-1" + * Teach mke2fs to get device topology information from blkid and use + it to populate the superblock stride and stripe sizes and warn if + the block device is misaligned + * Fix a file descriptor leak in debugfs when sourcing a command file + * Fix a file descriptor leak in fsck + * Round up the bitmap size to prevent spurious segmentation faults on + BSD platforms. + * Fix resize2fs to correctly calculate the minimum size needed, when + flex_bg is enabled, to prevent resize2fs -M from failing. + * Dumpe2fs now displays more information about the contents of the journal + * Make sure the libblkid1 and libblkid1-dbg packags have changelogs + * On low memory systems, e2fsck can print some very scary looking + error messages. Clean up them up to avoid user panic. (Closes: #509529) + * Enhance blkid to support .ko.gz files in the modules.dep parser + * Fix tune2fs -j for mounted exted-enabled file systems + * Use the feature name "extent" instead of "extents" in mke2fs.conf. + Both work, but the latter is what is documented in the man page. + (Closes: #540111) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 07 Feb 2010 20:56:47 -0500 + +e2fsprogs (1.41.9-1) unstable; urgency=low + + * New upstream release + * Fix tune2fs -I to work correctly in the face of bad blocks and + filesystems formatted for RAID arrays, and ENOSPC errors + * Require the user to only answer one question instead of multiple + ones for multiple bad block group checksums, or when an inode + table needs to be moved. + * Fix e2fsck to handle moving inode tables in FLEX_BG filesystems more + gracefully by looking in the entire flex_bg for space, instead of + just in the block group; if that doesn't work, try looking for + space in the entire filesystem. + * Fix the filefrag code to avoid printing the extent header if it + needs to fallback to using the FIBMAP ioctl. + * Fix filefrag to print the correct number of extents for zero-length + files when using FIBMAP. (Closes: #540376) + * Add a filefrag -B option to make it easier to debug the FIBMAP + support. + * Allow e2fsprogs programs to allocate from uninitalized block groups. + * Add a new program, e2freefrag, which displays information about the + free space fragmentation in an ext2/3/4 filesystem. + * E2fsck will now print much fuller information when the last mount + time or last written time is in the future, since most people can't + seem to believe their distribution has buggy init scripts, or they + have a failed CMOS/RTS clock battery. + * Update French, Polish, Czech, and Sweedish translation from the + Translation Project. + * Enhance debugfs's 'stat' command to print basic extent information + for extent-mapped inodes, and add a new command, 'dump_extents' + which prints detailed information about an inode's extent tree. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 23 Aug 2009 10:08:52 -0400 + +e2fsprogs (1.41.8-2) unstable; urgency=low + + * Fix regression in ext2fs_extent_set_bmap() which caused e2fsck -fD + to fail on ext4 filesystems if the directory needs to shrink by more + than a block (Closes: #537510) + * Fixed filefrag for non-extent based files + * Fix use of apostrohe's in package descriptions + * Don't use dietlibc when building for mips and mipsel architectures + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 20 Jul 2009 09:38:21 -0400 + +e2fsprogs (1.41.8-1) unstable; urgency=low + + * New upstream release + * Fix resize2fs bugs when shrinking ext4 filesystems + * Update debian policy compliance to 3.8.2 + * Update package descriptions to mention ext3 and ext4 filesytems + (Closes: #535530) + * Update French, Polish, Czech, Indonesian, and Sweedish translation + from the Translation Project. + * If the resize2fs operation fails, the user will be told to fix up + the filesystem using e2fsck -fy. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 11 Jul 2009 17:26:16 -0400 + +e2fsprogs (1.41.7-2) unstable; urgency=low + + * Fix online resizing using resize2fs (Closes: #535452) + * Fix the filefrag program for files with more than 144 extents + * Update and clarify various man pages. + * Fix potential filesystem corruptions caused by using resize2fs to + shrink filesystems with extents enabled. + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 07 Jul 2009 23:21:46 -0400 + +e2fsprogs (1.41.7-1) unstable; urgency=low + + * New upstream release + * Fix memory leaks in e2fsprogs, including a very large memory leak + which can cause e2fsck to run out of memory when checking very large + filesystems using extents. + * Fix a bug in libext2fs which can cause e2fsck and resize2fs to write + uninitalized data into the portion of the inode beyond the first 128 + bytes when operating on extents; potentially corrupting filesystems. + * The logsave program will now filter out the ^A and ^B characters when + writing to the console. + * Update/clarify man pages (Closes: #531385, #523063) + * Fix filefrag progam so it correctly checks for errors from the + fiemap ioctl. + * Change badblocks to allow block sizes larger than 4k. + * Fix libext2fs to properly initialize i_extra_size when creating the + journal and resize inodes. + * Resize2fs will now update the journal backup fileds in the + superblock if the journal is moved; this avoids an unnecessary full + fsck after resizing the filesystem. + * Use the same encoding as the kernel for rec_len == 64k in 64k block + filesystems. + * Fix lsattr to exit with a non-zero status when it encounters errors. + * Enhance badblocks to print the currently tested block number when + interrupted with ^C. + * Fix debugfs from core dumping if the logdump command fails to open the + output file. + * Harden ext2fs_validate_entry() so that lsdel will not read beyond the + end of the block even if the directory block is corrupted. + * Update Chinese and Czech translation from the Translation Project. + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 29 Jun 2009 15:12:14 -0400 + +e2fsprogs (1.41.6-1) unstable; urgency=low + + * New upstream release + * Update and clarify man pages + * Fix a number of Lintian warnings, including to updating to debian + policy 3.8.1 + * Update config.guess and config.sub to the latest (2009-04-17) + version so that e2fsprogs will build on the avr32 platform + (Closes: #528330) + * Add an explicit error message if the /etc/mtab file is missing + when running e2fsck or resize2fs (Closes: #527859) + * Enhance e2fsck to handle the case where the primary block group + descriptors need fixing, and the backup superblock is corrupt. + (Closes: #516820) + * Add an "-a" option to debugfs's close_filesys command + * e2fsck will no longer abort a preen operation if an inode's + i_file_acl_hi field is non-zero. (Closes: #526524) + * The chattr program can now migrate inodes from using direct/indirect + blocks to extent trees. + * Speed up e2fsck if there are multiple block groups with inodes in + use in the unused portion of the block group's inode table. + * Update Chinese translation from the translation project + * Fix resize2fs so it won't corrupt ext4 filesystem when asked to + shrink a filesystem smaller than the minimum suggested size. + * Fix e2fsck regression which can corrupt ext4 filesystems when + replaying the journal. + * Add support to e2fsck for handling I/O errors while replaying the + journal + * Fix a bug in e2fsck which could cause it to crash if an inode has a + corrupt extent header, and the user declines to clear the inode. + * Fix blkid to prefer the /dev/mapper/<name> device names over the + private /dev/dm-N device names. + * Add support for the FIEMAP ioctl to the filefrag program + * Further speed up e2fsck by skipping journal checks if the filesystem + is mounted read-only and is marked as not needing journal replay. + * Add a build depends in the control file indicating that dietlibc + must be newer than version 0.30 (Closes: #506064) + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 30 May 2009 13:26:23 -0400 + +e2fsprogs (1.41.5-1) unstable; urgency=low + + * New upstream release + * E2fsck will now detect and fix inodes that have a non-zero + i_file_acl_high field on 32-bit filesystems. + * Update build-depends to indicate that dietlibc 0.30 doesn't work. + (Closes: #506064) + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 24 Apr 2009 08:52:47 -0400 + +e2fsprogs (1.41.4-3) unstable; urgency=low + + * Update/clarify man pages (Closes: #365619) + * Fix a problem where the 'device names' for pseudo-filesystems in + /proc/mounts could confuse the e2fsprogs into thinking that a + filesystem image stored in a regular file was mounted when it was not + * Remove whole-disk entries from the blkid cache when partitions are found + * Reduce the number of disk reads needed when the filesystem is clean + * Add Chinese (simplified) translation from the Translation Project + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 23 Apr 2009 01:35:22 -0400 + +e2fsprogs (1.41.4-2) unstable; urgency=low + + * Update the debian copyright files to point at the version-specific + GPL and LGPL files. + * Update the debhelper compat level to 7 + * Fix a number of filesystem corruption bugs in resize2fs when growing + or shrinking ext4 filesystems off-line (i.e., when the ext4 + filesystem is not mounted). + * Clarify tune2fs man page (Closes: #515693) + * Add homepage field to the debian control file (Closes: #506279) + * Fix Hurd compilation problem (Closes: #521602) + * Debugfs can now set i_file_acl_high via the set_inodes_field command + * Debugfs will now display a 64-bit file acl block + * Fix various gcc compilation warnings and other programming cleanups + * Make sure libuuid closes all file descriptors before starting the + uuidd daemon. + * Avoid running e2fsck unnecessarily after doing an online resize + * Mke2fs -S will now avoid trying to create the journal + * Update the Czech translation from the translation project. + * Fix support for external journals (which was broken in e2fsprogs 1.41.4) + * Fix a compatibility issue with libext2fs info page and makeinfo 4.12 + * Fix a segfault in debugfs when running stat without an open filesystem + * Teach the blkid library that starting in 2.6.29, ext4 can support + filesystems without journals. + * Add error check preventing the reserved_ratio argument to mke2fs and + tune2fs from being negative. (Closes: #517015) + * Add support for tracking the number kilobytes written to the + filesystem via the superblock field s_kbytes_written + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 19 Apr 2009 23:05:53 -0400 + +e2fsprogs (1.41.4-1) unstable; urgency=low + + * New upstream release + * Fix bug which could sometimes cause blkid to return an exit value of + zero for a non-existent device (Closes: #502541) + * Fix spelling mistake in Debian changelog (Closes: #502323) + * Fix blkid to deal with an ext3 filesystem with the test_fs flag + * Fix debugfs's ncheck output to suppress extra characters at the end + of the file name + * Tune2fs now updates the block group checksums after changing the + filesystem's UUID + * Speed up tune2fs's inode resizing code so it is no longer vastly + inefficient for moderate to large filesystems + * Fix dumpe2fs so it doesn't attempt to print the inline journal + information on filesystems with an external journal + * Update the Catalan translation + * Filter out linux-vdso.so lines when determining the library + dependencies while building the initial ramdisk (Closes: #503057) + * Fix e2fsck so an errant INODE_UNINIT flag set in a block group + doesn't cause e2fsck to abort. + * E2fsck now distinguishes between fragmented directories and + fragmented files in verbose mode statistics and in the fragcheck + report. + * Avoid double-counting non-contiguous extent-based inodes in the + verbose mode statistics. + * E2fsck now leaves slack space when repacking directories so that a + few new directory entries won't cause leaf nodes to become split + right away. + * E2fsck was previously not handling the case of a corrupted interior + node in the extent tree, and would crash in that case. It now will + handle this and related failures robustly. + * E2fsck problem descriptions involving the journal are no longer + referred to as "ext3" problems, since ext4 filesystems also have + journals. + * Fix a long-standing bug in e2fsck which would cause it to crash when + replying journals for filesystems with block sizes greater than 8k. + * Fix a regression in debugfs's logdump command so it works for + filesystems with 32-bit block numbers. This was accidentally broken + when the header files were changed to support the 64-bit block numbers. + * Fix resize2fs for ext4 filesystems. Some blocks that that need moving + when shrinking filesystems with uninit_bg feature would not be + moved. In addition, blocks and inode table blocks were not being + correctly freed when shrinking filesystems with the flex_bg feable, + which caused resize2fs -M to fail. Finally, when blocks are moved, + make sure the uninitialized flag in extents is preserved. + * Add mkfs.ext4 symlink to the e2fsprogs-udeb package (Closes: #511207) + * Resize2fs now reserves some extra block when calculating the minimum + size to shrink the filesystem in case some extent allocation trees + * Add a "set -e" to uuid-runtime's prerm script to make Lintian happy + * The blkid library will now recognize btrfs filesystems and swap + devices currently used by user-level software suspend. + * tune2fs will not allow changing the inode size for filesystems that + have the flex_bg feature enabled, since the code currently assumes + the each block group's portion inode table is located in its own + block group. + * Fix tune2fs -I so it won't corrupt ext3/ext4 filesystem configured + for RAID storage devices. + * Mke2fs now understands a -U option which allows the UUID to be + specified for the new filesystem. + * Mke2fs will now treat devices with exactly 16TB as if they have 16TB + minus one block, since many users expect ext4 to support 16TB + devices, and the true maximum size is 16TB-1. + * E2fsck will now flag filesystems that have an insane s_first_ino + field in their superblock. + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 27 Jan 2009 11:50:49 -0500 + +e2fsprogs (1.41.3-1) unstable; urgency=low + + * New upstream release + * Fix e2fsck so it prints the correct inode number for uinit_bg + related problems. + * E2fsck will offer to clear the test_fs flag if the ext4 filesystem + is available. + * Fix a file descriptor leak in libblkid + * Avoid a potential infinite loop in e2fsck when there are disk I/O + errors while trying to close a filesystem. + * Fix a potential infinite loop in resize2fs when a bogus new size of + 0 blocks is specified on the command line. + * Add an early check to see if a device is read-only to avoid lots of + confusing error messages. + * Fix debugfs's ncheck command so it prints all of the names of + hardlinks in the same directories. + * Fix a bug in libblkid so it correctly detects whether the ext4 and + ext4dev filesystems are available, so that the ext4dev->ext4 + fallback code works correctly. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 12 Oct 2008 22:45:34 -0400 + +e2fsprogs (1.41.2-1) unstable; urgency=low + + * New upstream release + * Fix e2fsck's automatic blocksize detection. This fixes a regression + added in e2fsprogs 1.40.7 where e2fsck's -b option would not + work if a blocksize wasn't also specified via the -B option. + * Fix a potential file descriptor leak in libcom_err if the + application exec's another program. + * Fixed badblocks output for "badblocks -sw" + * debugfs: Fix ncheck to print all pathnames for all of the specified inodes + * Use dietlibc when possible for building e2fsck.static, to reduce the + size of the static binary. + * debugfs: Add the ability to specify the hash seed and to specify the + hash algorithm by name to the "hash" command. + * Add documentation for the file I/O functions to libext2fs.texinfo. + (Closes: #484877) + * Fix a bug in e2fsck where if a translation file is being used and + e2fsck needs to print problem report with a custom question (such as + "Run journal anyway?"), the PO file's header would get spewed onto + the terminal. + * Update Swedish, Vietnamese, Dutch, Indonesian, German, Czech translations + * Fixed spelling mistakes in man pages (Closes: #498100, #498101, + #498102, #498103) + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 02 Oct 2008 08:54:16 -0400 + +e2fsprogs (1.41.1-3) unstable; urgency=low + + * badblocks -v will now display the time and percentage complete + (Closes: #429739) + * Reordered debian/rules when building udebs to avoid a Lintian warning + * Fixed dependencies fields in the udeb packages (Closes: #497619) + * Avoid linking various programs with unneeded libraries + * Fixed a typo'ed bold font specifier in mke2fs's man page + * Fixed the pkg-config files so the include directory needed by the + various libraries is included, and to use Requires.private to + avoid unnecessary linking of dynamic libraries. + * Add more historical information to the debian/*.symbol files + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 05 Sep 2008 11:11:03 -0400 + +e2fsprogs (1.41.1-2) unstable; urgency=low + + * Make sure ext4_swab64() is defined on all platforms (Closes: #497515) + * Badlocks: Use O_LARGEFILE so it will run on files greater than 2GB + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 02 Sep 2008 09:53:46 -0400 + +e2fsprogs (1.41.1-1) unstable; urgency=low + + * New upstream release + * mke2fs and tune2fs now use half-md4 as the default hash algorithm + In addition the default hash algorithm can be via mke2fs.conf for + mke2fs, and via a command-line option for tune2fs. + * Add support for on-line resizing of ext4 filesystems with the + flex_bg filesystem feature. + * e2fsck now creates the journal in the middle of the filesystem, + which can speed up fsync-heavy workloads. + * Make the blkid library more efficient for devicemapper devices, + mostly by no longer using the libdevmapper library. + * Fix various namespace leakages by the libblkid, libe2p and libext2fs + libraries. + * Fix support for empty directories in 64k blocksize filesystems. + * Add supported_features command to debugfs + * Improve libblkid detection of JFS and HPFS filesystems + * The test I/O manager is now compiled in by default, but to avoid its + overhead, it is only enabled when the TEST_IO_FLAGS or TEST_IO_BLOCK + environment variables are set. + * Fix filefrag's ideal extent calculation (Closes: #458306) + * Fix postinstall scripts when the user/group is in LDAP (Closes: #497010) + * Add Indonesian and update French, Polish, Dutch, German, Sweedish, + Czech, and Vietnamese Translations. (Closes: #313697, #401092) + * Update/clarified man pages + * Add dpkg-gensymbols support to track ABI changes to the libraries + * Add lintian overrides for uuid-runtime and libuuid1 + * Remove (no longer needed) lintian overrides for e2fsck-static + * Add debian/watch file + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 01 Sep 2008 11:30:21 -0400 + +e2fsprogs (1.41.0-4) unstable; urgency=low + + * mke2fs will issue a warning if mke2fs.conf hasn't been updated and + the user tries to create an ext3, ext4, or ext4dev filesystem, + since it depends on the mke2fs.conf file in order to create the + filesystem properly with the appropriate features. + * Fix the maximum journal size message in mke2fs and tune2fs to be + consistent/correct. (Closes: #491620) + * Add detection for hfsx filesystem and add label and uuid detection + for hfs, hfsplus, and hfsx filesystems in libblkid. + * Fix cosmetic issue in resize2fs when a progress bar doesn't finish + with a newline for pass 4 (when the inode references are updated). + * Teach resize2fs to move blocks when extents are present (when + shrinking a filesystem and/or if resize_inode is not present). + * Teach resize2fs to work correctly with the uninit_bg when blocks + need to be moved or allocated. + * Fix and optimize extent manipulation in libext2fs for resize2fs. + * Fix "dumpe2fs -i" and "debugfs -i". (Closes: #495830) + * Fix resize2fs incorrectly managing directory in-use counts when + shrinking filesystems and directory inodes need to be moved. + * Fix spurious e2fsck complaints with i_size with extents and large + files and preallocated blocks. + * Make sure the creation timestamp is set by mke2fs and by new inodes + created by the libext2fs in general. + * Fix ind/dind/tind statistics when extents are present, and add + extent tree depth statistics. + * Add a fragmentation report extended option to e2fsck. + * Fix blkid cache validation and some possible blkid crashes + (Closes: #493216) + * Teach debugfs's htree command to work with extent-based directories. + * Improve the error message for "tune2fs -I". + * Fix miscellaneous strings and usage messages pointed out by the + translators. (Thanks, translators!) + * Enforce that mke2fs won't allow features for revision 0 filesystems. + * Optimize inode table allocation in mke2fs for flex_bg filesystems. + * Update/clarified man pages + * Fix minor typo in uuid-runtime's debian package description + * Wrap debian/copyright files to avoid "line too long" lintian warnings + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 23 Aug 2008 08:56:47 -0400 + +e2fsprogs (1.41.0-3) unstable; urgency=medium + + * Fix mips-specific FTBFS problem in debian/rules file + * Synchronize section and priority levels in control file with the + FTP masters' override file. + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 15 Jul 2008 11:38:59 -0400 + +e2fsprogs (1.41.0-2) unstable; urgency=medium + + * Don't try to check the group descriptor checksum if the GDT_CSUM + feature is not present. (Closes: #490637) + * Add a new blkid -L option which pretty-prints the currently + available block devices. (Closes: #490527) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 13 Jul 2008 19:18:08 -0400 + +e2fsprogs (1.41.0-1) unstable; urgency=medium + + * New upstream version + * Make e2fsck detect corrupted block group descriptors that would + cause it to relocate inode tables, causing more damage to the + filesystem, and make it try the backup superblock/block group + descriptors first. + * Fix resize2fs to clean up the resize_inode if all of the reserved + gdt blocks are consumed during an off-line resize. + * Enable huge_file, dir_nlink, extra_isize feautres for mke2fs and tune2fs. + * Enable huge_file, dir_nlink, extra_isize, and uninit_bg by default + in mke2fs.conf. + * Fix badblocks terminology in man page and program output. + (Closes: #440983, #440981) + * Clarify stripe-width and stride-size in mke2fs man page. (Closes: #487849) + * mke2fs: Dumb down filesystems for GNU Hurd (Closes: #471977) + * Add bash-static to the list of shells recommended for e2fsck-static + (Closes: #490003) + * mke2fs: Fix flex_bg metadata default layout to avoid a hole between + the bitmaps and inode tables. + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 10 Jul 2008 17:25:32 -0400 + +e2fsprogs (1.41~WIP-2008-07-07-1) experimental; urgency=low + + * New upstream version (pre-release for e2sprogs 1.41) + * Update to indicate compliance with debian policy version 3.8.0.0. + * Fix e2fsck to not truncate valid extent files that are larger than + what is supported by indirect files. + * Add -dbg packages which contain the debugging information. + * mke2fs: Print a better error message when a device is too big. + (Closes: #488663) + * Create external journal devices with a default blocksize of 4k + * Fix bug in badblocks which caused crash when lots of -t patterns are + given. (Closes: #487298) + * Fix blkid handling of stale entries. (Closes: #487758, #487783) + * Update Vietnamese, Polish, French, Spanish, German, Catalan, + Dutch, Czech translations from the translation project. + * Fix FTBFS problem on MIPS (Closes: #487675) + * Fix bug in libuuid1.postinst which would cause it to blow up if + there were spaces around the equals sign in /etc/adduser.conf. + (Closes: #487443) + * Update/clarified man pages. (Closes: #393313) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 07 Jul 2008 16:30:43 -0400 + +e2fsprogs (1.41~WIP-2008-06-17-1) experimental; urgency=low + + * New upstream version (pre-release for e2fsprogs 1.41) + * New options to badblocks allow it to limit how quickly it reads + from disk (for background scrubbing) and abort after a finding + giving a number of errors. + * Add support for ext4 filesystem features. (Closes: #388452, #425477) + * Tune2fs can migrate a filesystem from using 128 byte inodes to + larger inode sizes so the user can take full advantage of ext4) + * E2fsck and mke2fs can optionally record an undo log which can be + replayed by the e2undo program. + * E2fsck will display a less cryptic message when the last check field + in the superblock is in the future. (Closes: #446005) + * Improve blkid probes for LVM volumes and swap partitions + * Mke2fs has a much more sophisticated system for controlling the + parameters of newly created filesystems. The -t option now is used + to specify the filesystem type. See the mke2fs and mke2fs.conf man + pages for more details. + * Resize2fs will now print the minimum needed filesystem size if given + the -P option, and will resize the filesystem to the smallest possible + size if given the -M option. + * E2fsck now performs more extensive and careful checks of extended + attributes stored in the inode. + * Mke2fs will always make sure that lost+found always has at least 2 + blocks, even for filesystems with very large blocksizes (i.e., 64kb). + * The debugfs "ls" command now supports the -p option, which causes + filenames to be printed surrounded by double quotes. + * Fix a potential off-by-one buffer overflow in e2image + * The chattr program will now return a non-zero exit code in case of + failures. + * This version of e2fsprogs removes support for legacy big-endian + filesystems and for MASIX filesystems. + * Add I/O statistics reporting to e2fsck. + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 17 Jun 2008 23:57:08 -0400 + +e2fsprogs (1.40.11-1) unstable; urgency=low + + * Change mke2fs, tune2fs and resize2fs to use floating point precision + when calculating the number of reserved blocks. (Closes: #452639) + * Update Spanish and Catalan translations. + * Fix ext2fs_swap{16,32,64} for external applications. (Closes: #484879) + * Improve uuid-runtime package description. (Closes: #483962) + * Improve e2fsprogs package description. (Closes: #483023) + * Add support for detecting ZFS volumes to libblkid. + * Clarify debugfs man page. (Closes: #486463) + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 17 Jun 2008 21:59:21 -0400 + +e2fsprogs (1.40.10-1) unstable; urgency=low + + * Fix a very rare potential data corruption bug in e2fsck's journal + replay. + * Updated German, Dutch, Sweedish, and Vietnamese translations. + * Force blkid to revalidate a device if its mtime is newer than the + last validation time in the cache. + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 21 May 2008 13:35:12 -0400 + +e2fsprogs (1.40.9-1) unstable; urgency=low + + * Fix fsck so that if multiple filesystems are being checked in + parallel, the progress bar for subsequent filesystems will be + correctly displayed. (Closes: #432865) + * Fix fsck -Cn for n!=0 for better Ubuntu boot-time support + * debugfs: Don't bother using a pager of stdout is not a tty + * Fix tune2fs and debugfs to correctly parse time strings during + daylight savings time. (Closes: #471882) + * Teach fsck to treat ext4 and ext4 filesystems as ext* filesystems + * Logsave will now propagate SIGINT and SIGTERM signals to its child + process. + * Mke2fs will not allow the illogical combination of the resize_inode + and meta_bg filesystem features. + * Use UID/GID ranges from adduser.conf if present, even though we + don't use adduser to add users/groups. (Closes: #473179) + * Updated German, Czech, Dutch, French, Polish, Sweedish, and + Vietnamese translations. + * Update/clarified the mke2fs man page + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 27 Apr 2008 00:35:20 -0400 + +e2fsprogs (1.40.8-2) unstable; urgency=low + + * One more big-endian swap fix needed for resize2fs to work correctly + with in-inode extended attributes. + * Fix minor security issues identified in uuidd. + * Remove e2fsprogs preinstall script which contained stuff not needed + in well over two stable releases. + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 14 Mar 2008 14:25:54 -0400 + +e2fsprogs (1.40.8-1) unstable; urgency=low + + * Fix e2image -I so it works on image files which are larger than 2GB. + * Fix e2fsck's handling of directory inodes with a corrupt size field. + * Fully fix a resize2fs bug where extended attributes in large inodes + could get dropped on big-endian systems. + * Update Czech, Dutch, Polish, Sweedish, and Vietnamese translations. + * Significantly updated German translation! Thanks to Philipp Thomas + from Novell for stepping up to be our new German translation + maintainer! (Closes: #302512, #370247, #401092, #412882) + * Fixed mke2fs man page to document new default inode size. + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 13 Mar 2008 20:00:09 -0400 + +e2fsprogs (1.40.7-1) unstable; urgency=low + + * New upstream release + * tune2fs no longer will remove the sparse_super feature, as it is dangerous + * Update/clarified various man pages + * Fix bug where large nodes were not getting fully copied when + shrinking a fileystem using resize2fs. + * Allow mke2fs and tune2fs to manipulate the large_file feature flag + * Suppress fsck's warning message about an old-style fstab if the + fstab file is empty. (Closes: #468176) + * E2fsck will no longer clear the large_files feature flag + automatically when there are no more large files in the system. + * Fix blkid code to avoid segfaulting when a device mapper volume + disappears out from under it. + * Enhance e2fsck's reporting of unsupported filesystem features + * Fix dumpe2fs command syntax for explicit superblock/blocksize parameters + * Teach tune2fs to clear the resize_inode feature flag + * Fix libuuid1 postinstall script to explicitly pass 100 to UID_MIN + and GID_MIN, to make it clear we are not trying to allocate an + uid/gid in the globally reserved range. (Closes: #466929) + * Fix memory leak in ext2fs_alloc_block() + * Teach blkid to recognize LVM2 physical volumes + * Add support to dumpe2fs, mke2fs, and tune2fs for specifying and + printing the RAID stride and stripe width. + * Add support for new superblock fields to debugfs's set_super_value command + * Teach debugfs to print "mostly-printable" xattr strings, such as is + used by SELinux. + * Add support in fsck to ignore mounted filesystems when given the -M option + * Fix uuidd so it creates the pid file with the correct pid number + * Update Czech, Dutch, Polish, Sweedish, and Vietnamese translations + from the Translation Project. + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 28 Feb 2008 22:27:39 -0500 + +e2fsprogs (1.40.6-1) unstable; urgency=low + + * New upstream release + * Add support for returning labels for UDF filesystems in the blkid + library. + * Fix bug in the blkid library where cached filesystems was not being + flushed when opening USB devices returned the error ENOMEDIUM. + (Closes: #463787) + * Add logic to the blkid library to automatically choose whether a + filesystem should be mounted as ext4 or ext4dev, as appropriate. + * Allow tune2fs to set and clear the test_fs flag on ext4 filesystems. + * Document the BLKID_FILE environment variable in the libblkid man page + * Update Vietnamese and Czech translations from the translation project + * Fix dependency problem caused by dpkg 1.14.16 (Closes: #436058) + * Use thread local storage to fix a theoretical race condition if two + threads try to format an unknown error code at the same time in + the com_err library. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 10 Feb 2008 00:06:02 -0500 + +e2fsprogs (1.40.5-2) unstable; urgency=low + + * Fix debian/control and debian/rules so that they work correctly + after a change in dpkg-gencontrol's behavior after version 1.14.16 + of dpkg. This fixes bad version dependencies for comerr-dev, + uuid-dev and ss-dev. Thanks to Don Armstrong for the explanation and + Margarity Manterola for a proposed patch. (Closes: #463058) + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 30 Jan 2008 07:17:27 -0500 + +e2fsprogs (1.40.5-1) unstable; urgency=low + + * New upstream release. + * Mke2fs will now create new filesystems with 256 byte inodes and the + ext_attr feature flag by default. This allows for much better + future compatibity with ext4 and speeds up extended attributes + even on ext3 filesystems. + * Teach mke2fs and tune2fs to set a "test_fs" flag, which indicates + that it is ok to use the filesystem on in-development kernel + code (i.e., ext4dev) + * E2fsck now optimizes non-htree directories by sorting them by inode + number. + * Add support for detecting HFS+ and ext4/ext4dev filesystems in blkid + * Fix blkid's ntfs UUID handling so it is compatible with vol_id + * Avoid a floating point exception when blkid tries to probe a corrpt + reiserfs filesystem. + * Fix potential overflow problem in e2image if the device name is + too long. + * Cause e2image to exit immediately with an error message on a disk + full situation. + * Fix a minor typos in the resize2fs and uuidd manpages. + * E2fsck will no longer backup superblocks when the kernel makes + certain "safe" feature set changes behind the user's back. + * Fix debugfs's lsdel command so it works on large files + * Allow a user to undelete an inode with linking to a destination + directory. + * Update Swedish translation file from the Translation Project + * The libuuid1 and uuid-runtime packages requires passwd package, so + declare it as a dependency. (Closes: #459403) + * Fix a FTBFS problem on x86_64 caused by the fact that dietlibc + doesn't provide llseek on the x86_64. (Closes: #459614) + * Don't use dietlibc on platforms that don't support it (Closes: #459475) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 27 Jan 2008 16:57:34 -0500 + +e2fsprogs (1.40.4-1) unstable; urgency=low + + * Make sure that programs like tune2fs, when modifying a mounted + filesystem do not write the backup superblocks with the + NEEDS_RECOVERY flag, to avoid e2fsck from needlessly forcing a + full fsck because it thinks the feature flags need to be backed up + from the master to the backup superblocks. (Closes: #454926) + * Improve time-based UUID generation to guarantee uniqueness even when + UUID's are being generated at very high rates on SMP systems. To + do this we use an optional setuid helper daemon (uuidd) which is + started by libuuid when it is needed. The uuidd daemon is + packaged in the (new) uuid-runtime package, which now also includes + the uuidgen program (which had been previously been included as + part of the e2fsprogs package). + * Fix fsck to only treat '#' characters at the beginning of /etc/fstab + lines as starting a comment. This avoids spurious warnings printed + for filesystems such as fuse that often use '#' as part of the + filesystem specifier (i.e., wdfs#https://dav.hoster.com/foo). + * Enhance the blkid program to pretty-print control and meta + characters to avoid garbage filesystem labels from screwing up the + user's terminal + * Fix potential integer overflows passed to malloc() in resize2fs + * Update Dutch, Polish, and Vietnamese translations from the + Translation Project. Remove the Rwandan translation upon advice + of the Translation Project. + * Fix cross-compilation support for non-Linux architectures + (Closes: #451172, #437720) + * Clarified and improved man pages (Closes: #444883, #441872) + * Fix potential divide by zero error when libblkid tried probing an + invalid FAT filesystem. + * Make error_message() in libcom_err DTRT when when a 64-bit sign-extended + error code is passed to it. + * Build the e2fsck-static package so that e2fsck.static will not use + TLS and hence will run correctly on back-level Debian systems + using a 2.4 Linux kernel. (Closes: #458017) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 31 Dec 2007 22:40:42 -0500 + +e2fsprogs (1.40.3-1) unstable; urgency=medium + + * New upstream release + * libext2fs: Add checks to prevent integer overflows passed to + malloc(). Fixes security issue related to Xen's pygrub: CVE-2007-5497 + * libss: Fix parallel build failure + * e2fsprogs: fix blkid whole-disk scanning heuristics + * libext2fs: Fix a corner case bug in ext2fs_unlink + * fix check_mntent_file() to pass mode for open(O_CREAT) + * Fix errors in test_ss.c so it can be an example application and test case + * e2image in raw-mode appends an extra byte to image-file + * Fix typo in the summary section of the blkid man page + * mke2fs: Change usage message to use -E instead -R, which is deprecated + * libblkid: recognize squashfs filesystems on BE systems. + * libblkid: detect squashfs + * e2fsck: backup superblocks if key constants have changed + * e2fsck: update the backup superblocks if the feature bitmasks are changed + * ext2fs_dblist_dir_iterate: Fix ABORT propagation logic + * libblkid: Add more magic numbers that might mean there is a FAT filesystem + * e2fsck: Don't mark the filesystem invalid because of time errors + * Work around lame Ubuntu init scripts / installer bugs + * fsck: Ignore /etc/fstab entries for bind mounts + * e2fsck: If the superblock is corrupt, automatically retry with the backup sb + * Don't crash if s_inode_size is zero + * Use sscanf instead of atoi when parsing e2fsck options + * Add Catalan translation and update Spanish, French, and Dutch + translations from the Translation Project. (Closes: #411562) + * Fix typo and clarify the uuidgen man page + * Make sure $prefix/etc is created before installing mke2fs.conf + * e2fsck: Allow i_size to be rounded up to the size of a VM page + * Fix a bug in ext2fs_initialize() which causes mke2fs to fail while + allocating inode tables for some relatively rare odd disk sizes. + * Fix big-endian byte-swapping bug in ext2fs_swap_inode_full() + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 05 Dec 2007 20:04:28 -0500 + +e2fsprogs (1.40.2-1) unstable; urgency=low + + * New upstream release + * e2fsck: Fix salvage_directory when the last entry's rec_len is too big + * Update Turkish, Polish, Dutch, and Vietnamese PO files from the + Translation Project + * Fix a bug which would cause e2fsck segfault on very badly damaged + filesystems + * Update tune2fs man page to include more discussion of reserved + blocks (Addresses Ubuntu Launchpad bug #47817) + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 12 Jul 2007 22:18:51 -0400 + +e2fsprogs (1.40.1-1) unstable; urgency=low + + * New upstream release + * Clarify mk_cmds' error reporting + * e2fsck: Detect recursive loops in @-expansions + * Compile the default mke2fs.conf into mke2fs program + * Fix bogus strip permission errors when building under Debian + * Update Vietnamese, French, and Dutch PO files from the Translation Project + * Fix bug which could cause libblkid to loop forever (Closes: #432052) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 8 Jul 2007 20:25:08 -0400 + +e2fsprogs (1.40-1) unstable; urgency=low + + * New upstream release + * Remove RFC-4122 logic from Debian build rules (Closes: #407107) + * Fix com_err.texinfo so that the install-info command will remove + the com_err info file from the /usr/share/info/dir file when the + comerr-dev package is removed and purged (Closes: #401711) + * Fix divide-by-zero error in blkid's NTFS proving logic + * Add new blkid -g option which causes the blkid cache to be garbage + collected + * libblkid: Fix bug which could cuase bid_type to be corrupted + * mke2fs: Add santy check to make sure inode_size * num_inodes isn't too big + * Fix additional Coverity bugs in mke2fs and e2fsck + * Improve sanity check in e2fsck's algorithm for finding a backup superblock + * Fix e2fsck get_size logic so that it will work with the Linux floppy + driver (Closes: #410569) + * Fix error checking of badblock's last-block and start-block arguments + (Closes: #416477) + * e2fsck: avoid writing overwriting the backup superblocks until the + master superblock is confirmed to be sane + * Make the blkid library more paranoid about concluding a partition + contains a NTFS filesystem. (Addresses Launchpad Bug: #110138) + * Enhance e2fsck so it will recreate the ext3 journal if the original + journal inode was cleared to due being corrupt + * Fix e2fsck so that if the backup journal information is used, that + this is written out to the journal inode + * Make e2fsck check all of the blocks in the journal inode for validity + * blkid: Add support for detecting LUKS encrypted partitions + * e2fsck: added sanity check for xattr validation + * Fix byte-swapping bug for filesystems with large inodes + * Clarify the copyright licenses used by the various libraries in COPYING + * Remove RFC-4122 from upstream (Closes: #407107) + * Fix info-dir line which prevented install-info from removing + com_err entry from from /usr/share/info/dir when the comerr-dev + package is purged (Closes: #401711) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 29 Jun 2007 22:40:27 -0400 + +e2fsprogs (1.39+1.40-WIP-2007.04.07+dfsg-2) unstable; urgency=low + + * Allow the journal to up to 10,240,000 blocks + * Fix blkid library to recognize MD 0.90 superblock on little endian + systems + * Fix blkid library to report the correct UUID from MD superblocks + * Fix signed vs. unsigned problem in debugfs' setb/testb/freeb commands + * Enhance debugfs's date parser so it acccepts integer values + * Fix e2fsck's pass1c accounting so it doesn't terminate too early + if a file with multiply claimed blocks is hard linked. or not at + all if the root directory contains shared blocks + * Enhance debugfs so it can modify the block group descriptors using + the command set_block_group_descriptor + * Improve e2fsck's reporting of I/O errors so it's clearer what it + was trying to do when an error happens + * Fix a bug in how e2fsprogs byte swaps inodes containing fast + symlinks that have extended attributes. + * Fix potential file descriptor leak in ext2fs_get_device_size() + * Fix minor typo in e2fsck.conf.5 man page + * Cleanup udeb dependency (Closes: #419605) + * Rebuilding with libdevmapper 1.02.1 (Closes: #421022 and #421668) + * Add dependency on comerr-dev to ss-dev (Closes: #408352) + * Make mke2fs use sane defaults when /etc/mke2fs.conf doesn't exist + * Fix mke2fs and debugfs to support large (> 16 bit) uid's and gid's + * Fix spelling typo in debian package description for libblkid1 + (Closes: #399155) + * Remove -WIP language from the debian copyright file. (Closes: #415560) + * Remove check in e2fsck which required EA's in inodes to be sorted + (We should get this back-ported to the stable branch since + filesystems with large inodes will have EA's erroneously + removed, which will for example toast an SELinux system.) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 6 May 2007 19:44:35 -0400 + +e2fsprogs (1.39+1.40-WIP-2007.04.07+dfsg-1) unstable; urgency=low + + * Add libreadline.so.5 support to libss. + * Impove badblocks -n/-w exclusive usage message. + * Add debugging code (via the COMERR_DEBUG env. variable) to the + com_err library + * Fix dump_unused segfault in debugfs when a filesystem is not open + * Add versioned dependency in Debian's shlibs for libblkid. + (Closes: #413208) + * Fix memory leak in blkid library. (Closes: #413661) + * Let the debugfs lcd command work even if a filesystem is not open + * Fix large number of miscellaneous Coveriy bugs. (None were + security-security). + * Fix e2fsck to clear i_size for special devices with a bogus i_blocks + field on the first pass. + * Fix e2fsck to set the file type of the '..' entry when connecting + a directory to lost+found. + * Enhance e2fsck to recover directories whose modes field were + corrupted to look like special files. + * Allow debugfs to dump > 2GB files. (Closes: #412614) + * Misc. man page cleanups. (Closes: #379695) + * Fix resize2fs parsing of size parameter (Closes: #408298) + * Fix infinite loop in e2fsck on really big filesystems (Closes: #411838) + * Fix memory leak in ext2fs_write_new_inode() + * Add support for using a scratch files directory to reduce e2fsck's + memory utilization on really big filesystems. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 7 Apr 2007 10:38:40 -0400 + +e2fsprogs (1.39+1.40-WIP-2006.11.14+dfsg-1) unstable; urgency=low + + * Fix spurious error from e2fsck -c and mke2fs -c caused by the fix + to #386475. + * Add dirhash signed/unsigned hint to superblock. (Closes: #389772) + * Allow unix_io offsets greater than 2 gigabytes + * Make sure mk_cmds and compile_et work even in strange locales + * Fix type-punning bug which caused dumpe2fs to crash on the Arm platform + (Closes: #397044) + * Add explanatory message to badblocks that -n and -w are mutually + exclusive. (Closes: #371869) + * New +dfsg source tarball that has useful documentation REALLY + removed to satisfy the DFSG License Nazi's. (Closes: #390664) + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 14 Nov 2006 23:45:34 -0500 + +e2fsprogs (1.39+1.40-WIP-2006.10.02+dfsg-2) unstable; urgency=low + + * Add failsafes against duplicate UUID generation caused by threads + * Fix potential e2fsck -n crash caused by corrupt htrees + * Reorder the library line for static linking, to fix undefined + references to pthreads on amd64. (Closes: #393680) + * Fix mke2fs's error checking when creating revision 0 filesystems. + (Closes: #392107) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 22 Oct 2006 00:19:44 -0400 + +e2fsprogs (1.39+1.40-WIP-2006.10.02+dfsg-1) unstable; urgency=low + + * New +dfsg source tarball that has useful documentation removed to + satisfy the DFSG License Nazi's. (Closes: #390664) + * Remove dependency on e2fsprogs from the e2fsck-static package + (Closes: #383521) + * Fix badblocks interpretation of its first optional argument (last-block) + (Closes: #386475) + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 3 Oct 2006 23:36:05 -0400 + +e2fsprogs (1.39+1.40-WIP-2006.10.02-2) unstable; urgency=low + + * Build using the sid version of libc, not experimental! + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 2 Oct 2006 21:43:44 -0400 + +e2fsprogs (1.39+1.40-WIP-2006.10.02-1) unstable; urgency=low + + * Previous NMU acknowledged (Closes: #388718) + * Fix debugfs to print unsigned values for EA's + * Minor man page fixes (Closes: #373004, #369761) + * Allow the default inode size to be specified in mke2fs.conf + * Require mke2fs -F -F for really dangerous operations + * Add Vietnamese translation + * Update French and Dutch translations + * Fix debugfs coredump when lsdel is run without an open filesystem + (Closes: #378335) + * Fix spelling error in e2fsck output + * Fix overflow problems when the number of inodes and blocks is + close to 2**32-1 + * Add GFS/GFS2 support to the blkid library. + * Fix blkid support of empty FAT filesystem labels + * Avoid recursing forever due to symlinks in /dev by the blkid library + * Fix bogus error messages from resize2fs caused by the filesystem + not containing a resize inode. (Closes: #380548) + * Fixed device-mapper probing (it was failing due to an extra '/dev' being + added to the device pathname) + * Make sure the default minimum size journal is big enough to support + on-line resizing. + * Add a versioned build-dep on texi2html (Closes: #389554) + * Remove useful UUID specification thanks to License Nazi's (Closes: #390664) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 2 Oct 2006 13:04:27 -0400 + +e2fsprogs (1.39-1.1) unstable; urgency=low + + * Non-maintainer upload + * Added -pthreads to devmapper libraries (Closes: #388718) + + -- Ben Hutchings <ben@decadent.org.uk> Sat, 30 Sep 2006 12:49:47 +0100 + +e2fsprogs (1.39-1) unstable; urgency=low + + * New upstream version + * Fix debugfs's dump_unused command so it will not core dump on + filesystems with a 64k blocksize + * Clarified and improved man pages, including spelling errors + (Closes: #368392, #368393, #368394, #368179) + * New filesystems are now created with directory indexing and + on-line resizing enabled by default + * Fix previously mangled wording in an older Debian changelog entry + * Fix doc-base pointer to the top-level html file (Closes: #362544, #362970) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 29 May 2006 11:07:53 -0400 + +e2fsprogs (1.38+1.39-WIP-2006.04.09-2) unstable; urgency=low + + * Resize2fs automatically detects the previously used RAID stride + parameter so that resized filesystems can be more optimally laid + out for RAID filesystems. + * Fix mke2fs -cc and e2fsck -cc (Closes: #366017) + * Fix initrd script to fix failure with 2.4 kernels (Closes: #364516) + * Mke2fs now uses an improved layout for RAID filesystems when the + stride parameter is specified. + * Fix the debugfs commands htree_dump, dx_hash, and list_dir so they + print a usage message when an illegal option character is given. + * Speed up mke2fs and e2fsck by writing inode and block bitmaps in one pass + * Fix filefrag to be 32-bit clean by using unsigned long instead of + a signed integer for block numbers. + * Fix a bug in the e2p library which could cause dumpe2fs to + (rarely) fail to print out the journal or hash seed UUID. + * Fix memory leak in e2fsck's error paths. + * Fix comerr-dev's doc-base pointer to the top-level html file + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 14 May 2006 18:09:20 -0400 + +e2fsprogs (1.38+1.39-WIP-2006.04.09-1) unstable; urgency=low + + * Update config.guess and config.sub to latest version (2006-02-23) from FSF + * Update French, Dutch, Polish, Swedish, and Turkish translations + * Fix asm/types.h type conflicts on AMD64 to fix FTBFS problems. + (Closes: #360661, #360317) + * Fix bug which caused mke2fs -j to fail with an EBUSY error. (Closes + #360652) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 9 Apr 2006 23:04:15 -0400 + +e2fsprogs (1.38+1.39-WIP-2006.03.29-2) unstable; urgency=low + + * Added missing build dependency on libdevmapper-dev. (Closes: #360046) + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 30 Mar 2006 12:33:30 -0500 + +e2fsprogs (1.38+1.39-WIP-2006.03.29-1) unstable; urgency=low + + * Add udeb: lines to the Debian's shlibs files (Closes: #356293) + * Enhance dumpe2fs to print the size of the journal + * Fix e2sprogs so that it is 32-bit clean on x86 platorms. + * Fix mklost+ound so that it creates a full-sized directory on 4k and + larger block sizes. + * Add mke2fs.conf coniguration file to conigure mke2fs's defaults + * Add devmapper support to the blkid library. + * E2fsck, resize2fs and mke2fs will now open the filesystem device in + exclusive mode + * Fix documentation and man pages. (Closes: #351268, #357951, #347295, + #316040) + * Cix "mke2fs -O resize_inode" for very large filesystems (Closes: #346580) + * Add on-line resizing support into resize2fs + * Fix blkid's handling of verification timeouts when the system clock is + insane + * Fix library Makefiles so they work with GNU make 3.81 as well as GNU + make 3.80. + * Enhance the blkid library to display the uuid of external journals for + ext3 filesystems + * Enhance e2fsck so it will fix the external journal hint in the + superblock if it is out of date. + * Fix debugfs's icheck to correctly report the owner of an EA block + * Update Sweedish translation + * Add a configuration parameter to e2fsck.conf to control whether or not + filesystem checks are done when the system is running on battery power. + * Print an explanation when skipping a check due being on battery + (Closes: #350306) + * Update French translation (Closes: #341911, #300871, #316604, #316782, + #330789) + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 29 Mar 2006 20:37:27 -0500 + +e2fsprogs (1.38+1.39-WIP-2005.12.31-1) unstable; urgency=medium + + * New upstream version + * Update profile library code base + - Allow tag and section names to have quoted strings + - Make the profile library support reading files in a conf.d directory + - Slightly change the parser to support comments at the end of all lines + - Add syntax error reporting + - Simplify profile code + - Add E2FSCK_CONFIG environment variable which overrides where to + find /etc/e2fsck.conf + - Make e2fsck's filesystem problem handing configurable + - Fix FTBFS bug if comerr-dev is not installed. (Closes: #345519) + * Update Dutch, Polish, and Swedish translations. (Closes: #343149) + * Fix a fd leak across an exec in libuuid. (Closes: #345832) + * Address override file disparities + * Make urgency be medium to accelerate a workaround to Debian's buggy + initscripts (See Debian bugs: #343662, #343645) + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 6 Jan 2006 21:41:06 -0500 + +e2fsprogs (1.38+1.39-WIP-2005.12.10-2) unstable; urgency=low + + * Make resize2fs expand or truncate a file containing a filesystem. + (Closes: #271607) + * Add support for lib64ext2fs-nopic.a for the mips architecture + (Closes: #329074) + * Deal with the fact that Debian's boot sequence bogusly doesn't set the + time correctly until very late in the boot process; so if the + superblock's last mount or write time is in the future, don't treat + this as a fatal error. (Closes: #343662, #343645) + * Move the blkid and uuidgen binaries out of libblkid1 and libuuid1 and + into the e2fsprogs package to support soname transitions and + simulaneous installs of multiarch flavors to coexist. (It's not worth + creating two whole new packages for two separate binaries, so we just + fold them into e2fsprogs.) (Closes: #330737, #330736) + * Optionally allow the user to interrupt e2fsck "safely" during a boot + sequence without causing the boot scripts to abort. (Closes: #150295) + * Update and clarify man pages (Closes: #312515) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 31 Dec 2005 01:05:35 -0500 + +e2fsprogs (1.38+1.39-WIP-2005.12.10-1) unstable; urgency=low + + * Update and clarify man pages (Closes: #329859, #322188, #316811) + * Fix bug creating external journals on big-endian machines. + * Detect if the superblock's last mount time or last write time is in + the future, and offer to fix it if this is the case (Closes: #327580) + * Add new debugfs command, set_current_time which sets the time used to + update the filesystems's time fields. + * Fix display bug in badblocks -sw when printing the "done" message. + (Closes: #322231) + * Improve blkid's FAT/VFAT filesystem detection code so that it can find + labels stored the root directory and to be more correct/paranoid. + * Add support to extract iso9660 label information to the blkid library. + * Add support to detect the reiser4 filesystem to the blkid library. + * Add support for detecting software suspend partitions to the blkid library. + * Fix the blkid library to notice when an ext2 filesystem is upgraded to + ext3. + * Fix debugfs's set_inode_field so that successfully sets the i_size field + * Updated Dutch translation + * E2fsck will stop and print a warning if the user tries running a + read/write badblocks test on a read-only mounted root filesystem. + * Add resize2fs and badblocks to the e2fsprogs udeb + (Closes: #290429, #310950) + * Avoid trying to mount the root device if it is an NFS device. + (Closes: #310428) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 10 Dec 2005 22:49:47 -0500 + +e2fsprogs (1.38-2) unstable; urgency=low + + * Previous NMU acknowledged (Closes: #317862, #320389) + * Fix debugfs's set_inode_fields command so it doesn't silently fail + when setting certain inode fields. + * Fix e2fsck from segfaulting on disconnected inodes that contain one or + more extended attributes. (Closes: #316736, #318463) + * Allow mke2fs and tune2fs to take fractional percentages to the -m + option in mke2fs and tune2fs. (Closes: #80205) + * Fix a compile_et bug which miscount the number of error messages if + continuations are used in the .et file, and fix compatibility problems + with MIT Kerberos 1.4 + * Add extra sanity checks to protect users from unusual cirucmstances + where /etc/mtab may not be sane, by checking to see if the device is + reported busy (works on Linux 2.6) kernels. (Closes: #319002) + * Fix use-after-free bug in e2fsck when finishing up the use of the + e2fsck context structure. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 21 Aug 2005 23:35:29 -0400 + +e2fsprogs (1.38-1.1) unstable; urgency=low + + * NMU for RC bug durring bug squishing party + * Fix for changes to texi2html, patch by Matt Kraai + (Closes: #317862, #320389) + * version build-depend on texi2html, won't work with older one anymore + + -- Blars Blarson <blarson@blars.org> Fri, 5 Aug 2005 04:46:54 +0000 + +e2fsprogs (1.38-1) unstable; urgency=low + + * New upstream version + * Fix ia64 core dump bug caused by e2fsprogs running afoul of C99 strict + type aliasing rules on newer gcc compilers. (Addresses Red Hat + Bugzilla ##161183.) + * Fix minor typo's in tune2fs man page. + * Mke2fs will refuse to create filesystems greater than 2**31-1 blocks, + unless forced, to avoid kernel bugs that still need to be fixed as + of this release. + * Update French, Dutch, Polish, Swedish, and Turkish translations. + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 30 Jun 2005 20:02:42 -0400 + +e2fsprogs (1.37+1.38-WIP-0620-1) unstable; urgency=low + + * Update and clarify man pages. + * Clarify and clean up e2fsck's problem descriptions + * Add Dutch translation, and update French, Polish, Swedish, and + Turkish translation. + * mke2fs and badblocks will check to see if the device appears to be + busy and abort if so; this feature only works on Linux 2.6 systems. + (Closes: #308594) + * Fix filefrag so that it works on 64-bit platforms where the size of + an integer != the size of a long. (Closes: #309655) + * Change the default journal size to be bigger for larger filesystems, + given modern memory sizes. + * Fix com_err library so it is compatible with MIT krb5 1.4. + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 20 Jun 2005 17:11:29 -0400 + +e2fsprogs (1.37+1.38-WIP-0509-1) unstable; urgency=low + + * Make the blkid library much more efficient when a new device is added + on systems with a huge number of disks. + * Fix handling of the PAGER and SS_READLINE_PATH environment variables + in the ss library, and the TEST_IO_* environemnt vaiables for the + test_io io_manager, which was accidentally broken in 1.37-1. + * Fix libblkid's recognition of cramfs filesystems, and add support for + cramfs labels. + * Fix filefrag to give correct results when the first block found is an + indirect block. (Closes: #307607) + * Fix debugfs seg fault when the stat command is given and a filesystem + is not open. + * Improve environment variable paranoia checks. + * Fix e2fsck's handling of multiply claimed blocks involving the resize + inode. + * When determining the libraries needed for the initrd, unset LD_PRELOAD + and LD_LIBRARY_PATH and filter out libraries found in + /etc/ld.so.preload. (Closes: #304003) + * Update Swedish translation, and added translation for Rwanda. + * Minor man page spelling/typo fixes. (Closes: #304591, #304592, + #304594, #304597, #304593) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 9 May 2005 09:10:20 -0400 + +e2fsprogs (1.37-2) unstable; urgency=low + + * Fix filefrag so that it works non ext2/3 filesystems again. + (Closes: #303509) + * Make sure we include stdlib.h to fix a core dump bug in mke2fs on the + IA64 architecture (or other platforms where sizeof(ptr) > sizeof(int)) + (Closes: #302200) + * Add missing return values so that we don't return garbage in certain + error cases in ext2fs_write_new_inode() and ext2fs_read_int_block(). + * Fix minor spelling typo in the mke2fs man page + * Avoid doing the LOW_DTIME checks if the superblock last mount time + indicates that the system clock may not be set correctly. + * Add further paranoia checks to the blkid, ext2fs, and ss libraries to + make them safe to call from setuid or setgid applications. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 9 Apr 2005 11:08:04 -0400 + +e2fsprogs (1.37-1) unstable; urgency=low + + * New upstream release. + * Fixed a bug in e2fsck so it would notice if a file with an extended + attribute block was exactly 2**32 blocks, such that i_blocks wrapped + to zero. + * Fixed a bug in filefrag which caused it to falsely report a + discontinuity when there are one or more unallocated blocks at the + beginning of a file. + * Fix the missing translations (caused by a bug in the gen-tarball + script). (Closes: #296769) + * Add support in e2fsck and debugfs for extended attributes in inodes. + * Fix the missing translations (caused by a bug in the gen-tarball script). + (Closes: #296769) + * Force compile_et and mk_cmds to use /usr/bin/awk so that we will work + on any Debian system regardless of which version of awk is installed. + (Closes: #299341) + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 21 Mar 2005 22:31:08 -0500 + +e2fsprogs (1.36release-1) unstable; urgency=low + + * New upstream release. + * Make filefrag print the first and last blocks when in verbose mode. + * Drop sparc assembly bitops; it's less efficient than gcc 3.4's + generated code, and it triggers compiler warnings on sparc 64. + (Closes: #232326) + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 4 Feb 2005 20:58:35 -0500 + +e2fsprogs (1.36rc5-1) unstable; urgency=low + + * Make blkid -t work more consistently even when the cache file is not + available or set to /dev/null. (Closes: #292425) + * Don't ever use a blocksize greater than 4k, since not all 2.6 kernels + will support this. + * Fix bug where mke2fs would not correctly create filesystems greater + than 4TB. + * Fix e2fsck so it won't delete symlinks that contain an extended + attribute after the ext_attr feature flag has been cleared. + * Fix e2fsck's resize inode handling in some additional corner cases. + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 27 Jan 2005 22:44:31 -0500 + +e2fsprogs (1.36rc4-1) unstable; urgency=low + + * Fix a bug in resize2fs where we don't release the blocks belonging to + the old inode table blocks when we move the inode table. + (Closes: #290894) + * Make sure that we don't write garbage when writing a large inode. + * Check NTFS ahead of other filesystems since Windows doesn't always + clearing enough of the partition to avoid false positives with older + filesystems. (Closes: #291990) + * E2fsck now checks the summary filesystem accounting information, and + if any of the information is obviously wrong, it will force a full + filesystem check. (Closes: #291571) + * Clarified and updated tune2fs and blkid man pages + * Fix e2fsck to not complain when the resize_inode feature is enabled, + s_reserved_gdt_blocks is zero, and there is no DIND block allocated in + the resize inode. + * Fix blkid -t to display all devices that match the specified criteria, + not just the first one. (Closes: #290530) + * Add support for the blkid library to recognize Oracle ASM volumes. + * Add set_super_value jnl_blocks[] in debugfs. + * Fix the filefrag program so that it works correctly with sparse files. + * Fix portability problems with FreeBSD, Solaris, and Intel C++ 8.1. + * Add support for FreeBSD and Lites as OS Creator values. + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 26 Jan 2005 10:22:02 -0500 + +e2fsprogs (1.36rc3-2) unstable; urgency=low + + * Remove debugging printf's from e2image's -s code. + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 19 Jan 2005 02:25:53 -0500 + +e2fsprogs (1.36rc3-1) unstable; urgency=low + + * New upstream release + * Update Italian, French, and Turkish translations + * Fixed file descriptor leak in the filefrag program + * Add -s option to e2image which scrambles directory entries when making + raw image files + * Make sure e2fsck doesn't crash if /proc/acpi/ac_adapter does not + exist + * Added Solaris, FreeBSD portability fixes + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 19 Jan 2005 00:33:31 -0500 + +e2fsprogs (1.36rc2-1) unstable; urgency=low + + * New upstream release + * Update Italian translation + * Add support for swap partition labels and uuid's + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 11 Jan 2005 14:12:17 -0500 + +e2fsprogs (1.36rc1-1) unstable; urgency=low + + * Fix a FTBFS bug for amd64/gcc-3.0 (Closes: #289133) + * Minor man page clarifications. (Closes: #273679) + * Add support for online resizing via the resize inode. + * Badblocks will now correctly display block numbers greater than + 999,999,999 in its progress display. + * tune2fs will not allow the user from setting a ridiculous number of + reserved blocks which would cause e2fsck to assume the superblock + was corrupt. E2fsck's standards for what is a ridiculous number + of reserved blocks has also been relaxed to 50% of the blocks in + the filesystem. + * The blkid library will return vfat in preference to msdos, and ext3 in + preference to ext2 (if the journalling flag is set) so that mount + will do the right thing. (Closes: #287455) + * The fsck program will now accept an optional filedescriptor argument + to the -C option. + * Mke2fs will now use the -E option for extended options; the old -R + (raid options) option is still accepted for backwards compatibility. + * Fix a double-free problem in resize2fs. (Red Hat Bugzilla #132707) + * Mke2fs will now accept a size in megabytes or gigabytes (via "32m" or + "4g" on the command line) if the user finds this more convenient + than specifying a block count. + * Fix an obscure, hard-to find bug in "e2fsck -S" caused by an inode + cache conherency problem. + * Debugfs now supports a new command, set_inode_field, which allows a + user to manually set a specific inode field more conveniently, as + well as set entries in the indirect block map. + * Debugfs's set_super_value command has been enhanced so that the user + can set most superblock fields, including the date/time fields and + some of the more newsly added superblock fields. + * E2fsprogs programs now accept an offset to be passed to the file + specifiers, via the syntax: "/tmp/test.img?offset=1024" + * E2fsprogs will now accept blocksizes up to 65536; kernel support on + the x86 doesn't exist, but it is useful on other architectures. + * Fix bug in debugfs where kill_file would lead to errors when deleting + devices and symlinks. (Sourceforge Bugs #954741 and #957244) + * Fix bug in the blkid library when detecting the ocfs1 filesystem + * Updated Italian translation file + * E2fsck will now recover from a journal containing illegal blocks. + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 7 Jan 2005 20:22:36 -0500 + +e2fsprogs (1.35-9) unstable; urgency=low + + * Minor man page clarifications. (Closes: #273679) + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 28 Sep 2004 10:29:29 -0400 + +e2fsprogs (1.35-8) unstable; urgency=low + + * Remove double "//" when listing attributes in the root directory or + when there is a trailing '/' in the directory name. (Closes: #272943) + * Make sure the configure files are newer than configure.in the + debian/rules file so that a dpkg-source created patch won't + trigger an attempt rebuild of the configure script. + (Closes: #272558, #273242) + * Make sure /usr/lib/e2initrd_helper is in the e2fsprogs package. + (Closes: #272698, #272728, #273161, #273163) + * Only use blocksizes > 4k on Linux 2.6 and newer systems. (Closes: #271064) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 25 Sep 2004 07:37:52 -0400 + +e2fsprogs (1.35-7) unstable; urgency=low + + * Make sure "done" gets correctly translated in badblocks(8), and update + French translation (Closes: #252836) + * Always build the fsck wrapper on Debian systems (Closes: #248050) + * Filter out linux-gate.so, which is a pseudo entry for the 32->64bit + translation for amd64 systems, in the initrd creation script. + (Closes: #253595) + * Change the initrd scripts to be use a helper program which avoids + needing to mount the root filesystem and use awk to query the + /etc/fstab file. (Closes: #247775) + * Add support for the ocfs2 filesystem to the blkid library. + * Various portability fixes for Hurd and FreeBsd, as well as + removing XSI:isms. (Closes: #256669, #264630, #269044, #255589) + * Update config.guess and config.sub from the FSF. + * Minor manual page clarifications (Closes: #268148) + * Fix write ordering problems to make e2fsck more robust in the face + of system crashes while replaying the journal, etc. + * Fix debugging printf in resize2fs. (Closes: #271605) + * Add debugfs -d option to use a separate source of data blocks when + reading from an e2image file. + * Add e2image -I option which allows the e2image metadata to be + installed into a filesystem. + * Change e2fsck to accept directories greater than 32MB. + * Add test_io mechanisms to abort after reading or writing to a + particular block. + * Fix blkid file descriptor and memory leak. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 18 Sep 2004 09:58:46 -0400 + +e2fsprogs (1.35-6) unstable; urgency=low + + * In the mkinitrd script, make sure the directories exist before + trying to copy in the needed shared libraries. (Closes: #244058, #246480) + * In the mkinitrd script, use LD_ASSUME_KERNEL=2.4 if necessary. + (Closes: #245931) + * In the mkinitrd script copy in /usr/bin/awk instead of /usr/bin/mawk. + (Closes: #245670) + * In the initrd script, fail quietly if /mnt/etc/fstab does not exist. + (Closes: #246917) + * Minor updates to German translation (Closes: #244105) + * Since woody's sysvinit package is before the initscripts were broken out + we need an explict Conflict: sysvinit (<< 2.85-4) header. (Closes: #243829) + * Update the UUID library man pages + * Fix a Y8.8888K potential problem with the uuid library + * Minor updates to the german translation + * Clarified/corrected the copyright statements of the UUID and blkid + libraries in the Debian copyright files. + * Added sanity check to the blkid library so that if current time is + less than last time a device is verified, force a reverification since + it means the system time is not trustworthy. + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 4 May 2004 16:23:06 -0400 + +e2fsprogs (1.35-5) unstable; urgency=low + + * Add uuid_unparse_upper() and uuid_unparse_lower() functions to the + uuid library. + * Address GNU/KFreeBSD portability issues (Closes: #239934) + * Use unsigned for 1 bit wide bitfields in header files to avoid + Intel C++ compiler warnings. + * Use C99 stdint.h types in the uuid library + * Fix up and cleanup uuid man pages + * Change the licensing of the uuid man pages to be 3-clause BSD. + * Fix the initrd scripts so that the automatic ext3 journal + conversion actually works correctly; also allow conversion of the root + filesystem from ext3 back to ext2 (Closes: #241183) + * Minor man page fixes (Closes: #241940, 242995) + * Use the DEBUGFS_PAGER environment variable in preference to PAGER + (Closes: #239547) + * Added French translation + * Be flexible about the name of the ACPI device that cooresponds to + the AC adapter (Closes: #242136) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 12 Apr 2004 12:38:34 -0400 + +e2fsprogs (1.35-4) unstable; urgency=low + + * Fix bug in the blkid library (introduced in 1.35-3) which caused + the probe function to completely malfunction. (Closes: #239191) + * Make the debugfs command's link command set the filetype information + correctly. + * Update the Polish, Swedish, and Turkish translations + * Add an -o option to the blkid program which allows the user to + control the output format of blkid. + * Fixed and cleaned up the tune2fs and blkid man pages (Closes: #238741) + * Improve UUID generation algorithm (use all 14 bits in the clock sequence) + * Change the license on the UUID library to be 3-clause BSD. + * Remove the only-partially-implemented -p option to blkid. + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 21 Mar 2004 20:17:03 -0500 + +e2fsprogs (1.35-3) unstable; urgency=low + + * Mention e2image's limitation in writing a normal image file to + stdout (Closes: #236383) + * Only use BLKGETSIZE64 on Linux 2.6 since it is unreliable on Linux 2.4. + (Closes: #236528) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 8 Mar 2004 14:19:15 -0500 + +e2fsprogs (1.35-2) unstable; urgency=low + + * Use 64-bit ioctl's if present to determine the 64-bit size of a device + * Add tune2fs to the e2fsprogs udeb package (Closes: #235639) + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 2 Mar 2004 10:13:39 -0500 + +e2fsprogs (1.35-1) unstable; urgency=low + + * New upstream version. + * Fix "badblocks -t random". (Closes: #234828) + * Fix "e2fsck -k". (Closes: #234993) + * Change badblock's default number of blocks tested at once from + 16 to 64. (Closes: #232240) + * ss-dev and comerr-dev now use a versioned dependency for libss2 and + libcomerr2, respectively. (Closes: #235280) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 28 Feb 2004 10:14:19 -0500 + +e2fsprogs (1.34+1.35-WIP-2004.01.31-2) unstable; urgency=low + + * Add a new -k option to e2fsck which keeps the existing badblocks + list when using the -c option. (Closes: #229103) + * Update debugfs to support new large major/minor device numbers + supported by Linux 2.6. (Closes: #865289) + * Fix makefiles so that it will build correctly with --enable-profile. + * Add -mieee when compiling with GCC on an Alpha. + * Fix e2fsck preen mode messages using pass 1B/C/D. + * Fix the debugfs man page. (Closes: #232406) + * Fix the ext2fs.h header file to work correctly with C++. + * e2fsck and debugfs now correctly deals with symlinks that have + extended attribute information, such as those created by SE Linux. + (Closes: #232328) + * Make sure filefrag actually gets compiled under Linux (Closes: #230992) + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 24 Feb 2004 00:16:43 -0500 + +e2fsprogs (1.34+1.35-WIP-2004.01.31-1) unstable; urgency=medium + + * Fix byte swap bugs in e2fsck that caused the journal backup location + in the superblock and symlinks created by SE Linux to be cleared + by e2fsck on big-endian machines. (Closes: #228723) + * Chattr now stops processing options when it sees '--'. (Closes: #225188) + * Add FreeBSD port fixups + * Use the DEBUGFS_PAGER environment variable in preference to PAGER. + Document that less is a really, really, really bad pager to use + for debugfs (unfortunately, Debian policy says we must use + /usr/bin/pager even if it results in very annoying behaviour for + the user since 'less' is used in preference to 'more' unless it is + globally overriden via update-alternatives(8). Oh, well. Debian + users are encouraged to set DEBUGFS_PAGER to be "more" in their + dot files to avoid this brain damage). + * Fix libuuid1-udeb so that it provides libuuid1. (Closes: #229633) + * Fix bug in uuid library when there is no network card and the + library is generating a time-based uuid. The random MAC address + was not correctly generated to be a multicast address. + * Install the filefrag program. + * Don't try to compile filefrag on non-Linux platforms. (Closes: #226456) + * Minor manual page clarifications (Closes: #222606, #214920) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 31 Jan 2004 20:57:35 -0500 + +e2fsprogs (1.34+1.35-WIP-2003.12.07-2) unstable; urgency=low + + * Fix test for /etc/mkinitrd/scripts/e2fsprogs to make sure it gets + removed. (Closes: #213275) + * Debugfs now searches for the appropriate pager to use, beginning + with /usr/bin/pager, and then falling back to 'less' and 'more'. + (Closes: #221977) + * Fixed mangled encoding in Czech locale file. (Closes: #214633) + * Fix bug where using debugfs to copy a file from /dev/null caused + in correct mode bits. (Closes: #217456) + * Fixed a bug where e2fsck would bomb out if a journal needed to be + replayed when using an alternate superblock. + * Minor manual page fixups/cleanups. + * Debugfs's mkdir command will automatically expand the directory if + necessary. (Closes: #217892) + * Fix a bug in e2fsck which caused it to incorrectly fix a filesystem + when reconnecting a directory requires creating a lost+found + directory. (Closes: #219640) + * Add Spanish translation. + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 24 Dec 2003 14:24:14 -0500 + +e2fsprogs (1.34+1.35-WIP-2003.12.07-1) unstable; urgency=medium + + * Added regression tests for mke2fs and dumpe2fs. + * Support 2.6 kernel header files. (Closes: #221778) + * Fix bug which could a core dump if a non-existent LABEL or UUID + specifier is passed to e2fsck or tune2fs. + * Fix handling of corrupted indirect blocks in the bad block inode. + * If the number of mounts until the next forced filesystem check is less + than 6, mention this to the user. (Closes: #157194) + * E2fsck will try to avoid doing a forced filesystem chcek if a system + is running on batteries according to APM or ACPI. (Closes: #205177) + * Fix problems in the German translation. (Closes: #2000086) + * Updated Swedish translation and added Polish translation. + * Fix signed vs unsigned bug which could cause the com_right function to + seg fault. (Closes: #213450) + * Add libuuid1-udeb (Closes: #221777) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 22 Nov 2003 11:51:13 -0500 + +e2fsprogs (1.34+1.35-WIP-2003.08.21-3) unstable; urgency=low + + * Adjust the man page descriptions so that "apropos ext2" or + "apropos ext3" will find all of the e2fsprogs man pages. + (Closes: #206845) + * Protect against a potential core dump in e2fsck when printing a + message about a backup superblock. + * Fix a bug in mke2fs which caused -T largefile or -T largefile4 to + core dump due to a division by zero error. (Closes: #207082) + * Force e2fsprogs to use the matched version of e2fslibs. (Closes: #208103) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 31 Aug 2003 21:49:52 -0400 + +e2fsprogs (1.34+1.35-WIP-2003.08.21-2) unstable; urgency=low + + * When moving the journal or backing up the journal inode + information, make sure e2fsck updates all the superblocks, and not + just the master superblock. + * Change the priority of libblkid1-udeb to be required instead of + standard, to match the override file. + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 21 Aug 2003 08:50:34 -0400 + +e2fsprogs (1.34+1.35-WIP-2003.08.21-1) unstable; urgency=low + + * Fix compile_et to output the correct prototype for + initialize_xxx_err_table_r() in the header file. (Closes: #204332) + * E2fsck will avoid printing ^A and ^B characters bracketing the + progress bar when stdout is a tty device. (Closes: #204137) + * Add support for storing the journal inode location in the superblock + so that e2fsck can recover from a corrupted inode table after a power + failure. + * Move the initrd script from /etc/mkinitrd/scripts to + /usr/share/initrd-tools/scripts so that mkinitrd will not remove + the file when it is uninstalled. (Closes: #204019) + * Remove unneeded files in debian directory: blkid-dev.substvars and + e2fsprogs-bf.lintian-overrides. (Closes: #203914) + * Support "noopt" in DEB_BUILD_OPTIONS instead of "debug". + (Closes: #203914) + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 21 Aug 2003 01:47:58 -0400 + +e2fsprogs (1.34+1.35-WIP-2003.08.01-1) unstable; urgency=low + + * Fix O_DIRECT test to prevent badblocks from screwing up after + finding a bad block. (Closes: #203713) + * Add Heimdal compile_et extensions from Philipp Thomas (pthomas@suse.de) + * Fix potential pointer aliasing bugs caused by type-punning and gcc 3.x + + -- Theodore Y. Ts'o <tytso@mit.edu> Fri, 1 Aug 2003 13:44:58 -0400 + +e2fsprogs (1.34-2) unstable; urgency=low + + * Fix erroneous reference to /usr/share/doc/e2fsprogs/html-info in + /usr/share/doc-base/libext2fs (Closes: #203157) + * Explicitly specify the version of libblkid1 needed in + e2fsprogs.shlibs.local in order to avoid picking up the wrong depedency. + (Closes: #203157) + * Changed priority of libblkid1-udeb to be standard, not required. + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 30 Jul 2003 19:47:32 -0400 + +e2fsprogs (1.34-1.1) unstable; urgency=low + + * Non-maintainer upload. + * don't call ldconfig in udebs. + * fix dependencies of e2fsprogs-udeb. + + -- Bastian Blank <waldi@debian.org> Tue, 29 Jul 2003 12:11:54 +0200 + +e2fsprogs (1.34-1) unstable; urgency=low + + * New upstream version. + * Fixed bug in fsck which caused it to waste CPU by spinning while + waiting for a child fsck process under some circumstances. + * Fixed bug in blkid library which would cause it to spin forever if + /proc is not mounted and /etc/blkid.tab is not present. + * Improved the blkid library's UDF's probing functions. + * Fixed the blkid library so it will remove delete the LABEL + attribute from its cache when a filesystem that previously had a + label no longer has one. + * Added Swedish translation. + * Remove debugging printf in badblocks program (Closes: #201499) + * Split shared libraries out of the e2fsprogs package into separate + packages: libss2, libcomerr2, libuuid1, and e2fslibs. (Closes: #201155, + #201164) + * Warn the user when creating a filesystem with a journal and a blocksize + greater than 4096, since some kernels don't support ext3 with large + block sizes. (Closes: #193773) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 26 Jul 2003 01:01:55 -0400 + +e2fsprogs (1.33+1.34-WIP-2003.05.21-2) unstable; urgency=low + + * Set up FreeBSD configuration defaults (Closes: #195274) + * Clarify resize2fs man page (Closes: #195616) + * Fix resize2fs to deal with filesystem with bad blocks + * Fix spelling error in e2fsck + * Add workaround for intl library on Darwin + * Fix gcc -Wall nitpicks + * Round down the default size of the filesystem for mke2fs and + resize2fs to be a multiple of the pagesize to work around a potential + Linux kernel bug + * Fix bug in mke2fs where it could die with a floating exception if + the device does not support the BLKSSZGET ioctl (Closes: #196734) + * Add conflicts against older versions of sysvinit that don't correctly + handle an exit code that has the bit #2 set. (Closes: #183675) + * Badblocks will attempt to use O_DIRECT if it is safe to do so. + (Closes: #198006) + * Use symbolic links for fsck.ext{2,3} and mkfs.ext{2,3} in the udeb + package since busybox tar can't deal with hard links. (Closes: #196508) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 12 Jul 2003 03:16:08 -0400 + +e2fsprogs (1.33+1.34-WIP-2003.05.21-1) unstable; urgency=low + + * Fix problems with compiling e2fsprogs with NLS support on woody + (Closes: #193372) + * Remove the extraneous de-utf.po file. + * Add get-text to build-depends. + * Use ngettext (abbreviated with P_()) to simplify the statistics reporting. + * Fix badblocks to be able to support arbitrary 4 byte test patterns. + * Fix bug which caused us to accidentally include the EVMS plugin in + the e2fsprogs package (which doesn't work, but causes confusing messages + to show up when the evms client is started). + * If the hardware sector size of a device is larger than the default + blocksize, use the hardware sector size as the blocksize when creating + a filesystem, to solve problems with s/390 DASD's. + * Add a shared library dependency to libuuid to libblkid (Closes: #194094) + * Add initial implementation of a dump_unused command (Closes: #79164) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 18 May 2003 01:24:16 -0400 + +e2fsprogs (1.33-5) unstable; urgency=low + + * Clarify blocksize units when displaying messages in resize2fs, and + support using suffixes (sectors, kilobytes, megabites, gigabytes) + to the size parameter to indicate units. (Closes: #189814) + * Fix debugfs core-dumping problem caused by getopt. (Works around: #192834) + * Add package dependency to shlibs for comerr to indicate support + for kth compatibility. (Closes: #193096) + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 13 May 2003 23:45:08 -0400 + +e2fsprogs (1.33-4) unstable; urgency=low + + * Add replaces field to comerr-dev to resolve a file conflict with + /usr/include/com_err.h and the libkrb5-dev package. (Closes: #192277) + * Add -t option to badblocks to control the test pattern used. + * Remove e2fsprogs-bf package, as it is obsolete. (Closes: #183453) + * Remove NLS support from e2fsprogs-udeb. Save 5.5k on the boot + floppies / install media. + + -- Theodore Y. Ts'o <tytso@mit.edu> Thu, 8 May 2003 10:25:05 -0400 + +e2fsprogs (1.33-3) unstable; urgency=low + + * Add full Heimdall/Kerberos4-kth compatibility to com_err routines. + * Declare comerr-dev as replacing << e2fslibs-dev 1.33-2, to avoid + errors when upgrading to the new versions of comerr-dev and + e2fslibs-dev + + -- Theodore Y. Ts'o <tytso@mit.edu> Tue, 6 May 2003 00:29:47 -0400 + +e2fsprogs (1.33-2) unstable; urgency=low + + * Fix up NLS support + - Fix message abbreviations support (i.e., @g --> group) + - Update to gettext 0.11.5 + - Add Czech translation + - Install message catalogs + - Other miscellaneous NLS bug fixes + * Add new debugfs command, imap, which prints the location of a + specified inode in the inode table. + * Put /usr/include/com_err.h in comerr-dev instead of e2fslibs-dev. + (Closes: #191899) + * Add support for OV-style continuations in compile_et. (Closes: #191900) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 5 May 2003 18:13:12 -0400 + +e2fsprogs (1.33-1) unstable; urgency=low + + * New upstream version (Closes: #189687) + + -- Theodore Y. Ts'o <tytso@mit.edu> Mon, 21 Apr 2003 13:49:52 -0400 + +e2fsprogs (1.32+1.33-WIP-2003.04.14-1) unstable; urgency=low + + * New upstream version + - Add new utility program, logsave, to capture the output of fsck + during the boot sequence + * Add support for the -a and -s options to logsave. + * Change e2fsck to bracket its progress bar output with ctrl-A and ctrl-B + characters, so that logsave -s can omit writing the progress bar output + to the log file. + * Avoid printing the version banner for mke2fs if the -q option is + specified. (Closes: #172716) + + -- Theodore Y. Ts'o <tytso@mit.edu> Wed, 16 Apr 2003 15:27:20 -0400 + +e2fsprogs (1.32+1.33-WIP-2003.03.30-3) unstable; urgency=low + + * Provide /usr/include/com_err.h, which was previously provided by the + libkrb5-dev package + * Change the sectoin of com_err-dev, ss-dev, uuid-dev, libblkid-dev, + e2fslibs-dev to libdevel + * Add libblkid1-udeb package for the Debian Installer. + * Use the SS_READLINE_PATH environment variable to control the search + for a suitable readine library. + * Fix bug in mke2fs, which was was incorrectly checking the argument + to the -g option if the default block size is used. (Closes: #188319) + * Update man pages. (Closes: #188318) + * Mke2fs can be given a minimum block size by passing in a negative + number to the -b option. + * Update to standards 3.5.9 + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 12 Apr 2003 02:52:17 -0400 + +e2fsprogs (1.32+1.33-WIP-2003.03.30-2) unstable; urgency=low + + * Fix XFS superblock definition. Add support to extract UUID and + labels for JFS and ROMFS. + * Make the random number generator more paranoid about potentially buggy + /dev/random devices. + * The badblocks program now flushes its output as it discovers bad blocks. + * Imported bug fixes to EVMS driver from the EVMS 2.0 tree. Fixed a + few potential hangs, and eliminated a file descriptor leak. + * E2fsck now updates the global free block and inode counters from + the block group specific counters quietly. This is needed for an + experimental kernel patch which improves SMP scalability by not + locking the entire filesystem during block or inode allocation; if + the filesystem is not unmoutned cleanly, the global counts may not + be accurate. + * Fix a bug in fsck which can cause it to hang trying to access the + floppy disk if there the floppy drive has filesystem type of + 'auto'. (Closes: #187812) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 6 Apr 2003 23:13:50 -0400 + +e2fsprogs (1.32+1.33-WIP-2003.03.30-1) unstable; urgency=low + + * Change compile_et to generate header files that use <et/com_err.h> + instead of <com_err.h>, so the current version of the header file + is used. Remove legacy K&R, varargs, and pre-POSIX signal support. + * Fix (one more time!) Apple Darwin port in blkid/getsize.c + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 30 Mar 2003 23:34:55 -0500 + +e2fsprogs (1.32+1.33-WIP-2003.03.25-1) unstable; urgency=low + + * New maintainer + * New upstream release (Closes: #176814, #174766, #166048, #179671, + #173612, #175233, #175113, #170497, #185945) + + -- Theodore Y. Ts'o <tytso@mit.edu> Sun, 16 Mar 2003 18:05:08 -0500 + +e2fsprogs (1.32-2) unstable; urgency=high + + * Applied upstream patch to fix htree problems, and to deactivate it by + default in mke2fs (Closes: #181615, #179043) + * Be sure removal of libe2fsim doesn't fail, as it's not built on hurd + (Closes: #164117). + + -- Yann Dirson <dirson@debian.org> Fri, 21 Feb 2003 00:21:44 +0100 + +e2fsprogs (1.32-1) unstable; urgency=low + + * New upstream release (Closes: #167108). + + -- Yann Dirson <dirson@debian.org> Tue, 19 Nov 2002 00:18:09 +0100 + +e2fsprogs (1.29+1.30-WIP-0930-2) unstable; urgency=low + + * Made mkinitrd script to skip commented-out lines (Closes: #163251). + + -- Yann Dirson <dirson@debian.org> Tue, 15 Oct 2002 00:16:08 +0200 + +e2fsprogs (1.29+1.30-WIP-0930-1) unstable; urgency=low + + * New upstream prerelease. + * Replaced in mkinitrd script "tune2fs -j" with "tune2fs -O + has_journal", as suggested by Theodore Ts'o (Closes: #162949). + * Remove --disable-debugfs from mips-nopic flags (Closes: #162674). + + -- Yann Dirson <dirson@debian.org> Thu, 3 Oct 2002 00:05:36 +0200 + +e2fsprogs (1.29-1) unstable; urgency=low + + * New upstream release (Closes: #159423). + * Fixed typo in chattr manpage (Philipp Matthias Hahn, Closes: + #162297). + * Generate udeb package for debian-installer (Martin Sjoegren, Closes: + #162212). + * Fixed installation of mkinitrd script (don't use dh_install). Remove + it from the wrong location where it was, in preinst. Hopefully noone + noticed. + * Also have old scripts/e2fsprogs.mkinitrd removed. + * Bumped Standards-Version to 3.5.6, no change. 3.5.7 will need a bit + of work but not tonight. + + -- Yann Dirson <dirson@debian.org> Thu, 26 Sep 2002 01:46:25 +0200 + +e2fsprogs (1.28-5) unstable; urgency=low + + * The "this time it will work ! (famous last words)" release. + * Now that it builds, ensure the dir in which we install this damn mips + non-pic lib exists. + + -- Yann Dirson <dirson@debian.org> Tue, 17 Sep 2002 00:04:49 +0200 + +e2fsprogs (1.28-4) unstable; urgency=low + + * Moved setting of CFLAGS to the correct place when building the special + mips non-pic lib (Closes: #159757 again). + + -- Yann Dirson <dirson@debian.org> Sun, 15 Sep 2002 21:19:19 +0200 + +e2fsprogs (1.28-3) unstable; urgency=low + + * Don't use special cflags at configure time when building the special + mips non-pic lib, in yet another attempt to fix my adaptation of the + patch from the mips team. Also added --disable-nls which was present + in the original patch. + * Remove debian/BUILD-MIPS on clean. + * Install mkinitrd script as scripts/e2fsprogs, not as + scripts/e2fsprogs.mkinitrd. + + -- Yann Dirson <dirson@debian.org> Mon, 9 Sep 2002 23:01:31 +0200 + +e2fsprogs (1.28-2) unstable; urgency=low + + * Fixed my adapation of the mips non-pic build (Closes: #159757). + + -- Yann Dirson <dirson@debian.org> Fri, 6 Sep 2002 00:03:45 +0200 + +e2fsprogs (1.28-1) unstable; urgency=low + + * New upstream release. + + -- Yann Dirson <dirson@debian.org> Mon, 2 Sep 2002 23:34:55 +0200 + +e2fsprogs (1.27+1.28-WIP-0817-1) unstable; urgency=low + + * New upstream pre-release. Closes: #138003, #144621, #145044, #151990, + #152029, #152891, #155007, #131350, #147256, #153102. + * New binary: findfs. + * Added execute permissions to the mkinitrd script (thanks lintian). + * Don't ship FSIM for EVMS for now. + + -- Yann Dirson <dirson@debian.org> Sun, 25 Aug 2002 19:32:12 +0200 + +e2fsprogs (1.27+1.28-WIP-0626-2) experimental; urgency=low + + * Remove bogus shlibs deps on "e2fsprogs (>= <current>)" + + -- Theodore Y. Ts'o <tytso@mit.edu> Sat, 17 Aug 2002 17:59:17 -0400 + +e2fsprogs (1.27+1.28-WIP-0626-1) experimental; urgency=low + + * New upstream pre-release: + ** Supports v2 ACL format (Closes: #138160). + * Removed explicit --mandir flag, as it now uses FHS man location by + default. + * Added mkinitrd script, "upstream-contributed" ;) by Ted Ts'o (Closes: + #148064). + * Build a no-pic version of libext2fs.a on mips and mipsel, patch by + Florian Lohoff, adapted for style consistency (Closes: #145432). + * Removed presumably-useless and presumably-broken CFLAGS propagation. + If someone misses that, I'll add ${CFLAGS} to --ccopts. + + * Switched to debhelper v4. + * Added ${misc:Depends} to all packages' Depends field. + + * Fixed typos in fsck.8, added an example for clarity (Closes: + #145044). + * Fixed typo in chattr manpage (Closes: #141938). + * Fixed typo in tune2fs manpage (Closes: #148514). + + -- Yann Dirson <dirson@debian.org> Tue, 23 Jul 2002 00:12:33 +0200 + +e2fsprogs (1.27-2) unstable; urgency=medium + + * Urgency medium since this fixes a RC bug. + * Generate the shlibs file instead of just copying it in place, and make + it produce deps on "e2fsprogs (>= <current>)" as well, to cope with + new functions introduced in the libs (Closes: #139274). + * Added a note on this in README.Debian. + + -- Yann Dirson <dirson@debian.org> Thu, 21 Mar 2002 23:58:48 +0100 + +e2fsprogs (1.27-1) unstable; urgency=low + + * New upstream release (Closes: #136737). + * No more use for dh_link'ing *.ext[23], it's now done by upstream + Makefiles. + * Only include (new) inode_io.o from libext2fs when fileio.o is, or the + BF build fails because of this additional (unused) member (upstream + hint). + + -- Yann Dirson <dirson@debian.org> Mon, 11 Mar 2002 00:17:32 +0100 + +e2fsprogs (1.26-3) unstable; urgency=low + + * Simple rebuild after fixing the settings of my computer's clock, so + that katie accepts to install the package. + + -- Yann Dirson <dirson@debian.org> Sat, 23 Feb 2002 14:53:15 +0100 + +e2fsprogs (1.26-2) unstable; urgency=low + + * Applied upstream patch dealing with the rlimit filesize variation + among archs and kernel versions (Closes: #133909). + * Create fsck.ext3.8 symlink (Closes: #121526). + + -- Yann Dirson <dirson@debian.org> Sat, 23 Feb 2002 06:44:02 +0100 + +e2fsprogs (1.26-1) unstable; urgency=low + + * This uploads fixes 10 bugs, including data-corruption problems, and + adds much to the ease of maintainance and problem tracking. Good + choice for woody. + + * New upstream release (Closes: #106622, #116975, #118443, #119624, + #120171, #120077, #129828, #132764). + ** Fixes for data-corruption bugs not reported to the BTS: e2fsck + trashed external journals needing to be replayed, e2fsck now hides + visible journal files (data corruption problems when not excluded from + a backup and then restored) (Closes: #132654). + ** Other noticable bugs fixed include: e2fsck null pointer + dereferencing, fsck did not finds LVM volumes by UUID or by label, + largefile support (ie. dealing with filesystems inside 2GB+ files) was + broken in several programs. + * Switch to debhelper v3 to get ldconfig automatically handled + (lintian reported that it was broken). Now call dh_makeshlibs, but + still override its generated shlibs file with ours, to get compiled + packages depend of the correct virtual packages, which include + full sonames. + * Removed call do dh_installman (Closes: #115526). + * Cleaned up maintainer scripts with dead code - most things are now + more properly handled by debhelper. Removed an "exit 0" lurking in + preinst - can't find a reason for it in the changelog, it was probably + here for ages. + * Remove obsolete maint-scripts in binary-arch, as they are provided by + upstream. + * Also remove upstream-shipped config.cache before configuring. That + shouldn't impact us, but well, that makes lintian happy :) + + -- Yann Dirson <dirson@debian.org> Fri, 8 Feb 2002 06:12:35 +0100 + +e2fsprogs (1.25-1) unstable; urgency=high + + * New upstream bugfix release (Closes: #112414), targeted to woody. + * com_err.info provided again now that it was fixed upstream. + * Added metainfo to com_err.texinfo so that it gets indexed correctly + (thanks lintian). Moved @setfilename and @settitle to the top so that + things get output as expected. + * Added lintian overrides for -bf and -static packages. + * Put all stamp files in debian/stampdir. + + -- Yann Dirson <dirson@debian.org> Sat, 22 Sep 2001 16:22:47 +0200 + +e2fsprogs (1.24a-1) unstable; urgency=high + + * New upstream release (Closes: #109577). + ** The only new code in there is in codepaths that + are only visited when previously unsupported features are used, so + they add virtually no risk. Support for raw image files will be of + great help to debug users' problems. Urgency set to "high" to make + sure this version gets released with woody. + + ** Fsck prints a warning message if now valid filesystems are passed to + it. (Closes: #107458). + ** Fsck -A will not try to interpret device names for filesystems which + have a pass number is 0. (Closes: #106696). + ** If -O none is passed to mke2fs, it will now not set the sparse_super + feature (Closes: #108165). + ** Tune2fs has been fixed to make sure that only error messages go to + stderr, and normal message go to stdout (Closes: #108555). + ** Minor man pages updates (Closes: #30833, #108174). + ** Doc fixes (Closes: #110621). + + -- Yann Dirson <dirson@debian.org> Tue, 4 Sep 2001 23:44:56 +0200 + +e2fsprogs (1.22-2) unstable; urgency=medium + + * This is only a trivial patch to stop some user confusion, and would be + great to have in woody, hence the urgency. + * Applied upstream patch to e2fsck to warn user when some errors were + not corrected due to user answering "no" (Closes: #104502). + + -- Yann Dirson <dirson@debian.org> Sat, 28 Jul 2001 23:01:49 +0200 + +e2fsprogs (1.22-1) unstable; urgency=low + + * Final 1.22 release: + ** Fixes build problems on big-endian (Closes: #101686, #101798). + + -- Yann Dirson <dirson@debian.org> Sat, 23 Jun 2001 14:03:17 +0200 + +e2fsprogs (1.21+1.22-WIP-0620-1) unstable; urgency=low + + * New upstream pre-release, critical for big-endian platforms + (Closes: #101752). + * Re-applied hurd fix again. + * Build e2fsprogs-bf with -Os to gain more space. + + -- Yann Dirson <dirson@debian.org> Fri, 22 Jun 2001 00:18:40 +0200 + +e2fsprogs (1.21-1) unstable; urgency=low + + * Final 1.21 release. + * Re-applied hurd fix that did not came quickly enough to make it in + 1.21. + * Fixed name of copyright file in e2fsprogs-bf. + + -- Yann Dirson <dirson@debian.org> Wed, 20 Jun 2001 22:32:08 +0200 + +e2fsprogs (1.20+1.21-WIP-0614-2) unstable; urgency=low + + * Don't build PIC libs, build a reduced version of the libs instead, in + package e2fsprogs-bf. Made this new package conflict with e2fsprogs. + * Compilation fix for the Hurd (Closes: #101361). + + -- Yann Dirson <dirson@debian.org> Tue, 19 Jun 2001 23:33:25 +0200 + +e2fsprogs (1.20+1.21-WIP-0614-1) unstable; urgency=low + + * New upstream pre-release (Closes: #100559, #100304). + * Fixed lib/ext2fs/Makefile.in for installation of new generated .h + file. + + -- Yann Dirson <dirson@debian.org> Thu, 14 Jun 2001 16:14:11 +0200 + +e2fsprogs (1.20+1.21-WIP-0608-1) unstable; urgency=low + + * New upstream pre-release (critical ext3 bugfix mostly). + * Correctly use dh_installinfo. + * Adjusted various things accordingly. + + -- Yann Dirson <dirson@debian.org> Sat, 9 Jun 2001 00:25:51 +0200 + +e2fsprogs (1.20-4) unstable; urgency=low + + * Cleanup generated substvars files now that debhelper uses other + names (may cause problems on other archs). Build-dep on debhelper + 3.0.30 or newer to be sure it won't cause broken uploads. Allows to + get rid of hairy dep, but cannot build straightforwardly on potato any + more... + + -- Yann Dirson <dirson@debian.org> Wed, 6 Jun 2001 02:33:32 +0200 + +e2fsprogs (1.20-3) unstable; urgency=low + + * Create all symlinks to uuid-generate.3 (Closes: #99573). + * Somewhat modernized debian/rules (debhelper v2, etc.). + * Fixed libss2 copyright file. + * Fixed e2fslibs-pic short description. + + -- Yann Dirson <dirson@debian.org> Wed, 6 Jun 2001 01:19:19 +0200 + +e2fsprogs (1.20-2) unstable; urgency=low + + * Added support for building pic libs to Makefile.elf-lib. + * New package e2fslibs-pic for boot-floppies team (Closes: #99285). + * Use -N on dh_gencontrol instead of lots of -p. + + -- Yann Dirson <dirson@debian.org> Thu, 31 May 2001 23:59:51 +0200 + +e2fsprogs (1.20-1) unstable; urgency=low + + * Final 1.20 release. + * Added new zsh-static to the list of possible static shells recommended + by e2fsck-static. + + -- Yann Dirson <dirson@debian.org> Mon, 28 May 2001 21:39:06 +0200 + +e2fsprogs (1.19+1.20-WIP-0520-1) unstable; urgency=low + + * New upstream pre-release snapshot: + ** Extended "fsck -t" syntax (Closes: #89483). + ** Fix handling of devices for which fsck can't determine a physical + spindal, causing lockup when checking LVM volumes (Closes: #98103). + ** Fixed typo in e2fsck-static description - thanks Ted :). + * Fixed small compilation bug in fsck.c + + -- Yann Dirson <dirson@debian.org> Mon, 21 May 2001 20:47:10 +0200 + +e2fsprogs (1.19+1.20-WIP-0514-2) unstable; urgency=low + + * Tighten dependency on debhelper. + + -- Yann Dirson <dirson@debian.org> Tue, 15 May 2001 21:38:47 +0200 + +e2fsprogs (1.19+1.20-WIP-0514-1) unstable; urgency=low + + * New upstream pre-release snapshot: + ** new program: e2image. + ** e2fsck validates file descriptor specified in -C (Closes: #55220) + ** Fix multiple progress bar fsck bug (Closes: #65267) + ** Add devfs support to fsck (Closes: #94159) + ** Fix debugfs dump cmd looping on disk errors (Closes: #79163) + ** Miscellaneous manual page clarifications (Closes: #63442, #67446, + #87216) + ** Compilation fixes for Hurd (Closes: #52045). + ** New config.{guess,sub} for parisc support (Closes: #94690). + ** Improved ext3 support + ** tune2fs can now safely modify mounted filesystems + * Added missing @dircategory entry to libext2fs.info (lintian) + * Moved debugfs back from /usr/sbin/ to /sbin/ (Closes: #97035). + * Moved e2label back to /sbin/ as well, as it is now a hard link to + tune2fs. + * New binary package with statically linked e2fsck, recommending a + statically linked shell (Closes: #62611). + * All deps against e2fsprogs itself now versionned (lintian). + * Updated copyright file (upstream location, packaging copyright notice + for previous maintainers and for Alcove). + * Remove call to dh_testversion, use versionned build-dep instead + (lintian). + * Support for DEB_BUILD_OPTIONS debug/nostrip for policy 3.2 + compliance. + * Use dh_shlibdeps -l instead of setting LD_LIBRARY_PATH explicitely - + necessary for new versions of fakeroot, and requires debhelper 3.0.23 + for a fix. Well finally 3.0.23 is buggy, leave this for later. + * Avoid to call ldconfig at "make install" time, too costly. + * Get rid in control files of references to never-released standalone + lib files (split attempted in 1997/98). + * Bumped Standards-Version to 3.5.4. + + -- Yann Dirson <dirson@debian.org> Tue, 15 May 2001 14:28:39 +0200 + +e2fsprogs (1.19-4) unstable; urgency=medium + + * Added texinfo to build-deps (Closes: #87685). + + -- Yann Dirson <dirson@debian.org> Tue, 3 Apr 2001 09:03:13 +0200 + +e2fsprogs (1.19-3) unstable; urgency=low + + * Drop findsuper binary, and suggest gpart (Closes: #74034). + * Drop flushb and extend at upstream request (Closes: #39506). + * Applied upstream fix for chattr on large files (Closes: #72690). + * Applied clarification patch to tune2fs.8 (Closes: #67446). + * Applied typo patch to compile_et.1 (Closes: #63786). + * Include <sys/mount.h> in e2fsck/journal.c (Closes: #71775). + * Suggest parted. + + -- Yann Dirson <dirson@debian.org> Mon, 4 Dec 2000 22:08:06 +0100 + +e2fsprogs (1.19-2) unstable; urgency=low + + * Clarified libuuid copyright to LGPL-2, excluding LGPL-2.1. + * Added build-dependency on debhelper (Closes: #67532). + * Don't paralelize fsck runs on same drive for hd[efgh] (Closes: + #59103). + * Upload pristine source, -1 was erroneously uploaded as a + debian-specific package. + + -- Yann Dirson <dirson@debian.org> Thu, 3 Aug 2000 00:30:49 +0200 + +e2fsprogs (1.19-1) unstable; urgency=low + + * New upstream release: + ** new program: resize2fs. + ** ext3 support. + ** NLS support (non-default, activated). + ** Compression support (non-default, activated). + ** Progress bar nice to serial console (Closes: #66079) + ** Ensure filetype feature is turned off for Hurd filesystems (Closes: + #61863) + * Updated main copyright file for a number of things. + * Fixed NLS support for flushb and extend. + * Started to add build-depends. + * Include new e2p header. + + -- Yann Dirson <dirson@debian.org> Wed, 19 Jul 2000 01:55:27 +0200 + +e2fsprogs (1.18-3) frozen unstable; urgency=medium + + * Fix Y2K display-only bug in debugfs - "ls -l" displayed raw tm_year, + causing 2000 to be displayed as "100" (Closes: #57135). Potato should + be y2k-clean. + * Remove empty dirs /usr/share/et/ and /usr/share/ss/ from package + e2fsprogs (Closes: #52900). + + -- Yann Dirson <dirson@debian.org> Mon, 21 Feb 2000 23:06:47 +0100 + +e2fsprogs (1.18-2) unstable; urgency=low + + * Test for "__sparc__" instead of "sparc" as a cpp macro in mke2fs.c + (tests in other places are correct) (Closes: #50012). + + -- Yann Dirson <dirson@debian.org> Fri, 12 Nov 1999 21:40:27 +0100 + +e2fsprogs (1.18-1) unstable; urgency=low + + * New upstream (bugfix) release. + + -- Yann Dirson <dirson@debian.org> Fri, 12 Nov 1999 17:27:20 +0100 + +e2fsprogs (1.17-2) unstable; urgency=low + + * Applied upstream patch to fix segfault (Closes: #49535). + + -- Yann Dirson <dirson@debian.org> Tue, 9 Nov 1999 22:14:53 +0100 + +e2fsprogs (1.17-1) unstable; urgency=low + + * New upstream (bugfix) release. + + -- Yann Dirson <dirson@debian.org> Wed, 27 Oct 1999 23:46:39 +0200 + +e2fsprogs (1.16-2) unstable; urgency=low + + * Fixed build of a link list in fsck.c (Closes: #48312). + + -- Yann Dirson <dirson@debian.org> Tue, 26 Oct 1999 01:17:36 +0200 + +e2fsprogs (1.16-1) unstable; urgency=low + + * New upstream release. + * Re-applied Hurd patches that did not seem to have been received + upstream. + + -- Yann Dirson <dirson@debian.org> Sun, 24 Oct 1999 16:11:59 +0200 + +e2fsprogs (1.15-3) unstable; urgency=low + + * Fixed minor typo for the Hurd. + * Fixed various Hurd defines to __GNU__ (Closes: #44407). + * Switched doc/ and info/ to FHS. + * Cleaned up debian/rules to use new debhelper features. + * Bounced Standards-Version to 3.0.1. + * Do not install buggy com_err.info, shipped as HTML. + * Removed partinfo from the package, following the wish of upstream + author, because of duplicate functionality with "fdisk -l" (Closes: + #42139). + + -- Yann Dirson <dirson@debian.org> Mon, 20 Sep 1999 23:04:06 +0200 + +e2fsprogs (1.15-2) unstable; urgency=medium + + * Changed build directory do debian/BUILD/ - related cleanups in + debian/rules. + * Fixed partinfo.c to have it compiled, and fixed display of partition + device in error messages. + * Added /usr/sbin/partinfo to the package (Closes: #42139). + * Added note about uuidgen(1) in README.Debian. + * Documented in manpage that default mke2fs behaviour is now -r1 -s1 + (Closes: #44478). + * Documented in mke2fs.8 that -r1 forces -s1, thus ignoring -s0. + * Added warning message when -s0 is ignored because of -r1. + * Documented -n option of mke2fs. + * Fixed display buglet causing trailing commas in list of superblock + backups when sparse flag is on and last group has no superblock + backup. + * Closes: #42434, #43134. + + -- Yann Dirson <dirson@debian.org> Wed, 8 Sep 1999 00:46:38 +0200 + +e2fsprogs (1.15-1) unstable; urgency=low + + * New upstream release (Closes: Bug#41763). + * All changes to upstream files in 1.14-3 were integrated upstream. + * Separated libuuid-dev from e2fslibs-dev because it now has manpages. + * Fixed debian/rules for POSIX "rmdir -p" + * Corrected the location of the GPL in copyright file. + * Moved the manpages to /usr/share/. + * Bumped Standards-Version to 3.0.0. + + -- Yann Dirson <dirson@debian.org> Fri, 23 Jul 1999 01:37:51 +0200 + +e2fsprogs (1.14-3) unstable; urgency=low + + * Fail with error message when /dev/null cannot be opened (Fixes: + Bug#35595). + * Fixed typo in e2fsck/unix.c (Fixes: Bug#36960). + * Added "emeregency help" options summary to e2fsck (Fixes: Bug#11372). + * Prepared debian/rules for usr/share/man/. + + -- Yann Dirson <dirson@debian.org> Tue, 1 Jun 1999 23:37:12 +0200 + +e2fsprogs (1.14-2) unstable; urgency=low + + * Fixed fsck(1) not to coredump when it does not find its argument in + /etc/fstab (Fixes: Bug#33533, Bug#34320, part of Bug#34131). + * Fixed spelling of upstream author's name. + * Cleaned debian/*.files up. + * Undid the <linux/types.h> changes. + * Changed "rmdir -p" invocations in debian/rules into "-rmdir -p" to + turn around changed behaviour in fileutils_4.0. + + -- Yann Dirson <dirson@debian.org> Fri, 12 Mar 1999 23:50:47 +0100 + +e2fsprogs (1.14-1) unstable; urgency=low + + * New upstream release (Fixes: Bug#33113). + * All patches we used for 1.12 are obsoleted by 1.14. + * Still have to install com_err.info from debian/rules though. + * Incorporated patches from Gordon Matzigkeit for hurd cross-compilation: + * - configure.in: Change cross-compile default for sizeof (long + long) to 8, so that __s64 and __u64 get defined in ext2fs.h. + (BUILD_CC): Discover a native compiler if we are cross-compling + (used for util/subst). + - Include linux/types.h instead of asm/types.h, so that + non-Linux platforms use the stubbed version provided with this + package. + - misc/Makefile.in (findsuper): Add a rule so that findsuper gets built + with the right compiler flags. + - etc. + + -- Yann Dirson <dirson@debian.org> Wed, 10 Feb 1999 23:23:03 +0100 + +e2fsprogs (1.12-4) frozen unstable; urgency=low + + * Ship flushb(8) and extend(8) were missing in all 1.12 packages + (Fixes: Bug#28771). + * Add extend.8 link to undocumented.7. + * Replaced my (ad-hoc) fix for Bug#25684 with (really better) one + from upstream. + + -- Yann Dirson <dirson@debian.org> Mon, 2 Nov 1998 20:53:28 +0100 + +e2fsprogs (1.12-3) frozen unstable; urgency=low + + * Fixed <ext2fs/ext2fs.h> to use angle brackets instead of double + quotes when including files from /usr/include/. + * Made e2fslibs-dev depend on comerr-dev (Fixes: Bug#26282, + Bug#27497). + * Fixed mke2fs' display with inode numbers > 9999 (Fixes: Bug#25684). + * Use -D__NO_STRING_INLINES on powerpc to allow building the boot + blocks in QUIK, the powermac boot loader - reported by Matt + McLean. + * Removed unsupported info and texi entries from docbase files. + + -- Yann Dirson <dirson@debian.org> Mon, 19 Oct 1998 23:32:41 +0200 + +e2fsprogs (1.12-2.1) unstable; urgency=low + + * Non-maintainer upload + config.guess and config.sub files modified, to recognize a Arm + architecture. + + -- Turbo Fredriksson <turbo@debian.org> Thu, 13 Aug 1998 19:15:56 -0400 + +e2fsprogs (1.12-2) unstable; urgency=low + + * Really install e2label.8 manpage. + * Removed path from ldconfig invocation, obeying packaging manual. + * Improved the subst.c patch (thanks to Peter Moulder). + + -- Yann Dirson <dirson@debian.org> Thu, 14 Jul 1998 14:10:06 +0200 + +e2fsprogs (1.12-1) unstable; urgency=low + + * New upstream release - at last out of alpha status ! + * Removed some obsolete files from debian/attic. + * Patched util/subst.c to expand env variables, and MCONFIG.in to + have ${prefix} exported to the `subst' process, so that we get + correct paths in mk_cmds and compile_et. Forwarded upstream. + * Debian-specific /usr/share/comerr/ renamed to /usr/share/et/, now + installed upstream. + * Removed -isp from dh_gencontrol invocation - now the default. + * Passed lintian 0.5.0. + + -- Yann Dirson <dirson@debian.org> Fri, 10 Jul 1998 22:49:18 +0200 + +e2fsprogs (1.10-17) frozen unstable; urgency=low + + * Commented out obsolete code in fsck.c that assumed fstab entries + declared `noauto' should not be checked - successfully forwarded + upstream (Fixes: Bug#17244). + + -- Yann Dirson <dirson@debian.org> Fri, 15 May 1998 01:14:54 +0200 + +e2fsprogs (1.10-16) frozen unstable; urgency=low + + * Changed <linux/types.h> to <asm/types.h> in lib/uuid/uuidP.h to + allow compilation with glibc 2.0.7pre1 (Fixes: Bug#22039). + * Use "build-stamp" as a stamp file instead of "build". + * Restored "Provides: e2fslibsg" in order to allow upgrade from + unstable hamm. Documented in README.Debian so that it does not + get removed again (Fixes: Bug#22019). + + -- Yann Dirson <dirson@debian.org> Mon, 4 May 1998 21:11:38 +0200 + +e2fsprogs (1.10-15) frozen unstable; urgency=low + + * Added call to ldconfig in e2fsprogs.postinst. + * Fixes checks for install-docs in postinst/prerm (Fixes: Bug#20303, + Bug#20304, Bug#20590). + * Removed e2fslibsg from what e2fsprogs provides (was just forgotten). + * Passed lintian 0.4.2. + + -- Yann Dirson <dirson@debian.org> Sun, 26 Apr 1998 22:27:11 +0200 + +e2fsprogs (1.10-14) frozen unstable; urgency=low + + * Fixed checks for install-docs to use -x. + * Applied patch for sparc from Juan to fsck.c to compile with glibc + 2.1 (Fixes: Bug#20841). + + -- Yann Dirson <dirson@debian.org> Tue, 14 Apr 1998 17:12:19 +0200 + +e2fsprogs (1.10-13) frozen unstable; urgency=low + + * test for /usr/sbin/install-docs before trying to run it in + postinst and prerm (Fixes: Bug#19461, Bug#19469, Bug#19949, + Bug#20006). + * comerrg-dev now suggests doc-base. + * moved binary packages ss2g, comerr2g and e2fslibsg back into + binary package e2fsprogs. + * use new virtual packages libcomerr2, libss2, libext2fs2, libe2p2, + libuuid1 in shlibs and dependencies. + * Changed e2fsprogs dependency on libs to a Pre-Depends (Fixes: + Bug#18221). + * Not conflicting with old ss2g and comerr2g - these will have to be + removed by hand. + * Turned around dpkg's bug #17624 in e2fsprogs.preinst. + * Updated README.Debian to explain the new package architecture. + * Passed lintian 0.3.4. + + -- Yann Dirson <dirson@debian.org> Fri, 20 Mar 1998 13:03:11 +0100 + +e2fsprogs (1.10-12) unstable; urgency=low + + * Corrected doc menu entries to point to the real documents' places. + * Fixed mk_cmds to really find its support scripts (Fixes: Bug#18779). + * Made mk_cmds and compile_et use "sh -e". + * Have missing file /usr/include/ss/ss_err.h installed (Fixes: Bug#18778). + * Corrected typo in Description (Fixes: Bug#18890). + * Fixed descriptions for ss* packages, thanks to Greg Stark (Fixes: + Bug#18373, Bug#18447). + * Added description of e2p and uuid libs in e2fslibsg-dev description. + * Included texinfo sources. + * Added doc-base support - suppressed direct menu/dwww support. + * Complies with standards version 2.4.0.0. + * Passed lintian 0.3.0: + * removed .du control file. + * updated FSF address. + * fixed in *.files nasty ldconfig-symlink-before-shlib-in-deb's. + * turned relative links from /usr/lib into /lib into absolute ones. + + -- Yann Dirson <dirson@debian.org> Sun, 8 Mar 1998 19:42:58 +0100 + +e2fsprogs (1.10-11) unstable; urgency=low + + * Switched to debhelper (Fixes:Bug#16307). + * Updated standards to 2.3.0.1 + * Changed maintainer's mail address. + * Added conflicts with old versions of dump and quota. + * Added html-converted texi docs for libs, with menu(dwww) support. + * Added findsuper.8 link to undocumented. + * Changed version number of lib packages to reflect the lib versions. + * Moved libss into its own packages; added mk_cmds script and + support files for libss development (Fixes:Bug#17233). + * Added README.Debian file documenting all those dependency stuff. + * Included example error tables from libext2fs and libss in + comerr-dev. + * Included example command tables from debugfs in ss-dev. + * Added section/priority files in packages (-isp). + * Changed names/relations for doc dirs to comply with policy. + * Removed call to ldconfig from e2fsprogs.postinst. + + -- Yann Dirson <dirson@debian.org> Thu, 29 Jan 1998 18:10:03 +0100 + +e2fsprogs (1.10-10) unstable; urgency=low + + * Added patch from Michael Alan Dorman for compilation on alpha-Linux + (Closes:Bug#15596). + * Added '-fsigned-char' to COPTS to allow compilation on ppc-Linux + (Closes:Bug#15976). + * Suppressed Essential flag on libs, as well as useless Replaces + (Closes: Bug#16480). + * Suppressed reference to obsolete package `e2fsprogsg' in control + info, but Conflicts for security (Closes:Bug#16791). + + -- Yann Dirson <dirson@univ-mlv.fr> Wed, 7 Jan 1998 22:35:08 +0100 + +e2fsprogs (1.10-9) unstable; urgency=low + + * Fixed comerr2g.shlibs to reflect package-name change. + * Fixed problem with ss include files being removed from /usr on make + install (indeed fixed in 1.10-8). + * Added changelog file to comerr2g package (indeed fixed in 1.10-8). + * Corrected link from flushb.8 to undocumented (Closes:Bug#15335,Bug#15660,Bug#15675). + * Added /sbin/findsuper (Closes:Bug#15224). + * Fixed /usr/bin/compile_et script (Closes:Bug#15487). + * Included awk scripts in /usr/share/comerr, for use by compile_et. + * Changed back the name from "e2fsprogsg" to "e2fsprogs" to get better + dependencies. + * Strip libraries (Closes:Bug#15667). + + -- Yann Dirson <dirson@univ-mlv.fr> Tue, 9 Dec 1997 22:52:42 +0100 + +e2fsprogs (1.10-8) unstable; urgency=low + + * Added latest patch from Ted for autodetection of llseek() proto. + * Switched to libc6, without libc5 compatibility (yet ?). + * Turned Pre-Depends into Depends to allow installation. Dirty + though. But what were Pre-Depends for anyway ? + + -- Yann Dirson <dirson@univ-mlv.fr> Sun, 23 Nov 1997 23:03:02 +0100 + +e2fsprogs (1.10-7) unstable; urgency=HIGH + + * Turned "#if (__GLIBC__ == 2)" into "#if 1" to turn around missing llseek() + prototype in libc_5.4.33-5 as well as libc6. + + -- Yann Dirson <dirson@univ-mlv.fr> Tue, 21 Oct 1997 12:53:27 +0200 + +e2fsprogs (1.10-6) unstable; urgency=low + + * Official libc6 patches from Ted. + * Converted to debstd - let it do the stripping stuff. + * Separated libcomerr into a standalone lib - includes full doc and tools. + * Separated development files into e2fslibs-dev, which Provides the 4 other + -dev packages. + * Now Provides the 4 other lib packages, to make it possible not to depend + upon e2fsprogs itself. These libs WILL be taken out of "progs" in the + next release. + + -- Yann Dirson <dirson@univ-mlv.fr> Wed, 24 Sep 1997 10:46:00 +0200 + +e2fsprogs (1.10-5.1) experimental; urgency=low + + * Applied patch from Ted for libc6 compatibility, for test purpose. + + -- Yann Dirson <dirson@univ-mlv.fr> Thu, 11 Sep 1997 09:09:42 +0200 + +e2fsprogs (1.10-5) unstable; urgency=medium + + * Switched back to libc5 because of possible bug in libc6-2.0.4-provided + llseek() causing problem with partitions > 2Gb. + * Switched back to libc-provided llseek(). + + -- Yann Dirson <dirson@univ-mlv.fr> Tue, 5 Aug 1997 16:54:40 +0200 + +e2fsprogs (1.10-4.1) unstable; urgency=low + + * Make use of shipped llseek instead of glibc's which seems buggy + [unreleased - could not compile due to possible gcc bug]. + * Corrected compiler-options handling in debian/rules (use CCOPTS instead + of CFLAGS which is messed with in configure.in). + + -- Yann Dirson <dirson@univ-mlv.fr> Mon, 28 Jul 1997 19:47:02 +0200 + +e2fsprogs (1.10-4) unstable; urgency=low + + * Switched to libc6. + * Added calls to update-info in postins/prerm. + * Misc changes to debian/rules; some cleanup in Makefiles. + + -- Yann Dirson <dirson@univ-mlv.fr> Thu, 10 Jul 1997 19:42:54 +0200 + +e2fsprogs (1.10-3) stable unstable; urgency=low + + * New maintainer (closed many obsolete bug-reports). + * updated "copyright" to show new location on tsx-11. + * started debian/rules cleanup, towards new policy conformance. + * Added flushb.8 link to undocumented.7 (bug #8644). + * Added {fsck,mkfs}.ext2.8 links to existing manpages (bugs #5598, + #6286). + + -- Yann Dirson <dirson@univ-mlv.fr> Wed, 25 Jun 1997 14:59:58 +0200 + +e2fsprogs (1.10-2) frozen unstable; urgency=low + + * Add 'ldconfig' to postinst (should fix #9020). + * Define HAVE_NETINET_IN_H on alpha/glibc. + + -- Klee Dienes <klee@debian.org> Tue, 29 Apr 1997 17:24:12 -0400 + +e2fsprogs (1.10-1) frozen unstable; urgency=medium + + * Upstream bug-fix release. + + -- Klee Dienes <klee@debian.org> Thu, 24 Apr 1997 14:54:12 -0400 + +e2fsprogs (1.09-1) frozen; urgency=medium + + * Upstream bug-fix release. + + -- Klee Dienes <klee@debian.org> Thu, 24 Apr 1997 14:54:12 -0400 + +e2fsprogs (1.06-4) unstable; urgency=low + + * Added empty entries to shlibs.local, to neatly solve the pre-depends + problem, as suggested by Ian Jackson. + + -- Michael Nonweiler <mrn20@cam.ac.uk> Wed, 13 Nov 1996 08:13:28 +0000 + +e2fsprogs (1.06-3) unstable; urgency=low + + * Hard coded Pre-Depends line, as a temporary fix for the pre-depends + contains e2fsprogs problem. + + -- Michael Nonweiler <mrn20@cam.ac.uk> Sat, 9 Nov 1996 12:57:44 +0000 + +e2fsprogs (1.06-2) unstable; urgency=low + + * New packaging format + * Fixes packaging bugs - + Files in /lib are now stripped of all unneeded symbols (Bug#5121) + Calls to ldconfig in maintainer scripts have been removed (Bug#4247) + + -- Michael Nonweiler <mrn20@cam.ac.uk> Tue, 5 Nov 1996 21:14:54 +0000 + +e2fsprogs (1.01-1) unstable; urgency=low + + * upgraded to latest upstream version, to 1.06 from 1.05 + * upgraded to latest upstream version, to 1.05 from 1.04 + * gzip manpages + * minor changes to debian.rules + + -- Michael Meskes <meskes@debian.org> Fri, 18 Oct 1996 00:00:00 +0000 + +e2fsprogs (1.04-1) unstable; urgency=low + + * upgraded to latest upstream version, to 1.04 from 1.02 + * another tidy-up of debian.rules + * section and priority added to debian.control, since this is an + essential base package. + + -- Michael Nonweiler <mrn20@cam.ac.uk> Sun, 23 Jun 1996 00:00:00 +0000 + +e2fsprogs (1.02-1) unstable; urgency=low + + * upgraded to latest upstream version, to 1.02 from 1.01 + * copied "configure" usr_prefix change (see below), into configure.in + * updated debian.control file, added Pre-Depends field + created preinst script to check dpkg --assert-predepends + tidyed and fixed debian.rules + * set e2fsck to link shared, as suggested by Bruce Perens in Bug#2332 + * corrected problem in e2fsck error message, Bug#2534 + * added Architecture field + * very minor correction to expected output of a build time test + + -- Michael Nonweiler <mrn20@cam.ac.uk> Tue, 5 Mar 1996 00:00:00 +0000 + +e2fsprogs (1.01-1) unstable; urgency=low + + * removed debugging symbols from libs and enabled more optimization + as suggested by Rolf Rossius + * also removed the /var/catman pages + * changed to elf compilation + + -- Andrew D. Fernandes <adfernan@cnd.mcgill.ca> Mon, 20 Nov 1995 00:00:00 +0000 + +e2fsprogs (0.5b-2) unstable; urgency=low + + * Upgraded to latest version, to 1.01 from 0.5b. + * changed the installation groups from bin to root in MCONFIG.in + * changed configure to set usr_prefix="\${prefix}/usr" + * moved the cat pages to /var/catman in MCONFIG.in + + -- Andrew D. Fernandes <adfernan@cnd.mcgill.ca> Sat, 7 Oct 1995 00:00:00 +0000 + +e2fsprogs (0.5b-1) unstable; urgency=low + + * Made "fsck -t <filesystem-type> <device>" work correctly. Formerly + the -t argument was overriden by the filesystem type listed for the + device in /etc/fstab. + * added Debian GNU/Linux package maintenance system files + + -- Bruce Perens <Bruce@Pixar.com> Thu, 3 Aug 1995 00:00:00 +0000
diff --git a/debian/comerr-dev.doc-base b/debian/comerr-dev.doc-base new file mode 100644 index 0000000..463eb76 --- /dev/null +++ b/debian/comerr-dev.doc-base
@@ -0,0 +1,12 @@ +Document: comerr-manual +Title: The com_err library +Author: Ken Raeburn and Bill Sommerfeld +Abstract: A library, and associated utilities, + which allow a more uniform way for libraries + to return errors to their callers, and for programs + to describe errors and exceptional conditions to their users. +Section: Programming + +Format: HTML +Index: /usr/share/doc/comerr-dev/html-info/com_err.html +Files: /usr/share/doc/comerr-dev/html-info/*.html
diff --git a/debian/comerr-dev.examples b/debian/comerr-dev.examples new file mode 100644 index 0000000..aff20cc --- /dev/null +++ b/debian/comerr-dev.examples
@@ -0,0 +1,2 @@ +lib/ss/ss_err.et +debian/BUILD-STD/lib/ext2fs/ext2_err.et
diff --git a/debian/comerr-dev.files.in b/debian/comerr-dev.files.in new file mode 100644 index 0000000..a3b8b0e --- /dev/null +++ b/debian/comerr-dev.files.in
@@ -0,0 +1,9 @@ +usr/lib/*/libcom_err.a +usr/lib/*/libcom_err.so +usr/include/et/* +usr/include/com_err.h +usr/share/man/man1/compile_et* +usr/share/man/man3/com_err.3* +usr/bin/compile_et +usr/share/et/* +usr/lib/*/pkgconfig/com_err.pc
diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7f8f011 --- /dev/null +++ b/debian/compat
@@ -0,0 +1 @@ +7
diff --git a/debian/control.in b/debian/control.in new file mode 100644 index 0000000..7624029 --- /dev/null +++ b/debian/control.in
@@ -0,0 +1,337 @@ +define(MULTIARCH_HEADERS,ifdef(`DO_MULTIARCH', +Multi-Arch: same +Pre-Depends: ${misc:Pre-Depends},REMOVE_ME))dnl +define(UTIL_LINUX_NG_DEFINES, +ifdef(`UTIL_LINUX_NG', ``libblkid-dev (>= 2.16), uuid-dev (>= 2.16),''))dnl +define(DIETLIBC_DEFINES, +ifdef(`DIETLIBC', ``dietlibc-dev (>> 0.30) [alpha amd64 arm hppa i386 ia64 powerpc ppc64 s390 sparc],''))dnl +Source: e2fsprogs +Section: admin +Priority: required +Maintainer: Theodore Y. Ts'o <tytso@mit.edu> +Build-Depends: gettext, texinfo, pkg-config, DIETLIBC_DEFINES gcc-multilib [mips mipsel], debhelper (>= 7.0), UTIL_LINUX_NG_DEFINES m4 +Standards-Version: 3.9.6 +Homepage: http://e2fsprogs.sourceforge.net + +ifdef(`E2FSCK_STATIC',`` +Package: e2fsck-static +Priority: optional +Depends: ${shlibs:Depends}, ${misc:Depends} +Recommends: sash | bash-static | zsh-static | busybox-static | zsh30-static +Architecture: any +Description: statically-linked version of the ext2/ext3/ext4 filesystem checker + This may be of some help to you if your filesystem gets corrupted enough + to break the shared libraries used by the dynamically linked checker. + . + This binary takes much more space than its dynamic counterpart located + in e2fsprogs, though. + . + You may want to install a statically-linked shell as well, to be able + to run this program if something like your C library gets corrupted. +'')dnl + +Package: libcomerr2 +Section: libs +Provides: libcomerr-kth-compat +Depends: ${shlibs:Depends}, ${misc:Depends} +Replaces: e2fsprogs (<< 1.34-1) +Architecture: any +MULTIARCH_HEADERS +Description: common error description library + libcomerr is an attempt to present a common error-handling mechanism to + manipulate the most common form of error code in a fashion that does not + have the problems identified with mechanisms commonly in use. + +Package: comerr-dev +Section: libdevel +Priority: extra +Depends: libc6-dev | libc-dev, libcomerr2 (= ${mainBinary}), ${misc:Depends} +Suggests: doc-base +Replaces: e2fslibs-dev (<< 1.33-2), libkrb5-dev (<< 1.3) +Architecture: any +Description: common error description library - headers and static libraries + libcom_err is an attempt to present a common error-handling mechanism to + manipulate the most common form of error code in a fashion that does not + have the problems identified with mechanisms commonly in use. + . + This package contains the development environment for the com_err library. + +Package: libss2 +Section: libs +Depends: libcomerr2, ${shlibs:Depends}, ${misc:Depends} +Replaces: e2fsprogs (<< 1.34-1) +Architecture: any +MULTIARCH_HEADERS +Description: command-line interface parsing library + libss provides a simple command-line interface parser which will + accept input from the user, parse the command into an argv argument + vector, and then dispatch it to a handler function. + . + It was originally inspired by the Multics SubSystem library. + +Package: ss-dev +Section: libdevel +Priority: extra +Depends: libc6-dev | libc-dev, libss2 (= ${mainBinary}), comerr-dev, ${misc:Depends} +Architecture: any +Description: command-line interface parsing library - headers and static libraries + This package includes a tool that parses a command table to generate + a simple command-line interface parser, the include files needed to + compile and use it, and the static libs. + . + It was originally inspired by the Multics SubSystem library. + . + This package contains the development environment for the ss library. +ifdef(`UTIL_LINUX_NG',,`` +Package: libuuid1 +Section: libs +Depends: passwd, ${shlibs:Depends}, ${misc:Depends} +Recommends: uuid-runtime +Replaces: e2fsprogs (<< 1.34-1) +Architecture: any +MULTIARCH_HEADERS +Description: Universally Unique ID library + The libuuid library generates and parses 128-bit universally unique + ids (UUIDs). A UUID is an identifier that is unique across both + space and time, with respect to the space of all UUIDs. A UUID can + be used for multiple purposes, from tagging objects with an extremely + short lifetime, to reliably identifying very persistent objects + across a network. + . + See RFC 4122 for more information. + +Package: uuid-runtime +Section: libs +Priority: optional +Depends: passwd, libuuid1 (>> 1.40.3-1), ${shlibs:Depends}, ${misc:Depends} +Replaces: e2fsprogs (<= 1.40.3-1ubuntu1) +Architecture: any +Description: runtime components for the Universally Unique ID library + The libuuid library generates and parses 128-bit universally unique + ids (UUIDs). A UUID is an identifier that is unique across both + space and time, with respect to the space of all UUIDs. A UUID can + be used for multiple purposes, from tagging objects with an extremely + short lifetime, to reliably identifying very persistent objects + across a network. + . + See RFC 4122 for more information. + . + This package contains the uuidgen program and the uuidd daemon. + . + The uuidd daemon is used to generate UUIDs, especially time-based + UUID’s, in a secure and guaranteed-unique fashion, even in the face + of large numbers of threads trying to grab UUID’s running on + different CPU’s. It is used by libuuid as well as the uuidgen + program. + +ifdef(`UDEB_PKGS',`` +Package: libuuid1-udeb +XC-Package-Type: udeb +Section: debian-installer +Priority: optional +Depends: ${shlibs:Depends} +Architecture: any +Description: stripped down universally unique id library, for debian-installer + libuuid generates and parses 128-bit universally unique ids (UUIDs). + See RFC 4122 for more information. + . + This is a minimal package for debian-installer. +'')dnl + +Package: uuid-dev +Section: libdevel +Priority: extra +Depends: libc6-dev | libc-dev, libuuid1 (= ${mainBinary}), ${misc:Depends} +Replaces: e2fslibs-dev (<< 1.15) +Architecture: any +Description: universally unique id library - headers and static libraries + libuuid generates and parses 128-bit universally unique ids (UUIDs). + See RFC 4122 for more information. + . + This package contains the development environment for the uuid library. + +Package: libblkid1 +Section: libs +Depends: ${shlibs:Depends}, ${misc:Depends} +Architecture: any +Description: block device id library + The blkid library which allows system programs like fsck and + mount to quickly and easily find block devices by filesystem UUID and + LABEL. This allows system administrators to avoid specifying + filesystems by hard-coded device names, but via a logical naming + system instead. + +ifdef(`UDEB_PKGS',`` +Package: libblkid1-udeb +XC-Package-Type: udeb +Section: debian-installer +Priority: optional +Depends: ${shlibs:Depends}, ${misc:Depends} +Architecture: any +Description: stripped down block device id library, for debian-installer + The blkid library which allows system programs like fsck and + mount to quickly and easily find block devices by filesystem UUID and + LABEL. This allows system administrators to avoid specifiying + filesystems by hard-coded device names, but via a logical naming + system instead. + . + This is a minimal package for debian-installer. +'')dnl + +Package: libblkid-dev +Section: libdevel +Priority: extra +Depends: libc6-dev | libc-dev, libblkid1 (= ${binary:Version}), ${misc:Depends} +Architecture: any +Description: block device id library - headers and static libraries + The blkid library which allows system programs like fsck and + mount to quickly and easily find block devices by filesystem UUID and + LABEL. This allows system administrators to avoid specifiying + filesystems by hard-coded device names, but via a logical naming + system instead. + . + This package contains the development environment for the blkid library. +'')dnl + +ifdef(`UDEB_PKGS',`` +Package: e2fsprogs-udeb +XC-Package-Type: udeb +Section: debian-installer +Priority: optional +Depends: ${shlibs:Depends}, ${misc:Depends} +Architecture: any +Description: stripped-down versions of e2fsprogs, for debian-installer + This package is an e2fsprogs package built for a reduced size, so that + it can help to save space in debian-installer. + . + Don'''``t attempt to install this package, it has no support for a couple of + features you surely want. Anyway it should refuse to install. +'')dnl + +Package: e2fslibs +Section: libs +Depends: ${shlibs:Depends}, ${misc:Depends} +Replaces: e2fsprogs (<< 1.34-1) +Provides: libext2fs2, libe2p2 +Architecture: any +MULTIARCH_HEADERS +Description: ext2/ext3/ext4 file system libraries + The ext2, ext3 and ext4 file systems are successors of the original ext + ("extended") file system. They are the main file system types used for + hard disks on Debian and other Linux systems. + . + This package provides the ext2fs and e2p libraries, for userspace software + that directly accesses extended file systems. Programs that use libext2fs + include e2fsck, mke2fs, and tune2fs. Programs that use libe2p include + dumpe2fs, chattr, and lsattr. + +Package: e2fslibs-dev +Section: libdevel +Priority: extra +Depends: libc6-dev | libc-dev, comerr-dev, e2fslibs (= ${binary:Version}), ${misc:Depends} +Suggests: doc-base +Provides: ext2fs-dev, e2p-dev +Replaces: libkrb5-dev (<< 1.3) +Architecture: any +Description: ext2/ext3/ext4 file system libraries - headers and static libraries + The ext2, ext3 and ext4 file systems are successors of the original ext + ("extended") file system. They are the main file system types used for + hard disks on Debian and other Linux systems. + . + This package contains the development environment for the ext2fs and e2p + libraries. + +Package: e2fsprogs +Essential: yes +ifdef(`UTIL_LINUX_NG', +``Pre-Depends: ${shlibs:Depends}, ${misc:Depends}, util-linux (>= 2.15~rc1-1) +'', +``Pre-Depends: ${shlibs:Depends}, ${misc:Depends} +'')dnl +Multi-Arch: foreign +Suggests: gpart, parted, e2fsck-static +Conflicts: dump (<< 0.4b4-4), quota (<< 1.55-8.1), initscripts (<< 2.85-4), sysvinit (<< 2.85-4) +Replaces: hurd (<= 20040301-1), libblkid1 (<< 1.38+1.39-WIP-2005.12.10-2), libuuid1 (<< 1.38+1.39-WIP-2005.12.10-2) +Architecture: any +Description: ext2/ext3/ext4 file system utilities + The ext2, ext3 and ext4 file systems are successors of the original ext + ("extended") file system. They are the main file system types used for + hard disks on Debian and other Linux systems. + . + This package contains programs for creating, checking, and maintaining + ext2/3/4-based file systems. It also includes the "badblocks" program, + which can be used to scan for bad blocks on a disk or other storage device. + +Package: e2fsprogs-dbg +Section: debug +Priority: extra +Depends: e2fsprogs (= ${binary:Version}), ${misc:Depends} +Architecture: any +Description: debugging information for e2fsprogs + This package includes the debug information useful for debugging e2fsprogs + and its libraries, contained in the e2fsprogs and e2fsck-static packages. + The debug information is used for execution tracing and core + dump analysis. +ifdef(`UTIL_LINUX_NG',,`` +Package: uuid-runtime-dbg +Section: debug +Priority: extra +Depends: uuid-runtime (= ${binary:Version}), ${misc:Depends} +Architecture: any +Description: debugging information for uuid-runtime + This package includes the debug information useful for debugging the + uuid runtime programs, contained in the uuid-runtime package. + The debugging information is used for execution tracing and core + dump analysis. +'')dnl + +Package: e2fslibs-dbg +Section: debug +Priority: extra +Depends: e2fslibs (= ${binary:Version}), ${misc:Depends} +Architecture: any +Description: debugging information for e2fslibs + This package includes the debug information useful for debugging the + ext2fs and e2p libraries, contained in the e2fslibs package. The debug + information is used for execution tracing and core dump analysis. + +Package: libcomerr2-dbg +Section: debug +Priority: extra +Depends: libcomerr2 (= ${binary:Version}), ${misc:Depends} +Architecture: any +Description: debugging information for libcomerr2 + This package includes the debug information useful for debugging the + com_err library, contained in the libcomerr2 package. The debugging + information is used for execution tracing and core dump analysis. + +Package: libss2-dbg +Section: debug +Priority: extra +Depends: libss2 (= ${binary:Version}), ${misc:Depends} +Architecture: any +Description: debugging information for libss2 + This package includes the debug information useful for debugging the + ss library, contained in the libss2 package. The debug information + is used for execution tracing and core dump analysis. +ifdef(`UTIL_LINUX_NG',,`` +Package: libblkid1-dbg +Section: debug +Priority: extra +Depends: libblkid1 (= ${binary:Version}), ${misc:Depends} +Architecture: any +Description: debugging information for libblkid1 + This package includes the debug information useful for debugging the + blkid library, contained in the libblkid1 package. The debug + information is used for execution tracing and core dump analysis. + +Package: libuuid1-dbg +Section: debug +Priority: extra +Depends: libuuid1 (= ${binary:Version}), ${misc:Depends} +Architecture: any +Description: debugging information for libuuid1 + This package includes the debug information useful for debugging the + UUID library, contained in the libuuid1 package. The debug + information is used for execution tracing and core dump analysis. +'')dnl
diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..94a4d62 --- /dev/null +++ b/debian/copyright
@@ -0,0 +1,73 @@ +This is the Debian GNU/Linux prepackaged version of the EXT2 file +system utilities (e2fsck, mke2fs, etc.). The EXT2 utilities were +written by Theodore Ts'o <tytso@mit.edu> and Remy Card <card@masi.ibp.fr>. + +Sources were obtained from http://sourceforge.net/projects/e2fsprogs + +Packaging is Copyright (c) 2003-2007 Theodore Ts'o <tytso@mit.edu> + Copyright (c) 1997-2003 Yann Dirson <dirson@debian.org> + Copyright (c) 2001 Alcove <http://www.alcove.com/> + Copyright (c) 1997 Klee Dienes + Copyright (c) 1995-1996 Michael Nonweiler <mrn20@cam.ac.uk> + +Upstream Author: Theodore Ts'o <tytso@mit.edu> + +Copyright notice: + +This package, the EXT2 filesystem utilities, are made available under +the GNU Public License version 2, with the exception of the lib/ext2fs +and lib/e2p libraries, which are made available under the GNU Library +General Public License Version 2, the lib/uuid library which is made +available under a BSD-style license and the lib/et and lib/ss +libraries which are made available under an MIT-style license. + + Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Theodore Ts'o + +On Debian GNU systems, the complete text of the GNU General Public +License can be found in `/usr/share/common-licenses/GPL-2'. The +complete text of the GNU Library General Public License can be found +in '/usr/share/common-licenses/LGPL-2'. + + +The license used for lib/et and lib/ss libraries is: + + Copyright 1987 by the Student Information Processing Board + of the Massachusetts Institute of Technology + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose is hereby granted, provided that + the names of M.I.T. and the M.I.T. S.I.P.B. not be used in + advertising or publicity pertaining to distribution of the software + without specific, written prior permission. M.I.T. and the + M.I.T. S.I.P.B. make no representations about the suitability of + this software for any purpose. It is provided "as is" without + express or implied warranty. + +The license used for lib/uuid is: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, and the entire permission notice in its entirety, + including the disclaimer of warranties. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE.
diff --git a/debian/e2fsck-static.copyright b/debian/e2fsck-static.copyright new file mode 100644 index 0000000..82bdc67 --- /dev/null +++ b/debian/e2fsck-static.copyright
@@ -0,0 +1,26 @@ +This is the Debian GNU/Linux prepackaged version of the static EXT2 +file system consistency checker (e2fsck.static). The EXT2 utilities +were written by Theodore Ts'o <tytso@mit.edu> and Remy Card +<card@masi.ibp.fr>. + +Sources were obtained from http://sourceforge.net/projects/e2fsprogs + +Packaging is Copyright (c) 2003-2006 Theodore Ts'o <tytso@mit.edu> + Copyright (c) 1997-2003 Yann Dirson <dirson@debian.org> + Copyright (c) 2001 Alcove <http://www.alcove.com/> + Copyright (c) 1997 Klee Dienes + Copyright (c) 1995-1996 Michael Nonweiler <mrn20@cam.ac.uk> + +Upstream Author: Theodore Ts'o <tytso@mit.edu> + +Copyright notice: + +This package, the EXT2 filesystem utilities, is protected by the GNU +Public License. + + Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Theodore Ts'o + +On Debian GNU systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL-2'. +
diff --git a/debian/e2fsck-static.files b/debian/e2fsck-static.files new file mode 100644 index 0000000..15a7716 --- /dev/null +++ b/debian/e2fsck-static.files
@@ -0,0 +1,2 @@ +/sbin/e2fsck.static +/usr/share/man/man8/e2fsck.static*
diff --git a/debian/e2fsck-static.preinst b/debian/e2fsck-static.preinst new file mode 100644 index 0000000..e756ade --- /dev/null +++ b/debian/e2fsck-static.preinst
@@ -0,0 +1,19 @@ +#!/bin/sh + +# Abort on error. +set -e + +PKG=e2fsck-static +DOCLNK=/usr/share/doc/$PKG +if test "$1" = upgrade \ + -a -L $DOCLNK +then + rm $DOCLNK +fi + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0
diff --git a/debian/e2fslibs-dev.doc-base b/debian/e2fslibs-dev.doc-base new file mode 100644 index 0000000..19d04f4 --- /dev/null +++ b/debian/e2fslibs-dev.doc-base
@@ -0,0 +1,10 @@ +Document: libext2fs +Title: The EXT2FS library +Author: Theodore Ts'o +Abstract: The EXT2FS library is designed to allow + user-level programs to manipulate an ext2 filesystem. +Section: Programming + +Format: HTML +Index: /usr/share/doc/e2fslibs/html-info/libext2fs.html +Files: /usr/share/doc/e2fslibs/html-info/*.html
diff --git a/debian/e2fslibs-dev.files.in b/debian/e2fslibs-dev.files.in new file mode 100644 index 0000000..b2cd6c9 --- /dev/null +++ b/debian/e2fslibs-dev.files.in
@@ -0,0 +1,9 @@ +usr/lib/*/libext2fs*.so +usr/lib/*/libext2fs*.a +usr/lib/*/libe2p*.so +usr/lib/*/libe2p*.a +usr/include/ext2fs +usr/include/e2p +usr/share/info/libext2fs.info* +usr/lib/*/pkgconfig/e2p.pc +usr/lib/*/pkgconfig/ext2fs.pc
diff --git a/debian/e2fslibs.files.in b/debian/e2fslibs.files.in new file mode 100644 index 0000000..11198f7 --- /dev/null +++ b/debian/e2fslibs.files.in
@@ -0,0 +1,2 @@ +lib/*/libext2fs*.so.* +lib/*/libe2p*.so.*
diff --git a/debian/e2fslibs.symbols b/debian/e2fslibs.symbols new file mode 100644 index 0000000..c8a5fb6 --- /dev/null +++ b/debian/e2fslibs.symbols
@@ -0,0 +1,562 @@ +libe2p.so.2 e2fslibs #MINVER# + e2p_edit_feature2@Base 1.40.7 + e2p_edit_feature@Base 1.37 + e2p_edit_mntopts@Base 1.37 + e2p_feature2string@Base 1.37 + e2p_hash2string@Base 1.37 + e2p_is_null_uuid@Base 1.37 + e2p_jrnl_feature2string@Base 1.41.1 + e2p_jrnl_string2feature@Base 1.41.1 + e2p_mntopt2string@Base 1.37 + e2p_os2string@Base 1.37 + e2p_percent@Base 1.40 + e2p_string2feature@Base 1.37 + e2p_string2hash@Base 1.37 + e2p_string2mntopt@Base 1.37 + e2p_string2os@Base 1.37 + e2p_uuid2str@Base 1.37 + e2p_uuid_to_str@Base 1.37 + fgetflags@Base 1.37 + fgetversion@Base 1.37 + fsetflags@Base 1.37 + fsetversion@Base 1.37 + getflags@Base 1.37 + getversion@Base 1.37 + iterate_on_dir@Base 1.37 + list_super2@Base 1.37 + list_super@Base 1.37 + parse_num_blocks2@Base 1.42 + parse_num_blocks@Base 1.37 + print_flags@Base 1.37 + print_fs_errors@Base 1.37 + print_fs_state@Base 1.37 + setflags@Base 1.37 + setversion@Base 1.37 +libext2fs.so.2 e2fslibs #MINVER# + badblocks_list_add@Base 1.37 + badblocks_list_create@Base 1.37 + badblocks_list_free@Base 1.37 + badblocks_list_iterate@Base 1.37 + badblocks_list_iterate_begin@Base 1.37 + badblocks_list_iterate_end@Base 1.37 + badblocks_list_test@Base 1.37 + et_ext2_error_table@Base 1.37 + ext2fs_add_dir_block2@Base 1.42 + ext2fs_add_dir_block@Base 1.37 + ext2fs_add_journal_device@Base 1.37 + ext2fs_add_journal_inode2@Base 1.42.9-3~ + ext2fs_add_journal_inode@Base 1.37 + ext2fs_adjust_ea_refcount2@Base 1.42 + ext2fs_adjust_ea_refcount@Base 1.37 + ext2fs_alloc_block2@Base 1.42 + ext2fs_alloc_block@Base 1.37 + ext2fs_alloc_generic_bmap@Base 1.42 + ext2fs_allocate_block_bitmap@Base 1.37 + ext2fs_allocate_generic_bitmap@Base 1.37 + ext2fs_allocate_group_table@Base 1.37 + ext2fs_allocate_inode_bitmap@Base 1.37 + ext2fs_allocate_subcluster_bitmap@Base 1.42 + ext2fs_allocate_tables@Base 1.37 + ext2fs_badblocks_copy@Base 1.37 + ext2fs_badblocks_equal@Base 1.37 + ext2fs_badblocks_list_add@Base 1.37 + ext2fs_badblocks_list_create@Base 1.37 + ext2fs_badblocks_list_del@Base 1.37 + ext2fs_badblocks_list_free@Base 1.37 + ext2fs_badblocks_list_iterate@Base 1.37 + ext2fs_badblocks_list_iterate_begin@Base 1.37 + ext2fs_badblocks_list_iterate_end@Base 1.37 + ext2fs_badblocks_list_test@Base 1.37 + ext2fs_bg_checksum@Base 1.42 + ext2fs_bg_checksum_set@Base 1.42 + ext2fs_bg_flags@Base 1.42 + ext2fs_bg_flags_clear@Base 1.42 + ext2fs_bg_flags_set@Base 1.42 + ext2fs_bg_flags_test@Base 1.42 + ext2fs_bg_flags_zap@Base 1.42 + ext2fs_bg_free_blocks_count@Base 1.42 + ext2fs_bg_free_blocks_count_set@Base 1.42 + ext2fs_bg_free_inodes_count@Base 1.42 + ext2fs_bg_free_inodes_count_set@Base 1.42 + ext2fs_bg_has_super@Base 1.37 + ext2fs_bg_itable_unused@Base 1.42 + ext2fs_bg_itable_unused_set@Base 1.42 + ext2fs_bg_used_dirs_count@Base 1.42 + ext2fs_bg_used_dirs_count_set@Base 1.42 + ext2fs_bitcount@Base 1.42.7 + ext2fs_blkmap64_bitarray@Base 1.42 + ext2fs_blkmap64_rbtree@Base 1.42.1 + ext2fs_block_alloc_stats2@Base 1.42 + ext2fs_block_alloc_stats@Base 1.37 + ext2fs_block_alloc_stats_range@Base 1.42.9-3~ + ext2fs_block_bitmap_loc@Base 1.42 + ext2fs_block_bitmap_loc_set@Base 1.42 + ext2fs_block_iterate2@Base 1.37 + ext2fs_block_iterate3@Base 1.42 + ext2fs_block_iterate@Base 1.37 + ext2fs_blocks_count@Base 1.42 + ext2fs_blocks_count_add@Base 1.42 + ext2fs_blocks_count_set@Base 1.42 + ext2fs_bmap2@Base 1.41.0 + ext2fs_bmap@Base 1.37 + ext2fs_check_desc@Base 1.37 + ext2fs_check_directory@Base 1.37 + ext2fs_check_if_mounted@Base 1.37 + ext2fs_check_mount_point@Base 1.37 + ext2fs_clear_bit64@Base 1.42 + ext2fs_clear_bit@Base 1.37 + ext2fs_clear_block_bitmap@Base 1.37 + ext2fs_clear_generic_bitmap@Base 1.41.0 + ext2fs_clear_generic_bmap@Base 1.42 + ext2fs_clear_inode_bitmap@Base 1.37 + ext2fs_close2@Base 1.42 + ext2fs_close@Base 1.37 + ext2fs_close_free@Base 1.42.11 + ext2fs_close_inode_scan@Base 1.37 + ext2fs_compare_block_bitmap@Base 1.37 + ext2fs_compare_generic_bitmap@Base 1.41.0 + ext2fs_compare_generic_bmap@Base 1.42 + ext2fs_compare_inode_bitmap@Base 1.37 + ext2fs_convert_subcluster_bitmap@Base 1.42 + ext2fs_copy_bitmap@Base 1.37 + ext2fs_copy_dblist@Base 1.37 + ext2fs_copy_generic_bitmap@Base 1.41.0 + ext2fs_copy_generic_bmap@Base 1.42 + ext2fs_crc16@Base 1.41.1 + ext2fs_crc32c_be@Base 1.42 + ext2fs_crc32c_le@Base 1.42 + ext2fs_create_icount2@Base 1.37 + ext2fs_create_icount@Base 1.37 + ext2fs_create_icount_tdb@Base 1.40 + ext2fs_create_journal_superblock@Base 1.37 + ext2fs_create_resize_inode@Base 1.37 + ext2fs_dblist_count2@Base 1.42 + ext2fs_dblist_count@Base 1.37 + ext2fs_dblist_dir_iterate@Base 1.37 + ext2fs_dblist_drop_last@Base 1.40.8 + ext2fs_dblist_get_last2@Base 1.42 + ext2fs_dblist_get_last@Base 1.40.8 + ext2fs_dblist_iterate2@Base 1.42 + ext2fs_dblist_iterate@Base 1.37 + ext2fs_dblist_sort2@Base 1.42 + ext2fs_dblist_sort@Base 1.37 + ext2fs_default_journal_size@Base 1.40 + ext2fs_descriptor_block_loc2@Base 1.42 + ext2fs_descriptor_block_loc@Base 1.37 + ext2fs_dir_iterate2@Base 1.37 + ext2fs_dir_iterate@Base 1.37 + ext2fs_dirhash@Base 1.37 + ext2fs_div64_ceil@Base 1.42 + ext2fs_div_ceil@Base 1.40 + ext2fs_dup_handle@Base 1.37 + ext2fs_expand_dir@Base 1.37 + ext2fs_ext_attr_hash_entry@Base 1.41.0 + ext2fs_extent_delete@Base 1.41.0 + ext2fs_extent_fix_parents@Base 1.42.7 + ext2fs_extent_free@Base 1.41.0 + ext2fs_extent_get@Base 1.41.0 + ext2fs_extent_get_info@Base 1.41.0 + ext2fs_extent_goto2@Base 1.42.7 + ext2fs_extent_goto@Base 1.41.0 + ext2fs_extent_header_verify@Base 1.41.0 + ext2fs_extent_insert@Base 1.41.0 + ext2fs_extent_node_split@Base 1.42.7 + ext2fs_extent_open2@Base 1.41.6 + ext2fs_extent_open@Base 1.41.0 + ext2fs_extent_replace@Base 1.41.0 + ext2fs_extent_set_bmap@Base 1.41.0 + ext2fs_fast_clear_bit64@Base 1.42 + ext2fs_fast_clear_bit@Base 1.39 + ext2fs_fast_mark_block_bitmap2@Base 1.42 + ext2fs_fast_mark_block_bitmap@Base 1.37 + ext2fs_fast_mark_block_bitmap_range2@Base 1.42 + ext2fs_fast_mark_block_bitmap_range@Base 1.37 + ext2fs_fast_mark_inode_bitmap2@Base 1.42 + ext2fs_fast_mark_inode_bitmap@Base 1.37 + ext2fs_fast_set_bit64@Base 1.42 + ext2fs_fast_set_bit@Base 1.39 + ext2fs_fast_test_block_bitmap2@Base 1.42 + ext2fs_fast_test_block_bitmap@Base 1.37 + ext2fs_fast_test_block_bitmap_range2@Base 1.42 + ext2fs_fast_test_block_bitmap_range@Base 1.37 + ext2fs_fast_test_inode_bitmap2@Base 1.42 + ext2fs_fast_test_inode_bitmap@Base 1.37 + ext2fs_fast_unmark_block_bitmap2@Base 1.42 + ext2fs_fast_unmark_block_bitmap@Base 1.37 + ext2fs_fast_unmark_block_bitmap_range2@Base 1.42 + ext2fs_fast_unmark_block_bitmap_range@Base 1.37 + ext2fs_fast_unmark_inode_bitmap2@Base 1.42 + ext2fs_fast_unmark_inode_bitmap@Base 1.37 + ext2fs_file_acl_block@Base 1.42 + ext2fs_file_acl_block_set@Base 1.42 + ext2fs_file_block_offset_too_big@Base 1.42.9 + ext2fs_file_close@Base 1.37 + ext2fs_file_flush@Base 1.37 + ext2fs_file_get_fs@Base 1.37 + ext2fs_file_get_inode@Base 1.42 + ext2fs_file_get_inode_num@Base 1.42.1 + ext2fs_file_get_lsize@Base 1.37 + ext2fs_file_get_size@Base 1.37 + ext2fs_file_llseek@Base 1.37 + ext2fs_file_lseek@Base 1.37 + ext2fs_file_open2@Base 1.37 + ext2fs_file_open@Base 1.37 + ext2fs_file_read@Base 1.37 + ext2fs_file_set_size2@Base 1.42 + ext2fs_file_set_size@Base 1.37 + ext2fs_file_write@Base 1.37 + ext2fs_find_block_device@Base 1.37 + ext2fs_find_first_set_block_bitmap2@Base 1.42.9-3~ + ext2fs_find_first_set_generic_bitmap@Base 1.42.9-3~ + ext2fs_find_first_set_generic_bmap@Base 1.42.9-3~ + ext2fs_find_first_set_inode_bitmap2@Base 1.42.9-3~ + ext2fs_find_first_zero_block_bitmap2@Base 1.42.2 + ext2fs_find_first_zero_generic_bitmap@Base 1.42.3 + ext2fs_find_first_zero_generic_bmap@Base 1.42.2 + ext2fs_find_first_zero_inode_bitmap2@Base 1.42.2 + ext2fs_flush2@Base 1.42 + ext2fs_flush@Base 1.37 + ext2fs_flush_icache@Base 1.37 + ext2fs_follow_link@Base 1.37 + ext2fs_free@Base 1.37 + ext2fs_free_block_bitmap@Base 1.37 + ext2fs_free_blocks_count@Base 1.42 + ext2fs_free_blocks_count_add@Base 1.42 + ext2fs_free_blocks_count_set@Base 1.42 + ext2fs_free_dblist@Base 1.37 + ext2fs_free_generic_bitmap@Base 1.37 + ext2fs_free_generic_bmap@Base 1.42 + ext2fs_free_icount@Base 1.37 + ext2fs_free_inode_bitmap@Base 1.37 + ext2fs_free_mem@Base 1.37 + ext2fs_fstat@Base 1.42 + ext2fs_fudge_block_bitmap_end2@Base 1.42 + ext2fs_fudge_block_bitmap_end@Base 1.37 + ext2fs_fudge_generic_bitmap_end@Base 1.41.0 + ext2fs_fudge_generic_bmap_end@Base 1.42 + ext2fs_fudge_inode_bitmap_end@Base 1.37 + ext2fs_get_array@Base 1.40.3 + ext2fs_get_arrayzero@Base 1.42 + ext2fs_get_bitmap_granularity@Base 1.42 + ext2fs_get_block_bitmap_end2@Base 1.42 + ext2fs_get_block_bitmap_end@Base 1.37 + ext2fs_get_block_bitmap_range2@Base 1.42 + ext2fs_get_block_bitmap_range@Base 1.41.0 + ext2fs_get_block_bitmap_start2@Base 1.42 + ext2fs_get_block_bitmap_start@Base 1.37 + ext2fs_get_blocks@Base 1.37 + ext2fs_get_data_io@Base 1.37 + ext2fs_get_device_phys_sectsize@Base 1.41.12 + ext2fs_get_device_sectsize@Base 1.37 + ext2fs_get_device_size2@Base 1.41.4 + ext2fs_get_device_size@Base 1.37 + ext2fs_get_dio_alignment@Base 1.42.3 + ext2fs_get_free_blocks2@Base 1.42 + ext2fs_get_free_blocks@Base 1.37 + ext2fs_get_generic_bitmap_end@Base 1.41.0 + ext2fs_get_generic_bitmap_range@Base 1.41.0 + ext2fs_get_generic_bitmap_start@Base 1.41.0 + ext2fs_get_generic_bmap_end@Base 1.42 + ext2fs_get_generic_bmap_range@Base 1.42 + ext2fs_get_generic_bmap_start@Base 1.42 + ext2fs_get_icount_size@Base 1.37 + ext2fs_get_inode_bitmap_end2@Base 1.42 + ext2fs_get_inode_bitmap_end@Base 1.37 + ext2fs_get_inode_bitmap_range2@Base 1.42 + ext2fs_get_inode_bitmap_range@Base 1.41.0 + ext2fs_get_inode_bitmap_start2@Base 1.42 + ext2fs_get_inode_bitmap_start@Base 1.37 + ext2fs_get_library_version@Base 1.37 + ext2fs_get_mem@Base 1.37 + ext2fs_get_memalign@Base 1.41.13 + ext2fs_get_memzero@Base 1.42 + ext2fs_get_next_inode@Base 1.37 + ext2fs_get_next_inode_full@Base 1.37 + ext2fs_get_num_dirs@Base 1.37 + ext2fs_get_pathname@Base 1.37 + ext2fs_get_rec_len@Base 1.41.7 + ext2fs_group_blocks_count@Base 1.42 + ext2fs_group_desc@Base 1.42 + ext2fs_group_desc_csum@Base 1.42.2 + ext2fs_group_desc_csum_set@Base 1.41.0 + ext2fs_group_desc_csum_verify@Base 1.41.0 + ext2fs_group_first_block2@Base 1.42 + ext2fs_group_first_block@Base 1.40 + ext2fs_group_last_block2@Base 1.42 + ext2fs_group_last_block@Base 1.40 + ext2fs_group_of_blk2@Base 1.42 + ext2fs_group_of_blk@Base 1.37 + ext2fs_group_of_ino@Base 1.37 + ext2fs_iblk_add_blocks@Base 1.41.0 + ext2fs_iblk_set@Base 1.41.0 + ext2fs_iblk_sub_blocks@Base 1.41.0 + ext2fs_icount_decrement@Base 1.37 + ext2fs_icount_fetch@Base 1.37 + ext2fs_icount_increment@Base 1.37 + ext2fs_icount_store@Base 1.37 + ext2fs_icount_validate@Base 1.37 + ext2fs_image_bitmap_read@Base 1.37 + ext2fs_image_bitmap_write@Base 1.37 + ext2fs_image_inode_read@Base 1.37 + ext2fs_image_inode_write@Base 1.37 + ext2fs_image_super_read@Base 1.37 + ext2fs_image_super_write@Base 1.37 + ext2fs_init_dblist@Base 1.37 + ext2fs_initialize@Base 1.37 + ext2fs_inode_alloc_stats2@Base 1.37 + ext2fs_inode_alloc_stats@Base 1.37 + ext2fs_inode_bitmap_loc@Base 1.42 + ext2fs_inode_bitmap_loc_set@Base 1.42 + ext2fs_inode_data_blocks2@Base 1.42 + ext2fs_inode_data_blocks@Base 1.37 + ext2fs_inode_has_valid_blocks2@Base 1.42 + ext2fs_inode_has_valid_blocks@Base 1.37 + ext2fs_inode_i_blocks@Base 1.42 + ext2fs_inode_io_intern2@Base 1.37 + ext2fs_inode_io_intern@Base 1.37 + ext2fs_inode_scan_flags@Base 1.37 + ext2fs_inode_scan_goto_blockgroup@Base 1.37 + ext2fs_inode_size_set@Base 1.42.12 + ext2fs_inode_table_loc@Base 1.42 + ext2fs_inode_table_loc_set@Base 1.42 + ext2fs_journal_sb_start@Base 1.42.12 + ext2fs_link@Base 1.37 + ext2fs_llseek@Base 1.37 + ext2fs_lookup@Base 1.37 + ext2fs_make_generic_bitmap@Base 1.41.0 + ext2fs_map_cluster_block@Base 1.42.9 + ext2fs_mark_bb_dirty@Base 1.37 + ext2fs_mark_block_bitmap2@Base 1.42 + ext2fs_mark_block_bitmap@Base 1.37 + ext2fs_mark_block_bitmap_range2@Base 1.42 + ext2fs_mark_block_bitmap_range@Base 1.37 + ext2fs_mark_changed@Base 1.37 + ext2fs_mark_generic_bitmap@Base 1.37 + ext2fs_mark_generic_bmap@Base 1.42 + ext2fs_mark_ib_dirty@Base 1.37 + ext2fs_mark_inode_bitmap2@Base 1.42 + ext2fs_mark_inode_bitmap@Base 1.37 + ext2fs_mark_super_dirty@Base 1.37 + ext2fs_mark_valid@Base 1.37 + ext2fs_mem_is_zero@Base 1.42 + ext2fs_mkdir@Base 1.37 + ext2fs_mmp_clear@Base 1.42 + ext2fs_mmp_init@Base 1.42 + ext2fs_mmp_new_seq@Base 1.42 + ext2fs_mmp_read@Base 1.42 + ext2fs_mmp_start@Base 1.42 + ext2fs_mmp_stop@Base 1.42 + ext2fs_mmp_update@Base 1.42 + ext2fs_mmp_write@Base 1.42 + ext2fs_namei@Base 1.37 + ext2fs_namei_follow@Base 1.37 + ext2fs_native_flag@Base 1.37 + ext2fs_new_block2@Base 1.42 + ext2fs_new_block@Base 1.37 + ext2fs_new_dir_block@Base 1.37 + ext2fs_new_inode@Base 1.37 + ext2fs_numeric_progress_close@Base 1.42 + ext2fs_numeric_progress_init@Base 1.42 + ext2fs_numeric_progress_update@Base 1.42 + ext2fs_open2@Base 1.37 + ext2fs_open@Base 1.37 + ext2fs_open_file@Base 1.42 + ext2fs_open_inode_scan@Base 1.37 + ext2fs_parse_version_string@Base 1.37 + ext2fs_process_dir_block@Base 1.37 + ext2fs_punch@Base 1.42 + ext2fs_r_blocks_count@Base 1.42 + ext2fs_r_blocks_count_add@Base 1.42 + ext2fs_r_blocks_count_set@Base 1.42 + ext2fs_rb_augment_erase_begin@Base 1.42.1 + ext2fs_rb_augment_erase_end@Base 1.42.1 + ext2fs_rb_augment_insert@Base 1.42.1 + ext2fs_rb_erase@Base 1.42.1 + ext2fs_rb_first@Base 1.42.1 + ext2fs_rb_insert_color@Base 1.42.1 + ext2fs_rb_last@Base 1.42.1 + ext2fs_rb_next@Base 1.42.1 + ext2fs_rb_prev@Base 1.42.1 + ext2fs_rb_replace_node@Base 1.42.1 + ext2fs_read_bb_FILE2@Base 1.37 + ext2fs_read_bb_FILE@Base 1.37 + ext2fs_read_bb_inode@Base 1.37 + ext2fs_read_bitmaps@Base 1.37 + ext2fs_read_block_bitmap@Base 1.37 + ext2fs_read_dir_block2@Base 1.37 + ext2fs_read_dir_block3@Base 1.42 + ext2fs_read_dir_block@Base 1.37 + ext2fs_read_ext_attr2@Base 1.42 + ext2fs_read_ext_attr@Base 1.37 + ext2fs_read_ind_block@Base 1.37 + ext2fs_read_inode@Base 1.37 + ext2fs_read_inode_bitmap@Base 1.37 + ext2fs_read_inode_full@Base 1.37 + ext2fs_reserve_super_and_bgd@Base 1.37 + ext2fs_resize_block_bitmap2@Base 1.42 + ext2fs_resize_block_bitmap@Base 1.37 + ext2fs_resize_generic_bitmap@Base 1.37 + ext2fs_resize_generic_bmap@Base 1.42 + ext2fs_resize_inode_bitmap2@Base 1.42 + ext2fs_resize_inode_bitmap@Base 1.37 + ext2fs_resize_mem@Base 1.37 + ext2fs_rewrite_to_io@Base 1.37 + ext2fs_set_alloc_block_callback@Base 1.41.0 + ext2fs_set_bit64@Base 1.42 + ext2fs_set_bit@Base 1.37 + ext2fs_set_bitmap_padding@Base 1.37 + ext2fs_set_block_alloc_stats_callback@Base 1.41.0 + ext2fs_set_block_bitmap_range2@Base 1.42 + ext2fs_set_block_bitmap_range@Base 1.41.0 + ext2fs_set_data_io@Base 1.37 + ext2fs_set_dir_block2@Base 1.42 + ext2fs_set_dir_block@Base 1.37 + ext2fs_set_gdt_csum@Base 1.41.0 + ext2fs_set_generic_bitmap_padding@Base 1.41.0 + ext2fs_set_generic_bitmap_range@Base 1.41.0 + ext2fs_set_generic_bmap_padding@Base 1.42 + ext2fs_set_generic_bmap_range@Base 1.42 + ext2fs_set_inode_bitmap_range2@Base 1.42 + ext2fs_set_inode_bitmap_range@Base 1.41.0 + ext2fs_set_inode_callback@Base 1.37 + ext2fs_set_rec_len@Base 1.41.7 + ext2fs_stat@Base 1.42 + ext2fs_super_and_bgd_loc2@Base 1.42 + ext2fs_super_and_bgd_loc@Base 1.37 + ext2fs_swab16@Base 1.37 + ext2fs_swab32@Base 1.37 + ext2fs_swab64@Base 1.40 + ext2fs_symlink@Base 1.42.7 + ext2fs_sync_device@Base 1.37 + ext2fs_tdb_append@Base 1.40 + ext2fs_tdb_chainlock@Base 1.40 + ext2fs_tdb_chainlock_mark@Base 1.40.7 + ext2fs_tdb_chainlock_nonblock@Base 1.40.7 + ext2fs_tdb_chainlock_read@Base 1.40 + ext2fs_tdb_chainlock_unmark@Base 1.40.7 + ext2fs_tdb_chainunlock@Base 1.40 + ext2fs_tdb_chainunlock_read@Base 1.40 + ext2fs_tdb_close@Base 1.40 + ext2fs_tdb_delete@Base 1.40 + ext2fs_tdb_dump_all@Base 1.40 + ext2fs_tdb_enable_seqnum@Base 1.40.7 + ext2fs_tdb_error@Base 1.40 + ext2fs_tdb_errorstr@Base 1.40 + ext2fs_tdb_exists@Base 1.40 + ext2fs_tdb_fd@Base 1.40 + ext2fs_tdb_fetch@Base 1.40 + ext2fs_tdb_firstkey@Base 1.40 + ext2fs_tdb_get_flags@Base 1.40 + ext2fs_tdb_get_logging_private@Base 1.40 + ext2fs_tdb_get_seqnum@Base 1.40 + ext2fs_tdb_hash_size@Base 1.40 + ext2fs_tdb_increment_seqnum_nonblock@Base 1.40.7 + ext2fs_tdb_lock_nonblock@Base 1.40.7 + ext2fs_tdb_lockall@Base 1.40 + ext2fs_tdb_lockall_mark@Base 1.40.7 + ext2fs_tdb_lockall_nonblock@Base 1.40.7 + ext2fs_tdb_lockall_read@Base 1.40 + ext2fs_tdb_lockall_read_nonblock@Base 1.40.7 + ext2fs_tdb_lockall_unmark@Base 1.40.7 + ext2fs_tdb_log_fn@Base 1.40 + ext2fs_tdb_map_size@Base 1.40 + ext2fs_tdb_name@Base 1.40 + ext2fs_tdb_nextkey@Base 1.40 + ext2fs_tdb_open@Base 1.40 + ext2fs_tdb_open_ex@Base 1.40 + ext2fs_tdb_parse_record@Base 1.40 + ext2fs_tdb_printfreelist@Base 1.40 + ext2fs_tdb_reopen@Base 1.40 + ext2fs_tdb_reopen_all@Base 1.40 + ext2fs_tdb_set_logging_function@Base 1.40 + ext2fs_tdb_set_max_dead@Base 1.40 + ext2fs_tdb_store@Base 1.40 + ext2fs_tdb_transaction_cancel@Base 1.40 + ext2fs_tdb_transaction_commit@Base 1.40 + ext2fs_tdb_transaction_recover@Base 1.40 + ext2fs_tdb_transaction_start@Base 1.40 + ext2fs_tdb_traverse@Base 1.40 + ext2fs_tdb_traverse_read@Base 1.40 + ext2fs_tdb_unlockall@Base 1.40 + ext2fs_tdb_unlockall_read@Base 1.40 + ext2fs_tdb_validate_freelist@Base 1.40 + ext2fs_test_bb_dirty@Base 1.37 + ext2fs_test_bit64@Base 1.42 + ext2fs_test_bit@Base 1.37 + ext2fs_test_block_bitmap2@Base 1.42 + ext2fs_test_block_bitmap@Base 1.37 + ext2fs_test_block_bitmap_range2@Base 1.42 + ext2fs_test_block_bitmap_range@Base 1.37 + ext2fs_test_changed@Base 1.37 + ext2fs_test_generic_bitmap@Base 1.37 + ext2fs_test_generic_bmap@Base 1.42 + ext2fs_test_ib_dirty@Base 1.37 + ext2fs_test_inode_bitmap2@Base 1.42 + ext2fs_test_inode_bitmap@Base 1.37 + ext2fs_test_inode_bitmap_range@Base 1.41.8 + ext2fs_test_valid@Base 1.37 + ext2fs_u32_copy@Base 1.37 + ext2fs_u32_list_add@Base 1.37 + ext2fs_u32_list_count@Base 1.37 + ext2fs_u32_list_create@Base 1.37 + ext2fs_u32_list_del@Base 1.37 + ext2fs_u32_list_equal@Base 1.37 + ext2fs_u32_list_find@Base 1.37 + ext2fs_u32_list_free@Base 1.37 + ext2fs_u32_list_iterate@Base 1.37 + ext2fs_u32_list_iterate_begin@Base 1.37 + ext2fs_u32_list_iterate_end@Base 1.37 + ext2fs_u32_list_test@Base 1.37 + ext2fs_unlink@Base 1.37 + ext2fs_unmark_block_bitmap2@Base 1.42 + ext2fs_unmark_block_bitmap@Base 1.37 + ext2fs_unmark_block_bitmap_range2@Base 1.42 + ext2fs_unmark_block_bitmap_range@Base 1.37 + ext2fs_unmark_generic_bitmap@Base 1.37 + ext2fs_unmark_generic_bmap@Base 1.42 + ext2fs_unmark_inode_bitmap2@Base 1.42 + ext2fs_unmark_inode_bitmap@Base 1.37 + ext2fs_unmark_valid@Base 1.37 + ext2fs_update_bb_inode@Base 1.37 + ext2fs_update_dynamic_rev@Base 1.37 + ext2fs_warn_bitmap2@Base 1.37 + ext2fs_warn_bitmap32@Base 1.42 + ext2fs_warn_bitmap@Base 1.37 + ext2fs_write_bb_FILE@Base 1.37 + ext2fs_write_bitmaps@Base 1.37 + ext2fs_write_block_bitmap@Base 1.37 + ext2fs_write_dir_block2@Base 1.37 + ext2fs_write_dir_block3@Base 1.42 + ext2fs_write_dir_block@Base 1.37 + ext2fs_write_ext_attr2@Base 1.42 + ext2fs_write_ext_attr@Base 1.37 + ext2fs_write_ind_block@Base 1.37 + ext2fs_write_inode@Base 1.37 + ext2fs_write_inode_bitmap@Base 1.37 + ext2fs_write_inode_full@Base 1.37 + ext2fs_write_new_inode@Base 1.37 + ext2fs_zero_blocks2@Base 1.42 + ext2fs_zero_blocks@Base 1.41.0 + initialize_ext2_error_table@Base 1.37 + initialize_ext2_error_table_r@Base 1.37 + inode_io_manager@Base 1.37 + io_channel_alloc_buf@Base 1.42.3 + io_channel_discard@Base 1.42 + io_channel_read_blk64@Base 1.41.1 + io_channel_set_options@Base 1.37 + io_channel_write_blk64@Base 1.41.1 + io_channel_write_byte@Base 1.37 + qcow2_read_header@Base 1.42 + qcow2_write_raw_image@Base 1.42 + set_undo_io_backing_manager@Base 1.41.0 + set_undo_io_backup_file@Base 1.41.0 + test_io_backing_manager@Base 1.37 + test_io_cb_read_blk64@Base 1.41.0 + test_io_cb_read_blk@Base 1.37 + test_io_cb_set_blksize@Base 1.37 + test_io_cb_write_blk64@Base 1.41.0 + test_io_cb_write_blk@Base 1.37 + test_io_cb_write_byte@Base 1.37 + test_io_manager@Base 1.37 + undo_io_manager@Base 1.41.0 + unix_io_manager@Base 1.37
diff --git a/debian/e2fsprogs-udeb.shlibs.local b/debian/e2fsprogs-udeb.shlibs.local new file mode 100644 index 0000000..b41b583 --- /dev/null +++ b/debian/e2fsprogs-udeb.shlibs.local
@@ -0,0 +1,6 @@ +libblkid 1 libblkid1-udeb +# force the dependency to libblkid1-udeb, even if it don't include the lib +libcom_err 2 libblkid1-udeb +libuuid 1 libuuid1-udeb +libext2fs 2 libblkid1-udeb +libe2p 2 libblkid1-udeb
diff --git a/debian/e2fsprogs.docs b/debian/e2fsprogs.docs new file mode 100644 index 0000000..7af9733 --- /dev/null +++ b/debian/e2fsprogs.docs
@@ -0,0 +1,2 @@ +README +RELEASE-NOTES
diff --git a/debian/e2fsprogs.files b/debian/e2fsprogs.files new file mode 100644 index 0000000..37e54da --- /dev/null +++ b/debian/e2fsprogs.files
@@ -0,0 +1,6 @@ +sbin +usr/bin +usr/sbin +usr/share/man +usr/share/locale +etc
diff --git a/debian/e2fsprogs.preinst b/debian/e2fsprogs.preinst new file mode 100644 index 0000000..bfa9f6b --- /dev/null +++ b/debian/e2fsprogs.preinst
@@ -0,0 +1,19 @@ +#!/bin/sh + +# Abort on error. +set -e + +PKG=e2fsprogs +DOCLNK=/usr/share/doc/$PKG +if test "$1" = upgrade \ + -a -L $DOCLNK +then + rm $DOCLNK +fi + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0
diff --git a/debian/e2fsprogs.shlibs.local.in b/debian/e2fsprogs.shlibs.local.in new file mode 100644 index 0000000..db1b75a --- /dev/null +++ b/debian/e2fsprogs.shlibs.local.in
@@ -0,0 +1,8 @@ +libcom_err 2 libcomerr2 (>= 1.42~WIP-2011-10-05-1) +libss 2 libss2 (>= 1.34-1) +ifdef(`UTIL_LINUX_NG',, +``libuuid 1 libuuid1 (>= 1.34-1) +libblkid 1 libblkid1 (>= 1.34-1) +'')dnl +libext2fs 2 e2fslibs (= ${Source-Version}) +libe2p 2 e2fslibs (= ${Source-Version})
diff --git a/debian/libblkid-dev.files.in b/debian/libblkid-dev.files.in new file mode 100644 index 0000000..7b3da36 --- /dev/null +++ b/debian/libblkid-dev.files.in
@@ -0,0 +1,4 @@ +usr/lib/*/libblkid*.so.* +usr/include/blkid +usr/share/man/man3/libblkid.3 +usr/lib/*/pkgconfig/blkid.pc
diff --git a/debian/libblkid.copyright b/debian/libblkid.copyright new file mode 100644 index 0000000..8be818b --- /dev/null +++ b/debian/libblkid.copyright
@@ -0,0 +1,19 @@ +This package was added to the e2fsprogs debian source package by +Theodore Ts'o <tytso@mit.edu> on Sat Mar 15 15:33:37 EST 2003 + +It is part of the main e2fsprogs distribution, which can be found at: + + http://sourceforge.net/projects/e2fsprogs + +Upstream Author: Theodore Ts'o <tytso@mit.edu> + +Copyright: + +Copyright (C) 1999, 2001 by Andries Brouwer +Copyright (C) 1999, 2000, 2003 by Theodore Ts'o + +You are free to distribute this software under the terms of the GNU +Lesser (Library) General Public License. + +On Debian systems, the complete text of the GNU Lesser (Library) +General Public License can be found in /usr/share/common-licenses/LGPL-2.
diff --git a/debian/libblkid1.files.in b/debian/libblkid1.files.in new file mode 100644 index 0000000..54ef86d --- /dev/null +++ b/debian/libblkid1.files.in
@@ -0,0 +1 @@ +lib/*/libblkid*.so.*
diff --git a/debian/libblkid1.symbols b/debian/libblkid1.symbols new file mode 100644 index 0000000..5ab91f5 --- /dev/null +++ b/debian/libblkid1.symbols
@@ -0,0 +1,41 @@ +libblkid.so.1 libblkid1 #MINVER# + blkid__scan_dir@Base 1.41.1 + blkid_debug_mask@Base 1.33 + blkid_dev_devname@Base 1.33 + blkid_dev_has_tag@Base 1.38 + blkid_dev_iterate_begin@Base 1.33 + blkid_dev_iterate_end@Base 1.33 + blkid_dev_next@Base 1.33 + blkid_dev_set_search@Base 1.38 +#MISSING: 1.41.1# blkid_devdirs@Base 1.34 + blkid_devno_to_devname@Base 1.33 + blkid_find_dev_with_tag@Base 1.33 + blkid_find_tag_dev@Base 1.33 + blkid_flush_cache@Base 1.33 + blkid_free_dev@Base 1.33 + blkid_free_tag@Base 1.33 + blkid_gc_cache@Base 1.40 + blkid_get_cache@Base 1.33 + blkid_get_dev@Base 1.33 + blkid_get_dev_size@Base 1.33 + blkid_get_devname@Base 1.33 + blkid_get_library_version@Base 1.37 + blkid_get_tag_value@Base 1.33 + blkid_known_fstype@Base 1.34 + blkid_llseek@Base 1.33 + blkid_new_dev@Base 1.33 + blkid_parse_tag_string@Base 1.33 + blkid_parse_version_string@Base 1.37 + blkid_probe_all@Base 1.33 + blkid_probe_all_new@Base 1.38 + blkid_put_cache@Base 1.33 + blkid_read_cache@Base 1.33 + blkid_set_tag@Base 1.33 + blkid_strdup@Base 1.33 + blkid_strndup@Base 1.33 + blkid_tag_iterate_begin@Base 1.33 + blkid_tag_iterate_end@Base 1.33 + blkid_tag_next@Base 1.33 + blkid_verify@Base 1.37 +#MISSING: 1.40.7# check_for_modules@Base 1.40.6 +#MISSING: 1.40.7# fs_proc_check@Base 1.40.6
diff --git a/debian/libcomerr2.copyright b/debian/libcomerr2.copyright new file mode 100644 index 0000000..578628a --- /dev/null +++ b/debian/libcomerr2.copyright
@@ -0,0 +1,24 @@ +This is the Debian GNU/Linux prepackaged version of the Common Error +Description library. It is currently distributed together with the EXT2 file +system utilities, which are otherwise packaged as "e2fsprogs". + +This package was put together by Yann Dirson <dirson@debian.org>, +from sources obtained from a mirror of: + tsx-11.mit.edu:/pub/linux/packages/ext2fs/ + +From the original distribution: + +Copyright 1987, 1988 by the Student Information Processing Board + of the Massachusetts Institute of Technology + +Permission to use, copy, modify, and distribute this software +and its documentation for any purpose and without fee is +hereby granted, provided that the above copyright notice +appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, +and that the names of M.I.T. and the M.I.T. S.I.P.B. not be +used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +M.I.T. and the M.I.T. S.I.P.B. make no representations about +the suitability of this software for any purpose. It is +provided "as is" without express or implied warranty.
diff --git a/debian/libcomerr2.files.in b/debian/libcomerr2.files.in new file mode 100644 index 0000000..16b039e --- /dev/null +++ b/debian/libcomerr2.files.in
@@ -0,0 +1 @@ +lib/*/libcom_err*.so.*
diff --git a/debian/libcomerr2.symbols b/debian/libcomerr2.symbols new file mode 100644 index 0000000..ce3b74a --- /dev/null +++ b/debian/libcomerr2.symbols
@@ -0,0 +1,21 @@ +libcom_err.so.2 libcomerr2 #MINVER# + _et_dynamic_list@Base 1.38 + _et_list@Base 1.01 + add_error_table@Base 1.34 + add_to_error_table@Base 1.34 + com_err@Base 1.01 + com_err_hook@Base 1.01 + com_err_va@Base 1.01 + com_right@Base 1.34 + com_right_r@Base 1.41.11 + error_message@Base 1.01 + error_table_name@Base 1.01 + et_list_lock@Base 1.41.2 + et_list_unlock@Base 1.41.2 + free_error_table@Base 1.34 + init_error_table@Base 1.01 + initialize_error_table_r@Base 1.34 + remove_error_table@Base 1.34 + reset_com_err_hook@Base 1.01 + set_com_err_gettext@Base 1.41.99 + set_com_err_hook@Base 1.01
diff --git a/debian/libss2.copyright b/debian/libss2.copyright new file mode 100644 index 0000000..eb261c3 --- /dev/null +++ b/debian/libss2.copyright
@@ -0,0 +1,25 @@ +This is the Debian GNU/Linux prepackaged version of the ss +command-line interface parsing library library. It is currently +distributed together with the EXT2 file system utilities, which are +otherwise packaged as "e2fsprogs". + +This package was put together by Yann Dirson <dirson@debian.org>, +from sources obtained from a mirror of: + tsx-11.mit.edu:/pub/linux/packages/ext2fs/ + +From the original distribution: + +Copyright 1987, 1988 by the Student Information Processing Board + of the Massachusetts Institute of Technology + +Permission to use, copy, modify, and distribute this software +and its documentation for any purpose and without fee is +hereby granted, provided that the above copyright notice +appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, +and that the names of M.I.T. and the M.I.T. S.I.P.B. not be +used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +M.I.T. and the M.I.T. S.I.P.B. make no representations about +the suitability of this software for any purpose. It is +provided "as is" without express or implied warranty.
diff --git a/debian/libss2.files.in b/debian/libss2.files.in new file mode 100644 index 0000000..386e185 --- /dev/null +++ b/debian/libss2.files.in
@@ -0,0 +1 @@ +lib/*/libss*.so.*
diff --git a/debian/libss2.symbols b/debian/libss2.symbols new file mode 100644 index 0000000..b6fe40b --- /dev/null +++ b/debian/libss2.symbols
@@ -0,0 +1,35 @@ +libss.so.2 libss2 #MINVER# + _ss_pager_name@Base 1.01 + _ss_table@Base 1.01 + et_ss_error_table@Base 1.35 + initialize_ss_error_table@Base 1.01 + initialize_ss_error_table_r@Base 1.34 + ss_abort_subsystem@Base 1.01 + ss_add_info_dir@Base 1.01 + ss_add_request_table@Base 1.01 + ss_create_invocation@Base 1.01 + ss_delete_info_dir@Base 1.01 + ss_delete_invocation@Base 1.01 + ss_delete_request_table@Base 1.01 + ss_error@Base 1.01 + ss_execute_command@Base 1.01 + ss_execute_line@Base 1.01 + ss_get_prompt@Base 1.01 + ss_get_readline@Base 1.34 + ss_help@Base 1.01 + ss_list_requests@Base 1.01 + ss_listen@Base 1.01 + ss_name@Base 1.01 + ss_page_stdin@Base 1.01 + ss_pager_create@Base 1.01 + ss_parse@Base 1.01 + ss_perror@Base 1.01 + ss_quit@Base 1.01 + ss_rl_completion@Base 1.34 + ss_safe_getenv@Base 1.38 + ss_self_identify@Base 1.01 + ss_set_prompt@Base 1.01 + ss_std_requests@Base 1.01 + ss_subsystem_name@Base 1.01 + ss_subsystem_version@Base 1.01 + ss_unimplemented@Base 1.01
diff --git a/debian/libuuid1.copyright b/debian/libuuid1.copyright new file mode 100644 index 0000000..f346739 --- /dev/null +++ b/debian/libuuid1.copyright
@@ -0,0 +1,38 @@ +This package was added to the e2fsprogs debian source package by +Theodore Ts'o <tytso@mit.edu> on Sat Mar 15 15:33:37 EST 2003 + +It is part of the main e2fsprogs distribution, which can be found at: + + http://sourceforge.net/projects/e2fsprogs + +Upstream Author: Theodore Ts'o <tytso@mit.edu> + +Copyright: + +Copyright (C) 1999, 2000, 2003, 2004 by Theodore Ts'o + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, and the entire permission notice in its entirety, + including the disclaimer of warranties. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF +WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE.
diff --git a/debian/libuuid1.files.in b/debian/libuuid1.files.in new file mode 100644 index 0000000..0761f3b --- /dev/null +++ b/debian/libuuid1.files.in
@@ -0,0 +1 @@ +lib/*/libuuid*.so.*
diff --git a/debian/libuuid1.postinst b/debian/libuuid1.postinst new file mode 100644 index 0000000..5336fcf --- /dev/null +++ b/debian/libuuid1.postinst
@@ -0,0 +1,40 @@ +#!/bin/sh + +set -e + +ADDUSERCONF='/etc/adduser.conf' + +if test -f $ADDUSERCONF; then + FIRST_SYSTEM_UID=$(sed -n "s/^[[:space:]]*FIRST_SYSTEM_UID[[:space:]]*=[[:space:]]*[\"']\?\([^\"']*\)[\"']\?/\1/p" $ADDUSERCONF) + LAST_SYSTEM_UID=$(sed -n "s/^[[:space:]]*LAST_SYSTEM_UID[[:space:]]*=[[:space:]]*[\"']\?\([^\"']*\)[\"']\?/\1/p" $ADDUSERCONF) + FIRST_SYSTEM_GID=$(sed -n "s/^[[:space:]]*FIRST_SYSTEM_GID[[:space:]]*=[[:space:]]*[\"']\?\([^\"']*\)[\"']\?/\1/p" $ADDUSERCONF) + LAST_SYSTEM_GID=$(sed -n "s/^[[:space:]]*LAST_SYSTEM_GID[[:space:]]*=[[:space:]]*[\"']\?\([^\"']*\)[\"']\?/\1/p" $ADDUSERCONF) +fi + +if test -z "$FIRST_SYSTEM_UID"; then + FIRST_SYSTEM_UID=100 +fi +if test -z "$LAST_SYSTEM_UID"; then + LAST_SYSTEM_UID=999 +fi +if test -z "$FIRST_SYSTEM_GID"; then + FIRST_SYSTEM_GID=100 +fi +if test -z "$LAST_SYSTEM_GID"; then + LAST_SYSTEM_GID=999 +fi + +if ! getent group | grep -q libuuid; then + groupadd -f -K GID_MIN=$FIRST_SYSTEM_GID -K GID_MAX=$LAST_SYSTEM_GID libuuid +fi +if ! getent passwd | grep -q libuuid; then + useradd -d /var/lib/libuuid -K UID_MIN=$FIRST_SYSTEM_UID -K UID_MAX=$LAST_SYSTEM_UID -g libuuid libuuid +fi + +mkdir -p /var/lib/libuuid +chown libuuid:libuuid /var/lib/libuuid +chmod 2775 /var/lib/libuuid + +#DEBHELPER# + +exit 0
diff --git a/debian/libuuid1.postrm b/debian/libuuid1.postrm new file mode 100644 index 0000000..8c286ee --- /dev/null +++ b/debian/libuuid1.postrm
@@ -0,0 +1,10 @@ +#!/bin/sh +set -e +if [ "$1" = purge ] +then + rm -rf /var/lib/libuuid +fi + +#DEBHELPER# + +exit 0
diff --git a/debian/libuuid1.symbols b/debian/libuuid1.symbols new file mode 100644 index 0000000..5a00431 --- /dev/null +++ b/debian/libuuid1.symbols
@@ -0,0 +1,19 @@ +libuuid.so.1 libuuid1 #MINVER# + uuid__generate_random@Base 1.40.4 + uuid__generate_time@Base 1.40.4 + uuid_clear@Base 1.05 + uuid_compare@Base 1.05 + uuid_copy@Base 1.05 + uuid_generate@Base 1.05 + uuid_generate_random@Base 1.15 + uuid_generate_time@Base 1.15 + uuid_is_null@Base 1.05 + uuid_pack@Base 1.05 + uuid_parse@Base 1.05 + uuid_time@Base 1.15 + uuid_type@Base 1.15 + uuid_unpack@Base 1.05 + uuid_unparse@Base 1.05 + uuid_unparse_lower@Base 1.36 + uuid_unparse_upper@Base 1.36 + uuid_variant@Base 1.15
diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..5e55e68 --- /dev/null +++ b/debian/rules
@@ -0,0 +1,692 @@ +#! /usr/bin/make -f +# -*- makefile -*- +# +# Invoke each target with `./debian/rules <target>'. All targets should be +# invoked with the package root as the current directory. +# +# The `binary' target must be run as root, as it needs to install files with +# specific ownerships. + +-include debian/rules.custom + +# be paranoid +export LC_ALL ?= C + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) +DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH) +DEB_HOST_OS ?= $(shell dpkg-architecture -qDEB_HOST_OS) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null) + +# Allow distro-specific behaviour +DISTRO :=$(shell sed -ne '/DISTRIB_ID/s/.*=//p' /etc/lsb-release 2>/dev/null || echo Debian) +UTIL_LINUX_NG ?= yes + +# find the version for the main package, from changelog file +MAIN_VERSION = $(shell head -n 1 debian/changelog | cut '-d ' -f 2 | sed 's/[()]//g') +# find versions for libraries going into their own packages, from their Makefile.in's, +# and sonames for all libs +COMERR_VERSION ?= $(shell grep ELF_VERSION lib/et/Makefile.in | cut '-d ' -f3) +COMERR_SOVERSION ?= $(shell grep ELF_SO_VERSION lib/et/Makefile.in | cut '-d ' -f3) +SS_VERSION ?= $(shell grep ELF_VERSION lib/ss/Makefile.in | cut '-d ' -f3) +SS_SOVERSION ?= $(shell grep ELF_SO_VERSION lib/ss/Makefile.in | cut '-d ' -f3) + +ifneq ($(UTIL_LINUX_NG),yes) +UUID_VERSION ?= $(shell grep ELF_VERSION lib/uuid/Makefile.in | cut '-d ' -f3) +UUID_SOVERSION ?= $(shell grep ELF_SO_VERSION lib/uuid/Makefile.in | cut '-d ' -f3) + +BLKID_VERSION ?= $(shell grep ELF_VERSION lib/blkid/Makefile.in | cut '-d ' -f3) +BLKID_SOVERSION ?= $(shell grep ELF_SO_VERSION lib/blkid/Makefile.in | cut '-d ' -f3) +endif + +EXT2FS_SOVERSION ?= $(shell grep ELF_SO_VERSION lib/ext2fs/Makefile.in | cut '-d ' -f3) +E2P_SOVERSION ?= $(shell grep ELF_SO_VERSION lib/e2p/Makefile.in | cut '-d ' -f3) + +package ?= e2fsprogs + +topdir ?= $(shell pwd) +debdir ?= ${topdir}/debian +tmpdir ?= ${debdir}/tmp +udebdir ?= ${debdir}/e2fsprogs-udeb +ifneq ($(UTIL_LINUX_NG),yes) +blkidudebdir ?= ${debdir}/libblkid1-udeb +uuidudebdir ?= ${debdir}/libuuid1-udeb +endif +libcomerrdir ?= ${debdir}/libcomerr${COMERR_SOVERSION} +comerrdevdir ?= ${debdir}/comerr-dev +libcomerrdbgdir ?= ${debdir}/libcomerr2-dbg +libssdir ?= ${debdir}/libss${SS_SOVERSION} +ssdevdir ?= ${debdir}/ss-dev +libssdbgdir ?= ${debdir}/libss2-dbg +ifneq ($(UTIL_LINUX_NG),yes) +libblkiddir ?= ${debdir}/libblkid${BLKID_SOVERSION} +libblkiddevdir ?= ${debdir}/libblkid-dev +libblkiddbgdir ?= ${debdir}/libblkid1-dbg +libuuiddir ?= ${debdir}/libuuid${UUID_SOVERSION} +uuiddevdir ?= ${debdir}/uuid-dev +libuuiddbgdir ?= ${debdir}/libuuid1-dbg +uuidruntimedir ?= ${debdir}/uuid-runtime +uuidruntimedbgdir ?= ${debdir}/uuid-runtime-dbg +endif +libext2dir ?= ${debdir}/e2fslibs +libext2devdir ?= ${debdir}/e2fslibs-dev +libext2dbgdir ?= ${debdir}/e2fslibs-dbg +maindir ?= ${debdir}/e2fsprogs +e2fsckstaticdir ?= ${debdir}/e2fsck-static +debugdir ?= ${debdir}/e2fsprogs-dbg +stdbuilddir ?= ${debdir}/BUILD-STD +staticbuilddir ?= ${debdir}/BUILD-STATIC +mipsbuilddir ?= ${debdir}/BUILD-MIPS +mipsbuilddir64 ?= ${debdir}/BUILD-MIPS-64 +# docdir ?= ${maindir}/usr/share/doc/${package} +MANDIR ?= /usr/share/man +mandir ?= ${tmpdir}${MANDIR} + +UDEB_NAME ?= $(package)-udeb_$(MAIN_VERSION)_$(DEB_HOST_ARCH).udeb +UDEB_PRIORITY ?= $(shell grep '^Package: e2fsprogs-udeb' debian/control.in -A 10 | grep ^Priority: | cut -d ' ' -f 2) + +ifneq ($(UTIL_LINUX_NG),yes) +BLKID_UDEB_NAME ?= libblkid1-udeb_$(MAIN_VERSION)_$(DEB_HOST_ARCH).udeb +BLKID_UDEB_PRIORITY ?= $(shell grep '^Package: libblkid1-udeb' debian/control.in -A 10 | grep ^Priority: | cut -d ' ' -f 2) + +UUID_UDEB_NAME ?= libuuid1-udeb_$(MAIN_VERSION)_$(DEB_HOST_ARCH).udeb +UUID_UDEB_PRIORITY ?= $(shell grep '^Package: libuuid1-udeb' debian/control.in -A 10 | grep ^Priority: | cut -d ' ' -f 2) +endif + +STAMPSDIR ?= debian/stampdir +CFGSTDSTAMP ?= ${STAMPSDIR}/configure-std-stamp +CFGBFSTAMP ?= ${STAMPSDIR}/configure-bf-stamp +CFGSTATICSTAMP ?= ${STAMPSDIR}/configure-static-stamp +BUILDSTDSTAMP ?= ${STAMPSDIR}/build-std-stamp +BUILDBFSTAMP ?= ${STAMPSDIR}/build-bf-stamp +BUILDSTATICSTAMP ?=${STAMPSDIR}/build-static-stamp + +INSTALL ?= install +INSTALL_PROGRAM ?= $(INSTALL) -p -o root -g root -m 0755 + +#ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) +#INSTALL_PROGRAM += -s +#endif + +ifneq (,$(findstring update-symbols,$(DEB_BUILD_OPTIONS))) +SYMBOL_LIBS := e2fslibs libcomerr2 libss2 +ifneq ($(UTIL_LINUX_NG),yes) +SYMBOL_LIBS += libblkid1 libuuid1 +endif +endif + +DEFAULT_CFLAGS ?= -g -O2 +DEFAULT_LDFLAGS ?= -Wl,-Bsymbolic-functions + +CFLAGS ?= $(shell if dpkg-buildflags > /dev/null 2>&1 ; then \ + dpkg-buildflags --get CFLAGS; else echo $(DEFAULT_CFLAGS) ; fi) +LDFLAGS ?= $(shell if dpkg-buildflags > /dev/null 2>&1 ; then \ + dpkg-buildflags --get LDFLAGS; else echo $(DEFAULT_LDFLAGS) ; fi) +CPPFLAGS ?= $(shell if dpkg-buildflags > /dev/null 2>&1 ; then \ + dpkg-buildflags --get CPPFLAGS; fi) + +ifeq (${DEB_HOST_ARCH},alpha) +CFLAGS += -DHAVE_NETINET_IN_H +else +CFLAGS += -D__NO_STRING_INLINES +endif + +ifneq (${DEB_HOST_ARCH_OS},linux) +SKIP_STATIC = yes +endif + +ifeq ($(SKIP_STATIC),yes) +BUILD_STATIC = +E2FSCK_STATIC = ${stdbuilddir}/e2fsck/e2fsck.static +else +BUILD_STATIC = build-static +E2FSCK_STATIC = ${staticbuilddir}/e2fsck/e2fsck.static +endif + +ifneq ($(SKIP_UDEB),) +SKIP_BF ?= yes +endif + +ifeq ($(SKIP_BF),yes) +BUILD_BF = +bfbuilddir ?= ${stdbuilddir} +else +BUILD_BF = build-bf +bfbuilddir ?= ${debdir}/BUILD-BF +endif + +BF_CFLAGS = -Os -fomit-frame-pointer + +ifeq ($(UTIL_LINUX_NG),yes) +UTIL_CONF_FLAGS ?= --disable-fsck --disable-libblkid \ + --disable-libuuid --disable-uuidd +else +UTIL_CONF_FLAGS ?= --enable-fsck --enable-libblkid \ + --enable-libuuid --enable-uuidd +endif + +ifneq ($(strip $(DEB_HOST_MULTIARCH)),) +MULTIARCH_CONF ?= --with-multiarch=$(DEB_HOST_MULTIARCH) +# This doesn't work yet because gdb and lintian don't expect and/or +# don't work with /usr/lib/<triplet>/debug +#USRLIB = /usr/lib/$(DEB_HOST_MULTIARCH) +USRLIB ?= /usr/lib +else +USRLIB ?= /usr/lib +endif + +BACKTRACE_CONF_FLAGS ?= $(shell if ${debdir}/scripts/test-backtrace ; then echo --disable-backtrace ; fi) + +COMMON_CONF_FLAGS = --disable-e2initrd-helper --enable-quota \ + --infodir=/usr/share/info --enable-symlink-install \ + $(MULTIARCH_CONF) $(BACKTRACE_CONF_FLAGS) $(UTIL_CONF_FLAGS) + +STD_CONF_FLAGS ?= --enable-elf-shlibs + +BF_CONF_FLAGS ?= --enable-elf-shlibs --disable-nls --disable-imager \ + --disable-testio-debug --disable-uuidd --disable-tls --disable-debugfs + +STATIC_CONF_FLAGS ?= --disable-nls --disable-imager \ + --disable-uuidd --disable-tls + +MIPS_NOPIC_CONF_FLAGS ?= --disable-nls --disable-imager \ + --disable-uuidd --disable-tls \ + --disable-resizer # --disable-debugfs + +# we can't use those flags at configure time +MIPS_CFLAGS ?= -G 0 -fno-pic -mno-abicalls +MIPS_CFLAGS_64 ?= -mabi=64 -G 0 -fno-pic -mno-abicalls + +ifeq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH)) +ifneq (,$(findstring $(DEB_BUILD_ARCH),mips mipsel)) +ismips=ismips +endif +endif + +M4_ARGS= +ifeq ($(UTIL_LINUX_NG),yes) +M4_ARGS+=-DUTIL_LINUX_NG +else +M4_ARGS+=-UUTIL_LINUX_NG +endif + +ifneq ($(strip $(DEB_HOST_MULTIARCH)),) +M4_ARGS+=-DDO_MULTIARCH +else +M4_ARGS+=-UDO_MULTIARCH +endif + +ifneq ($(SKIP_DIETLIBC),) +M4_ARGS+=-UDIETLIBC +WITH_DIET_LIBC = +else +M4_ARGS+=-DDIETLIBC +WITH_DIET_LIBC = --with-diet-libc --enable-libuuid --enable-libblkid +endif + +ifneq ($(BUILD_E2FSCK_STATIC),no) +M4_ARGS+=-DE2FSCK_STATIC +else +M4_ARGS+=-UE2FSCK_STATIC +endif + +ifeq ($(SKIP_UDEB),) +INSTALL_UDEB = install-udeb +M4_ARGS+=-DUDEB_PKGS +else +M4_ARGS+=-UUDEB_PKGS +endif + +FILES_FIXUP= libcomerr2.files comerr-dev.files libss2.files ss-dev.files \ + libuuid1.files uuid-dev.files libblkid1.files libblkid-dev.files \ + e2fslibs.files e2fslibs-dev.files + +debian-files: debian/control debian/e2fsprogs.shlibs.local +ifeq ($(strip $(DEB_HOST_MULTIARCH)),) + for i in $(FILES_FIXUP); do \ + sed -e 's;lib/\*/;lib/;' debian/$$i.in > debian/$$i; \ + done +else + for i in $(FILES_FIXUP); do cp debian/$$i.in debian/$$i; done +endif + +mrproper: clean + rm debian/control debian/e2fsprogs.shlibs.local + +debian/control: debian/control.in debian/rules + m4 $(M4_ARGS) < debian/control.in | grep -v ^REMOVE_ME$$ > $@ + +debian/e2fsprogs.shlibs.local: debian/e2fsprogs.shlibs.local.in + m4 $(M4_ARGS) < debian/e2fsprogs.shlibs.local.in > $@ + +${CFGSTDSTAMP}: + dh_testdir + + # Make sure we don't try to rebuild the configure scripts + find . -name configure | xargs touch + + mkdir -p ${stdbuilddir} +ifeq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH)) + cd ${stdbuilddir} && AWK=/usr/bin/awk \ + ${topdir}/configure ${COMMON_CONF_FLAGS} ${STD_CONF_FLAGS} \ + ${EXTRA_CONF_FLAGS} CFLAGS="${CFLAGS}" CPPFLAGS="$(CPPFLAGS)" \ + LDFLAGS="$(LDFLAGS)" +else + cd ${stdbuilddir} && AWK=/usr/bin/awk CC="${DEB_HOST_GNU_TYPE}-gcc" \ + ${topdir}/configure ${COMMON_CONF_FLAGS} ${STD_CONF_FLAGS} \ + ${EXTRA_CONF_FLAGS} --build=$(DEB_BUILD_GNU_TYPE) \ + --host=$(DEB_HOST_GNU_TYPE) CFLAGS="${CFLAGS}" \ + CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" +endif + + # specially-built MIPS libs +ifneq ($(ismips),) + mkdir -p ${mipsbuilddir} ${mipsbuilddir64} + cd ${mipsbuilddir} && AWK=/usr/bin/awk \ + ${topdir}/configure ${COMMON_CONF_FLAGS} \ + ${MIPS_NOPIC_CONF_FLAGS} CFLAGS="${CFLAGS}" \ + CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" + cd ${mipsbuilddir64} && AWK=/usr/bin/awk \ + ${topdir}/configure ${COMMON_CONF_FLAGS} \ + ${MIPS_NOPIC_CONF_FLAGS} CFLAGS="${CFLAGS}" \ + CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" +endif + + mkdir -p ${STAMPSDIR} + touch ${CFGSTDSTAMP} + +${CFGBFSTAMP}: + dh_testdir + rm -f config.cache + + mkdir -p ${bfbuilddir} +ifeq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH)) + cd ${bfbuilddir} && AWK=/usr/bin/awk \ + ${topdir}/configure ${COMMON_CONF_FLAGS} ${BF_CONF_FLAGS} \ + ${EXTRA_CONF_FLAGS} CFLAGS="${CFLAGS} ${BF_CFLAGS}" \ + CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" +else + cd ${bfbuilddir} && AWK=/usr/bin/awk CC="${DEB_HOST_GNU_TYPE}-gcc" \ + ${topdir}/configure ${COMMON_CONF_FLAGS} ${BF_CONF_FLAGS} \ + ${EXTRA_CONF_FLAGS} --build=$(DEB_BUILD_GNU_TYPE) \ + --host=$(DEB_HOST_GNU_TYPE) CFLAGS="${CFLAGS}" \ + CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" +endif + mkdir -p ${STAMPSDIR} + touch ${CFGBFSTAMP} + +${CFGSTATICSTAMP}: + dh_testdir + rm -f config.cache + + mkdir -p ${staticbuilddir} +ifeq ($(DEB_BUILD_ARCH),$(DEB_HOST_ARCH)) + if type diet > /dev/null 2>&1 ; then \ + cd ${staticbuilddir} && AWK=/usr/bin/awk \ + ${topdir}/configure ${COMMON_CONF_FLAGS} ${STATIC_CONF_FLAGS} \ + ${EXTRA_CONF_FLAGS} ${WITH_DIET_LIBC} CFLAGS="${CFLAGS}" \ + CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)"; \ + else \ + cd ${staticbuilddir} && AWK=/usr/bin/awk \ + ${topdir}/configure ${COMMON_CONF_FLAGS} \ + ${STATIC_CONF_FLAGS} ${EXTRA_CONF_FLAGS} \ + CFLAGS="${CFLAGS}" CPPFLAGS="$(CPPFLAGS)" \ + LDFLAGS="$(LDFLAGS)"; \ + fi +else + cd ${staticbuilddir} && AWK=/usr/bin/awk CC="${DEB_HOST_GNU_TYPE}-gcc" \ + ${topdir}/configure ${COMMON_CONF_FLAGS} ${STATIC_CONF_FLAGS} \ + ${EXTRA_CONF_FLAGS} --build=$(DEB_BUILD_GNU_TYPE) \ + --host=$(DEB_HOST_GNU_TYPE) CFLAGS="${CFLAGS}" \ + CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" +endif + mkdir -p ${STAMPSDIR} + touch ${CFGSTATICSTAMP} + +build-arch: build +build-indep: build +build: build-std $(BUILD_BF) $(BUILD_STATIC) + +build-std: ${BUILDSTDSTAMP} +${BUILDSTDSTAMP}: ${CFGSTDSTAMP} + dh_testdir + $(MAKE) -C ${stdbuilddir} V=1 all +ifneq ($(BUILD_E2FSCK_STATIC),no) + $(MAKE) -C ${stdbuilddir}/e2fsck V=1 e2fsck.static +endif + $(MAKE) -C ${stdbuilddir}/po V=1 update-gmo + + ( cd ${stdbuilddir}/doc && $(MAKE) V=1 libext2fs.html ) + ( cd ${stdbuilddir}/lib/et && $(MAKE) V=1 com_err.info com_err.html ) + + # specially-built MIPS libs +ifneq ($(ismips),) + $(MAKE) -C ${mipsbuilddir}/util V=1 + $(MAKE) -C ${mipsbuilddir} V=1 \ + CFLAGS="${CFLAGS} ${MIPS_CFLAGS}" \ + LIB_SUBDIRS="lib/et lib/ext2fs" libs + $(MAKE) -C ${mipsbuilddir64}/util V=1 + $(MAKE) -C ${mipsbuilddir64} V=1 \ + CFLAGS="${CFLAGS} ${MIPS_CFLAGS_64}" \ + LIB_SUBDIRS="lib/et lib/ext2fs" libs +endif + + touch ${BUILDSTDSTAMP} + +build-bf: ${BUILDBFSTAMP} +${BUILDBFSTAMP}: ${CFGBFSTAMP} + dh_testdir + $(MAKE) -C ${bfbuilddir} V=1 libs + $(MAKE) -C ${bfbuilddir}/e2fsck V=1 all + $(MAKE) -C ${bfbuilddir}/misc V=1 all + $(MAKE) -C ${bfbuilddir}/resize V=1 all + touch ${BUILDBFSTAMP} + +build-static: ${BUILDSTATICSTAMP} +${BUILDSTATICSTAMP}: ${CFGSTATICSTAMP} + dh_testdir + $(MAKE) -C ${staticbuilddir} V=1 libs +ifneq ($(BUILD_E2FSCK_STATIC),no) + $(MAKE) -C ${staticbuilddir}/e2fsck V=1 all e2fsck.static +endif + touch ${BUILDSTATICSTAMP} + +clean: + dh_testdir + rm -rf ${STAMPSDIR} + [ ! -f ${stdbuilddir}/Makefile ] || $(MAKE) -C ${stdbuilddir} V=1 distclean + [ ! -f ${bfbuilddir}/Makefile ] || $(MAKE) -C ${bfbuilddir} V=1 distclean + [ ! -f ${staticbuilddir}/Makefile ] || $(MAKE) -C ${staticbuilddir} V=1 distclean + rm -rf ${stdbuilddir} ${bfbuilddir} ${staticbuilddir} ${mipsbuilddir} ${mipsbuilddir64} + rm -f debian/*.substvars + dh_clean + +install: cleanup install-std + +# This rule allows to factorize the dh_clean between the 2 install rules +# This must be launched before install-* (if launching them by hand, for +# exemple) or results are unpredictable +cleanup: + dh_testdir + dh_testroot + dh_prep + +install-std: DH_OPTIONS= +install-std: build + dh_testdir + dh_testroot + dh_installdirs + + mkdir -p ${tmpdir}/sbin + $(MAKE) -C ${stdbuilddir} V=1 install DESTDIR=${tmpdir} \ + INSTALL_PROGRAM="${INSTALL_PROGRAM}" LDCONFIG=true + # static libs and .h files + $(MAKE) -C ${stdbuilddir} V=1 install-libs DESTDIR=${tmpdir} LDCONFIG=true + +ifneq ($(BUILD_E2FSCK_STATIC),no) + # statically-linked fsck + ${INSTALL_PROGRAM} $(E2FSCK_STATIC) ${tmpdir}/sbin + cp ${mandir}/man8/e2fsck.8 ${mandir}/man8/e2fsck.static.8 +endif + +ifeq ($(DEB_BUILD_GNU_SYSTEM), gnu) + ${INSTALL} -m 0644 misc/mke2fs-hurd.conf ${tmpdir}/etc/mke2fs.conf +endif + + dh_movefiles + test -z "`find ${tmpdir} -type f`" + + # specially-built MIPS libs +ifneq ($(ismips),) + $(INSTALL) -p -m 0644 ${mipsbuilddir}/lib/libext2fs.a \ + ${debdir}/e2fslibs-dev/usr/lib/libext2fs-nopic.a + $(INSTALL) -p -m 0644 ${mipsbuilddir64}/lib/libext2fs.a \ + ${debdir}/e2fslibs-dev/usr/lib/lib64ext2fs-nopic.a +endif + +install-udeb: DH_OPTIONS= +install-udeb: build + dh_testdir + dh_testroot + + $(MAKE) -C ${bfbuilddir} V=1 install-shlibs-libs-recursive DESTDIR=${udebdir} \ + INSTALL_PROGRAM="${INSTALL_PROGRAM}" LDCONFIG=true + $(MAKE) -C ${bfbuilddir}/e2fsck V=1 install DESTDIR=${udebdir} \ + INSTALL_PROGRAM="${INSTALL_PROGRAM}" LDCONFIG=true + $(MAKE) -C ${bfbuilddir}/misc V=1 install DESTDIR=${udebdir} \ + INSTALL_PROGRAM="${INSTALL_PROGRAM}" LDCONFIG=true + $(MAKE) -C ${bfbuilddir}/resize V=1 install DESTDIR=${udebdir} \ + INSTALL_PROGRAM="${INSTALL_PROGRAM}" LDCONFIG=true + + rm -rf ${udebdir}/usr + find ${udebdir}/sbin -type f -a ! -name e2fsck \ + -a ! -name mke2fs -a ! -name tune2fs \ + -a ! -name resize2fs -a ! -name badblocks -print | xargs rm + + (cd ${udebdir}/sbin; ln -sf e2fsck fsck.ext2 ; \ + ln -sf e2fsck fsck.ext3 ; ln -sf e2fsck fsck.ext4 ; \ + ln -sf mke2fs mkfs.ext2 ; ln -sf mke2fs mkfs.ext3 ; \ + ln -sf mke2fs mkfs.ext4) + +ifneq ($(UTIL_LINUX_NG),yes) + mkdir -p ${blkidudebdir}/lib + mv ${udebdir}/lib/libblkid.* ${blkidudebdir}/lib + + mkdir -p ${uuidudebdir}/lib + mv ${udebdir}/lib/libuuid.* ${uuidudebdir}/lib +endif + +binary-indep: + # no arch-independant debs. + +binary-arch: DH_OPTIONS= -a +binary-arch: install $(INSTALL_UDEB) + dh_testdir + dh_testroot + + # lintian overrides + for i in $$(cd debian && echo *.lintian-overrides); do \ + pkg=$${i%.lintian-overrides} ;\ + if test "$${pkg}" != source ; then \ + $(INSTALL) -m 0644 -D -p debian/$$i ${debdir}/$${pkg}/usr/share/lintian/overrides/$${pkg} ;\ + fi ;\ + done + + # symlinks to prepare dh_installdocs run + +ifneq ($(UTIL_LINUX_NG),yes) + mkdir -p ${debdir}/libblkid${BLKID_SOVERSION}/usr/share/doc/libblkid${BLKID_SOVERSION} + mkdir -p ${debdir}/libblkid-dev/usr/share/doc + ln -sf libblkid${BLKID_SOVERSION} ${debdir}/libblkid-dev/usr/share/doc/libblkid-dev +endif + + mkdir -p ${debdir}/libss${SS_SOVERSION}/usr/share/doc/libss${SS_SOVERSION} + mkdir -p ${debdir}/ss-dev/usr/share/doc + ln -sf libss${SS_SOVERSION} ${debdir}/ss-dev/usr/share/doc/ss-dev + + mkdir -p ${debdir}/libcomerr${COMERR_SOVERSION}/usr/share/doc/libcomerr${COMERR_SOVERSION} + mkdir -p ${debdir}/comerr-dev/usr/share/doc + ln -sf libcomerr${COMERR_SOVERSION} ${debdir}/comerr-dev/usr/share/doc/comerr-dev + +ifneq ($(UTIL_LINUX_NG),yes) + mkdir -p ${debdir}/libuuid${UUID_SOVERSION}/usr/share/doc/libuuid${UUID_SOVERSION} + mkdir -p ${debdir}/uuid-dev/usr/share/doc +# ln -sf libuuid${UUID_SOVERSION} ${debdir}/uuid-dev/usr/share/doc/uuid-dev +endif + + mkdir -p ${debdir}/e2fslibs/usr/share/doc/e2fslibs + mkdir -p ${debdir}/e2fslibs-dev/usr/share/doc + ln -sf e2fslibs ${debdir}/e2fslibs-dev/usr/share/doc/e2fslibs-dev + +ifneq ($(UTIL_LINUX_NG),yes) + $(INSTALL) -p -m 0644 debian/libblkid.copyright \ + ${debdir}/libblkid${BLKID_SOVERSION}/usr/share/doc/libblkid${BLKID_SOVERSION}/copyright +endif + + dh_installdocs -Ne2fsprogs-udeb -Nlibblkid1-udeb -Nlibuuid1-udeb + + # HTML docs + $(INSTALL) -d ${debdir}/e2fslibs-dev/usr/share/doc/e2fslibs/html-info/ + $(INSTALL) -p -m 0644 ${stdbuilddir}/doc/*.html \ + ${debdir}/e2fslibs-dev/usr/share/doc/e2fslibs/html-info/ + $(INSTALL) -d ${debdir}/comerr-dev/usr/share/doc/libcomerr${COMERR_SOVERSION}/html-info/ + $(INSTALL) -p -m 0644 ${stdbuilddir}/lib/et/*.html \ + ${debdir}/comerr-dev/usr/share/doc/libcomerr${COMERR_SOVERSION}/html-info/ + + # texinfo docs + mkdir -p ${debdir}/comerr-dev/usr/share/doc/libcomerr${COMERR_SOVERSION} + $(INSTALL) -p -m 0644 ${topdir}/doc/libext2fs.texinfo \ + ${debdir}/e2fslibs-dev/usr/share/doc/e2fslibs/libext2fs.texi + $(INSTALL) -p -m 0644 ${topdir}/lib/et/com_err.texinfo \ + ${debdir}/comerr-dev/usr/share/doc/libcomerr${COMERR_SOVERSION}/com_err.texi + + $(INSTALL) -d ${debdir}/comerr-dev/usr/share/doc/libcomerr${COMERR_SOVERSION}/examples + $(INSTALL) -p -m 0644 lib/ss/ss_err.et \ + ${stdbuilddir}/lib/ext2fs/ext2_err.et \ + ${debdir}/comerr-dev/usr/share/doc/libcomerr${COMERR_SOVERSION}/examples + $(INSTALL) -d ${debdir}/ss-dev/usr/share/doc/libss${SS_SOVERSION}/examples + $(INSTALL) -p -m 0644 debugfs/debug_cmds.ct \ + ${debdir}/ss-dev/usr/share/doc/libss${SS_SOVERSION}/examples + + dh_installinfo -pcomerr-dev ${stdbuilddir}/lib/et/com_err.info + dh_installinfo -pe2fslibs-dev ${stdbuilddir}/doc/libext2fs.info + + DH_OPTIONS= dh_installchangelogs -pe2fsprogs \ + -plibcomerr${COMERR_SOVERSION} \ + -plibss${SS_SOVERSION} \ + -pe2fslibs \ + -pe2fsprogs-dbg -pe2fslibs-dbg \ + -plibcomerr2-dbg -plibss2-dbg +ifneq ($(BUILD_E2FSCK_STATIC),no) + DH_OPTIONS= dh_installchangelogs -pe2fsck-static +endif +ifneq ($(UTIL_LINUX_NG),yes) + DH_OPTIONS= dh_installchangelogs -plibuuid${UUID_SOVERSION} \ + -puuid-dev -puuid-runtime -puuid-runtime-dbg -plibuuid1-dbg \ + -plibblkid${BLKID_SOVERSION} -plibblkid1-dbg +endif + + dh_fixperms + dh_strip -pe2fsprogs --dbg-package=e2fsprogs-dbg +ifneq ($(BUILD_E2FSCK_STATIC),no) + dh_strip -pe2fsck-static --dbg-package=e2fsprogs-dbg +endif +ifneq ($(ismips),) + dh_strip -pe2fslibs --dbg-package=e2fslibs-dbg -Xlib64ext2fs-nopic.a +else + dh_strip -pe2fslibs --dbg-package=e2fslibs-dbg +endif + dh_strip -plibss${SS_SOVERSION} --dbg-package=libss${SS_SOVERSION}-dbg + dh_strip -plibcomerr${COMERR_SOVERSION} \ + --dbg-package=libcomerr${COMERR_SOVERSION}-dbg +ifneq ($(UTIL_LINUX_NG),yes) + dh_strip -plibblkid${BLKID_SOVERSION} \ + --dbg-package=libblkid${BLKID_SOVERSION}-dbg + dh_strip -plibuuid${UUID_SOVERSION} --dbg-package=libuuid${UUID_SOVERSION}-dbg +endif + dh_strip + + # dpkg symbol handling + for i in $(SYMBOL_LIBS); \ + do \ + echo "Generating symbols for $$i..."; \ + dpkg-gensymbols -p$$i -Pdebian/$$i > debian/$$i.tmp-patch; \ + cat debian/$$i.tmp-patch; \ + patch debian/$$i.symbols < debian/$$i.tmp-patch; \ + /bin/rm debian/$$i.tmp-patch; \ + done + + for i in e2fsprogs e2fsprogs-dbg e2fslibs e2fslibs-dbg; do \ + $(INSTALL) -p -m 0644 debian/copyright \ + ${debdir}/$$i/usr/share/doc/$$i/copyright; \ + done + +ifneq ($(UTIL_LINUX_NG),yes) + $(INSTALL) -p -m 0644 debian/uuid-runtime.copyright \ + ${uuidruntimedbgdir}/usr/share/doc/uuid-runtime-dbg/copyright +endif + + $(INSTALL) -p -m 0644 debian/libcomerr2.copyright \ + ${libcomerrdbgdir}/usr/share/doc/libcomerr2-dbg/copyright + + $(INSTALL) -p -m 0644 debian/libss2.copyright \ + ${libssdbgdir}/usr/share/doc/libss2-dbg/copyright + +ifneq ($(UTIL_LINUX_NG),yes) + $(INSTALL) -p -m 0644 debian/libblkid.copyright \ + ${libblkiddbgdir}/usr/share/doc/libblkid1-dbg/copyright + + $(INSTALL) -p -m 0644 debian/libuuid1.copyright \ + ${libuuiddbgdir}/usr/share/doc/libuuid1-dbg/copyright +endif + + dh_compress + + dh_makeshlibs -Ne2fsprogs-udeb -Nlibblkid1-udeb -Nlibuuid1-udeb +ifeq ($(SKIP_UDEB),) + dh_makeshlibs --add-udeb=e2fsprogs-udeb -plibcomerr${COMERR_SOVERSION} \ + -V 'libcomerr2 (>= 1.33-3)' +ifneq ($(UTIL_LINUX_NG),yes) + dh_makeshlibs -plibblkid${BLKID_SOVERSION} -V 'libblkid1 (>= 1.39-1)' + echo "udeb: libblkid 1 libblkid1-udeb" >> \ + debian/libblkid1/DEBIAN/shlibs + echo "udeb: libuuid 1 libuuid1-udeb" >> debian/libuuid1/DEBIAN/shlibs +endif +endif + + dh_installdeb + dh_shlibdeps -l${stdbuilddir}/lib + dh_shlibdeps -pe2fsprogs -l${stdbuilddir}/lib \ + -u"-Ldebian/e2fsprogs.shlibs.local" +ifeq ($(SKIP_UDEB),) + dh_shlibdeps -pe2fsprogs-udeb -l${stdbuilddir}/lib \ + -u"-Ldebian/e2fsprogs-udeb.shlibs.local" +endif + + dh_gencontrol -Ncomerr-dev -Nss-dev -Nuuid-dev \ + -Ne2fsprogs-udeb -Nlibblkid1-udeb -Nlibuuid1-udeb + DH_OPTIONS= dh_gencontrol -pcomerr-dev \ + -u '-v${COMERR_VERSION}-${MAIN_VERSION} -VmainBinary=${MAIN_VERSION}' + DH_OPTIONS= dh_gencontrol -pss-dev \ + -u '-v${SS_VERSION}-${MAIN_VERSION} -VmainBinary=${MAIN_VERSION}' +ifneq ($(UTIL_LINUX_NG),yes) + DH_OPTIONS= dh_gencontrol -puuid-dev \ + -u '-v${UUID_VERSION}-${MAIN_VERSION} -VmainBinary=${MAIN_VERSION}' +endif +ifeq ($(SKIP_UDEB),) + dh_gencontrol -pe2fsprogs-udeb -- -fdebian/files~ +ifneq ($(UTIL_LINUX_NG),yes) + dh_gencontrol -plibblkid1-udeb -- -fdebian/files~ + dh_gencontrol -plibuuid1-udeb -- -fdebian/files~ +endif +endif + +ifeq ($(SKIP_UDEB),) + dpkg-distaddfile $(UDEB_NAME) debian-installer $(UDEB_PRIORITY) +ifneq ($(UTIL_LINUX_NG),yes) + dpkg-distaddfile $(BLKID_UDEB_NAME) debian-installer $(BLKID_UDEB_PRIORITY) + dpkg-distaddfile $(UUID_UDEB_NAME) debian-installer $(UUID_UDEB_PRIORITY) +endif +endif + dh_md5sums -Ne2fsprogs-udeb -Nlibblkid1-udeb -Nlibuuid1-udeb + dh_builddeb -Ne2fsprogs-udeb -Nlibblkid1-udeb -Nlibuuid1-udeb +ifeq ($(SKIP_UDEB),) + dh_builddeb -pe2fsprogs-udeb --filename=$(UDEB_NAME) +ifneq ($(UTIL_LINUX_NG),yes) + dh_builddeb -plibblkid1-udeb --filename=$(BLKID_UDEB_NAME) + dh_builddeb -plibuuid1-udeb --filename=$(UUID_UDEB_NAME) +endif +endif + +binary: binary-indep binary-arch + +.PHONY: binary binary-arch binary-indep clean checkroot mrproper \ + debug_flags debian-files + +debug_flags: + @echo CFLAGS is $(CFLAGS) + @echo LDFLAGS is $(LDFLAGS) + @echo CPPFLAGS is $(CPPFLAGS)
diff --git a/debian/scripts/test-backtrace b/debian/scripts/test-backtrace new file mode 100755 index 0000000..d90486a --- /dev/null +++ b/debian/scripts/test-backtrace
@@ -0,0 +1,34 @@ +#!/bin/sh +# +# Test to see if backtrace requires a library in /usr/lib +# Returns true if the backtrace command works and requires a library in /usr/lib +# This is a nasty workaround for Debian bug #708307, which is really a glibc bug +# + +cat > /tmp/backtrace$$.c << EOF + +#include <execinfo.h> + +int main(int argc, char **argv) +{ + void *stack_syms[32]; + int frames; + + frames = backtrace(stack_syms, 32); + backtrace_symbols_fd(stack_syms, frames, 0); +} +EOF + +if ! cc -o /tmp/backtrace$$ /tmp/backtrace$$.c; then + exit 1 +fi + +if ! ldd /tmp/backtrace$$ > /tmp/backtrace$$.ldd 2>&1 ; then + exit 1 +fi + +grep -q /usr/lib /tmp/backtrace$$.ldd +ret=$? + +/bin/rm -f /tmp/backtrace$$* +exit $ret
diff --git a/debian/shlibs.local b/debian/shlibs.local new file mode 100644 index 0000000..e678de0 --- /dev/null +++ b/debian/shlibs.local
@@ -0,0 +1,6 @@ +libext2fs 2 +libe2p 2 +libuuid 1 +libcom_err 2 +libss 2 +libblkid 1
diff --git a/debian/source.lintian-overrides b/debian/source.lintian-overrides new file mode 100644 index 0000000..fd597df --- /dev/null +++ b/debian/source.lintian-overrides
@@ -0,0 +1,4 @@ +e2fsprogs source: weak-library-dev-dependency ss-dev on libss2 (= ${mainBinary}) +e2fsprogs source: weak-library-dev-dependency comerr-dev on libcomerr2 (= ${mainBinary}) +e2fsprogs source: weak-library-dev-dependency uuid-dev on libuuid1 (= ${mainBinary}) +e2fsprogs source: source-is-missing misc/util.o
diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format
@@ -0,0 +1 @@ +3.0 (quilt)
diff --git a/debian/ss-dev.examples b/debian/ss-dev.examples new file mode 100644 index 0000000..b7930bb --- /dev/null +++ b/debian/ss-dev.examples
@@ -0,0 +1 @@ +debugfs/debug_cmds.ct
diff --git a/debian/ss-dev.files.in b/debian/ss-dev.files.in new file mode 100644 index 0000000..d0c788e --- /dev/null +++ b/debian/ss-dev.files.in
@@ -0,0 +1,7 @@ +usr/lib/*/libss.so +usr/lib/*/libss.a +usr/include/ss/* +usr/bin/mk_cmds +usr/share/ss/* +usr/share/man/man1/mk_cmds* +usr/lib/*/pkgconfig/ss.pc
diff --git a/debian/uuid-dev.README.Debian b/debian/uuid-dev.README.Debian new file mode 100644 index 0000000..3d8cc89 --- /dev/null +++ b/debian/uuid-dev.README.Debian
@@ -0,0 +1,23 @@ + +In order to santize e2fsprogs to be DFSG free, the file +draft-leach-uuids-guids-01.txt has been removed. It can be obtained +by downloading e2fsprogs from the upstream sources. It may also be +available from other sites on the network, if you do a quick web +search for the string "draft-leach-uuids-guids-01". + +Note that debian/rules is set up to include the file on Ubuntu +systems, so for people trying to build e2fsprogs on Ubuntu systems, +they should start from the upstream sources, and not the +Debian-expurgated sources found in the Debian repository. (n.b., for +WIP releases the command "./util/gen-tarball ubuntu" will help create +tar file which is appropriately named to make life easier for +dpkg-buildpackage.) Since Ubuntu doesn't have the DFSG restrictions, +the documentation which has been removed for Debian's DFSG license +purity shouldn't be denied to Ubuntu users. + + Theodore Ts'o + Ocotober 3, 2006 + + + +
diff --git a/debian/uuid-dev.copyright b/debian/uuid-dev.copyright new file mode 100644 index 0000000..f346739 --- /dev/null +++ b/debian/uuid-dev.copyright
@@ -0,0 +1,38 @@ +This package was added to the e2fsprogs debian source package by +Theodore Ts'o <tytso@mit.edu> on Sat Mar 15 15:33:37 EST 2003 + +It is part of the main e2fsprogs distribution, which can be found at: + + http://sourceforge.net/projects/e2fsprogs + +Upstream Author: Theodore Ts'o <tytso@mit.edu> + +Copyright: + +Copyright (C) 1999, 2000, 2003, 2004 by Theodore Ts'o + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, and the entire permission notice in its entirety, + including the disclaimer of warranties. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF +WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE.
diff --git a/debian/uuid-dev.files.in b/debian/uuid-dev.files.in new file mode 100644 index 0000000..534b92c --- /dev/null +++ b/debian/uuid-dev.files.in
@@ -0,0 +1,5 @@ +usr/lib/*/libuuid.so +usr/lib/*/libuuid.a +usr/include/uuid/* +usr/share/man/man3/uuid* +usr/lib/*/pkgconfig/uuid.pc
diff --git a/debian/uuid-runtime.copyright b/debian/uuid-runtime.copyright new file mode 100644 index 0000000..afcd4c5 --- /dev/null +++ b/debian/uuid-runtime.copyright
@@ -0,0 +1,39 @@ +This package was added to the e2fsprogs debian source package by +Theodore Ts'o <tytso@mit.edu> on Fri Dec 14 22:24:35 EST 2007 + +It is part of the main e2fsprogs distribution, which can be found at: + + http://sourceforge.net/projects/e2fsprogs + +Upstream Author: Theodore Ts'o <tytso@mit.edu> + +Copyright: + +Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 by +Theodore Ts'o + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, and the entire permission notice in its entirety, + including the disclaimer of warranties. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF +WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE.
diff --git a/debian/uuid-runtime.files b/debian/uuid-runtime.files new file mode 100644 index 0000000..ff8d87a --- /dev/null +++ b/debian/uuid-runtime.files
@@ -0,0 +1,4 @@ +usr/bin/uuidgen +usr/sbin/uuidd +usr/share/man/man8/uuidd.* +usr/share/man/man1/uuidgen.*
diff --git a/debian/uuid-runtime.lintian-overrides b/debian/uuid-runtime.lintian-overrides new file mode 100644 index 0000000..4642d30 --- /dev/null +++ b/debian/uuid-runtime.lintian-overrides
@@ -0,0 +1 @@ +uuid-runtime: command-with-path-in-maintainer-script prerm:5 /usr/sbin/uuidd
diff --git a/debian/uuid-runtime.postinst b/debian/uuid-runtime.postinst new file mode 100644 index 0000000..3c1adb6 --- /dev/null +++ b/debian/uuid-runtime.postinst
@@ -0,0 +1,15 @@ +#!/bin/sh + +set -e +if ! getent group | grep -q libuuid; then +groupadd -f -K GID_MIN=1 -K GID_MAX=999 libuuid +fi +if ! getent passwd | grep -q libuuid; then + useradd -d /var/lib/libuuid -K UID_MIN=1 -K UID_MAX=499 -g libuuid libuuid +fi +chown libuuid:libuuid /usr/sbin/uuidd +chmod 6755 /usr/sbin/uuidd + +#DEBHELPER# + +exit 0
diff --git a/debian/uuid-runtime.postrm b/debian/uuid-runtime.postrm new file mode 100644 index 0000000..f077001 --- /dev/null +++ b/debian/uuid-runtime.postrm
@@ -0,0 +1,10 @@ +#!/bin/sh +set -e +if [ "$1" = purge ] +then + rm -rf /var/run/uuidd +fi + +#DEBHELPER# + +exit 0
diff --git a/debian/uuid-runtime.prerm b/debian/uuid-runtime.prerm new file mode 100644 index 0000000..904e161 --- /dev/null +++ b/debian/uuid-runtime.prerm
@@ -0,0 +1,10 @@ +#! /bin/sh +set -e +if [ -x /usr/sbin/uuidd ] +then + /usr/sbin/uuidd -k || true +fi + +#DEBHELPER# + +exit 0
diff --git a/debian/uuid-runtime.shlibs.local b/debian/uuid-runtime.shlibs.local new file mode 100644 index 0000000..5d97674 --- /dev/null +++ b/debian/uuid-runtime.shlibs.local
@@ -0,0 +1 @@ +libuuid 1 libuuid1 (> 1.40.3-1)
diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..96f61d3 --- /dev/null +++ b/debian/watch
@@ -0,0 +1,4 @@ +version=3 +http://sf.net/e2fsprogs/e2fsprogs-([0-9].+)\.tar\.gz +#ftp://ftp.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/e2fsprogs-([0-9].+)\.tar\.gz +
diff --git a/debugfs/Makefile.in b/debugfs/Makefile.in new file mode 100644 index 0000000..3dd06f0 --- /dev/null +++ b/debugfs/Makefile.in
@@ -0,0 +1,287 @@ +# +# Standard e2fsprogs prologue.... +# + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +top_builddir = .. +my_dir = debugfs +INSTALL = @INSTALL@ + +@MCONFIG@ + +PROGS= debugfs +MANPAGES= debugfs.8 + +MK_CMDS= _SS_DIR_OVERRIDE=../lib/ss ../lib/ss/mk_cmds + +DEBUG_OBJS= debug_cmds.o debugfs.o util.o ncheck.o icheck.o ls.o \ + lsdel.o dump.o set_fields.o logdump.o htree.o unused.o e2freefrag.o \ + filefrag.o extent_cmds.o extent_inode.o zap.o quota.o + +RO_DEBUG_OBJS= ro_debug_cmds.o ro_debugfs.o util.o ncheck.o icheck.o ls.o \ + lsdel.o logdump.o htree.o e2freefrag.o filefrag.o extent_cmds.o \ + extent_inode.o quota.o + +SRCS= debug_cmds.c $(srcdir)/debugfs.c $(srcdir)/util.c $(srcdir)/ls.c \ + $(srcdir)/ncheck.c $(srcdir)/icheck.c $(srcdir)/lsdel.c \ + $(srcdir)/dump.c $(srcdir)/set_fields.c ${srcdir}/logdump.c \ + $(srcdir)/htree.c $(srcdir)/unused.c ${srcdir}/../misc/e2freefrag.c \ + $(srcdir)/filefrag.c $(srcdir)/extent_inode.c $(srcdir)/zap.c \ + $(srcdir)/quota.c + +LIBS= $(LIBQUOTA) $(LIBEXT2FS) $(LIBE2P) $(LIBSS) $(LIBCOM_ERR) $(LIBBLKID) \ + $(LIBUUID) $(SYSLIBS) +DEPLIBS= $(DEPLIBQUOTA) $(LIBEXT2FS) $(LIBE2P) $(DEPLIBSS) $(DEPLIBCOM_ERR) \ + $(DEPLIBBLKID) $(DEPLIBUUID) + +STATIC_LIBS= $(STATIC_LIBQUOTA) $(STATIC_LIBEXT2FS) $(STATIC_LIBSS) \ + $(STATIC_LIBCOM_ERR) $(STATIC_LIBBLKID) $(STATIC_LIBUUID) \ + $(STATIC_LIBE2P) $(SYSLIBS) +STATIC_DEPLIBS= $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBSS) \ + $(DEPSTATIC_LIBCOM_ERR) $(DEPSTATIC_LIBUUID) \ + $(DEPSTATIC_LIBE2P) + +.c.o: + $(E) " CC $<" + $(Q) $(CC) -c $(ALL_CFLAGS) $< -o $@ + $(Q) $(CHECK_CMD) $(ALL_CFLAGS) $< + +all:: $(PROGS) $(MANPAGES) + +debugfs: $(DEBUG_OBJS) $(DEPLIBS) + $(E) " LD $@" + $(Q) $(CC) $(ALL_LDFLAGS) -o debugfs $(DEBUG_OBJS) $(LIBS) + +debugfs.static: $(DEBUG_OBJS) $(STATIC_DEPLIBS) + $(E) " LD $@" + $(Q) $(CC) $(LDFLAGS_STATIC) -o debugfs.static $(DEBUG_OBJS) \ + $(STATIC_LIBS) $(READLINE_LIB) + +rdebugfs: $(RO_DEBUG_OBJS) $(DEPLIBS) + $(E) " LD $@" + $(Q) $(CC) $(ALL_LDFLAGS) -o rdebugfs $(RO_DEBUG_OBJS) $(LIBS) + +debug_cmds.c debug_cmds.h: debug_cmds.ct + $(E) " MK_CMDS $@" + $(Q) $(MK_CMDS) $(srcdir)/debug_cmds.ct + +extent_cmds.c extent_cmds.h: extent_cmds.ct + $(E) " MK_CMDS $@" + $(Q) $(MK_CMDS) $(srcdir)/extent_cmds.ct + +ro_debug_cmds.c ro_debug_cmds.h: ro_debug_cmds.ct + $(E) " MK_CMDS $@" + $(Q) $(MK_CMDS) $(srcdir)/ro_debug_cmds.ct + +ro_debugfs.o: debugfs.c + $(E) " CC $@" + $(Q) $(CC) -c $(ALL_CFLAGS) $< -DREAD_ONLY -o $@ + +e2freefrag.o: $(srcdir)/../misc/e2freefrag.c + $(E) " CC $@" + $(Q) $(CC) -c $(ALL_CFLAGS) -I$(srcdir) $< -DDEBUGFS -o $@ + +debugfs.8: $(DEP_SUBSTITUTE) $(srcdir)/debugfs.8.in + $(E) " SUBST $@" + $(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/debugfs.8.in debugfs.8 + +installdirs: + $(E) " MKINSTALLDIRS $(root_sbindir) $(man8dir)" + $(Q) $(MKINSTALLDIRS) $(DESTDIR)$(root_sbindir) \ + $(DESTDIR)$(man8dir) + +install: $(PROGS) $(MANPAGES) installdirs + $(Q) for i in $(PROGS); do \ + echo " INSTALL $(root_sbindir)/$$i"; \ + $(INSTALL_PROGRAM) $$i $(DESTDIR)$(root_sbindir)/$$i; \ + done + $(Q) for i in $(MANPAGES); do \ + for j in $(COMPRESS_EXT); do \ + $(RM) -f $(DESTDIR)$(man8dir)/$$i.$$j; \ + done; \ + echo " INSTALL_DATA $(man8dir)/$$i"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(man8dir)/$$i; \ + done + +install-strip: install + $(Q) for i in $(PROGS); do \ + echo " STRIP $(root_sbindir)/$$i"; \ + $(STRIP) $(DESTDIR)$(root_sbindir)/$$i; \ + done + +uninstall: + for i in $(PROGS); do \ + $(RM) -f $(DESTDIR)$(root_sbindir)/$$i; \ + done + for i in $(MANPAGES); do \ + $(RM) -f $(DESTDIR)$(man8dir)/$$i; \ + done + +clean:: + $(RM) -f $(PROGS) debugfs.8 \#* *.s *.o *.a *~ debug_cmds.c \ + extent_cmds.c ro_debug_cmds.c core rdebugfs debugfs.static + +mostlyclean: clean +distclean: clean + $(RM) -f debug_cmds.c .depend Makefile $(srcdir)/TAGS \ + $(srcdir)/Makefile.in.old + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# +debug_cmds.o: debug_cmds.c $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h +debugfs.o: $(srcdir)/debugfs.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \ + $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/version.h $(srcdir)/jfs_user.h \ + $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \ + $(top_srcdir)/lib/ext2fs/kernel-list.h +util.o: $(srcdir)/util.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/debugfs.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ + $(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h +ls.o: $(srcdir)/ls.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h +ncheck.o: $(srcdir)/ncheck.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h +icheck.o: $(srcdir)/icheck.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h +lsdel.o: $(srcdir)/lsdel.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h +dump.o: $(srcdir)/dump.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h +set_fields.o: $(srcdir)/set_fields.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \ + $(top_srcdir)/lib/e2p/e2p.h +logdump.o: $(srcdir)/logdump.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \ + $(srcdir)/jfs_user.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \ + $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h +htree.o: $(srcdir)/htree.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h \ + $(top_srcdir)/lib/e2p/e2p.h +unused.o: $(srcdir)/unused.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h +e2freefrag.o: $(srcdir)/../misc/e2freefrag.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ + $(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/../misc/e2freefrag.h +filefrag.o: $(srcdir)/filefrag.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h +extent_inode.o: $(srcdir)/extent_inode.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h +zap.o: $(srcdir)/zap.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h +quota.o: $(srcdir)/quota.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/debugfs.h $(top_srcdir)/lib/ss/ss.h \ + $(top_builddir)/lib/ss/ss_err.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(top_srcdir)/lib/quota/quotaio.h $(top_srcdir)/lib/quota/dqblk_v2.h \ + $(top_srcdir)/lib/quota/quotaio_tree.h $(top_srcdir)/lib/../e2fsck/dict.h
diff --git a/debugfs/debug_cmds.ct b/debugfs/debug_cmds.ct new file mode 100644 index 0000000..ed3728f --- /dev/null +++ b/debugfs/debug_cmds.ct
@@ -0,0 +1,204 @@ +# +# Copyright (C) 1993 Theodore Ts'o. This file may be redistributed +# under the terms of the GNU Public License. +# +command_table debug_cmds; + +request do_show_debugfs_params, "Show debugfs parameters", + show_debugfs_params, params; + +request do_open_filesys, "Open a filesystem", + open_filesys, open; + +request do_close_filesys, "Close the filesystem", + close_filesys, close; + +request do_freefrag, "Report free space fragmentation", + freefrag, e2freefrag; + +request do_features, "Set/print superblock features", + feature, features; + +request do_dirty_filesys, "Mark the filesystem as dirty", + dirty_filesys, dirty; + +request do_init_filesys, "Initialize a filesystem (DESTROYS DATA)", + init_filesys; + +request do_show_super_stats, "Show superblock statistics", + show_super_stats, stats; + +request do_ncheck, "Do inode->name translation", + ncheck; + +request do_icheck, "Do block->inode translation", + icheck; + +request do_chroot, "Change root directory", + change_root_directory, chroot; + +request do_change_working_dir, "Change working directory", + change_working_directory, cd; + +request do_list_dir, "List directory", + list_directory, ls; + +request do_stat, "Show inode information ", + show_inode_info, stat; + +request do_dump_extents, "Dump extents information ", + dump_extents, extents, ex; + +request do_blocks, "Dump blocks used by an inode ", + blocks; + +request do_filefrag, "Report fragmentation information for an inode", + filefrag; + +request do_link, "Create directory link", + link, ln; + +request do_unlink, "Delete a directory link", + unlink; + +request do_mkdir, "Create a directory", + mkdir; + +request do_rmdir, "Remove a directory", + rmdir; + +request do_rm, "Remove a file (unlink and kill_file, if appropriate)", + rm; + +request do_kill_file, "Deallocate an inode and its blocks", + kill_file; + +request do_clri, "Clear an inode's contents", + clri; + +request do_freei, "Clear an inode's in-use flag", + freei; + +request do_seti, "Set an inode's in-use flag", + seti; + +request do_testi, "Test an inode's in-use flag", + testi; + +request do_freeb, "Clear a block's in-use flag", + freeb; + +request do_setb, "Set a block's in-use flag", + setb; + +request do_testb, "Test a block's in-use flag", + testb; + +request do_modify_inode, "Modify an inode by structure", + modify_inode, mi; + +request do_find_free_block, "Find free block(s)", + find_free_block, ffb; + +request do_find_free_inode, "Find free inode(s)", + find_free_inode, ffi; + +request do_print_working_directory, "Print current working directory", + print_working_directory, pwd; + +request do_expand_dir, "Expand directory", + expand_dir, expand; + +request do_mknod, "Create a special file", + mknod; + +request do_lsdel, "List deleted inodes", + list_deleted_inodes, lsdel; + +request do_undel, "Undelete file", + undelete, undel; + +request do_write, "Copy a file from your native filesystem", + write; + +request do_dump, "Dump an inode out to a file", + dump_inode, dump; + +request do_cat, "Dump an inode out to stdout", + cat; + +request do_lcd, "Change the current directory on your native filesystem", + lcd; + +request do_rdump, "Recursively dump a directory to the native filesystem", + rdump; + +request do_set_super, "Set superblock value", + set_super_value, ssv; + +request do_set_inode, "Set inode field", + set_inode_field, sif; + +request do_set_block_group_descriptor, "Set block group descriptor field", + set_block_group, set_bg; + +request do_logdump, "Dump the contents of the journal", + logdump; + +request do_htree_dump, "Dump a hash-indexed directory", + htree_dump, htree; + +request do_dx_hash, "Calculate the directory hash of a filename", + dx_hash, hash; + +request do_dirsearch, "Search a directory for a particular filename", + dirsearch; + +request do_bmap, "Calculate the logical->physical block mapping for an inode", + bmap; + +request do_punch, "Punch (or truncate) blocks from an inode by deallocating them", + punch, truncate; + +request do_symlink, "Create a symbolic link", + symlink; + +request do_imap, "Calculate the location of an inode", + imap; + +request do_dump_unused, "Dump unused blocks", + dump_unused; + +request do_set_current_time, "Set current time to use when setting filesystem fields", + set_current_time; + +request do_supported_features, "Print features supported by this version of e2fsprogs", + supported_features; + +request do_dump_mmp, "Dump MMP information", + dump_mmp; + +request do_set_mmp_value, "Set MMP value", + set_mmp_value, smmp; + +request do_extent_open, "Open inode for extent manipulation", + extent_open, eo; + +request do_zap_block, "Zap block: fill with 0, pattern, flip bits etc.", + zap_block, zap; + +request do_block_dump, "Dump contents of a block", + block_dump, bdump, bd; + +request do_list_quota, "List quota", + list_quota, lq; + +request do_get_quota, "Get quota", + get_quota, gq; + +request do_idump, "Dump the inode structure in hex", + inode_dump, idump, id; + + +end; +
diff --git a/debugfs/debugfs.8.in b/debugfs/debugfs.8.in new file mode 100644 index 0000000..bae14db --- /dev/null +++ b/debugfs/debugfs.8.in
@@ -0,0 +1,723 @@ +.\" -*- nroff -*- +.\" Copyright 1993, 1994, 1995 by Theodore Ts'o. All Rights Reserved. +.\" This file may be copied under the terms of the GNU Public License. +.\" +.TH DEBUGFS 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@" +.SH NAME +debugfs \- ext2/ext3/ext4 file system debugger +.SH SYNOPSIS +.B debugfs +[ +.B \-DVwci +] +[ +.B \-b +blocksize +] +[ +.B \-s +superblock +] +[ +.B \-f +cmd_file +] +[ +.B \-R +request +] +[ +.B \-d +data_source_device +] +[ +device +] +.SH DESCRIPTION +The +.B debugfs +program is an interactive file system debugger. It can be used to +examine and change the state of an ext2, ext3, or ext4 file system. +.br +.I device +is the special file corresponding to the device containing the +file system (e.g /dev/hdXX). +.SH OPTIONS +.TP +.I \-w +Specifies that the file system should be opened in read-write mode. +Without this option, the file system is opened in read-only mode. +.TP +.I \-c +Specifies that the file system should be opened in catastrophic mode, in +which the inode and group bitmaps are not read initially. This can be +useful for filesystems with significant corruption, but because of this, +catastrophic mode forces the filesystem to be opened read-only. +.TP +.I \-i +Specifies that +.I device +represents an ext2 image file created by the +.B e2image +program. Since the ext2 image file only contains the superblock, block +group descriptor, block and inode allocation bitmaps, and +the inode table, many +.B debugfs +commands will not function properly. +.B Warning: +no safety checks are in place, and +.B debugfs +may fail in interesting ways if commands such as +.IR ls ", " dump ", " +etc. are tried without specifying the +.I data_source_device +using the +.I \-d +option. +.B debugfs +is a debugging tool. It has rough edges! +.TP +.I -d data_source_device +Used with the +.I \-i +option, specifies that +.I data_source_device +should be used when reading blocks not found in the ext2 image file. +This includes data, directory, and indirect blocks. +.TP +.I -b blocksize +Forces the use of the given block size for the file system, rather than +detecting the correct block size as normal. +.TP +.I -s superblock +Causes the file system superblock to be read from the given block +number, instead of using the primary superblock (located at an offset of +1024 bytes from the beginning of the filesystem). If you specify the +.I -s +option, you must also provide the blocksize of the filesystem via the +.I -b +option. +.TP +.I -f cmd_file +Causes +.B debugfs +to read in commands from +.IR cmd_file , +and execute them. When +.B debugfs +is finished executing those commands, it will exit. +.TP +.I -D +Causes +.B debugfs +to open the device using Direct I/O, bypassing the buffer cache. Note +that some Linux devices, notably device mapper as of this writing, do +not support Direct I/O. +.TP +.I -R request +Causes +.B debugfs +to execute the single command +.IR request , +and then exit. +.TP +.I -V +print the version number of +.B debugfs +and exit. +.SH SPECIFYING FILES +Many +.B debugfs +commands take a +.I filespec +as an argument to specify an inode (as opposed to a pathname) +in the filesystem which is currently opened by +.BR debugfs . +The +.I filespec +argument may be specified in two forms. The first form is an inode +number surrounded by angle brackets, e.g., +.IR <2> . +The second form is a pathname; if the pathname is prefixed by a forward slash +('/'), then it is interpreted relative to the root of the filesystem +which is currently opened by +.BR debugfs . +If not, the pathname is +interpreted relative to the current working directory as maintained by +.BR debugfs . +This may be modified by using the +.B debugfs +command +.IR cd . +.\" +.\" +.\" +.SH COMMANDS +This is a list of the commands which +.B debugfs +supports. +.TP +.BI blocks " filespace" +Print the blocks used by the inode +.I filespec +to stdout. +.TP +.BI bmap " filespec logical_block" +Print the physical block number corresponding to the logical block number +.I logical_block +in the inode +.IR filespec . +.TP +.BI block_dump " [-f filespec] block_num" +Dump the filesystem block given by +.I block_num +in hex and ASCII format to the console. If the +.I -f +option is specified, the block number is relative to the start of the given +.BR filespec . +.TP +.BI cat " filespec" +Dump the contents of the inode +.I filespec +to stdout. +.TP +.BI cd " filespec" +Change the current working directory to +.IR filespec . +.TP +.BI chroot " filespec" +Change the root directory to be the directory +.IR filespec . +.TP +.BI close " [-a]" +Close the currently open file system. If the +.I -a +option is specified, write out any changes to the superblock and block +group descriptors to all of the backup superblocks, not just to the +master superblock. +.TP +.BI clri " filespec" +Clear the contents of the inode +.IR filespec . +.TP +.BI dirsearch " filespec filename" +Search the directory +.I filespec +for +.IR filename . +.TP +.B dirty +Mark the filesystem as dirty, so that the superblocks will be written on exit. +.TP +.BI dump " [-p] filespec out_file" +Dump the contents of the inode +.I filespec +to the output file +.IR out_file . +If the +.I -p +option is given set the owner, group and permissions information on +.I out_file +to match +.IR filespec . +.TP +.B dump_mmp +Display the multiple-mount protection (mmp) field values. +.TP +.BI dx_hash " [-h hash_alg] [-s hash_seed] filename" +Calculate the directory hash of +.IR filename . +The hash algorithm specified with +.I -h +may be +.BR legacy , " half_md4" ", or " tea . +The hash seed specified with +.I -s +must be in UUID format. +.TP +.BI dump_extents " [-n] [-l] filespec" +Dump the the extent tree of the inode +.IR filespec . +The +.I -n +flag will cause +.B dump_extents +to only display the interior nodes in the extent tree. The +.I -l +flag will cause +.B dump_extents +to only display the leaf nodes in the extent tree. +.IP +(Please note that the length and range of blocks for the last extent in +an interior node is an estimate by the extents library functions, and is +not stored in filesystem data structures. Hence, the values displayed +may not necessarily by accurate and does not indicate a problem or +corruption in the file system.) +.TP +.BI expand_dir " filespec" +Expand the directory +.IR filespec . +.TP +.BI feature " [fs_feature] [-fs_feature] ..." +Set or clear various filesystem features in the superblock. After setting +or clearing any filesystem features that were requested, print the current +state of the filesystem feature set. +.TP +.BI filefrag " [-dvr] filespec" +Print the number of contiguous extents in +.IR filespec . +If +.I filespec +is a directory and the +.I -d +option is not specified, +.I filefrag +will print the number of contiguous extents for each file in +the directory. The +.I -v +option will cause +.I filefrag +print a tabular listing of the contiguous extents in the +file. The +.I -r +option will cause +.I filefrag +to do a recursive listing of the directory. +.TP +.BI find_free_block " [count [goal]]" +Find the first +.I count +free blocks, starting from +.I goal +and allocate it. Also available as +.BR ffb . +.TP +.BI find_free_inode " [dir [mode]]" +Find a free inode and allocate it. If present, +.I dir +specifies the inode number of the directory +which the inode is to be located. The second +optional argument +.I mode +specifies the permissions of the new inode. (If the directory bit is set +on the mode, the allocation routine will function differently.) Also +available as +.BR ffi . +.TP +.BI freeb " block [count]" +Mark the block number +.I block +as not allocated. +If the optional argument +.I count +is present, then +.I count +blocks starting at block number +.I block +will be marked as not allocated. +.TP +.BI freefrag " [-c chunk_kb]" +Report free space fragmentation on the currently open file system. +If the +.I \-c +option is specified then the filefrag command will print how many free +chunks of size +.I chunk_kb +can be found in the file system. The chunk size must be a power of two +and be larger than the file system block size. +.TP +.BI freei " filespec [num]" +Free the inode specified by +.IR filespec . +If +.I num +is specified, also clear num-1 inodes after the specified inode. +.TP +.B help +Print a list of commands understood by +.BR debugfs . +.TP +.BI htree_dump " filespec" +Dump the hash-indexed directory +.IR filespec , +showing its tree structure. +.TP +.BI icheck " block ..." +Print a listing of the inodes which use the one or more blocks specified +on the command line. +.TP +.BI inode_dump " filespec" +Print the contents of the inode data structure in hex and ASCII format. +.TP +.BI imap " filespec" +Print the location of the inode data structure (in the inode table) +of the inode +.IR filespec . +.TP +.BI init_filesys " device blocksize" +Create an ext2 file system on +.I device +with device size +.IR blocksize . +Note that this does not fully initialize all of the data structures; +to do this, use the +.BR mke2fs (8) +program. This is just a call to the low-level library, which sets up +the superblock and block descriptors. +.TP +.BI kill_file " filespec" +Deallocate the inode +.I filespec +and its blocks. Note that this does not remove any directory +entries (if any) to this inode. See the +.BR rm (1) +command if you wish to unlink a file. +.TP +.BI lcd " directory" +Change the current working directory of the +.B debugfs +process to +.I directory +on the native filesystem. +.TP +.BI ln " filespec dest_file" +Create a link named +.I dest_file +which is a hard link to +.IR filespec . +Note this does not adjust the inode reference counts. +.TP +.BI logdump " [-acs] [-b block] [-i filespec] [-f journal_file] [output_file]" +Dump the contents of the ext3 journal. By default, dump the journal inode as +specified in the superblock. However, this can be overridden with the +.I \-i +option, which dumps the journal from the internal inode given by +.IR filespec . +A regular file containing journal data can be specified using the +.I \-f +option. Finally, the +.I \-s +option utilizes the backup information in the superblock to locate the +journal. +.IP +The +.I \-a +option causes the +.B logdump +program to print the contents of all of the descriptor blocks. +The +.I \-b +option causes +.B logdump +to print all journal records that are refer to the specified block. +The +.I \-c +option will print out the contents of all of the data blocks selected by +the +.I \-a +and +.I \-b +options. +.TP +.BI ls " [-d] [-l] [-p] filespec" +Print a listing of the files in the directory +.IR filespec . +The +.I \-d +flag will list deleted entries in the directory. +The +.I \-l +flag will list files using a more verbose format. +The +.I \-p +flag will list the files in a format which is more easily parsable by +scripts, as well as making it more clear when there are spaces or other +non-printing characters at the end of filenames. +.TP +.BI list_deleted_inodes " [limit]" +List deleted inodes, optionally limited to those deleted within +.I limit +seconds ago. Also available as +.BR lsdel . +.IP +This command was useful for recovering from accidental file deletions +for ext2 file systems. Unfortunately, it is not useful for this purpose +if the files were deleted using ext3 or ext4, since the inode's +data blocks are no longer available after the inode is released. +.TP +.BI modify_inode " filespec" +Modify the contents of the inode structure in the inode +.IR filespec . +Also available as +.BR mi . +.TP +.BI mkdir " filespec" +Make a directory. +.TP +.BI mknod " filespec [p|[[c|b] major minor]]" +Create a special device file (a named pipe, character or block device). +If a character or block device is to be made, the +.I major +and +.I minor +device numbers must be specified. +.TP +.BI ncheck " [-c] inode_num ..." +Take the requested list of inode numbers, and print a listing of pathnames +to those inodes. The +.I -c +flag will enable checking the file type information in the directory +entry to make sure it matches the inode's type. +.TP +.BI open " [-weficD] [-b blocksize] [-s superblock] device" +Open a filesystem for editing. The +.I -f +flag forces the filesystem to be opened even if there are some unknown +or incompatible filesystem features which would normally +prevent the filesystem from being opened. The +.I -e +flag causes the filesystem to be opened in exclusive mode. The +.IR -b ", " -c ", " -i ", " -s ", " -w ", and " -D +options behave the same as the command-line options to +.BR debugfs . +.TP +.BI punch " filespec start_blk [end_blk]" +Delete the blocks in the inode ranging from +.I start_blk +to +.IR end_blk . +If +.I end_blk +is omitted then this command will function as a truncate command; that +is, all of the blocks starting at +.I start_blk +through to the end of the file will be deallocated. +.TP +.BI symlink " filespec target" +Make a symbolic link. +.TP +.B pwd +Print the current working directory. +.TP +.B quit +Quit +.B debugfs +.TP +.BI rdump " directory[...] destination" +Recursively dump +.IR directory , +or multiple +.IR directories , +and all its contents (including regular files, symbolic links, and other +directories) into the named +.IR destination , +which should be an existing directory on the native filesystem. +.TP +.BI rm " pathname" +Unlink +.IR pathname . +If this causes the inode pointed to by +.I pathname +to have no other references, deallocate the file. This command functions +as the unlink() system call. +.I +.TP +.BI rmdir " filespec" +Remove the directory +.IR filespec . +.TP +.BI setb " block [count]" +Mark the block number +.I block +as allocated. +If the optional argument +.I count +is present, then +.I count +blocks starting at block number +.I block +will be marked as allocated. +.TP +.BI set_block_group " bgnum field value" +Modify the block group descriptor specified by +.I bgnum +so that the block group descriptor field +.I field +has value +.IR value . +Also available as +.BR set_bg . +.TP +.BI seti " filespec [num]" +Mark inode +.I filespec +as in use in the inode bitmap. If +.I num +is specified, also set num-1 inodes after the specified inode. +.TP +.BI set_inode_field " filespec field value" +Modify the inode specified by +.I filespec +so that the inode field +.I field +has value +.I value. +The list of valid inode fields which can be set via this command +can be displayed by using the command: +.B set_inode_field -l +Also available as +.BR sif . +.TP +.BI set_mmp_value " field value" +Modify the multiple-mount protection (MMP) data so that the MMP field +.I field +has value +.I value. +The list of valid MMP fields which can be set via this command +can be displayed by using the command: +.B set_mmp_value -l +Also available as +.BR smmp . +.TP +.BI set_super_value " field value" +Set the superblock field +.I field +to +.I value. +The list of valid superblock fields which can be set via this command +can be displayed by using the command: +.B set_super_value -l +Also available as +.BR ssv . +.TP +.BI show_super_stats " [-h]" +List the contents of the super block and the block group descriptors. If the +.I -h +flag is given, only print out the superblock contents. Also available as +.BR stats . +.TP +.BI stat " filespec" +Display the contents of the inode structure of the inode +.IR filespec . +.TP +.BI testb " block [count]" +Test if the block number +.I block +is marked as allocated in the block bitmap. +If the optional argument +.I count +is present, then +.I count +blocks starting at block number +.I block +will be tested. +.TP +.BI testi " filespec" +Test if the inode +.I filespec +is marked as allocated in the inode bitmap. +.TP +.BI undel " <inode_number> [pathname]" +Undelete the specified inode number (which must be surrounded by angle +brackets) so that it and its blocks are marked in use, and optionally +link the recovered inode to the specified pathname. The +.B e2fsck +command should always be run after using the +.B undel +command to recover deleted files. +.IP +Note that if you are recovering a large number of deleted files, linking +the inode to a directory may require the directory to be expanded, which +could allocate a block that had been used by one of the +yet-to-be-undeleted files. So it is safer to undelete all of the +inodes without specifying a destination pathname, and then in a separate +pass, use the debugfs +.B link +command to link the inode to the destination pathname, or use +.B e2fsck +to check the filesystem and link all of the recovered inodes to the +lost+found directory. +.TP +.BI unlink " pathname" +Remove the link specified by +.I pathname +to an inode. Note this does not adjust the inode reference counts. +.TP +.BI write " source_file out_file" +Copy the contents of +.I source_file +into a newly-created file in the filesystem named +.IR out_file . +.TP +.BI zap_block " [-f filespec] [-o offset] [-l length] [-p pattern] block_num" +.TP +Overwrite the block specified by +.I block_num +with zero (NUL) bytes, or if +.I -p +is given use the byte specified by +.IR pattern . +If +.I -f +is given then +.I block_num +is relative to the start of the file given by +.IR filespec . +The +.I -o +and +.I -l +options limit the range of bytes to zap to the specified +.I offset +and +.I length +relative to the start of the block. +.TP +.BI zap_block " [-f filespec] [-b bit] block_num" +Bit-flip portions of the physical +.IR block_num . +If +.I -f +is given, then +.I block_num +is a logical block relative to the start of +.IR filespec . +.SH ENVIRONMENT VARIABLES +.TP +.B DEBUGFS_PAGER, PAGER +The +.B debugfs +program always pipes the output of the some commands through a +pager program. These commands include: +.IR show_super_stats " (" stats ), +.IR list_directory " (" ls ), +.IR show_inode_info " (" stat ), +.IR list_deleted_inodes " (" lsdel ), +and +.IR htree_dump . +The specific pager can explicitly specified by the +.B DEBUGFS_PAGER +environment variable, and if it is not set, by the +.B PAGER +environment variable. +.IP +Note that since a pager is always used, the +.BR less (1) +pager is not particularly appropriate, since it clears the screen before +displaying the output of the command and clears the output the screen +when the pager is exited. Many users prefer to use the +.BR less (1) +pager for most purposes, which is why the +.B DEBUGFS_PAGER +environment variable is available to override the more general +.B PAGER +environment variable. +.SH AUTHOR +.B debugfs +was written by Theodore Ts'o <tytso@mit.edu>. +.SH SEE ALSO +.BR dumpe2fs (8), +.BR tune2fs (8), +.BR e2fsck (8), +.BR mke2fs (8), +.BR ext4 (5)
diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c new file mode 100644 index 0000000..5423634 --- /dev/null +++ b/debugfs/debugfs.c
@@ -0,0 +1,2557 @@ +/* + * debugfs.c --- a program which allows you to attach an ext2fs + * filesystem and play with it. + * + * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + * + * Modifications by Robert Sanders <gt8134b@prism.gatech.edu> + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "debugfs.h" +#include "uuid/uuid.h" +#include "e2p/e2p.h" + +#include <ext2fs/ext2_ext_attr.h> + +#include "../version.h" +#include "jfs_user.h" + +#ifndef BUFSIZ +#define BUFSIZ 8192 +#endif + +/* 64KiB is the minimium blksize to best minimize system call overhead. */ +#ifndef IO_BUFSIZE +#define IO_BUFSIZE 64*1024 +#endif + +/* Block size for `st_blocks' */ +#ifndef S_BLKSIZE +#define S_BLKSIZE 512 +#endif + +ss_request_table *extra_cmds; +const char *debug_prog_name; +int sci_idx; + +ext2_filsys current_fs = NULL; +quota_ctx_t current_qctx; +ext2_ino_t root, cwd; + +static void open_filesystem(char *device, int open_flags, blk64_t superblock, + blk64_t blocksize, int catastrophic, + char *data_filename) +{ + int retval; + io_channel data_io = 0; + + if (superblock != 0 && blocksize == 0) { + com_err(device, 0, "if you specify the superblock, you must also specify the block size"); + current_fs = NULL; + return; + } + + if (data_filename) { + if ((open_flags & EXT2_FLAG_IMAGE_FILE) == 0) { + com_err(device, 0, + "The -d option is only valid when reading an e2image file"); + current_fs = NULL; + return; + } + retval = unix_io_manager->open(data_filename, 0, &data_io); + if (retval) { + com_err(data_filename, 0, "while opening data source"); + current_fs = NULL; + return; + } + } + + if (catastrophic && (open_flags & EXT2_FLAG_RW)) { + com_err(device, 0, + "opening read-only because of catastrophic mode"); + open_flags &= ~EXT2_FLAG_RW; + } + if (catastrophic) + open_flags |= EXT2_FLAG_SKIP_MMP; + + retval = ext2fs_open(device, open_flags, superblock, blocksize, + unix_io_manager, ¤t_fs); + if (retval) { + com_err(device, retval, "while opening filesystem"); + current_fs = NULL; + return; + } + current_fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE; + + if (catastrophic) + com_err(device, 0, "catastrophic mode - not reading inode or group bitmaps"); + else { + retval = ext2fs_read_inode_bitmap(current_fs); + if (retval) { + com_err(device, retval, "while reading inode bitmap"); + goto errout; + } + retval = ext2fs_read_block_bitmap(current_fs); + if (retval) { + com_err(device, retval, "while reading block bitmap"); + goto errout; + } + } + + if (data_io) { + retval = ext2fs_set_data_io(current_fs, data_io); + if (retval) { + com_err(device, retval, + "while setting data source"); + goto errout; + } + } + + root = cwd = EXT2_ROOT_INO; + return; + +errout: + retval = ext2fs_close_free(¤t_fs); + if (retval) + com_err(device, retval, "while trying to close filesystem"); +} + +void do_open_filesys(int argc, char **argv) +{ + int c, err; + int catastrophic = 0; + blk64_t superblock = 0; + blk64_t blocksize = 0; + int open_flags = EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS; + char *data_filename = 0; + + reset_getopt(); + while ((c = getopt (argc, argv, "iwfecb:s:d:D")) != EOF) { + switch (c) { + case 'i': + open_flags |= EXT2_FLAG_IMAGE_FILE; + break; + case 'w': +#ifdef READ_ONLY + goto print_usage; +#else + open_flags |= EXT2_FLAG_RW; +#endif /* READ_ONLY */ + break; + case 'f': + open_flags |= EXT2_FLAG_FORCE; + break; + case 'e': + open_flags |= EXT2_FLAG_EXCLUSIVE; + break; + case 'c': + catastrophic = 1; + break; + case 'd': + data_filename = optarg; + break; + case 'D': + open_flags |= EXT2_FLAG_DIRECT_IO; + break; + case 'b': + blocksize = parse_ulong(optarg, argv[0], + "block size", &err); + if (err) + return; + break; + case 's': + err = strtoblk(argv[0], optarg, + "superblock block number", &superblock); + if (err) + return; + break; + default: + goto print_usage; + } + } + if (optind != argc-1) { + goto print_usage; + } + if (check_fs_not_open(argv[0])) + return; + open_filesystem(argv[optind], open_flags, + superblock, blocksize, catastrophic, + data_filename); + return; + +print_usage: + fprintf(stderr, "%s: Usage: open [-s superblock] [-b blocksize] " + "[-d image_filename] [-c] [-i] [-f] [-e] [-D] " +#ifndef READ_ONLY + "[-w] " +#endif + "<device>\n", argv[0]); +} + +void do_lcd(int argc, char **argv) +{ + if (argc != 2) { + com_err(argv[0], 0, "Usage: %s %s", argv[0], "<native dir>"); + return; + } + + if (chdir(argv[1]) == -1) { + com_err(argv[0], errno, + "while trying to change native directory to %s", + argv[1]); + return; + } +} + +static void close_filesystem(NOARGS) +{ + int retval; + + if (current_fs->flags & EXT2_FLAG_IB_DIRTY) { + retval = ext2fs_write_inode_bitmap(current_fs); + if (retval) + com_err("ext2fs_write_inode_bitmap", retval, 0); + } + if (current_fs->flags & EXT2_FLAG_BB_DIRTY) { + retval = ext2fs_write_block_bitmap(current_fs); + if (retval) + com_err("ext2fs_write_block_bitmap", retval, 0); + } + if (current_qctx) + quota_release_context(¤t_qctx); + retval = ext2fs_close_free(¤t_fs); + if (retval) + com_err("ext2fs_close", retval, 0); + return; +} + +void do_close_filesys(int argc, char **argv) +{ + int c; + + if (check_fs_open(argv[0])) + return; + + reset_getopt(); + while ((c = getopt (argc, argv, "a")) != EOF) { + switch (c) { + case 'a': + current_fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; + break; + default: + goto print_usage; + } + } + + if (argc > optind) { + print_usage: + com_err(0, 0, "Usage: close_filesys [-a]"); + return; + } + + close_filesystem(); +} + +#ifndef READ_ONLY +void do_init_filesys(int argc, char **argv) +{ + struct ext2_super_block param; + errcode_t retval; + int err; + blk64_t blocks; + + if (common_args_process(argc, argv, 3, 3, "initialize", + "<device> <blocks>", CHECK_FS_NOTOPEN)) + return; + + memset(¶m, 0, sizeof(struct ext2_super_block)); + err = strtoblk(argv[0], argv[2], "blocks count", &blocks); + if (err) + return; + ext2fs_blocks_count_set(¶m, blocks); + retval = ext2fs_initialize(argv[1], 0, ¶m, + unix_io_manager, ¤t_fs); + if (retval) { + com_err(argv[1], retval, "while initializing filesystem"); + current_fs = NULL; + return; + } + root = cwd = EXT2_ROOT_INO; + return; +} + +static void print_features(struct ext2_super_block * s, FILE *f) +{ + int i, j, printed=0; + __u32 *mask = &s->s_feature_compat, m; + + fputs("Filesystem features:", f); + for (i=0; i <3; i++,mask++) { + for (j=0,m=1; j < 32; j++, m<<=1) { + if (*mask & m) { + fprintf(f, " %s", e2p_feature2string(i, m)); + printed++; + } + } + } + if (printed == 0) + fputs("(none)", f); + fputs("\n", f); +} +#endif /* READ_ONLY */ + +static void print_bg_opts(ext2_filsys fs, dgrp_t group, int mask, + const char *str, int *first, FILE *f) +{ + if (ext2fs_bg_flags_test(fs, group, mask)) { + if (*first) { + fputs(" [", f); + *first = 0; + } else + fputs(", ", f); + fputs(str, f); + } +} + +void do_show_super_stats(int argc, char *argv[]) +{ + const char *units ="block"; + dgrp_t i; + FILE *out; + int c, header_only = 0; + int numdirs = 0, first, gdt_csum; + + reset_getopt(); + while ((c = getopt (argc, argv, "h")) != EOF) { + switch (c) { + case 'h': + header_only++; + break; + default: + goto print_usage; + } + } + if (optind != argc) { + goto print_usage; + } + if (check_fs_open(argv[0])) + return; + out = open_pager(); + + if (EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super, + EXT4_FEATURE_RO_COMPAT_BIGALLOC)) + units = "cluster"; + + list_super2(current_fs->super, out); + for (i=0; i < current_fs->group_desc_count; i++) + numdirs += ext2fs_bg_used_dirs_count(current_fs, i); + fprintf(out, "Directories: %d\n", numdirs); + + if (header_only) { + close_pager(out); + return; + } + + gdt_csum = EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super, + EXT4_FEATURE_RO_COMPAT_GDT_CSUM); + for (i = 0; i < current_fs->group_desc_count; i++) { + fprintf(out, " Group %2d: block bitmap at %llu, " + "inode bitmap at %llu, " + "inode table at %llu\n" + " %u free %s%s, " + "%u free %s, " + "%u used %s%s", + i, ext2fs_block_bitmap_loc(current_fs, i), + ext2fs_inode_bitmap_loc(current_fs, i), + ext2fs_inode_table_loc(current_fs, i), + ext2fs_bg_free_blocks_count(current_fs, i), units, + ext2fs_bg_free_blocks_count(current_fs, i) != 1 ? + "s" : "", + ext2fs_bg_free_inodes_count(current_fs, i), + ext2fs_bg_free_inodes_count(current_fs, i) != 1 ? + "inodes" : "inode", + ext2fs_bg_used_dirs_count(current_fs, i), + ext2fs_bg_used_dirs_count(current_fs, i) != 1 ? "directories" + : "directory", gdt_csum ? ", " : "\n"); + if (gdt_csum) + fprintf(out, "%u unused %s\n", + ext2fs_bg_itable_unused(current_fs, i), + ext2fs_bg_itable_unused(current_fs, i) != 1 ? + "inodes" : "inode"); + first = 1; + print_bg_opts(current_fs, i, EXT2_BG_INODE_UNINIT, "Inode not init", + &first, out); + print_bg_opts(current_fs, i, EXT2_BG_BLOCK_UNINIT, "Block not init", + &first, out); + if (gdt_csum) { + fprintf(out, "%sChecksum 0x%04x", + first ? " [":", ", ext2fs_bg_checksum(current_fs, i)); + first = 0; + } + if (!first) + fputs("]\n", out); + } + close_pager(out); + return; +print_usage: + fprintf(stderr, "%s: Usage: show_super [-h]\n", argv[0]); +} + +#ifndef READ_ONLY +void do_dirty_filesys(int argc EXT2FS_ATTR((unused)), + char **argv EXT2FS_ATTR((unused))) +{ + if (check_fs_open(argv[0])) + return; + if (check_fs_read_write(argv[0])) + return; + + if (argv[1] && !strcmp(argv[1], "-clean")) + current_fs->super->s_state |= EXT2_VALID_FS; + else + current_fs->super->s_state &= ~EXT2_VALID_FS; + ext2fs_mark_super_dirty(current_fs); +} +#endif /* READ_ONLY */ + +struct list_blocks_struct { + FILE *f; + e2_blkcnt_t total; + blk64_t first_block, last_block; + e2_blkcnt_t first_bcnt, last_bcnt; + e2_blkcnt_t first; +}; + +static void finish_range(struct list_blocks_struct *lb) +{ + if (lb->first_block == 0) + return; + if (lb->first) + lb->first = 0; + else + fprintf(lb->f, ", "); + if (lb->first_block == lb->last_block) + fprintf(lb->f, "(%lld):%llu", + (long long)lb->first_bcnt, lb->first_block); + else + fprintf(lb->f, "(%lld-%lld):%llu-%llu", + (long long)lb->first_bcnt, (long long)lb->last_bcnt, + lb->first_block, lb->last_block); + lb->first_block = 0; +} + +static int list_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)), + blk64_t *blocknr, e2_blkcnt_t blockcnt, + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *private) +{ + struct list_blocks_struct *lb = (struct list_blocks_struct *) private; + + lb->total++; + if (blockcnt >= 0) { + /* + * See if we can add on to the existing range (if it exists) + */ + if (lb->first_block && + (lb->last_block+1 == *blocknr) && + (lb->last_bcnt+1 == blockcnt)) { + lb->last_block = *blocknr; + lb->last_bcnt = blockcnt; + return 0; + } + /* + * Start a new range. + */ + finish_range(lb); + lb->first_block = lb->last_block = *blocknr; + lb->first_bcnt = lb->last_bcnt = blockcnt; + return 0; + } + /* + * Not a normal block. Always force a new range. + */ + finish_range(lb); + if (lb->first) + lb->first = 0; + else + fprintf(lb->f, ", "); + if (blockcnt == -1) + fprintf(lb->f, "(IND):%llu", (unsigned long long) *blocknr); + else if (blockcnt == -2) + fprintf(lb->f, "(DIND):%llu", (unsigned long long) *blocknr); + else if (blockcnt == -3) + fprintf(lb->f, "(TIND):%llu", (unsigned long long) *blocknr); + return 0; +} + +static void dump_xattr_string(FILE *out, const char *str, int len) +{ + int printable = 0; + int i; + + /* check: is string "printable enough?" */ + for (i = 0; i < len; i++) + if (isprint(str[i])) + printable++; + + if (printable <= len*7/8) + printable = 0; + + for (i = 0; i < len; i++) + if (printable) + fprintf(out, isprint(str[i]) ? "%c" : "\\%03o", + (unsigned char)str[i]); + else + fprintf(out, "%02x ", (unsigned char)str[i]); +} + +static void internal_dump_inode_extra(FILE *out, + const char *prefix EXT2FS_ATTR((unused)), + ext2_ino_t inode_num EXT2FS_ATTR((unused)), + struct ext2_inode_large *inode) +{ + struct ext2_ext_attr_entry *entry; + __u32 *magic; + char *start, *end; + + fprintf(out, "Size of extra inode fields: %u\n", inode->i_extra_isize); + if (inode->i_extra_isize > EXT2_INODE_SIZE(current_fs->super) - + EXT2_GOOD_OLD_INODE_SIZE) { + fprintf(stderr, "invalid inode->i_extra_isize (%u)\n", + inode->i_extra_isize); + return; + } + magic = (__u32 *)((char *)inode + EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize); + if (*magic == EXT2_EXT_ATTR_MAGIC) { + fprintf(out, "Extended attributes stored in inode body: \n"); + end = (char *) inode + EXT2_INODE_SIZE(current_fs->super); + start = (char *) magic + sizeof(__u32); + entry = (struct ext2_ext_attr_entry *) start; + while (!EXT2_EXT_IS_LAST_ENTRY(entry)) { + struct ext2_ext_attr_entry *next = + EXT2_EXT_ATTR_NEXT(entry); + char *name = EXT2_EXT_ATTR_NAME(entry); + char *value = start + entry->e_value_offs; + + if (name + entry->e_name_len >= end || + value + entry->e_value_size >= end || + (char *) next >= end) { + fprintf(out, "invalid EA entry in inode\n"); + return; + } + fprintf(out, " "); + dump_xattr_string(out, name, entry->e_name_len); + fprintf(out, " = \""); + dump_xattr_string(out, value, entry->e_value_size); + fprintf(out, "\" (%u)\n", entry->e_value_size); + entry = next; + } + } +} + +static void dump_blocks(FILE *f, const char *prefix, ext2_ino_t inode) +{ + struct list_blocks_struct lb; + + fprintf(f, "%sBLOCKS:\n%s", prefix, prefix); + lb.total = 0; + lb.first_block = 0; + lb.f = f; + lb.first = 1; + ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL, + list_blocks_proc, (void *)&lb); + finish_range(&lb); + if (lb.total) + fprintf(f, "\n%sTOTAL: %lld\n", prefix, (long long)lb.total); + fprintf(f,"\n"); +} + +static int int_log10(unsigned long long arg) +{ + int l = 0; + + arg = arg / 10; + while (arg) { + l++; + arg = arg / 10; + } + return l; +} + +#define DUMP_LEAF_EXTENTS 0x01 +#define DUMP_NODE_EXTENTS 0x02 +#define DUMP_EXTENT_TABLE 0x04 + +static void dump_extents(FILE *f, const char *prefix, ext2_ino_t ino, + int flags, int logical_width, int physical_width) +{ + ext2_extent_handle_t handle; + struct ext2fs_extent extent; + struct ext2_extent_info info; + int op = EXT2_EXTENT_ROOT; + unsigned int printed = 0; + errcode_t errcode; + + errcode = ext2fs_extent_open(current_fs, ino, &handle); + if (errcode) + return; + + if (flags & DUMP_EXTENT_TABLE) + fprintf(f, "Level Entries %*s %*s Length Flags\n", + (logical_width*2)+3, "Logical", + (physical_width*2)+3, "Physical"); + else + fprintf(f, "%sEXTENTS:\n%s", prefix, prefix); + + while (1) { + errcode = ext2fs_extent_get(handle, op, &extent); + + if (errcode) + break; + + op = EXT2_EXTENT_NEXT; + + if (extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) + continue; + + if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) { + if ((flags & DUMP_LEAF_EXTENTS) == 0) + continue; + } else { + if ((flags & DUMP_NODE_EXTENTS) == 0) + continue; + } + + errcode = ext2fs_extent_get_info(handle, &info); + if (errcode) + continue; + + if (!(extent.e_flags & EXT2_EXTENT_FLAGS_LEAF)) { + if (extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) + continue; + + if (flags & DUMP_EXTENT_TABLE) { + fprintf(f, "%2d/%2d %3d/%3d %*llu - %*llu " + "%*llu%*s %6u\n", + info.curr_level, info.max_depth, + info.curr_entry, info.num_entries, + logical_width, + extent.e_lblk, + logical_width, + extent.e_lblk + (extent.e_len - 1), + physical_width, + extent.e_pblk, + physical_width+3, "", extent.e_len); + continue; + } + + fprintf(f, "%s(ETB%d):%lld", + printed ? ", " : "", info.curr_level, + extent.e_pblk); + printed = 1; + continue; + } + + if (flags & DUMP_EXTENT_TABLE) { + fprintf(f, "%2d/%2d %3d/%3d %*llu - %*llu " + "%*llu - %*llu %6u %s\n", + info.curr_level, info.max_depth, + info.curr_entry, info.num_entries, + logical_width, + extent.e_lblk, + logical_width, + extent.e_lblk + (extent.e_len - 1), + physical_width, + extent.e_pblk, + physical_width, + extent.e_pblk + (extent.e_len - 1), + extent.e_len, + extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ? + "Uninit" : ""); + continue; + } + + if (extent.e_len == 0) + continue; + else if (extent.e_len == 1) + fprintf(f, + "%s(%lld%s):%lld", + printed ? ", " : "", + extent.e_lblk, + extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ? + "[u]" : "", + extent.e_pblk); + else + fprintf(f, + "%s(%lld-%lld%s):%lld-%lld", + printed ? ", " : "", + extent.e_lblk, + extent.e_lblk + (extent.e_len - 1), + extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT ? + "[u]" : "", + extent.e_pblk, + extent.e_pblk + (extent.e_len - 1)); + printed = 1; + } + if (printed) + fprintf(f, "\n"); +} + +void internal_dump_inode(FILE *out, const char *prefix, + ext2_ino_t inode_num, struct ext2_inode *inode, + int do_dump_blocks) +{ + const char *i_type; + char frag, fsize; + int os = current_fs->super->s_creator_os; + struct ext2_inode_large *large_inode; + int is_large_inode = 0; + + if (EXT2_INODE_SIZE(current_fs->super) > EXT2_GOOD_OLD_INODE_SIZE) + is_large_inode = 1; + large_inode = (struct ext2_inode_large *) inode; + + if (LINUX_S_ISDIR(inode->i_mode)) i_type = "directory"; + else if (LINUX_S_ISREG(inode->i_mode)) i_type = "regular"; + else if (LINUX_S_ISLNK(inode->i_mode)) i_type = "symlink"; + else if (LINUX_S_ISBLK(inode->i_mode)) i_type = "block special"; + else if (LINUX_S_ISCHR(inode->i_mode)) i_type = "character special"; + else if (LINUX_S_ISFIFO(inode->i_mode)) i_type = "FIFO"; + else if (LINUX_S_ISSOCK(inode->i_mode)) i_type = "socket"; + else i_type = "bad type"; + fprintf(out, "%sInode: %u Type: %s ", prefix, inode_num, i_type); + fprintf(out, "%sMode: %04o Flags: 0x%x\n", + prefix, inode->i_mode & 0777, inode->i_flags); + if (is_large_inode && large_inode->i_extra_isize >= 24) { + fprintf(out, "%sGeneration: %u Version: 0x%08x:%08x\n", + prefix, inode->i_generation, large_inode->i_version_hi, + inode->osd1.linux1.l_i_version); + } else { + fprintf(out, "%sGeneration: %u Version: 0x%08x\n", prefix, + inode->i_generation, inode->osd1.linux1.l_i_version); + } + fprintf(out, "%sUser: %5d Group: %5d Size: ", + prefix, inode_uid(*inode), inode_gid(*inode)); + if (LINUX_S_ISREG(inode->i_mode)) + fprintf(out, "%llu\n", EXT2_I_SIZE(inode)); + else + fprintf(out, "%d\n", inode->i_size); + if (os == EXT2_OS_HURD) + fprintf(out, + "%sFile ACL: %d Directory ACL: %d Translator: %d\n", + prefix, + inode->i_file_acl, LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0, + inode->osd1.hurd1.h_i_translator); + else + fprintf(out, "%sFile ACL: %llu Directory ACL: %d\n", + prefix, + inode->i_file_acl | ((long long) + (inode->osd2.linux2.l_i_file_acl_high) << 32), + LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0); + if (os == EXT2_OS_LINUX) + fprintf(out, "%sLinks: %d Blockcount: %llu\n", + prefix, inode->i_links_count, + (((unsigned long long) + inode->osd2.linux2.l_i_blocks_hi << 32)) + + inode->i_blocks); + else + fprintf(out, "%sLinks: %d Blockcount: %u\n", + prefix, inode->i_links_count, inode->i_blocks); + switch (os) { + case EXT2_OS_HURD: + frag = inode->osd2.hurd2.h_i_frag; + fsize = inode->osd2.hurd2.h_i_fsize; + break; + default: + frag = fsize = 0; + } + fprintf(out, "%sFragment: Address: %d Number: %d Size: %d\n", + prefix, inode->i_faddr, frag, fsize); + if (is_large_inode && large_inode->i_extra_isize >= 24) { + fprintf(out, "%s ctime: 0x%08x:%08x -- %s", prefix, + inode->i_ctime, large_inode->i_ctime_extra, + time_to_string(inode->i_ctime)); + fprintf(out, "%s atime: 0x%08x:%08x -- %s", prefix, + inode->i_atime, large_inode->i_atime_extra, + time_to_string(inode->i_atime)); + fprintf(out, "%s mtime: 0x%08x:%08x -- %s", prefix, + inode->i_mtime, large_inode->i_mtime_extra, + time_to_string(inode->i_mtime)); + fprintf(out, "%scrtime: 0x%08x:%08x -- %s", prefix, + large_inode->i_crtime, large_inode->i_crtime_extra, + time_to_string(large_inode->i_crtime)); + } else { + fprintf(out, "%sctime: 0x%08x -- %s", prefix, inode->i_ctime, + time_to_string(inode->i_ctime)); + fprintf(out, "%satime: 0x%08x -- %s", prefix, inode->i_atime, + time_to_string(inode->i_atime)); + fprintf(out, "%smtime: 0x%08x -- %s", prefix, inode->i_mtime, + time_to_string(inode->i_mtime)); + } + if (inode->i_dtime) + fprintf(out, "%sdtime: 0x%08x -- %s", prefix, inode->i_dtime, + time_to_string(inode->i_dtime)); + if (EXT2_INODE_SIZE(current_fs->super) > EXT2_GOOD_OLD_INODE_SIZE) + internal_dump_inode_extra(out, prefix, inode_num, + (struct ext2_inode_large *) inode); + if (LINUX_S_ISLNK(inode->i_mode) && ext2fs_inode_data_blocks(current_fs,inode) == 0) + fprintf(out, "%sFast_link_dest: %.*s\n", prefix, + (int) inode->i_size, (char *)inode->i_block); + else if (LINUX_S_ISBLK(inode->i_mode) || LINUX_S_ISCHR(inode->i_mode)) { + int major, minor; + const char *devnote; + + if (inode->i_block[0]) { + major = (inode->i_block[0] >> 8) & 255; + minor = inode->i_block[0] & 255; + devnote = ""; + } else { + major = (inode->i_block[1] & 0xfff00) >> 8; + minor = ((inode->i_block[1] & 0xff) | + ((inode->i_block[1] >> 12) & 0xfff00)); + devnote = "(New-style) "; + } + fprintf(out, "%sDevice major/minor number: %02d:%02d (hex %02x:%02x)\n", + devnote, major, minor, major, minor); + } else if (do_dump_blocks) { + if (inode->i_flags & EXT4_EXTENTS_FL) + dump_extents(out, prefix, inode_num, + DUMP_LEAF_EXTENTS|DUMP_NODE_EXTENTS, 0, 0); + else + dump_blocks(out, prefix, inode_num); + } +} + +static void dump_inode(ext2_ino_t inode_num, struct ext2_inode *inode) +{ + FILE *out; + + out = open_pager(); + internal_dump_inode(out, "", inode_num, inode, 1); + close_pager(out); +} + +void do_stat(int argc, char *argv[]) +{ + ext2_ino_t inode; + struct ext2_inode * inode_buf; + + if (check_fs_open(argv[0])) + return; + + inode_buf = (struct ext2_inode *) + malloc(EXT2_INODE_SIZE(current_fs->super)); + if (!inode_buf) { + fprintf(stderr, "do_stat: can't allocate buffer\n"); + return; + } + + if (common_inode_args_process(argc, argv, &inode, 0)) { + free(inode_buf); + return; + } + + if (debugfs_read_inode_full(inode, inode_buf, argv[0], + EXT2_INODE_SIZE(current_fs->super))) { + free(inode_buf); + return; + } + + dump_inode(inode, inode_buf); + free(inode_buf); + return; +} + +void do_dump_extents(int argc, char **argv) +{ + struct ext2_inode inode; + ext2_ino_t ino; + FILE *out; + int c, flags = 0; + int logical_width; + int physical_width; + + reset_getopt(); + while ((c = getopt(argc, argv, "nl")) != EOF) { + switch (c) { + case 'n': + flags |= DUMP_NODE_EXTENTS; + break; + case 'l': + flags |= DUMP_LEAF_EXTENTS; + break; + } + } + + if (argc != optind + 1) { + com_err(0, 0, "Usage: dump_extents [-n] [-l] file"); + return; + } + + if (flags == 0) + flags = DUMP_NODE_EXTENTS | DUMP_LEAF_EXTENTS; + flags |= DUMP_EXTENT_TABLE; + + if (check_fs_open(argv[0])) + return; + + ino = string_to_inode(argv[optind]); + if (ino == 0) + return; + + if (debugfs_read_inode(ino, &inode, argv[0])) + return; + + if ((inode.i_flags & EXT4_EXTENTS_FL) == 0) { + fprintf(stderr, "%s: does not uses extent block maps\n", + argv[optind]); + return; + } + + logical_width = int_log10((EXT2_I_SIZE(&inode)+current_fs->blocksize-1)/ + current_fs->blocksize) + 1; + if (logical_width < 5) + logical_width = 5; + physical_width = int_log10(ext2fs_blocks_count(current_fs->super)) + 1; + if (physical_width < 5) + physical_width = 5; + + out = open_pager(); + dump_extents(out, "", ino, flags, logical_width, physical_width); + close_pager(out); + return; +} + +static int print_blocks_proc(ext2_filsys fs EXT2FS_ATTR((unused)), + blk64_t *blocknr, + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *private EXT2FS_ATTR((unused))) +{ + printf("%llu ", *blocknr); + return 0; +} + +void do_blocks(int argc, char *argv[]) +{ + ext2_ino_t inode; + + if (check_fs_open(argv[0])) + return; + + if (common_inode_args_process(argc, argv, &inode, 0)) { + return; + } + + ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL, + print_blocks_proc, NULL); + fputc('\n', stdout); + return; +} + +void do_chroot(int argc, char *argv[]) +{ + ext2_ino_t inode; + int retval; + + if (common_inode_args_process(argc, argv, &inode, 0)) + return; + + retval = ext2fs_check_directory(current_fs, inode); + if (retval) { + com_err(argv[1], retval, 0); + return; + } + root = inode; +} + +#ifndef READ_ONLY +void do_clri(int argc, char *argv[]) +{ + ext2_ino_t inode; + struct ext2_inode inode_buf; + + if (common_inode_args_process(argc, argv, &inode, CHECK_FS_RW)) + return; + + if (debugfs_read_inode(inode, &inode_buf, argv[0])) + return; + memset(&inode_buf, 0, sizeof(inode_buf)); + if (debugfs_write_inode(inode, &inode_buf, argv[0])) + return; +} + +void do_freei(int argc, char *argv[]) +{ + unsigned int len = 1; + int err = 0; + ext2_ino_t inode; + + if (common_args_process(argc, argv, 2, 3, argv[0], "<file> [num]", + CHECK_FS_RW | CHECK_FS_BITMAPS)) + return; + if (check_fs_read_write(argv[0])) + return; + + inode = string_to_inode(argv[1]); + if (!inode) + return; + + if (argc == 3) { + len = parse_ulong(argv[2], argv[0], "length", &err); + if (err) + return; + } + + if (len == 1 && + !ext2fs_test_inode_bitmap2(current_fs->inode_map,inode)) + com_err(argv[0], 0, "Warning: inode already clear"); + while (len-- > 0) + ext2fs_unmark_inode_bitmap2(current_fs->inode_map, inode++); + ext2fs_mark_ib_dirty(current_fs); +} + +void do_seti(int argc, char *argv[]) +{ + unsigned int len = 1; + int err = 0; + ext2_ino_t inode; + + if (common_args_process(argc, argv, 2, 3, argv[0], "<file> [num]", + CHECK_FS_RW | CHECK_FS_BITMAPS)) + return; + if (check_fs_read_write(argv[0])) + return; + + inode = string_to_inode(argv[1]); + if (!inode) + return; + + if (argc == 3) { + len = parse_ulong(argv[2], argv[0], "length", &err); + if (err) + return; + } + + if ((len == 1) && + ext2fs_test_inode_bitmap2(current_fs->inode_map,inode)) + com_err(argv[0], 0, "Warning: inode already set"); + while (len-- > 0) + ext2fs_mark_inode_bitmap2(current_fs->inode_map, inode++); + ext2fs_mark_ib_dirty(current_fs); +} +#endif /* READ_ONLY */ + +void do_testi(int argc, char *argv[]) +{ + ext2_ino_t inode; + + if (common_inode_args_process(argc, argv, &inode, CHECK_FS_BITMAPS)) + return; + + if (ext2fs_test_inode_bitmap2(current_fs->inode_map,inode)) + printf("Inode %u is marked in use\n", inode); + else + printf("Inode %u is not in use\n", inode); +} + +#ifndef READ_ONLY +void do_freeb(int argc, char *argv[]) +{ + blk64_t block; + blk64_t count = 1; + + if (common_block_args_process(argc, argv, &block, &count)) + return; + if (check_fs_read_write(argv[0])) + return; + while (count-- > 0) { + if (!ext2fs_test_block_bitmap2(current_fs->block_map,block)) + com_err(argv[0], 0, "Warning: block %llu already clear", + block); + ext2fs_unmark_block_bitmap2(current_fs->block_map,block); + block++; + } + ext2fs_mark_bb_dirty(current_fs); +} + +void do_setb(int argc, char *argv[]) +{ + blk64_t block; + blk64_t count = 1; + + if (common_block_args_process(argc, argv, &block, &count)) + return; + if (check_fs_read_write(argv[0])) + return; + while (count-- > 0) { + if (ext2fs_test_block_bitmap2(current_fs->block_map,block)) + com_err(argv[0], 0, "Warning: block %llu already set", + block); + ext2fs_mark_block_bitmap2(current_fs->block_map,block); + block++; + } + ext2fs_mark_bb_dirty(current_fs); +} +#endif /* READ_ONLY */ + +void do_testb(int argc, char *argv[]) +{ + blk64_t block; + blk64_t count = 1; + + if (common_block_args_process(argc, argv, &block, &count)) + return; + while (count-- > 0) { + if (ext2fs_test_block_bitmap2(current_fs->block_map,block)) + printf("Block %llu marked in use\n", block); + else + printf("Block %llu not in use\n", block); + block++; + } +} + +#ifndef READ_ONLY +static void modify_u8(char *com, const char *prompt, + const char *format, __u8 *val) +{ + char buf[200]; + unsigned long v; + char *tmp; + + sprintf(buf, format, *val); + printf("%30s [%s] ", prompt, buf); + if (!fgets(buf, sizeof(buf), stdin)) + return; + if (buf[strlen (buf) - 1] == '\n') + buf[strlen (buf) - 1] = '\0'; + if (!buf[0]) + return; + v = strtoul(buf, &tmp, 0); + if (*tmp) + com_err(com, 0, "Bad value - %s", buf); + else + *val = v; +} + +static void modify_u16(char *com, const char *prompt, + const char *format, __u16 *val) +{ + char buf[200]; + unsigned long v; + char *tmp; + + sprintf(buf, format, *val); + printf("%30s [%s] ", prompt, buf); + if (!fgets(buf, sizeof(buf), stdin)) + return; + if (buf[strlen (buf) - 1] == '\n') + buf[strlen (buf) - 1] = '\0'; + if (!buf[0]) + return; + v = strtoul(buf, &tmp, 0); + if (*tmp) + com_err(com, 0, "Bad value - %s", buf); + else + *val = v; +} + +static void modify_u32(char *com, const char *prompt, + const char *format, __u32 *val) +{ + char buf[200]; + unsigned long v; + char *tmp; + + sprintf(buf, format, *val); + printf("%30s [%s] ", prompt, buf); + if (!fgets(buf, sizeof(buf), stdin)) + return; + if (buf[strlen (buf) - 1] == '\n') + buf[strlen (buf) - 1] = '\0'; + if (!buf[0]) + return; + v = strtoul(buf, &tmp, 0); + if (*tmp) + com_err(com, 0, "Bad value - %s", buf); + else + *val = v; +} + + +void do_modify_inode(int argc, char *argv[]) +{ + struct ext2_inode inode; + ext2_ino_t inode_num; + int i; + unsigned char *frag, *fsize; + char buf[80]; + int os; + const char *hex_format = "0x%x"; + const char *octal_format = "0%o"; + const char *decimal_format = "%d"; + const char *unsignedlong_format = "%lu"; + + if (common_inode_args_process(argc, argv, &inode_num, CHECK_FS_RW)) + return; + + os = current_fs->super->s_creator_os; + + if (debugfs_read_inode(inode_num, &inode, argv[1])) + return; + + modify_u16(argv[0], "Mode", octal_format, &inode.i_mode); + modify_u16(argv[0], "User ID", decimal_format, &inode.i_uid); + modify_u16(argv[0], "Group ID", decimal_format, &inode.i_gid); + modify_u32(argv[0], "Size", unsignedlong_format, &inode.i_size); + modify_u32(argv[0], "Creation time", decimal_format, &inode.i_ctime); + modify_u32(argv[0], "Modification time", decimal_format, &inode.i_mtime); + modify_u32(argv[0], "Access time", decimal_format, &inode.i_atime); + modify_u32(argv[0], "Deletion time", decimal_format, &inode.i_dtime); + modify_u16(argv[0], "Link count", decimal_format, &inode.i_links_count); + if (os == EXT2_OS_LINUX) + modify_u16(argv[0], "Block count high", unsignedlong_format, + &inode.osd2.linux2.l_i_blocks_hi); + modify_u32(argv[0], "Block count", unsignedlong_format, &inode.i_blocks); + modify_u32(argv[0], "File flags", hex_format, &inode.i_flags); + modify_u32(argv[0], "Generation", hex_format, &inode.i_generation); +#if 0 + modify_u32(argv[0], "Reserved1", decimal_format, &inode.i_reserved1); +#endif + modify_u32(argv[0], "File acl", decimal_format, &inode.i_file_acl); + if (LINUX_S_ISDIR(inode.i_mode)) + modify_u32(argv[0], "Directory acl", decimal_format, &inode.i_dir_acl); + else + modify_u32(argv[0], "High 32bits of size", decimal_format, &inode.i_size_high); + + if (os == EXT2_OS_HURD) + modify_u32(argv[0], "Translator Block", + decimal_format, &inode.osd1.hurd1.h_i_translator); + + modify_u32(argv[0], "Fragment address", decimal_format, &inode.i_faddr); + switch (os) { + case EXT2_OS_HURD: + frag = &inode.osd2.hurd2.h_i_frag; + fsize = &inode.osd2.hurd2.h_i_fsize; + break; + default: + frag = fsize = 0; + } + if (frag) + modify_u8(argv[0], "Fragment number", decimal_format, frag); + if (fsize) + modify_u8(argv[0], "Fragment size", decimal_format, fsize); + + for (i=0; i < EXT2_NDIR_BLOCKS; i++) { + sprintf(buf, "Direct Block #%d", i); + modify_u32(argv[0], buf, decimal_format, &inode.i_block[i]); + } + modify_u32(argv[0], "Indirect Block", decimal_format, + &inode.i_block[EXT2_IND_BLOCK]); + modify_u32(argv[0], "Double Indirect Block", decimal_format, + &inode.i_block[EXT2_DIND_BLOCK]); + modify_u32(argv[0], "Triple Indirect Block", decimal_format, + &inode.i_block[EXT2_TIND_BLOCK]); + if (debugfs_write_inode(inode_num, &inode, argv[1])) + return; +} +#endif /* READ_ONLY */ + +void do_change_working_dir(int argc, char *argv[]) +{ + ext2_ino_t inode; + int retval; + + if (common_inode_args_process(argc, argv, &inode, 0)) + return; + + retval = ext2fs_check_directory(current_fs, inode); + if (retval) { + com_err(argv[1], retval, 0); + return; + } + cwd = inode; + return; +} + +void do_print_working_directory(int argc, char *argv[]) +{ + int retval; + char *pathname = NULL; + + if (common_args_process(argc, argv, 1, 1, + "print_working_directory", "", 0)) + return; + + retval = ext2fs_get_pathname(current_fs, cwd, 0, &pathname); + if (retval) { + com_err(argv[0], retval, + "while trying to get pathname of cwd"); + } + printf("[pwd] INODE: %6u PATH: %s\n", + cwd, pathname ? pathname : "NULL"); + if (pathname) { + free(pathname); + pathname = NULL; + } + retval = ext2fs_get_pathname(current_fs, root, 0, &pathname); + if (retval) { + com_err(argv[0], retval, + "while trying to get pathname of root"); + } + printf("[root] INODE: %6u PATH: %s\n", + root, pathname ? pathname : "NULL"); + if (pathname) { + free(pathname); + pathname = NULL; + } + return; +} + +#ifndef READ_ONLY +static void make_link(char *sourcename, char *destname) +{ + ext2_ino_t ino; + struct ext2_inode inode; + int retval; + ext2_ino_t dir; + char *dest, *cp, *base_name; + + /* + * Get the source inode + */ + ino = string_to_inode(sourcename); + if (!ino) + return; + base_name = strrchr(sourcename, '/'); + if (base_name) + base_name++; + else + base_name = sourcename; + /* + * Figure out the destination. First see if it exists and is + * a directory. + */ + if (! (retval=ext2fs_namei(current_fs, root, cwd, destname, &dir))) + dest = base_name; + else { + /* + * OK, it doesn't exist. See if it is + * '<dir>/basename' or 'basename' + */ + cp = strrchr(destname, '/'); + if (cp) { + *cp = 0; + dir = string_to_inode(destname); + if (!dir) + return; + dest = cp+1; + } else { + dir = cwd; + dest = destname; + } + } + + if (debugfs_read_inode(ino, &inode, sourcename)) + return; + + retval = ext2fs_link(current_fs, dir, dest, ino, + ext2_file_type(inode.i_mode)); + if (retval) + com_err("make_link", retval, 0); + return; +} + + +void do_link(int argc, char *argv[]) +{ + if (common_args_process(argc, argv, 3, 3, "link", + "<source file> <dest_name>", CHECK_FS_RW)) + return; + + make_link(argv[1], argv[2]); +} + +static int mark_blocks_proc(ext2_filsys fs, blk64_t *blocknr, + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *private EXT2FS_ATTR((unused))) +{ + blk64_t block; + + block = *blocknr; + ext2fs_block_alloc_stats2(fs, block, +1); + return 0; +} + +void do_undel(int argc, char *argv[]) +{ + ext2_ino_t ino; + struct ext2_inode inode; + + if (common_args_process(argc, argv, 2, 3, "undelete", + "<inode_num> [dest_name]", + CHECK_FS_RW | CHECK_FS_BITMAPS)) + return; + + ino = string_to_inode(argv[1]); + if (!ino) + return; + + if (debugfs_read_inode(ino, &inode, argv[1])) + return; + + if (ext2fs_test_inode_bitmap2(current_fs->inode_map, ino)) { + com_err(argv[1], 0, "Inode is not marked as deleted"); + return; + } + + /* + * XXX this function doesn't handle changing the links count on the + * parent directory when undeleting a directory. + */ + inode.i_links_count = LINUX_S_ISDIR(inode.i_mode) ? 2 : 1; + inode.i_dtime = 0; + + if (debugfs_write_inode(ino, &inode, argv[0])) + return; + + ext2fs_block_iterate3(current_fs, ino, BLOCK_FLAG_READ_ONLY, NULL, + mark_blocks_proc, NULL); + + ext2fs_inode_alloc_stats2(current_fs, ino, +1, 0); + + if (argc > 2) + make_link(argv[1], argv[2]); +} + +static void unlink_file_by_name(char *filename) +{ + int retval; + ext2_ino_t dir; + char *base_name; + + base_name = strrchr(filename, '/'); + if (base_name) { + *base_name++ = '\0'; + dir = string_to_inode(filename); + if (!dir) + return; + } else { + dir = cwd; + base_name = filename; + } + retval = ext2fs_unlink(current_fs, dir, base_name, 0, 0); + if (retval) + com_err("unlink_file_by_name", retval, 0); + return; +} + +void do_unlink(int argc, char *argv[]) +{ + if (common_args_process(argc, argv, 2, 2, "link", + "<pathname>", CHECK_FS_RW)) + return; + + unlink_file_by_name(argv[1]); +} +#endif /* READ_ONLY */ + +void do_find_free_block(int argc, char *argv[]) +{ + blk64_t free_blk, goal, first_free = 0; + int count; + errcode_t retval; + char *tmp; + + if ((argc > 3) || (argc==2 && *argv[1] == '?')) { + com_err(argv[0], 0, "Usage: find_free_block [count [goal]]"); + return; + } + if (check_fs_open(argv[0])) + return; + + if (argc > 1) { + count = strtol(argv[1],&tmp,0); + if (*tmp) { + com_err(argv[0], 0, "Bad count - %s", argv[1]); + return; + } + } else + count = 1; + + if (argc > 2) { + goal = strtol(argv[2], &tmp, 0); + if (*tmp) { + com_err(argv[0], 0, "Bad goal - %s", argv[1]); + return; + } + } + else + goal = current_fs->super->s_first_data_block; + + printf("Free blocks found: "); + free_blk = goal - 1; + while (count-- > 0) { + retval = ext2fs_new_block2(current_fs, free_blk + 1, 0, + &free_blk); + if (first_free) { + if (first_free == free_blk) + break; + } else + first_free = free_blk; + if (retval) { + com_err("ext2fs_new_block", retval, 0); + return; + } else + printf("%llu ", free_blk); + } + printf("\n"); +} + +void do_find_free_inode(int argc, char *argv[]) +{ + ext2_ino_t free_inode, dir; + int mode; + int retval; + char *tmp; + + if (argc > 3 || (argc>1 && *argv[1] == '?')) { + com_err(argv[0], 0, "Usage: find_free_inode [dir] [mode]"); + return; + } + if (check_fs_open(argv[0])) + return; + + if (argc > 1) { + dir = strtol(argv[1], &tmp, 0); + if (*tmp) { + com_err(argv[0], 0, "Bad dir - %s", argv[1]); + return; + } + } + else + dir = root; + if (argc > 2) { + mode = strtol(argv[2], &tmp, 0); + if (*tmp) { + com_err(argv[0], 0, "Bad mode - %s", argv[2]); + return; + } + } else + mode = 010755; + + retval = ext2fs_new_inode(current_fs, dir, mode, 0, &free_inode); + if (retval) + com_err("ext2fs_new_inode", retval, 0); + else + printf("Free inode found: %u\n", free_inode); +} + +#ifndef READ_ONLY +static errcode_t copy_file(int fd, ext2_ino_t newfile, int bufsize, + int make_holes) +{ + ext2_file_t e2_file; + errcode_t retval, close_ret; + int got; + unsigned int written; + char *buf; + char *ptr; + char *zero_buf; + int cmp; + + retval = ext2fs_file_open(current_fs, newfile, + EXT2_FILE_WRITE, &e2_file); + if (retval) + return retval; + + retval = ext2fs_get_mem(bufsize, &buf); + if (retval) { + com_err("copy_file", retval, "can't allocate buffer\n"); + goto out_close; + } + + /* This is used for checking whether the whole block is zero */ + retval = ext2fs_get_memzero(bufsize, &zero_buf); + if (retval) { + com_err("copy_file", retval, "can't allocate zero buffer\n"); + goto out_free_buf; + } + + while (1) { + got = read(fd, buf, bufsize); + if (got == 0) + break; + if (got < 0) { + retval = errno; + goto fail; + } + ptr = buf; + + /* Sparse copy */ + if (make_holes) { + /* Check whether all is zero */ + cmp = memcmp(ptr, zero_buf, got); + if (cmp == 0) { + /* The whole block is zero, make a hole */ + retval = ext2fs_file_lseek(e2_file, got, + EXT2_SEEK_CUR, NULL); + if (retval) + goto fail; + got = 0; + } + } + + /* Normal copy */ + while (got > 0) { + retval = ext2fs_file_write(e2_file, ptr, + got, &written); + if (retval) + goto fail; + + got -= written; + ptr += written; + } + } + +fail: + ext2fs_free_mem(&zero_buf); +out_free_buf: + ext2fs_free_mem(&buf); +out_close: + close_ret = ext2fs_file_close(e2_file); + if (retval == 0) + retval = close_ret; + return retval; +} + + +void do_write(int argc, char *argv[]) +{ + int fd; + struct stat statbuf; + ext2_ino_t newfile; + errcode_t retval; + struct ext2_inode inode; + int bufsize = IO_BUFSIZE; + int make_holes = 0; + + if (common_args_process(argc, argv, 3, 3, "write", + "<native file> <new file>", CHECK_FS_RW)) + return; + + fd = open(argv[1], O_RDONLY); + if (fd < 0) { + com_err(argv[1], errno, 0); + return; + } + if (fstat(fd, &statbuf) < 0) { + com_err(argv[1], errno, 0); + close(fd); + return; + } + + retval = ext2fs_namei(current_fs, root, cwd, argv[2], &newfile); + if (retval == 0) { + com_err(argv[0], 0, "The file '%s' already exists\n", argv[2]); + close(fd); + return; + } + + retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); + if (retval) { + com_err(argv[0], retval, 0); + close(fd); + return; + } + printf("Allocated inode: %u\n", newfile); + retval = ext2fs_link(current_fs, cwd, argv[2], newfile, + EXT2_FT_REG_FILE); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(current_fs, cwd); + if (retval) { + com_err(argv[0], retval, "while expanding directory"); + close(fd); + return; + } + retval = ext2fs_link(current_fs, cwd, argv[2], newfile, + EXT2_FT_REG_FILE); + } + if (retval) { + com_err(argv[2], retval, 0); + close(fd); + return; + } + if (ext2fs_test_inode_bitmap2(current_fs->inode_map,newfile)) + com_err(argv[0], 0, "Warning: inode already set"); + ext2fs_inode_alloc_stats2(current_fs, newfile, +1, 0); + memset(&inode, 0, sizeof(inode)); + inode.i_mode = (statbuf.st_mode & ~LINUX_S_IFMT) | LINUX_S_IFREG; + inode.i_atime = inode.i_ctime = inode.i_mtime = + current_fs->now ? current_fs->now : time(0); + inode.i_links_count = 1; + retval = ext2fs_inode_size_set(current_fs, &inode, statbuf.st_size); + if (retval) { + com_err(argv[2], retval, 0); + close(fd); + return; + } + if (current_fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_EXTENTS) { + int i; + struct ext3_extent_header *eh; + + eh = (struct ext3_extent_header *) &inode.i_block[0]; + eh->eh_depth = 0; + eh->eh_entries = 0; + eh->eh_magic = ext2fs_cpu_to_le16(EXT3_EXT_MAGIC); + i = (sizeof(inode.i_block) - sizeof(*eh)) / + sizeof(struct ext3_extent); + eh->eh_max = ext2fs_cpu_to_le16(i); + inode.i_flags |= EXT4_EXTENTS_FL; + } + if (debugfs_write_new_inode(newfile, &inode, argv[0])) { + close(fd); + return; + } + if (LINUX_S_ISREG(inode.i_mode)) { + if (statbuf.st_blocks < statbuf.st_size / S_BLKSIZE) { + make_holes = 1; + /* + * Use I/O blocksize as buffer size when + * copying sparse files. + */ + bufsize = statbuf.st_blksize; + } + retval = copy_file(fd, newfile, bufsize, make_holes); + if (retval) + com_err("copy_file", retval, 0); + } + close(fd); +} + +void do_mknod(int argc, char *argv[]) +{ + unsigned long mode, major, minor; + ext2_ino_t newfile; + errcode_t retval; + struct ext2_inode inode; + int filetype, nr; + + if (check_fs_open(argv[0])) + return; + if (argc < 3 || argv[2][1]) { + usage: + com_err(argv[0], 0, "Usage: mknod <name> [p| [c|b] <major> <minor>]"); + return; + } + mode = minor = major = 0; + switch (argv[2][0]) { + case 'p': + mode = LINUX_S_IFIFO; + filetype = EXT2_FT_FIFO; + nr = 3; + break; + case 'c': + mode = LINUX_S_IFCHR; + filetype = EXT2_FT_CHRDEV; + nr = 5; + break; + case 'b': + mode = LINUX_S_IFBLK; + filetype = EXT2_FT_BLKDEV; + nr = 5; + break; + default: + filetype = 0; + nr = 0; + } + if (nr == 5) { + major = strtoul(argv[3], argv+3, 0); + minor = strtoul(argv[4], argv+4, 0); + if (major > 65535 || minor > 65535 || argv[3][0] || argv[4][0]) + nr = 0; + } + if (argc != nr) + goto usage; + if (check_fs_read_write(argv[0])) + return; + retval = ext2fs_new_inode(current_fs, cwd, 010755, 0, &newfile); + if (retval) { + com_err(argv[0], retval, 0); + return; + } + printf("Allocated inode: %u\n", newfile); + retval = ext2fs_link(current_fs, cwd, argv[1], newfile, filetype); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(current_fs, cwd); + if (retval) { + com_err(argv[0], retval, "while expanding directory"); + return; + } + retval = ext2fs_link(current_fs, cwd, argv[1], newfile, + filetype); + } + if (retval) { + com_err(argv[1], retval, 0); + return; + } + if (ext2fs_test_inode_bitmap2(current_fs->inode_map,newfile)) + com_err(argv[0], 0, "Warning: inode already set"); + ext2fs_inode_alloc_stats2(current_fs, newfile, +1, 0); + memset(&inode, 0, sizeof(inode)); + inode.i_mode = mode; + inode.i_atime = inode.i_ctime = inode.i_mtime = + current_fs->now ? current_fs->now : time(0); + if ((major < 256) && (minor < 256)) { + inode.i_block[0] = major*256+minor; + inode.i_block[1] = 0; + } else { + inode.i_block[0] = 0; + inode.i_block[1] = (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); + } + inode.i_links_count = 1; + if (debugfs_write_new_inode(newfile, &inode, argv[0])) + return; +} + +void do_mkdir(int argc, char *argv[]) +{ + char *cp; + ext2_ino_t parent; + char *name; + errcode_t retval; + + if (common_args_process(argc, argv, 2, 2, "mkdir", + "<filename>", CHECK_FS_RW)) + return; + + cp = strrchr(argv[1], '/'); + if (cp) { + *cp = 0; + parent = string_to_inode(argv[1]); + if (!parent) { + com_err(argv[1], ENOENT, 0); + return; + } + name = cp+1; + } else { + parent = cwd; + name = argv[1]; + } + +try_again: + retval = ext2fs_mkdir(current_fs, parent, 0, name); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(current_fs, parent); + if (retval) { + com_err(argv[0], retval, "while expanding directory"); + return; + } + goto try_again; + } + if (retval) { + com_err("ext2fs_mkdir", retval, 0); + return; + } + +} + +static int release_blocks_proc(ext2_filsys fs, blk64_t *blocknr, + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *private EXT2FS_ATTR((unused))) +{ + blk64_t block; + + block = *blocknr; + ext2fs_block_alloc_stats2(fs, block, -1); + return 0; +} + +static void kill_file_by_inode(ext2_ino_t inode) +{ + struct ext2_inode inode_buf; + + if (debugfs_read_inode(inode, &inode_buf, 0)) + return; + inode_buf.i_dtime = current_fs->now ? current_fs->now : time(0); + if (debugfs_write_inode(inode, &inode_buf, 0)) + return; + if (!ext2fs_inode_has_valid_blocks2(current_fs, &inode_buf)) + return; + + ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, NULL, + release_blocks_proc, NULL); + printf("\n"); + ext2fs_inode_alloc_stats2(current_fs, inode, -1, + LINUX_S_ISDIR(inode_buf.i_mode)); +} + + +void do_kill_file(int argc, char *argv[]) +{ + ext2_ino_t inode_num; + + if (common_inode_args_process(argc, argv, &inode_num, CHECK_FS_RW)) + return; + + kill_file_by_inode(inode_num); +} + +void do_rm(int argc, char *argv[]) +{ + int retval; + ext2_ino_t inode_num; + struct ext2_inode inode; + + if (common_args_process(argc, argv, 2, 2, "rm", + "<filename>", CHECK_FS_RW)) + return; + + retval = ext2fs_namei(current_fs, root, cwd, argv[1], &inode_num); + if (retval) { + com_err(argv[0], retval, "while trying to resolve filename"); + return; + } + + if (debugfs_read_inode(inode_num, &inode, argv[0])) + return; + + if (LINUX_S_ISDIR(inode.i_mode)) { + com_err(argv[0], 0, "file is a directory"); + return; + } + + --inode.i_links_count; + if (debugfs_write_inode(inode_num, &inode, argv[0])) + return; + + unlink_file_by_name(argv[1]); + if (inode.i_links_count == 0) + kill_file_by_inode(inode_num); +} + +struct rd_struct { + ext2_ino_t parent; + int empty; +}; + +static int rmdir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)), + int entry EXT2FS_ATTR((unused)), + struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *private) +{ + struct rd_struct *rds = (struct rd_struct *) private; + + if (dirent->inode == 0) + return 0; + if (((dirent->name_len&0xFF) == 1) && (dirent->name[0] == '.')) + return 0; + if (((dirent->name_len&0xFF) == 2) && (dirent->name[0] == '.') && + (dirent->name[1] == '.')) { + rds->parent = dirent->inode; + return 0; + } + rds->empty = 0; + return 0; +} + +void do_rmdir(int argc, char *argv[]) +{ + int retval; + ext2_ino_t inode_num; + struct ext2_inode inode; + struct rd_struct rds; + + if (common_args_process(argc, argv, 2, 2, "rmdir", + "<filename>", CHECK_FS_RW)) + return; + + retval = ext2fs_namei(current_fs, root, cwd, argv[1], &inode_num); + if (retval) { + com_err(argv[0], retval, "while trying to resolve filename"); + return; + } + + if (debugfs_read_inode(inode_num, &inode, argv[0])) + return; + + if (!LINUX_S_ISDIR(inode.i_mode)) { + com_err(argv[0], 0, "file is not a directory"); + return; + } + + rds.parent = 0; + rds.empty = 1; + + retval = ext2fs_dir_iterate2(current_fs, inode_num, 0, + 0, rmdir_proc, &rds); + if (retval) { + com_err(argv[0], retval, "while iterating over directory"); + return; + } + if (rds.empty == 0) { + com_err(argv[0], 0, "directory not empty"); + return; + } + + inode.i_links_count = 0; + if (debugfs_write_inode(inode_num, &inode, argv[0])) + return; + + unlink_file_by_name(argv[1]); + kill_file_by_inode(inode_num); + + if (rds.parent) { + if (debugfs_read_inode(rds.parent, &inode, argv[0])) + return; + if (inode.i_links_count > 1) + inode.i_links_count--; + if (debugfs_write_inode(rds.parent, &inode, argv[0])) + return; + } +} +#endif /* READ_ONLY */ + +void do_show_debugfs_params(int argc EXT2FS_ATTR((unused)), + char *argv[] EXT2FS_ATTR((unused))) +{ + if (current_fs) + printf("Open mode: read-%s\n", + current_fs->flags & EXT2_FLAG_RW ? "write" : "only"); + printf("Filesystem in use: %s\n", + current_fs ? current_fs->device_name : "--none--"); +} + +#ifndef READ_ONLY +void do_expand_dir(int argc, char *argv[]) +{ + ext2_ino_t inode; + int retval; + + if (common_inode_args_process(argc, argv, &inode, CHECK_FS_RW)) + return; + + retval = ext2fs_expand_dir(current_fs, inode); + if (retval) + com_err("ext2fs_expand_dir", retval, 0); + return; +} + +void do_features(int argc, char *argv[]) +{ + int i; + + if (check_fs_open(argv[0])) + return; + + if ((argc != 1) && check_fs_read_write(argv[0])) + return; + for (i=1; i < argc; i++) { + if (e2p_edit_feature(argv[i], + ¤t_fs->super->s_feature_compat, 0)) + com_err(argv[0], 0, "Unknown feature: %s\n", + argv[i]); + else + ext2fs_mark_super_dirty(current_fs); + } + print_features(current_fs->super, stdout); +} +#endif /* READ_ONLY */ + +void do_bmap(int argc, char *argv[]) +{ + ext2_ino_t ino; + blk64_t blk, pblk; + int err; + errcode_t errcode; + + if (common_args_process(argc, argv, 3, 3, argv[0], + "<file> logical_blk", 0)) + return; + + ino = string_to_inode(argv[1]); + if (!ino) + return; + err = strtoblk(argv[0], argv[2], "logical block", &blk); + if (err) + return; + + errcode = ext2fs_bmap2(current_fs, ino, 0, 0, 0, blk, 0, &pblk); + if (errcode) { + com_err(argv[0], errcode, + "while mapping logical block %llu\n", blk); + return; + } + printf("%llu\n", pblk); +} + +void do_imap(int argc, char *argv[]) +{ + ext2_ino_t ino; + unsigned long group, block, block_nr, offset; + + if (common_args_process(argc, argv, 2, 2, argv[0], + "<file>", 0)) + return; + ino = string_to_inode(argv[1]); + if (!ino) + return; + + group = (ino - 1) / EXT2_INODES_PER_GROUP(current_fs->super); + offset = ((ino - 1) % EXT2_INODES_PER_GROUP(current_fs->super)) * + EXT2_INODE_SIZE(current_fs->super); + block = offset >> EXT2_BLOCK_SIZE_BITS(current_fs->super); + if (!ext2fs_inode_table_loc(current_fs, (unsigned)group)) { + com_err(argv[0], 0, "Inode table for group %lu is missing\n", + group); + return; + } + block_nr = ext2fs_inode_table_loc(current_fs, (unsigned)group) + + block; + offset &= (EXT2_BLOCK_SIZE(current_fs->super) - 1); + + printf("Inode %d is part of block group %lu\n" + "\tlocated at block %lu, offset 0x%04lx\n", ino, group, + block_nr, offset); + +} + +void do_idump(int argc, char *argv[]) +{ + ext2_ino_t ino; + unsigned char *buf; + errcode_t err; + int isize; + + if (common_args_process(argc, argv, 2, 2, argv[0], + "<file>", 0)) + return; + ino = string_to_inode(argv[1]); + if (!ino) + return; + + isize = EXT2_INODE_SIZE(current_fs->super); + err = ext2fs_get_mem(isize, &buf); + if (err) { + com_err(argv[0], err, "while allocating memory"); + return; + } + + err = ext2fs_read_inode_full(current_fs, ino, + (struct ext2_inode *)buf, isize); + if (err) { + com_err(argv[0], err, "while reading inode %d", ino); + goto err; + } + + do_byte_hexdump(stdout, buf, isize); +err: + ext2fs_free_mem(&buf); +} + +#ifndef READ_ONLY +void do_set_current_time(int argc, char *argv[]) +{ + time_t now; + + if (common_args_process(argc, argv, 2, 2, argv[0], + "<time>", 0)) + return; + + now = string_to_time(argv[1]); + if (now == ((time_t) -1)) { + com_err(argv[0], 0, "Couldn't parse argument as a time: %s\n", + argv[1]); + return; + + } else { + printf("Setting current time to %s\n", time_to_string(now)); + current_fs->now = now; + } +} +#endif /* READ_ONLY */ + +static int find_supp_feature(__u32 *supp, int feature_type, char *name) +{ + int compat, bit, ret; + unsigned int feature_mask; + + if (name) { + if (feature_type == E2P_FS_FEATURE) + ret = e2p_string2feature(name, &compat, &feature_mask); + else + ret = e2p_jrnl_string2feature(name, &compat, + &feature_mask); + if (ret) + return ret; + + if (!(supp[compat] & feature_mask)) + return 1; + } else { + for (compat = 0; compat < 3; compat++) { + for (bit = 0, feature_mask = 1; bit < 32; + bit++, feature_mask <<= 1) { + if (supp[compat] & feature_mask) { + if (feature_type == E2P_FS_FEATURE) + fprintf(stdout, " %s", + e2p_feature2string(compat, + feature_mask)); + else + fprintf(stdout, " %s", + e2p_jrnl_feature2string(compat, + feature_mask)); + } + } + } + fprintf(stdout, "\n"); + } + + return 0; +} + +void do_supported_features(int argc, char *argv[]) +{ + int ret; + __u32 supp[3] = { EXT2_LIB_FEATURE_COMPAT_SUPP, + EXT2_LIB_FEATURE_INCOMPAT_SUPP, + EXT2_LIB_FEATURE_RO_COMPAT_SUPP }; + __u32 jrnl_supp[3] = { JFS_KNOWN_COMPAT_FEATURES, + JFS_KNOWN_INCOMPAT_FEATURES, + JFS_KNOWN_ROCOMPAT_FEATURES }; + + if (argc > 1) { + ret = find_supp_feature(supp, E2P_FS_FEATURE, argv[1]); + if (ret) { + ret = find_supp_feature(jrnl_supp, E2P_JOURNAL_FEATURE, + argv[1]); + } + if (ret) + com_err(argv[0], 0, "Unknown feature: %s\n", argv[1]); + else + fprintf(stdout, "Supported feature: %s\n", argv[1]); + } else { + fprintf(stdout, "Supported features:"); + ret = find_supp_feature(supp, E2P_FS_FEATURE, NULL); + ret = find_supp_feature(jrnl_supp, E2P_JOURNAL_FEATURE, NULL); + } +} + +#ifndef READ_ONLY +void do_punch(int argc, char *argv[]) +{ + ext2_ino_t ino; + blk64_t start, end; + int err; + errcode_t errcode; + + if (common_args_process(argc, argv, 3, 4, argv[0], + "<file> start_blk [end_blk]", + CHECK_FS_RW | CHECK_FS_BITMAPS)) + return; + + ino = string_to_inode(argv[1]); + if (!ino) + return; + err = strtoblk(argv[0], argv[2], "logical block", &start); + if (err) + return; + if (argc == 4) { + err = strtoblk(argv[0], argv[3], "logical block", &end); + if (err) + return; + } else + end = ~0; + + errcode = ext2fs_punch(current_fs, ino, 0, 0, start, end); + + if (errcode) { + com_err(argv[0], errcode, + "while truncating inode %u from %llu to %llu\n", ino, + (unsigned long long) start, (unsigned long long) end); + return; + } +} +#endif /* READ_ONLY */ + +void do_symlink(int argc, char *argv[]) +{ + char *cp; + ext2_ino_t parent; + char *name, *target; + errcode_t retval; + + if (common_args_process(argc, argv, 3, 3, "symlink", + "<filename> <target>", CHECK_FS_RW)) + return; + + cp = strrchr(argv[1], '/'); + if (cp) { + *cp = 0; + parent = string_to_inode(argv[1]); + if (!parent) { + com_err(argv[1], ENOENT, 0); + return; + } + name = cp+1; + } else { + parent = cwd; + name = argv[1]; + } + target = argv[2]; + +try_again: + retval = ext2fs_symlink(current_fs, parent, 0, name, target); + if (retval == EXT2_ET_DIR_NO_SPACE) { + retval = ext2fs_expand_dir(current_fs, parent); + if (retval) { + com_err(argv[0], retval, "while expanding directory"); + return; + } + goto try_again; + } + if (retval) { + com_err("ext2fs_symlink", retval, 0); + return; + } + +} + +void do_dump_mmp(int argc EXT2FS_ATTR((unused)), char *argv[]) +{ + struct mmp_struct *mmp_s; + time_t t; + errcode_t retval = 0; + + if (check_fs_open(argv[0])) + return; + + if (current_fs->mmp_buf == NULL) { + retval = ext2fs_get_mem(current_fs->blocksize, + ¤t_fs->mmp_buf); + if (retval) { + com_err(argv[0], retval, "allocating MMP buffer.\n"); + return; + } + } + + mmp_s = current_fs->mmp_buf; + + retval = ext2fs_mmp_read(current_fs, current_fs->super->s_mmp_block, + current_fs->mmp_buf); + if (retval) { + com_err(argv[0], retval, "reading MMP block.\n"); + return; + } + + t = mmp_s->mmp_time; + fprintf(stdout, "block_number: %llu\n", current_fs->super->s_mmp_block); + fprintf(stdout, "update_interval: %d\n", + current_fs->super->s_mmp_update_interval); + fprintf(stdout, "check_interval: %d\n", mmp_s->mmp_check_interval); + fprintf(stdout, "sequence: %08x\n", mmp_s->mmp_seq); + fprintf(stdout, "time: %lld -- %s", mmp_s->mmp_time, ctime(&t)); + fprintf(stdout, "node_name: %s\n", mmp_s->mmp_nodename); + fprintf(stdout, "device_name: %s\n", mmp_s->mmp_bdevname); + fprintf(stdout, "magic: 0x%x\n", mmp_s->mmp_magic); +} + +static int source_file(const char *cmd_file, int ss_idx) +{ + FILE *f; + char buf[BUFSIZ]; + char *cp; + int exit_status = 0; + int retval; + + if (strcmp(cmd_file, "-") == 0) + f = stdin; + else { + f = fopen(cmd_file, "r"); + if (!f) { + perror(cmd_file); + exit(1); + } + } + fflush(stdout); + fflush(stderr); + setbuf(stdout, NULL); + setbuf(stderr, NULL); + while (!feof(f)) { + if (fgets(buf, sizeof(buf), f) == NULL) + break; + cp = strchr(buf, '\n'); + if (cp) + *cp = 0; + cp = strchr(buf, '\r'); + if (cp) + *cp = 0; + printf("debugfs: %s\n", buf); + retval = ss_execute_line(ss_idx, buf); + if (retval) { + ss_perror(ss_idx, retval, buf); + exit_status++; + } + } + if (f != stdin) + fclose(f); + return exit_status; +} + +int main(int argc, char **argv) +{ + int retval; + const char *usage = + "Usage: %s [-b blocksize] [-s superblock] [-f cmd_file] " + "[-R request] [-V] [" +#ifndef READ_ONLY + "[-w] " +#endif + "[-c] device]"; + int c; + int open_flags = EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS; + char *request = 0; + int exit_status = 0; + char *cmd_file = 0; + blk64_t superblock = 0; + blk64_t blocksize = 0; + int catastrophic = 0; + char *data_filename = 0; +#ifdef READ_ONLY + const char *opt_string = "icR:f:b:s:Vd:D"; +#else + const char *opt_string = "iwcR:f:b:s:Vd:D"; +#endif + + if (debug_prog_name == 0) +#ifdef READ_ONLY + debug_prog_name = "rdebugfs"; +#else + debug_prog_name = "debugfs"; +#endif + add_error_table(&et_ext2_error_table); + fprintf (stderr, "%s %s (%s)\n", debug_prog_name, + E2FSPROGS_VERSION, E2FSPROGS_DATE); + + while ((c = getopt (argc, argv, opt_string)) != EOF) { + switch (c) { + case 'R': + request = optarg; + break; + case 'f': + cmd_file = optarg; + break; + case 'd': + data_filename = optarg; + break; + case 'i': + open_flags |= EXT2_FLAG_IMAGE_FILE; + break; +#ifndef READ_ONLY + case 'w': + open_flags |= EXT2_FLAG_RW; + break; +#endif + case 'D': + open_flags |= EXT2_FLAG_DIRECT_IO; + break; + case 'b': + blocksize = parse_ulong(optarg, argv[0], + "block size", 0); + break; + case 's': + retval = strtoblk(argv[0], optarg, + "superblock block number", + &superblock); + if (retval) + return 1; + break; + case 'c': + catastrophic = 1; + break; + case 'V': + /* Print version number and exit */ + fprintf(stderr, "\tUsing %s\n", + error_message(EXT2_ET_BASE)); + exit(0); + default: + com_err(argv[0], 0, usage, debug_prog_name); + return 1; + } + } + if (optind < argc) + open_filesystem(argv[optind], open_flags, + superblock, blocksize, catastrophic, + data_filename); + + sci_idx = ss_create_invocation(debug_prog_name, "0.0", (char *) NULL, + &debug_cmds, &retval); + if (retval) { + ss_perror(sci_idx, retval, "creating invocation"); + exit(1); + } + ss_get_readline(sci_idx); + + (void) ss_add_request_table (sci_idx, &ss_std_requests, 1, &retval); + if (retval) { + ss_perror(sci_idx, retval, "adding standard requests"); + exit (1); + } + if (extra_cmds) + ss_add_request_table (sci_idx, extra_cmds, 1, &retval); + if (retval) { + ss_perror(sci_idx, retval, "adding extra requests"); + exit (1); + } + if (request) { + retval = 0; + retval = ss_execute_line(sci_idx, request); + if (retval) { + ss_perror(sci_idx, retval, request); + exit_status++; + } + } else if (cmd_file) { + exit_status = source_file(cmd_file, sci_idx); + } else { + ss_listen(sci_idx); + } + + ss_delete_invocation(sci_idx); + + if (current_fs) + close_filesystem(); + + remove_error_table(&et_ext2_error_table); + return exit_status; +}
diff --git a/debugfs/debugfs.h b/debugfs/debugfs.h new file mode 100644 index 0000000..0e75cee --- /dev/null +++ b/debugfs/debugfs.h
@@ -0,0 +1,186 @@ +/* + * debugfs.h --- header file for the debugfs program + */ + +#include "ss/ss.h" +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fs.h" +#include "quota/quotaio.h" + +#ifdef __STDC__ +#define NOARGS void +#else +#define NOARGS +#define const +#endif + +/* + * Flags used by the common argument processing functions + */ +#define CHECK_FS_RW 0x0001 +#define CHECK_FS_BITMAPS 0x0002 +#define CHECK_FS_NOTOPEN 0x0004 + +extern ext2_filsys current_fs; +extern quota_ctx_t current_qctx; +extern ext2_ino_t root, cwd; +extern int sci_idx; +extern ss_request_table debug_cmds, extent_cmds; + +extern void reset_getopt(void); +extern FILE *open_pager(void); +extern void close_pager(FILE *stream); +extern int check_fs_open(char *name); +extern int check_fs_not_open(char *name); +extern int check_fs_read_write(char *name); +extern int check_fs_bitmaps(char *name); +extern ext2_ino_t string_to_inode(char *str); +extern char *time_to_string(__u32); +extern time_t string_to_time(const char *); +extern unsigned long parse_ulong(const char *str, const char *cmd, + const char *descr, int *err); +extern unsigned long long parse_ulonglong(const char *str, const char *cmd, + const char *descr, int *err); +extern int strtoblk(const char *cmd, const char *str, const char *errmsg, + blk64_t *ret); +extern int common_args_process(int argc, char *argv[], int min_argc, + int max_argc, const char *cmd, + const char *usage, int flags); +extern int common_inode_args_process(int argc, char *argv[], + ext2_ino_t *inode, int flags); +extern int common_block_args_process(int argc, char *argv[], + blk64_t *block, blk64_t *count); +extern int debugfs_read_inode(ext2_ino_t ino, struct ext2_inode * inode, + const char *cmd); +extern int debugfs_read_inode_full(ext2_ino_t ino, struct ext2_inode * inode, + const char *cmd, int bufsize); +extern int debugfs_write_inode(ext2_ino_t ino, struct ext2_inode * inode, + const char *cmd); +extern int debugfs_write_inode_full(ext2_ino_t ino, struct ext2_inode * inode, + const char *cmd, int bufsize); +extern int debugfs_write_new_inode(ext2_ino_t ino, struct ext2_inode * inode, + const char *cmd); +extern int ext2_file_type(unsigned int mode); + +/* ss command functions */ + +/* dump.c */ +extern void do_dump(int argc, char **argv); +extern void do_cat(int argc, char **argv); +extern void do_rdump(int argc, char **argv); + +/* extent_inode.c */ +extern void do_extent_open(int argc, char **argv); +extern void do_extent_close(int argc, char **argv); +extern void do_current_node(int argc, char **argv); +extern void do_root_node(int argc, char **argv); +extern void do_last_leaf(int argc, char **argv); +extern void do_first_sib(int argc, char **argv); +extern void do_last_sib(int argc, char **argv); +extern void do_next_sib(int argc, char **argv); +extern void do_prev_sib(int argc, char **argv); +extern void do_next_leaf(int argc, char **argv); +extern void do_prev_leaf(int argc, char **argv); +extern void do_next(int argc, char **argv); +extern void do_prev(int argc, char **argv); +extern void do_up(int argc, char **argv); +extern void do_down(int argc, char **argv); +extern void do_delete_node(int argc, char **argv); +extern void do_replace_node(int argc, char **argv); +extern void do_split_node(int argc, char **argv); +extern void do_insert_node(int argc, char **argv); +extern void do_set_bmap(int argc, char **argv); +extern void do_print_all(int argc, char **argv); +extern void do_fix_parents(int argc, char **argv); +extern void do_info(int argc, char **argv); +extern void do_goto_block(int argc, char **argv); + +/* htree.c */ +extern void do_htree_dump(int argc, char **argv); +extern void do_dx_hash(int argc, char **argv); +extern void do_dirsearch(int argc, char **argv); + +/* logdump.c */ +extern void do_logdump(int argc, char **argv); + +/* lsdel.c */ +extern void do_lsdel(int argc, char **argv); + +/* icheck.c */ +extern void do_icheck(int argc, char **argv); + +/* ncheck.c */ +extern void do_ncheck(int argc, char **argv); + +/* set_fields.c */ +extern void do_set_super(int argc, char **); +extern void do_set_inode(int argc, char **); +extern void do_set_block_group_descriptor(int argc, char **); + +/* unused.c */ +extern void do_dump_unused(int argc, char **argv); + +/* debugfs.c */ +extern void internal_dump_inode(FILE *, const char *, ext2_ino_t, + struct ext2_inode *, int); + +extern void do_dirty_filesys(int argc, char **argv); +extern void do_open_filesys(int argc, char **argv); +extern void do_close_filesys(int argc, char **argv); +extern void do_lcd(int argc, char **argv); +extern void do_init_filesys(int argc, char **argv); +extern void do_show_super_stats(int argc, char **argv); +extern void do_kill_file(int argc, char **argv); +extern void do_rm(int argc, char **argv); +extern void do_link(int argc, char **argv); +extern void do_undel(int argc, char **argv); +extern void do_unlink(int argc, char **argv); +extern void do_find_free_block(int argc, char **argv); +extern void do_find_free_inode(int argc, char **argv); +extern void do_stat(int argc, char **argv); +extern void do_dump_extents(int argc, char **argv); +extern void do_blocks(int argc, char *argv[]); + +extern void do_chroot(int argc, char **argv); +extern void do_clri(int argc, char **argv); +extern void do_freei(int argc, char **argv); +extern void do_seti(int argc, char **argv); +extern void do_testi(int argc, char **argv); +extern void do_freeb(int argc, char **argv); +extern void do_setb(int argc, char **argv); +extern void do_testb(int argc, char **argv); +extern void do_modify_inode(int argc, char **argv); +extern void do_list_dir(int argc, char **argv); +extern void do_change_working_dir(int argc, char **argv); +extern void do_print_working_directory(int argc, char **argv); +extern void do_write(int argc, char **argv); +extern void do_mknod(int argc, char **argv); +extern void do_mkdir(int argc, char **argv); +extern void do_rmdir(int argc, char **argv); +extern void do_show_debugfs_params(int argc, char **argv); +extern void do_expand_dir(int argc, char **argv); +extern void do_features(int argc, char **argv); +extern void do_bmap(int argc, char **argv); +extern void do_imap(int argc, char **argv); +extern void do_set_current_time(int argc, char **argv); +extern void do_supported_features(int argc, char **argv); +extern void do_punch(int argc, char **argv); +extern void do_symlink(int argc, char **argv); + +extern void do_dump_mmp(int argc, char **argv); +extern void do_set_mmp_value(int argc, char **argv); + +extern void do_freefrag(int argc, char **argv); +extern void do_filefrag(int argc, char *argv[]); + +/* quota.c */ +extern void do_list_quota(int argc, char *argv[]); +extern void do_get_quota(int argc, char *argv[]); + +/* util.c */ +extern time_t string_to_time(const char *arg); + +/* zap.c */ +extern void do_zap_block(int argc, char **argv); +extern void do_block_dump(int argc, char **argv); +extern void do_byte_hexdump(FILE *fp, unsigned char *buf, size_t bufsize);
diff --git a/debugfs/dump.c b/debugfs/dump.c new file mode 100644 index 0000000..8d97886 --- /dev/null +++ b/debugfs/dump.c
@@ -0,0 +1,384 @@ +/* + * dump.c --- dump the contents of an inode out to a file + * + * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE /* for O_LARGEFILE */ +#endif + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <utime.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif + +#include "debugfs.h" + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + +/* + * The mode_xlate function translates a linux mode into a native-OS mode_t. + */ +static struct { + __u16 lmask; + mode_t mask; +} mode_table[] = { + { LINUX_S_IRUSR, S_IRUSR }, + { LINUX_S_IWUSR, S_IWUSR }, + { LINUX_S_IXUSR, S_IXUSR }, + { LINUX_S_IRGRP, S_IRGRP }, + { LINUX_S_IWGRP, S_IWGRP }, + { LINUX_S_IXGRP, S_IXGRP }, + { LINUX_S_IROTH, S_IROTH }, + { LINUX_S_IWOTH, S_IWOTH }, + { LINUX_S_IXOTH, S_IXOTH }, + { 0, 0 } +}; + +static mode_t mode_xlate(__u16 lmode) +{ + mode_t mode = 0; + int i; + + for (i=0; mode_table[i].lmask; i++) { + if (lmode & mode_table[i].lmask) + mode |= mode_table[i].mask; + } + return mode; +} + +static void fix_perms(const char *cmd, const struct ext2_inode *inode, + int fd, const char *name) +{ + struct utimbuf ut; + int i; + + if (fd != -1) + i = fchmod(fd, mode_xlate(inode->i_mode)); + else + i = chmod(name, mode_xlate(inode->i_mode)); + if (i == -1) + com_err(cmd, errno, "while setting permissions of %s", name); + +#ifndef HAVE_FCHOWN + i = chown(name, inode->i_uid, inode->i_gid); +#else + if (fd != -1) + i = fchown(fd, inode->i_uid, inode->i_gid); + else + i = chown(name, inode->i_uid, inode->i_gid); +#endif + if (i == -1) + com_err(cmd, errno, "while changing ownership of %s", name); + + ut.actime = inode->i_atime; + ut.modtime = inode->i_mtime; + if (utime(name, &ut) == -1) + com_err(cmd, errno, "while setting times of %s", name); +} + +static void dump_file(const char *cmdname, ext2_ino_t ino, int fd, + int preserve, char *outname) +{ + errcode_t retval; + struct ext2_inode inode; + char *buf = 0; + ext2_file_t e2_file; + int nbytes; + unsigned int got, blocksize = current_fs->blocksize; + + if (debugfs_read_inode(ino, &inode, cmdname)) + return; + + retval = ext2fs_file_open(current_fs, ino, 0, &e2_file); + if (retval) { + com_err(cmdname, retval, "while opening ext2 file"); + return; + } + retval = ext2fs_get_mem(blocksize, &buf); + if (retval) { + com_err(cmdname, retval, "while allocating memory"); + return; + } + while (1) { + retval = ext2fs_file_read(e2_file, buf, blocksize, &got); + if (retval) + com_err(cmdname, retval, "while reading ext2 file"); + if (got == 0) + break; + nbytes = write(fd, buf, got); + if ((unsigned) nbytes != got) + com_err(cmdname, errno, "while writing file"); + } + if (buf) + ext2fs_free_mem(&buf); + retval = ext2fs_file_close(e2_file); + if (retval) { + com_err(cmdname, retval, "while closing ext2 file"); + return; + } + + if (preserve) + fix_perms("dump_file", &inode, fd, outname); + + return; +} + +void do_dump(int argc, char **argv) +{ + ext2_ino_t inode; + int fd; + int c; + int preserve = 0; + char *in_fn, *out_fn; + + reset_getopt(); + while ((c = getopt (argc, argv, "p")) != EOF) { + switch (c) { + case 'p': + preserve++; + break; + default: + print_usage: + com_err(argv[0], 0, "Usage: dump_inode [-p] " + "<file> <output_file>"); + return; + } + } + if (optind != argc-2) + goto print_usage; + + if (check_fs_open(argv[0])) + return; + + in_fn = argv[optind]; + out_fn = argv[optind+1]; + + inode = string_to_inode(in_fn); + if (!inode) + return; + + fd = open(out_fn, O_CREAT | O_WRONLY | O_TRUNC | O_LARGEFILE, 0666); + if (fd < 0) { + com_err(argv[0], errno, "while opening %s for dump_inode", + out_fn); + return; + } + + dump_file(argv[0], inode, fd, preserve, out_fn); + if (close(fd) != 0) { + com_err(argv[0], errno, "while closing %s for dump_inode", + out_fn); + return; + } + + return; +} + +static void rdump_symlink(ext2_ino_t ino, struct ext2_inode *inode, + const char *fullname) +{ + ext2_file_t e2_file; + char *buf; + errcode_t retval; + + buf = malloc(inode->i_size + 1); + if (!buf) { + com_err("rdump", errno, "while allocating for symlink"); + goto errout; + } + + /* Apparently, this is the right way to detect and handle fast + * symlinks; see do_stat() in debugfs.c. */ + if (inode->i_blocks == 0) + strcpy(buf, (char *) inode->i_block); + else { + unsigned bytes = inode->i_size; + char *p = buf; + retval = ext2fs_file_open(current_fs, ino, 0, &e2_file); + if (retval) { + com_err("rdump", retval, "while opening symlink"); + goto errout; + } + for (;;) { + unsigned int got; + retval = ext2fs_file_read(e2_file, p, bytes, &got); + if (retval) { + com_err("rdump", retval, "while reading symlink"); + goto errout; + } + bytes -= got; + p += got; + if (got == 0 || bytes == 0) + break; + } + buf[inode->i_size] = 0; + retval = ext2fs_file_close(e2_file); + if (retval) + com_err("rdump", retval, "while closing symlink"); + } + + if (symlink(buf, fullname) == -1) { + com_err("rdump", errno, "while creating symlink %s -> %s", buf, fullname); + goto errout; + } + +errout: + free(buf); +} + +static int rdump_dirent(struct ext2_dir_entry *, int, int, char *, void *); + +static void rdump_inode(ext2_ino_t ino, struct ext2_inode *inode, + const char *name, const char *dumproot) +{ + char *fullname; + + /* There are more efficient ways to do this, but this method + * requires only minimal debugging. */ + fullname = malloc(strlen(dumproot) + strlen(name) + 2); + if (!fullname) { + com_err("rdump", errno, "while allocating memory"); + return; + } + sprintf(fullname, "%s/%s", dumproot, name); + + if (LINUX_S_ISLNK(inode->i_mode)) + rdump_symlink(ino, inode, fullname); + else if (LINUX_S_ISREG(inode->i_mode)) { + int fd; + fd = open(fullname, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRWXU); + if (fd == -1) { + com_err("rdump", errno, "while opening %s", fullname); + goto errout; + } + dump_file("rdump", ino, fd, 1, fullname); + if (close(fd) != 0) { + com_err("rdump", errno, "while closing %s", fullname); + goto errout; + } + } + else if (LINUX_S_ISDIR(inode->i_mode) && strcmp(name, ".") && strcmp(name, "..")) { + errcode_t retval; + + /* Create the directory with 0700 permissions, because we + * expect to have to create entries it. Then fix its perms + * once we've done the traversal. */ + if (mkdir(fullname, S_IRWXU) == -1) { + com_err("rdump", errno, "while making directory %s", fullname); + goto errout; + } + + retval = ext2fs_dir_iterate(current_fs, ino, 0, 0, + rdump_dirent, (void *) fullname); + if (retval) + com_err("rdump", retval, "while dumping %s", fullname); + + fix_perms("rdump", inode, -1, fullname); + } + /* else do nothing (don't dump device files, sockets, fifos, etc.) */ + +errout: + free(fullname); +} + +static int rdump_dirent(struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), void *private) +{ + char name[EXT2_NAME_LEN + 1]; + int thislen; + const char *dumproot = private; + struct ext2_inode inode; + + thislen = dirent->name_len & 0xFF; + strncpy(name, dirent->name, thislen); + name[thislen] = 0; + + if (debugfs_read_inode(dirent->inode, &inode, name)) + return 0; + + rdump_inode(dirent->inode, &inode, name, dumproot); + + return 0; +} + +void do_rdump(int argc, char **argv) +{ + struct stat st; + char *dest_dir; + int i; + + if (common_args_process(argc, argv, 3, INT_MAX, "rdump", + "<directory>... <native directory>", 0)) + return; + + /* Pull out last argument */ + dest_dir = argv[argc - 1]; + argc--; + + /* Ensure last arg is a directory. */ + if (stat(dest_dir, &st) == -1) { + com_err("rdump", errno, "while statting %s", dest_dir); + return; + } + if (!S_ISDIR(st.st_mode)) { + com_err("rdump", 0, "%s is not a directory", dest_dir); + return; + } + + for (i = 1; i < argc; i++) { + char *arg = argv[i], *basename; + struct ext2_inode inode; + ext2_ino_t ino = string_to_inode(arg); + if (!ino) + continue; + + if (debugfs_read_inode(ino, &inode, arg)) + continue; + + basename = strrchr(arg, '/'); + if (basename) + basename++; + else + basename = arg; + + rdump_inode(ino, &inode, basename, dest_dir); + } +} + +void do_cat(int argc, char **argv) +{ + ext2_ino_t inode; + + if (common_inode_args_process(argc, argv, &inode, 0)) + return; + + fflush(stdout); + fflush(stderr); + dump_file(argv[0], inode, 1, 0, argv[2]); + + return; +} +
diff --git a/debugfs/extent_cmds.ct b/debugfs/extent_cmds.ct new file mode 100644 index 0000000..e1c4395 --- /dev/null +++ b/debugfs/extent_cmds.ct
@@ -0,0 +1,77 @@ +# +# Copyright (C) 1993 Theodore Ts'o. This file may be redistributed +# under the terms of the GNU Public License. +# +command_table extent_cmds; + +request do_current_node, "Current extent node", + current_node, current; + +request do_root_node, "Goto root extent", + root_node, root; + +request do_last_leaf, "Goto last leaf", + last_leaf; + +request do_first_sib, "Goto first sibling", + first_sibling, first_sib; + +request do_last_sib, "Goto last sibling", + last_sibling, last_sib; + +request do_next_sib, "Goto next sibling", + next_sibling, next_sib, ns; + +request do_prev_sib, "Goto previous sibling", + prev_sibling, prev_sib, ps; + +request do_next_leaf, "Goto next leaf", + next_leaf, nl; + +request do_prev_leaf, "Goto previous leaf", + prev_leaf, pl; + +request do_next, "Goto next node", + next, n; + +request do_prev, "Goto previous node", + previous, prev, p; + +request do_up, "Up node", + up_node, up, u; + +request do_down, "Down node", + down_node, down, d; + +request do_delete_node, "Delete node", + delete_node, delete; + +request do_insert_node, "Insert node", + insert_node, insert; + +request do_split_node, "Split node", + split_node, split; + +request do_fix_parents, "Fix parents", + fix_parents, fixp; + +request do_set_bmap, "Set block mapping", + set_bmap; + +request do_replace_node, "Insert node", + replace_node, replace; + +request do_print_all, "Iterate over all nodes and print them", + print_all, all; + +request do_goto_block, "Goto extent containing specified block", + goto_block, goto; + +request do_info, "Print extent info", + info; + +request do_extent_close, "Close extent handle", + extent_close, ec; + +end; +
diff --git a/debugfs/extent_inode.c b/debugfs/extent_inode.c new file mode 100644 index 0000000..8b22f5e --- /dev/null +++ b/debugfs/extent_inode.c
@@ -0,0 +1,537 @@ +/* + * extent_inode.c --- direct extent tree manipulation + * + * Copyright (C) 2012 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif + +#include "debugfs.h" + +static ext2_ino_t current_ino; +static ext2_extent_handle_t current_handle; + +static void dbg_print_extent(char *desc, struct ext2fs_extent *extent) +{ + if (desc) + printf("%s: ", desc); + printf("extent: lblk %llu--%llu, len %u, pblk %llu, flags: ", + extent->e_lblk, extent->e_lblk + extent->e_len - 1, + extent->e_len, extent->e_pblk); + if (extent->e_flags & EXT2_EXTENT_FLAGS_LEAF) + fputs("LEAF ", stdout); + if (extent->e_flags & EXT2_EXTENT_FLAGS_UNINIT) + fputs("UNINIT ", stdout); + if (extent->e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) + fputs("2ND_VISIT ", stdout); + if (!extent->e_flags) + fputs("(none)", stdout); + fputc('\n', stdout); + +} + +static int common_extent_args_process(int argc, char *argv[], int min_argc, + int max_argc, const char *cmd, + const char *usage, int flags) +{ + if (common_args_process(argc, argv, min_argc, max_argc, cmd, + usage, flags)) + return 1; + + if (!current_handle) { + com_err(cmd, 0, "Extent handle not open"); + return 1; + } + return 0; +} + +static char *orig_prompt, *extent_prompt; + +void do_extent_open(int argc, char *argv[]) +{ + ext2_ino_t inode; + int ret; + errcode_t retval; + char *cp; + + if (check_fs_open(argv[0])) + return; + + if (argc == 1) { + if (current_ino) + printf("Current inode is %d\n", current_ino); + else + printf("No current inode\n"); + return; + } + + if (common_inode_args_process(argc, argv, &inode, 0)) + return; + + current_ino = 0; + + retval = ext2fs_extent_open(current_fs, inode, ¤t_handle); + if (retval) { + com_err(argv[1], retval, "while opening extent handle"); + return; + } + + current_ino = inode; + + orig_prompt = ss_get_prompt(sci_idx); + extent_prompt = malloc(strlen(orig_prompt) + 32); + strcpy(extent_prompt, orig_prompt); + cp = strchr(extent_prompt, ':'); + if (cp) + *cp = 0; + sprintf(extent_prompt + strlen(extent_prompt), " (extent ino %d): ", + current_ino); + ss_add_request_table(sci_idx, &extent_cmds, 1, &ret); + ss_set_prompt(sci_idx, extent_prompt); + return; +} + +void do_extent_close(int argc, char *argv[]) +{ + int ret; + + if (common_args_process(argc, argv, 1, 1, + "extent_close", "", 0)) + return; + + if (!current_handle) { + com_err(argv[0], 0, "Extent handle not open"); + return; + } + + ext2fs_extent_free(current_handle); + current_handle = NULL; + current_ino = 0; + ss_delete_request_table(sci_idx, &extent_cmds, &ret); + ss_set_prompt(sci_idx, orig_prompt); + free(extent_prompt); + extent_prompt = NULL; +} + +static void generic_goto_node(const char *my_name, int argc, + char **argv, int op) +{ + struct ext2fs_extent extent; + errcode_t retval; + + if (my_name && common_args_process(argc, argv, 1, 1, + my_name, "", 0)) + return; + + if (!current_handle) { + com_err(argv[0], 0, "Extent handle not open"); + return; + } + + retval = ext2fs_extent_get(current_handle, op, &extent); + if (retval) { + com_err(argv[0], retval, 0); + return; + } + dbg_print_extent(0, &extent); +} + +void do_current_node(int argc, char *argv[]) +{ + generic_goto_node("current_node", argc, argv, EXT2_EXTENT_CURRENT); +} + +void do_root_node(int argc, char *argv[]) +{ + generic_goto_node("root_node", argc, argv, EXT2_EXTENT_ROOT); +} + +void do_last_leaf(int argc, char *argv[]) +{ + generic_goto_node("last_leaf", argc, argv, EXT2_EXTENT_LAST_LEAF); +} + +void do_first_sib(int argc, char *argv[]) +{ + generic_goto_node("first_sib", argc, argv, EXT2_EXTENT_FIRST_SIB); +} + +void do_last_sib(int argc, char *argv[]) +{ + generic_goto_node("next_sib", argc, argv, EXT2_EXTENT_LAST_SIB); +} + +void do_next_sib(int argc, char *argv[]) +{ + generic_goto_node("next_sib", argc, argv, EXT2_EXTENT_NEXT_SIB); +} + +void do_prev_sib(int argc, char *argv[]) +{ + generic_goto_node("prev_sib", argc, argv, EXT2_EXTENT_PREV_SIB); +} + +void do_next_leaf(int argc, char *argv[]) +{ + generic_goto_node("next_leaf", argc, argv, EXT2_EXTENT_NEXT_LEAF); +} + +void do_prev_leaf(int argc, char *argv[]) +{ + generic_goto_node("prev_leaf", argc, argv, EXT2_EXTENT_PREV_LEAF); +} + +void do_next(int argc, char *argv[]) +{ + generic_goto_node("next", argc, argv, EXT2_EXTENT_NEXT); +} + +void do_prev(int argc, char *argv[]) +{ + generic_goto_node("prev", argc, argv, EXT2_EXTENT_PREV); +} + +void do_up(int argc, char *argv[]) +{ + generic_goto_node("up", argc, argv, EXT2_EXTENT_UP); +} + +void do_down(int argc, char *argv[]) +{ + generic_goto_node("down", argc, argv, EXT2_EXTENT_DOWN); +} + +void do_delete_node(int argc, char *argv[]) +{ + struct ext2fs_extent extent; + errcode_t retval; + + if (common_extent_args_process(argc, argv, 1, 1, "delete_node", + "", CHECK_FS_RW | CHECK_FS_BITMAPS)) + return; + + retval = ext2fs_extent_delete(current_handle, 0); + if (retval) { + com_err(argv[0], retval, 0); + return; + } + + retval = ext2fs_extent_get(current_handle, EXT2_EXTENT_CURRENT, + &extent); + if (retval) + return; + dbg_print_extent(0, &extent); +} + +void do_replace_node(int argc, char *argv[]) +{ + const char *usage = "[--uninit] <lblk> <len> <pblk>"; + errcode_t retval; + struct ext2fs_extent extent; + int err; + + if (common_extent_args_process(argc, argv, 3, 5, "replace_node", + usage, CHECK_FS_RW | CHECK_FS_BITMAPS)) + return; + + extent.e_flags = 0; + + if (!strcmp(argv[1], "--uninit")) { + argc--; + argv++; + extent.e_flags |= EXT2_EXTENT_FLAGS_UNINIT; + } + + if (argc != 4) { + fprintf(stderr, "Usage: %s %s\n", argv[0], usage); + return; + } + + err = strtoblk(argv[0], argv[1], "logical block", &extent.e_lblk); + if (err) + return; + + extent.e_len = parse_ulong(argv[2], argv[0], "length", &err); + if (err) + return; + + err = strtoblk(argv[0], argv[3], "physical block", &extent.e_pblk); + if (err) + return; + + retval = ext2fs_extent_replace(current_handle, 0, &extent); + if (retval) { + com_err(argv[0], retval, 0); + return; + } + generic_goto_node(NULL, argc, argv, EXT2_EXTENT_CURRENT); +} + +void do_split_node(int argc, char *argv[]) +{ + errcode_t retval; + + if (common_extent_args_process(argc, argv, 1, 1, "split_node", + "", CHECK_FS_RW | CHECK_FS_BITMAPS)) + return; + + retval = ext2fs_extent_node_split(current_handle); + if (retval) { + com_err(argv[0], retval, 0); + return; + } + generic_goto_node(NULL, argc, argv, EXT2_EXTENT_CURRENT); +} + +void do_insert_node(int argc, char *argv[]) +{ + const char *usage = "[--after] [--uninit] <lblk> <len> <pblk>"; + errcode_t retval; + struct ext2fs_extent extent; + char *cmd; + int err; + int flags = 0; + + if (common_extent_args_process(argc, argv, 3, 6, "insert_node", + usage, CHECK_FS_RW | CHECK_FS_BITMAPS)) + return; + + cmd = argv[0]; + + extent.e_flags = 0; + + while (argc > 2) { + if (!strcmp(argv[1], "--after")) { + argc--; + argv++; + flags |= EXT2_EXTENT_INSERT_AFTER; + continue; + } + if (!strcmp(argv[1], "--uninit")) { + argc--; + argv++; + extent.e_flags |= EXT2_EXTENT_FLAGS_UNINIT; + continue; + } + break; + } + + if (argc != 4) { + fprintf(stderr, "usage: %s %s\n", cmd, usage); + return; + } + + err = strtoblk(cmd, argv[1], "logical block", &extent.e_lblk); + if (err) + return; + + extent.e_len = parse_ulong(argv[2], cmd, "length", &err); + if (err) + return; + + err = strtoblk(cmd, argv[3], "physical block", &extent.e_pblk); + if (err) + return; + + retval = ext2fs_extent_insert(current_handle, flags, &extent); + if (retval) { + com_err(cmd, retval, 0); + return; + } + generic_goto_node(NULL, argc, argv, EXT2_EXTENT_CURRENT); +} + +void do_set_bmap(int argc, char **argv) +{ + const char *usage = "[--uninit] <lblk> <pblk>"; + struct ext2fs_extent extent; + errcode_t retval; + blk64_t logical; + blk64_t physical; + char *cmd = argv[0]; + int flags = 0; + int err; + + if (common_extent_args_process(argc, argv, 3, 5, "set_bmap", + usage, CHECK_FS_RW | CHECK_FS_BITMAPS)) + return; + + if (argc > 2 && !strcmp(argv[1], "--uninit")) { + argc--; + argv++; + flags |= EXT2_EXTENT_SET_BMAP_UNINIT; + } + + if (argc != 3) { + fprintf(stderr, "Usage: %s %s\n", cmd, usage); + return; + } + + err = strtoblk(cmd, argv[1], "logical block", &logical); + if (err) + return; + + err = strtoblk(cmd, argv[2], "physical block", &physical); + if (err) + return; + + retval = ext2fs_extent_set_bmap(current_handle, logical, + physical, flags); + if (retval) { + com_err(cmd, retval, 0); + return; + } + + retval = ext2fs_extent_get(current_handle, EXT2_EXTENT_CURRENT, + &extent); + if (retval) + return; + dbg_print_extent(0, &extent); +} + +void do_print_all(int argc, char **argv) +{ + const char *usage = "[--leaf-only|--reverse|--reverse-leaf]"; + struct ext2fs_extent extent; + errcode_t retval; + errcode_t end_err = EXT2_ET_EXTENT_NO_NEXT; + int op = EXT2_EXTENT_NEXT; + int first_op = EXT2_EXTENT_ROOT; + + + if (common_extent_args_process(argc, argv, 1, 2, "print_all", + usage, 0)) + return; + + if (argc == 2) { + if (!strcmp(argv[1], "--leaf-only")) + op = EXT2_EXTENT_NEXT_LEAF; + else if (!strcmp(argv[1], "--reverse")) { + op = EXT2_EXTENT_PREV; + first_op = EXT2_EXTENT_LAST_LEAF; + end_err = EXT2_ET_EXTENT_NO_PREV; + } else if (!strcmp(argv[1], "--reverse-leaf")) { + op = EXT2_EXTENT_PREV_LEAF; + first_op = EXT2_EXTENT_LAST_LEAF; + end_err = EXT2_ET_EXTENT_NO_PREV; + } else { + fprintf(stderr, "Usage: %s %s\n", argv[0], usage); + return; + } + } + + retval = ext2fs_extent_get(current_handle, first_op, &extent); + if (retval) { + com_err(argv[0], retval, 0); + return; + } + dbg_print_extent(0, &extent); + + while (1) { + retval = ext2fs_extent_get(current_handle, op, &extent); + if (retval == end_err) + break; + + if (retval) { + com_err(argv[0], retval, 0); + return; + } + dbg_print_extent(0, &extent); + } +} + +void do_fix_parents(int argc, char **argv) +{ + errcode_t retval; + + if (common_extent_args_process(argc, argv, 1, 1, "fix_parents", "", + CHECK_FS_RW)) + return; + + retval = ext2fs_extent_fix_parents(current_handle); + if (retval) { + com_err(argv[0], retval, 0); + return; + } +} + +void do_info(int argc, char **argv) +{ + struct ext2fs_extent extent; + struct ext2_extent_info info; + errcode_t retval; + + if (common_extent_args_process(argc, argv, 1, 1, "info", "", 0)) + return; + + retval = ext2fs_extent_get_info(current_handle, &info); + if (retval) { + com_err(argv[0], retval, 0); + return; + } + + retval = ext2fs_extent_get(current_handle, + EXT2_EXTENT_CURRENT, &extent); + if (retval) { + com_err(argv[0], retval, 0); + return; + } + + dbg_print_extent(0, &extent); + + printf("Current handle location: %d/%d (max: %d, bytes %d), level %d/%d\n", + info.curr_entry, info.num_entries, info.max_entries, + info.bytes_avail, info.curr_level, info.max_depth); + printf("\tmax lblk: %llu, max pblk: %llu\n", info.max_lblk, + info.max_pblk); + printf("\tmax_len: %u, max_uninit_len: %u\n", info.max_len, + info.max_uninit_len); +} + +void do_goto_block(int argc, char **argv) +{ + errcode_t retval; + blk64_t blk; + int level = 0, err; + + if (common_extent_args_process(argc, argv, 2, 3, "goto_block", + "block [level]", 0)) + return; + + if (strtoblk(argv[0], argv[1], NULL, &blk)) + return; + + if (argc == 3) { + level = parse_ulong(argv[2], argv[0], "level", &err); + if (err) + return; + } + + retval = ext2fs_extent_goto2(current_handle, level, (blk64_t) blk); + + if (retval) { + com_err(argv[0], retval, + "while trying to go to block %llu, level %d", + (unsigned long long) blk, level); + return; + } + + generic_goto_node(NULL, argc, argv, EXT2_EXTENT_CURRENT); +}
diff --git a/debugfs/filefrag.c b/debugfs/filefrag.c new file mode 100644 index 0000000..0adea40 --- /dev/null +++ b/debugfs/filefrag.c
@@ -0,0 +1,324 @@ +/* + * filefrag.c --- display the fragmentation information for a file + * + * Copyright (C) 2011 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <utime.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif + +#include "debugfs.h" + +#define VERBOSE_OPT 0x0001 +#define DIR_OPT 0x0002 +#define RECURSIVE_OPT 0x0004 + +struct dir_list { + char *name; + ext2_ino_t ino; + struct dir_list *next; +}; + +struct filefrag_struct { + FILE *f; + const char *name; + const char *dir_name; + int options; + int logical_width; + int physical_width; + int ext; + int cont_ext; + e2_blkcnt_t num; + e2_blkcnt_t logical_start; + blk64_t physical_start; + blk64_t expected; + struct dir_list *dir_list, *dir_last; +}; + +static int int_log10(unsigned long long arg) +{ + int l = 0; + + arg = arg / 10; + while (arg) { + l++; + arg = arg / 10; + } + return l; +} + +static void print_header(struct filefrag_struct *fs) +{ + if (fs->options & VERBOSE_OPT) { + fprintf(fs->f, "%4s %*s %*s %*s %*s\n", "ext", + fs->logical_width, "logical", fs->physical_width, + "physical", fs->physical_width, "expected", + fs->logical_width, "length"); + } +} + +static void report_filefrag(struct filefrag_struct *fs) +{ + if (fs->num == 0) + return; + if (fs->options & VERBOSE_OPT) { + if (fs->expected) + fprintf(fs->f, "%4d %*lu %*llu %*llu %*lu\n", fs->ext, + fs->logical_width, + (unsigned long) fs->logical_start, + fs->physical_width, fs->physical_start, + fs->physical_width, fs->expected, + fs->logical_width, (unsigned long) fs->num); + else + fprintf(fs->f, "%4d %*lu %*llu %*s %*lu\n", fs->ext, + fs->logical_width, + (unsigned long) fs->logical_start, + fs->physical_width, fs->physical_start, + fs->physical_width, "", + fs->logical_width, (unsigned long) fs->num); + } + fs->ext++; +} + +static int filefrag_blocks_proc(ext2_filsys ext4_fs EXT2FS_ATTR((unused)), + blk64_t *blocknr, e2_blkcnt_t blockcnt, + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *private) +{ + struct filefrag_struct *fs = private; + + if (blockcnt < 0 || *blocknr == 0) + return 0; + + if ((fs->num == 0) || (blockcnt != fs->logical_start + fs->num) || + (*blocknr != fs->physical_start + fs->num)) { + report_filefrag(fs); + if (blockcnt == fs->logical_start + fs->num) + fs->expected = fs->physical_start + fs->num; + else + fs->expected = 0; + fs->logical_start = blockcnt; + fs->physical_start = *blocknr; + fs->num = 1; + fs->cont_ext++; + } else + fs->num++; + return 0; +} + +static void filefrag(ext2_ino_t ino, struct ext2_inode *inode, + struct filefrag_struct *fs) +{ + errcode_t retval; + int blocksize = current_fs->blocksize; + + fs->logical_width = int_log10((EXT2_I_SIZE(inode) + blocksize - 1) / + blocksize) + 1; + if (fs->logical_width < 7) + fs->logical_width = 7; + fs->ext = 0; + fs->cont_ext = 0; + fs->logical_start = 0; + fs->physical_start = 0; + fs->num = 0; + + if (fs->options & VERBOSE_OPT) { + blk64_t num_blocks = ext2fs_inode_i_blocks(current_fs, inode); + + if (!(current_fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_HUGE_FILE) || + !(inode->i_flags & EXT4_HUGE_FILE_FL)) + num_blocks /= current_fs->blocksize / 512; + + fprintf(fs->f, "\n%s has %llu block(s), i_size is %llu\n", + fs->name, num_blocks, EXT2_I_SIZE(inode)); + } + print_header(fs); + retval = ext2fs_block_iterate3(current_fs, ino, + BLOCK_FLAG_READ_ONLY, NULL, + filefrag_blocks_proc, fs); + if (retval) + com_err("ext2fs_block_iterate3", retval, 0); + + report_filefrag(fs); + fprintf(fs->f, "%s: %d contiguous extents%s\n", fs->name, fs->ext, + LINUX_S_ISDIR(inode->i_mode) ? " (dir)" : ""); +} + +static int filefrag_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)), + int entry, + struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *private) +{ + struct filefrag_struct *fs = private; + struct ext2_inode inode; + ext2_ino_t ino; + char name[EXT2_NAME_LEN + 1]; + char *cp; + int thislen; + + if (entry == DIRENT_DELETED_FILE) + return 0; + + thislen = dirent->name_len & 0xFF; + strncpy(name, dirent->name, thislen); + name[thislen] = '\0'; + ino = dirent->inode; + + if (!strcmp(name, ".") || !strcmp(name, "..")) + return 0; + + cp = malloc(strlen(fs->dir_name) + strlen(name) + 2); + if (!cp) { + fprintf(stderr, "Couldn't allocate memory for %s/%s\n", + fs->dir_name, name); + return 0; + } + + sprintf(cp, "%s/%s", fs->dir_name, name); + fs->name = cp; + + if (debugfs_read_inode(ino, &inode, fs->name)) + goto errout; + + filefrag(ino, &inode, fs); + + if ((fs->options & RECURSIVE_OPT) && LINUX_S_ISDIR(inode.i_mode)) { + struct dir_list *p; + + p = malloc(sizeof(struct dir_list)); + if (!p) { + fprintf(stderr, "Couldn't allocate dir_list for %s\n", + fs->name); + goto errout; + } + memset(p, 0, sizeof(struct dir_list)); + p->name = cp; + p->ino = ino; + if (fs->dir_last) + fs->dir_last->next = p; + else + fs->dir_list = p; + fs->dir_last = p; + return 0; + } +errout: + free(cp); + fs->name = 0; + return 0; +} + + +static void dir_iterate(ext2_ino_t ino, struct filefrag_struct *fs) +{ + errcode_t retval; + struct dir_list *p = NULL; + + fs->dir_name = fs->name; + + while (1) { + retval = ext2fs_dir_iterate2(current_fs, ino, 0, + 0, filefrag_dir_proc, fs); + if (retval) + com_err("ext2fs_dir_iterate2", retval, 0); + if (p) { + free(p->name); + fs->dir_list = p->next; + if (!fs->dir_list) + fs->dir_last = 0; + free(p); + } + p = fs->dir_list; + if (!p) + break; + ino = p->ino; + fs->dir_name = p->name; + } +} + +void do_filefrag(int argc, char *argv[]) +{ + struct filefrag_struct fs; + struct ext2_inode inode; + ext2_ino_t ino; + int c; + + memset(&fs, 0, sizeof(fs)); + if (check_fs_open(argv[0])) + return; + + reset_getopt(); + while ((c = getopt(argc, argv, "dvr")) != EOF) { + switch (c) { + case 'd': + fs.options |= DIR_OPT; + break; + case 'v': + fs.options |= VERBOSE_OPT; + break; + case 'r': + fs.options |= RECURSIVE_OPT; + break; + default: + goto print_usage; + } + } + + if (argc > optind+1) { + print_usage: + com_err(0, 0, "Usage: filefrag [-dvr] file"); + return; + } + + if (argc == optind) { + ino = cwd; + fs.name = "."; + } else { + ino = string_to_inode(argv[optind]); + fs.name = argv[optind]; + } + if (!ino) + return; + + if (debugfs_read_inode(ino, &inode, argv[0])) + return; + + fs.f = open_pager(); + fs.physical_width = int_log10(ext2fs_blocks_count(current_fs->super)); + fs.physical_width++; + if (fs.physical_width < 8) + fs.physical_width = 8; + + if (!LINUX_S_ISDIR(inode.i_mode) || (fs.options & DIR_OPT)) + filefrag(ino, &inode, &fs); + else + dir_iterate(ino, &fs); + + fprintf(fs.f, "\n"); + close_pager(fs.f); + + return; +}
diff --git a/debugfs/htree.c b/debugfs/htree.c new file mode 100644 index 0000000..24f8250 --- /dev/null +++ b/debugfs/htree.c
@@ -0,0 +1,409 @@ +/* + * htree.c --- hash tree routines + * + * Copyright (C) 2002 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif + +#include "debugfs.h" +#include "uuid/uuid.h" +#include "e2p/e2p.h" + +static FILE *pager; + +static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + struct ext2_dx_root_info * rootnode, + blk64_t blk, char *buf) +{ + errcode_t errcode; + struct ext2_dir_entry *dirent; + int thislen, col = 0; + unsigned int offset = 0; + char name[EXT2_NAME_LEN + 1]; + char tmp[EXT2_NAME_LEN + 64]; + blk64_t pblk; + ext2_dirhash_t hash, minor_hash; + unsigned int rec_len; + int hash_alg; + + errcode = ext2fs_bmap2(fs, ino, inode, buf, 0, blk, 0, &pblk); + if (errcode) { + com_err("htree_dump_leaf_node", errcode, + "while mapping logical block %llu\n", blk); + return; + } + + fprintf(pager, "Reading directory block %llu, phys %llu\n", blk, pblk); + errcode = ext2fs_read_dir_block2(current_fs, pblk, buf, 0); + if (errcode) { + com_err("htree_dump_leaf_node", errcode, + "while reading block %llu (%llu)\n", + blk, pblk); + return; + } + hash_alg = rootnode->hash_version; + if ((hash_alg <= EXT2_HASH_TEA) && + (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) + hash_alg += 3; + + while (offset < fs->blocksize) { + dirent = (struct ext2_dir_entry *) (buf + offset); + errcode = ext2fs_get_rec_len(fs, dirent, &rec_len); + if (errcode) { + com_err("htree_dump_leaf_inode", errcode, + "while getting rec_len for block %lu", + (unsigned long) blk); + return; + } + if (((offset + rec_len) > fs->blocksize) || + (rec_len < 8) || + ((rec_len % 4) != 0) || + ((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) { + fprintf(pager, "Corrupted directory block (%llu)!\n", + blk); + break; + } + thislen = dirent->name_len & 0xFF; + strncpy(name, dirent->name, thislen); + name[thislen] = '\0'; + errcode = ext2fs_dirhash(hash_alg, name, + thislen, fs->super->s_hash_seed, + &hash, &minor_hash); + if (errcode) + com_err("htree_dump_leaf_node", errcode, + "while calculating hash"); + snprintf(tmp, EXT2_NAME_LEN + 64, "%u 0x%08x-%08x (%d) %s ", + dirent->inode, hash, minor_hash, rec_len, name); + thislen = strlen(tmp); + if (col + thislen > 80) { + fprintf(pager, "\n"); + col = 0; + } + fprintf(pager, "%s", tmp); + col += thislen; + offset += rec_len; + } + fprintf(pager, "\n"); +} + + +static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + struct ext2_dx_root_info * rootnode, + blk64_t blk, char *buf, int level); + + +static void htree_dump_int_node(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + struct ext2_dx_root_info * rootnode, + struct ext2_dx_entry *ent, + char *buf, int level) +{ + struct ext2_dx_countlimit limit; + struct ext2_dx_entry e; + int hash, i; + + + limit = *((struct ext2_dx_countlimit *) ent); + limit.count = ext2fs_le16_to_cpu(limit.count); + limit.limit = ext2fs_le16_to_cpu(limit.limit); + + fprintf(pager, "Number of entries (count): %d\n", limit.count); + fprintf(pager, "Number of entries (limit): %d\n", limit.limit); + + for (i=0; i < limit.count; i++) { + hash = i ? ext2fs_le32_to_cpu(ent[i].hash) : 0; + fprintf(pager, "Entry #%d: Hash 0x%08x%s, block %u\n", i, + hash, (hash & 1) ? " (**)" : "", + ext2fs_le32_to_cpu(ent[i].block)); + } + + fprintf(pager, "\n"); + + for (i=0; i < limit.count; i++) { + e.hash = ext2fs_le32_to_cpu(ent[i].hash); + e.block = ext2fs_le32_to_cpu(ent[i].block); + fprintf(pager, "Entry #%d: Hash 0x%08x, block %u\n", i, + i ? e.hash : 0, e.block); + if (level) + htree_dump_int_block(fs, ino, inode, rootnode, + e.block, buf, level-1); + else + htree_dump_leaf_node(fs, ino, inode, rootnode, + e.block, buf); + } + + fprintf(pager, "---------------------\n"); +} + +static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, + struct ext2_dx_root_info * rootnode, + blk64_t blk, char *buf, int level) +{ + char *cbuf; + errcode_t errcode; + blk64_t pblk; + + cbuf = malloc(fs->blocksize); + if (!cbuf) { + fprintf(pager, "Couldn't allocate child block.\n"); + return; + } + + errcode = ext2fs_bmap2(fs, ino, inode, buf, 0, blk, 0, &pblk); + if (errcode) { + com_err("htree_dump_int_block", errcode, + "while mapping logical block %llu\n", blk); + goto errout; + } + + errcode = io_channel_read_blk64(current_fs->io, pblk, 1, buf); + if (errcode) { + com_err("htree_dump_int_block", errcode, + "while reading block %llu\n", blk); + goto errout; + } + + htree_dump_int_node(fs, ino, inode, rootnode, + (struct ext2_dx_entry *) (buf+8), + cbuf, level); +errout: + free(cbuf); +} + + + +void do_htree_dump(int argc, char *argv[]) +{ + ext2_ino_t ino; + struct ext2_inode inode; + blk64_t blk; + char *buf = NULL; + struct ext2_dx_root_info *rootnode; + struct ext2_dx_entry *ent; + errcode_t errcode; + + if (check_fs_open(argv[0])) + return; + + pager = open_pager(); + + if (common_inode_args_process(argc, argv, &ino, 0)) + goto errout; + + if (debugfs_read_inode(ino, &inode, argv[1])) + goto errout; + + if (!LINUX_S_ISDIR(inode.i_mode)) { + com_err(argv[0], 0, "Not a directory"); + goto errout; + } + + if ((inode.i_flags & EXT2_BTREE_FL) == 0) { + com_err(argv[0], 0, "Not a hash-indexed directory"); + goto errout; + } + + buf = malloc(2*current_fs->blocksize); + if (!buf) { + com_err(argv[0], 0, "Couldn't allocate htree buffer"); + goto errout; + } + + errcode = ext2fs_bmap2(current_fs, ino, &inode, buf, 0, 0, 0, &blk); + if (errcode) { + com_err("do_htree_block", errcode, + "while mapping logical block 0\n"); + goto errout; + } + + errcode = io_channel_read_blk64(current_fs->io, blk, + 1, buf); + if (errcode) { + com_err(argv[0], errcode, "Error reading root node"); + goto errout; + } + + rootnode = (struct ext2_dx_root_info *) (buf + 24); + + fprintf(pager, "Root node dump:\n"); + fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero); + fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version); + fprintf(pager, "\t Info length: %d\n", rootnode->info_length); + fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels); + fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags); + + ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length); + + htree_dump_int_node(current_fs, ino, &inode, rootnode, ent, + buf + current_fs->blocksize, + rootnode->indirect_levels); + +errout: + free(buf); + close_pager(pager); +} + +/* + * This function prints the hash of a given file. + */ +void do_dx_hash(int argc, char *argv[]) +{ + ext2_dirhash_t hash, minor_hash; + errcode_t err; + int c; + int hash_version = 0; + __u32 hash_seed[4]; + + hash_seed[0] = hash_seed[1] = hash_seed[2] = hash_seed[3] = 0; + + reset_getopt(); + while ((c = getopt (argc, argv, "h:s:")) != EOF) { + switch (c) { + case 'h': + hash_version = e2p_string2hash(optarg); + if (hash_version < 0) + hash_version = atoi(optarg); + break; + case 's': + if (uuid_parse(optarg, (unsigned char *) hash_seed)) { + fprintf(stderr, "Invalid UUID format: %s\n", + optarg); + return; + } + break; + default: + goto print_usage; + } + } + if (optind != argc-1) { + print_usage: + com_err(argv[0], 0, "usage: dx_hash [-h hash_alg] " + "[-s hash_seed] filename"); + return; + } + err = ext2fs_dirhash(hash_version, argv[optind], strlen(argv[optind]), + hash_seed, &hash, &minor_hash); + if (err) { + com_err(argv[0], err, "while caclulating hash"); + return; + } + printf("Hash of %s is 0x%0x (minor 0x%0x)\n", argv[optind], + hash, minor_hash); +} + +/* + * Search for particular directory entry (useful for debugging very + * large hash tree directories that have lost some blocks from the + * btree index). + */ +struct process_block_struct { + char *search_name; + char *buf; + int len; +}; + +static int search_dir_block(ext2_filsys fs, blk64_t *blocknr, + e2_blkcnt_t blockcnt, blk64_t ref_blk, + int ref_offset, void *priv_data); + +void do_dirsearch(int argc, char *argv[]) +{ + ext2_ino_t inode; + struct process_block_struct pb; + + if (check_fs_open(argv[0])) + return; + + if (argc != 3) { + com_err(0, 0, "Usage: dirsearch dir filename"); + return; + } + + inode = string_to_inode(argv[1]); + if (!inode) + return; + + pb.buf = malloc(current_fs->blocksize); + if (!pb.buf) { + com_err("dirsearch", 0, "Couldn't allocate buffer"); + return; + } + pb.search_name = argv[2]; + pb.len = strlen(pb.search_name); + + ext2fs_block_iterate3(current_fs, inode, BLOCK_FLAG_READ_ONLY, 0, + search_dir_block, &pb); + + free(pb.buf); +} + + +static int search_dir_block(ext2_filsys fs, blk64_t *blocknr, + e2_blkcnt_t blockcnt, + blk64_t ref_blk EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct process_block_struct *p; + struct ext2_dir_entry *dirent; + errcode_t errcode; + unsigned int offset = 0; + unsigned int rec_len; + + if (blockcnt < 0) + return 0; + + p = (struct process_block_struct *) priv_data; + + errcode = io_channel_read_blk64(current_fs->io, *blocknr, 1, p->buf); + if (errcode) { + com_err("search_dir_block", errcode, + "while reading block %lu", (unsigned long) *blocknr); + return BLOCK_ABORT; + } + + while (offset < fs->blocksize) { + dirent = (struct ext2_dir_entry *) (p->buf + offset); + errcode = ext2fs_get_rec_len(fs, dirent, &rec_len); + if (errcode) { + com_err("htree_dump_leaf_inode", errcode, + "while getting rec_len for block %lu", + (unsigned long) *blocknr); + return BLOCK_ABORT; + } + if (dirent->inode && + p->len == (dirent->name_len & 0xFF) && + strncmp(p->search_name, dirent->name, + p->len) == 0) { + printf("Entry found at logical block %lld, " + "phys %llu, offset %u\n", (long long)blockcnt, + *blocknr, offset); + printf("offset %u\n", offset); + return BLOCK_ABORT; + } + offset += rec_len; + } + return 0; +} +
diff --git a/debugfs/icheck.c b/debugfs/icheck.c new file mode 100644 index 0000000..3b9bd14 --- /dev/null +++ b/debugfs/icheck.c
@@ -0,0 +1,173 @@ +/* + * icheck.c --- given a list of blocks, generate a list of inodes + * + * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> + +#include "debugfs.h" + +struct block_info { + blk64_t blk; + ext2_ino_t ino; +}; + +struct block_walk_struct { + struct block_info *barray; + e2_blkcnt_t blocks_left; + e2_blkcnt_t num_blocks; + ext2_ino_t inode; +}; + +static int icheck_proc(ext2_filsys fs EXT2FS_ATTR((unused)), + blk64_t *block_nr, + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *private) +{ + struct block_walk_struct *bw = (struct block_walk_struct *) private; + e2_blkcnt_t i; + + for (i=0; i < bw->num_blocks; i++) { + if (!bw->barray[i].ino && bw->barray[i].blk == *block_nr) { + bw->barray[i].ino = bw->inode; + bw->blocks_left--; + } + } + if (!bw->blocks_left) + return BLOCK_ABORT; + + return 0; +} + +void do_icheck(int argc, char **argv) +{ + struct block_walk_struct bw; + struct block_info *binfo; + int i; + ext2_inode_scan scan = 0; + ext2_ino_t ino; + struct ext2_inode inode; + errcode_t retval; + char *block_buf; + + if (argc < 2) { + com_err(argv[0], 0, "Usage: icheck <block number> ..."); + return; + } + if (check_fs_open(argv[0])) + return; + + bw.barray = malloc(sizeof(struct block_info) * argc); + if (!bw.barray) { + com_err("icheck", ENOMEM, + "while allocating inode info array"); + return; + } + memset(bw.barray, 0, sizeof(struct block_info) * argc); + + block_buf = malloc(current_fs->blocksize * 3); + if (!block_buf) { + com_err("icheck", ENOMEM, "while allocating block buffer"); + goto error_out; + } + + for (i=1; i < argc; i++) { + if (strtoblk(argv[0], argv[i], NULL, &bw.barray[i-1].blk)) + goto error_out; + } + + bw.num_blocks = bw.blocks_left = argc-1; + + retval = ext2fs_open_inode_scan(current_fs, 0, &scan); + if (retval) { + com_err("icheck", retval, "while opening inode scan"); + goto error_out; + } + + do { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); + if (retval) { + com_err("icheck", retval, "while starting inode scan"); + goto error_out; + } + + while (ino) { + blk64_t blk; + + if (!inode.i_links_count) + goto next; + + bw.inode = ino; + + blk = ext2fs_file_acl_block(current_fs, &inode); + if (blk) { + icheck_proc(current_fs, &blk, 0, + 0, 0, &bw); + if (bw.blocks_left == 0) + break; + ext2fs_file_acl_block_set(current_fs, &inode, blk); + } + + if (!ext2fs_inode_has_valid_blocks2(current_fs, &inode)) + goto next; + /* + * To handle filesystems touched by 0.3c extfs; can be + * removed later. + */ + if (inode.i_dtime) + goto next; + + retval = ext2fs_block_iterate3(current_fs, ino, + BLOCK_FLAG_READ_ONLY, block_buf, + icheck_proc, &bw); + if (retval) { + com_err("icheck", retval, + "while calling ext2fs_block_iterate"); + goto next; + } + + if (bw.blocks_left == 0) + break; + + next: + do { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); + if (retval) { + com_err("icheck", retval, + "while doing inode scan"); + goto error_out; + } + } + + printf("Block\tInode number\n"); + for (i=0, binfo = bw.barray; i < bw.num_blocks; i++, binfo++) { + if (binfo->ino == 0) { + printf("%llu\t<block not found>\n", binfo->blk); + continue; + } + printf("%llu\t%u\n", binfo->blk, binfo->ino); + } + +error_out: + free(bw.barray); + free(block_buf); + if (scan) + ext2fs_close_inode_scan(scan); + return; +}
diff --git a/debugfs/jfs_user.h b/debugfs/jfs_user.h new file mode 100644 index 0000000..3070cd5 --- /dev/null +++ b/debugfs/jfs_user.h
@@ -0,0 +1,8 @@ +#ifndef _JFS_USER_H +#define _JFS_USER_H + +typedef unsigned short kdev_t; + +#include <ext2fs/kernel-jbd.h> + +#endif /* _JFS_USER_H */
diff --git a/debugfs/logdump.c b/debugfs/logdump.c new file mode 100644 index 0000000..d2c3b30 --- /dev/null +++ b/debugfs/logdump.c
@@ -0,0 +1,696 @@ +/* + * logdump.c --- dump the contents of the journal out to a file + * + * Authro: Stephen C. Tweedie, 2001 <sct@redhat.com> + * Copyright (C) 2001 Red Hat, Inc. + * Based on portions Copyright (C) 1994 Theodore Ts'o. + * + * This file may be redistributed under the terms of the GNU Public + * License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <utime.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif + +#include "debugfs.h" +#include "blkid/blkid.h" +#include "jfs_user.h" +#include <uuid/uuid.h> + +enum journal_location {JOURNAL_IS_INTERNAL, JOURNAL_IS_EXTERNAL}; + +#define ANY_BLOCK ((blk64_t) -1) + +static int dump_all, dump_contents, dump_descriptors; +static blk64_t block_to_dump, bitmap_to_dump, inode_block_to_dump; +static unsigned int group_to_dump, inode_offset_to_dump; +static ext2_ino_t inode_to_dump; + +struct journal_source +{ + enum journal_location where; + int fd; + ext2_file_t file; +}; + +static void dump_journal(char *, FILE *, struct journal_source *); + +static void dump_descriptor_block(FILE *, struct journal_source *, + char *, journal_superblock_t *, + unsigned int *, int, tid_t); + +static void dump_revoke_block(FILE *, char *, journal_superblock_t *, + unsigned int, int, tid_t); + +static void dump_metadata_block(FILE *, struct journal_source *, + journal_superblock_t*, + unsigned int, unsigned int, unsigned int, + int, tid_t); + +static void do_hexdump (FILE *, char *, int); + +#define WRAP(jsb, blocknr) \ + if (blocknr >= be32_to_cpu((jsb)->s_maxlen)) \ + blocknr -= (be32_to_cpu((jsb)->s_maxlen) - \ + be32_to_cpu((jsb)->s_first)); + +void do_logdump(int argc, char **argv) +{ + int c; + int retval; + char *out_fn; + FILE *out_file; + + char *inode_spec = NULL; + char *journal_fn = NULL; + int journal_fd = 0; + int use_sb = 0; + ext2_ino_t journal_inum; + struct ext2_inode journal_inode; + ext2_file_t journal_file; + char *tmp; + struct journal_source journal_source; + struct ext2_super_block *es = NULL; + + journal_source.where = JOURNAL_IS_INTERNAL; + journal_source.fd = 0; + journal_source.file = 0; + dump_all = 0; + dump_contents = 0; + dump_descriptors = 1; + block_to_dump = ANY_BLOCK; + bitmap_to_dump = -1; + inode_block_to_dump = ANY_BLOCK; + inode_to_dump = -1; + + reset_getopt(); + while ((c = getopt (argc, argv, "ab:ci:f:s")) != EOF) { + switch (c) { + case 'a': + dump_all++; + break; + case 'b': + block_to_dump = strtoul(optarg, &tmp, 0); + if (*tmp) { + com_err(argv[0], 0, + "Bad block number - %s", optarg); + return; + } + dump_descriptors = 0; + break; + case 'c': + dump_contents++; + break; + case 'f': + journal_fn = optarg; + break; + case 'i': + inode_spec = optarg; + dump_descriptors = 0; + break; + case 's': + use_sb++; + break; + default: + goto print_usage; + } + } + if (optind != argc && optind != argc-1) { + goto print_usage; + } + + if (current_fs) + es = current_fs->super; + + if (inode_spec) { + int inode_group, group_offset, inodes_per_block; + + if (check_fs_open(argv[0])) + return; + + inode_to_dump = string_to_inode(inode_spec); + if (!inode_to_dump) + return; + + inode_group = ((inode_to_dump - 1) + / es->s_inodes_per_group); + group_offset = ((inode_to_dump - 1) + % es->s_inodes_per_group); + inodes_per_block = (current_fs->blocksize + / sizeof(struct ext2_inode)); + + inode_block_to_dump = + ext2fs_inode_table_loc(current_fs, inode_group) + + (group_offset / inodes_per_block); + inode_offset_to_dump = ((group_offset % inodes_per_block) + * sizeof(struct ext2_inode)); + printf("Inode %u is at group %u, block %llu, offset %u\n", + inode_to_dump, inode_group, + inode_block_to_dump, inode_offset_to_dump); + } + + if (optind == argc) { + out_file = stdout; + } else { + out_fn = argv[optind]; + out_file = fopen(out_fn, "w"); + if (!out_file) { + com_err(argv[0], errno, "while opening %s for logdump", + out_fn); + goto errout; + } + } + + if (block_to_dump != ANY_BLOCK && current_fs != NULL) { + group_to_dump = ((block_to_dump - + es->s_first_data_block) + / es->s_blocks_per_group); + bitmap_to_dump = ext2fs_block_bitmap_loc(current_fs, group_to_dump); + } + + if (!journal_fn && check_fs_open(argv[0])) + goto errout; + + if (journal_fn) { + /* Set up to read journal from a regular file somewhere */ + journal_fd = open(journal_fn, O_RDONLY, 0); + if (journal_fd < 0) { + com_err(argv[0], errno, "while opening %s for logdump", + journal_fn); + goto errout; + } + + journal_source.where = JOURNAL_IS_EXTERNAL; + journal_source.fd = journal_fd; + } else if ((journal_inum = es->s_journal_inum)) { + if (use_sb) { + if (es->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS) { + com_err(argv[0], 0, + "no journal backup in super block\n"); + goto errout; + } + memset(&journal_inode, 0, sizeof(struct ext2_inode)); + memcpy(&journal_inode.i_block[0], es->s_jnl_blocks, + EXT2_N_BLOCKS*4); + journal_inode.i_size_high = es->s_jnl_blocks[15]; + journal_inode.i_size = es->s_jnl_blocks[16]; + journal_inode.i_links_count = 1; + journal_inode.i_mode = LINUX_S_IFREG | 0600; + } else { + if (debugfs_read_inode(journal_inum, &journal_inode, + argv[0])) + goto errout; + } + + retval = ext2fs_file_open2(current_fs, journal_inum, + &journal_inode, 0, &journal_file); + if (retval) { + com_err(argv[0], retval, "while opening ext2 file"); + goto errout; + } + journal_source.where = JOURNAL_IS_INTERNAL; + journal_source.file = journal_file; + } else { + char uuid[37]; + + uuid_unparse(es->s_journal_uuid, uuid); + journal_fn = blkid_get_devname(NULL, "UUID", uuid); + if (!journal_fn) + journal_fn = blkid_devno_to_devname(es->s_journal_dev); + if (!journal_fn) { + com_err(argv[0], 0, "filesystem has no journal"); + goto errout; + } + journal_fd = open(journal_fn, O_RDONLY, 0); + if (journal_fd < 0) { + com_err(argv[0], errno, "while opening %s for logdump", + journal_fn); + free(journal_fn); + goto errout; + } + fprintf(out_file, "Using external journal found at %s\n", + journal_fn); + free(journal_fn); + journal_source.where = JOURNAL_IS_EXTERNAL; + journal_source.fd = journal_fd; + } + + dump_journal(argv[0], out_file, &journal_source); + + if (journal_source.where == JOURNAL_IS_INTERNAL) + ext2fs_file_close(journal_file); + else + close(journal_fd); + +errout: + if (out_file && (out_file != stdout)) + fclose(out_file); + + return; + +print_usage: + fprintf(stderr, "%s: Usage: logdump [-acs] [-b<block>] [-i<filespec>]\n\t" + "[-f<journal_file>] [output_file]\n", argv[0]); +} + + +static int read_journal_block(const char *cmd, struct journal_source *source, + off_t offset, char *buf, unsigned int size) +{ + int retval; + unsigned int got; + + if (source->where == JOURNAL_IS_EXTERNAL) { + if (lseek(source->fd, offset, SEEK_SET) < 0) { + retval = errno; + goto seek_err; + } + retval = read(source->fd, buf, size); + if (retval < 0) { + retval = errno; + goto read_err; + } + got = retval; + retval = 0; + } else { + retval = ext2fs_file_lseek(source->file, offset, + EXT2_SEEK_SET, NULL); + if (retval) { + seek_err: + com_err(cmd, retval, "while seeking in reading journal"); + return retval; + } + retval = ext2fs_file_read(source->file, buf, size, &got); + if (retval) { + read_err: + com_err(cmd, retval, "while reading journal"); + return retval; + } + } + if (got != size) { + com_err(cmd, 0, "short read (read %u, expected %u) " + "while reading journal", got, size); + retval = -1; + } + return retval; +} + +static const char *type_to_name(int btype) +{ + switch (btype) { + case JFS_DESCRIPTOR_BLOCK: + return "descriptor block"; + case JFS_COMMIT_BLOCK: + return "commit block"; + case JFS_SUPERBLOCK_V1: + return "V1 superblock"; + case JFS_SUPERBLOCK_V2: + return "V2 superblock"; + case JFS_REVOKE_BLOCK: + return "revoke table"; + } + return "unrecognised type"; +} + + +static void dump_journal(char *cmdname, FILE *out_file, + struct journal_source *source) +{ + struct ext2_super_block *sb; + char jsb_buffer[1024]; + char buf[8192]; + journal_superblock_t *jsb; + unsigned int blocksize = 1024; + int retval; + __u32 magic, sequence, blocktype; + journal_header_t *header; + + tid_t transaction; + unsigned int blocknr = 0; + + /* First, check to see if there's an ext2 superblock header */ + retval = read_journal_block(cmdname, source, 0, buf, 2048); + if (retval) + return; + + jsb = (journal_superblock_t *) buf; + sb = (struct ext2_super_block *) (buf+1024); +#ifdef WORDS_BIGENDIAN + if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) + ext2fs_swap_super(sb); +#endif + + if ((be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) && + (sb->s_magic == EXT2_SUPER_MAGIC) && + (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { + blocksize = EXT2_BLOCK_SIZE(sb); + blocknr = (blocksize == 1024) ? 2 : 1; + uuid_unparse(sb->s_uuid, jsb_buffer); + fprintf(out_file, "Ext2 superblock header found.\n"); + if (dump_all) { + fprintf(out_file, "\tuuid=%s\n", jsb_buffer); + fprintf(out_file, "\tblocksize=%d\n", blocksize); + fprintf(out_file, "\tjournal data size %lu\n", + (unsigned long) ext2fs_blocks_count(sb)); + } + } + + /* Next, read the journal superblock */ + + retval = read_journal_block(cmdname, source, blocknr*blocksize, + jsb_buffer, 1024); + if (retval) + return; + + jsb = (journal_superblock_t *) jsb_buffer; + if (be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) { + fprintf(out_file, + "Journal superblock magic number invalid!\n"); + return; + } + blocksize = be32_to_cpu(jsb->s_blocksize); + transaction = be32_to_cpu(jsb->s_sequence); + blocknr = be32_to_cpu(jsb->s_start); + + fprintf(out_file, "Journal starts at block %u, transaction %u\n", + blocknr, transaction); + + if (!blocknr) + /* Empty journal, nothing to do. */ + return; + + while (1) { + retval = read_journal_block(cmdname, source, + blocknr*blocksize, buf, + blocksize); + if (retval) + return; + + header = (journal_header_t *) buf; + + magic = be32_to_cpu(header->h_magic); + sequence = be32_to_cpu(header->h_sequence); + blocktype = be32_to_cpu(header->h_blocktype); + + if (magic != JFS_MAGIC_NUMBER) { + fprintf (out_file, "No magic number at block %u: " + "end of journal.\n", blocknr); + return; + } + + if (sequence != transaction) { + fprintf (out_file, "Found sequence %u (not %u) at " + "block %u: end of journal.\n", + sequence, transaction, blocknr); + return; + } + + if (dump_descriptors) { + fprintf (out_file, "Found expected sequence %u, " + "type %u (%s) at block %u\n", + sequence, blocktype, + type_to_name(blocktype), blocknr); + } + + switch (blocktype) { + case JFS_DESCRIPTOR_BLOCK: + dump_descriptor_block(out_file, source, buf, jsb, + &blocknr, blocksize, + transaction); + continue; + + case JFS_COMMIT_BLOCK: + transaction++; + blocknr++; + WRAP(jsb, blocknr); + continue; + + case JFS_REVOKE_BLOCK: + dump_revoke_block(out_file, buf, jsb, + blocknr, blocksize, + transaction); + blocknr++; + WRAP(jsb, blocknr); + continue; + + default: + fprintf (out_file, "Unexpected block type %u at " + "block %u.\n", blocktype, blocknr); + return; + } + } +} + + +static void dump_descriptor_block(FILE *out_file, + struct journal_source *source, + char *buf, + journal_superblock_t *jsb, + unsigned int *blockp, int blocksize, + tid_t transaction) +{ + int offset, tag_size = JBD_TAG_SIZE32; + char *tagp; + journal_block_tag_t *tag; + unsigned int blocknr; + __u32 tag_block; + __u32 tag_flags; + + if (be32_to_cpu(jsb->s_feature_incompat) & JFS_FEATURE_INCOMPAT_64BIT) + tag_size = JBD_TAG_SIZE64; + + offset = sizeof(journal_header_t); + blocknr = *blockp; + + if (dump_all) + fprintf(out_file, "Dumping descriptor block, sequence %u, at " + "block %u:\n", transaction, blocknr); + + ++blocknr; + WRAP(jsb, blocknr); + + do { + /* Work out the location of the current tag, and skip to + * the next one... */ + tagp = &buf[offset]; + tag = (journal_block_tag_t *) tagp; + offset += tag_size; + + /* ... and if we have gone too far, then we've reached the + end of this block. */ + if (offset > blocksize) + break; + + tag_block = be32_to_cpu(tag->t_blocknr); + tag_flags = be32_to_cpu(tag->t_flags); + + if (!(tag_flags & JFS_FLAG_SAME_UUID)) + offset += 16; + + dump_metadata_block(out_file, source, jsb, + blocknr, tag_block, tag_flags, blocksize, + transaction); + + ++blocknr; + WRAP(jsb, blocknr); + + } while (!(tag_flags & JFS_FLAG_LAST_TAG)); + + *blockp = blocknr; +} + + +static void dump_revoke_block(FILE *out_file, char *buf, + journal_superblock_t *jsb EXT2FS_ATTR((unused)), + unsigned int blocknr, + int blocksize EXT2FS_ATTR((unused)), + tid_t transaction) +{ + int offset, max; + journal_revoke_header_t *header; + unsigned int *entry, rblock; + + if (dump_all) + fprintf(out_file, "Dumping revoke block, sequence %u, at " + "block %u:\n", transaction, blocknr); + + header = (journal_revoke_header_t *) buf; + offset = sizeof(journal_revoke_header_t); + max = be32_to_cpu(header->r_count); + + while (offset < max) { + entry = (unsigned int *) (buf + offset); + rblock = be32_to_cpu(*entry); + if (dump_all || rblock == block_to_dump) { + fprintf(out_file, " Revoke FS block %u", rblock); + if (dump_all) + fprintf(out_file, "\n"); + else + fprintf(out_file," at block %u, sequence %u\n", + blocknr, transaction); + } + offset += 4; + } +} + + +static void show_extent(FILE *out_file, int start_extent, int end_extent, + __u32 first_block) +{ + if (start_extent >= 0 && first_block != 0) + fprintf(out_file, "(%d+%u): %u ", + start_extent, end_extent-start_extent, first_block); +} + +static void show_indirect(FILE *out_file, const char *name, __u32 where) +{ + if (where) + fprintf(out_file, "(%s): %u ", name, where); +} + + +static void dump_metadata_block(FILE *out_file, struct journal_source *source, + journal_superblock_t *jsb EXT2FS_ATTR((unused)), + unsigned int log_blocknr, + unsigned int fs_blocknr, + unsigned int log_tag_flags, + int blocksize, + tid_t transaction) +{ + int retval; + char buf[8192]; + + if (!(dump_all + || (fs_blocknr == block_to_dump) + || (fs_blocknr == inode_block_to_dump) + || (fs_blocknr == bitmap_to_dump))) + return; + + fprintf(out_file, " FS block %u logged at ", fs_blocknr); + if (!dump_all) + fprintf(out_file, "sequence %u, ", transaction); + fprintf(out_file, "journal block %u (flags 0x%x)\n", log_blocknr, + log_tag_flags); + + /* There are two major special cases to parse: + * + * If this block is a block + * bitmap block, we need to give it special treatment so that we + * can log any allocates and deallocates which affect the + * block_to_dump query block. + * + * If the block is an inode block for the inode being searched + * for, then we need to dump the contents of that inode + * structure symbolically. + */ + + if (!(dump_contents && dump_all) + && fs_blocknr != block_to_dump + && fs_blocknr != bitmap_to_dump + && fs_blocknr != inode_block_to_dump) + return; + + retval = read_journal_block("logdump", source, + blocksize * log_blocknr, + buf, blocksize); + if (retval) + return; + + if (fs_blocknr == bitmap_to_dump) { + struct ext2_super_block *super; + int offset; + + super = current_fs->super; + offset = ((block_to_dump - super->s_first_data_block) % + super->s_blocks_per_group); + + fprintf(out_file, " (block bitmap for block %llu: " + "block is %s)\n", + block_to_dump, + ext2fs_test_bit(offset, buf) ? "SET" : "CLEAR"); + } + + if (fs_blocknr == inode_block_to_dump) { + struct ext2_inode *inode; + int first, prev, this, start_extent, i; + + fprintf(out_file, " (inode block for inode %u):\n", + inode_to_dump); + + inode = (struct ext2_inode *) (buf + inode_offset_to_dump); + internal_dump_inode(out_file, " ", inode_to_dump, inode, 0); + + /* Dump out the direct/indirect blocks here: + * internal_dump_inode can only dump them from the main + * on-disk inode, not from the journaled copy of the + * inode. */ + + fprintf (out_file, " Blocks: "); + first = prev = start_extent = -1; + + for (i=0; i<EXT2_NDIR_BLOCKS; i++) { + this = inode->i_block[i]; + if (start_extent >= 0 && this == prev+1) { + prev = this; + continue; + } else { + show_extent(out_file, start_extent, i, first); + start_extent = i; + first = prev = this; + } + } + show_extent(out_file, start_extent, i, first); + show_indirect(out_file, "IND", inode->i_block[i++]); + show_indirect(out_file, "DIND", inode->i_block[i++]); + show_indirect(out_file, "TIND", inode->i_block[i++]); + + fprintf(out_file, "\n"); + } + + if (dump_contents) + do_hexdump(out_file, buf, blocksize); + +} + +static void do_hexdump (FILE *out_file, char *buf, int blocksize) +{ + int i,j; + int *intp; + char *charp; + unsigned char c; + + intp = (int *) buf; + charp = (char *) buf; + + for (i=0; i<blocksize; i+=16) { + fprintf(out_file, " %04x: ", i); + for (j=0; j<16; j+=4) + fprintf(out_file, "%08x ", *intp++); + for (j=0; j<16; j++) { + c = *charp++; + if (c < ' ' || c >= 127) + c = '.'; + fprintf(out_file, "%c", c); + } + fprintf(out_file, "\n"); + } +} +
diff --git a/debugfs/ls.c b/debugfs/ls.c new file mode 100644 index 0000000..b4036de --- /dev/null +++ b/debugfs/ls.c
@@ -0,0 +1,183 @@ +/* + * ls.c --- list directories + * + * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif + +#include "debugfs.h" + +/* + * list directory + */ + +#define LONG_OPT 0x0001 +#define DELETED_OPT 0x0002 +#define PARSE_OPT 0x0004 + +struct list_dir_struct { + FILE *f; + int col; + int options; +}; + +static const char *monstr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +static int list_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)), + int entry, + struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *private) +{ + struct ext2_inode inode; + ext2_ino_t ino; + struct tm *tm_p; + time_t modtime; + char name[EXT2_NAME_LEN + 1]; + char tmp[EXT2_NAME_LEN + 16]; + char datestr[80]; + char lbr, rbr; + int thislen; + struct list_dir_struct *ls = (struct list_dir_struct *) private; + + thislen = dirent->name_len & 0xFF; + strncpy(name, dirent->name, thislen); + name[thislen] = '\0'; + ino = dirent->inode; + + if (entry == DIRENT_DELETED_FILE) { + lbr = '<'; + rbr = '>'; + ino = 0; + } else { + lbr = rbr = ' '; + } + if (ls->options & PARSE_OPT) { + if (ino) { + if (debugfs_read_inode(ino, &inode, name)) + return 0; + } else + memset(&inode, 0, sizeof(struct ext2_inode)); + fprintf(ls->f,"/%u/%06o/%d/%d/%s/",ino,inode.i_mode,inode.i_uid, inode.i_gid,name); + if (LINUX_S_ISDIR(inode.i_mode)) + fprintf(ls->f, "/"); + else + fprintf(ls->f, "%lld/", EXT2_I_SIZE(&inode)); + fprintf(ls->f, "\n"); + } else if (ls->options & LONG_OPT) { + if (ino) { + if (debugfs_read_inode(ino, &inode, name)) + return 0; + modtime = inode.i_mtime; + tm_p = localtime(&modtime); + sprintf(datestr, "%2d-%s-%4d %02d:%02d", + tm_p->tm_mday, monstr[tm_p->tm_mon], + 1900 + tm_p->tm_year, tm_p->tm_hour, + tm_p->tm_min); + } else { + strcpy(datestr, " "); + memset(&inode, 0, sizeof(struct ext2_inode)); + } + fprintf(ls->f, "%c%6u%c %6o (%d) %5d %5d ", lbr, ino, rbr, + inode.i_mode, dirent->name_len >> 8, + inode_uid(inode), inode_gid(inode)); + if (LINUX_S_ISDIR(inode.i_mode)) + fprintf(ls->f, "%5d", inode.i_size); + else + fprintf(ls->f, "%5llu", EXT2_I_SIZE(&inode)); + fprintf (ls->f, " %s %s\n", datestr, name); + } else { + sprintf(tmp, "%c%u%c (%d) %s ", lbr, dirent->inode, rbr, + dirent->rec_len, name); + thislen = strlen(tmp); + + if (ls->col + thislen > 80) { + fprintf(ls->f, "\n"); + ls->col = 0; + } + fprintf(ls->f, "%s", tmp); + ls->col += thislen; + } + return 0; +} + +void do_list_dir(int argc, char *argv[]) +{ + ext2_ino_t inode; + int retval; + int c; + int flags; + struct list_dir_struct ls; + + ls.options = 0; + if (check_fs_open(argv[0])) + return; + + reset_getopt(); + while ((c = getopt (argc, argv, "dlp")) != EOF) { + switch (c) { + case 'l': + ls.options |= LONG_OPT; + break; + case 'd': + ls.options |= DELETED_OPT; + break; + case 'p': + ls.options |= PARSE_OPT; + break; + default: + goto print_usage; + } + } + + if (argc > optind+1) { + print_usage: + com_err(0, 0, "Usage: ls [-l] [-d] [-p] file"); + return; + } + + if (argc == optind) + inode = cwd; + else + inode = string_to_inode(argv[optind]); + if (!inode) + return; + + ls.f = open_pager(); + ls.col = 0; + flags = DIRENT_FLAG_INCLUDE_EMPTY; + if (ls.options & DELETED_OPT) + flags |= DIRENT_FLAG_INCLUDE_REMOVED; + + retval = ext2fs_dir_iterate2(current_fs, inode, flags, + 0, list_dir_proc, &ls); + fprintf(ls.f, "\n"); + close_pager(ls.f); + if (retval) + com_err(argv[1], retval, 0); + + return; +} + +
diff --git a/debugfs/lsdel.c b/debugfs/lsdel.c new file mode 100644 index 0000000..e5b2d20 --- /dev/null +++ b/debugfs/lsdel.c
@@ -0,0 +1,212 @@ +/* + * lsdel.c --- routines to try to help a user recover a deleted file. + * + * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 + * Theodore Ts'o. This file may be redistributed under the terms of + * the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> + +#include "debugfs.h" + +struct deleted_info { + ext2_ino_t ino; + unsigned short mode; + __u32 uid; + __u64 size; + time_t dtime; + e2_blkcnt_t num_blocks; + e2_blkcnt_t free_blocks; +}; + +struct lsdel_struct { + ext2_ino_t inode; + e2_blkcnt_t num_blocks; + e2_blkcnt_t free_blocks; + e2_blkcnt_t bad_blocks; +}; + +static int deleted_info_compare(const void *a, const void *b) +{ + const struct deleted_info *arg1, *arg2; + + arg1 = (const struct deleted_info *) a; + arg2 = (const struct deleted_info *) b; + + return arg1->dtime - arg2->dtime; +} + +static int lsdel_proc(ext2_filsys fs, + blk64_t *block_nr, + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *private) +{ + struct lsdel_struct *lsd = (struct lsdel_struct *) private; + + lsd->num_blocks++; + + if (*block_nr < fs->super->s_first_data_block || + *block_nr >= ext2fs_blocks_count(fs->super)) { + lsd->bad_blocks++; + return BLOCK_ABORT; + } + + if (!ext2fs_test_block_bitmap2(fs->block_map,*block_nr)) + lsd->free_blocks++; + + return 0; +} + +void do_lsdel(int argc, char **argv) +{ + struct lsdel_struct lsd; + struct deleted_info *delarray; + int num_delarray, max_delarray; + ext2_inode_scan scan = 0; + ext2_ino_t ino; + struct ext2_inode inode; + errcode_t retval; + char *block_buf; + int i; + long secs = 0; + char *tmp; + time_t now; + FILE *out; + + if (common_args_process(argc, argv, 1, 2, "list_deleted_inodes", + "[secs]", 0)) + return; + + if (argc > 1) { + secs = strtol(argv[1],&tmp,0); + if (*tmp) { + com_err(argv[0], 0, "Bad time - %s",argv[1]); + return; + } + } + + now = current_fs->now ? current_fs->now : time(0); + max_delarray = 100; + num_delarray = 0; + delarray = malloc(max_delarray * sizeof(struct deleted_info)); + if (!delarray) { + com_err("ls_deleted_inodes", ENOMEM, + "while allocating deleted information storage"); + exit(1); + } + + block_buf = malloc(current_fs->blocksize * 3); + if (!block_buf) { + com_err("ls_deleted_inodes", ENOMEM, "while allocating block buffer"); + goto error_out; + } + + retval = ext2fs_open_inode_scan(current_fs, 0, &scan); + if (retval) { + com_err("ls_deleted_inodes", retval, + "while opening inode scan"); + goto error_out; + } + + do { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); + if (retval) { + com_err("ls_deleted_inodes", retval, + "while starting inode scan"); + goto error_out; + } + + while (ino) { + if ((inode.i_dtime == 0) || + (secs && ((unsigned) abs(now - secs) > inode.i_dtime))) + goto next; + + lsd.inode = ino; + lsd.num_blocks = 0; + lsd.free_blocks = 0; + lsd.bad_blocks = 0; + + retval = ext2fs_block_iterate3(current_fs, ino, + BLOCK_FLAG_READ_ONLY, block_buf, + lsdel_proc, &lsd); + if (retval) { + com_err("ls_deleted_inodes", retval, + "while calling ext2fs_block_iterate2"); + goto next; + } + if (lsd.free_blocks && !lsd.bad_blocks) { + if (num_delarray >= max_delarray) { + max_delarray += 50; + delarray = realloc(delarray, + max_delarray * sizeof(struct deleted_info)); + if (!delarray) { + com_err("ls_deleted_inodes", + ENOMEM, + "while reallocating array"); + exit(1); + } + } + + delarray[num_delarray].ino = ino; + delarray[num_delarray].mode = inode.i_mode; + delarray[num_delarray].uid = inode_uid(inode); + delarray[num_delarray].size = EXT2_I_SIZE(&inode); + delarray[num_delarray].dtime = inode.i_dtime; + delarray[num_delarray].num_blocks = lsd.num_blocks; + delarray[num_delarray].free_blocks = lsd.free_blocks; + num_delarray++; + } + + next: + do { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); + if (retval) { + com_err("ls_deleted_inodes", retval, + "while doing inode scan"); + goto error_out; + } + } + + out = open_pager(); + + fprintf(out, " Inode Owner Mode Size Blocks Time deleted\n"); + + qsort(delarray, num_delarray, sizeof(struct deleted_info), + deleted_info_compare); + + for (i = 0; i < num_delarray; i++) { + fprintf(out, "%6u %6d %6o %6llu %6lld/%6lld %s", + delarray[i].ino, + delarray[i].uid, delarray[i].mode, delarray[i].size, + delarray[i].free_blocks, delarray[i].num_blocks, + time_to_string(delarray[i].dtime)); + } + fprintf(out, "%d deleted inodes found.\n", num_delarray); + close_pager(out); + +error_out: + free(block_buf); + free(delarray); + if (scan) + ext2fs_close_inode_scan(scan); + return; +} + + +
diff --git a/debugfs/ncheck.c b/debugfs/ncheck.c new file mode 100644 index 0000000..58f3a50 --- /dev/null +++ b/debugfs/ncheck.c
@@ -0,0 +1,206 @@ +/* + * ncheck.c --- given a list of inodes, generate a list of names + * + * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif + +#include "debugfs.h" + +struct inode_walk_struct { + ext2_ino_t dir; + ext2_ino_t *iarray; + int inodes_left; + int num_inodes; + int position; + char *parent; + unsigned int get_pathname_failed:1; + unsigned int check_dirent:1; +}; + +static int ncheck_proc(struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *private) +{ + struct inode_walk_struct *iw = (struct inode_walk_struct *) private; + struct ext2_inode inode; + errcode_t retval; + int filetype = dirent->name_len >> 8; + int i; + + iw->position++; + if (iw->position <= 2) + return 0; + for (i=0; i < iw->num_inodes; i++) { + if (iw->iarray[i] == dirent->inode) { + if (!iw->parent && !iw->get_pathname_failed) { + retval = ext2fs_get_pathname(current_fs, + iw->dir, + 0, &iw->parent); + if (retval) { + com_err("ncheck", retval, + "while calling ext2fs_get_pathname for inode #%u", iw->dir); + iw->get_pathname_failed = 1; + } + } + if (iw->parent) + printf("%u\t%s/%.*s", iw->iarray[i], + iw->parent, + (dirent->name_len & 0xFF), dirent->name); + else + printf("%u\t<%u>/%.*s", iw->iarray[i], + iw->dir, + (dirent->name_len & 0xFF), dirent->name); + if (iw->check_dirent && filetype) { + if (!debugfs_read_inode(dirent->inode, &inode, + "ncheck") && + filetype != ext2_file_type(inode.i_mode)) { + printf(" <--- BAD FILETYPE"); + } + } + putc('\n', stdout); + } + } + if (!iw->inodes_left) + return DIRENT_ABORT; + + return 0; +} + +void do_ncheck(int argc, char **argv) +{ + struct inode_walk_struct iw; + int c, i; + ext2_inode_scan scan = 0; + ext2_ino_t ino; + struct ext2_inode inode; + errcode_t retval; + char *tmp; + + iw.check_dirent = 0; + + reset_getopt(); + while ((c = getopt (argc, argv, "c")) != EOF) { + switch (c) { + case 'c': + iw.check_dirent = 1; + break; + default: + goto print_usage; + } + } + argc -= optind; + argv += optind; + + if (argc < 1) { + print_usage: + com_err(argv[0], 0, "Usage: ncheck [-c] <inode number> ..."); + return; + } + if (check_fs_open(argv[0])) + return; + + iw.iarray = malloc(sizeof(ext2_ino_t) * argc); + if (!iw.iarray) { + com_err("ncheck", ENOMEM, + "while allocating inode number array"); + return; + } + memset(iw.iarray, 0, sizeof(ext2_ino_t) * argc); + + for (i=0; i < argc; i++) { + iw.iarray[i] = strtol(argv[i], &tmp, 0); + if (*tmp) { + com_err(argv[0], 0, "Bad inode - %s", argv[i]); + goto error_out; + } + } + + iw.num_inodes = iw.inodes_left = argc; + + retval = ext2fs_open_inode_scan(current_fs, 0, &scan); + if (retval) { + com_err("ncheck", retval, "while opening inode scan"); + goto error_out; + } + + do { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); + if (retval) { + com_err("ncheck", retval, "while starting inode scan"); + goto error_out; + } + + printf("Inode\tPathname\n"); + while (ino) { + if (!inode.i_links_count) + goto next; + /* + * To handle filesystems touched by 0.3c extfs; can be + * removed later. + */ + if (inode.i_dtime) + goto next; + /* Ignore anything that isn't a directory */ + if (!LINUX_S_ISDIR(inode.i_mode)) + goto next; + + iw.position = 0; + iw.parent = 0; + iw.dir = ino; + iw.get_pathname_failed = 0; + + retval = ext2fs_dir_iterate(current_fs, ino, 0, 0, + ncheck_proc, &iw); + ext2fs_free_mem(&iw.parent); + if (retval) { + com_err("ncheck", retval, + "while calling ext2_dir_iterate"); + goto next; + } + + if (iw.inodes_left == 0) + break; + + next: + do { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); + + if (retval) { + com_err("ncheck", retval, + "while doing inode scan"); + goto error_out; + } + } + +error_out: + free(iw.iarray); + if (scan) + ext2fs_close_inode_scan(scan); + return; +} + + +
diff --git a/debugfs/quota.c b/debugfs/quota.c new file mode 100644 index 0000000..9612f64 --- /dev/null +++ b/debugfs/quota.c
@@ -0,0 +1,170 @@ +/* + * quota.c --- debugfs quota commands + * + * Copyright (C) 2014 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif + +#include "debugfs.h" + +const char *quota_type[] = { "user", "group", NULL }; + +static int load_quota_ctx(char *progname) +{ + errcode_t retval; + + if (check_fs_open(progname)) + return 1; + + if (!EXT2_HAS_RO_COMPAT_FEATURE(current_fs->super, + EXT4_FEATURE_RO_COMPAT_QUOTA)) { + com_err(progname, 0, "quota feature not enabled"); + return 1; + } + + if (current_qctx) + return 0; + + retval = quota_init_context(¤t_qctx, current_fs, -1); + if (retval) { + com_err(current_fs->device_name, retval, + "while trying to load quota information"); + return 1; + } + return 0; +} + +static int parse_quota_type(const char *cmdname, const char *str) +{ + errcode_t retval; + char *t; + int flags = 0; + int i; + + for (i = 0; i < MAXQUOTAS; i++) { + if (strcasecmp(str, quota_type[i]) == 0) + break; + } + if (i >= MAXQUOTAS) { + i = strtol(str, &t, 0); + if (*t) + i = -1; + } + if (i < 0 || i >= MAXQUOTAS) { + com_err(0, 0, "Invalid quota type: %s", str); + printf("Valid quota types are: "); + for (i = 0; i < MAXQUOTAS; i++) + printf("%s ", quota_type[i]); + printf("\n"); + return -1; + } + + if (current_fs->flags & EXT2_FLAG_RW) + flags |= EXT2_FILE_WRITE; + + retval = quota_file_open(current_qctx, NULL, 0, i, -1, flags); + if (retval) { + com_err(cmdname, retval, + "while opening quota inode (type %d)", i); + return -1; + } + return i; +} + + +static int list_quota_callback(struct dquot *dq, void *cb_data) +{ + printf("%8u %8lld %8lld %8lld %8lld %8lld %8lld\n", + dq->dq_id, (long long)dq->dq_dqb.dqb_curspace, + (long long)dq->dq_dqb.dqb_bsoftlimit, + (long long)dq->dq_dqb.dqb_bhardlimit, + (long long)dq->dq_dqb.dqb_curinodes, + (long long)dq->dq_dqb.dqb_isoftlimit, + (long long)dq->dq_dqb.dqb_ihardlimit); + return 0; +} + +void do_list_quota(int argc, char *argv[]) +{ + errcode_t retval; + int type; + struct quota_handle *qh; + + if (load_quota_ctx(argv[0])) + return; + + if (argc != 2) { + com_err(0, 0, "Usage: list_quota <quota_type>\n"); + return; + } + + type = parse_quota_type(argv[0], argv[1]); + if (type < 0) + return; + + printf("%8s %8s %8s %8s %8s %8s %8s\n", + (type == 0) ? "user id" : "group id", + "blocks", "quota", "limit", "inodes", "quota", "limit"); + qh = current_qctx->quota_file[type]; + retval = qh->qh_ops->scan_dquots(qh, list_quota_callback, NULL); + if (retval) { + com_err(argv[0], retval, "while scanning dquots"); + return; + } +} + +void do_get_quota(int argc, char *argv[]) +{ + int err, type; + struct quota_handle *qh; + struct dquot *dq; + qid_t id; + + if (load_quota_ctx(argv[0])) + return; + + if (argc != 3) { + com_err(0, 0, "Usage: get_quota <quota_type> <id>\n"); + return; + } + + type = parse_quota_type(argv[0], argv[1]); + if (type < 0) + return; + + id = parse_ulong(argv[2], argv[0], "id", &err); + if (err) + return; + + printf("%8s %8s %8s %8s %8s %8s %8s\n", + (type == 0) ? "user id" : "group id", + "blocks", "quota", "limit", "inodes", "quota", "limit"); + + qh = current_qctx->quota_file[type]; + + dq = qh->qh_ops->read_dquot(qh, id); + if (dq) { + list_quota_callback(dq, NULL); + ext2fs_free_mem(&dq); + } else { + com_err(argv[0], 0, "couldn't read quota record"); + } +}
diff --git a/debugfs/ro_debug_cmds.ct b/debugfs/ro_debug_cmds.ct new file mode 100644 index 0000000..736ade6 --- /dev/null +++ b/debugfs/ro_debug_cmds.ct
@@ -0,0 +1,99 @@ +# +# Restricted set of debugfs commands +# +# Copyright (C) 1993 Theodore Ts'o. This file may be redistributed +# under the terms of the GNU Public License. +# +command_table debug_cmds; + +request do_show_debugfs_params, "Show debugfs parameters", + show_debugfs_params, params; + +request do_open_filesys, "Open a filesystem", + open_filesys, open; + +request do_close_filesys, "Close the filesystem", + close_filesys, close; + +request do_freefrag, "Report free space fragmentation", + freefrag, e2freefrag; + +request do_show_super_stats, "Show superblock statistics", + show_super_stats, stats; + +request do_ncheck, "Do inode->name translation", + ncheck; + +request do_icheck, "Do block->inode translation", + icheck; + +request do_chroot, "Change root directory", + change_root_directory, chroot; + +request do_change_working_dir, "Change working directory", + change_working_directory, cd; + +request do_list_dir, "List directory", + list_directory, ls; + +request do_stat, "Show inode information ", + show_inode_info, stat; + +request do_dump_extents, "Dump extents information ", + dump_extents, extents, ex; + +request do_blocks, "Dump blocks used by an inode ", + blocks; + +request do_filefrag, "Report fragmentation information for an inode", + filefrag; + +request do_testi, "Test an inode's in-use flag", + testi; + +request do_find_free_block, "Find free block(s)", + find_free_block, ffb; + +request do_find_free_inode, "Find free inode(s)", + find_free_inode, ffi; + +request do_print_working_directory, "Print current working directory", + print_working_directory, pwd; + +request do_lsdel, "List deleted inodes", + list_deleted_inodes, lsdel; + +request do_logdump, "Dump the contents of the journal", + logdump; + +request do_htree_dump, "Dump a hash-indexed directory", + htree_dump, htree; + +request do_dx_hash, "Calculate the directory hash of a filename", + dx_hash, hash; + +request do_dirsearch, "Search a directory for a particular filename", + dirsearch; + +request do_bmap, "Calculate the logical->physical block mapping for an inode", + bmap; + +request do_imap, "Calculate the location of an inode", + imap; + +request do_supported_features, "Print features supported by this version of e2fsprogs", + supported_features; + +request do_dump_mmp, "Dump MMP information", + dump_mmp; + +request do_extent_open, "Open inode for extent manipulation", + extent_open, eo; + +request do_list_quota, "List quota", + lost_quota, lq; + +request do_get_quota, "Get quota", + get_quota, gq; + +end;
diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c new file mode 100644 index 0000000..6104b2b --- /dev/null +++ b/debugfs/set_fields.c
@@ -0,0 +1,844 @@ +/* + * set_fields.c --- set a superblock value + * + * Copyright (C) 2000, 2001, 2002, 2003, 2004 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#define _XOPEN_SOURCE 600 /* for inclusion of strptime() and strtoull */ + +#ifdef HAVE_STRTOULL +#define STRTOULL strtoull +#else +#define STRTOULL strtoul +#endif + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <strings.h> +#include <time.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_STRINGS_H +#include <strings.h> +#endif +#include <fcntl.h> +#include <utime.h> + +#include "debugfs.h" +#include "uuid/uuid.h" +#include "e2p/e2p.h" + +static struct ext2_super_block set_sb; +static struct ext2_inode_large set_inode; +static struct ext2_group_desc set_gd; +static struct ext4_group_desc set_gd4; +static struct mmp_struct set_mmp; +static dgrp_t set_bg; +static ext2_ino_t set_ino; +static int array_idx; + +#define FLAG_ARRAY 0x0001 + +struct field_set_info { + const char *name; + void *ptr; + void *ptr2; + unsigned int size; + errcode_t (*func)(struct field_set_info *info, char *field, char *arg); + int flags; + int max_idx; +}; + +static errcode_t parse_uint(struct field_set_info *info, char *field, char *arg); +static errcode_t parse_int(struct field_set_info *info, char *field, char *arg); +static errcode_t parse_string(struct field_set_info *info, char *field, char *arg); +static errcode_t parse_uuid(struct field_set_info *info, char *field, char *arg); +static errcode_t parse_hashalg(struct field_set_info *info, char *field, char *arg); +static errcode_t parse_time(struct field_set_info *info, char *field, char *arg); +static errcode_t parse_bmap(struct field_set_info *info, char *field, char *arg); +static errcode_t parse_gd_csum(struct field_set_info *info, char *field, char *arg); +static errcode_t parse_mmp_clear(struct field_set_info *info, char *field, + char *arg); + +static struct field_set_info super_fields[] = { + { "inodes_count", &set_sb.s_inodes_count, NULL, 4, parse_uint }, + { "blocks_count", &set_sb.s_blocks_count, &set_sb.s_blocks_count_hi, + 4, parse_uint }, + { "r_blocks_count", &set_sb.s_r_blocks_count, + &set_sb.s_r_blocks_count_hi, 4, parse_uint }, + { "free_blocks_count", &set_sb.s_free_blocks_count, + &set_sb.s_free_blocks_hi, 4, parse_uint }, + { "free_inodes_count", &set_sb.s_free_inodes_count, NULL, 4, parse_uint }, + { "first_data_block", &set_sb.s_first_data_block, NULL, 4, parse_uint }, + { "log_block_size", &set_sb.s_log_block_size, NULL, 4, parse_uint }, + { "log_cluster_size", &set_sb.s_log_cluster_size, NULL, 4, parse_int }, + { "blocks_per_group", &set_sb.s_blocks_per_group, NULL, 4, parse_uint }, + { "clusters_per_group", &set_sb.s_clusters_per_group, NULL, 4, parse_uint }, + { "inodes_per_group", &set_sb.s_inodes_per_group, NULL, 4, parse_uint }, + { "mtime", &set_sb.s_mtime, NULL, 4, parse_time }, + { "wtime", &set_sb.s_wtime, NULL, 4, parse_time }, + { "mnt_count", &set_sb.s_mnt_count, NULL, 2, parse_uint }, + { "max_mnt_count", &set_sb.s_max_mnt_count, NULL, 2, parse_int }, + /* s_magic */ + { "state", &set_sb.s_state, NULL, 2, parse_uint }, + { "errors", &set_sb.s_errors, NULL, 2, parse_uint }, + { "minor_rev_level", &set_sb.s_minor_rev_level, NULL, 2, parse_uint }, + { "lastcheck", &set_sb.s_lastcheck, NULL, 4, parse_time }, + { "checkinterval", &set_sb.s_checkinterval, NULL, 4, parse_uint }, + { "creator_os", &set_sb.s_creator_os, NULL, 4, parse_uint }, + { "rev_level", &set_sb.s_rev_level, NULL, 4, parse_uint }, + { "def_resuid", &set_sb.s_def_resuid, NULL, 2, parse_uint }, + { "def_resgid", &set_sb.s_def_resgid, NULL, 2, parse_uint }, + { "first_ino", &set_sb.s_first_ino, NULL, 4, parse_uint }, + { "inode_size", &set_sb.s_inode_size, NULL, 2, parse_uint }, + { "block_group_nr", &set_sb.s_block_group_nr, NULL, 2, parse_uint }, + { "feature_compat", &set_sb.s_feature_compat, NULL, 4, parse_uint }, + { "feature_incompat", &set_sb.s_feature_incompat, NULL, 4, parse_uint }, + { "feature_ro_compat", &set_sb.s_feature_ro_compat, NULL, 4, parse_uint }, + { "uuid", &set_sb.s_uuid, NULL, 16, parse_uuid }, + { "volume_name", &set_sb.s_volume_name, NULL, 16, parse_string }, + { "last_mounted", &set_sb.s_last_mounted, NULL, 64, parse_string }, + { "lastcheck", &set_sb.s_lastcheck, NULL, 4, parse_uint }, + { "algorithm_usage_bitmap", &set_sb.s_algorithm_usage_bitmap, NULL, + 4, parse_uint }, + { "prealloc_blocks", &set_sb.s_prealloc_blocks, NULL, 1, parse_uint }, + { "prealloc_dir_blocks", &set_sb.s_prealloc_dir_blocks, NULL, 1, + parse_uint }, + { "reserved_gdt_blocks", &set_sb.s_reserved_gdt_blocks, NULL, 2, + parse_uint }, + { "journal_uuid", &set_sb.s_journal_uuid, NULL, 16, parse_uuid }, + { "journal_inum", &set_sb.s_journal_inum, NULL, 4, parse_uint }, + { "journal_dev", &set_sb.s_journal_dev, NULL, 4, parse_uint }, + { "last_orphan", &set_sb.s_last_orphan, NULL, 4, parse_uint }, + { "hash_seed", &set_sb.s_hash_seed, NULL, 16, parse_uuid }, + { "def_hash_version", &set_sb.s_def_hash_version, NULL, 1, parse_hashalg }, + { "jnl_backup_type", &set_sb.s_jnl_backup_type, NULL, 1, parse_uint }, + { "desc_size", &set_sb.s_desc_size, NULL, 2, parse_uint }, + { "default_mount_opts", &set_sb.s_default_mount_opts, NULL, 4, parse_uint }, + { "first_meta_bg", &set_sb.s_first_meta_bg, NULL, 4, parse_uint }, + { "mkfs_time", &set_sb.s_mkfs_time, NULL, 4, parse_time }, + { "jnl_blocks", &set_sb.s_jnl_blocks[0], NULL, 4, parse_uint, FLAG_ARRAY, + 17 }, + { "min_extra_isize", &set_sb.s_min_extra_isize, NULL, 2, parse_uint }, + { "want_extra_isize", &set_sb.s_want_extra_isize, NULL, 2, parse_uint }, + { "flags", &set_sb.s_flags, NULL, 4, parse_uint }, + { "raid_stride", &set_sb.s_raid_stride, NULL, 2, parse_uint }, + { "min_extra_isize", &set_sb.s_min_extra_isize, NULL, 4, parse_uint }, + { "mmp_interval", &set_sb.s_mmp_update_interval, NULL, 2, parse_uint }, + { "mmp_block", &set_sb.s_mmp_block, NULL, 8, parse_uint }, + { "raid_stripe_width", &set_sb.s_raid_stripe_width, NULL, 4, parse_uint }, + { "log_groups_per_flex", &set_sb.s_log_groups_per_flex, NULL, 1, parse_uint }, + { "kbytes_written", &set_sb.s_kbytes_written, NULL, 8, parse_uint }, + { "snapshot_inum", &set_sb.s_snapshot_inum, NULL, 4, parse_uint }, + { "snapshot_id", &set_sb.s_snapshot_id, NULL, 4, parse_uint }, + { "snapshot_r_blocks_count", &set_sb.s_snapshot_r_blocks_count, + NULL, 8, parse_uint }, + { "snapshot_list", &set_sb.s_snapshot_list, NULL, 4, parse_uint }, + { "mount_opts", &set_sb.s_mount_opts, NULL, 64, parse_string }, + { "usr_quota_inum", &set_sb.s_usr_quota_inum, NULL, 4, parse_uint }, + { "grp_quota_inum", &set_sb.s_grp_quota_inum, NULL, 4, parse_uint }, + { "overhead_blocks", &set_sb.s_overhead_blocks, NULL, 4, parse_uint }, + { "backup_bgs", &set_sb.s_backup_bgs[0], NULL, 4, parse_uint, + FLAG_ARRAY, 2 }, + { "checksum", &set_sb.s_checksum, NULL, 4, parse_uint }, + { "error_count", &set_sb.s_error_count, NULL, 4, parse_uint }, + { "first_error_time", &set_sb.s_first_error_time, NULL, 4, parse_time }, + { "first_error_ino", &set_sb.s_first_error_ino, NULL, 4, parse_uint }, + { "first_error_block", &set_sb.s_first_error_block, NULL, 8, parse_uint }, + { "first_error_func", &set_sb.s_first_error_func, NULL, 32, parse_string }, + { "first_error_line", &set_sb.s_first_error_ino, NULL, 4, parse_uint }, + { "last_error_time", &set_sb.s_last_error_time, NULL, 4, parse_time }, + { "last_error_ino", &set_sb.s_last_error_ino, NULL, 4, parse_uint }, + { "last_error_block", &set_sb.s_last_error_block, NULL, 8, parse_uint }, + { "last_error_func", &set_sb.s_last_error_func, NULL, 32, parse_string }, + { "last_error_line", &set_sb.s_last_error_ino, NULL, 4, parse_uint }, + { 0, 0, 0, 0 } +}; + +static struct field_set_info inode_fields[] = { + { "inodes_count", &set_sb.s_inodes_count, NULL, 4, parse_uint }, + { "mode", &set_inode.i_mode, NULL, 2, parse_uint }, + { "uid", &set_inode.i_uid, &set_inode.osd2.linux2.l_i_uid_high, + 2, parse_uint }, + { "size", &set_inode.i_size, &set_inode.i_size_high, 4, parse_uint }, + { "atime", &set_inode.i_atime, NULL, 4, parse_time }, + { "ctime", &set_inode.i_ctime, NULL, 4, parse_time }, + { "mtime", &set_inode.i_mtime, NULL, 4, parse_time }, + { "dtime", &set_inode.i_dtime, NULL, 4, parse_time }, + { "gid", &set_inode.i_gid, &set_inode.osd2.linux2.l_i_gid_high, + 2, parse_uint }, + { "links_count", &set_inode.i_links_count, NULL, 2, parse_uint }, + /* Special case: i_blocks is 4 bytes, i_blocks_high is 2 bytes */ + { "blocks", &set_inode.i_blocks, &set_inode.osd2.linux2.l_i_blocks_hi, + 6, parse_uint }, + { "flags", &set_inode.i_flags, NULL, 4, parse_uint }, + { "version", &set_inode.osd1.linux1.l_i_version, + &set_inode.i_version_hi, 4, parse_uint }, + { "translator", &set_inode.osd1.hurd1.h_i_translator, NULL, 4, parse_uint }, + { "block", &set_inode.i_block[0], NULL, 4, parse_uint, FLAG_ARRAY, + EXT2_NDIR_BLOCKS }, + { "block[IND]", &set_inode.i_block[EXT2_IND_BLOCK], NULL, 4, parse_uint }, + { "block[DIND]", &set_inode.i_block[EXT2_DIND_BLOCK], NULL, 4, parse_uint }, + { "block[TIND]", &set_inode.i_block[EXT2_TIND_BLOCK], NULL, 4, parse_uint }, + { "generation", &set_inode.i_generation, NULL, 4, parse_uint }, + /* Special case: i_file_acl_high is 2 bytes */ + { "file_acl", &set_inode.i_file_acl, + &set_inode.osd2.linux2.l_i_file_acl_high, 6, parse_uint }, + { "dir_acl", &set_inode.i_dir_acl, NULL, 4, parse_uint }, + { "faddr", &set_inode.i_faddr, NULL, 4, parse_uint }, + { "frag", &set_inode.osd2.hurd2.h_i_frag, NULL, 1, parse_uint }, + { "fsize", &set_inode.osd2.hurd2.h_i_fsize, NULL, 1, parse_uint }, + { "checksum", &set_inode.osd2.linux2.l_i_checksum_lo, + &set_inode.i_checksum_hi, 2, parse_uint }, + { "author", &set_inode.osd2.hurd2.h_i_author, NULL, + 4, parse_uint }, + { "extra_isize", &set_inode.i_extra_isize, NULL, + 2, parse_uint }, + { "ctime_extra", &set_inode.i_ctime_extra, NULL, + 4, parse_uint }, + { "mtime_extra", &set_inode.i_mtime_extra, NULL, + 4, parse_uint }, + { "atime_extra", &set_inode.i_atime_extra, NULL, + 4, parse_uint }, + { "crtime", &set_inode.i_crtime, NULL, 4, parse_uint }, + { "crtime_extra", &set_inode.i_crtime_extra, NULL, + 4, parse_uint }, + { "bmap", NULL, NULL, 4, parse_bmap, FLAG_ARRAY }, + { 0, 0, 0, 0 } +}; + +static struct field_set_info ext2_bg_fields[] = { + { "block_bitmap", &set_gd.bg_block_bitmap, NULL, 4, parse_uint }, + { "inode_bitmap", &set_gd.bg_inode_bitmap, NULL, 4, parse_uint }, + { "inode_table", &set_gd.bg_inode_table, NULL, 4, parse_uint }, + { "free_blocks_count", &set_gd.bg_free_blocks_count, NULL, 2, parse_uint }, + { "free_inodes_count", &set_gd.bg_free_inodes_count, NULL, 2, parse_uint }, + { "used_dirs_count", &set_gd.bg_used_dirs_count, NULL, 2, parse_uint }, + { "flags", &set_gd.bg_flags, NULL, 2, parse_uint }, + { "itable_unused", &set_gd.bg_itable_unused, NULL, 2, parse_uint }, + { "checksum", &set_gd.bg_checksum, NULL, 2, parse_gd_csum }, + { 0, 0, 0, 0 } +}; + +static struct field_set_info ext4_bg_fields[] = { + { "block_bitmap", &set_gd4.bg_block_bitmap, + &set_gd4.bg_block_bitmap_hi, 4, parse_uint }, + { "inode_bitmap", &set_gd4.bg_inode_bitmap, + &set_gd4.bg_inode_bitmap_hi, 4, parse_uint }, + { "inode_table", &set_gd4.bg_inode_table, + &set_gd4.bg_inode_table_hi, 4, parse_uint }, + { "free_blocks_count", &set_gd4.bg_free_blocks_count, + &set_gd4.bg_free_blocks_count_hi, 2, parse_uint }, + { "free_inodes_count", &set_gd4.bg_free_inodes_count, + &set_gd4.bg_free_inodes_count_hi, 2, parse_uint }, + { "used_dirs_count", &set_gd4.bg_used_dirs_count, + &set_gd4.bg_used_dirs_count_hi, 2, parse_uint }, + { "flags", &set_gd4.bg_flags, NULL, 2, parse_uint }, + { "exclude_bitmap", &set_gd4.bg_exclude_bitmap_lo, + &set_gd4.bg_exclude_bitmap_hi, 4, parse_uint }, + { "block_bitmap_csum", &set_gd4.bg_block_bitmap_csum_lo, + &set_gd4.bg_block_bitmap_csum_hi, 2, parse_uint }, + { "inode_bitmap_csum", &set_gd4.bg_inode_bitmap_csum_lo, + &set_gd4.bg_inode_bitmap_csum_hi, 2, parse_uint }, + { "itable_unused", &set_gd4.bg_itable_unused, + &set_gd4.bg_itable_unused_hi, 2, parse_uint }, + { "checksum", &set_gd4.bg_checksum, NULL, 2, parse_gd_csum }, + { 0, 0, 0, 0 } +}; + +static struct field_set_info mmp_fields[] = { + { "clear", &set_mmp.mmp_magic, NULL, sizeof(set_mmp), parse_mmp_clear }, + { "magic", &set_mmp.mmp_magic, NULL, 4, parse_uint }, + { "seq", &set_mmp.mmp_seq, NULL, 4, parse_uint }, + { "time", &set_mmp.mmp_time, NULL, 8, parse_uint }, + { "nodename", &set_mmp.mmp_nodename, NULL, sizeof(set_mmp.mmp_nodename), + parse_string }, + { "bdevname", &set_mmp.mmp_bdevname, NULL, sizeof(set_mmp.mmp_bdevname), + parse_string }, + { "check_interval", &set_mmp.mmp_check_interval, NULL, 2, parse_uint }, +}; + +static int check_suffix(const char *field) +{ + int len = strlen(field); + + if (len <= 3) + return 0; + field += len-3; + if (!strcmp(field, "_lo")) + return 1; + if (!strcmp(field, "_hi")) + return 2; + return 0; +} + +static struct field_set_info *find_field(struct field_set_info *fields, + char *field) +{ + struct field_set_info *ss; + const char *prefix; + char *arg, *delim, *idx, *tmp; + int suffix, prefix_len; + + if (fields == super_fields) + prefix = "s_"; + else if (fields == inode_fields) + prefix = "i_"; + else + prefix = "bg_"; + prefix_len = strlen(prefix); + if (strncmp(field, prefix, prefix_len) == 0) + field += prefix_len; + + arg = malloc(strlen(field)+1); + if (!arg) + return NULL; + strcpy(arg, field); + + idx = strchr(arg, '['); + if (idx) { + *idx++ = 0; + delim = idx + strlen(idx) - 1; + if (!*idx || *delim != ']') + idx = 0; + else + *delim = 0; + } + /* + * Can we parse the number? + */ + if (idx) { + array_idx = strtol(idx, &tmp, 0); + if (*tmp) { + *(--idx) = '['; + *delim = ']'; + idx = 0; + } + } + + /* + * If there is a valid _hi or a _lo suffix, strip it off + */ + suffix = check_suffix(arg); + if (suffix > 0) + arg[strlen(arg)-3] = 0; + + for (ss = fields ; ss->name ; ss++) { + if (suffix && ss->ptr2 == 0) + continue; + if (ss->flags & FLAG_ARRAY) { + if (!idx || (strcmp(ss->name, arg) != 0)) + continue; + if (ss->max_idx > 0 && array_idx >= ss->max_idx) + continue; + } else { + if (strcmp(ss->name, arg) != 0) + continue; + } + free(arg); + return ss; + } + free(arg); + return NULL; +} + +/* + * Note: info->size == 6 is special; this means a base size 4 bytes, + * and secondiory (high) size of 2 bytes. This is needed for the + * special case of i_blocks_high and i_file_acl_high. + */ +static errcode_t parse_uint(struct field_set_info *info, char *field, + char *arg) +{ + unsigned long long n, num, mask, limit; + int suffix = check_suffix(field); + char *tmp; + void *field1 = info->ptr, *field2 = info->ptr2; + int size = (info->size == 6) ? 4 : info->size; + union { + __u64 *ptr64; + __u32 *ptr32; + __u16 *ptr16; + __u8 *ptr8; + } u; + + if (suffix == 1) + field2 = 0; + if (suffix == 2) { + field1 = field2; + field2 = 0; + } + + u.ptr8 = (__u8 *) field1; + if (info->flags & FLAG_ARRAY) + u.ptr8 += array_idx * info->size; + + errno = 0; + num = STRTOULL(arg, &tmp, 0); + if (*tmp || errno) { + fprintf(stderr, "Couldn't parse '%s' for field %s.\n", + arg, info->name); + return EINVAL; + } + mask = ~0ULL >> ((8 - size) * 8); + limit = ~0ULL >> ((8 - info->size) * 8); + if (field2 && info->size != 6) + limit = ~0ULL >> ((8 - info->size*2) * 8); + + if (num > limit) { + fprintf(stderr, "Value '%s' exceeds field %s maximum %llu.\n", + arg, info->name, limit); + return EINVAL; + } + n = num & mask; + switch (size) { + case 8: + /* Should never get here */ + fprintf(stderr, "64-bit field %s has a second 64-bit field\n" + "defined; BUG?!?\n", info->name); + *u.ptr64 = 0; + break; + case 4: + *u.ptr32 = n; + break; + case 2: + *u.ptr16 = n; + break; + case 1: + *u.ptr8 = n; + break; + } + if (!field2) + return 0; + n = num >> (size*8); + u.ptr8 = (__u8 *) field2; + if (info->size == 6) + size = 2; + switch (size) { + case 8: + *u.ptr64 = n; + break; + case 4: + *u.ptr32 = n; + break; + case 2: + *u.ptr16 = n; + break; + case 1: + *u.ptr8 = n; + break; + } + return 0; +} + +static errcode_t parse_int(struct field_set_info *info, + char *field EXT2FS_ATTR((unused)), char *arg) +{ + long num; + char *tmp; + __s32 *ptr32; + __s16 *ptr16; + __s8 *ptr8; + + num = strtol(arg, &tmp, 0); + if (*tmp) { + fprintf(stderr, "Couldn't parse '%s' for field %s.\n", + arg, info->name); + return EINVAL; + } + switch (info->size) { + case 4: + ptr32 = (__s32 *) info->ptr; + *ptr32 = num; + break; + case 2: + ptr16 = (__s16 *) info->ptr; + *ptr16 = num; + break; + case 1: + ptr8 = (__s8 *) info->ptr; + *ptr8 = num; + break; + } + return 0; +} + +static errcode_t parse_string(struct field_set_info *info, + char *field EXT2FS_ATTR((unused)), char *arg) +{ + char *cp = (char *) info->ptr; + + if (strlen(arg) >= info->size) { + fprintf(stderr, "Error maximum size for %s is %d.\n", + info->name, info->size); + return EINVAL; + } + strcpy(cp, arg); + return 0; +} + +static errcode_t parse_time(struct field_set_info *info, + char *field EXT2FS_ATTR((unused)), char *arg) +{ + time_t t; + __u32 *ptr32; + + ptr32 = (__u32 *) info->ptr; + + t = string_to_time(arg); + + if (t == ((time_t) -1)) { + fprintf(stderr, "Couldn't parse '%s' for field %s.\n", + arg, info->name); + return EINVAL; + } + *ptr32 = t; + return 0; +} + +static errcode_t parse_uuid(struct field_set_info *info, + char *field EXT2FS_ATTR((unused)), char *arg) +{ + unsigned char * p = (unsigned char *) info->ptr; + + if ((strcasecmp(arg, "null") == 0) || + (strcasecmp(arg, "clear") == 0)) { + uuid_clear(p); + } else if (strcasecmp(arg, "time") == 0) { + uuid_generate_time(p); + } else if (strcasecmp(arg, "random") == 0) { + uuid_generate(p); + } else if (uuid_parse(arg, p)) { + fprintf(stderr, "Invalid UUID format: %s\n", arg); + return EINVAL; + } + return 0; +} + +static errcode_t parse_hashalg(struct field_set_info *info, + char *field EXT2FS_ATTR((unused)), char *arg) +{ + int hashv; + unsigned char *p = (unsigned char *) info->ptr; + + hashv = e2p_string2hash(arg); + if (hashv < 0) { + fprintf(stderr, "Invalid hash algorithm: %s\n", arg); + return EINVAL; + } + *p = hashv; + return 0; +} + +static errcode_t parse_bmap(struct field_set_info *info, + char *field EXT2FS_ATTR((unused)), char *arg) +{ + blk64_t blk; + errcode_t retval; + char *tmp; + + blk = strtoull(arg, &tmp, 0); + if (*tmp) { + fprintf(stderr, "Couldn't parse '%s' for field %s.\n", + arg, info->name); + return EINVAL; + } + + retval = ext2fs_bmap2(current_fs, set_ino, + (struct ext2_inode *) &set_inode, + NULL, BMAP_ALLOC | BMAP_SET, array_idx, NULL, + &blk); + if (retval) { + com_err("set_inode", retval, "while setting block map"); + } + return retval; +} + +static errcode_t parse_gd_csum(struct field_set_info *info, char *field, + char *arg) +{ + + if (strcmp(arg, "calc") == 0) { + ext2fs_group_desc_csum_set(current_fs, set_bg); + memcpy(&set_gd, ext2fs_group_desc(current_fs, + current_fs->group_desc, + set_bg), + sizeof(set_gd)); + printf("Checksum set to 0x%04x\n", + ext2fs_bg_checksum(current_fs, set_bg)); + return 0; + } + + return parse_uint(info, field, arg); +} + +static void print_possible_fields(struct field_set_info *fields) +{ + struct field_set_info *ss; + const char *type, *cmd; + FILE *f; + char name[40], idx[40]; + + if (fields == super_fields) { + type = "Superblock"; + cmd = "set_super_value"; + } else if (fields == inode_fields) { + type = "Inode"; + cmd = "set_inode"; + } else if (fields == mmp_fields) { + type = "MMP"; + cmd = "set_mmp_value"; + } else { + type = "Block group descriptor"; + cmd = "set_block_group"; + } + f = open_pager(); + + fprintf(f, "%s fields supported by the %s command:\n", type, cmd); + + for (ss = fields ; ss->name ; ss++) { + type = "unknown"; + if (ss->func == parse_string) + type = "string"; + else if (ss->func == parse_int) + type = "integer"; + else if (ss->func == parse_uint) + type = "unsigned integer"; + else if (ss->func == parse_uuid) + type = "UUID"; + else if (ss->func == parse_hashalg) + type = "hash algorithm"; + else if (ss->func == parse_time) + type = "date/time"; + else if (ss->func == parse_bmap) + type = "set physical->logical block map"; + else if (ss->func == parse_gd_csum) + type = "unsigned integer OR \"calc\""; + strcpy(name, ss->name); + if (ss->flags & FLAG_ARRAY) { + if (ss->max_idx > 0) + sprintf(idx, "[%d]", ss->max_idx); + else + strcpy(idx, "[]"); + strcat(name, idx); + } + if (ss->ptr2) + strcat(name, "[_hi|_lo]"); + fprintf(f, "\t%-25s\t%s\n", name, type); + } + close_pager(f); +} + + +void do_set_super(int argc, char *argv[]) +{ + const char *usage = "<field> <value>\n" + "\t\"set_super_value -l\" will list the names of " + "superblock fields\n\twhich can be set."; + static struct field_set_info *ss; + + if ((argc == 2) && !strcmp(argv[1], "-l")) { + print_possible_fields(super_fields); + return; + } + + if (common_args_process(argc, argv, 3, 3, "set_super_value", + usage, CHECK_FS_RW)) + return; + + if ((ss = find_field(super_fields, argv[1])) == 0) { + com_err(argv[0], 0, "invalid field specifier: %s", argv[1]); + return; + } + set_sb = *current_fs->super; + if (ss->func(ss, argv[1], argv[2]) == 0) { + *current_fs->super = set_sb; + ext2fs_mark_super_dirty(current_fs); + } +} + +void do_set_inode(int argc, char *argv[]) +{ + const char *usage = "<inode> <field> <value>\n" + "\t\"set_inode_field -l\" will list the names of " + "the fields in an ext2 inode\n\twhich can be set."; + static struct field_set_info *ss; + + if ((argc == 2) && !strcmp(argv[1], "-l")) { + print_possible_fields(inode_fields); + return; + } + + if (common_args_process(argc, argv, 4, 4, "set_inode", + usage, CHECK_FS_RW)) + return; + + if ((ss = find_field(inode_fields, argv[2])) == 0) { + com_err(argv[0], 0, "invalid field specifier: %s", argv[2]); + return; + } + + set_ino = string_to_inode(argv[1]); + if (!set_ino) + return; + + if (debugfs_read_inode_full(set_ino, + (struct ext2_inode *) &set_inode, argv[1], + sizeof(set_inode))) + return; + + if (ss->func(ss, argv[2], argv[3]) == 0) { + if (debugfs_write_inode_full(set_ino, + (struct ext2_inode *) &set_inode, + argv[1], sizeof(set_inode))) + return; + } +} + +void do_set_block_group_descriptor(int argc, char *argv[]) +{ + const char *usage = "<bg number> <field> <value>\n" + "\t\"set_block_group_descriptor -l\" will list the names of " + "the fields in a block group descriptor\n\twhich can be set."; + struct field_set_info *table; + struct field_set_info *ss; + char *end; + void *edit, *target; + int size; + + /* + * Determine whether we are editing an ext2 or ext4 block group + * descriptor. Descriptors larger than ext4_group_desc cannot + * have their fields edited yet, because they do not have any + * names assigned. When that happens, this function needs to + * be updated for the new descriptor struct and fields. + */ + if (current_fs && + EXT2_DESC_SIZE(current_fs->super) >= EXT2_MIN_DESC_SIZE_64BIT) { + table = ext4_bg_fields; + edit = &set_gd4; + size = sizeof(set_gd4); + } else { + table = ext2_bg_fields; + edit = &set_gd; + size = sizeof(set_gd); + } + + if ((argc == 2) && !strcmp(argv[1], "-l")) { + print_possible_fields(table); + return; + } + + if (common_args_process(argc, argv, 4, 4, "set_block_group_descriptor", + usage, CHECK_FS_RW)) + return; + + set_bg = strtoul(argv[1], &end, 0); + if (*end) { + com_err(argv[0], 0, "invalid block group number: %s", argv[1]); + return; + } + + if (set_bg >= current_fs->group_desc_count) { + com_err(argv[0], 0, "block group number too big: %d", set_bg); + return; + } + + if ((ss = find_field(table, argv[2])) == 0) { + com_err(argv[0], 0, "invalid field specifier: %s", argv[2]); + return; + } + + target = ext2fs_group_desc(current_fs, current_fs->group_desc, set_bg); + memcpy(edit, target, size); + if (ss->func(ss, argv[2], argv[3]) == 0) { + memcpy(target, edit, size); + ext2fs_mark_super_dirty(current_fs); + } +} + +static errcode_t parse_mmp_clear(struct field_set_info *info, + char *field EXT2FS_ATTR((unused)), + char *arg EXT2FS_ATTR((unused))) +{ + errcode_t retval; + + retval = ext2fs_mmp_clear(current_fs); + if (retval != 0) + com_err("set_mmp_value", retval, "while clearing MMP block\n"); + else + memcpy(info->ptr, current_fs->mmp_buf, info->size); + + return 1; /* we don't need the MMP block written again */ +} + +void do_set_mmp_value(int argc, char *argv[]) +{ + const char *usage = "<field> <value>\n" + "\t\"set_mmp_value -l\" will list the names of " + "MMP fields\n\twhich can be set."; + static struct field_set_info *smmp; + struct mmp_struct *mmp_s; + errcode_t retval; + + if (argc == 2 && strcmp(argv[1], "-l") == 0) { + print_possible_fields(mmp_fields); + return; + } + + if (check_fs_open(argv[0])) + return; + + if (current_fs->super->s_mmp_block == 0) { + com_err(argv[0], 0, "no MMP block allocated\n"); + return; + } + + if (common_args_process(argc, argv, 2, 3, "set_mmp_value", + usage, CHECK_FS_RW)) + return; + + mmp_s = current_fs->mmp_buf; + if (mmp_s == NULL) { + retval = ext2fs_get_mem(current_fs->blocksize, &mmp_s); + if (retval) { + com_err(argv[0], retval, "allocating MMP buffer\n"); + return; + } + retval = ext2fs_mmp_read(current_fs, + current_fs->super->s_mmp_block, mmp_s); + if (retval) { + com_err(argv[0], retval, "reading MMP block %llu.\n", + (long long)current_fs->super->s_mmp_block); + ext2fs_free_mem(&mmp_s); + return; + } + current_fs->mmp_buf = mmp_s; + } + + smmp = find_field(mmp_fields, argv[1]); + if (smmp == 0) { + com_err(argv[0], 0, "invalid field specifier: %s", argv[1]); + return; + } + + set_mmp = *mmp_s; + if (smmp->func(smmp, argv[1], argv[2]) == 0) { + ext2fs_mmp_write(current_fs, current_fs->super->s_mmp_block, + &set_mmp); + *mmp_s = set_mmp; + } +} +
diff --git a/debugfs/unused.c b/debugfs/unused.c new file mode 100644 index 0000000..4cb1191 --- /dev/null +++ b/debugfs/unused.c
@@ -0,0 +1,58 @@ +/* + * unused.c --- quick and dirty unused space dumper + * + * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif + +#include "debugfs.h" + +void do_dump_unused(int argc EXT2FS_ATTR((unused)), char **argv) +{ + blk64_t blk; + unsigned char buf[EXT2_MAX_BLOCK_SIZE]; + unsigned int i; + errcode_t retval; + + if (common_args_process(argc, argv, 1, 1, + "dump_unused", "", 0)) + return; + + for (blk=current_fs->super->s_first_data_block; + blk < ext2fs_blocks_count(current_fs->super); blk++) { + if (ext2fs_test_block_bitmap2(current_fs->block_map,blk)) + continue; + retval = io_channel_read_blk64(current_fs->io, blk, 1, buf); + if (retval) { + com_err(argv[0], retval, "While reading block\n"); + return; + } + for (i=0; i < current_fs->blocksize; i++) + if (buf[i]) + break; + if (i >= current_fs->blocksize) + continue; + printf("\nUnused block %llu contains non-zero data:\n\n", + blk); + for (i=0; i < current_fs->blocksize; i++) + fputc(buf[i], stdout); + } +}
diff --git a/debugfs/util.c b/debugfs/util.c new file mode 100644 index 0000000..20c6c61 --- /dev/null +++ b/debugfs/util.c
@@ -0,0 +1,499 @@ +/* + * util.c --- utilities for the debugfs program + * + * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be + * redistributed under the terms of the GNU Public License. + * + */ + +#define _XOPEN_SOURCE 600 /* needed for strptime */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#include <signal.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif +#ifdef HAVE_OPTRESET +extern int optreset; /* defined by BSD, but not others */ +#endif + +#include "ss/ss.h" +#include "debugfs.h" + +/* + * This function resets the libc getopt() function, which keeps + * internal state. Bad design! Stupid libc API designers! No + * biscuit! + * + * BSD-derived getopt() functions require that optind be reset to 1 in + * order to reset getopt() state. This used to be generally accepted + * way of resetting getopt(). However, glibc's getopt() + * has additional getopt() state beyond optind, and requires that + * optind be set zero to reset its state. So the unfortunate state of + * affairs is that BSD-derived versions of getopt() misbehave if + * optind is set to 0 in order to reset getopt(), and glibc's getopt() + * will core dump if optind is set 1 in order to reset getopt(). + * + * More modern versions of BSD require that optreset be set to 1 in + * order to reset getopt(). Sigh. Standards, anyone? + * + * We hide the hair here. + */ +void reset_getopt(void) +{ +#if defined(__GLIBC__) || defined(__linux__) + optind = 0; +#else + optind = 1; +#endif +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif +} + +static const char *pager_search_list[] = { "pager", "more", "less", 0 }; +static const char *pager_dir_list[] = { "/usr/bin", "/bin", 0 }; + +static const char *find_pager(char *buf) +{ + const char **i, **j; + + for (i = pager_search_list; *i; i++) { + for (j = pager_dir_list; *j; j++) { + sprintf(buf, "%s/%s", *j, *i); + if (access(buf, X_OK) == 0) + return(buf); + } + } + return 0; +} + +FILE *open_pager(void) +{ + FILE *outfile = 0; + const char *pager = ss_safe_getenv("DEBUGFS_PAGER"); + char buf[80]; + + signal(SIGPIPE, SIG_IGN); + if (!isatty(1)) + return stdout; + if (!pager) + pager = ss_safe_getenv("PAGER"); + if (!pager) + pager = find_pager(buf); + if (!pager || + (strcmp(pager, "__none__") == 0) || + ((outfile = popen(pager, "w")) == 0)) + return stdout; + return outfile; +} + +void close_pager(FILE *stream) +{ + if (stream && stream != stdout) pclose(stream); +} + +/* + * This routine is used whenever a command needs to turn a string into + * an inode. + */ +ext2_ino_t string_to_inode(char *str) +{ + ext2_ino_t ino; + int len = strlen(str); + char *end; + int retval; + + /* + * If the string is of the form <ino>, then treat it as an + * inode number. + */ + if ((len > 2) && (str[0] == '<') && (str[len-1] == '>')) { + ino = strtoul(str+1, &end, 0); + if (*end=='>') + return ino; + } + + retval = ext2fs_namei(current_fs, root, cwd, str, &ino); + if (retval) { + com_err(str, retval, 0); + return 0; + } + return ino; +} + +/* + * This routine returns 1 if the filesystem is not open, and prints an + * error message to that effect. + */ +int check_fs_open(char *name) +{ + if (!current_fs) { + com_err(name, 0, "Filesystem not open"); + return 1; + } + return 0; +} + +/* + * This routine returns 1 if a filesystem is open, and prints an + * error message to that effect. + */ +int check_fs_not_open(char *name) +{ + if (current_fs) { + com_err(name, 0, + "Filesystem %s is still open. Close it first.\n", + current_fs->device_name); + return 1; + } + return 0; +} + +/* + * This routine returns 1 if a filesystem is not opened read/write, + * and prints an error message to that effect. + */ +int check_fs_read_write(char *name) +{ + if (!(current_fs->flags & EXT2_FLAG_RW)) { + com_err(name, 0, "Filesystem opened read/only"); + return 1; + } + return 0; +} + +/* + * This routine returns 1 if a filesystem is doesn't have its inode + * and block bitmaps loaded, and prints an error message to that + * effect. + */ +int check_fs_bitmaps(char *name) +{ + if (!current_fs->block_map || !current_fs->inode_map) { + com_err(name, 0, "Filesystem bitmaps not loaded"); + return 1; + } + return 0; +} + +/* + * This function takes a __u32 time value and converts it to a string, + * using ctime + */ +char *time_to_string(__u32 cl) +{ + static int do_gmt = -1; + time_t t = (time_t) cl; + const char *tz; + + if (do_gmt == -1) { + /* The diet libc doesn't respect the TZ environemnt variable */ + tz = ss_safe_getenv("TZ"); + if (!tz) + tz = ""; + do_gmt = !strcmp(tz, "GMT") | !strcmp(tz, "GMT0"); + } + + return asctime((do_gmt) ? gmtime(&t) : localtime(&t)); +} + +/* + * Parse a string as a time. Return ((time_t)-1) if the string + * doesn't appear to be a sane time. + */ +time_t string_to_time(const char *arg) +{ + struct tm ts; + time_t ret; + char *tmp; + + if (strcmp(arg, "now") == 0) { + return time(0); + } + if (arg[0] == '@') { + /* interpret it as an integer */ + arg++; + fallback: + ret = strtoul(arg, &tmp, 0); + if (*tmp) + return ((time_t) -1); + return ret; + } + memset(&ts, 0, sizeof(ts)); +#ifdef HAVE_STRPTIME + tmp = strptime(arg, "%Y%m%d%H%M%S", &ts); + if (tmp == NULL) + goto fallback; +#else + sscanf(arg, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon, + &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec); + ts.tm_year -= 1900; + ts.tm_mon -= 1; + if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 || + ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 || + ts.tm_min > 59 || ts.tm_sec > 61) + ts.tm_mday = 0; +#endif + ts.tm_isdst = -1; + /* strptime() may only update the specified fields, which does not + * necessarily include ts.tm_yday (%j). Calculate this if unset: + * + * Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec + * 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + * + * Start with 31 days per month. Even months have only 30 days, but + * reverse in August, subtract one day for those months. February has + * only 28 days, not 30, subtract two days. Add day of month, minus + * one, since day is not finished yet. Leap years handled afterward. */ + if (ts.tm_yday == 0) + ts.tm_yday = (ts.tm_mon * 31) - + ((ts.tm_mon - (ts.tm_mon > 7)) / 2) - + 2 * (ts.tm_mon > 1) + ts.tm_mday - 1; + ret = ts.tm_sec + ts.tm_min*60 + ts.tm_hour*3600 + ts.tm_yday*86400 + + (ts.tm_year-70)*31536000 + ((ts.tm_year-69)/4)*86400 - + ((ts.tm_year-1)/100)*86400 + ((ts.tm_year+299)/400)*86400; + return ret; +} + +/* + * This function will convert a string to an unsigned long, printing + * an error message if it fails, and returning success or failure in err. + */ +unsigned long parse_ulong(const char *str, const char *cmd, + const char *descr, int *err) +{ + char *tmp; + unsigned long ret; + + ret = strtoul(str, &tmp, 0); + if (*tmp == 0) { + if (err) + *err = 0; + return ret; + } + com_err(cmd, 0, "Bad %s - %s", descr, str); + if (err) + *err = 1; + else + exit(1); + return 0; +} + +/* + * This function will convert a string to an unsigned long long, printing + * an error message if it fails, and returning success or failure in err. + */ +unsigned long long parse_ulonglong(const char *str, const char *cmd, + const char *descr, int *err) +{ + char *tmp; + unsigned long long ret; + + ret = strtoull(str, &tmp, 0); + if (*tmp == 0) { + if (err) + *err = 0; + return ret; + } + com_err(cmd, 0, "Bad %s - %s", descr, str); + if (err) + *err = 1; + else + exit(1); + return 0; +} + +/* + * This function will convert a string to a block number. It returns + * 0 on success, 1 on failure. On failure, it outputs either an optionally + * specified error message or a default. + */ +int strtoblk(const char *cmd, const char *str, const char *errmsg, + blk64_t *ret) +{ + blk64_t blk; + int err; + + if (errmsg == NULL) + blk = parse_ulonglong(str, cmd, "block number", &err); + else + blk = parse_ulonglong(str, cmd, errmsg, &err); + *ret = blk; + return err; +} + +/* + * This is a common helper function used by the command processing + * routines + */ +int common_args_process(int argc, char *argv[], int min_argc, int max_argc, + const char *cmd, const char *usage, int flags) +{ + if (argc < min_argc || argc > max_argc) { + com_err(argv[0], 0, "Usage: %s %s", cmd, usage); + return 1; + } + if (flags & CHECK_FS_NOTOPEN) { + if (check_fs_not_open(argv[0])) + return 1; + } else { + if (check_fs_open(argv[0])) + return 1; + } + if ((flags & CHECK_FS_RW) && check_fs_read_write(argv[0])) + return 1; + if ((flags & CHECK_FS_BITMAPS) && check_fs_bitmaps(argv[0])) + return 1; + return 0; +} + +/* + * This is a helper function used by do_stat, do_freei, do_seti, and + * do_testi, etc. Basically, any command which takes a single + * argument which is a file/inode number specifier. + */ +int common_inode_args_process(int argc, char *argv[], + ext2_ino_t *inode, int flags) +{ + if (common_args_process(argc, argv, 2, 2, argv[0], "<file>", flags)) + return 1; + + *inode = string_to_inode(argv[1]); + if (!*inode) + return 1; + return 0; +} + +/* + * This is a helper function used by do_freeb, do_setb, and do_testb + */ +int common_block_args_process(int argc, char *argv[], + blk64_t *block, blk64_t *count) +{ + int err; + + if (common_args_process(argc, argv, 2, 3, argv[0], + "<block> [count]", CHECK_FS_BITMAPS)) + return 1; + + if (strtoblk(argv[0], argv[1], NULL, block)) + return 1; + if (*block == 0) { + com_err(argv[0], 0, "Invalid block number 0"); + err = 1; + } + + if (argc > 2) { + err = strtoblk(argv[0], argv[2], "count", count); + if (err) + return 1; + } + return 0; +} + +int debugfs_read_inode_full(ext2_ino_t ino, struct ext2_inode * inode, + const char *cmd, int bufsize) +{ + int retval; + + retval = ext2fs_read_inode_full(current_fs, ino, inode, bufsize); + if (retval) { + com_err(cmd, retval, "while reading inode %u", ino); + return 1; + } + return 0; +} + +int debugfs_read_inode(ext2_ino_t ino, struct ext2_inode * inode, + const char *cmd) +{ + int retval; + + retval = ext2fs_read_inode(current_fs, ino, inode); + if (retval) { + com_err(cmd, retval, "while reading inode %u", ino); + return 1; + } + return 0; +} + +int debugfs_write_inode_full(ext2_ino_t ino, + struct ext2_inode *inode, + const char *cmd, + int bufsize) +{ + int retval; + + retval = ext2fs_write_inode_full(current_fs, ino, + inode, bufsize); + if (retval) { + com_err(cmd, retval, "while writing inode %u", ino); + return 1; + } + return 0; +} + +int debugfs_write_inode(ext2_ino_t ino, struct ext2_inode * inode, + const char *cmd) +{ + int retval; + + retval = ext2fs_write_inode(current_fs, ino, inode); + if (retval) { + com_err(cmd, retval, "while writing inode %u", ino); + return 1; + } + return 0; +} + +int debugfs_write_new_inode(ext2_ino_t ino, struct ext2_inode * inode, + const char *cmd) +{ + int retval; + + retval = ext2fs_write_new_inode(current_fs, ino, inode); + if (retval) { + com_err(cmd, retval, "while creating inode %u", ino); + return 1; + } + return 0; +} + +/* + * Given a mode, return the ext2 file type + */ +int ext2_file_type(unsigned int mode) +{ + if (LINUX_S_ISREG(mode)) + return EXT2_FT_REG_FILE; + + if (LINUX_S_ISDIR(mode)) + return EXT2_FT_DIR; + + if (LINUX_S_ISCHR(mode)) + return EXT2_FT_CHRDEV; + + if (LINUX_S_ISBLK(mode)) + return EXT2_FT_BLKDEV; + + if (LINUX_S_ISLNK(mode)) + return EXT2_FT_SYMLINK; + + if (LINUX_S_ISFIFO(mode)) + return EXT2_FT_FIFO; + + if (LINUX_S_ISSOCK(mode)) + return EXT2_FT_SOCK; + + return 0; +}
diff --git a/debugfs/zap.c b/debugfs/zap.c new file mode 100644 index 0000000..917bddf --- /dev/null +++ b/debugfs/zap.c
@@ -0,0 +1,265 @@ +/* + * zap.c --- zap block + * + * Copyright (C) 2012 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +extern int optind; +extern char *optarg; +#endif + +#include "debugfs.h" + +void do_zap_block(int argc, char *argv[]) +{ + unsigned long pattern = 0; + unsigned char *buf; + ext2_ino_t inode; + errcode_t errcode; + blk64_t block; + char *file = NULL; + int c, err; + int offset = -1; + int length = -1; + int bit = -1; + + if (check_fs_open(argv[0])) + return; + if (check_fs_read_write(argv[0])) + return; + + reset_getopt(); + while ((c = getopt (argc, argv, "b:f:l:o:p:")) != EOF) { + switch (c) { + case 'f': + file = optarg; + break; + case 'b': + bit = parse_ulong(optarg, argv[0], + "bit", &err); + if (err) + return; + if (bit >= (int) current_fs->blocksize * 8) { + com_err(argv[0], 0, "The bit to flip " + "must be within a %d block\n", + current_fs->blocksize); + return; + } + break; + case 'p': + pattern = parse_ulong(optarg, argv[0], + "pattern", &err); + if (err) + return; + if (pattern >= 256) { + com_err(argv[0], 0, "The fill pattern must " + "be an 8-bit value\n"); + return; + } + break; + case 'o': + offset = parse_ulong(optarg, argv[0], + "offset", &err); + if (err) + return; + if (offset >= (int) current_fs->blocksize) { + com_err(argv[0], 0, "The offset must be " + "within a %d block\n", + current_fs->blocksize); + return; + } + break; + + break; + case 'l': + length = parse_ulong(optarg, argv[0], + "length", &err); + if (err) + return; + break; + default: + goto print_usage; + } + } + + if (bit > 0 && offset > 0) { + com_err(argv[0], 0, "The -o and -b options can not be mixed."); + return; + } + + if (offset < 0) + offset = 0; + if (length < 0) + length = current_fs->blocksize - offset; + if ((offset + length) > (int) current_fs->blocksize) { + com_err(argv[0], 0, "The specified length is too bug\n"); + return; + } + + if (argc != optind+1) { + print_usage: + com_err(0, 0, "Usage:\tzap_block [-f file] [-o offset] " + "[-l length] [-p pattern] block_num"); + com_err(0, 0, "\tzap_block [-f file] [-b bit] " + "block_num"); + return; + } + + block = parse_ulonglong(argv[optind], argv[0], "block", &err); + if (err) + return; + + if (file) { + inode = string_to_inode(file); + if (!inode) + return; + errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0, + block, 0, &block); + if (errcode) { + com_err(argv[0], errcode, + "while mapping logical block %llu\n", block); + return; + } + } + + buf = malloc(current_fs->blocksize); + if (!buf) { + com_err(argv[0], 0, "Couldn't allocate block buffer"); + return; + } + + errcode = io_channel_read_blk64(current_fs->io, block, 1, buf); + if (errcode) { + com_err(argv[0], errcode, + "while reading block %llu\n", block); + goto errout; + } + + if (bit >= 0) + buf[bit >> 3] ^= 1 << (bit & 7); + else + memset(buf+offset, pattern, length); + + errcode = io_channel_write_blk64(current_fs->io, block, 1, buf); + if (errcode) { + com_err(argv[0], errcode, + "while write block %llu\n", block); + goto errout; + } + +errout: + free(buf); + return; +} + +void do_block_dump(int argc, char *argv[]) +{ + unsigned char *buf; + ext2_ino_t inode; + errcode_t errcode; + blk64_t block; + char *file = NULL; + unsigned int i, j; + int c, err; + + if (check_fs_open(argv[0])) + return; + + reset_getopt(); + while ((c = getopt (argc, argv, "f:")) != EOF) { + switch (c) { + case 'f': + file = optarg; + break; + + default: + goto print_usage; + } + } + + if (argc != optind + 1) { + print_usage: + com_err(0, 0, "Usage: block_dump [-f inode] block_num"); + return; + } + + block = parse_ulonglong(argv[optind], argv[0], "block", &err); + if (err) + return; + + if (file) { + inode = string_to_inode(file); + if (!inode) + return; + errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0, + block, 0, &block); + if (errcode) { + com_err(argv[0], errcode, + "while mapping logical block %llu\n", block); + return; + } + } + + buf = malloc(current_fs->blocksize); + if (!buf) { + com_err(argv[0], 0, "Couldn't allocate block buffer"); + return; + } + + errcode = io_channel_read_blk64(current_fs->io, block, 1, buf); + if (errcode) { + com_err(argv[0], errcode, + "while reading block %llu\n", block); + goto errout; + } + + do_byte_hexdump(stdout, buf, current_fs->blocksize); +errout: + free(buf); +} + +void do_byte_hexdump(FILE *fp, unsigned char *buf, size_t bufsize) +{ + size_t i, j; + int suppress = -1; + + for (i = 0; i < bufsize; i += 16) { + if (suppress < 0) { + if (i && memcmp(buf + i, buf + i - 16, 16) == 0) { + suppress = i; + fprintf(fp, "*\n"); + continue; + } + } else { + if (memcmp(buf + i, buf + suppress, 16) == 0) + continue; + suppress = -1; + } + fprintf(fp, "%04o ", (unsigned int)i); + for (j = 0; j < 16; j++) { + fprintf(fp, "%02x", buf[i+j]); + if ((j % 2) == 1) + fprintf(fp, " "); + } + fprintf(fp, " "); + for (j = 0; j < 16; j++) + fprintf(fp, "%c", isprint(buf[i+j]) ? buf[i+j] : '.'); + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); +}
diff --git a/depfix.sed b/depfix.sed new file mode 100644 index 0000000..582d79f --- /dev/null +++ b/depfix.sed
@@ -0,0 +1,35 @@ +# +# Insert the header..... +# +1i\ +# +++ Dependency line eater +++\ +# \ +# Makefile dependencies follow. This must be the last section in\ +# the Makefile.in file\ +# + +# +# Remove line continuations.... +# +:FIRST +y/ / / +s/^ *// +/\\$/{ +N +y/ / / +s/\\\n */ / +bFIRST +} +s/ */ /g + +s;/usr/include/[^ ]* *;;g +s;/usr/lib/[^ ]* *;;g +s;/mit/cygnus[^ ]* *;;g +s;\.\./[^ ]*lib/blkid/blkid[^ ]* *;;g +s;\.\./[^ ]*lib/uuid/uuid.h[^ ]* *;;g + +# +# Now insert a trailing newline... +# +$a\ +
diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..a2b2612 --- /dev/null +++ b/doc/Makefile.in
@@ -0,0 +1,84 @@ +# +# Makefile for the doc directory +# + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +top_builddir = .. +my_dir = doc +INSTALL = @INSTALL@ + +@MCONFIG@ + +DVI=texi2dvi +DVIPS=dvips -o "$@" +INFO=@MAKEINFO@ +HTML=makeinfo --html --no-split +PS2PDF=ps2pdf + +all:: libext2fs.info libext2fs.dvi libext2fs.html + +install-doc-libs: libext2fs.info libext2fs.dvi + $(Q) $(RM) -rf $(DESTDIR)$(infodir)/libext2fs.info* + $(E) " MKINSTALLDIRS $(infodir)" + $(Q) $(MKINSTALLDIRS) $(DESTDIR)$(infodir) + -$(Q) for i in libext2fs.info* ; do \ + echo " INSTALL_DATA $(infodir)/$$i" ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(infodir)/$$i ; \ + done + $(E) " GZIP $(infodir)/libext2fs.info*" + -$(Q) gzip -9 $(DESTDIR)$(infodir)/libext2fs.info* + +uninstall-doc-libs: + $(RM) -rf $(DESTDIR)$(infodir)/libext2fs.info* + +libext2fs.info: $(srcdir)/libext2fs.texinfo + $(E) " MAKEINFO $@" + -$(Q) $(INFO) $(srcdir)/libext2fs.texinfo + +libext2fs.dvi: $(srcdir)/libext2fs.texinfo + $(E) " TEXI2DVI $@" + -$(Q) $(DVI) $(srcdir)/libext2fs.texinfo + +libext2fs.ps: libext2fs.dvi + $(E) " DVIPS $@" + -$(Q) $(DVIPS) libext2fs.dvi + +libext2fs.pdf: libext2fs.ps + $(E) " PS2PDF $@" + -$(Q) $(PS2PDF) libext2fs.ps + +libext2fs.html: $(srcdir)/libext2fs.texinfo + $(E) " TEXI2HTML $@" + -$(Q) $(HTML) $(srcdir)/libext2fs.texinfo + +.PHONY: distclean +distclean:: clean + $(RM) -f Makefile + +.PHONY: clean +clean:: clean-all + +.PHONY: clean-all +clean-all:: clean-tex clean-backup clean-final clean-tarfiles clean-html + +.PHONY: clean-final +clean-final:: + $(RM) -f *.ps *.info *.info-? *.html *.pdf + +.PHONY: clean-tex +clean-tex:: + $(RM) -f *.aux *.cp *.dvi *.fn *.ky *.log *.pg *.toc *.tp *.vr *.fns + +.PHONY: clean-backup +clean-backup:: + $(RM) -f *~ #* + +.PHONY: clean-tarfiles +clean-tarfiles:: + $(RM) -f *.tar *.tar.gz *.tgz + +clean-html:: + $(RM) -f *.html +
diff --git a/doc/libblkid.txt b/doc/libblkid.txt new file mode 100644 index 0000000..4aea1b6 --- /dev/null +++ b/doc/libblkid.txt
@@ -0,0 +1,78 @@ +libblkid - a library to handle device identification and token extraction + +Basic usage is as follows - there are two normal usage patterns: + +For cases where a program wants information about multiple devices, or +expects to be doing multiple token searches, the program should +directly initialize cache file via (second parameter is cache +filename, NULL = default): + + blkid_cache cache = NULL; + if (blkid_get_cache(&cache, NULL) < 0) + /* error reading the cache file, not really fatal */ + +Note that if no cache file exists, an empty cache struct is still +allocated. Usage of libblkid functions will use the cache to avoid +needless device scans. + +The model of the blkid cache is that each device has a number of +attributes that can be associated with it. Currently the attributes +which are supported (and set) by blkid are: + + TYPE filesystem type + UUID filesystem uuid + LABEL filesystem label + + +How to use libblkid? Normally, you either want to find a device with +a specific NAME=value token, or you want to output token(s) from a +device. To find a device that matches a following attribute, you +simply call the blkid_get_devname() function: + + if ((devname = blkid_get_devname(cache, attribute_name, value))) { + /* do something with devname */ + string_free(devname); + } + +The cache parameter is optional; if it is NULL, then the blkid library +will load the default blkid.tab cache file, and then release the cache +before function call returns. The return value is an allocated string +which holds the resulting device name (if it is found). If the value +is NULL, then attribute_name is parsed as if it were +"<attribute_name>=<value>"; if it cannot be so parsed, then the +original attribute_name is returned in a copied allocated string. +This is a convenience to allow user programs to want to translate user +input, whether it is of the form: "/dev/hda1", "LABEL=root", +"UUID=082D-26E3", and get back a device name that it can use. + +Alternatively, of course, the programmer can pass an attribute name of +"LABEL", and value of "root", if that is more convenient. + +Another common usage is to retrieve the value of a specific attribute +for a particular device. This can be used to determine the filesystem +type, or label, or uuid for a particular device: + + if ((value = blkid_get_tag_value(cache, attribute_name, devname))) { + /* do something with value */ + string_free(value); + } + +If a program needs to call multiple blkid functions, then passing in a +cache value of NULL is not recommended, since the /etc/blkid.tab file +will be repeatedly parsed over and over again, with memory allocated +and deallocated. To initialize the blkid cache, blkid_get_cache() +function is used: + + if (blkid_get_cache(&cache, NULL) < 0) + goto errout; + +The second parameter of blkid_get_cache (if non-zero) is the alternate +filename of the blkid cache file (where the default is +/etc/blkid.tab). Normally, programs should just pass in NULL. + +If you have called blkid_get_cache(), you should call blkid_put_cache() +when you are done using the blkid library functions. This will save the +cache to the blkid.tab file, if you have write access to the file. It +will also free all associated devices and tags: + + blkid_put_cache(cache);
diff --git a/doc/libext2fs.texinfo b/doc/libext2fs.texinfo new file mode 100644 index 0000000..c6699fe --- /dev/null +++ b/doc/libext2fs.texinfo
@@ -0,0 +1,1374 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename libext2fs.info +@settitle The EXT2FS Library (version 1.42.13) +@synindex tp fn +@comment %**end of header + +@ifinfo +@dircategory Development +@direntry +* libext2fs: (libext2fs). The EXT2FS library. +@end direntry +@end ifinfo + +@c smallbook + +@iftex +@finalout +@end iftex + +@c Note: the edition number is listed in *three* places; please update +@c all three. Also, update the month and year where appropriate. + +@c ==> Update edition number for settitle and subtitle, and in the +@c ==> following paragraph; update date, too. + + +@ifinfo +This file documents the ext2fs library, a library for manipulating the +ext2 filesystem. + +Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, +2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 by Theodore Ts'o + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through TeX and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the author. +@end ifinfo + +@setchapternewpage on +@titlepage +@c use the new format for titles + +@title The EXT2FS Library +@subtitle The EXT2FS Library +@subtitle Version 1.42.13 +@subtitle May 2015 + +@author by Theodore Ts'o + +@c Include the Distribution inside the titlepage so +@c that headings are turned off. + +@tex +\global\parindent=0pt +\global\parskip=8pt +\global\baselineskip=13pt +@end tex + +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Theodore Ts'o + +@sp 2 + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the above conditions for modified versions, +except that this permission notice may be stated in a translation approved +by the Foundation. +@end titlepage +@headings double + +@node Top, Introduction to the EXT2FS Library, (dir), (dir) + +@top The EXT2FS Library + +This manual documents the EXT2FS Library, version 1.42.13. + +@menu +* Introduction to the EXT2FS Library:: +* EXT2FS Library Functions:: +* Concept Index:: +* Function Index:: +@end menu + +@c ---------------------------------------------------------------------- + +@node Introduction to the EXT2FS Library, EXT2FS Library Functions, Top, Top +@comment node-name, next, previous, up +@chapter Introduction to the EXT2FS Library + +The EXT2FS library is designed to allow user-level programs to +manipulate an ext2 filesystem. + +@node EXT2FS Library Functions, Concept Index, Introduction to the EXT2FS Library, Top +@comment node-name, next, previous, up +@chapter EXT2FS Library Functions + +@menu +* Filesystem-level functions:: +* File I/O Functions:: +* Inode Functions:: +* Directory functions:: +* Bitmap Functions:: +* EXT2 data abstractions:: +* Byte-swapping functions:: +* Other functions:: +@end menu + +@c ---------------------------------------------------------------------- + +@node Filesystem-level functions, File I/O Functions, EXT2FS Library Functions, EXT2FS Library Functions +@comment node-name, next, previous, up +@section Filesystem-level functions + +The following functions operate on a filesystem handle. Most EXT2FS +Library functions require a filesystem handle as their first argument. +There are two functions which create a filesystem handle, +@code{ext2fs_open} and @code{ext2fs_initialize}. + +The filesystem can also be closed using @code{ext2fs_close}, and any +changes to the superblock and group descripts can be written out to disk +using @code{ext2fs_flush}. + +@menu +* Opening an ext2 filesystem:: +* Closing and flushing out changes:: +* Initializing a filesystem:: +* Filesystem flag functions:: +@end menu + +@c ---------------------------------------------------------------------- + +@node Opening an ext2 filesystem, Closing and flushing out changes, Filesystem-level functions, Filesystem-level functions +@comment node-name, next, previous, up +@subsection Opening an ext2 filesystem + +Most libext2fs functions take a filesystem handle of type +@code{ext2_filsys}. A filesystem handle is created either by opening +an existing function using @code{ext2fs_open}, or by initializing a new +filesystem using @code{ext2fs_initialize}. + +@deftypefun errcode_t ext2fs_open (const char *@var{name}, int @var{flags}, int @var{superblock}, int @var{block_size}, io_manager @var{manager}, ext2_filsys *@var{ret_fs}) + +Opens a filesystem named @var{name}, using the the io_manager +@var{manager} to define the input/output routines needed to read and +write the filesystem. In the case of the @code{unix_io} io_manager, +@var{name} is interpreted as the Unix filename of the filesystem image. +This is often a device file, such as @file{/dev/hda1}. + +The @var{superblock} parameter specifies the block number of the +superblock which should be used when opening the filesystem. +If @var{superblock} is zero, @code{ext2fs_open} will use the primary +superblock located at offset 1024 bytes from the start of the filesystem +image. + +The @var{block_size} parameter specifies the block size used by the +filesystem. Normally this is determined automatically from the +filesystem uperblock. If @var{block_size} is non-zero, it must match +the block size found in the superblock, or the error +@code{EXT2_ET_UNEXPECTED_BLOCK_SIZE} will be returned. The +@var{block_size} parameter is also used to help fund the superblock when +@var{superblock} is non-zero. + +The @var{flags} argument contains a bitmask of flags which control how +the filesystem open should be handled. + +@table @code +@item EXT2_FLAG_RW +Open the filesystem for reading and writing. Without this flag, the +filesystem is opened for reading only. + +@item EXT2_FLAG_FORCE +Open the filesystem regardless of the feature sets listed in the +superblock. + +@end table +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Closing and flushing out changes, Initializing a filesystem, Opening an ext2 filesystem, Filesystem-level functions +@comment node-name, next, previous, up +@subsection Closing and flushing out changes + +@deftypefun errcode_t ext2fs_flush (ext2_filsys @var{fs}) + +Write any changes to the high-level filesystem data structures in the +@var{fs} filesystem. The following data structures will be written out: + +@itemize @bullet +@item The filesystem superblock +@item The filesystem group descriptors +@item The filesystem bitmaps, if read in via @code{ext2fs_read_bitmaps}. +@end itemize + +@end deftypefun + +@deftypefun void ext2fs_free (ext2_filsys @var{fs}) + +Close the io_manager abstraction for @var{fs} and release all memory +associated with the filesystem handle. +@end deftypefun + +@deftypefun errcode_t ext2fs_close (ext2_filsys @var{fs}) + +Flush out any changes to the high-level filesystem data structures using +@code{ext2fs_flush} if the filesystem is marked dirty; then close and +free the filesystem using @code{ext2fs_free}. + +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Initializing a filesystem, Filesystem flag functions, Closing and flushing out changes, Filesystem-level functions +@comment node-name, next, previous, up +@subsection Initializing a filesystem + +An ext2 filesystem is initializing by the @code{mke2fs} program. The +two functions described here, @code{ext2fs_initialize} and +@code{ext2fs_allocate_tables} do much of the initial work for setting up +a filesystem. However, they don't do the whole job. @code{mke2fs} +calls @code{ext2fs_initialize} to set up the filesystem superblock, and +calls @code{ext2fs_allocate_tables} to allocate space for the inode +table, and the inode and block bitmaps. In addition, @code{mke2fs} must +also initialize the inode tables by clearing them with zeros, create the +root and lost+found directories, and reserve the reserved inodes. + +@deftypefun errcode_t ext2fs_initialize (const char *@var{name}, int @var{flags}, struct ext2_super_block *@var{param}, io_manager @var{manager}, ext2_filsys *@var{ret_fs}) + +This function is used by the @code{mke2fs} program to initialize a +filesystem. The @code{ext2fs_initialize} function creates a filesystem +handle which is returned in @var{ret_fs} that has been properly setup +for a filesystem to be located in @var{name}, using the io_manager +@var{manager}. The prototype superblock in @var{param} is used to +supply parameters such as the number of blocks in the filesystem, the +block size, etc. + +The @code{ext2fs_initialize} function does not actually do any I/O; that +will be done when the application program calls @code{ext2fs_close} or +@code{ext2fs_flush}. Also, this function only initializes the +superblock and group descriptor structures. It does not create the +inode table or the root directory. This must be done by the calling +application, such as @code{mke2fs}. + +The following values may be set in the @var{param} prototype superblock; +if a value of 0 is found in a field, @code{ext2fs_initialize} will use a +default value. The calling application should zero out the prototype +entire superblock, and then fill in any appropriate values. + +@table @code + +@item s_blocks_count +The number of blocks in the filesystem. This parameter is mandatory and +must be set by the calling application. + +@item s_inodes_count +The number of inodes in the filesystem. The +default value is determined by calculating the size of the filesystem, +and creating one inode for every 4096 bytes. + +@item s_r_blocks_count +The number of blocks which should be reserved for the superuser. The +default value is zero blocks. + +@item s_log_block_size +The blocksize of the filesystem. Valid values are 0 (1024 bytes), 1 +(2048 bytes), or 2 (4096 bytes). The default blocksize is 1024 bytes. + +@item s_log_frag_size +The size of fragments. The ext2 filesystem does not support fragments +(and may never support fragments). Currently this field must be the +same as @code{s_log_block_size}. + +@item s_first_data_block +The first data block for the filesystem. For filesystem with a +blocksize of 1024 bytes, this value must be at least 1, since the +superblock is located in block number 1. For filesystems with larger +blocksizes, the superblock is still located at an offset of 1024 bytes, +so the superblock is located in block number 0. By default, this value +is set to 1 for filesystems with a block size of 1024 bytes, or 0 for +filesystems with larger blocksizes. + +@item s_max_mnt_count +This field defines the number of times that the filesystem can be +mounted before it should be checked using @code{e2fsck}. When +@code{e2fsck} is run without the @samp{-f} option, @code{e2fsck} will +skip the filesystem check if the number of times that the filesystem has +been mounted is less than @code{s_max_mnt_count} and if the interval +between the last time a filesystem check was performed and the current +time is less than @code{s_checkinterval} (see below). The default value +of @code{s_max_mnt_count} is 20. + +@item s_checkinterval +This field defines the minimal interval between filesystem checks. See +the previous entry for a discussion of how this field is used by +@code{e2fsck}. The default value of this field is 180 days (six +months). + +@item s_errors +This field defines the behavior which should be used by the kernel of +errors are detected in the filesystem. Possible values include: + +@table @samp +@item EXT2_ERRORS_CONTINUE +Continue execution when errors are detected. + +@item EXT2_ERRORS_RO +Remount the filesystem read-only. + +@item EXT2_ERRORS_PANIC +Panic. + +@end table + +The default behavior is @samp{EXT2_ERRORS_CONTINUE}. + +@end table + +@end deftypefun + +@deftypefun errcode_t ext2fs_allocate_tables (ext2_filsys @var{fs}) +Allocate space for the inode table and the block and inode bitmaps. The +inode tables and block and inode bitmaps aren't actually initialized; +this function just allocates the space for them. +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Filesystem flag functions, , Initializing a filesystem, Filesystem-level functions +@comment node-name, next, previous, up +@subsection Filesystem flag functions + +The filesystem handle has a number of flags which can be manipulated +using the following function. Some of these flags affect how the +libext2fs filesystem behaves; others are provided solely for the +application's convenience. + +@deftypefun void ext2fs_mark_changed (ext2_filsys @var{fs}) +@deftypefunx int ext2fs_test_changed (ext2_filsys @var{fs}) +This flag indicates whether or not the filesystem has been changed. +It is not used by the ext2fs library. +@end deftypefun + +@deftypefun void ext2fs_mark_super_dirty (ext2_filsys @var{fs}) +Mark the filesystem @var{fs} as being dirty; this will cause +the superblock information to be flushed out when @code{ext2fs_close} is +called. @code{ext2fs_mark_super_dirty} will also set the filesystem +changed flag. The dirty flag is automatically cleared by +@code{ext2fs_flush} when the superblock is written to disk. +@end deftypefun + +@deftypefun void ext2fs_mark_valid (ext2_filsys @var{fs}) +@deftypefunx void ext2fs_unmark_valid (ext2_filsys @var{fs}) +@deftypefunx int ext2fs_test_valid (ext2_filsys @var{fs}) +This flag indicates whether or not the filesystem is free of errors. +It is not used by libext2fs, and is solely for the application's +convenience. +@end deftypefun + +@deftypefun void ext2fs_mark_ib_dirty (ext2_filsys @var{fs}) +@deftypefunx void ext2fs_mark_bb_dirty (ext2_filsys @var{fs}) +@deftypefunx int ext2fs_test_ib_dirty (ext2_filsys @var{fs}) +@deftypefunx int ext2fs_test_bb_dirty (ext2_filsys @var{fs}) +These flags indicate whether or not the inode or block bitmaps have been +modified. If the flag is set, it will cause the appropriate bitmap +to be written when the filesystem is closed or flushed. +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node File I/O Functions, Inode Functions, Filesystem-level functions, EXT2FS Library Functions +@comment node-name, next, previous, up +@section File I/O Functions + +The following functions provide a convenient abstraction to read or +write a file in an filesystem. The interface is similar in spirit to +the Linux/POSIX file I/O system calls. + +@menu +* File handle manipulation:: +* Reading and writing data:: +* Changing the file offset :: +* Getting the file size:: +@end menu + +@c ---------------------------------------------------------------------- + +@node File handle manipulation, Reading and writing data, File I/O Functions, File I/O Functions +@comment node-name, next, previous, up +@subsection File handle manipulation + +The file handle functions much like a file descriptor in the Linux/POSIX +file I/O system calls. Unlike the Linux/POSIX system calls, files are +opened via inode numbers instead of via pathnames. To resolve a +pathname to an inode number, use the function @code{ext2fs_namei} or to +create a new file, use @code{ext2fs_new_inode} and @code{ext2fs_link}. + +@deftypefun errcode_t ext2fs_file_open2 (ext2_filsys @var{fs}, ext2_ino_t @var{ino}, struct ext2_inode *@var{inode}, int @var{flags}, ext2_file_t *@var{ret}) +@deftypefunx errcode_t ext2fs_file_open (ext2_filsys @var{fs}, ext2_ino_t @var{ino}, int @var{flags}, ext2_file_t *@var{ret}) + +Opens a file identified by inode number @var{ino} in filesystem @var{fs} +and returns a file handle in @var{ret}. If an inode structure is +provided in @var{inode}, then it is used instead of reading the inode +from the filesystem. + +The @var{flags} argument contains a bitmask of flags which control how +the file should be opened. + +@table @code +@item EXT2_FILE_WRITE +Open the file for reading and writing. Without this flag, the file is +opened for writing only. + +@item EXT2_FILE_CREATE +Create the file if it is not already present. + +@end table +@end deftypefun + +@deftypefun ext2_filsys ext2fs_file_get_fs (ext2_file_t @var{file}) +Return the filesystem handle where the open file @var{file} was opened. +@end deftypefun + +@deftypefun errcode_t ext2fs_file_close (ext2_file_t @var{file}) +Close the file handle @var{file}. +@end deftypefun + +@deftypefun errcode_t ext2fs_file_flush (ext2_file_t @var{file}) +Force any data written via @code{ext2fs_file_write} to disk. +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Reading and writing data, Changing the file offset , File handle manipulation, File I/O Functions +@comment node-name, next, previous, up +@subsection Reading and writing data + +@deftypefun errcode_t ext2fs_file_read (ext2_file_t @var{file}, void *@var{buf}, unsigned int @var{wanted}, unsigned int *@var{got}) +Read @var{wanted} bytes of data from @var{file} store it in the buffer +@var{buf}. The number of bytes that was actually read is returned +via @var{got}. +@end deftypefun + +@deftypefun errcode_t ext2fs_file_write (ext2_file_t @var{file}, const void *@var{buf}, unsigned int @var{nbytes}, unsigned int *@var{written}) +Write @var{wanted} bytes of data from the buffer @var{buf} to the +current file position of @var{file}. The number of bytes that was +actually written is returned via @var{got}. +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Changing the file offset , Getting the file size, Reading and writing data, File I/O Functions +@comment node-name, next, previous, up +@subsection Changing the file offset + +@deftypefun errcode_t ext2fs_file_llseek (ext2_file_t @var{file}, __u64 @var{offset}, int @var{whence}, __u64 *@var{ret_pos}) +@deftypefunx errcode_t ext2fs_file_lseek (ext2_file_t @var{file}, ext2_off_t @var{offset}, int @var{whence}, ext2_off_t *@var{ret_pos}) +Change the current file position of @var{file} according to the +directive @var{whence} as follows: + +@table @code +@item EXT2_SEEK_SET +The file position is set to @var{offset} bytes from the beginning of the +file. + +@item EXT2_SEEK_CUR +The file position set to its current location plus @var{offset} bytes. + +@item EXT2_SEEK_END +The file position is set to the size of the file plus @var{offset} +bytes. +@end table + +The current offset is returned via @var{ret_pos}. +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Getting the file size, , Changing the file offset , File I/O Functions +@comment node-name, next, previous, up +@subsection Getting the file size + +@deftypefun errcode_t ext2fs_file_get_lsize (ext2_file_t @var{file}, __u64 *@var{ret_size}) +Return the size of the file @var{file} in @var{ret_size}. +@end deftypefun + +@deftypefun ext2_off_t ext2fs_file_get_size (ext2_file_t @var{file}) +Return the size of the file @var{file}. +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Inode Functions, Directory functions, File I/O Functions, EXT2FS Library Functions +@comment node-name, next, previous, up +@section Inode Functions + +@menu +* Reading and writing inodes:: +* Iterating over inodes in a filesystem:: +* Iterating over blocks in an inode:: +* Inode Convenience Functions:: +@end menu + +@c ---------------------------------------------------------------------- + +@node Reading and writing inodes, Iterating over inodes in a filesystem, Inode Functions, Inode Functions +@comment node-name, next, previous, up +@subsection Reading and writing inodes + +@deftypefun errcode_t ext2fs_read_inode (ext2_filsys @var{fs}, ext2_ino_t @var{ino}, struct ext2_inode *@var{inode}) +Read the inode number @var{ino} into @var{inode}. +@end deftypefun + +@deftypefun errcode_t ext2fs_write_inode (ext2_filsys @var{fs}, ext2_ino_t @var{ino}, struct ext2_inode *@var{inode}) +Write @var{inode} to inode @var{ino}. +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Iterating over inodes in a filesystem, Iterating over blocks in an inode, Reading and writing inodes, Inode Functions +@comment node-name, next, previous, up +@subsection Iterating over inodes in a filesystem + +The inode_scan abstraction is useful for iterating over all the inodes +in a filesystem. + +@deftypefun errcode_t ext2fs_open_inode_scan (ext2_filsys @var{fs}, int @var{buffer_blocks}, ext2_inode_scan *@var{scan}) +Initialize the iteration variable @var{scan}. This variable is used by +@code{ext2fs_get_next_inode}. The @var{buffer_blocks} parameter +controls how many blocks of the inode table are read in at a time. A +large number of blocks requires more memory, but reduces the overhead in +seeking and reading from the disk. If @var{buffer_blocks} is zero, a +suitable default value will be used. +@end deftypefun + +@deftypefun void ext2fs_close_inode_scan (ext2_inode_scan @var{scan}) +Release the memory associated with @var{scan} and invalidate it. +@end deftypefun + +@deftypefun errcode_t ext2fs_get_next_inode (ext2_inode_scan @var{scan}, ext2_ino_t *@var{ino}, struct ext2_inode *@var{inode}) + +This function returns the next inode from the filesystem; the inode +number of the inode is stored in @var{ino}, and the inode is stored in +@var{inode}. + +If the inode is located in a block that has been marked as bad, +@code{ext2fs_get_next_inode} will return the error +@code{EXT2_ET_BAD_BLOCK_IN_INODE_TABLE}. +@end deftypefun + +@deftypefun errcode_t ext2fs_inode_scan_goto_blockgroup (ext2_inode_scan @var{scan}, int @var{group}) +Start the inode scan at a particular ext2 blockgroup, @var{group}. +This function may be safely called at any time while @var{scan} is valid. +@end deftypefun + +@deftypefun void ext2fs_set_inode_callback (ext2_inode_scan @var{scan}, errcode_t (*done_group)(ext2_filsys @var{fs}, ext2_inode_scan @var{scan}, dgrp_t @var{group}, void * @var{private}), void *@var{done_group_data}) +Register a callback function which will be called by +@code{ext2_get_next_inode} when all of the inodes in a block group have +been processed. +@end deftypefun + +@deftypefun int ext2fs_inode_scan_flags (ext2_inode_scan @var{scan}, int @var{set_flags}, int @var{clear_flags}) + +Set the scan_flags @var{set_flags} and clear the scan_flags @var{clear_flags}. +The following flags can be set using this interface: + +@table @samp + +@item EXT2_SF_SKIP_MISSING_ITABLE +When a block group is missing an inode table, skip it. If this flag is +not set @code{ext2fs_get_next_inode} will return the error +EXT2_ET_MISSING_INODE_TABLE. + +@end table + +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Iterating over blocks in an inode, Inode Convenience Functions, Iterating over inodes in a filesystem, Inode Functions +@comment node-name, next, previous, up +@subsection Iterating over blocks in an inode + +@deftypefun errcode_t ext2fs_block_iterate (ext2_filsys @var{fs}, ext2_ino_t @var{ino}, int @var{flags}, char *block_buf, int (*func)(ext2_filsys @var{fs}, blk_t *@var{blocknr}, int @var{blockcnt}, void *@var{private}), void *@var{private}) + +Iterate over all of the blocks in inode number @var{ino} in filesystem +@var{fs}, by calling the function @var{func} for each block in the +inode. The @var{block_buf} parameter should either be NULL, or if the +@code{ext2fs_block_iterate} function is called repeatedly, the overhead +of allocating and freeing scratch memory can be avoided by passing a +pointer to a scratch buffer which must be at least as big as three times the +filesystem's blocksize. + +The @var{flags} parameter controls how the iterator will function: + +@table @samp + +@item BLOCK_FLAG_HOLE +This flag indiciates that the interator function should be called on +blocks where the block number is zero (also known as ``holes''.) It is +also known as BLOCK_FLAG_APPEND, since it is also used by functions +such as ext2fs_expand_dir() to add a new block to an inode. + +@item BLOCK_FLAG_DEPTH_TRAVERSE +This flag indicates that the iterator function for the +indirect, doubly indirect, etc. blocks should be called after all +of the blocks containined in the indirect blocks are processed. +This is useful if you are going to be deallocating blocks from an +inode. + +@item BLOCK_FLAG_DATA_ONLY +This flag indicates that the iterator function should be +called for data blocks only. + +@end table + +The callback function @var{func} is called with a number of parameters; +the @var{fs} and @var{private} parameters are self-explanatory, and +their values are taken from the parameters to +@code{ext2fs_block_iterate}. (The @var{private} data structure is +generally used by callers to @code{ext2fs_block_iterate} so that some +private data structure can be passed to the callback function. The +@var{blockcnt} parameter, if non-negative, indicates the logical block +number of a data block in the inode. If @var{blockcnt} is less than +zero, then @var{func} was called on a metadata block, and @var{blockcnt} +will be one of the following values: BLOCK_COUNT_IND, BLOCK_COUNT_DIND, +BLOCK_COUNT_TIND, or BLOCK_COUNT_TRANSLATOR. The @var{blocknr} is a +pointer to the inode or indirect block entry listing physical block +number. The callback function may modify the physical block number, if +it returns the @var{BLOCK_CHANGED} flag. + + +The callback function @var{func} returns a result code which is composed of +the logical OR of the following flags: + +@table @samp + +@item BLOCK_CHANGED + +This flag indicates that callback function has modified the physical +block number pointed to by @var{blocknr}. + +@item BLOCK_ABORT + +This flag requests that @code{ext2fs_block_iterate} to stop immediately +and return to the caller. + +@end table + +@end deftypefun + +@deftypefun errcode_t ext2fs_block_iterate2 (ext2_filsys @var{fs}, ext2_ino_t @var{ino}, int @var{flags}, char *@var{block}_buf, int (*func)(ext2_filsys @var{fs}, blk_t *@var{blocknr}, e2_blkcnt_t @var{blockcnt}, blk_t @var{ref_blk}, int @var{ref_offset}, void *@var{private}), void *@var{private}) + +This function is much like @code{ext2fs_block_iterate}, except that the +@var{blockcnt} type is a 64-bit signed quantity, to support larger +files, and the addition of the @var{ref_blk} and @var{ref_offset} +arguments passed to the callback function, which identify the location +of the physical block pointed to by pointer @var{blocknr}. If +@var{ref_blk} is zero, then @var{ref_offset} contains the offset into +the @code{i_blocks} array. If @var{ref_blk} is non-zero, then the physical +block location is contained inside an indirect block group, and +@var{ref_offset} contains the offset into the indirect block. + +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Inode Convenience Functions, , Iterating over blocks in an inode, Inode Functions +@comment node-name, next, previous, up +@subsection Convenience functions for Inodes + +@deftypefun errcode_t ext2fs_get_blocks (ext2_filsys @var{fs}, ext2_ino_t @var{ino}, blk_t *@var{blocks}) + +Returns an array of blocks corresponding to the direct, +indirect, doubly indirect, and triply indirect blocks as stored in the +inode structure. +@end deftypefun + +@deftypefun errcode_t ext2fs_check_directory (ext2_filsys @var{fs}, ext2_ino_t @var{ino}) +Returns 0 if @var{ino} is a directory, and @code{ENOTDIR} if it is not. +@end deftypefun + +@deftypefun int ext2fs_inode_has_valid_blocks (struct ext2_inode *@var{inode}) + +Returns 1 if the inode's block entries actually valid block entries, and +0 if not. Inodes which represent devices and fast symbolic links do not +contain valid block entries. +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Directory functions, Bitmap Functions, Inode Functions, EXT2FS Library Functions +@comment node-name, next, previous, up +@section Directory functions + +@menu +* Directory block functions:: +* Iterating over a directory:: +* Creating and expanding directories:: +* Creating and removing directory entries:: +* Looking up filenames:: +* Translating inode numbers to filenames:: +@end menu + +@c ---------------------------------------------------------------------- + +@node Directory block functions, Iterating over a directory, Directory functions, Directory functions +@comment node-name, next, previous, up +@subsection Directory block functions + +@deftypefun errcode_t ext2fs_read_dir_block (ext2_filsys @var{fs}, blk_t @var{block}, void *@var{buf}) + +This function reads a directory block, performing any necessary +byte swapping if necessary. +@end deftypefun + +@deftypefun errcode_t ext2fs_write_dir_block (ext2_filsys @var{fs}, blk_t @var{block}, void *@var{buf}) + +This function writes a directory block, performing any necessary +byte swapping if necessary. +@end deftypefun + +@deftypefun errcode_t ext2fs_new_dir_block (ext2_filsys @var{fs}, ext2_ino_t @var{dir_ino}, ext2_ino_t @var{parent_ino}, char **@var{block}) + +This function creates a new directory block in @var{block}. If +@var{dir_ino} is non-zero, then @var{dir_info} and @var{parent_ino} is used +to initialize directory entries for @file{.} and @file{..}, respectively. +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Iterating over a directory, Creating and expanding directories, Directory block functions, Directory functions +@comment node-name, next, previous, up +@subsection Iterating over a directory + +@deftypefun errcode_t ext2fs_dir_iterate (ext2_filsys @var{fs}, ext2_ino_t @var{dir}, int @var{flags}, char *@var{block_buf}, int (*@var{func})(struct ext2_dir_entry *@var{dirent}, int @var{offset}, int @var{blocksize}, char *@var{buf}, void *@var{private}), void *@var{private}) + +This function iterates over all of the directory entries in the +directory @var{dir}, calling the callback function @var{func} for each +directory entry in the directory. The @var{block_buf} parameter should +either be NULL, or if the @code{ext2fs_dir_iterate} function is +called repeatedly, the overhead of allocating and freeing +scratch memory can be avoided by passing a pointer to a scratch buffer +which must be at least as big as the filesystem's blocksize. + +The @var{flags} parameter controls how the iterator will function: + +@table @samp + +@item DIRENT_FLAG_INCLUDE_EMPTY + +This flag indicates that the callback function should be called even +for deleted or empty directory entries. + +@end table + +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Creating and expanding directories, Creating and removing directory entries, Iterating over a directory, Directory functions +@comment node-name, next, previous, up +@subsection Creating and expanding directories + +@deftypefun errcode_t ext2fs_mkdir (ext2_filsys @var{fs}, ext2_ino_t @var{parent}, ext2_ino_t @var{inum}, const char *@var{name}) + +This function creates a new directory. If @var{inum} is zero, then a +new inode will be allocated; otherwise, the directory will be created in +the inode specified by @var{inum}. If @var{name} specifies the name of +the new directory; if it is non-NULL, then the new directory will be +linked into the parent directory @var{parent}. +@end deftypefun + +@deftypefun errcode_t ext2fs_expand_dir (ext2_filsys @var{fs}, ext2_ino_t @var{dir}) + +This function adds a new empty directory block and appends it to +the directory @var{dir}. This allows functions such as +@code{ext2fs_link} to add new directory entries to a directory which is full. + +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Creating and removing directory entries, Looking up filenames, Creating and expanding directories, Directory functions +@comment node-name, next, previous, up +@subsection Creating and removing directory entries + +@deftypefun errcode_t ext2fs_link (ext2_filsys @var{fs}, ext2_ino_t @var{dir}, const char *@var{name}, ext2_ino_t @var{ino}, int flags) + +This function adds a new directory entry to the directory @var{dir}, +with @var{name} and @var{ino} specifying the name and inode number in +the directory entry, respectively. + +The low 3 bits of the flags field is used to specify the file type of +inode: (No other flags are currently defined.) + +@table @samp + +@item EXT2_FT_UNKNOWN + +The file type is unknown. + +@item EXT2_FT_REG_FILE + +The file type is a normal file. + +@item EXT2_FT_DIR + +The file type is a directory. + +@item EXT2_FT_CHRDEV + +The file type is a character device. + +@item EXT2_FT_BLKDEV + +The file type is a block device. + +@item EXT2_FT_FIFO + +The file type is a named pipe. + +@item EXT2_FT_SOCK + +The file type is a unix domain socket. + +@item EXT2_FT_SYMLINK + +The file type is a symbolic link. +@end table + +@end deftypefun + +@deftypefun errcode_t ext2fs_unlink (ext2_filsys @var{fs}, ext2_ino_t @var{dir}, const char *@var{name}, ext2_ino_t @var{ino}, int @var{flags}) + +This function removes a directory entry from @var{dir}. +The directory entry to be removed is the first one which is +matched by @var{name} and @var{ino}. If @var{name} is non-NULL, +the directory entry's name must match @var{name}. If @var{ino} is +non-zero, the directory entry's inode number must match @var{ino}. +No flags are currently defined for @code{ext2fs_unlink}; callers should +pass in zero to this parameter. + +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Looking up filenames, Translating inode numbers to filenames, Creating and removing directory entries, Directory functions +@comment node-name, next, previous, up +@subsection Looking up filenames + +@deftypefun errcode_t ext2fs_lookup (ext2_filsys @var{fs}, ext2_ino_t @var{dir}, const char *@var{name}, int @var{namelen}, char *@var{buf}, ext2_ino_t *@var{inode}) +@end deftypefun + +@deftypefun errcode_t ext2fs_namei (ext2_filsys @var{fs}, ext2_ino_t @var{root}, ext2_ino_t @var{cwd}, const char *@var{name}, ext2_ino_t *@var{inode}) +@end deftypefun + +@deftypefun errcode_t ext2fs_namei_follow (ext2_filsys @var{fs}, ext2_ino_t @var{root}, ext2_ino_t @var{cwd}, const char *@var{name}, ext2_ino_t *@var{inode}) +@end deftypefun + +@deftypefun errcode_t ext2fs_follow_link (ext2_filsys @var{fs}, ext2_ino_t @var{root}, ext2_ino_t @var{cwd}, ext2_ino_t @var{inode}, ext2_ino_t *@var{res}_inode) +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Translating inode numbers to filenames, , Looking up filenames, Directory functions +@comment node-name, next, previous, up +@subsection Translating inode numbers to filenames + +@deftypefun errcode_t ext2fs_get_pathname (ext2_filsys @var{fs}, ext2_ino_t @var{dir}, ext2_ino_t @var{ino}, char **@var{name}) +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Bitmap Functions, EXT2 data abstractions, Directory functions, EXT2FS Library Functions +@comment node-name, next, previous, up +@section Bitmap Functions + +@menu +* Reading and Writing Bitmaps:: +* Allocating Bitmaps:: +* Free bitmaps:: +* Bitmap Operations:: +* Comparing bitmaps:: +* Modifying Bitmaps:: +* Resizing Bitmaps:: +* Clearing Bitmaps:: +@end menu + +@c ---------------------------------------------------------------------- + +@node Reading and Writing Bitmaps, Allocating Bitmaps, Bitmap Functions, Bitmap Functions +@comment node-name, next, previous, up +@subsection Reading and Writing Bitmaps + +@deftypefun errcode_t ext2fs_write_inode_bitmap (ext2_filsys @var{fs}) +@end deftypefun + +@deftypefun errcode_t ext2fs_write_block_bitmap (ext2_filsys @var{fs}) +@end deftypefun + +@deftypefun errcode_t ext2fs_read_inode_bitmap (ext2_filsys @var{fs}) +@end deftypefun + +@deftypefun errcode_t ext2fs_read_block_bitmap (ext2_filsys @var{fs}) +@end deftypefun + +@deftypefun errcode_t ext2fs_read_bitmaps (ext2_filsys @var{fs}) +@end deftypefun + +@deftypefun errcode_t ext2fs_write_bitmaps (ext2_filsys @var{fs}) +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Allocating Bitmaps, Free bitmaps, Reading and Writing Bitmaps, Bitmap Functions +@comment node-name, next, previous, up +@subsection Allocating Bitmaps + +@deftypefun errcode_t ext2fs_allocate_generic_bitmap (__u32 @var{start}, __u32 @var{end}, _u32 @var{real_end}, const char *@var{descr}, ext2fs_generic_bitmap *@var{ret}) +@end deftypefun + +@deftypefun errcode_t ext2fs_allocate_block_bitmap (ext2_filsys @var{fs}, const char *@var{descr}, ext2fs_block_bitmap *@var{ret}) +@end deftypefun + +@deftypefun errcode_t ext2fs_allocate_inode_bitmap (ext2_filsys @var{fs}, const char *@var{descr}, ext2fs_inode_bitmap *@var{ret}) +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Free bitmaps, Bitmap Operations, Allocating Bitmaps, Bitmap Functions +@comment node-name, next, previous, up +@subsection Freeing bitmaps + + +@deftypefun void ext2fs_free_generic_bitmap (ext2fs_inode_bitmap @var{bitmap}) +@end deftypefun + +@deftypefun void ext2fs_free_block_bitmap (ext2fs_block_bitmap @var{bitmap}) +@end deftypefun + +@deftypefun void ext2fs_free_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}) +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Bitmap Operations, Comparing bitmaps, Free bitmaps, Bitmap Functions +@comment node-name, next, previous, up +@subsection Bitmap Operations + +@deftypefun void ext2fs_mark_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block}) + +@deftypefunx void ext2fs_unmark_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block}) + +@deftypefunx int ext2fs_test_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block}) + +These functions set, clear, and test bits in a block bitmap @var{bitmap}. +@end deftypefun + + +@deftypefun void ext2fs_mark_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ext2_ino_t @var{inode}) + +@deftypefunx void ext2fs_unmark_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ext2_ino_t @var{inode}) + +@deftypefunx int ext2fs_test_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ext2_ino_t @var{inode}) + +These functions set, clear, and test bits in an inode bitmap @var{bitmap}. +@end deftypefun + +@deftypefun void ext2fs_fast_mark_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block}) + +@deftypefunx void ext2fs_fast_unmark_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block}) + +@deftypefunx int ext2fs_fast_test_block_bitmap (ext2fs_block_bitmap @var{bitmap}, blk_t @var{block}) + +@deftypefunx void ext2fs_fast_mark_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ext2_ino_t @var{inode}) + +@deftypefunx void ext2fs_fast_unmark_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ext2_ino_t @var{inode}) + +@deftypefunx int ext2fs_fast_test_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}, ext2_ino_t @var{inode}) + +These ``fast'' functions are like their normal counterparts; however, +they are implemented as inline functions and do not perform bounds +checks on the inode number or block number; they are assumed to be +correct. They should only be used in speed-critical applications, where +the inode or block number has already been validated by other means. +@end deftypefun + +@deftypefun blk_t ext2fs_get_block_bitmap_start (ext2fs_block_bitmap @var{bitmap}) +@deftypefunx ext2_ino_t ext2fs_get_inode_bitmap_start (ext2fs_inode_bitmap @var{bitmap}) +Return the first inode or block which is stored in the bitmap. +@end deftypefun + +@deftypefun blk_t ext2fs_get_block_bitmap_end (ext2fs_block_bitmap @var{bitmap}) +@deftypefunx ext2_ino_t ext2fs_get_inode_bitmap_end (ext2fs_inode_bitmap @var{bitmap}) + +Return the last inode or block which is stored in the bitmap. +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Comparing bitmaps, Modifying Bitmaps, Bitmap Operations, Bitmap Functions +@comment node-name, next, previous, up +@subsection Comparing bitmaps + +@deftypefun errcode_t ext2fs_compare_block_bitmap (ext2fs_block_bitmap @var{bm1}, ext2fs_block_bitmap @var{bm2}) +@end deftypefun + +@deftypefun errcode_t ext2fs_compare_inode_bitmap (ext2fs_inode_bitmap @var{bm1}, ext2fs_inode_bitmap @var{bm2}) +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Modifying Bitmaps, Resizing Bitmaps, Comparing bitmaps, Bitmap Functions +@comment node-name, next, previous, up +@subsection Modifying Bitmaps + +@deftypefun errcode_t ext2fs_fudge_inode_bitmap_end (ext2fs_inode_bitmap @var{bitmap}, ext2_ino_t @var{end}, ext2_ino_t *@var{oend}) +@end deftypefun + +@deftypefun errcode_t ext2fs_fudge_block_bitmap_end (ext2fs_block_bitmap @var{bitmap}, blk_t @var{end}, blk_t *@var{oend}) +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Resizing Bitmaps, Clearing Bitmaps, Modifying Bitmaps, Bitmap Functions +@comment node-name, next, previous, up +@subsection Resizing Bitmaps + +@deftypefun errcode_t ext2fs_resize_generic_bitmap (__u32 @var{new_end}, __u32 @var{new_real_end}, ext2fs_generic_bitmap @var{bmap}) +@end deftypefun + +@deftypefun errcode_t ext2fs_resize_inode_bitmap (__u32 @var{new_end}, __u32 @var{new_real_end}, ext2fs_inode_bitmap @var{bmap}) +@end deftypefun + +@deftypefun errcode_t ext2fs_resize_block_bitmap (__u32 @var{new_end}, __u32 @var{new_real_end}, ext2fs_block_bitmap @var{bmap}) +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Clearing Bitmaps, , Resizing Bitmaps, Bitmap Functions +@comment node-name, next, previous, up +@subsection Clearing Bitmaps + +@deftypefun void ext2fs_clear_inode_bitmap (ext2fs_inode_bitmap @var{bitmap}) + +This function sets all of the bits in the inode bitmap @var{bitmap} to +be zero. + +@end deftypefun + +@deftypefun void ext2fs_clear_block_bitmap (ext2fs_block_bitmap @var{bitmap}) + +This function sets all of the bits in the block bitmap @var{bitmap} to +be zero. +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node EXT2 data abstractions, Byte-swapping functions, Bitmap Functions, EXT2FS Library Functions +@comment node-name, next, previous, up +@section EXT2 data abstractions + +The ext2 library has a number of abstractions which are useful for ext2 +utility programs. + +@menu +* Badblocks list management:: +* Directory-block list management:: +* Inode count functions:: +@end menu + +@c ---------------------------------------------------------------------- + +@node Badblocks list management, Directory-block list management, EXT2 data abstractions, EXT2 data abstractions +@comment node-name, next, previous, up +@subsection Badblocks list management + + +@deftypefun errcode_t ext2fs_badblocks_list_create (ext2_badblocks_list *@var{ret}, int @var{size}) +@end deftypefun + +@deftypefun void ext2fs_badblocks_list_free (ext2_badblocks_list @var{bb}) +@end deftypefun + +@deftypefun errcode_t ext2fs_badblocks_list_add (ext2_badblocks_list @var{bb}, blk_t @var{blk}) +@end deftypefun + +@deftypefun int ext2fs_badblocks_list_test (ext2_badblocks_list @var{bb}, blk_t @var{blk}) +@end deftypefun + +@deftypefun errcode_t ext2fs_badblocks_list_iterate_begin (ext2_badblocks_list @var{bb}, ext2_badblocks_iterate *@var{ret}) +@end deftypefun + +@deftypefun int ext2fs_badblocks_list_iterate (ext2_badblocks_iterate iter, blk_t *@var{blk}) +@end deftypefun + +@deftypefun void ext2fs_badblocks_list_iterate_end (ext2_badblocks_iterate @var{iter}) +@end deftypefun + +@deftypefun errcode_t ext2fs_update_bb_inode (ext2_filsys @var{fs}, ext2_badblocks_list @var{bb_list}) +@end deftypefun + +@deftypefun errcode_t ext2fs_read_bb_inode (ext2_filsys @var{fs}, ext2_badblocks_list *@var{bb_list}) +@end deftypefun + +@deftypefun errcode_t ext2fs_read_bb_FILE (ext2_filsys @var{fs}, FILE *f, ext2_badblocks_list *@var{bb_list}, void (*invalid)(ext2_filsys @var{fs}, blk_t @var{blk})) +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Directory-block list management, Inode count functions, Badblocks list management, EXT2 data abstractions +@comment node-name, next, previous, up +@subsection Directory-block list management + +The dblist abstraction stores a list of blocks belonging to +directories. This list can be useful when a program needs to interate +over all directory entries in a filesystem; @code{e2fsck} does this in +pass 2 of its operations, and @code{debugfs} needs to do this when it is +trying to turn an inode number into a pathname. + +@deftypefun errcode_t ext2fs_init_dblist (ext2_filsys @var{fs}, ext2_dblist *@var{ret_dblist}) + +Creates a dblist data structure and return it in @var{ret_dblist}. +@end deftypefun + +@deftypefun void ext2fs_free_dblist (ext2_dblist @var{dblist}) + +Free a dblist data structure. +@end deftypefun + +@deftypefun errcode_t ext2fs_add_dir_block (ext2_dblist @var{dblist}, ext2_ino_t @var{ino}, blk_t @var{blk}, int @var{blockcnt}) + +Add an entry to the dblist data structure. This call records the fact +that block number @var{blockcnt} of directory inode @var{ino} is stored +in block @var{blk}. +@end deftypefun + +@deftypefun errcode_t ext2fs_set_dir_block (ext2_dblist @var{dblist}, ext2_ino_t @var{ino}, blk_t @var{blk}, int @var{blockcnt}) + +Change an entry in the dblist data structure; this changes the location +of block number @var{blockcnt} of directory indoe @var{ino} to be block +@var{blk}. +@end deftypefun + +@deftypefun errcode_t ext2fs_dblist_iterate (ext2_dblist @var{dblist}, int (*func)(ext2_filsys @var{fs}, struct ext2_db_entry *@var{db_info}, void *@var{private}), void *@var{private}) + +This iterator calls @var{func} for every entry in the dblist data structure. +@end deftypefun + +@deftypefun errcode_t ext2fs_dblist_dir_iterate (ext2_dblist @var{dblist}, int flags, char *@var{block_buf}, int (*func)(ext2_ino_t @var{dir}, int @var{entry}, struct ext2_dir_entry *@var{dirent}, int @var{offset}, int @var{blocksize}, char *@var{buf}, void *@var{private}), void *@var{private}) + +This iterator takes reads in the directory block indicated in each +dblist entry, and calls @var{func} for each directory entry in each +directory block. If @var{dblist} contains all the directory blocks in a +filesystem, this function provides a convenient way to iterate over all +directory entries for that filesystem. +@end deftypefun + +@c ---------------------------------------------------------------------- + +@node Inode count functions, , Directory-block list management, EXT2 data abstractions +@comment node-name, next, previous, up +@subsection Inode count functions + +The icount abstraction is a specialized data type used by @code{e2fsck} +to store how many times a particular inode is referenced by the +filesystem. This is used twice; once to store the actual number of times +that the inode is reference; and once to store the claimed number of times +the inode is referenced according to the inode structure. + +This abstraction is designed to be extremely efficient for storing this +sort of information, by taking advantage of the following properties of +inode counts, namely (1) inode counts are very often zero (because +the inode is currrently not in use), and (2) many files have a inode +count of 1 (because they are a file which has no additional hard links). + +@deftypefun errcode_t ext2fs_create_icount2 (ext2_filsys @var{fs}, int @var{flags}, int @var{size}, ext2_icount_t @var{hint}, ext2_icount_t *@var{ret}) + +Creates an icount stucture for a filesystem @var{fs}, with initial space +for @var{size} inodes whose count is greater than 1. The @var{flags} +parameter is either 0 or @code{EXT2_ICOUNT_OPT_INCREMENT}, which +indicates that icount structure should be able to increment inode counts +quickly. The icount structure is returned in @var{ret}. The returned +icount structure initially has a count of zero for all inodes. + +The @var{hint} parameter allows the caller to optionally pass in another +icount structure which is used to initialize the array of inodes whose +count is greater than 1. It is used purely as a speed optimization so +that the icount structure can determine in advance which inodes are +likely to contain a count grater than 1. +@end deftypefun + +@deftypefun void ext2fs_free_icount (ext2_icount_t @var{icount}) + +Frees an icount structure. +@end deftypefun + +@deftypefun errcode_t ext2fs_icount_fetch (ext2_icount_t @var{icount}, ext2_ino_t @var{ino}, __u16 *@var{ret}) + +Returns in @var{ret} fetches the count for a particular inode @var{ino}. +@end deftypefun + +@deftypefun errcode_t ext2fs_icount_increment (ext2_icount_t @var{icount}, ext2_ino_t @var{ino}, __u16 *@var{ret}) + +Increments the ref count for inode @var{ino}. +@end deftypefun + +@deftypefun errcode_t ext2fs_icount_decrement (ext2_icount_t @var{icount}, ext2_ino_t @var{ino}, __u16 *@var{ret}) + +Decrements the ref count for inode @var{ino}. +@end deftypefun + +@deftypefun errcode_t ext2fs_icount_store (ext2_icount_t @var{icount}, ext2_ino_t @var{ino}, __u16 @var{count}) + +Sets the reference count for inode @var{ino} to be @var{count}. +@end deftypefun + +@deftypefun ext2_ino_t ext2fs_get_icount_size (ext2_icount_t @var{icount}) + +Returns the current number of inodes in @var{icount} which has a count +greater than 1. +@end deftypefun + +@deftypefun errcode_t ext2fs_icount_validate (ext2_icount_t @var{icount}, FILE *@var{f}) + +Validates the internal rep invariant of @var{icount}; if there are any +problems, print out debugging information to @var{f}. This function is +intended for debugging and testing use only. +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Byte-swapping functions, Other functions, EXT2 data abstractions, EXT2FS Library Functions +@comment node-name, next, previous, up +@section Byte-swapping functions + +@deftypefun void ext2fs_swap_super (struct ext2_super_block * @var{super}) +@end deftypefun + +@deftypefun void ext2fs_swap_group_desc (struct ext2_group_desc *@var{gdp}) +@end deftypefun + +@deftypefun void ext2fs_swap_inode (ext2_filsys @var{fs}, struct ext2_inode *@var{to}, struct ext2_inode *@var{from}, int @var{hostorder}) +@end deftypefun + +@deftypefun int ext2fs_native_flag (void) +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Other functions, , Byte-swapping functions, EXT2FS Library Functions +@comment node-name, next, previous, up +@section Other functions + +/* alloc.c */ +@deftypefun errcode_t ext2fs_new_inode (ext2_filsys @var{fs}, ext2_ino_t @var{dir}, int @var{mode}, ext2fs_inode_bitmap @var{map}, ext2_ino_t *@var{ret}) +@end deftypefun + +@deftypefun errcode_t ext2fs_new_block (ext2_filsys @var{fs}, blk_t @var{goal}, ext2fs_block_bitmap @var{map}, blk_t *@var{ret}) +@end deftypefun + +@deftypefun errcode_t ext2fs_get_free_blocks (ext2_filsys @var{fs}, blk_t @var{start}, blk_t @var{finish}, int @var{num}, ext2fs_block_bitmap @var{map}, blk_t *@var{ret}) +@end deftypefun + +/* check_desc.c */ +@deftypefun errcode_t ext2fs_check_desc (ext2_filsys @var{fs}) +@end deftypefun + +@deftypefun errcode_t ext2fs_get_num_dirs (ext2_filsys @var{fs}, ext2_ino_t *@var{ret_num_dirs}) +@end deftypefun + + +/* getsize.c */ +@deftypefun errcode_t ext2fs_get_device_size (const char *@var{file}, int @var{blocksize}, blk_t *@var{retblocks}) +@end deftypefun + + +/* ismounted.c */ +@deftypefun errcode_t ext2fs_check_if_mounted (const char *@var{file}, int *@var{mount_flags}) +@end deftypefun + +/* version.c */ + +@deftypefun int ext2fs_get_library_version (const char **@var{ver_string}, const char **@var{date_string}) + +This function returns the current version of the ext2 library. The +return value contains an integer version code, which consists of the +major version number of the library multiplied by 100, plus the minor +version number of the library. Hence, if the library version is 1.08, +the returned value will be 108. + +If @var{ver_string} and/or @var{date_string} are non-NULL, they will be +set to point at a constant string containing the library version and/or +release date, respectively. +@end deftypefun + +@deftypefun int ext2fs_parse_version_string (const char *@var{ver_string}) + +This function takes a version string which may included in an +application and returns a version code using the same algorithm used by +@code{ext2fs_get_library_version}. It can be used by programs included +in the @code{e2fsprogs} distribution to assure that they are using an +up-to-date ext2 shared library. +@end deftypefun + +/* inline functions */ +@deftypefun int ext2fs_group_of_blk (ext2_filsys @var{fs}, blk_t @var{blk}) + +This function returns the block group which contains the block @var{blk}. + +@end deftypefun + +@deftypefun int ext2fs_group_of_ino (ext2_filsys @var{fs}, ext2_ino_t @var{ino}) + +This function returns the block group which contains the inode @var{ino}. +@end deftypefun + + +@c ---------------------------------------------------------------------- + +@node Concept Index, Function Index, EXT2FS Library Functions, Top +@comment node-name, next, previous, up +@unnumbered Concept Index +@printindex cp + +@c ---------------------------------------------------------------------- + +@node Function Index, , Concept Index, Top +@comment node-name, next, previous, up +@unnumbered Function and Type Index +@printindex fn + + +@contents +@bye
diff --git a/doc/texinfo.tex b/doc/texinfo.tex new file mode 100644 index 0000000..dddd014 --- /dev/null +++ b/doc/texinfo.tex
@@ -0,0 +1,7226 @@ +% texinfo.tex -- TeX macros to handle Texinfo files. +% +% Load plain if necessary, i.e., if running under initex. +\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi +% +\def\texinfoversion{2006-02-13.16} +% +% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, +% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free +% Software Foundation, Inc. +% +% This texinfo.tex file is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License as +% published by the Free Software Foundation; either version 2, or (at +% your option) any later version. +% +% This texinfo.tex file is distributed in the hope that it will be +% useful, but WITHOUT 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 texinfo.tex file; see the file COPYING. If not, write +% to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +% Boston, MA 02110-1301, USA. +% +% As a special exception, when this file is read by TeX when processing +% a Texinfo source document, you may use the result without +% restriction. (This has been our intent since Texinfo was invented.) +% +% Please try the latest version of texinfo.tex before submitting bug +% reports; you can get the latest version from: +% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or +% ftp://tug.org/tex/texinfo.tex +% (and all CTAN mirrors, see http://www.ctan.org). +% The texinfo.tex in any given distribution could well be out +% of date, so if that's what you're using, please check. +% +% Send bug reports to bug-texinfo@gnu.org. Please include including a +% complete document in each bug report with which we can reproduce the +% problem. Patches are, of course, greatly appreciated. +% +% To process a Texinfo manual with TeX, it's most reliable to use the +% texi2dvi shell script that comes with the distribution. For a simple +% manual foo.texi, however, you can get away with this: +% tex foo.texi +% texindex foo.?? +% tex foo.texi +% tex foo.texi +% dvips foo.dvi -o # or whatever; this makes foo.ps. +% The extra TeX runs get the cross-reference information correct. +% Sometimes one run after texindex suffices, and sometimes you need more +% than two; texi2dvi does it as many times as necessary. +% +% It is possible to adapt texinfo.tex for other languages, to some +% extent. You can get the existing language-specific files from the +% full Texinfo distribution. +% +% The GNU Texinfo home page is http://www.gnu.org/software/texinfo. + + +\message{Loading texinfo [version \texinfoversion]:} + +% If in a .fmt file, print the version number +% and turn on active characters that we couldn't do earlier because +% they might have appeared in the input file name. +\everyjob{\message{[Texinfo version \texinfoversion]}% + \catcode`+=\active \catcode`\_=\active} + +\message{Basics,} +\chardef\other=12 + +% We never want plain's \outer definition of \+ in Texinfo. +% For @tex, we can use \tabalign. +\let\+ = \relax + +% Save some plain tex macros whose names we will redefine. +\let\ptexb=\b +\let\ptexbullet=\bullet +\let\ptexc=\c +\let\ptexcomma=\, +\let\ptexdot=\. +\let\ptexdots=\dots +\let\ptexend=\end +\let\ptexequiv=\equiv +\let\ptexexclam=\! +\let\ptexfootnote=\footnote +\let\ptexgtr=> +\let\ptexhat=^ +\let\ptexi=\i +\let\ptexindent=\indent +\let\ptexinsert=\insert +\let\ptexlbrace=\{ +\let\ptexless=< +\let\ptexnewwrite\newwrite +\let\ptexnoindent=\noindent +\let\ptexplus=+ +\let\ptexrbrace=\} +\let\ptexslash=\/ +\let\ptexstar=\* +\let\ptext=\t + +% If this character appears in an error message or help string, it +% starts a new line in the output. +\newlinechar = `^^J + +% Use TeX 3.0's \inputlineno to get the line number, for better error +% messages, but if we're using an old version of TeX, don't do anything. +% +\ifx\inputlineno\thisisundefined + \let\linenumber = \empty % Pre-3.0. +\else + \def\linenumber{l.\the\inputlineno:\space} +\fi + +% Set up fixed words for English if not already set. +\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi +\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi +\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi +\ifx\putwordin\undefined \gdef\putwordin{in}\fi +\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi +\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi +\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi +\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi +\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi +\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi +\ifx\putwordof\undefined \gdef\putwordof{of}\fi +\ifx\putwordon\undefined \gdef\putwordon{on}\fi +\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi +\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi +\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi +\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi +\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi +\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi +\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi +% +\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi +\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi +\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi +\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi +\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi +\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi +\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi +\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi +\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi +\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi +\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi +\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi +% +\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi +\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi +\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi +\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi +\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi + +% Since the category of space is not known, we have to be careful. +\chardef\spacecat = 10 +\def\spaceisspace{\catcode`\ =\spacecat} + +% Ignore a token. +% +\def\gobble#1{} + +% The following is used inside several \edef's. +\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} + +% Hyphenation fixes. +\hyphenation{ + Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script + ap-pen-dix bit-map bit-maps + data-base data-bases eshell fall-ing half-way long-est man-u-script + man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm + par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces + spell-ing spell-ings + stand-alone strong-est time-stamp time-stamps which-ever white-space + wide-spread wrap-around +} + +% Margin to add to right of even pages, to left of odd pages. +\newdimen\bindingoffset +\newdimen\normaloffset +\newdimen\pagewidth \newdimen\pageheight + +% For a final copy, take out the rectangles +% that mark overfull boxes (in case you have decided +% that the text looks ok even though it passes the margin). +% +\def\finalout{\overfullrule=0pt} + +% @| inserts a changebar to the left of the current line. It should +% surround any changed text. This approach does *not* work if the +% change spans more than two lines of output. To handle that, we would +% have adopt a much more difficult approach (putting marks into the main +% vertical list for the beginning and end of each change). +% +\def\|{% + % \vadjust can only be used in horizontal mode. + \leavevmode + % + % Append this vertical mode material after the current line in the output. + \vadjust{% + % We want to insert a rule with the height and depth of the current + % leading; that is exactly what \strutbox is supposed to record. + \vskip-\baselineskip + % + % \vadjust-items are inserted at the left edge of the type. So + % the \llap here moves out into the left-hand margin. + \llap{% + % + % For a thicker or thinner bar, change the `1pt'. + \vrule height\baselineskip width1pt + % + % This is the space between the bar and the text. + \hskip 12pt + }% + }% +} + +% Sometimes it is convenient to have everything in the transcript file +% and nothing on the terminal. We don't just call \tracingall here, +% since that produces some useless output on the terminal. We also make +% some effort to order the tracing commands to reduce output in the log +% file; cf. trace.sty in LaTeX. +% +\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% +\def\loggingall{% + \tracingstats2 + \tracingpages1 + \tracinglostchars2 % 2 gives us more in etex + \tracingparagraphs1 + \tracingoutput1 + \tracingmacros2 + \tracingrestores1 + \showboxbreadth\maxdimen \showboxdepth\maxdimen + \ifx\eTeXversion\undefined\else % etex gives us more logging + \tracingscantokens1 + \tracingifs1 + \tracinggroups1 + \tracingnesting2 + \tracingassigns1 + \fi + \tracingcommands3 % 3 gives us more in etex + \errorcontextlines16 +}% + +% add check for \lastpenalty to plain's definitions. If the last thing +% we did was a \nobreak, we don't want to insert more space. +% +\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount + \removelastskip\penalty-50\smallskip\fi\fi} +\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount + \removelastskip\penalty-100\medskip\fi\fi} +\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount + \removelastskip\penalty-200\bigskip\fi\fi} + +% For @cropmarks command. +% Do @cropmarks to get crop marks. +% +\newif\ifcropmarks +\let\cropmarks = \cropmarkstrue +% +% Dimensions to add cropmarks at corners. +% Added by P. A. MacKay, 12 Nov. 1986 +% +\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines +\newdimen\cornerlong \cornerlong=1pc +\newdimen\cornerthick \cornerthick=.3pt +\newdimen\topandbottommargin \topandbottommargin=.75in + +% Main output routine. +\chardef\PAGE = 255 +\output = {\onepageout{\pagecontents\PAGE}} + +\newbox\headlinebox +\newbox\footlinebox + +% \onepageout takes a vbox as an argument. Note that \pagecontents +% does insertions, but you have to call it yourself. +\def\onepageout#1{% + \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi + % + \ifodd\pageno \advance\hoffset by \bindingoffset + \else \advance\hoffset by -\bindingoffset\fi + % + % Do this outside of the \shipout so @code etc. will be expanded in + % the headline as they should be, not taken literally (outputting ''code). + \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% + \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% + % + {% + % Have to do this stuff outside the \shipout because we want it to + % take effect in \write's, yet the group defined by the \vbox ends + % before the \shipout runs. + % + \indexdummies % don't expand commands in the output. + \normalturnoffactive % \ in index entries must not stay \, e.g., if + % the page break happens to be in the middle of an example. + % We don't want .vr (or whatever) entries like this: + % \entry{{\tt \indexbackslash }acronym}{32}{\code {\acronym}} + % "\acronym" won't work when it's read back in; + % it needs to be + % {\code {{\tt \backslashcurfont }acronym} + \shipout\vbox{% + % Do this early so pdf references go to the beginning of the page. + \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi + % + \ifcropmarks \vbox to \outervsize\bgroup + \hsize = \outerhsize + \vskip-\topandbottommargin + \vtop to0pt{% + \line{\ewtop\hfil\ewtop}% + \nointerlineskip + \line{% + \vbox{\moveleft\cornerthick\nstop}% + \hfill + \vbox{\moveright\cornerthick\nstop}% + }% + \vss}% + \vskip\topandbottommargin + \line\bgroup + \hfil % center the page within the outer (page) hsize. + \ifodd\pageno\hskip\bindingoffset\fi + \vbox\bgroup + \fi + % + \unvbox\headlinebox + \pagebody{#1}% + \ifdim\ht\footlinebox > 0pt + % Only leave this space if the footline is nonempty. + % (We lessened \vsize for it in \oddfootingxxx.) + % The \baselineskip=24pt in plain's \makefootline has no effect. + \vskip 2\baselineskip + \unvbox\footlinebox + \fi + % + \ifcropmarks + \egroup % end of \vbox\bgroup + \hfil\egroup % end of (centering) \line\bgroup + \vskip\topandbottommargin plus1fill minus1fill + \boxmaxdepth = \cornerthick + \vbox to0pt{\vss + \line{% + \vbox{\moveleft\cornerthick\nsbot}% + \hfill + \vbox{\moveright\cornerthick\nsbot}% + }% + \nointerlineskip + \line{\ewbot\hfil\ewbot}% + }% + \egroup % \vbox from first cropmarks clause + \fi + }% end of \shipout\vbox + }% end of group with \indexdummies + \advancepageno + \ifnum\outputpenalty>-20000 \else\dosupereject\fi +} + +\newinsert\margin \dimen\margin=\maxdimen + +\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} +{\catcode`\@ =11 +\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi +% marginal hacks, juha@viisa.uucp (Juha Takala) +\ifvoid\margin\else % marginal info is present + \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi +\dimen@=\dp#1 \unvbox#1 +\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi +\ifr@ggedbottom \kern-\dimen@ \vfil \fi} +} + +% Here are the rules for the cropmarks. Note that they are +% offset so that the space between them is truly \outerhsize or \outervsize +% (P. A. MacKay, 12 November, 1986) +% +\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} +\def\nstop{\vbox + {\hrule height\cornerthick depth\cornerlong width\cornerthick}} +\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} +\def\nsbot{\vbox + {\hrule height\cornerlong depth\cornerthick width\cornerthick}} + +% Parse an argument, then pass it to #1. The argument is the rest of +% the input line (except we remove a trailing comment). #1 should be a +% macro which expects an ordinary undelimited TeX argument. +% +\def\parsearg{\parseargusing{}} +\def\parseargusing#1#2{% + \def\next{#2}% + \begingroup + \obeylines + \spaceisspace + #1% + \parseargline\empty% Insert the \empty token, see \finishparsearg below. +} + +{\obeylines % + \gdef\parseargline#1^^M{% + \endgroup % End of the group started in \parsearg. + \argremovecomment #1\comment\ArgTerm% + }% +} + +% First remove any @comment, then any @c comment. +\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} +\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} + +% Each occurence of `\^^M' or `<space>\^^M' is replaced by a single space. +% +% \argremovec might leave us with trailing space, e.g., +% @end itemize @c foo +% This space token undergoes the same procedure and is eventually removed +% by \finishparsearg. +% +\def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} +\def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} +\def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% + \def\temp{#3}% + \ifx\temp\empty + % We cannot use \next here, as it holds the macro to run; + % thus we reuse \temp. + \let\temp\finishparsearg + \else + \let\temp\argcheckspaces + \fi + % Put the space token in: + \temp#1 #3\ArgTerm +} + +% If a _delimited_ argument is enclosed in braces, they get stripped; so +% to get _exactly_ the rest of the line, we had to prevent such situation. +% We prepended an \empty token at the very beginning and we expand it now, +% just before passing the control to \next. +% (Similarily, we have to think about #3 of \argcheckspacesY above: it is +% either the null string, or it ends with \^^M---thus there is no danger +% that a pair of braces would be stripped. +% +% But first, we have to remove the trailing space token. +% +\def\finishparsearg#1 \ArgTerm{\expandafter\next\expandafter{#1}} + +% \parseargdef\foo{...} +% is roughly equivalent to +% \def\foo{\parsearg\Xfoo} +% \def\Xfoo#1{...} +% +% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my +% favourite TeX trick. --kasal, 16nov03 + +\def\parseargdef#1{% + \expandafter \doparseargdef \csname\string#1\endcsname #1% +} +\def\doparseargdef#1#2{% + \def#2{\parsearg#1}% + \def#1##1% +} + +% Several utility definitions with active space: +{ + \obeyspaces + \gdef\obeyedspace{ } + + % Make each space character in the input produce a normal interword + % space in the output. Don't allow a line break at this space, as this + % is used only in environments like @example, where each line of input + % should produce a line of output anyway. + % + \gdef\sepspaces{\obeyspaces\let =\tie} + + % If an index command is used in an @example environment, any spaces + % therein should become regular spaces in the raw index file, not the + % expansion of \tie (\leavevmode \penalty \@M \ ). + \gdef\unsepspaces{\let =\space} +} + + +\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} + +% Define the framework for environments in texinfo.tex. It's used like this: +% +% \envdef\foo{...} +% \def\Efoo{...} +% +% It's the responsibility of \envdef to insert \begingroup before the +% actual body; @end closes the group after calling \Efoo. \envdef also +% defines \thisenv, so the current environment is known; @end checks +% whether the environment name matches. The \checkenv macro can also be +% used to check whether the current environment is the one expected. +% +% Non-false conditionals (@iftex, @ifset) don't fit into this, so they +% are not treated as enviroments; they don't open a group. (The +% implementation of @end takes care not to call \endgroup in this +% special case.) + + +% At runtime, environments start with this: +\def\startenvironment#1{\begingroup\def\thisenv{#1}} +% initialize +\let\thisenv\empty + +% ... but they get defined via ``\envdef\foo{...}'': +\long\def\envdef#1#2{\def#1{\startenvironment#1#2}} +\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} + +% Check whether we're in the right environment: +\def\checkenv#1{% + \def\temp{#1}% + \ifx\thisenv\temp + \else + \badenverr + \fi +} + +% Evironment mismatch, #1 expected: +\def\badenverr{% + \errhelp = \EMsimple + \errmessage{This command can appear only \inenvironment\temp, + not \inenvironment\thisenv}% +} +\def\inenvironment#1{% + \ifx#1\empty + out of any environment% + \else + in environment \expandafter\string#1% + \fi +} + +% @end foo executes the definition of \Efoo. +% But first, it executes a specialized version of \checkenv +% +\parseargdef\end{% + \if 1\csname iscond.#1\endcsname + \else + % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03 + \expandafter\checkenv\csname#1\endcsname + \csname E#1\endcsname + \endgroup + \fi +} + +\newhelp\EMsimple{Press RETURN to continue.} + + +%% Simple single-character @ commands + +% @@ prints an @ +% Kludge this until the fonts are right (grr). +\def\@{{\tt\char64}} + +% This is turned off because it was never documented +% and you can use @w{...} around a quote to suppress ligatures. +%% Define @` and @' to be the same as ` and ' +%% but suppressing ligatures. +%\def\`{{`}} +%\def\'{{'}} + +% Used to generate quoted braces. +\def\mylbrace {{\tt\char123}} +\def\myrbrace {{\tt\char125}} +\let\{=\mylbrace +\let\}=\myrbrace +\begingroup + % Definitions to produce \{ and \} commands for indices, + % and @{ and @} for the aux/toc files. + \catcode`\{ = \other \catcode`\} = \other + \catcode`\[ = 1 \catcode`\] = 2 + \catcode`\! = 0 \catcode`\\ = \other + !gdef!lbracecmd[\{]% + !gdef!rbracecmd[\}]% + !gdef!lbraceatcmd[@{]% + !gdef!rbraceatcmd[@}]% +!endgroup + +% @comma{} to avoid , parsing problems. +\let\comma = , + +% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent +% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. +\let\, = \c +\let\dotaccent = \. +\def\ringaccent#1{{\accent23 #1}} +\let\tieaccent = \t +\let\ubaraccent = \b +\let\udotaccent = \d + +% Other special characters: @questiondown @exclamdown @ordf @ordm +% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. +\def\questiondown{?`} +\def\exclamdown{!`} +\def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} +\def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} + +% Dotless i and dotless j, used for accents. +\def\imacro{i} +\def\jmacro{j} +\def\dotless#1{% + \def\temp{#1}% + \ifx\temp\imacro \ptexi + \else\ifx\temp\jmacro \j + \else \errmessage{@dotless can be used only with i or j}% + \fi\fi +} + +% The \TeX{} logo, as in plain, but resetting the spacing so that a +% period following counts as ending a sentence. (Idea found in latex.) +% +\edef\TeX{\TeX \spacefactor=1000 } + +% @LaTeX{} logo. Not quite the same results as the definition in +% latex.ltx, since we use a different font for the raised A; it's most +% convenient for us to use an explicitly smaller font, rather than using +% the \scriptstyle font (since we don't reset \scriptstyle and +% \scriptscriptstyle). +% +\def\LaTeX{% + L\kern-.36em + {\setbox0=\hbox{T}% + \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}% + \kern-.15em + \TeX +} + +% Be sure we're in horizontal mode when doing a tie, since we make space +% equivalent to this in @example-like environments. Otherwise, a space +% at the beginning of a line will start with \penalty -- and +% since \penalty is valid in vertical mode, we'd end up putting the +% penalty on the vertical list instead of in the new paragraph. +{\catcode`@ = 11 + % Avoid using \@M directly, because that causes trouble + % if the definition is written into an index file. + \global\let\tiepenalty = \@M + \gdef\tie{\leavevmode\penalty\tiepenalty\ } +} + +% @: forces normal size whitespace following. +\def\:{\spacefactor=1000 } + +% @* forces a line break. +\def\*{\hfil\break\hbox{}\ignorespaces} + +% @/ allows a line break. +\let\/=\allowbreak + +% @. is an end-of-sentence period. +\def\.{.\spacefactor=\endofsentencespacefactor\space} + +% @! is an end-of-sentence bang. +\def\!{!\spacefactor=\endofsentencespacefactor\space} + +% @? is an end-of-sentence query. +\def\?{?\spacefactor=\endofsentencespacefactor\space} + +% @frenchspacing on|off says whether to put extra space after punctuation. +% +\def\onword{on} +\def\offword{off} +% +\parseargdef\frenchspacing{% + \def\temp{#1}% + \ifx\temp\onword \plainfrenchspacing + \else\ifx\temp\offword \plainnonfrenchspacing + \else + \errhelp = \EMsimple + \errmessage{Unknown @frenchspacing option `\temp', must be on/off}% + \fi\fi +} + +% @w prevents a word break. Without the \leavevmode, @w at the +% beginning of a paragraph, when TeX is still in vertical mode, would +% produce a whole line of output instead of starting the paragraph. +\def\w#1{\leavevmode\hbox{#1}} + +% @group ... @end group forces ... to be all on one page, by enclosing +% it in a TeX vbox. We use \vtop instead of \vbox to construct the box +% to keep its height that of a normal line. According to the rules for +% \topskip (p.114 of the TeXbook), the glue inserted is +% max (\topskip - \ht (first item), 0). If that height is large, +% therefore, no glue is inserted, and the space between the headline and +% the text is small, which looks bad. +% +% Another complication is that the group might be very large. This can +% cause the glue on the previous page to be unduly stretched, because it +% does not have much material. In this case, it's better to add an +% explicit \vfill so that the extra space is at the bottom. The +% threshold for doing this is if the group is more than \vfilllimit +% percent of a page (\vfilllimit can be changed inside of @tex). +% +\newbox\groupbox +\def\vfilllimit{0.7} +% +\envdef\group{% + \ifnum\catcode`\^^M=\active \else + \errhelp = \groupinvalidhelp + \errmessage{@group invalid in context where filling is enabled}% + \fi + \startsavinginserts + % + \setbox\groupbox = \vtop\bgroup + % Do @comment since we are called inside an environment such as + % @example, where each end-of-line in the input causes an + % end-of-line in the output. We don't want the end-of-line after + % the `@group' to put extra space in the output. Since @group + % should appear on a line by itself (according to the Texinfo + % manual), we don't worry about eating any user text. + \comment +} +% +% The \vtop produces a box with normal height and large depth; thus, TeX puts +% \baselineskip glue before it, and (when the next line of text is done) +% \lineskip glue after it. Thus, space below is not quite equal to space +% above. But it's pretty close. +\def\Egroup{% + % To get correct interline space between the last line of the group + % and the first line afterwards, we have to propagate \prevdepth. + \endgraf % Not \par, as it may have been set to \lisppar. + \global\dimen1 = \prevdepth + \egroup % End the \vtop. + % \dimen0 is the vertical size of the group's box. + \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox + % \dimen2 is how much space is left on the page (more or less). + \dimen2 = \pageheight \advance\dimen2 by -\pagetotal + % if the group doesn't fit on the current page, and it's a big big + % group, force a page break. + \ifdim \dimen0 > \dimen2 + \ifdim \pagetotal < \vfilllimit\pageheight + \page + \fi + \fi + \box\groupbox + \prevdepth = \dimen1 + \checkinserts +} +% +% TeX puts in an \escapechar (i.e., `@') at the beginning of the help +% message, so this ends up printing `@group can only ...'. +% +\newhelp\groupinvalidhelp{% +group can only be used in environments such as @example,^^J% +where each line of input produces a line of output.} + +% @need space-in-mils +% forces a page break if there is not space-in-mils remaining. + +\newdimen\mil \mil=0.001in + +% Old definition--didn't work. +%\parseargdef\need{\par % +%% This method tries to make TeX break the page naturally +%% if the depth of the box does not fit. +%{\baselineskip=0pt% +%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak +%\prevdepth=-1000pt +%}} + +\parseargdef\need{% + % Ensure vertical mode, so we don't make a big box in the middle of a + % paragraph. + \par + % + % If the @need value is less than one line space, it's useless. + \dimen0 = #1\mil + \dimen2 = \ht\strutbox + \advance\dimen2 by \dp\strutbox + \ifdim\dimen0 > \dimen2 + % + % Do a \strut just to make the height of this box be normal, so the + % normal leading is inserted relative to the preceding line. + % And a page break here is fine. + \vtop to #1\mil{\strut\vfil}% + % + % TeX does not even consider page breaks if a penalty added to the + % main vertical list is 10000 or more. But in order to see if the + % empty box we just added fits on the page, we must make it consider + % page breaks. On the other hand, we don't want to actually break the + % page after the empty box. So we use a penalty of 9999. + % + % There is an extremely small chance that TeX will actually break the + % page at this \penalty, if there are no other feasible breakpoints in + % sight. (If the user is using lots of big @group commands, which + % almost-but-not-quite fill up a page, TeX will have a hard time doing + % good page breaking, for example.) However, I could not construct an + % example where a page broke at this \penalty; if it happens in a real + % document, then we can reconsider our strategy. + \penalty9999 + % + % Back up by the size of the box, whether we did a page break or not. + \kern -#1\mil + % + % Do not allow a page break right after this kern. + \nobreak + \fi +} + +% @br forces paragraph break (and is undocumented). + +\let\br = \par + +% @page forces the start of a new page. +% +\def\page{\par\vfill\supereject} + +% @exdent text.... +% outputs text on separate line in roman font, starting at standard page margin + +% This records the amount of indent in the innermost environment. +% That's how much \exdent should take out. +\newskip\exdentamount + +% This defn is used inside fill environments such as @defun. +\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} + +% This defn is used inside nofill environments such as @example. +\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount + \leftline{\hskip\leftskip{\rm#1}}}} + +% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current +% paragraph. For more general purposes, use the \margin insertion +% class. WHICH is `l' or `r'. +% +\newskip\inmarginspacing \inmarginspacing=1cm +\def\strutdepth{\dp\strutbox} +% +\def\doinmargin#1#2{\strut\vadjust{% + \nobreak + \kern-\strutdepth + \vtop to \strutdepth{% + \baselineskip=\strutdepth + \vss + % if you have multiple lines of stuff to put here, you'll need to + % make the vbox yourself of the appropriate size. + \ifx#1l% + \llap{\ignorespaces #2\hskip\inmarginspacing}% + \else + \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% + \fi + \null + }% +}} +\def\inleftmargin{\doinmargin l} +\def\inrightmargin{\doinmargin r} +% +% @inmargin{TEXT [, RIGHT-TEXT]} +% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; +% else use TEXT for both). +% +\def\inmargin#1{\parseinmargin #1,,\finish} +\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \def\lefttext{#1}% have both texts + \def\righttext{#2}% + \else + \def\lefttext{#1}% have only one text + \def\righttext{#1}% + \fi + % + \ifodd\pageno + \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin + \else + \def\temp{\inleftmargin\lefttext}% + \fi + \temp +} + +% @include file insert text of that file as input. +% +\def\include{\parseargusing\filenamecatcodes\includezzz} +\def\includezzz#1{% + \pushthisfilestack + \def\thisfile{#1}% + {% + \makevalueexpandable + \def\temp{\input #1 }% + \expandafter + }\temp + \popthisfilestack +} +\def\filenamecatcodes{% + \catcode`\\=\other + \catcode`~=\other + \catcode`^=\other + \catcode`_=\other + \catcode`|=\other + \catcode`<=\other + \catcode`>=\other + \catcode`+=\other + \catcode`-=\other +} + +\def\pushthisfilestack{% + \expandafter\pushthisfilestackX\popthisfilestack\StackTerm +} +\def\pushthisfilestackX{% + \expandafter\pushthisfilestackY\thisfile\StackTerm +} +\def\pushthisfilestackY #1\StackTerm #2\StackTerm {% + \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% +} + +\def\popthisfilestack{\errthisfilestackempty} +\def\errthisfilestackempty{\errmessage{Internal error: + the stack of filenames is empty.}} + +\def\thisfile{} + +% @center line +% outputs that line, centered. +% +\parseargdef\center{% + \ifhmode + \let\next\centerH + \else + \let\next\centerV + \fi + \next{\hfil \ignorespaces#1\unskip \hfil}% +} +\def\centerH#1{% + {% + \hfil\break + \advance\hsize by -\leftskip + \advance\hsize by -\rightskip + \line{#1}% + \break + }% +} +\def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} + +% @sp n outputs n lines of vertical space + +\parseargdef\sp{\vskip #1\baselineskip} + +% @comment ...line which is ignored... +% @c is the same as @comment +% @ignore ... @end ignore is another way to write a comment + +\def\comment{\begingroup \catcode`\^^M=\other% +\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% +\commentxxx} +{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} + +\let\c=\comment + +% @paragraphindent NCHARS +% We'll use ems for NCHARS, close enough. +% NCHARS can also be the word `asis' or `none'. +% We cannot feasibly implement @paragraphindent asis, though. +% +\def\asisword{asis} % no translation, these are keywords +\def\noneword{none} +% +\parseargdef\paragraphindent{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \defaultparindent = 0pt + \else + \defaultparindent = #1em + \fi + \fi + \parindent = \defaultparindent +} + +% @exampleindent NCHARS +% We'll use ems for NCHARS like @paragraphindent. +% It seems @exampleindent asis isn't necessary, but +% I preserve it to make it similar to @paragraphindent. +\parseargdef\exampleindent{% + \def\temp{#1}% + \ifx\temp\asisword + \else + \ifx\temp\noneword + \lispnarrowing = 0pt + \else + \lispnarrowing = #1em + \fi + \fi +} + +% @firstparagraphindent WORD +% If WORD is `none', then suppress indentation of the first paragraph +% after a section heading. If WORD is `insert', then do indent at such +% paragraphs. +% +% The paragraph indentation is suppressed or not by calling +% \suppressfirstparagraphindent, which the sectioning commands do. +% We switch the definition of this back and forth according to WORD. +% By default, we suppress indentation. +% +\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} +\def\insertword{insert} +% +\parseargdef\firstparagraphindent{% + \def\temp{#1}% + \ifx\temp\noneword + \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent + \else\ifx\temp\insertword + \let\suppressfirstparagraphindent = \relax + \else + \errhelp = \EMsimple + \errmessage{Unknown @firstparagraphindent option `\temp'}% + \fi\fi +} + +% Here is how we actually suppress indentation. Redefine \everypar to +% \kern backwards by \parindent, and then reset itself to empty. +% +% We also make \indent itself not actually do anything until the next +% paragraph. +% +\gdef\dosuppressfirstparagraphindent{% + \gdef\indent{% + \restorefirstparagraphindent + \indent + }% + \gdef\noindent{% + \restorefirstparagraphindent + \noindent + }% + \global\everypar = {% + \kern -\parindent + \restorefirstparagraphindent + }% +} + +\gdef\restorefirstparagraphindent{% + \global \let \indent = \ptexindent + \global \let \noindent = \ptexnoindent + \global \everypar = {}% +} + + +% @asis just yields its argument. Used with @table, for example. +% +\def\asis#1{#1} + +% @math outputs its argument in math mode. +% +% One complication: _ usually means subscripts, but it could also mean +% an actual _ character, as in @math{@var{some_variable} + 1}. So make +% _ active, and distinguish by seeing if the current family is \slfam, +% which is what @var uses. +{ + \catcode`\_ = \active + \gdef\mathunderscore{% + \catcode`\_=\active + \def_{\ifnum\fam=\slfam \_\else\sb\fi}% + } +} +% Another complication: we want \\ (and @\) to output a \ character. +% FYI, plain.tex uses \\ as a temporary control sequence (why?), but +% this is not advertised and we don't care. Texinfo does not +% otherwise define @\. +% +% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. +\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} +% +\def\math{% + \tex + \mathunderscore + \let\\ = \mathbackslash + \mathactive + $\finishmath +} +\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. + +% Some active characters (such as <) are spaced differently in math. +% We have to reset their definitions in case the @math was an argument +% to a command which sets the catcodes (such as @item or @section). +% +{ + \catcode`^ = \active + \catcode`< = \active + \catcode`> = \active + \catcode`+ = \active + \gdef\mathactive{% + \let^ = \ptexhat + \let< = \ptexless + \let> = \ptexgtr + \let+ = \ptexplus + } +} + +% @bullet and @minus need the same treatment as @math, just above. +\def\bullet{$\ptexbullet$} +\def\minus{$-$} + +% @dots{} outputs an ellipsis using the current font. +% We do .5em per period so that it has the same spacing in a typewriter +% font as three actual period characters. +% +\def\dots{% + \leavevmode + \hbox to 1.5em{% + \hskip 0pt plus 0.25fil + .\hfil.\hfil.% + \hskip 0pt plus 0.5fil + }% +} + +% @enddots{} is an end-of-sentence ellipsis. +% +\def\enddots{% + \dots + \spacefactor=\endofsentencespacefactor +} + +% @comma{} is so commas can be inserted into text without messing up +% Texinfo's parsing. +% +\let\comma = , + +% @refill is a no-op. +\let\refill=\relax + +% If working on a large document in chapters, it is convenient to +% be able to disable indexing, cross-referencing, and contents, for test runs. +% This is done with @novalidate (before @setfilename). +% +\newif\iflinks \linkstrue % by default we want the aux files. +\let\novalidate = \linksfalse + +% @setfilename is done at the beginning of every texinfo file. +% So open here the files we need to have open while reading the input. +% This makes it possible to make a .fmt file for texinfo. +\def\setfilename{% + \fixbackslash % Turn off hack to swallow `\input texinfo'. + \iflinks + \tryauxfile + % Open the new aux file. TeX will close it automatically at exit. + \immediate\openout\auxfile=\jobname.aux + \fi % \openindices needs to do some work in any case. + \openindices + \let\setfilename=\comment % Ignore extra @setfilename cmds. + % + % If texinfo.cnf is present on the system, read it. + % Useful for site-wide @afourpaper, etc. + \openin 1 texinfo.cnf + \ifeof 1 \else \input texinfo.cnf \fi + \closein 1 + % + \comment % Ignore the actual filename. +} + +% Called from \setfilename. +% +\def\openindices{% + \newindex{cp}% + \newcodeindex{fn}% + \newcodeindex{vr}% + \newcodeindex{tp}% + \newcodeindex{ky}% + \newcodeindex{pg}% +} + +% @bye. +\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} + + +\message{pdf,} +% adobe `portable' document format +\newcount\tempnum +\newcount\lnkcount +\newtoks\filename +\newcount\filenamelength +\newcount\pgn +\newtoks\toksA +\newtoks\toksB +\newtoks\toksC +\newtoks\toksD +\newbox\boxA +\newcount\countA +\newif\ifpdf +\newif\ifpdfmakepagedest + +% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 +% can be set). So we test for \relax and 0 as well as \undefined, +% borrowed from ifpdf.sty. +\ifx\pdfoutput\undefined +\else + \ifx\pdfoutput\relax + \else + \ifcase\pdfoutput + \else + \pdftrue + \fi + \fi +\fi + +% PDF uses PostScript string constants for the names of xref targets, +% for display in the outlines, and in other places. Thus, we have to +% double any backslashes. Otherwise, a name like "\node" will be +% interpreted as a newline (\n), followed by o, d, e. Not good. +% http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html +% (and related messages, the final outcome is that it is up to the TeX +% user to double the backslashes and otherwise make the string valid, so +% that's what we do). + +% double active backslashes. +% +{\catcode`\@=0 \catcode`\\=\active + @gdef@activebackslashdouble{% + @catcode`@\=@active + @let\=@doublebackslash} +} + +% To handle parens, we must adopt a different approach, since parens are +% not active characters. hyperref.dtx (which has the same problem as +% us) handles it with this amazing macro to replace tokens. I've +% tinkered with it a little for texinfo, but it's definitely from there. +% +% #1 is the tokens to replace. +% #2 is the replacement. +% #3 is the control sequence with the string. +% +\def\HyPsdSubst#1#2#3{% + \def\HyPsdReplace##1#1##2\END{% + ##1% + \ifx\\##2\\% + \else + #2% + \HyReturnAfterFi{% + \HyPsdReplace##2\END + }% + \fi + }% + \xdef#3{\expandafter\HyPsdReplace#3#1\END}% +} +\long\def\HyReturnAfterFi#1\fi{\fi#1} + +% #1 is a control sequence in which to do the replacements. +\def\backslashparens#1{% + \xdef#1{#1}% redefine it as its expansion; the definition is simply + % \lastnode when called from \setref -> \pdfmkdest. + \HyPsdSubst{(}{\realbackslash(}{#1}% + \HyPsdSubst{)}{\realbackslash)}{#1}% +} + +\ifpdf + \input pdfcolor + \pdfcatalog{/PageMode /UseOutlines}% + \def\dopdfimage#1#2#3{% + \def\imagewidth{#2}% + \def\imageheight{#3}% + % without \immediate, pdftex seg faults when the same image is + % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) + \ifnum\pdftexversion < 14 + \immediate\pdfimage + \else + \immediate\pdfximage + \fi + \ifx\empty\imagewidth\else width \imagewidth \fi + \ifx\empty\imageheight\else height \imageheight \fi + \ifnum\pdftexversion<13 + #1.pdf% + \else + {#1.pdf}% + \fi + \ifnum\pdftexversion < 14 \else + \pdfrefximage \pdflastximage + \fi} + \def\pdfmkdest#1{{% + % We have to set dummies so commands such as @code, and characters + % such as \, aren't expanded when present in a section title. + \atdummies + \activebackslashdouble + \def\pdfdestname{#1}% + \backslashparens\pdfdestname + \pdfdest name{\pdfdestname} xyz% + }}% + % + % used to mark target names; must be expandable. + \def\pdfmkpgn#1{#1}% + % + \let\linkcolor = \Blue % was Cyan, but that seems light? + \def\endlink{\Black\pdfendlink} + % Adding outlines to PDF; macros for calculating structure of outlines + % come from Petr Olsak + \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% + \else \csname#1\endcsname \fi} + \def\advancenumber#1{\tempnum=\expnumber{#1}\relax + \advance\tempnum by 1 + \expandafter\xdef\csname#1\endcsname{\the\tempnum}} + % + % #1 is the section text, which is what will be displayed in the + % outline by the pdf viewer. #2 is the pdf expression for the number + % of subentries (or empty, for subsubsections). #3 is the node text, + % which might be empty if this toc entry had no corresponding node. + % #4 is the page number + % + \def\dopdfoutline#1#2#3#4{% + % Generate a link to the node text if that exists; else, use the + % page number. We could generate a destination for the section + % text in the case where a section has no node, but it doesn't + % seem worth the trouble, since most documents are normally structured. + \def\pdfoutlinedest{#3}% + \ifx\pdfoutlinedest\empty + \def\pdfoutlinedest{#4}% + \else + % Doubled backslashes in the name. + {\activebackslashdouble \xdef\pdfoutlinedest{#3}% + \backslashparens\pdfoutlinedest}% + \fi + % + % Also double the backslashes in the display string. + {\activebackslashdouble \xdef\pdfoutlinetext{#1}% + \backslashparens\pdfoutlinetext}% + % + \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{\pdfoutlinetext}% + } + % + \def\pdfmakeoutlines{% + \begingroup + % Thanh's hack / proper braces in bookmarks + \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace + \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace + % + % Read toc silently, to get counts of subentries for \pdfoutline. + \def\numchapentry##1##2##3##4{% + \def\thischapnum{##2}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% + }% + \def\numsecentry##1##2##3##4{% + \advancenumber{chap\thischapnum}% + \def\thissecnum{##2}% + \def\thissubsecnum{0}% + }% + \def\numsubsecentry##1##2##3##4{% + \advancenumber{sec\thissecnum}% + \def\thissubsecnum{##2}% + }% + \def\numsubsubsecentry##1##2##3##4{% + \advancenumber{subsec\thissubsecnum}% + }% + \def\thischapnum{0}% + \def\thissecnum{0}% + \def\thissubsecnum{0}% + % + % use \def rather than \let here because we redefine \chapentry et + % al. a second time, below. + \def\appentry{\numchapentry}% + \def\appsecentry{\numsecentry}% + \def\appsubsecentry{\numsubsecentry}% + \def\appsubsubsecentry{\numsubsubsecentry}% + \def\unnchapentry{\numchapentry}% + \def\unnsecentry{\numsecentry}% + \def\unnsubsecentry{\numsubsecentry}% + \def\unnsubsubsecentry{\numsubsubsecentry}% + \readdatafile{toc}% + % + % Read toc second time, this time actually producing the outlines. + % The `-' means take the \expnumber as the absolute number of + % subentries, which we calculated on our first read of the .toc above. + % + % We use the node names as the destinations. + \def\numchapentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% + \def\numsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% + \def\numsubsecentry##1##2##3##4{% + \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% + \def\numsubsubsecentry##1##2##3##4{% count is always zero + \dopdfoutline{##1}{}{##3}{##4}}% + % + % PDF outlines are displayed using system fonts, instead of + % document fonts. Therefore we cannot use special characters, + % since the encoding is unknown. For example, the eogonek from + % Latin 2 (0xea) gets translated to a | character. Info from + % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. + % + % xx to do this right, we have to translate 8-bit characters to + % their "best" equivalent, based on the @documentencoding. Right + % now, I guess we'll just let the pdf reader have its way. + \indexnofonts + \setupdatafile + \catcode`\\=\active \otherbackslash + \input \jobname.toc + \endgroup + } + % + \def\skipspaces#1{\def\PP{#1}\def\D{|}% + \ifx\PP\D\let\nextsp\relax + \else\let\nextsp\skipspaces + \ifx\p\space\else\addtokens{\filename}{\PP}% + \advance\filenamelength by 1 + \fi + \fi + \nextsp} + \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} + \ifnum\pdftexversion < 14 + \let \startlink \pdfannotlink + \else + \let \startlink \pdfstartlink + \fi + % make a live url in pdf output. + \def\pdfurl#1{% + \begingroup + % it seems we really need yet another set of dummies; have not + % tried to figure out what each command should do in the context + % of @url. for now, just make @/ a no-op, that's the only one + % people have actually reported a problem with. + % + \normalturnoffactive + \def\@{@}% + \let\/=\empty + \makevalueexpandable + \leavevmode\Red + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + \endgroup} + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS|\relax + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdflink#1{% + \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} + \linkcolor #1\endlink} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\else + \let\pdfmkdest = \gobble + \let\pdfurl = \gobble + \let\endlink = \relax + \let\linkcolor = \relax + \let\pdfmakeoutlines = \relax +\fi % \ifx\pdfoutput + + +\message{fonts,} + +% Change the current font style to #1, remembering it in \curfontstyle. +% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in +% italics, not bold italics. +% +\def\setfontstyle#1{% + \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. + \csname ten#1\endcsname % change the current font +} + +% Select #1 fonts with the current style. +% +\def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} + +\def\rm{\fam=0 \setfontstyle{rm}} +\def\it{\fam=\itfam \setfontstyle{it}} +\def\sl{\fam=\slfam \setfontstyle{sl}} +\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} +\def\tt{\fam=\ttfam \setfontstyle{tt}} + +% Texinfo sort of supports the sans serif font style, which plain TeX does not. +% So we set up a \sf. +\newfam\sffam +\def\sf{\fam=\sffam \setfontstyle{sf}} +\let\li = \sf % Sometimes we call it \li, not \sf. + +% We don't need math for this font style. +\def\ttsl{\setfontstyle{ttsl}} + +% Default leading. +\newdimen\textleading \textleading = 13.2pt + +% Set the baselineskip to #1, and the lineskip and strut size +% correspondingly. There is no deep meaning behind these magic numbers +% used as factors; they just match (closely enough) what Knuth defined. +% +\def\lineskipfactor{.08333} +\def\strutheightpercent{.70833} +\def\strutdepthpercent {.29167} +% +\def\setleading#1{% + \normalbaselineskip = #1\relax + \normallineskip = \lineskipfactor\normalbaselineskip + \normalbaselines + \setbox\strutbox =\hbox{% + \vrule width0pt height\strutheightpercent\baselineskip + depth \strutdepthpercent \baselineskip + }% +} + +% Set the font macro #1 to the font named #2, adding on the +% specified font prefix (normally `cm'). +% #3 is the font's design size, #4 is a scale factor +\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} + +% Use cm as the default font prefix. +% To specify the font prefix, you must define \fontprefix +% before you read in texinfo.tex. +\ifx\fontprefix\undefined +\def\fontprefix{cm} +\fi +% Support font families that don't use the same naming scheme as CM. +\def\rmshape{r} +\def\rmbshape{bx} %where the normal face is bold +\def\bfshape{b} +\def\bxshape{bx} +\def\ttshape{tt} +\def\ttbshape{tt} +\def\ttslshape{sltt} +\def\itshape{ti} +\def\itbshape{bxti} +\def\slshape{sl} +\def\slbshape{bxsl} +\def\sfshape{ss} +\def\sfbshape{ss} +\def\scshape{csc} +\def\scbshape{csc} + +% Text fonts (11.2pt, magstep1). +\def\textnominalsize{11pt} +\edef\mainmagstep{\magstephalf} +\setfont\textrm\rmshape{10}{\mainmagstep} +\setfont\texttt\ttshape{10}{\mainmagstep} +\setfont\textbf\bfshape{10}{\mainmagstep} +\setfont\textit\itshape{10}{\mainmagstep} +\setfont\textsl\slshape{10}{\mainmagstep} +\setfont\textsf\sfshape{10}{\mainmagstep} +\setfont\textsc\scshape{10}{\mainmagstep} +\setfont\textttsl\ttslshape{10}{\mainmagstep} +\font\texti=cmmi10 scaled \mainmagstep +\font\textsy=cmsy10 scaled \mainmagstep + +% A few fonts for @defun names and args. +\setfont\defbf\bfshape{10}{\magstep1} +\setfont\deftt\ttshape{10}{\magstep1} +\setfont\defttsl\ttslshape{10}{\magstep1} +\def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} + +% Fonts for indices, footnotes, small examples (9pt). +\def\smallnominalsize{9pt} +\setfont\smallrm\rmshape{9}{1000} +\setfont\smalltt\ttshape{9}{1000} +\setfont\smallbf\bfshape{10}{900} +\setfont\smallit\itshape{9}{1000} +\setfont\smallsl\slshape{9}{1000} +\setfont\smallsf\sfshape{9}{1000} +\setfont\smallsc\scshape{10}{900} +\setfont\smallttsl\ttslshape{10}{900} +\font\smalli=cmmi9 +\font\smallsy=cmsy9 + +% Fonts for small examples (8pt). +\def\smallernominalsize{8pt} +\setfont\smallerrm\rmshape{8}{1000} +\setfont\smallertt\ttshape{8}{1000} +\setfont\smallerbf\bfshape{10}{800} +\setfont\smallerit\itshape{8}{1000} +\setfont\smallersl\slshape{8}{1000} +\setfont\smallersf\sfshape{8}{1000} +\setfont\smallersc\scshape{10}{800} +\setfont\smallerttsl\ttslshape{10}{800} +\font\smalleri=cmmi8 +\font\smallersy=cmsy8 + +% Fonts for title page (20.4pt): +\def\titlenominalsize{20pt} +\setfont\titlerm\rmbshape{12}{\magstep3} +\setfont\titleit\itbshape{10}{\magstep4} +\setfont\titlesl\slbshape{10}{\magstep4} +\setfont\titlett\ttbshape{12}{\magstep3} +\setfont\titlettsl\ttslshape{10}{\magstep4} +\setfont\titlesf\sfbshape{17}{\magstep1} +\let\titlebf=\titlerm +\setfont\titlesc\scbshape{10}{\magstep4} +\font\titlei=cmmi12 scaled \magstep3 +\font\titlesy=cmsy10 scaled \magstep4 +\def\authorrm{\secrm} +\def\authortt{\sectt} + +% Chapter (and unnumbered) fonts (17.28pt). +\def\chapnominalsize{17pt} +\setfont\chaprm\rmbshape{12}{\magstep2} +\setfont\chapit\itbshape{10}{\magstep3} +\setfont\chapsl\slbshape{10}{\magstep3} +\setfont\chaptt\ttbshape{12}{\magstep2} +\setfont\chapttsl\ttslshape{10}{\magstep3} +\setfont\chapsf\sfbshape{17}{1000} +\let\chapbf=\chaprm +\setfont\chapsc\scbshape{10}{\magstep3} +\font\chapi=cmmi12 scaled \magstep2 +\font\chapsy=cmsy10 scaled \magstep3 + +% Section fonts (14.4pt). +\def\secnominalsize{14pt} +\setfont\secrm\rmbshape{12}{\magstep1} +\setfont\secit\itbshape{10}{\magstep2} +\setfont\secsl\slbshape{10}{\magstep2} +\setfont\sectt\ttbshape{12}{\magstep1} +\setfont\secttsl\ttslshape{10}{\magstep2} +\setfont\secsf\sfbshape{12}{\magstep1} +\let\secbf\secrm +\setfont\secsc\scbshape{10}{\magstep2} +\font\seci=cmmi12 scaled \magstep1 +\font\secsy=cmsy10 scaled \magstep2 + +% Subsection fonts (13.15pt). +\def\ssecnominalsize{13pt} +\setfont\ssecrm\rmbshape{12}{\magstephalf} +\setfont\ssecit\itbshape{10}{1315} +\setfont\ssecsl\slbshape{10}{1315} +\setfont\ssectt\ttbshape{12}{\magstephalf} +\setfont\ssecttsl\ttslshape{10}{1315} +\setfont\ssecsf\sfbshape{12}{\magstephalf} +\let\ssecbf\ssecrm +\setfont\ssecsc\scbshape{10}{1315} +\font\sseci=cmmi12 scaled \magstephalf +\font\ssecsy=cmsy10 scaled 1315 + +% Reduced fonts for @acro in text (10pt). +\def\reducednominalsize{10pt} +\setfont\reducedrm\rmshape{10}{1000} +\setfont\reducedtt\ttshape{10}{1000} +\setfont\reducedbf\bfshape{10}{1000} +\setfont\reducedit\itshape{10}{1000} +\setfont\reducedsl\slshape{10}{1000} +\setfont\reducedsf\sfshape{10}{1000} +\setfont\reducedsc\scshape{10}{1000} +\setfont\reducedttsl\ttslshape{10}{1000} +\font\reducedi=cmmi10 +\font\reducedsy=cmsy10 + +% In order for the font changes to affect most math symbols and letters, +% we have to define the \textfont of the standard families. Since +% texinfo doesn't allow for producing subscripts and superscripts except +% in the main text, we don't bother to reset \scriptfont and +% \scriptscriptfont (which would also require loading a lot more fonts). +% +\def\resetmathfonts{% + \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy + \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf + \textfont\ttfam=\tentt \textfont\sffam=\tensf +} + +% The font-changing commands redefine the meanings of \tenSTYLE, instead +% of just \STYLE. We do this because \STYLE needs to also set the +% current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire +% \tenSTYLE to set the current font. +% +% Each font-changing command also sets the names \lsize (one size lower) +% and \lllsize (three sizes lower). These relative commands are used in +% the LaTeX logo and acronyms. +% +% This all needs generalizing, badly. +% +\def\textfonts{% + \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl + \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc + \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy + \let\tenttsl=\textttsl + \def\curfontsize{text}% + \def\lsize{reduced}\def\lllsize{smaller}% + \resetmathfonts \setleading{\textleading}} +\def\titlefonts{% + \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl + \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc + \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy + \let\tenttsl=\titlettsl + \def\curfontsize{title}% + \def\lsize{chap}\def\lllsize{subsec}% + \resetmathfonts \setleading{25pt}} +\def\titlefont#1{{\titlefonts\rm #1}} +\def\chapfonts{% + \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl + \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc + \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy + \let\tenttsl=\chapttsl + \def\curfontsize{chap}% + \def\lsize{sec}\def\lllsize{text}% + \resetmathfonts \setleading{19pt}} +\def\secfonts{% + \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl + \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc + \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy + \let\tenttsl=\secttsl + \def\curfontsize{sec}% + \def\lsize{subsec}\def\lllsize{reduced}% + \resetmathfonts \setleading{16pt}} +\def\subsecfonts{% + \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl + \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc + \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy + \let\tenttsl=\ssecttsl + \def\curfontsize{ssec}% + \def\lsize{text}\def\lllsize{small}% + \resetmathfonts \setleading{15pt}} +\let\subsubsecfonts = \subsecfonts +\def\reducedfonts{% + \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl + \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc + \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy + \let\tenttsl=\reducedttsl + \def\curfontsize{reduced}% + \def\lsize{small}\def\lllsize{smaller}% + \resetmathfonts \setleading{10.5pt}} +\def\smallfonts{% + \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl + \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc + \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy + \let\tenttsl=\smallttsl + \def\curfontsize{small}% + \def\lsize{smaller}\def\lllsize{smaller}% + \resetmathfonts \setleading{10.5pt}} +\def\smallerfonts{% + \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl + \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc + \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy + \let\tenttsl=\smallerttsl + \def\curfontsize{smaller}% + \def\lsize{smaller}\def\lllsize{smaller}% + \resetmathfonts \setleading{9.5pt}} + +% Set the fonts to use with the @small... environments. +\let\smallexamplefonts = \smallfonts + +% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample +% can fit this many characters: +% 8.5x11=86 smallbook=72 a4=90 a5=69 +% If we use \scriptfonts (8pt), then we can fit this many characters: +% 8.5x11=90+ smallbook=80 a4=90+ a5=77 +% For me, subjectively, the few extra characters that fit aren't worth +% the additional smallness of 8pt. So I'm making the default 9pt. +% +% By the way, for comparison, here's what fits with @example (10pt): +% 8.5x11=71 smallbook=60 a4=75 a5=58 +% +% I wish the USA used A4 paper. +% --karl, 24jan03. + + +% Set up the default fonts, so we can use them for creating boxes. +% +\textfonts \rm + +% Define these so they can be easily changed for other fonts. +\def\angleleft{$\langle$} +\def\angleright{$\rangle$} + +% Count depth in font-changes, for error checks +\newcount\fontdepth \fontdepth=0 + +% Fonts for short table of contents. +\setfont\shortcontrm\rmshape{12}{1000} +\setfont\shortcontbf\bfshape{10}{\magstep1} % no cmb12 +\setfont\shortcontsl\slshape{12}{1000} +\setfont\shortconttt\ttshape{12}{1000} + +%% Add scribe-like font environments, plus @l for inline lisp (usually sans +%% serif) and @ii for TeX italic + +% \smartitalic{ARG} outputs arg in italics, followed by an italic correction +% unless the following character is such as not to need one. +\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else + \ptexslash\fi\fi\fi} +\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} +\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} + +% like \smartslanted except unconditionally uses \ttsl. +% @var is set to this for defun arguments. +\def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx} + +% like \smartslanted except unconditionally use \sl. We never want +% ttsl for book titles, do we? +\def\cite#1{{\sl #1}\futurelet\next\smartitalicx} + +\let\i=\smartitalic +\let\slanted=\smartslanted +\let\var=\smartslanted +\let\dfn=\smartslanted +\let\emph=\smartitalic + +% @b, explicit bold. +\def\b#1{{\bf #1}} +\let\strong=\b + +% @sansserif, explicit sans. +\def\sansserif#1{{\sf #1}} + +% We can't just use \exhyphenpenalty, because that only has effect at +% the end of a paragraph. Restore normal hyphenation at the end of the +% group within which \nohyphenation is presumably called. +% +\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} +\def\restorehyphenation{\hyphenchar\font = `- } + +% Set sfcode to normal for the chars that usually have another value. +% Can't use plain's \frenchspacing because it uses the `\x notation, and +% sometimes \x has an active definition that messes things up. +% +\chardef\colonChar = `\: +\chardef\commaChar = `\, +\chardef\dotChar = `\. +\chardef\exclamChar= `\! +\chardef\questChar = `\? +\chardef\semiChar = `\; +% +\catcode`@=11 + \def\plainfrenchspacing{% + \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m + \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m + \def\endofsentencespacefactor{1000}% for @. and friends + } + \def\plainnonfrenchspacing{% + \sfcode`\.3000\sfcode`\?3000\sfcode`\!3000 + \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 + \def\endofsentencespacefactor{3000}% for @. and friends + } +\catcode`@=\other +\def\endofsentencespacefactor{3000}% default + +\def\t#1{% + {\tt \rawbackslash \plainfrenchspacing #1}% + \null +} +\def\samp#1{`\tclose{#1}'\null} +\setfont\keyrm\rmshape{8}{1000} +\font\keysy=cmsy9 +\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% + \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% + \vbox{\hrule\kern-0.4pt + \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% + \kern-0.4pt\hrule}% + \kern-.06em\raise0.4pt\hbox{\angleright}}}} +% The old definition, with no lozenge: +%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} +\def\ctrl #1{{\tt \rawbackslash \hat}#1} + +% @file, @option are the same as @samp. +\let\file=\samp +\let\option=\samp + +% @code is a modification of @t, +% which makes spaces the same size as normal in the surrounding text. +\def\tclose#1{% + {% + % Change normal interword space to be same as for the current font. + \spaceskip = \fontdimen2\font + % + % Switch to typewriter. + \tt + % + % But `\ ' produces the large typewriter interword space. + \def\ {{\spaceskip = 0pt{} }}% + % + % Turn off hyphenation. + \nohyphenation + % + \rawbackslash + \plainfrenchspacing + #1% + }% + \null +} + +% We *must* turn on hyphenation at `-' and `_' in @code. +% Otherwise, it is too hard to avoid overfull hboxes +% in the Emacs manual, the Library manual, etc. + +% Unfortunately, TeX uses one parameter (\hyphenchar) to control +% both hyphenation at - and hyphenation within words. +% We must therefore turn them both off (\tclose does that) +% and arrange explicitly to hyphenate at a dash. +% -- rms. +{ + \catcode`\-=\active + \catcode`\_=\active + % + \global\def\code{\begingroup + \catcode`\-=\active \catcode`\_=\active + \ifallowcodebreaks + \let-\codedash + \let_\codeunder + \else + \let-\realdash + \let_\realunder + \fi + \codex + } +} + +\def\realdash{-} +\def\codedash{-\discretionary{}{}{}} +\def\codeunder{% + % this is all so @math{@code{var_name}+1} can work. In math mode, _ + % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) + % will therefore expand the active definition of _, which is us + % (inside @code that is), therefore an endless loop. + \ifusingtt{\ifmmode + \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. + \else\normalunderscore \fi + \discretionary{}{}{}}% + {\_}% +} +\def\codex #1{\tclose{#1}\endgroup} + +% An additional complication: the above will allow breaks after, e.g., +% each of the four underscores in __typeof__. This is undesirable in +% some manuals, especially if they don't have long identifiers in +% general. @allowcodebreaks provides a way to control this. +% +\newif\ifallowcodebreaks \allowcodebreakstrue + +\def\keywordtrue{true} +\def\keywordfalse{false} + +\parseargdef\allowcodebreaks{% + \def\txiarg{#1}% + \ifx\txiarg\keywordtrue + \allowcodebreakstrue + \else\ifx\txiarg\keywordfalse + \allowcodebreaksfalse + \else + \errhelp = \EMsimple + \errmessage{Unknown @allowcodebreaks option `\txiarg'}% + \fi\fi +} + +% @kbd is like @code, except that if the argument is just one @key command, +% then @kbd has no effect. + +% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), +% `example' (@kbd uses ttsl only inside of @example and friends), +% or `code' (@kbd uses normal tty font always). +\parseargdef\kbdinputstyle{% + \def\txiarg{#1}% + \ifx\txiarg\worddistinct + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% + \else\ifx\txiarg\wordexample + \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% + \else\ifx\txiarg\wordcode + \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% + \else + \errhelp = \EMsimple + \errmessage{Unknown @kbdinputstyle option `\txiarg'}% + \fi\fi\fi +} +\def\worddistinct{distinct} +\def\wordexample{example} +\def\wordcode{code} + +% Default is `distinct.' +\kbdinputstyle distinct + +\def\xkey{\key} +\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% +\ifx\one\xkey\ifx\threex\three \key{#2}% +\else{\tclose{\kbdfont\look}}\fi +\else{\tclose{\kbdfont\look}}\fi} + +% For @indicateurl, @env, @command quotes seem unnecessary, so use \code. +\let\indicateurl=\code +\let\env=\code +\let\command=\code + +% @uref (abbreviation for `urlref') takes an optional (comma-separated) +% second argument specifying the text to display and an optional third +% arg as text to display instead of (rather than in addition to) the url +% itself. First (mandatory) arg is the url. Perhaps eventually put in +% a hypertex \special here. +% +\def\uref#1{\douref #1,,,\finish} +\def\douref#1,#2,#3,#4\finish{\begingroup + \unsepspaces + \pdfurl{#1}% + \setbox0 = \hbox{\ignorespaces #3}% + \ifdim\wd0 > 0pt + \unhbox0 % third arg given, show only that + \else + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0 > 0pt + \ifpdf + \unhbox0 % PDF: 2nd arg given, show only it + \else + \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url + \fi + \else + \code{#1}% only url given, so show it + \fi + \fi + \endlink +\endgroup} + +% @url synonym for @uref, since that's how everyone uses it. +% +\let\url=\uref + +% rms does not like angle brackets --karl, 17may97. +% So now @email is just like @uref, unless we are pdf. +% +%\def\email#1{\angleleft{\tt #1}\angleright} +\ifpdf + \def\email#1{\doemail#1,,\finish} + \def\doemail#1,#2,#3\finish{\begingroup + \unsepspaces + \pdfurl{mailto:#1}% + \setbox0 = \hbox{\ignorespaces #2}% + \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi + \endlink + \endgroup} +\else + \let\email=\uref +\fi + +% Check if we are currently using a typewriter font. Since all the +% Computer Modern typewriter fonts have zero interword stretch (and +% shrink), and it is reasonable to expect all typewriter fonts to have +% this property, we can check that font parameter. +% +\def\ifmonospace{\ifdim\fontdimen3\font=0pt } + +% Typeset a dimension, e.g., `in' or `pt'. The only reason for the +% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. +% +\def\dmn#1{\thinspace #1} + +\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} + +% @l was never documented to mean ``switch to the Lisp font'', +% and it is not used as such in any manual I can find. We need it for +% Polish suppressed-l. --karl, 22sep96. +%\def\l#1{{\li #1}\null} + +% Explicit font changes: @r, @sc, undocumented @ii. +\def\r#1{{\rm #1}} % roman font +\def\sc#1{{\smallcaps#1}} % smallcaps font +\def\ii#1{{\it #1}} % italic font + +% @acronym for "FBI", "NATO", and the like. +% We print this one point size smaller, since it's intended for +% all-uppercase. +% +\def\acronym#1{\doacronym #1,,\finish} +\def\doacronym#1,#2,#3\finish{% + {\selectfonts\lsize #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi +} + +% @abbr for "Comput. J." and the like. +% No font change, but don't do end-of-sentence spacing. +% +\def\abbr#1{\doabbr #1,,\finish} +\def\doabbr#1,#2,#3\finish{% + {\plainfrenchspacing #1}% + \def\temp{#2}% + \ifx\temp\empty \else + \space ({\unsepspaces \ignorespaces \temp \unskip})% + \fi +} + +% @pounds{} is a sterling sign, which Knuth put in the CM italic font. +% +\def\pounds{{\it\$}} + +% @euro{} comes from a separate font, depending on the current style. +% We use the free feym* fonts from the eurosym package by Henrik +% Theiling, which support regular, slanted, bold and bold slanted (and +% "outlined" (blackboard board, sort of) versions, which we don't need). +% It is available from http://www.ctan.org/tex-archive/fonts/eurosym. +% +% Although only regular is the truly official Euro symbol, we ignore +% that. The Euro is designed to be slightly taller than the regular +% font height. +% +% feymr - regular +% feymo - slanted +% feybr - bold +% feybo - bold slanted +% +% There is no good (free) typewriter version, to my knowledge. +% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide. +% Hmm. +% +% Also doesn't work in math. Do we need to do math with euro symbols? +% Hope not. +% +% +\def\euro{{\eurofont e}} +\def\eurofont{% + % We set the font at each command, rather than predefining it in + % \textfonts and the other font-switching commands, so that + % installations which never need the symbol don't have to have the + % font installed. + % + % There is only one designed size (nominal 10pt), so we always scale + % that to the current nominal size. + % + % By the way, simply using "at 1em" works for cmr10 and the like, but + % does not work for cmbx10 and other extended/shrunken fonts. + % + \def\eurosize{\csname\curfontsize nominalsize\endcsname}% + % + \ifx\curfontstyle\bfstylename + % bold: + \font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize + \else + % regular: + \font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize + \fi + \thiseurofont +} + +% @registeredsymbol - R in a circle. The font for the R should really +% be smaller yet, but lllsize is the best we can do for now. +% Adapted from the plain.tex definition of \copyright. +% +\def\registeredsymbol{% + $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% + \hfil\crcr\Orb}}% + }$% +} + +% Laurent Siebenmann reports \Orb undefined with: +% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38 +% so we'll define it if necessary. +% +\ifx\Orb\undefined +\def\Orb{\mathhexbox20D} +\fi + + +\message{page headings,} + +\newskip\titlepagetopglue \titlepagetopglue = 1.5in +\newskip\titlepagebottomglue \titlepagebottomglue = 2pc + +% First the title page. Must do @settitle before @titlepage. +\newif\ifseenauthor +\newif\iffinishedtitlepage + +% Do an implicit @contents or @shortcontents after @end titlepage if the +% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. +% +\newif\ifsetcontentsaftertitlepage + \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue +\newif\ifsetshortcontentsaftertitlepage + \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue + +\parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% + \endgroup\page\hbox{}\page} + +\envdef\titlepage{% + % Open one extra group, as we want to close it in the middle of \Etitlepage. + \begingroup + \parindent=0pt \textfonts + % Leave some space at the very top of the page. + \vglue\titlepagetopglue + % No rule at page bottom unless we print one at the top with @title. + \finishedtitlepagetrue + % + % Most title ``pages'' are actually two pages long, with space + % at the top of the second. We don't want the ragged left on the second. + \let\oldpage = \page + \def\page{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + \let\page = \oldpage + \page + \null + }% +} + +\def\Etitlepage{% + \iffinishedtitlepage\else + \finishtitlepage + \fi + % It is important to do the page break before ending the group, + % because the headline and footline are only empty inside the group. + % If we use the new definition of \page, we always get a blank page + % after the title page, which we certainly don't want. + \oldpage + \endgroup + % + % Need this before the \...aftertitlepage checks so that if they are + % in effect the toc pages will come out with page numbers. + \HEADINGSon + % + % If they want short, they certainly want long too. + \ifsetshortcontentsaftertitlepage + \shortcontents + \contents + \global\let\shortcontents = \relax + \global\let\contents = \relax + \fi + % + \ifsetcontentsaftertitlepage + \contents + \global\let\contents = \relax + \global\let\shortcontents = \relax + \fi +} + +\def\finishtitlepage{% + \vskip4pt \hrule height 2pt width \hsize + \vskip\titlepagebottomglue + \finishedtitlepagetrue +} + +%%% Macros to be used within @titlepage: + +\let\subtitlerm=\tenrm +\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} + +\def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines + \let\tt=\authortt} + +\parseargdef\title{% + \checkenv\titlepage + \leftline{\titlefonts\rm #1} + % print a rule at the page bottom also. + \finishedtitlepagefalse + \vskip4pt \hrule height 4pt width \hsize \vskip4pt +} + +\parseargdef\subtitle{% + \checkenv\titlepage + {\subtitlefont \rightline{#1}}% +} + +% @author should come last, but may come many times. +% It can also be used inside @quotation. +% +\parseargdef\author{% + \def\temp{\quotation}% + \ifx\thisenv\temp + \def\quotationauthor{#1}% printed in \Equotation. + \else + \checkenv\titlepage + \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi + {\authorfont \leftline{#1}}% + \fi +} + + +%%% Set up page headings and footings. + +\let\thispage=\folio + +\newtoks\evenheadline % headline on even pages +\newtoks\oddheadline % headline on odd pages +\newtoks\evenfootline % footline on even pages +\newtoks\oddfootline % footline on odd pages + +% Now make TeX use those variables +\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline + \else \the\evenheadline \fi}} +\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline + \else \the\evenfootline \fi}\HEADINGShook} +\let\HEADINGShook=\relax + +% Commands to set those variables. +% For example, this is what @headings on does +% @evenheading @thistitle|@thispage|@thischapter +% @oddheading @thischapter|@thispage|@thistitle +% @evenfooting @thisfile|| +% @oddfooting ||@thisfile + + +\def\evenheading{\parsearg\evenheadingxxx} +\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} +\def\evenheadingyyy #1\|#2\|#3\|#4\finish{% +\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\def\oddheading{\parsearg\oddheadingxxx} +\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} +\def\oddheadingyyy #1\|#2\|#3\|#4\finish{% +\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% + +\def\evenfooting{\parsearg\evenfootingxxx} +\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} +\def\evenfootingyyy #1\|#2\|#3\|#4\finish{% +\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} + +\def\oddfooting{\parsearg\oddfootingxxx} +\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} +\def\oddfootingyyy #1\|#2\|#3\|#4\finish{% + \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% + % + % Leave some space for the footline. Hopefully ok to assume + % @evenfooting will not be used by itself. + \global\advance\pageheight by -\baselineskip + \global\advance\vsize by -\baselineskip +} + +\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} + + +% @headings double turns headings on for double-sided printing. +% @headings single turns headings on for single-sided printing. +% @headings off turns them off. +% @headings on same as @headings double, retained for compatibility. +% @headings after turns on double-sided headings after this page. +% @headings doubleafter turns on double-sided headings after this page. +% @headings singleafter turns on single-sided headings after this page. +% By default, they are off at the start of a document, +% and turned `on' after @end titlepage. + +\def\headings #1 {\csname HEADINGS#1\endcsname} + +\def\HEADINGSoff{% +\global\evenheadline={\hfil} \global\evenfootline={\hfil} +\global\oddheadline={\hfil} \global\oddfootline={\hfil}} +\HEADINGSoff +% When we turn headings on, set the page number to 1. +% For double-sided printing, put current file name in lower left corner, +% chapter name on inside top of right hand pages, document +% title on inside top of left hand pages, and page numbers on outside top +% edge of all pages. +\def\HEADINGSdouble{% +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} +\let\contentsalignmacro = \chappager + +% For single-sided printing, chapter title goes across top left of page, +% page number on top right. +\def\HEADINGSsingle{% +\global\pageno=1 +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} +\def\HEADINGSon{\HEADINGSdouble} + +\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} +\let\HEADINGSdoubleafter=\HEADINGSafter +\def\HEADINGSdoublex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\folio\hfil\thistitle}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chapoddpage +} + +\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} +\def\HEADINGSsinglex{% +\global\evenfootline={\hfil} +\global\oddfootline={\hfil} +\global\evenheadline={\line{\thischapter\hfil\folio}} +\global\oddheadline={\line{\thischapter\hfil\folio}} +\global\let\contentsalignmacro = \chappager +} + +% Subroutines used in generating headings +% This produces Day Month Year style of output. +% Only define if not already defined, in case a txi-??.tex file has set +% up a different format (e.g., txi-cs.tex does this). +\ifx\today\undefined +\def\today{% + \number\day\space + \ifcase\month + \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr + \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug + \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec + \fi + \space\number\year} +\fi + +% @settitle line... specifies the title of the document, for headings. +% It generates no output of its own. +\def\thistitle{\putwordNoTitle} +\def\settitle{\parsearg{\gdef\thistitle}} + + +\message{tables,} +% Tables -- @table, @ftable, @vtable, @item(x). + +% default indentation of table text +\newdimen\tableindent \tableindent=.8in +% default indentation of @itemize and @enumerate text +\newdimen\itemindent \itemindent=.3in +% margin between end of table item and start of table text. +\newdimen\itemmargin \itemmargin=.1in + +% used internally for \itemindent minus \itemmargin +\newdimen\itemmax + +% Note @table, @ftable, and @vtable define @item, @itemx, etc., with +% these defs. +% They also define \itemindex +% to index the item name in whatever manner is desired (perhaps none). + +\newif\ifitemxneedsnegativevskip + +\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} + +\def\internalBitem{\smallbreak \parsearg\itemzzz} +\def\internalBitemx{\itemxpar \parsearg\itemzzz} + +\def\itemzzz #1{\begingroup % + \advance\hsize by -\rightskip + \advance\hsize by -\tableindent + \setbox0=\hbox{\itemindicate{#1}}% + \itemindex{#1}% + \nobreak % This prevents a break before @itemx. + % + % If the item text does not fit in the space we have, put it on a line + % by itself, and do not allow a page break either before or after that + % line. We do not start a paragraph here because then if the next + % command is, e.g., @kindex, the whatsit would get put into the + % horizontal list on a line by itself, resulting in extra blank space. + \ifdim \wd0>\itemmax + % + % Make this a paragraph so we get the \parskip glue and wrapping, + % but leave it ragged-right. + \begingroup + \advance\leftskip by-\tableindent + \advance\hsize by\tableindent + \advance\rightskip by0pt plus1fil + \leavevmode\unhbox0\par + \endgroup + % + % We're going to be starting a paragraph, but we don't want the + % \parskip glue -- logically it's part of the @item we just started. + \nobreak \vskip-\parskip + % + % Stop a page break at the \parskip glue coming up. However, if + % what follows is an environment such as @example, there will be no + % \parskip glue; then the negative vskip we just inserted would + % cause the example and the item to crash together. So we use this + % bizarre value of 10001 as a signal to \aboveenvbreak to insert + % \parskip glue after all. Section titles are handled this way also. + % + \penalty 10001 + \endgroup + \itemxneedsnegativevskipfalse + \else + % The item text fits into the space. Start a paragraph, so that the + % following text (if any) will end up on the same line. + \noindent + % Do this with kerns and \unhbox so that if there is a footnote in + % the item text, it can migrate to the main vertical list and + % eventually be printed. + \nobreak\kern-\tableindent + \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 + \unhbox0 + \nobreak\kern\dimen0 + \endgroup + \itemxneedsnegativevskiptrue + \fi +} + +\def\item{\errmessage{@item while not in a list environment}} +\def\itemx{\errmessage{@itemx while not in a list environment}} + +% @table, @ftable, @vtable. +\envdef\table{% + \let\itemindex\gobble + \tablecheck{table}% +} +\envdef\ftable{% + \def\itemindex ##1{\doind {fn}{\code{##1}}}% + \tablecheck{ftable}% +} +\envdef\vtable{% + \def\itemindex ##1{\doind {vr}{\code{##1}}}% + \tablecheck{vtable}% +} +\def\tablecheck#1{% + \ifnum \the\catcode`\^^M=\active + \endgroup + \errmessage{This command won't work in this context; perhaps the problem is + that we are \inenvironment\thisenv}% + \def\next{\doignore{#1}}% + \else + \let\next\tablex + \fi + \next +} +\def\tablex#1{% + \def\itemindicate{#1}% + \parsearg\tabley +} +\def\tabley#1{% + {% + \makevalueexpandable + \edef\temp{\noexpand\tablez #1\space\space\space}% + \expandafter + }\temp \endtablez +} +\def\tablez #1 #2 #3 #4\endtablez{% + \aboveenvbreak + \ifnum 0#1>0 \advance \leftskip by #1\mil \fi + \ifnum 0#2>0 \tableindent=#2\mil \fi + \ifnum 0#3>0 \advance \rightskip by #3\mil \fi + \itemmax=\tableindent + \advance \itemmax by -\itemmargin + \advance \leftskip by \tableindent + \exdentamount=\tableindent + \parindent = 0pt + \parskip = \smallskipamount + \ifdim \parskip=0pt \parskip=2pt \fi + \let\item = \internalBitem + \let\itemx = \internalBitemx +} +\def\Etable{\endgraf\afterenvbreak} +\let\Eftable\Etable +\let\Evtable\Etable +\let\Eitemize\Etable +\let\Eenumerate\Etable + +% This is the counter used by @enumerate, which is really @itemize + +\newcount \itemno + +\envdef\itemize{\parsearg\doitemize} + +\def\doitemize#1{% + \aboveenvbreak + \itemmax=\itemindent + \advance\itemmax by -\itemmargin + \advance\leftskip by \itemindent + \exdentamount=\itemindent + \parindent=0pt + \parskip=\smallskipamount + \ifdim\parskip=0pt \parskip=2pt \fi + \def\itemcontents{#1}% + % @itemize with no arg is equivalent to @itemize @bullet. + \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi + \let\item=\itemizeitem +} + +% Definition of @item while inside @itemize and @enumerate. +% +\def\itemizeitem{% + \advance\itemno by 1 % for enumerations + {\let\par=\endgraf \smallbreak}% reasonable place to break + {% + % If the document has an @itemize directly after a section title, a + % \nobreak will be last on the list, and \sectionheading will have + % done a \vskip-\parskip. In that case, we don't want to zero + % parskip, or the item text will crash with the heading. On the + % other hand, when there is normal text preceding the item (as there + % usually is), we do want to zero parskip, or there would be too much + % space. In that case, we won't have a \nobreak before. At least + % that's the theory. + \ifnum\lastpenalty<10000 \parskip=0in \fi + \noindent + \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% + \vadjust{\penalty 1200}}% not good to break after first line of item. + \flushcr +} + +% \splitoff TOKENS\endmark defines \first to be the first token in +% TOKENS, and \rest to be the remainder. +% +\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% + +% Allow an optional argument of an uppercase letter, lowercase letter, +% or number, to specify the first label in the enumerated list. No +% argument is the same as `1'. +% +\envparseargdef\enumerate{\enumeratey #1 \endenumeratey} +\def\enumeratey #1 #2\endenumeratey{% + % If we were given no argument, pretend we were given `1'. + \def\thearg{#1}% + \ifx\thearg\empty \def\thearg{1}\fi + % + % Detect if the argument is a single token. If so, it might be a + % letter. Otherwise, the only valid thing it can be is a number. + % (We will always have one token, because of the test we just made. + % This is a good thing, since \splitoff doesn't work given nothing at + % all -- the first parameter is undelimited.) + \expandafter\splitoff\thearg\endmark + \ifx\rest\empty + % Only one token in the argument. It could still be anything. + % A ``lowercase letter'' is one whose \lccode is nonzero. + % An ``uppercase letter'' is one whose \lccode is both nonzero, and + % not equal to itself. + % Otherwise, we assume it's a number. + % + % We need the \relax at the end of the \ifnum lines to stop TeX from + % continuing to look for a <number>. + % + \ifnum\lccode\expandafter`\thearg=0\relax + \numericenumerate % a number (we hope) + \else + % It's a letter. + \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax + \lowercaseenumerate % lowercase letter + \else + \uppercaseenumerate % uppercase letter + \fi + \fi + \else + % Multiple tokens in the argument. We hope it's a number. + \numericenumerate + \fi +} + +% An @enumerate whose labels are integers. The starting integer is +% given in \thearg. +% +\def\numericenumerate{% + \itemno = \thearg + \startenumeration{\the\itemno}% +} + +% The starting (lowercase) letter is in \thearg. +\def\lowercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more lowercase letters in @enumerate; get a bigger + alphabet}% + \fi + \char\lccode\itemno + }% +} + +% The starting (uppercase) letter is in \thearg. +\def\uppercaseenumerate{% + \itemno = \expandafter`\thearg + \startenumeration{% + % Be sure we're not beyond the end of the alphabet. + \ifnum\itemno=0 + \errmessage{No more uppercase letters in @enumerate; get a bigger + alphabet} + \fi + \char\uccode\itemno + }% +} + +% Call \doitemize, adding a period to the first argument and supplying the +% common last two arguments. Also subtract one from the initial value in +% \itemno, since @item increments \itemno. +% +\def\startenumeration#1{% + \advance\itemno by -1 + \doitemize{#1.}\flushcr +} + +% @alphaenumerate and @capsenumerate are abbreviations for giving an arg +% to @enumerate. +% +\def\alphaenumerate{\enumerate{a}} +\def\capsenumerate{\enumerate{A}} +\def\Ealphaenumerate{\Eenumerate} +\def\Ecapsenumerate{\Eenumerate} + + +% @multitable macros +% Amy Hendrickson, 8/18/94, 3/6/96 +% +% @multitable ... @end multitable will make as many columns as desired. +% Contents of each column will wrap at width given in preamble. Width +% can be specified either with sample text given in a template line, +% or in percent of \hsize, the current width of text on page. + +% Table can continue over pages but will only break between lines. + +% To make preamble: +% +% Either define widths of columns in terms of percent of \hsize: +% @multitable @columnfractions .25 .3 .45 +% @item ... +% +% Numbers following @columnfractions are the percent of the total +% current hsize to be used for each column. You may use as many +% columns as desired. + + +% Or use a template: +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item ... +% using the widest term desired in each column. + +% Each new table line starts with @item, each subsequent new column +% starts with @tab. Empty columns may be produced by supplying @tab's +% with nothing between them for as many times as empty columns are needed, +% ie, @tab@tab@tab will produce two empty columns. + +% @item, @tab do not need to be on their own lines, but it will not hurt +% if they are. + +% Sample multitable: + +% @multitable {Column 1 template} {Column 2 template} {Column 3 template} +% @item first col stuff @tab second col stuff @tab third col +% @item +% first col stuff +% @tab +% second col stuff +% @tab +% third col +% @item first col stuff @tab second col stuff +% @tab Many paragraphs of text may be used in any column. +% +% They will wrap at the width determined by the template. +% @item@tab@tab This will be in third column. +% @end multitable + +% Default dimensions may be reset by user. +% @multitableparskip is vertical space between paragraphs in table. +% @multitableparindent is paragraph indent in table. +% @multitablecolmargin is horizontal space to be left between columns. +% @multitablelinespace is space to leave between table items, baseline +% to baseline. +% 0pt means it depends on current normal line spacing. +% +\newskip\multitableparskip +\newskip\multitableparindent +\newdimen\multitablecolspace +\newskip\multitablelinespace +\multitableparskip=0pt +\multitableparindent=6pt +\multitablecolspace=12pt +\multitablelinespace=0pt + +% Macros used to set up halign preamble: +% +\let\endsetuptable\relax +\def\xendsetuptable{\endsetuptable} +\let\columnfractions\relax +\def\xcolumnfractions{\columnfractions} +\newif\ifsetpercent + +% #1 is the @columnfraction, usually a decimal number like .5, but might +% be just 1. We just use it, whatever it is. +% +\def\pickupwholefraction#1 {% + \global\advance\colcount by 1 + \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% + \setuptable +} + +\newcount\colcount +\def\setuptable#1{% + \def\firstarg{#1}% + \ifx\firstarg\xendsetuptable + \let\go = \relax + \else + \ifx\firstarg\xcolumnfractions + \global\setpercenttrue + \else + \ifsetpercent + \let\go\pickupwholefraction + \else + \global\advance\colcount by 1 + \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a + % separator; typically that is always in the input, anyway. + \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% + \fi + \fi + \ifx\go\pickupwholefraction + % Put the argument back for the \pickupwholefraction call, so + % we'll always have a period there to be parsed. + \def\go{\pickupwholefraction#1}% + \else + \let\go = \setuptable + \fi% + \fi + \go +} + +% multitable-only commands. +% +% @headitem starts a heading row, which we typeset in bold. +% Assignments have to be global since we are inside the implicit group +% of an alignment entry. Note that \everycr resets \everytab. +\def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}% +% +% A \tab used to include \hskip1sp. But then the space in a template +% line is not enough. That is bad. So let's go back to just `&' until +% we encounter the problem it was intended to solve again. +% --karl, nathan@acm.org, 20apr99. +\def\tab{\checkenv\multitable &\the\everytab}% + +% @multitable ... @end multitable definitions: +% +\newtoks\everytab % insert after every tab. +% +\envdef\multitable{% + \vskip\parskip + \startsavinginserts + % + % @item within a multitable starts a normal row. + % We use \def instead of \let so that if one of the multitable entries + % contains an @itemize, we don't choke on the \item (seen as \crcr aka + % \endtemplate) expanding \doitemize. + \def\item{\crcr}% + % + \tolerance=9500 + \hbadness=9500 + \setmultitablespacing + \parskip=\multitableparskip + \parindent=\multitableparindent + \overfullrule=0pt + \global\colcount=0 + % + \everycr = {% + \noalign{% + \global\everytab={}% + \global\colcount=0 % Reset the column counter. + % Check for saved footnotes, etc. + \checkinserts + % Keeps underfull box messages off when table breaks over pages. + %\filbreak + % Maybe so, but it also creates really weird page breaks when the + % table breaks over pages. Wouldn't \vfil be better? Wait until the + % problem manifests itself, so it can be fixed for real --karl. + }% + }% + % + \parsearg\domultitable +} +\def\domultitable#1{% + % To parse everything between @multitable and @item: + \setuptable#1 \endsetuptable + % + % This preamble sets up a generic column definition, which will + % be used as many times as user calls for columns. + % \vtop will set a single line and will also let text wrap and + % continue for many paragraphs if desired. + \halign\bgroup &% + \global\advance\colcount by 1 + \multistrut + \vtop{% + % Use the current \colcount to find the correct column width: + \hsize=\expandafter\csname col\the\colcount\endcsname + % + % In order to keep entries from bumping into each other + % we will add a \leftskip of \multitablecolspace to all columns after + % the first one. + % + % If a template has been used, we will add \multitablecolspace + % to the width of each template entry. + % + % If the user has set preamble in terms of percent of \hsize we will + % use that dimension as the width of the column, and the \leftskip + % will keep entries from bumping into each other. Table will start at + % left margin and final column will justify at right margin. + % + % Make sure we don't inherit \rightskip from the outer environment. + \rightskip=0pt + \ifnum\colcount=1 + % The first column will be indented with the surrounding text. + \advance\hsize by\leftskip + \else + \ifsetpercent \else + % If user has not set preamble in terms of percent of \hsize + % we will advance \hsize by \multitablecolspace. + \advance\hsize by \multitablecolspace + \fi + % In either case we will make \leftskip=\multitablecolspace: + \leftskip=\multitablecolspace + \fi + % Ignoring space at the beginning and end avoids an occasional spurious + % blank line, when TeX decides to break the line at the space before the + % box from the multistrut, so the strut ends up on a line by itself. + % For example: + % @multitable @columnfractions .11 .89 + % @item @code{#} + % @tab Legal holiday which is valid in major parts of the whole country. + % Is automatically provided with highlighting sequences respectively + % marking characters. + \noindent\ignorespaces##\unskip\multistrut + }\cr +} +\def\Emultitable{% + \crcr + \egroup % end the \halign + \global\setpercentfalse +} + +\def\setmultitablespacing{% + \def\multistrut{\strut}% just use the standard line spacing + % + % Compute \multitablelinespace (if not defined by user) for use in + % \multitableparskip calculation. We used define \multistrut based on + % this, but (ironically) that caused the spacing to be off. + % See bug-texinfo report from Werner Lemberg, 31 Oct 2004 12:52:20 +0100. +\ifdim\multitablelinespace=0pt +\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip +\global\advance\multitablelinespace by-\ht0 +\fi +%% Test to see if parskip is larger than space between lines of +%% table. If not, do nothing. +%% If so, set to same dimension as multitablelinespace. +\ifdim\multitableparskip>\multitablelinespace +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi% +\ifdim\multitableparskip=0pt +\global\multitableparskip=\multitablelinespace +\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller + %% than skip between lines in the table. +\fi} + + +\message{conditionals,} + +% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, +% @ifnotxml always succeed. They currently do nothing; we don't +% attempt to check whether the conditionals are properly nested. But we +% have to remember that they are conditionals, so that @end doesn't +% attempt to close an environment group. +% +\def\makecond#1{% + \expandafter\let\csname #1\endcsname = \relax + \expandafter\let\csname iscond.#1\endcsname = 1 +} +\makecond{iftex} +\makecond{ifnotdocbook} +\makecond{ifnothtml} +\makecond{ifnotinfo} +\makecond{ifnotplaintext} +\makecond{ifnotxml} + +% Ignore @ignore, @ifhtml, @ifinfo, and the like. +% +\def\direntry{\doignore{direntry}} +\def\documentdescription{\doignore{documentdescription}} +\def\docbook{\doignore{docbook}} +\def\html{\doignore{html}} +\def\ifdocbook{\doignore{ifdocbook}} +\def\ifhtml{\doignore{ifhtml}} +\def\ifinfo{\doignore{ifinfo}} +\def\ifnottex{\doignore{ifnottex}} +\def\ifplaintext{\doignore{ifplaintext}} +\def\ifxml{\doignore{ifxml}} +\def\ignore{\doignore{ignore}} +\def\menu{\doignore{menu}} +\def\xml{\doignore{xml}} + +% Ignore text until a line `@end #1', keeping track of nested conditionals. +% +% A count to remember the depth of nesting. +\newcount\doignorecount + +\def\doignore#1{\begingroup + % Scan in ``verbatim'' mode: + \obeylines + \catcode`\@ = \other + \catcode`\{ = \other + \catcode`\} = \other + % + % Make sure that spaces turn into tokens that match what \doignoretext wants. + \spaceisspace + % + % Count number of #1's that we've seen. + \doignorecount = 0 + % + % Swallow text until we reach the matching `@end #1'. + \dodoignore{#1}% +} + +{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. + \obeylines % + % + \gdef\dodoignore#1{% + % #1 contains the command name as a string, e.g., `ifinfo'. + % + % Define a command to find the next `@end #1'. + \long\def\doignoretext##1^^M@end #1{% + \doignoretextyyy##1^^M@#1\_STOP_}% + % + % And this command to find another #1 command, at the beginning of a + % line. (Otherwise, we would consider a line `@c @ifset', for + % example, to count as an @ifset for nesting.) + \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% + % + % And now expand that command. + \doignoretext ^^M% + }% +} + +\def\doignoreyyy#1{% + \def\temp{#1}% + \ifx\temp\empty % Nothing found. + \let\next\doignoretextzzz + \else % Found a nested condition, ... + \advance\doignorecount by 1 + \let\next\doignoretextyyy % ..., look for another. + % If we're here, #1 ends with ^^M\ifinfo (for example). + \fi + \next #1% the token \_STOP_ is present just after this macro. +} + +% We have to swallow the remaining "\_STOP_". +% +\def\doignoretextzzz#1{% + \ifnum\doignorecount = 0 % We have just found the outermost @end. + \let\next\enddoignore + \else % Still inside a nested condition. + \advance\doignorecount by -1 + \let\next\doignoretext % Look for the next @end. + \fi + \next +} + +% Finish off ignored text. +{ \obeylines% + % Ignore anything after the last `@end #1'; this matters in verbatim + % environments, where otherwise the newline after an ignored conditional + % would result in a blank line in the output. + \gdef\enddoignore#1^^M{\endgroup\ignorespaces}% +} + + +% @set VAR sets the variable VAR to an empty value. +% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. +% +% Since we want to separate VAR from REST-OF-LINE (which might be +% empty), we can't just use \parsearg; we have to insert a space of our +% own to delimit the rest of the line, and then take it out again if we +% didn't need it. +% We rely on the fact that \parsearg sets \catcode`\ =10. +% +\parseargdef\set{\setyyy#1 \endsetyyy} +\def\setyyy#1 #2\endsetyyy{% + {% + \makevalueexpandable + \def\temp{#2}% + \edef\next{\gdef\makecsname{SET#1}}% + \ifx\temp\empty + \next{}% + \else + \setzzz#2\endsetzzz + \fi + }% +} +% Remove the trailing space \setxxx inserted. +\def\setzzz#1 \endsetzzz{\next{#1}} + +% @clear VAR clears (i.e., unsets) the variable VAR. +% +\parseargdef\clear{% + {% + \makevalueexpandable + \global\expandafter\let\csname SET#1\endcsname=\relax + }% +} + +% @value{foo} gets the text saved in variable foo. +\def\value{\begingroup\makevalueexpandable\valuexxx} +\def\valuexxx#1{\expandablevalue{#1}\endgroup} +{ + \catcode`\- = \active \catcode`\_ = \active + % + \gdef\makevalueexpandable{% + \let\value = \expandablevalue + % We don't want these characters active, ... + \catcode`\-=\other \catcode`\_=\other + % ..., but we might end up with active ones in the argument if + % we're called from @code, as @code{@value{foo-bar_}}, though. + % So \let them to their normal equivalents. + \let-\realdash \let_\normalunderscore + } +} + +% We have this subroutine so that we can handle at least some @value's +% properly in indexes (we call \makevalueexpandable in \indexdummies). +% The command has to be fully expandable (if the variable is set), since +% the result winds up in the index file. This means that if the +% variable's value contains other Texinfo commands, it's almost certain +% it will fail (although perhaps we could fix that with sufficient work +% to do a one-level expansion on the result, instead of complete). +% +\def\expandablevalue#1{% + \expandafter\ifx\csname SET#1\endcsname\relax + {[No value for ``#1'']}% + \message{Variable `#1', used in @value, is not set.}% + \else + \csname SET#1\endcsname + \fi +} + +% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined +% with @set. +% +% To get special treatment of `@end ifset,' call \makeond and the redefine. +% +\makecond{ifset} +\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} +\def\doifset#1#2{% + {% + \makevalueexpandable + \let\next=\empty + \expandafter\ifx\csname SET#2\endcsname\relax + #1% If not set, redefine \next. + \fi + \expandafter + }\next +} +\def\ifsetfail{\doignore{ifset}} + +% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been +% defined with @set, or has been undefined with @clear. +% +% The `\else' inside the `\doifset' parameter is a trick to reuse the +% above code: if the variable is not set, do nothing, if it is set, +% then redefine \next to \ifclearfail. +% +\makecond{ifclear} +\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} +\def\ifclearfail{\doignore{ifclear}} + +% @dircategory CATEGORY -- specify a category of the dir file +% which this file should belong to. Ignore this in TeX. +\let\dircategory=\comment + +% @defininfoenclose. +\let\definfoenclose=\comment + + +\message{indexing,} +% Index generation facilities + +% Define \newwrite to be identical to plain tex's \newwrite +% except not \outer, so it can be used within macros and \if's. +\edef\newwrite{\makecsname{ptexnewwrite}} + +% \newindex {foo} defines an index named foo. +% It automatically defines \fooindex such that +% \fooindex ...rest of line... puts an entry in the index foo. +% It also defines \fooindfile to be the number of the output channel for +% the file that accumulates this index. The file's extension is foo. +% The name of an index should be no more than 2 characters long +% for the sake of vms. +% +\def\newindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 % Open the file + \fi + \expandafter\xdef\csname#1index\endcsname{% % Define @#1index + \noexpand\doindex{#1}} +} + +% @defindex foo == \newindex{foo} +% +\def\defindex{\parsearg\newindex} + +% Define @defcodeindex, like @defindex except put all entries in @code. +% +\def\defcodeindex{\parsearg\newcodeindex} +% +\def\newcodeindex#1{% + \iflinks + \expandafter\newwrite \csname#1indfile\endcsname + \openout \csname#1indfile\endcsname \jobname.#1 + \fi + \expandafter\xdef\csname#1index\endcsname{% + \noexpand\docodeindex{#1}}% +} + + +% @synindex foo bar makes index foo feed into index bar. +% Do this instead of @defindex foo if you don't want it as a separate index. +% +% @syncodeindex foo bar similar, but put all entries made for index foo +% inside @code. +% +\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} +\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} + +% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), +% #3 the target index (bar). +\def\dosynindex#1#2#3{% + % Only do \closeout if we haven't already done it, else we'll end up + % closing the target index. + \expandafter \ifx\csname donesynindex#2\endcsname \undefined + % The \closeout helps reduce unnecessary open files; the limit on the + % Acorn RISC OS is a mere 16 files. + \expandafter\closeout\csname#2indfile\endcsname + \expandafter\let\csname\donesynindex#2\endcsname = 1 + \fi + % redefine \fooindfile: + \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname + \expandafter\let\csname#2indfile\endcsname=\temp + % redefine \fooindex: + \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% +} + +% Define \doindex, the driver for all \fooindex macros. +% Argument #1 is generated by the calling \fooindex macro, +% and it is "foo", the name of the index. + +% \doindex just uses \parsearg; it calls \doind for the actual work. +% This is because \doind is more useful to call from other macros. + +% There is also \dosubind {index}{topic}{subtopic} +% which makes an entry in a two-level index such as the operation index. + +\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} +\def\singleindexer #1{\doind{\indexname}{#1}} + +% like the previous two, but they put @code around the argument. +\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} +\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} + +% Take care of Texinfo commands that can appear in an index entry. +% Since there are some commands we want to expand, and others we don't, +% we have to laboriously prevent expansion for those that we don't. +% +\def\indexdummies{% + \escapechar = `\\ % use backslash in output files. + \def\@{@}% change to @@ when we switch to @ as escape char in index files. + \def\ {\realbackslash\space }% + % Need these in case \tex is in effect and \{ is a \delimiter again. + % But can't use \lbracecmd and \rbracecmd because texindex assumes + % braces and backslashes are used only as delimiters. + \let\{ = \mylbrace + \let\} = \myrbrace + % + % Do the redefinitions. + \commondummies +} + +% For the aux and toc files, @ is the escape character. So we want to +% redefine everything using @ as the escape character (instead of +% \realbackslash, still used for index files). When everything uses @, +% this will be simpler. +% +\def\atdummies{% + \def\@{@@}% + \def\ {@ }% + \let\{ = \lbraceatcmd + \let\} = \rbraceatcmd + % + % Do the redefinitions. + \commondummies + \otherbackslash +} + +% Called from \indexdummies and \atdummies. +% +\def\commondummies{% + % + % \definedummyword defines \#1 as \string\#1\space, thus effectively + % preventing its expansion. This is used only for control% words, + % not control letters, because the \space would be incorrect for + % control characters, but is needed to separate the control word + % from whatever follows. + % + % For control letters, we have \definedummyletter, which omits the + % space. + % + % These can be used both for control words that take an argument and + % those that do not. If it is followed by {arg} in the input, then + % that will dutifully get written to the index (or wherever). + % + \def\definedummyword ##1{\def##1{\string##1\space}}% + \def\definedummyletter##1{\def##1{\string##1}}% + \let\definedummyaccent\definedummyletter + % + \commondummiesnofonts + % + \definedummyletter\_% + % + % Non-English letters. + \definedummyword\AA + \definedummyword\AE + \definedummyword\L + \definedummyword\OE + \definedummyword\O + \definedummyword\aa + \definedummyword\ae + \definedummyword\l + \definedummyword\oe + \definedummyword\o + \definedummyword\ss + \definedummyword\exclamdown + \definedummyword\questiondown + \definedummyword\ordf + \definedummyword\ordm + % + % Although these internal commands shouldn't show up, sometimes they do. + \definedummyword\bf + \definedummyword\gtr + \definedummyword\hat + \definedummyword\less + \definedummyword\sf + \definedummyword\sl + \definedummyword\tclose + \definedummyword\tt + % + \definedummyword\LaTeX + \definedummyword\TeX + % + % Assorted special characters. + \definedummyword\bullet + \definedummyword\comma + \definedummyword\copyright + \definedummyword\registeredsymbol + \definedummyword\dots + \definedummyword\enddots + \definedummyword\equiv + \definedummyword\error + \definedummyword\euro + \definedummyword\expansion + \definedummyword\minus + \definedummyword\pounds + \definedummyword\point + \definedummyword\print + \definedummyword\result + % + % We want to disable all macros so that they are not expanded by \write. + \macrolist + % + \normalturnoffactive + % + % Handle some cases of @value -- where it does not contain any + % (non-fully-expandable) commands. + \makevalueexpandable +} + +% \commondummiesnofonts: common to \commondummies and \indexnofonts. +% +\def\commondummiesnofonts{% + % Control letters and accents. + \definedummyletter\!% + \definedummyaccent\"% + \definedummyaccent\'% + \definedummyletter\*% + \definedummyaccent\,% + \definedummyletter\.% + \definedummyletter\/% + \definedummyletter\:% + \definedummyaccent\=% + \definedummyletter\?% + \definedummyaccent\^% + \definedummyaccent\`% + \definedummyaccent\~% + \definedummyword\u + \definedummyword\v + \definedummyword\H + \definedummyword\dotaccent + \definedummyword\ringaccent + \definedummyword\tieaccent + \definedummyword\ubaraccent + \definedummyword\udotaccent + \definedummyword\dotless + % + % Texinfo font commands. + \definedummyword\b + \definedummyword\i + \definedummyword\r + \definedummyword\sc + \definedummyword\t + % + % Commands that take arguments. + \definedummyword\acronym + \definedummyword\cite + \definedummyword\code + \definedummyword\command + \definedummyword\dfn + \definedummyword\emph + \definedummyword\env + \definedummyword\file + \definedummyword\kbd + \definedummyword\key + \definedummyword\math + \definedummyword\option + \definedummyword\pxref + \definedummyword\ref + \definedummyword\samp + \definedummyword\strong + \definedummyword\tie + \definedummyword\uref + \definedummyword\url + \definedummyword\var + \definedummyword\verb + \definedummyword\w + \definedummyword\xref +} + +% \indexnofonts is used when outputting the strings to sort the index +% by, and when constructing control sequence names. It eliminates all +% control sequences and just writes whatever the best ASCII sort string +% would be for a given command (usually its argument). +% +\def\indexnofonts{% + % Accent commands should become @asis. + \def\definedummyaccent##1{\let##1\asis}% + % We can just ignore other control letters. + \def\definedummyletter##1{\let##1\empty}% + % Hopefully, all control words can become @asis. + \let\definedummyword\definedummyaccent + % + \commondummiesnofonts + % + % Don't no-op \tt, since it isn't a user-level command + % and is used in the definitions of the active chars like <, >, |, etc. + % Likewise with the other plain tex font commands. + %\let\tt=\asis + % + \def\ { }% + \def\@{@}% + % how to handle braces? + \def\_{\normalunderscore}% + % + % Non-English letters. + \def\AA{AA}% + \def\AE{AE}% + \def\L{L}% + \def\OE{OE}% + \def\O{O}% + \def\aa{aa}% + \def\ae{ae}% + \def\l{l}% + \def\oe{oe}% + \def\o{o}% + \def\ss{ss}% + \def\exclamdown{!}% + \def\questiondown{?}% + \def\ordf{a}% + \def\ordm{o}% + % + \def\LaTeX{LaTeX}% + \def\TeX{TeX}% + % + % Assorted special characters. + % (The following {} will end up in the sort string, but that's ok.) + \def\bullet{bullet}% + \def\comma{,}% + \def\copyright{copyright}% + \def\registeredsymbol{R}% + \def\dots{...}% + \def\enddots{...}% + \def\equiv{==}% + \def\error{error}% + \def\euro{euro}% + \def\expansion{==>}% + \def\minus{-}% + \def\pounds{pounds}% + \def\point{.}% + \def\print{-|}% + \def\result{=>}% + % + % We need to get rid of all macros, leaving only the arguments (if present). + % Of course this is not nearly correct, but it is the best we can do for now. + % makeinfo does not expand macros in the argument to @deffn, which ends up + % writing an index entry, and texindex isn't prepared for an index sort entry + % that starts with \. + % + % Since macro invocations are followed by braces, we can just redefine them + % to take a single TeX argument. The case of a macro invocation that + % goes to end-of-line is not handled. + % + \macrolist +} + +\let\indexbackslash=0 %overridden during \printindex. +\let\SETmarginindex=\relax % put index entries in margin (undocumented)? + +% Most index entries go through here, but \dosubind is the general case. +% #1 is the index name, #2 is the entry text. +\def\doind#1#2{\dosubind{#1}{#2}{}} + +% Workhorse for all \fooindexes. +% #1 is name of index, #2 is stuff to put there, #3 is subentry -- +% empty if called from \doind, as we usually are (the main exception +% is with most defuns, which call us directly). +% +\def\dosubind#1#2#3{% + \iflinks + {% + % Store the main index entry text (including the third arg). + \toks0 = {#2}% + % If third arg is present, precede it with a space. + \def\thirdarg{#3}% + \ifx\thirdarg\empty \else + \toks0 = \expandafter{\the\toks0 \space #3}% + \fi + % + \edef\writeto{\csname#1indfile\endcsname}% + % + \ifvmode + \dosubindsanitize + \else + \dosubindwrite + \fi + }% + \fi +} + +% Write the entry in \toks0 to the index file: +% +\def\dosubindwrite{% + % Put the index entry in the margin if desired. + \ifx\SETmarginindex\relax\else + \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% + \fi + % + % Remember, we are within a group. + \indexdummies % Must do this here, since \bf, etc expand at this stage + \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now + % so it will be output as is; and it will print as backslash. + % + % Process the index entry with all font commands turned off, to + % get the string to sort by. + {\indexnofonts + \edef\temp{\the\toks0}% need full expansion + \xdef\indexsorttmp{\temp}% + }% + % + % Set up the complete index entry, with both the sort key and + % the original text, including any font commands. We write + % three arguments to \entry to the .?? file (four in the + % subentry case), texindex reduces to two when writing the .??s + % sorted result. + \edef\temp{% + \write\writeto{% + \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% + }% + \temp +} + +% Take care of unwanted page breaks: +% +% If a skip is the last thing on the list now, preserve it +% by backing up by \lastskip, doing the \write, then inserting +% the skip again. Otherwise, the whatsit generated by the +% \write will make \lastskip zero. The result is that sequences +% like this: +% @end defun +% @tindex whatever +% @defun ... +% will have extra space inserted, because the \medbreak in the +% start of the @defun won't see the skip inserted by the @end of +% the previous defun. +% +% But don't do any of this if we're not in vertical mode. We +% don't want to do a \vskip and prematurely end a paragraph. +% +% Avoid page breaks due to these extra skips, too. +% +% But wait, there is a catch there: +% We'll have to check whether \lastskip is zero skip. \ifdim is not +% sufficient for this purpose, as it ignores stretch and shrink parts +% of the skip. The only way seems to be to check the textual +% representation of the skip. +% +% The following is almost like \def\zeroskipmacro{0.0pt} except that +% the ``p'' and ``t'' characters have catcode \other, not 11 (letter). +% +\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} +% +% ..., ready, GO: +% +\def\dosubindsanitize{% + % \lastskip and \lastpenalty cannot both be nonzero simultaneously. + \skip0 = \lastskip + \edef\lastskipmacro{\the\lastskip}% + \count255 = \lastpenalty + % + % If \lastskip is nonzero, that means the last item was a + % skip. And since a skip is discardable, that means this + % -\skip0 glue we're inserting is preceded by a + % non-discardable item, therefore it is not a potential + % breakpoint, therefore no \nobreak needed. + \ifx\lastskipmacro\zeroskipmacro + \else + \vskip-\skip0 + \fi + % + \dosubindwrite + % + \ifx\lastskipmacro\zeroskipmacro + % If \lastskip was zero, perhaps the last item was a penalty, and + % perhaps it was >=10000, e.g., a \nobreak. In that case, we want + % to re-insert the same penalty (values >10000 are used for various + % signals); since we just inserted a non-discardable item, any + % following glue (such as a \parskip) would be a breakpoint. For example: + % + % @deffn deffn-whatever + % @vindex index-whatever + % Description. + % would allow a break between the index-whatever whatsit + % and the "Description." paragraph. + \ifnum\count255>9999 \penalty\count255 \fi + \else + % On the other hand, if we had a nonzero \lastskip, + % this make-up glue would be preceded by a non-discardable item + % (the whatsit from the \write), so we must insert a \nobreak. + \nobreak\vskip\skip0 + \fi +} + +% The index entry written in the file actually looks like +% \entry {sortstring}{page}{topic} +% or +% \entry {sortstring}{page}{topic}{subtopic} +% The texindex program reads in these files and writes files +% containing these kinds of lines: +% \initial {c} +% before the first topic whose initial is c +% \entry {topic}{pagelist} +% for a topic that is used without subtopics +% \primary {topic} +% for the beginning of a topic that is used with subtopics +% \secondary {subtopic}{pagelist} +% for each subtopic. + +% Define the user-accessible indexing commands +% @findex, @vindex, @kindex, @cindex. + +\def\findex {\fnindex} +\def\kindex {\kyindex} +\def\cindex {\cpindex} +\def\vindex {\vrindex} +\def\tindex {\tpindex} +\def\pindex {\pgindex} + +\def\cindexsub {\begingroup\obeylines\cindexsub} +{\obeylines % +\gdef\cindexsub "#1" #2^^M{\endgroup % +\dosubind{cp}{#2}{#1}}} + +% Define the macros used in formatting output of the sorted index material. + +% @printindex causes a particular index (the ??s file) to get printed. +% It does not print any chapter heading (usually an @unnumbered). +% +\parseargdef\printindex{\begingroup + \dobreak \chapheadingskip{10000}% + % + \smallfonts \rm + \tolerance = 9500 + \everypar = {}% don't want the \kern\-parindent from indentation suppression. + % + % See if the index file exists and is nonempty. + % Change catcode of @ here so that if the index file contains + % \initial {@} + % as its first line, TeX doesn't complain about mismatched braces + % (because it thinks @} is a control sequence). + \catcode`\@ = 11 + \openin 1 \jobname.#1s + \ifeof 1 + % \enddoublecolumns gets confused if there is no text in the index, + % and it loses the chapter title and the aux file entries for the + % index. The easiest way to prevent this problem is to make sure + % there is some text. + \putwordIndexNonexistent + \else + % + % If the index file exists but is empty, then \openin leaves \ifeof + % false. We have to make TeX try to read something from the file, so + % it can discover if there is anything in it. + \read 1 to \temp + \ifeof 1 + \putwordIndexIsEmpty + \else + % Index files are almost Texinfo source, but we use \ as the escape + % character. It would be better to use @, but that's too big a change + % to make right now. + \def\indexbackslash{\backslashcurfont}% + \catcode`\\ = 0 + \escapechar = `\\ + \begindoublecolumns + \input \jobname.#1s + \enddoublecolumns + \fi + \fi + \closein 1 +\endgroup} + +% These macros are used by the sorted index file itself. +% Change them to control the appearance of the index. + +\def\initial#1{{% + % Some minor font changes for the special characters. + \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt + % + % Remove any glue we may have, we'll be inserting our own. + \removelastskip + % + % We like breaks before the index initials, so insert a bonus. + \nobreak + \vskip 0pt plus 3\baselineskip + \penalty 0 + \vskip 0pt plus -3\baselineskip + % + % Typeset the initial. Making this add up to a whole number of + % baselineskips increases the chance of the dots lining up from column + % to column. It still won't often be perfect, because of the stretch + % we need before each entry, but it's better. + % + % No shrink because it confuses \balancecolumns. + \vskip 1.67\baselineskip plus .5\baselineskip + \leftline{\secbf #1}% + % Do our best not to break after the initial. + \nobreak + \vskip .33\baselineskip plus .1\baselineskip +}} + +% \entry typesets a paragraph consisting of the text (#1), dot leaders, and +% then page number (#2) flushed to the right margin. It is used for index +% and table of contents entries. The paragraph is indented by \leftskip. +% +% A straightforward implementation would start like this: +% \def\entry#1#2{... +% But this frozes the catcodes in the argument, and can cause problems to +% @code, which sets - active. This problem was fixed by a kludge--- +% ``-'' was active throughout whole index, but this isn't really right. +% +% The right solution is to prevent \entry from swallowing the whole text. +% --kasal, 21nov03 +\def\entry{% + \begingroup + % + % Start a new paragraph if necessary, so our assignments below can't + % affect previous text. + \par + % + % Do not fill out the last line with white space. + \parfillskip = 0in + % + % No extra space above this paragraph. + \parskip = 0in + % + % Do not prefer a separate line ending with a hyphen to fewer lines. + \finalhyphendemerits = 0 + % + % \hangindent is only relevant when the entry text and page number + % don't both fit on one line. In that case, bob suggests starting the + % dots pretty far over on the line. Unfortunately, a large + % indentation looks wrong when the entry text itself is broken across + % lines. So we use a small indentation and put up with long leaders. + % + % \hangafter is reset to 1 (which is the value we want) at the start + % of each paragraph, so we need not do anything with that. + \hangindent = 2em + % + % When the entry text needs to be broken, just fill out the first line + % with blank space. + \rightskip = 0pt plus1fil + % + % A bit of stretch before each entry for the benefit of balancing + % columns. + \vskip 0pt plus1pt + % + % Swallow the left brace of the text (first parameter): + \afterassignment\doentry + \let\temp = +} +\def\doentry{% + \bgroup % Instead of the swallowed brace. + \noindent + \aftergroup\finishentry + % And now comes the text of the entry. +} +\def\finishentry#1{% + % #1 is the page number. + % + % The following is kludged to not output a line of dots in the index if + % there are no page numbers. The next person who breaks this will be + % cursed by a Unix daemon. + \def\tempa{{\rm }}% + \def\tempb{#1}% + \edef\tempc{\tempa}% + \edef\tempd{\tempb}% + \ifx\tempc\tempd + \ % + \else + % + % If we must, put the page number on a line of its own, and fill out + % this line with blank space. (The \hfil is overwhelmed with the + % fill leaders glue in \indexdotfill if the page number does fit.) + \hfil\penalty50 + \null\nobreak\indexdotfill % Have leaders before the page number. + % + % The `\ ' here is removed by the implicit \unskip that TeX does as + % part of (the primitive) \par. Without it, a spurious underfull + % \hbox ensues. + \ifpdf + \pdfgettoks#1.% + \ \the\toksA + \else + \ #1% + \fi + \fi + \par + \endgroup +} + +% Like \dotfill except takes at least 1 em. +\def\indexdotfill{\cleaders + \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} + +\def\primary #1{\line{#1\hfil}} + +\newskip\secondaryindent \secondaryindent=0.5cm +\def\secondary#1#2{{% + \parfillskip=0in + \parskip=0in + \hangindent=1in + \hangafter=1 + \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill + \ifpdf + \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. + \else + #2 + \fi + \par +}} + +% Define two-column mode, which we use to typeset indexes. +% Adapted from the TeXbook, page 416, which is to say, +% the manmac.tex format used to print the TeXbook itself. +\catcode`\@=11 + +\newbox\partialpage +\newdimen\doublecolumnhsize + +\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns + % Grab any single-column material above us. + \output = {% + % + % Here is a possibility not foreseen in manmac: if we accumulate a + % whole lot of material, we might end up calling this \output + % routine twice in a row (see the doublecol-lose test, which is + % essentially a couple of indexes with @setchapternewpage off). In + % that case we just ship out what is in \partialpage with the normal + % output routine. Generally, \partialpage will be empty when this + % runs and this will be a no-op. See the indexspread.tex test case. + \ifvoid\partialpage \else + \onepageout{\pagecontents\partialpage}% + \fi + % + \global\setbox\partialpage = \vbox{% + % Unvbox the main output page. + \unvbox\PAGE + \kern-\topskip \kern\baselineskip + }% + }% + \eject % run that output routine to set \partialpage + % + % Use the double-column output routine for subsequent pages. + \output = {\doublecolumnout}% + % + % Change the page size parameters. We could do this once outside this + % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 + % format, but then we repeat the same computation. Repeating a couple + % of assignments once per index is clearly meaningless for the + % execution time, so we may as well do it in one place. + % + % First we halve the line length, less a little for the gutter between + % the columns. We compute the gutter based on the line length, so it + % changes automatically with the paper format. The magic constant + % below is chosen so that the gutter has the same value (well, +-<1pt) + % as it did when we hard-coded it. + % + % We put the result in a separate register, \doublecolumhsize, so we + % can restore it in \pagesofar, after \hsize itself has (potentially) + % been clobbered. + % + \doublecolumnhsize = \hsize + \advance\doublecolumnhsize by -.04154\hsize + \divide\doublecolumnhsize by 2 + \hsize = \doublecolumnhsize + % + % Double the \vsize as well. (We don't need a separate register here, + % since nobody clobbers \vsize.) + \vsize = 2\vsize +} + +% The double-column output routine for all double-column pages except +% the last. +% +\def\doublecolumnout{% + \splittopskip=\topskip \splitmaxdepth=\maxdepth + % Get the available space for the double columns -- the normal + % (undoubled) page height minus any material left over from the + % previous page. + \dimen@ = \vsize + \divide\dimen@ by 2 + \advance\dimen@ by -\ht\partialpage + % + % box0 will be the left-hand column, box2 the right. + \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ + \onepageout\pagesofar + \unvbox255 + \penalty\outputpenalty +} +% +% Re-output the contents of the output page -- any previous material, +% followed by the two boxes we just split, in box0 and box2. +\def\pagesofar{% + \unvbox\partialpage + % + \hsize = \doublecolumnhsize + \wd0=\hsize \wd2=\hsize + \hbox to\pagewidth{\box0\hfil\box2}% +} +% +% All done with double columns. +\def\enddoublecolumns{% + \output = {% + % Split the last of the double-column material. Leave it on the + % current page, no automatic page break. + \balancecolumns + % + % If we end up splitting too much material for the current page, + % though, there will be another page break right after this \output + % invocation ends. Having called \balancecolumns once, we do not + % want to call it again. Therefore, reset \output to its normal + % definition right away. (We hope \balancecolumns will never be + % called on to balance too much material, but if it is, this makes + % the output somewhat more palatable.) + \global\output = {\onepageout{\pagecontents\PAGE}}% + }% + \eject + \endgroup % started in \begindoublecolumns + % + % \pagegoal was set to the doubled \vsize above, since we restarted + % the current page. We're now back to normal single-column + % typesetting, so reset \pagegoal to the normal \vsize (after the + % \endgroup where \vsize got restored). + \pagegoal = \vsize +} +% +% Called at the end of the double column material. +\def\balancecolumns{% + \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. + \dimen@ = \ht0 + \advance\dimen@ by \topskip + \advance\dimen@ by-\baselineskip + \divide\dimen@ by 2 % target to split to + %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% + \splittopskip = \topskip + % Loop until we get a decent breakpoint. + {% + \vbadness = 10000 + \loop + \global\setbox3 = \copy0 + \global\setbox1 = \vsplit3 to \dimen@ + \ifdim\ht3>\dimen@ + \global\advance\dimen@ by 1pt + \repeat + }% + %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% + \setbox0=\vbox to\dimen@{\unvbox1}% + \setbox2=\vbox to\dimen@{\unvbox3}% + % + \pagesofar +} +\catcode`\@ = \other + + +\message{sectioning,} +% Chapters, sections, etc. + +% \unnumberedno is an oxymoron, of course. But we count the unnumbered +% sections so that we can refer to them unambiguously in the pdf +% outlines by their "section number". We avoid collisions with chapter +% numbers by starting them at 10000. (If a document ever has 10000 +% chapters, we're in trouble anyway, I'm sure.) +\newcount\unnumberedno \unnumberedno = 10000 +\newcount\chapno +\newcount\secno \secno=0 +\newcount\subsecno \subsecno=0 +\newcount\subsubsecno \subsubsecno=0 + +% This counter is funny since it counts through charcodes of letters A, B, ... +\newcount\appendixno \appendixno = `\@ +% +% \def\appendixletter{\char\the\appendixno} +% We do the following ugly conditional instead of the above simple +% construct for the sake of pdftex, which needs the actual +% letter in the expansion, not just typeset. +% +\def\appendixletter{% + \ifnum\appendixno=`A A% + \else\ifnum\appendixno=`B B% + \else\ifnum\appendixno=`C C% + \else\ifnum\appendixno=`D D% + \else\ifnum\appendixno=`E E% + \else\ifnum\appendixno=`F F% + \else\ifnum\appendixno=`G G% + \else\ifnum\appendixno=`H H% + \else\ifnum\appendixno=`I I% + \else\ifnum\appendixno=`J J% + \else\ifnum\appendixno=`K K% + \else\ifnum\appendixno=`L L% + \else\ifnum\appendixno=`M M% + \else\ifnum\appendixno=`N N% + \else\ifnum\appendixno=`O O% + \else\ifnum\appendixno=`P P% + \else\ifnum\appendixno=`Q Q% + \else\ifnum\appendixno=`R R% + \else\ifnum\appendixno=`S S% + \else\ifnum\appendixno=`T T% + \else\ifnum\appendixno=`U U% + \else\ifnum\appendixno=`V V% + \else\ifnum\appendixno=`W W% + \else\ifnum\appendixno=`X X% + \else\ifnum\appendixno=`Y Y% + \else\ifnum\appendixno=`Z Z% + % The \the is necessary, despite appearances, because \appendixletter is + % expanded while writing the .toc file. \char\appendixno is not + % expandable, thus it is written literally, thus all appendixes come out + % with the same letter (or @) in the toc without it. + \else\char\the\appendixno + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + +% Each @chapter defines this as the name of the chapter. +% page headings and footings can use it. @section does likewise. +% However, they are not reliable, because we don't use marks. +\def\thischapter{} +\def\thissection{} + +\newcount\absseclevel % used to calculate proper heading level +\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count + +% @raisesections: treat @section as chapter, @subsection as section, etc. +\def\raisesections{\global\advance\secbase by -1} +\let\up=\raisesections % original BFox name + +% @lowersections: treat @chapter as section, @section as subsection, etc. +\def\lowersections{\global\advance\secbase by 1} +\let\down=\lowersections % original BFox name + +% we only have subsub. +\chardef\maxseclevel = 3 +% +% A numbered section within an unnumbered changes to unnumbered too. +% To achive this, remember the "biggest" unnum. sec. we are currently in: +\chardef\unmlevel = \maxseclevel +% +% Trace whether the current chapter is an appendix or not: +% \chapheadtype is "N" or "A", unnumbered chapters are ignored. +\def\chapheadtype{N} + +% Choose a heading macro +% #1 is heading type +% #2 is heading level +% #3 is text for heading +\def\genhead#1#2#3{% + % Compute the abs. sec. level: + \absseclevel=#2 + \advance\absseclevel by \secbase + % Make sure \absseclevel doesn't fall outside the range: + \ifnum \absseclevel < 0 + \absseclevel = 0 + \else + \ifnum \absseclevel > 3 + \absseclevel = 3 + \fi + \fi + % The heading type: + \def\headtype{#1}% + \if \headtype U% + \ifnum \absseclevel < \unmlevel + \chardef\unmlevel = \absseclevel + \fi + \else + % Check for appendix sections: + \ifnum \absseclevel = 0 + \edef\chapheadtype{\headtype}% + \else + \if \headtype A\if \chapheadtype N% + \errmessage{@appendix... within a non-appendix chapter}% + \fi\fi + \fi + % Check for numbered within unnumbered: + \ifnum \absseclevel > \unmlevel + \def\headtype{U}% + \else + \chardef\unmlevel = 3 + \fi + \fi + % Now print the heading: + \if \headtype U% + \ifcase\absseclevel + \unnumberedzzz{#3}% + \or \unnumberedseczzz{#3}% + \or \unnumberedsubseczzz{#3}% + \or \unnumberedsubsubseczzz{#3}% + \fi + \else + \if \headtype A% + \ifcase\absseclevel + \appendixzzz{#3}% + \or \appendixsectionzzz{#3}% + \or \appendixsubseczzz{#3}% + \or \appendixsubsubseczzz{#3}% + \fi + \else + \ifcase\absseclevel + \chapterzzz{#3}% + \or \seczzz{#3}% + \or \numberedsubseczzz{#3}% + \or \numberedsubsubseczzz{#3}% + \fi + \fi + \fi + \suppressfirstparagraphindent +} + +% an interface: +\def\numhead{\genhead N} +\def\apphead{\genhead A} +\def\unnmhead{\genhead U} + +% @chapter, @appendix, @unnumbered. Increment top-level counter, reset +% all lower-level sectioning counters to zero. +% +% Also set \chaplevelprefix, which we prepend to @float sequence numbers +% (e.g., figures), q.v. By default (before any chapter), that is empty. +\let\chaplevelprefix = \empty +% +\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz +\def\chapterzzz#1{% + % section resetting is \global in case the chapter is in a group, such + % as an @include file. + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\chapno by 1 + % + % Used for \float. + \gdef\chaplevelprefix{\the\chapno.}% + \resetallfloatnos + % + \message{\putwordChapter\space \the\chapno}% + % + % Write the actual heading. + \chapmacro{#1}{Ynumbered}{\the\chapno}% + % + % So @section and the like are numbered underneath this chapter. + \global\let\section = \numberedsec + \global\let\subsection = \numberedsubsec + \global\let\subsubsection = \numberedsubsubsec +} + +\outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz +\def\appendixzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\appendixno by 1 + \gdef\chaplevelprefix{\appendixletter.}% + \resetallfloatnos + % + \def\appendixnum{\putwordAppendix\space \appendixletter}% + \message{\appendixnum}% + % + \chapmacro{#1}{Yappendix}{\appendixletter}% + % + \global\let\section = \appendixsec + \global\let\subsection = \appendixsubsec + \global\let\subsubsection = \appendixsubsubsec +} + +\outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz +\def\unnumberedzzz#1{% + \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 + \global\advance\unnumberedno by 1 + % + % Since an unnumbered has no number, no prefix for figures. + \global\let\chaplevelprefix = \empty + \resetallfloatnos + % + % This used to be simply \message{#1}, but TeX fully expands the + % argument to \message. Therefore, if #1 contained @-commands, TeX + % expanded them. For example, in `@unnumbered The @cite{Book}', TeX + % expanded @cite (which turns out to cause errors because \cite is meant + % to be executed, not expanded). + % + % Anyway, we don't want the fully-expanded definition of @cite to appear + % as a result of the \message, we just want `@cite' itself. We use + % \the<toks register> to achieve this: TeX expands \the<toks> only once, + % simply yielding the contents of <toks register>. (We also do this for + % the toc entries.) + \toks0 = {#1}% + \message{(\the\toks0)}% + % + \chapmacro{#1}{Ynothing}{\the\unnumberedno}% + % + \global\let\section = \unnumberedsec + \global\let\subsection = \unnumberedsubsec + \global\let\subsubsection = \unnumberedsubsubsec +} + +% @centerchap is like @unnumbered, but the heading is centered. +\outer\parseargdef\centerchap{% + % Well, we could do the following in a group, but that would break + % an assumption that \chapmacro is called at the outermost level. + % Thus we are safer this way: --kasal, 24feb04 + \let\centerparametersmaybe = \centerparameters + \unnmhead0{#1}% + \let\centerparametersmaybe = \relax +} + +% @top is like @unnumbered. +\let\top\unnumbered + +% Sections. +\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz +\def\seczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% +} + +\outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz +\def\appendixsectionzzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% +} +\let\appendixsec\appendixsection + +\outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz +\def\unnumberedseczzz#1{% + \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 + \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% +} + +% Subsections. +\outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz +\def\numberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% +} + +\outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz +\def\appendixsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno}% +} + +\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz +\def\unnumberedsubseczzz#1{% + \global\subsubsecno=0 \global\advance\subsecno by 1 + \sectionheading{#1}{subsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno}% +} + +% Subsubsections. +\outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz +\def\numberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynumbered}% + {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +\outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz +\def\appendixsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Yappendix}% + {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz +\def\unnumberedsubsubseczzz#1{% + \global\advance\subsubsecno by 1 + \sectionheading{#1}{subsubsec}{Ynothing}% + {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% +} + +% These macros control what the section commands do, according +% to what kind of chapter we are in (ordinary, appendix, or unnumbered). +% Define them by default for a numbered chapter. +\let\section = \numberedsec +\let\subsection = \numberedsubsec +\let\subsubsection = \numberedsubsubsec + +% Define @majorheading, @heading and @subheading + +% NOTE on use of \vbox for chapter headings, section headings, and such: +% 1) We use \vbox rather than the earlier \line to permit +% overlong headings to fold. +% 2) \hyphenpenalty is set to 10000 because hyphenation in a +% heading is obnoxious; this forbids it. +% 3) Likewise, headings look best if no \parindent is used, and +% if justification is not attempted. Hence \raggedright. + + +\def\majorheading{% + {\advance\chapheadingskip by 10pt \chapbreak }% + \parsearg\chapheadingzzz +} + +\def\chapheading{\chapbreak \parsearg\chapheadingzzz} +\def\chapheadingzzz#1{% + {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}% + \bigskip \par\penalty 200\relax + \suppressfirstparagraphindent +} + +% @heading, @subheading, @subsubheading. +\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} +\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} + \suppressfirstparagraphindent} + +% These macros generate a chapter, section, etc. heading only +% (including whitespace, linebreaking, etc. around it), +% given all the information in convenient, parsed form. + +%%% Args are the skip and penalty (usually negative) +\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} + +%%% Define plain chapter starts, and page on/off switching for it +% Parameter controlling skip before chapter headings (if needed) + +\newskip\chapheadingskip + +\def\chapbreak{\dobreak \chapheadingskip {-4000}} +\def\chappager{\par\vfill\supereject} +\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} + +\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} + +\def\CHAPPAGoff{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chapbreak +\global\let\pagealignmacro=\chappager} + +\def\CHAPPAGon{% +\global\let\contentsalignmacro = \chappager +\global\let\pchapsepmacro=\chappager +\global\let\pagealignmacro=\chappager +\global\def\HEADINGSon{\HEADINGSsingle}} + +\def\CHAPPAGodd{% +\global\let\contentsalignmacro = \chapoddpage +\global\let\pchapsepmacro=\chapoddpage +\global\let\pagealignmacro=\chapoddpage +\global\def\HEADINGSon{\HEADINGSdouble}} + +\CHAPPAGon + +% Chapter opening. +% +% #1 is the text, #2 is the section type (Ynumbered, Ynothing, +% Yappendix, Yomitfromtoc), #3 the chapter number. +% +% To test against our argument. +\def\Ynothingkeyword{Ynothing} +\def\Yomitfromtockeyword{Yomitfromtoc} +\def\Yappendixkeyword{Yappendix} +% +\def\chapmacro#1#2#3{% + \pchapsepmacro + {% + \chapfonts \rm + % + % Have to define \thissection before calling \donoderef, because the + % xref code eventually uses it. On the other hand, it has to be called + % after \pchapsepmacro, or the headline will change too soon. + \gdef\thissection{#1}% + \gdef\thischaptername{#1}% + % + % Only insert the separating space if we have a chapter/appendix + % number, and don't print the unnumbered ``number''. + \def\temptype{#2}% + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unnchap}% + \gdef\thischapter{#1}% + \else\ifx\temptype\Yomitfromtockeyword + \setbox0 = \hbox{}% contents like unnumbered, but no toc entry + \def\toctype{omit}% + \gdef\thischapter{}% + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% + \def\toctype{app}% + % We don't substitute the actual chapter name into \thischapter + % because we don't want its macros evaluated now. And we don't + % use \thissection because that changes with each section. + % + \xdef\thischapter{\putwordAppendix{} \appendixletter: + \noexpand\thischaptername}% + \else + \setbox0 = \hbox{#3\enspace}% + \def\toctype{numchap}% + \xdef\thischapter{\putwordChapter{} \the\chapno: + \noexpand\thischaptername}% + \fi\fi\fi + % + % Write the toc entry for this chapter. Must come before the + % \donoderef, because we include the current node name in the toc + % entry, and \donoderef resets it to empty. + \writetocentry{\toctype}{#1}{#3}% + % + % For pdftex, we have to write out the node definition (aka, make + % the pdfdest) after any page break, but before the actual text has + % been typeset. If the destination for the pdf outline is after the + % text, then jumping from the outline may wind up with the text not + % being visible, for instance under high magnification. + \donoderef{#2}% + % + % Typeset the actual heading. + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent=\wd0 \centerparametersmaybe + \unhbox0 #1\par}% + }% + \nobreak\bigskip % no page break after a chapter title + \nobreak +} + +% @centerchap -- centered and unnumbered. +\let\centerparametersmaybe = \relax +\def\centerparameters{% + \advance\rightskip by 3\rightskip + \leftskip = \rightskip + \parfillskip = 0pt +} + + +% I don't think this chapter style is supported any more, so I'm not +% updating it with the new noderef stuff. We'll see. --karl, 11aug03. +% +\def\setchapterstyle #1 {\csname CHAPF#1\endcsname} +% +\def\unnchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt\raggedright + \rm #1\hfill}}\bigskip \par\nobreak +} +\def\chfopen #1#2{\chapoddpage {\chapfonts +\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% +\par\penalty 5000 % +} +\def\centerchfopen #1{% +\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 + \parindent=0pt + \hfill {\rm #1}\hfill}}\bigskip \par\nobreak +} +\def\CHAPFopen{% + \global\let\chapmacro=\chfopen + \global\let\centerchapmacro=\centerchfopen} + + +% Section titles. These macros combine the section number parts and +% call the generic \sectionheading to do the printing. +% +\newskip\secheadingskip +\def\secheadingbreak{\dobreak \secheadingskip{-1000}} + +% Subsection titles. +\newskip\subsecheadingskip +\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} + +% Subsubsection titles. +\def\subsubsecheadingskip{\subsecheadingskip} +\def\subsubsecheadingbreak{\subsecheadingbreak} + + +% Print any size, any type, section title. +% +% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is +% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the +% section number. +% +\def\sectionheading#1#2#3#4{% + {% + % Switch to the right set of fonts. + \csname #2fonts\endcsname \rm + % + % Insert space above the heading. + \csname #2headingbreak\endcsname + % + % Only insert the space after the number if we have a section number. + \def\sectionlevel{#2}% + \def\temptype{#3}% + % + \ifx\temptype\Ynothingkeyword + \setbox0 = \hbox{}% + \def\toctype{unn}% + \gdef\thissection{#1}% + \else\ifx\temptype\Yomitfromtockeyword + % for @headings -- no section number, don't include in toc, + % and don't redefine \thissection. + \setbox0 = \hbox{}% + \def\toctype{omit}% + \let\sectionlevel=\empty + \else\ifx\temptype\Yappendixkeyword + \setbox0 = \hbox{#4\enspace}% + \def\toctype{app}% + \gdef\thissection{#1}% + \else + \setbox0 = \hbox{#4\enspace}% + \def\toctype{num}% + \gdef\thissection{#1}% + \fi\fi\fi + % + % Write the toc entry (before \donoderef). See comments in \chapmacro. + \writetocentry{\toctype\sectionlevel}{#1}{#4}% + % + % Write the node reference (= pdf destination for pdftex). + % Again, see comments in \chapmacro. + \donoderef{#3}% + % + % Interline glue will be inserted when the vbox is completed. + % That glue will be a valid breakpoint for the page, since it'll be + % preceded by a whatsit (usually from the \donoderef, or from the + % \writetocentry if there was no node). We don't want to allow that + % break, since then the whatsits could end up on page n while the + % section is on page n+1, thus toc/etc. are wrong. Debian bug 276000. + \nobreak + % + % Output the actual section heading. + \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright + \hangindent=\wd0 % zero if no section number + \unhbox0 #1}% + }% + % Add extra space after the heading -- half of whatever came above it. + % Don't allow stretch, though. + \kern .5 \csname #2headingskip\endcsname + % + % Do not let the kern be a potential breakpoint, as it would be if it + % was followed by glue. + \nobreak + % + % We'll almost certainly start a paragraph next, so don't let that + % glue accumulate. (Not a breakpoint because it's preceded by a + % discardable item.) + \vskip-\parskip + % + % This is purely so the last item on the list is a known \penalty > + % 10000. This is so \startdefun can avoid allowing breakpoints after + % section headings. Otherwise, it would insert a valid breakpoint between: + % + % @section sec-whatever + % @deffn def-whatever + \penalty 10001 +} + + +\message{toc,} +% Table of contents. +\newwrite\tocfile + +% Write an entry to the toc file, opening it if necessary. +% Called from @chapter, etc. +% +% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} +% We append the current node name (if any) and page number as additional +% arguments for the \{chap,sec,...}entry macros which will eventually +% read this. The node name is used in the pdf outlines as the +% destination to jump to. +% +% We open the .toc file for writing here instead of at @setfilename (or +% any other fixed time) so that @contents can be anywhere in the document. +% But if #1 is `omit', then we don't do anything. This is used for the +% table of contents chapter openings themselves. +% +\newif\iftocfileopened +\def\omitkeyword{omit}% +% +\def\writetocentry#1#2#3{% + \edef\writetoctype{#1}% + \ifx\writetoctype\omitkeyword \else + \iftocfileopened\else + \immediate\openout\tocfile = \jobname.toc + \global\tocfileopenedtrue + \fi + % + \iflinks + {\atdummies + \edef\temp{% + \write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}% + \temp + }% + \fi + \fi + % + % Tell \shipout to create a pdf destination on each page, if we're + % writing pdf. These are used in the table of contents. We can't + % just write one on every page because the title pages are numbered + % 1 and 2 (the page numbers aren't printed), and so are the first + % two pages of the document. Thus, we'd have two destinations named + % `1', and two named `2'. + \ifpdf \global\pdfmakepagedesttrue \fi +} + + +% These characters do not print properly in the Computer Modern roman +% fonts, so we must take special care. This is more or less redundant +% with the Texinfo input format setup at the end of this file. +% +\def\activecatcodes{% + \catcode`\"=\active + \catcode`\$=\active + \catcode`\<=\active + \catcode`\>=\active + \catcode`\\=\active + \catcode`\^=\active + \catcode`\_=\active + \catcode`\|=\active + \catcode`\~=\active +} + + +% Read the toc file, which is essentially Texinfo input. +\def\readtocfile{% + \setupdatafile + \activecatcodes + \input \jobname.toc +} + +\newskip\contentsrightmargin \contentsrightmargin=1in +\newcount\savepageno +\newcount\lastnegativepageno \lastnegativepageno = -1 + +% Prepare to read what we've written to \tocfile. +% +\def\startcontents#1{% + % If @setchapternewpage on, and @headings double, the contents should + % start on an odd page, unlike chapters. Thus, we maintain + % \contentsalignmacro in parallel with \pagealignmacro. + % From: Torbjorn Granlund <tege@matematik.su.se> + \contentsalignmacro + \immediate\closeout\tocfile + % + % Don't need to put `Contents' or `Short Contents' in the headline. + % It is abundantly clear what they are. + \def\thischapter{}% + \chapmacro{#1}{Yomitfromtoc}{}% + % + \savepageno = \pageno + \begingroup % Set up to handle contents files properly. + \raggedbottom % Worry more about breakpoints than the bottom. + \advance\hsize by -\contentsrightmargin % Don't use the full line length. + % + % Roman numerals for page numbers. + \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi +} + + +% Normal (long) toc. +\def\contents{% + \startcontents{\putwordTOC}% + \openin 1 \jobname.toc + \ifeof 1 \else + \readtocfile + \fi + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \ifeof 1 \else + \pdfmakeoutlines + \fi + \closein 1 + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} + +% And just the chapters. +\def\summarycontents{% + \startcontents{\putwordShortTOC}% + % + \let\numchapentry = \shortchapentry + \let\appentry = \shortchapentry + \let\unnchapentry = \shortunnchapentry + % We want a true roman here for the page numbers. + \secfonts + \let\rm=\shortcontrm \let\bf=\shortcontbf + \let\sl=\shortcontsl \let\tt=\shortconttt + \rm + \hyphenpenalty = 10000 + \advance\baselineskip by 1pt % Open it up a little. + \def\numsecentry##1##2##3##4{} + \let\appsecentry = \numsecentry + \let\unnsecentry = \numsecentry + \let\numsubsecentry = \numsecentry + \let\appsubsecentry = \numsecentry + \let\unnsubsecentry = \numsecentry + \let\numsubsubsecentry = \numsecentry + \let\appsubsubsecentry = \numsecentry + \let\unnsubsubsecentry = \numsecentry + \openin 1 \jobname.toc + \ifeof 1 \else + \readtocfile + \fi + \closein 1 + \vfill \eject + \contentsalignmacro % in case @setchapternewpage odd is in effect + \endgroup + \lastnegativepageno = \pageno + \global\pageno = \savepageno +} +\let\shortcontents = \summarycontents + +% Typeset the label for a chapter or appendix for the short contents. +% The arg is, e.g., `A' for an appendix, or `3' for a chapter. +% +\def\shortchaplabel#1{% + % This space should be enough, since a single number is .5em, and the + % widest letter (M) is 1em, at least in the Computer Modern fonts. + % But use \hss just in case. + % (This space doesn't include the extra space that gets added after + % the label; that gets put in by \shortchapentry above.) + % + % We'd like to right-justify chapter numbers, but that looks strange + % with appendix letters. And right-justifying numbers and + % left-justifying letters looks strange when there is less than 10 + % chapters. Have to read the whole toc once to know how many chapters + % there are before deciding ... + \hbox to 1em{#1\hss}% +} + +% These macros generate individual entries in the table of contents. +% The first argument is the chapter or section name. +% The last argument is the page number. +% The arguments in between are the chapter number, section number, ... + +% Chapters, in the main contents. +\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} +% +% Chapters, in the short toc. +% See comments in \dochapentry re vbox and related settings. +\def\shortchapentry#1#2#3#4{% + \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% +} + +% Appendices, in the main contents. +% Need the word Appendix, and a fixed-size box. +% +\def\appendixbox#1{% + % We use M since it's probably the widest letter. + \setbox0 = \hbox{\putwordAppendix{} M}% + \hbox to \wd0{\putwordAppendix{} #1\hss}} +% +\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} + +% Unnumbered chapters. +\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} +\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} + +% Sections. +\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} +\let\appsecentry=\numsecentry +\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} + +% Subsections. +\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} +\let\appsubsecentry=\numsubsecentry +\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} + +% And subsubsections. +\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} +\let\appsubsubsecentry=\numsubsubsecentry +\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} + +% This parameter controls the indentation of the various levels. +% Same as \defaultparindent. +\newdimen\tocindent \tocindent = 15pt + +% Now for the actual typesetting. In all these, #1 is the text and #2 is the +% page number. +% +% If the toc has to be broken over pages, we want it to be at chapters +% if at all possible; hence the \penalty. +\def\dochapentry#1#2{% + \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip + \begingroup + \chapentryfonts + \tocentry{#1}{\dopageno\bgroup#2\egroup}% + \endgroup + \nobreak\vskip .25\baselineskip plus.1\baselineskip +} + +\def\dosecentry#1#2{\begingroup + \secentryfonts \leftskip=\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsecentry#1#2{\begingroup + \subsecentryfonts \leftskip=2\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +\def\dosubsubsecentry#1#2{\begingroup + \subsubsecentryfonts \leftskip=3\tocindent + \tocentry{#1}{\dopageno\bgroup#2\egroup}% +\endgroup} + +% We use the same \entry macro as for the index entries. +\let\tocentry = \entry + +% Space between chapter (or whatever) number and the title. +\def\labelspace{\hskip1em \relax} + +\def\dopageno#1{{\rm #1}} +\def\doshortpageno#1{{\rm #1}} + +\def\chapentryfonts{\secfonts \rm} +\def\secentryfonts{\textfonts} +\def\subsecentryfonts{\textfonts} +\def\subsubsecentryfonts{\textfonts} + + +\message{environments,} +% @foo ... @end foo. + +% @point{}, @result{}, @expansion{}, @print{}, @equiv{}. +% +% Since these characters are used in examples, it should be an even number of +% \tt widths. Each \tt character is 1en, so two makes it 1em. +% +\def\point{$\star$} +\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} +\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} +\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} +\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} + +% The @error{} command. +% Adapted from the TeXbook's \boxit. +% +\newbox\errorbox +% +{\tentt \global\dimen0 = 3em}% Width of the box. +\dimen2 = .55pt % Thickness of rules +% The text. (`r' is open on the right, `e' somewhat less so on the left.) +\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} +% +\setbox\errorbox=\hbox to \dimen0{\hfil + \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. + \advance\hsize by -2\dimen2 % Rules. + \vbox{% + \hrule height\dimen2 + \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. + \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. + \kern3pt\vrule width\dimen2}% Space to right. + \hrule height\dimen2} + \hfil} +% +\def\error{\leavevmode\lower.7ex\copy\errorbox} + +% @tex ... @end tex escapes into raw Tex temporarily. +% One exception: @ is still an escape character, so that @end tex works. +% But \@ or @@ will get a plain tex @ character. + +\envdef\tex{% + \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 + \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 + \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie + \catcode `\%=14 + \catcode `\+=\other + \catcode `\"=\other + \catcode `\|=\other + \catcode `\<=\other + \catcode `\>=\other + \escapechar=`\\ + % + \let\b=\ptexb + \let\bullet=\ptexbullet + \let\c=\ptexc + \let\,=\ptexcomma + \let\.=\ptexdot + \let\dots=\ptexdots + \let\equiv=\ptexequiv + \let\!=\ptexexclam + \let\i=\ptexi + \let\indent=\ptexindent + \let\noindent=\ptexnoindent + \let\{=\ptexlbrace + \let\+=\tabalign + \let\}=\ptexrbrace + \let\/=\ptexslash + \let\*=\ptexstar + \let\t=\ptext + \let\frenchspacing=\plainfrenchspacing + % + \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% + \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% + \def\@{@}% +} +% There is no need to define \Etex. + +% Define @lisp ... @end lisp. +% @lisp environment forms a group so it can rebind things, +% including the definition of @end lisp (which normally is erroneous). + +% Amount to narrow the margins by for @lisp. +\newskip\lispnarrowing \lispnarrowing=0.4in + +% This is the definition that ^^M gets inside @lisp, @example, and other +% such environments. \null is better than a space, since it doesn't +% have any width. +\def\lisppar{\null\endgraf} + +% This space is always present above and below environments. +\newskip\envskipamount \envskipamount = 0pt + +% Make spacing and below environment symmetrical. We use \parskip here +% to help in doing that, since in @example-like environments \parskip +% is reset to zero; thus the \afterenvbreak inserts no space -- but the +% start of the next paragraph will insert \parskip. +% +\def\aboveenvbreak{{% + % =10000 instead of <10000 because of a special case in \itemzzz and + % \sectionheading, q.v. + \ifnum \lastpenalty=10000 \else + \advance\envskipamount by \parskip + \endgraf + \ifdim\lastskip<\envskipamount + \removelastskip + % it's not a good place to break if the last penalty was \nobreak + % or better ... + \ifnum\lastpenalty<10000 \penalty-50 \fi + \vskip\envskipamount + \fi + \fi +}} + +\let\afterenvbreak = \aboveenvbreak + +% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will +% also clear it, so that its embedded environments do the narrowing again. +\let\nonarrowing=\relax + +% @cartouche ... @end cartouche: draw rectangle w/rounded corners around +% environment contents. +\font\circle=lcircle10 +\newdimen\circthick +\newdimen\cartouter\newdimen\cartinner +\newskip\normbskip\newskip\normpskip\newskip\normlskip +\circthick=\fontdimen8\circle +% +\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth +\def\ctr{{\hskip 6pt\circle\char'010}} +\def\cbl{{\circle\char'012\hskip -6pt}} +\def\cbr{{\hskip 6pt\circle\char'011}} +\def\carttop{\hbox to \cartouter{\hskip\lskip + \ctl\leaders\hrule height\circthick\hfil\ctr + \hskip\rskip}} +\def\cartbot{\hbox to \cartouter{\hskip\lskip + \cbl\leaders\hrule height\circthick\hfil\cbr + \hskip\rskip}} +% +\newskip\lskip\newskip\rskip + +\envdef\cartouche{% + \ifhmode\par\fi % can't be in the midst of a paragraph. + \startsavinginserts + \lskip=\leftskip \rskip=\rightskip + \leftskip=0pt\rightskip=0pt % we want these *outside*. + \cartinner=\hsize \advance\cartinner by-\lskip + \advance\cartinner by-\rskip + \cartouter=\hsize + \advance\cartouter by 18.4pt % allow for 3pt kerns on either + % side, and for 6pt waste from + % each corner char, and rule thickness + \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip + % Flag to tell @lisp, etc., not to narrow margin. + \let\nonarrowing = t% + \vbox\bgroup + \baselineskip=0pt\parskip=0pt\lineskip=0pt + \carttop + \hbox\bgroup + \hskip\lskip + \vrule\kern3pt + \vbox\bgroup + \kern3pt + \hsize=\cartinner + \baselineskip=\normbskip + \lineskip=\normlskip + \parskip=\normpskip + \vskip -\parskip + \comment % For explanation, see the end of \def\group. +} +\def\Ecartouche{% + \ifhmode\par\fi + \kern3pt + \egroup + \kern3pt\vrule + \hskip\rskip + \egroup + \cartbot + \egroup + \checkinserts +} + + +% This macro is called at the beginning of all the @example variants, +% inside a group. +\def\nonfillstart{% + \aboveenvbreak + \hfuzz = 12pt % Don't be fussy + \sepspaces % Make spaces be word-separators rather than space tokens. + \let\par = \lisppar % don't ignore blank lines + \obeylines % each line of input is a line of output + \parskip = 0pt + \parindent = 0pt + \emergencystretch = 0pt % don't try to avoid overfull boxes + \ifx\nonarrowing\relax + \advance \leftskip by \lispnarrowing + \exdentamount=\lispnarrowing + \else + \let\nonarrowing = \relax + \fi + \let\exdent=\nofillexdent +} + +% If you want all examples etc. small: @set dispenvsize small. +% If you want even small examples the full size: @set dispenvsize nosmall. +% This affects the following displayed environments: +% @example, @display, @format, @lisp +% +\def\smallword{small} +\def\nosmallword{nosmall} +\let\SETdispenvsize\relax +\def\setnormaldispenv{% + \ifx\SETdispenvsize\smallword + \smallexamplefonts \rm + \fi +} +\def\setsmalldispenv{% + \ifx\SETdispenvsize\nosmallword + \else + \smallexamplefonts \rm + \fi +} + +% We often define two environments, @foo and @smallfoo. +% Let's do it by one command: +\def\makedispenv #1#2{ + \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2} + \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2} + \expandafter\let\csname E#1\endcsname \afterenvbreak + \expandafter\let\csname Esmall#1\endcsname \afterenvbreak +} + +% Define two synonyms: +\def\maketwodispenvs #1#2#3{ + \makedispenv{#1}{#3} + \makedispenv{#2}{#3} +} + +% @lisp: indented, narrowed, typewriter font; @example: same as @lisp. +% +% @smallexample and @smalllisp: use smaller fonts. +% Originally contributed by Pavel@xerox. +% +\maketwodispenvs {lisp}{example}{% + \nonfillstart + \tt + \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. + \gobble % eat return +} + +% @display/@smalldisplay: same as @lisp except keep current font. +% +\makedispenv {display}{% + \nonfillstart + \gobble +} + +% @format/@smallformat: same as @display except don't narrow margins. +% +\makedispenv{format}{% + \let\nonarrowing = t% + \nonfillstart + \gobble +} + +% @flushleft: same as @format, but doesn't obey \SETdispenvsize. +\envdef\flushleft{% + \let\nonarrowing = t% + \nonfillstart + \gobble +} +\let\Eflushleft = \afterenvbreak + +% @flushright. +% +\envdef\flushright{% + \let\nonarrowing = t% + \nonfillstart + \advance\leftskip by 0pt plus 1fill + \gobble +} +\let\Eflushright = \afterenvbreak + + +% @quotation does normal linebreaking (hence we can't use \nonfillstart) +% and narrows the margins. We keep \parskip nonzero in general, since +% we're doing normal filling. So, when using \aboveenvbreak and +% \afterenvbreak, temporarily make \parskip 0. +% +\envdef\quotation{% + {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip + \parindent=0pt + % + % @cartouche defines \nonarrowing to inhibit narrowing at next level down. + \ifx\nonarrowing\relax + \advance\leftskip by \lispnarrowing + \advance\rightskip by \lispnarrowing + \exdentamount = \lispnarrowing + \else + \let\nonarrowing = \relax + \fi + \parsearg\quotationlabel +} + +% We have retained a nonzero parskip for the environment, since we're +% doing normal filling. +% +\def\Equotation{% + \par + \ifx\quotationauthor\undefined\else + % indent a bit. + \leftline{\kern 2\leftskip \sl ---\quotationauthor}% + \fi + {\parskip=0pt \afterenvbreak}% +} + +% If we're given an argument, typeset it in bold with a colon after. +\def\quotationlabel#1{% + \def\temp{#1}% + \ifx\temp\empty \else + {\bf #1: }% + \fi +} + + +% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>} +% If we want to allow any <char> as delimiter, +% we need the curly braces so that makeinfo sees the @verb command, eg: +% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org +% +% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. +% +% [Knuth] p.344; only we need to do the other characters Texinfo sets +% active too. Otherwise, they get lost as the first character on a +% verbatim line. +\def\dospecials{% + \do\ \do\\\do\{\do\}\do\$\do\&% + \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% + \do\<\do\>\do\|\do\@\do+\do\"% +} +% +% [Knuth] p. 380 +\def\uncatcodespecials{% + \def\do##1{\catcode`##1=\other}\dospecials} +% +% [Knuth] pp. 380,381,391 +% Disable Spanish ligatures ?` and !` of \tt font +\begingroup + \catcode`\`=\active\gdef`{\relax\lq} +\endgroup +% +% Setup for the @verb command. +% +% Eight spaces for a tab +\begingroup + \catcode`\^^I=\active + \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} +\endgroup +% +\def\setupverb{% + \tt % easiest (and conventionally used) font for verbatim + \def\par{\leavevmode\endgraf}% + \catcode`\`=\active + \tabeightspaces + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces +} + +% Setup for the @verbatim environment +% +% Real tab expansion +\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount +% +\def\starttabbox{\setbox0=\hbox\bgroup} +\begingroup + \catcode`\^^I=\active + \gdef\tabexpand{% + \catcode`\^^I=\active + \def^^I{\leavevmode\egroup + \dimen0=\wd0 % the width so far, or since the previous tab + \divide\dimen0 by\tabw + \multiply\dimen0 by\tabw % compute previous multiple of \tabw + \advance\dimen0 by\tabw % advance to next multiple of \tabw + \wd0=\dimen0 \box0 \starttabbox + }% + } +\endgroup +\def\setupverbatim{% + \let\nonarrowing = t% + \nonfillstart + % Easiest (and conventionally used) font for verbatim + \tt + \def\par{\leavevmode\egroup\box0\endgraf}% + \catcode`\`=\active + \tabexpand + % Respect line breaks, + % print special symbols as themselves, and + % make each space count + % must do in this order: + \obeylines \uncatcodespecials \sepspaces + \everypar{\starttabbox}% +} + +% Do the @verb magic: verbatim text is quoted by unique +% delimiter characters. Before first delimiter expect a +% right brace, after last delimiter expect closing brace: +% +% \def\doverb'{'<char>#1<char>'}'{#1} +% +% [Knuth] p. 382; only eat outer {} +\begingroup + \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other + \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] +\endgroup +% +\def\verb{\begingroup\setupverb\doverb} +% +% +% Do the @verbatim magic: define the macro \doverbatim so that +% the (first) argument ends when '@end verbatim' is reached, ie: +% +% \def\doverbatim#1@end verbatim{#1} +% +% For Texinfo it's a lot easier than for LaTeX, +% because texinfo's \verbatim doesn't stop at '\end{verbatim}': +% we need not redefine '\', '{' and '}'. +% +% Inspired by LaTeX's verbatim command set [latex.ltx] +% +\begingroup + \catcode`\ =\active + \obeylines % + % ignore everything up to the first ^^M, that's the newline at the end + % of the @verbatim input line itself. Otherwise we get an extra blank + % line in the output. + \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% + % We really want {...\end verbatim} in the body of the macro, but + % without the active space; thus we have to use \xdef and \gobble. +\endgroup +% +\envdef\verbatim{% + \setupverbatim\doverbatim +} +\let\Everbatim = \afterenvbreak + + +% @verbatiminclude FILE - insert text of file in verbatim environment. +% +\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} +% +\def\doverbatiminclude#1{% + {% + \makevalueexpandable + \setupverbatim + \input #1 + \afterenvbreak + }% +} + +% @copying ... @end copying. +% Save the text away for @insertcopying later. +% +% We save the uninterpreted tokens, rather than creating a box. +% Saving the text in a box would be much easier, but then all the +% typesetting commands (@smallbook, font changes, etc.) have to be done +% beforehand -- and a) we want @copying to be done first in the source +% file; b) letting users define the frontmatter in as flexible order as +% possible is very desirable. +% +\def\copying{\checkenv{}\begingroup\scanargctxt\docopying} +\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} +% +\def\insertcopying{% + \begingroup + \parindent = 0pt % paragraph indentation looks wrong on title page + \scanexp\copyingtext + \endgroup +} + +\message{defuns,} +% @defun etc. + +\newskip\defbodyindent \defbodyindent=.4in +\newskip\defargsindent \defargsindent=50pt +\newskip\deflastargmargin \deflastargmargin=18pt + +% Start the processing of @deffn: +\def\startdefun{% + \ifnum\lastpenalty<10000 + \medbreak + \else + % If there are two @def commands in a row, we'll have a \nobreak, + % which is there to keep the function description together with its + % header. But if there's nothing but headers, we need to allow a + % break somewhere. Check specifically for penalty 10002, inserted + % by \defargscommonending, instead of 10000, since the sectioning + % commands also insert a nobreak penalty, and we don't want to allow + % a break between a section heading and a defun. + % + \ifnum\lastpenalty=10002 \penalty2000 \fi + % + % Similarly, after a section heading, do not allow a break. + % But do insert the glue. + \medskip % preceded by discardable penalty, so not a breakpoint + \fi + % + \parindent=0in + \advance\leftskip by \defbodyindent + \exdentamount=\defbodyindent +} + +\def\dodefunx#1{% + % First, check whether we are in the right environment: + \checkenv#1% + % + % As above, allow line break if we have multiple x headers in a row. + % It's not a great place, though. + \ifnum\lastpenalty=10002 \penalty3000 \fi + % + % And now, it's time to reuse the body of the original defun: + \expandafter\gobbledefun#1% +} +\def\gobbledefun#1\startdefun{} + +% \printdefunline \deffnheader{text} +% +\def\printdefunline#1#2{% + \begingroup + % call \deffnheader: + #1#2 \endheader + % common ending: + \interlinepenalty = 10000 + \advance\rightskip by 0pt plus 1fil + \endgraf + \nobreak\vskip -\parskip + \penalty 10002 % signal to \startdefun and \dodefunx + % Some of the @defun-type tags do not enable magic parentheses, + % rendering the following check redundant. But we don't optimize. + \checkparencounts + \endgroup +} + +\def\Edefun{\endgraf\medbreak} + +% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; +% the only thing remainnig is to define \deffnheader. +% +\def\makedefun#1{% + \expandafter\let\csname E#1\endcsname = \Edefun + \edef\temp{\noexpand\domakedefun + \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% + \temp +} + +% \domakedefun \deffn \deffnx \deffnheader +% +% Define \deffn and \deffnx, without parameters. +% \deffnheader has to be defined explicitly. +% +\def\domakedefun#1#2#3{% + \envdef#1{% + \startdefun + \parseargusing\activeparens{\printdefunline#3}% + }% + \def#2{\dodefunx#1}% + \def#3% +} + +%%% Untyped functions: + +% @deffn category name args +\makedefun{deffn}{\deffngeneral{}} + +% @deffn category class name args +\makedefun{defop}#1 {\defopon{#1\ \putwordon}} + +% \defopon {category on}class name args +\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } + +% \deffngeneral {subind}category name args +% +\def\deffngeneral#1#2 #3 #4\endheader{% + % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. + \dosubind{fn}{\code{#3}}{#1}% + \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% +} + +%%% Typed functions: + +% @deftypefn category type name args +\makedefun{deftypefn}{\deftypefngeneral{}} + +% @deftypeop category class type name args +\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} + +% \deftypeopon {category on}class type name args +\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } + +% \deftypefngeneral {subind}category type name args +% +\def\deftypefngeneral#1#2 #3 #4 #5\endheader{% + \dosubind{fn}{\code{#4}}{#1}% + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +} + +%%% Typed variables: + +% @deftypevr category type var args +\makedefun{deftypevr}{\deftypecvgeneral{}} + +% @deftypecv category class type var args +\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} + +% \deftypecvof {category of}class type var args +\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } + +% \deftypecvgeneral {subind}category type var args +% +\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% + \dosubind{vr}{\code{#4}}{#1}% + \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +} + +%%% Untyped variables: + +% @defvr category var args +\makedefun{defvr}#1 {\deftypevrheader{#1} {} } + +% @defcv category class var args +\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} + +% \defcvof {category of}class var args +\def\defcvof#1#2 {\deftypecvof{#1}#2 {} } + +%%% Type: +% @deftp category name args +\makedefun{deftp}#1 #2 #3\endheader{% + \doind{tp}{\code{#2}}% + \defname{#1}{}{#2}\defunargs{#3\unskip}% +} + +% Remaining @defun-like shortcuts: +\makedefun{defun}{\deffnheader{\putwordDeffunc} } +\makedefun{defmac}{\deffnheader{\putwordDefmac} } +\makedefun{defspec}{\deffnheader{\putwordDefspec} } +\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } +\makedefun{defvar}{\defvrheader{\putwordDefvar} } +\makedefun{defopt}{\defvrheader{\putwordDefopt} } +\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } +\makedefun{defmethod}{\defopon\putwordMethodon} +\makedefun{deftypemethod}{\deftypeopon\putwordMethodon} +\makedefun{defivar}{\defcvof\putwordInstanceVariableof} +\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} + +% \defname, which formats the name of the @def (not the args). +% #1 is the category, such as "Function". +% #2 is the return type, if any. +% #3 is the function name. +% +% We are followed by (but not passed) the arguments, if any. +% +\def\defname#1#2#3{% + % Get the values of \leftskip and \rightskip as they were outside the @def... + \advance\leftskip by -\defbodyindent + % + % How we'll format the type name. Putting it in brackets helps + % distinguish it from the body text that may end up on the next line + % just below it. + \def\temp{#1}% + \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} + % + % Figure out line sizes for the paragraph shape. + % The first line needs space for \box0; but if \rightskip is nonzero, + % we need only space for the part of \box0 which exceeds it: + \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip + % The continuations: + \dimen2=\hsize \advance\dimen2 by -\defargsindent + % (plain.tex says that \dimen1 should be used only as global.) + \parshape 2 0in \dimen0 \defargsindent \dimen2 + % + % Put the type name to the right margin. + \noindent + \hbox to 0pt{% + \hfil\box0 \kern-\hsize + % \hsize has to be shortened this way: + \kern\leftskip + % Intentionally do not respect \rightskip, since we need the space. + }% + % + % Allow all lines to be underfull without complaint: + \tolerance=10000 \hbadness=10000 + \exdentamount=\defbodyindent + {% + % defun fonts. We use typewriter by default (used to be bold) because: + % . we're printing identifiers, they should be in tt in principle. + % . in languages with many accents, such as Czech or French, it's + % common to leave accents off identifiers. The result looks ok in + % tt, but exceedingly strange in rm. + % . we don't want -- and --- to be treated as ligatures. + % . this still does not fix the ?` and !` ligatures, but so far no + % one has made identifiers using them :). + \df \tt + \def\temp{#2}% return value type + \ifx\temp\empty\else \tclose{\temp} \fi + #3% output function name + }% + {\rm\enskip}% hskip 0.5 em of \tenrm + % + \boldbrax + % arguments will be output next, if any. +} + +% Print arguments in slanted roman (not ttsl), inconsistently with using +% tt for the name. This is because literal text is sometimes needed in +% the argument list (groff manual), and ttsl and tt are not very +% distinguishable. Prevent hyphenation at `-' chars. +% +\def\defunargs#1{% + % use sl by default (not ttsl), + % tt for the names. + \df \sl \hyphenchar\font=0 + % + % On the other hand, if an argument has two dashes (for instance), we + % want a way to get ttsl. Let's try @var for that. + \let\var=\ttslanted + #1% + \sl\hyphenchar\font=45 +} + +% We want ()&[] to print specially on the defun line. +% +\def\activeparens{% + \catcode`\(=\active \catcode`\)=\active + \catcode`\[=\active \catcode`\]=\active + \catcode`\&=\active +} + +% Make control sequences which act like normal parenthesis chars. +\let\lparen = ( \let\rparen = ) + +% Be sure that we always have a definition for `(', etc. For example, +% if the fn name has parens in it, \boldbrax will not be in effect yet, +% so TeX would otherwise complain about undefined control sequence. +{ + \activeparens + \global\let(=\lparen \global\let)=\rparen + \global\let[=\lbrack \global\let]=\rbrack + \global\let& = \& + + \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + \gdef\magicamp{\let&=\amprm} +} + +\newcount\parencount + +% If we encounter &foo, then turn on ()-hacking afterwards +\newif\ifampseen +\def\amprm#1 {\ampseentrue{\bf\ }} + +\def\parenfont{% + \ifampseen + % At the first level, print parens in roman, + % otherwise use the default font. + \ifnum \parencount=1 \rm \fi + \else + % The \sf parens (in \boldbrax) actually are a little bolder than + % the contained text. This is especially needed for [ and ] . + \sf + \fi +} +\def\infirstlevel#1{% + \ifampseen + \ifnum\parencount=1 + #1% + \fi + \fi +} +\def\bfafterword#1 {#1 \bf} + +\def\opnr{% + \global\advance\parencount by 1 + {\parenfont(}% + \infirstlevel \bfafterword +} +\def\clnr{% + {\parenfont)}% + \infirstlevel \sl + \global\advance\parencount by -1 +} + +\newcount\brackcount +\def\lbrb{% + \global\advance\brackcount by 1 + {\bf[}% +} +\def\rbrb{% + {\bf]}% + \global\advance\brackcount by -1 +} + +\def\checkparencounts{% + \ifnum\parencount=0 \else \badparencount \fi + \ifnum\brackcount=0 \else \badbrackcount \fi +} +\def\badparencount{% + \errmessage{Unbalanced parentheses in @def}% + \global\parencount=0 +} +\def\badbrackcount{% + \errmessage{Unbalanced square braces in @def}% + \global\brackcount=0 +} + + +\message{macros,} +% @macro. + +% To do this right we need a feature of e-TeX, \scantokens, +% which we arrange to emulate with a temporary file in ordinary TeX. +\ifx\eTeXversion\undefined + \newwrite\macscribble + \def\scantokens#1{% + \toks0={#1}% + \immediate\openout\macscribble=\jobname.tmp + \immediate\write\macscribble{\the\toks0}% + \immediate\closeout\macscribble + \input \jobname.tmp + } +\fi + +\def\scanmacro#1{% + \begingroup + \newlinechar`\^^M + \let\xeatspaces\eatspaces + % Undo catcode changes of \startcontents and \doprintindex + % When called from @insertcopying or (short)caption, we need active + % backslash to get it printed correctly. Previously, we had + % \catcode`\\=\other instead. We'll see whether a problem appears + % with macro expansion. --kasal, 19aug04 + \catcode`\@=0 \catcode`\\=\active \escapechar=`\@ + % ... and \example + \spaceisspace + % + % Append \endinput to make sure that TeX does not see the ending newline. + % + % I've verified that it is necessary both for e-TeX and for ordinary TeX + % --kasal, 29nov03 + \scantokens{#1\endinput}% + \endgroup +} + +\def\scanexp#1{% + \edef\temp{\noexpand\scanmacro{#1}}% + \temp +} + +\newcount\paramno % Count of parameters +\newtoks\macname % Macro name +\newif\ifrecursive % Is it recursive? + +% List of all defined macros in the form +% \definedummyword\macro1\definedummyword\macro2... +% Currently is also contains all @aliases; the list can be split +% if there is a need. +\def\macrolist{} + +% Add the macro to \macrolist +\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname} +\def\addtomacrolistxxx#1{% + \toks0 = \expandafter{\macrolist\definedummyword#1}% + \xdef\macrolist{\the\toks0}% +} + +% Utility routines. +% This does \let #1 = #2, with \csnames; that is, +% \let \csname#1\endcsname = \csname#2\endcsname +% (except of course we have to play expansion games). +% +\def\cslet#1#2{% + \expandafter\let + \csname#1\expandafter\endcsname + \csname#2\endcsname +} + +% Trim leading and trailing spaces off a string. +% Concepts from aro-bend problem 15 (see CTAN). +{\catcode`\@=11 +\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} +\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} +\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} +\def\unbrace#1{#1} +\unbrace{\gdef\trim@@@ #1 } #2@{#1} +} + +% Trim a single trailing ^^M off a string. +{\catcode`\^^M=\other \catcode`\Q=3% +\gdef\eatcr #1{\eatcra #1Q^^MQ}% +\gdef\eatcra#1^^MQ{\eatcrb#1Q}% +\gdef\eatcrb#1Q#2Q{#1}% +} + +% Macro bodies are absorbed as an argument in a context where +% all characters are catcode 10, 11 or 12, except \ which is active +% (as in normal texinfo). It is necessary to change the definition of \. + +% It's necessary to have hard CRs when the macro is executed. This is +% done by making ^^M (\endlinechar) catcode 12 when reading the macro +% body, and then making it the \newlinechar in \scanmacro. + +\def\scanctxt{% + \catcode`\"=\other + \catcode`\+=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\@=\other + \catcode`\^=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\~=\other +} + +\def\scanargctxt{% + \scanctxt + \catcode`\\=\other + \catcode`\^^M=\other +} + +\def\macrobodyctxt{% + \scanctxt + \catcode`\{=\other + \catcode`\}=\other + \catcode`\^^M=\other + \usembodybackslash +} + +\def\macroargctxt{% + \scanctxt + \catcode`\\=\other +} + +% \mbodybackslash is the definition of \ in @macro bodies. +% It maps \foo\ => \csname macarg.foo\endcsname => #N +% where N is the macro parameter number. +% We define \csname macarg.\endcsname to be \realbackslash, so +% \\ in macro replacement text gets you a backslash. + +{\catcode`@=0 @catcode`@\=@active + @gdef@usembodybackslash{@let\=@mbodybackslash} + @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} +} +\expandafter\def\csname macarg.\endcsname{\realbackslash} + +\def\macro{\recursivefalse\parsearg\macroxxx} +\def\rmacro{\recursivetrue\parsearg\macroxxx} + +\def\macroxxx#1{% + \getargs{#1}% now \macname is the macname and \argl the arglist + \ifx\argl\empty % no arguments + \paramno=0% + \else + \expandafter\parsemargdef \argl;% + \fi + \if1\csname ismacro.\the\macname\endcsname + \message{Warning: redefining \the\macname}% + \else + \expandafter\ifx\csname \the\macname\endcsname \relax + \else \errmessage{Macro name \the\macname\space already defined}\fi + \global\cslet{macsave.\the\macname}{\the\macname}% + \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% + \addtomacrolist{\the\macname}% + \fi + \begingroup \macrobodyctxt + \ifrecursive \expandafter\parsermacbody + \else \expandafter\parsemacbody + \fi} + +\parseargdef\unmacro{% + \if1\csname ismacro.#1\endcsname + \global\cslet{#1}{macsave.#1}% + \global\expandafter\let \csname ismacro.#1\endcsname=0% + % Remove the macro name from \macrolist: + \begingroup + \expandafter\let\csname#1\endcsname \relax + \let\definedummyword\unmacrodo + \xdef\macrolist{\macrolist}% + \endgroup + \else + \errmessage{Macro #1 not defined}% + \fi +} + +% Called by \do from \dounmacro on each macro. The idea is to omit any +% macro definitions that have been changed to \relax. +% +\def\unmacrodo#1{% + \ifx #1\relax + % remove this + \else + \noexpand\definedummyword \noexpand#1% + \fi +} + +% This makes use of the obscure feature that if the last token of a +% <parameter list> is #, then the preceding argument is delimited by +% an opening brace, and that opening brace is not consumed. +\def\getargs#1{\getargsxxx#1{}} +\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} +\def\getmacname #1 #2\relax{\macname={#1}} +\def\getmacargs#1{\def\argl{#1}} + +% Parse the optional {params} list. Set up \paramno and \paramlist +% so \defmacro knows what to do. Define \macarg.blah for each blah +% in the params list, to be ##N where N is the position in that list. +% That gets used by \mbodybackslash (above). + +% We need to get `macro parameter char #' into several definitions. +% The technique used is stolen from LaTeX: let \hash be something +% unexpandable, insert that wherever you need a #, and then redefine +% it to # just before using the token list produced. +% +% The same technique is used to protect \eatspaces till just before +% the macro is used. + +\def\parsemargdef#1;{\paramno=0\def\paramlist{}% + \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} +\def\parsemargdefxxx#1,{% + \if#1;\let\next=\relax + \else \let\next=\parsemargdefxxx + \advance\paramno by 1% + \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname + {\xeatspaces{\hash\the\paramno}}% + \edef\paramlist{\paramlist\hash\the\paramno,}% + \fi\next} + +% These two commands read recursive and nonrecursive macro bodies. +% (They're different since rec and nonrec macros end differently.) + +\long\def\parsemacbody#1@end macro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% +\long\def\parsermacbody#1@end rmacro% +{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% + +% This defines the macro itself. There are six cases: recursive and +% nonrecursive macros of zero, one, and many arguments. +% Much magic with \expandafter here. +% \xdef is used so that macro definitions will survive the file +% they're defined in; @include reads the file inside a group. +\def\defmacro{% + \let\hash=##% convert placeholders to macro parameter chars + \ifrecursive + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\scanmacro{\temp}}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup\noexpand\scanmacro{\temp}}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{\egroup\noexpand\scanmacro{\temp}}% + \fi + \else + \ifcase\paramno + % 0 + \expandafter\xdef\csname\the\macname\endcsname{% + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \or % 1 + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \noexpand\braceorline + \expandafter\noexpand\csname\the\macname xxx\endcsname}% + \expandafter\xdef\csname\the\macname xxx\endcsname##1{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \else % many + \expandafter\xdef\csname\the\macname\endcsname{% + \bgroup\noexpand\macroargctxt + \expandafter\noexpand\csname\the\macname xx\endcsname}% + \expandafter\xdef\csname\the\macname xx\endcsname##1{% + \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% + \expandafter\expandafter + \expandafter\xdef + \expandafter\expandafter + \csname\the\macname xxx\endcsname + \paramlist{% + \egroup + \noexpand\norecurse{\the\macname}% + \noexpand\scanmacro{\temp}\egroup}% + \fi + \fi} + +\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} + +% \braceorline decides whether the next nonwhitespace character is a +% {. If so it reads up to the closing }, if not, it reads the whole +% line. Whatever was read is then fed to the next control sequence +% as an argument (by \parsebrace or \parsearg) +\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx} +\def\braceorlinexxx{% + \ifx\nchar\bgroup\else + \expandafter\parsearg + \fi \next} + + +% @alias. +% We need some trickery to remove the optional spaces around the equal +% sign. Just make them active and then expand them all to nothing. +\def\alias{\parseargusing\obeyspaces\aliasxxx} +\def\aliasxxx #1{\aliasyyy#1\relax} +\def\aliasyyy #1=#2\relax{% + {% + \expandafter\let\obeyedspace=\empty + \addtomacrolist{#1}% + \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% + }% + \next +} + + +\message{cross references,} + +\newwrite\auxfile + +\newif\ifhavexrefs % True if xref values are known. +\newif\ifwarnedxrefs % True if we warned once that they aren't known. + +% @inforef is relatively simple. +\def\inforef #1{\inforefzzz #1,,,,**} +\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, + node \samp{\ignorespaces#1{}}} + +% @node's only job in TeX is to define \lastnode, which is used in +% cross-references. The @node line might or might not have commas, and +% might or might not have spaces before the first comma, like: +% @node foo , bar , ... +% We don't want such trailing spaces in the node name. +% +\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} +% +% also remove a trailing comma, in case of something like this: +% @node Help-Cross, , , Cross-refs +\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} +\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} + +\let\nwnode=\node +\let\lastnode=\empty + +% Write a cross-reference definition for the current node. #1 is the +% type (Ynumbered, Yappendix, Ynothing). +% +\def\donoderef#1{% + \ifx\lastnode\empty\else + \setref{\lastnode}{#1}% + \global\let\lastnode=\empty + \fi +} + +% @anchor{NAME} -- define xref target at arbitrary point. +% +\newcount\savesfregister +% +\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} +\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} +\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} + +% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an +% anchor), which consists of three parts: +% 1) NAME-title - the current sectioning name taken from \thissection, +% or the anchor name. +% 2) NAME-snt - section number and type, passed as the SNT arg, or +% empty for anchors. +% 3) NAME-pg - the page number. +% +% This is called from \donoderef, \anchor, and \dofloat. In the case of +% floats, there is an additional part, which is not written here: +% 4) NAME-lof - the text as it should appear in a @listoffloats. +% +\def\setref#1#2{% + \pdfmkdest{#1}% + \iflinks + {% + \atdummies % preserve commands, but don't expand them + \edef\writexrdef##1##2{% + \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef + ##1}{##2}}% these are parameters of \writexrdef + }% + \toks0 = \expandafter{\thissection}% + \immediate \writexrdef{title}{\the\toks0 }% + \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. + \writexrdef{pg}{\folio}% will be written later, during \shipout + }% + \fi +} + +% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is +% the node name, #2 the name of the Info cross-reference, #3 the printed +% node name, #4 the name of the Info file, #5 the name of the printed +% manual. All but the node name can be omitted. +% +\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} +\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} +\def\ref#1{\xrefX[#1,,,,,,,]} +\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup + \unsepspaces + \def\printedmanual{\ignorespaces #5}% + \def\printedrefname{\ignorespaces #3}% + \setbox1=\hbox{\printedmanual\unskip}% + \setbox0=\hbox{\printedrefname\unskip}% + \ifdim \wd0 = 0pt + % No printed node name was explicitly given. + \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax + % Use the node name inside the square brackets. + \def\printedrefname{\ignorespaces #1}% + \else + % Use the actual chapter/section title appear inside + % the square brackets. Use the real section title if we have it. + \ifdim \wd1 > 0pt + % It is in another manual, so we don't have it. + \def\printedrefname{\ignorespaces #1}% + \else + \ifhavexrefs + % We know the real title if we have the xref values. + \def\printedrefname{\refx{#1-title}{}}% + \else + % Otherwise just copy the Info node name. + \def\printedrefname{\ignorespaces #1}% + \fi% + \fi + \fi + \fi + % + % Make link in pdf output. + \ifpdf + \leavevmode + \getfilename{#4}% + {\turnoffactive + % See comments at \activebackslashdouble. + {\activebackslashdouble \xdef\pdfxrefdest{#1}% + \backslashparens\pdfxrefdest}% + % + \ifnum\filenamelength>0 + \startlink attr{/Border [0 0 0]}% + goto file{\the\filename.pdf} name{\pdfxrefdest}% + \else + \startlink attr{/Border [0 0 0]}% + goto name{\pdfmkpgn{\pdfxrefdest}}% + \fi + }% + \linkcolor + \fi + % + % Float references are printed completely differently: "Figure 1.2" + % instead of "[somenode], p.3". We distinguish them by the + % LABEL-title being set to a magic string. + {% + % Have to otherify everything special to allow the \csname to + % include an _ in the xref name, etc. + \indexnofonts + \turnoffactive + \expandafter\global\expandafter\let\expandafter\Xthisreftitle + \csname XR#1-title\endcsname + }% + \iffloat\Xthisreftitle + % If the user specified the print name (third arg) to the ref, + % print it instead of our usual "Figure 1.2". + \ifdim\wd0 = 0pt + \refx{#1-snt}{}% + \else + \printedrefname + \fi + % + % if the user also gave the printed manual name (fifth arg), append + % "in MANUALNAME". + \ifdim \wd1 > 0pt + \space \putwordin{} \cite{\printedmanual}% + \fi + \else + % node/anchor (non-float) references. + % + % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not + % insert empty discretionaries after hyphens, which means that it will + % not find a line break at a hyphen in a node names. Since some manuals + % are best written with fairly long node names, containing hyphens, this + % is a loss. Therefore, we give the text of the node name again, so it + % is as if TeX is seeing it for the first time. + \ifdim \wd1 > 0pt + \putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}% + \else + % _ (for example) has to be the character _ for the purposes of the + % control sequence corresponding to the node, but it has to expand + % into the usual \leavevmode...\vrule stuff for purposes of + % printing. So we \turnoffactive for the \refx-snt, back on for the + % printing, back off for the \refx-pg. + {\turnoffactive + % Only output a following space if the -snt ref is nonempty; for + % @unnumbered and @anchor, it won't be. + \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% + \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi + }% + % output the `[mynode]' via a macro so it can be overridden. + \xrefprintnodename\printedrefname + % + % But we always want a comma and a space: + ,\space + % + % output the `page 3'. + \turnoffactive \putwordpage\tie\refx{#1-pg}{}% + \fi + \fi + \endlink +\endgroup} + +% This macro is called from \xrefX for the `[nodename]' part of xref +% output. It's a separate macro only so it can be changed more easily, +% since square brackets don't work well in some documents. Particularly +% one that Bob is working on :). +% +\def\xrefprintnodename#1{[#1]} + +% Things referred to by \setref. +% +\def\Ynothing{} +\def\Yomitfromtoc{} +\def\Ynumbered{% + \ifnum\secno=0 + \putwordChapter@tie \the\chapno + \else \ifnum\subsecno=0 + \putwordSection@tie \the\chapno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno + \else + \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} +\def\Yappendix{% + \ifnum\secno=0 + \putwordAppendix@tie @char\the\appendixno{}% + \else \ifnum\subsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno + \else \ifnum\subsubsecno=0 + \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno + \else + \putwordSection@tie + @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno + \fi\fi\fi +} + +% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. +% If its value is nonempty, SUFFIX is output afterward. +% +\def\refx#1#2{% + {% + \indexnofonts + \otherbackslash + \expandafter\global\expandafter\let\expandafter\thisrefX + \csname XR#1\endcsname + }% + \ifx\thisrefX\relax + % If not defined, say something at least. + \angleleft un\-de\-fined\angleright + \iflinks + \ifhavexrefs + \message{\linenumber Undefined cross reference `#1'.}% + \else + \ifwarnedxrefs\else + \global\warnedxrefstrue + \message{Cross reference values unknown; you must run TeX again.}% + \fi + \fi + \fi + \else + % It's defined, so just use it. + \thisrefX + \fi + #2% Output the suffix in any case. +} + +% This is the macro invoked by entries in the aux file. Usually it's +% just a \def (we prepend XR to the control sequence name to avoid +% collisions). But if this is a float type, we have more work to do. +% +\def\xrdef#1#2{% + \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value. + % + % Was that xref control sequence that we just defined for a float? + \expandafter\iffloat\csname XR#1\endcsname + % it was a float, and we have the (safe) float type in \iffloattype. + \expandafter\let\expandafter\floatlist + \csname floatlist\iffloattype\endcsname + % + % Is this the first time we've seen this float type? + \expandafter\ifx\floatlist\relax + \toks0 = {\do}% yes, so just \do + \else + % had it before, so preserve previous elements in list. + \toks0 = \expandafter{\floatlist\do}% + \fi + % + % Remember this xref in the control sequence \floatlistFLOATTYPE, + % for later use in \listoffloats. + \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}% + \fi +} + +% Read the last existing aux file, if any. No error if none exists. +% +\def\tryauxfile{% + \openin 1 \jobname.aux + \ifeof 1 \else + \readdatafile{aux}% + \global\havexrefstrue + \fi + \closein 1 +} + +\def\setupdatafile{% + \catcode`\^^@=\other + \catcode`\^^A=\other + \catcode`\^^B=\other + \catcode`\^^C=\other + \catcode`\^^D=\other + \catcode`\^^E=\other + \catcode`\^^F=\other + \catcode`\^^G=\other + \catcode`\^^H=\other + \catcode`\^^K=\other + \catcode`\^^L=\other + \catcode`\^^N=\other + \catcode`\^^P=\other + \catcode`\^^Q=\other + \catcode`\^^R=\other + \catcode`\^^S=\other + \catcode`\^^T=\other + \catcode`\^^U=\other + \catcode`\^^V=\other + \catcode`\^^W=\other + \catcode`\^^X=\other + \catcode`\^^Z=\other + \catcode`\^^[=\other + \catcode`\^^\=\other + \catcode`\^^]=\other + \catcode`\^^^=\other + \catcode`\^^_=\other + % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. + % in xref tags, i.e., node names. But since ^^e4 notation isn't + % supported in the main text, it doesn't seem desirable. Furthermore, + % that is not enough: for node names that actually contain a ^ + % character, we would end up writing a line like this: 'xrdef {'hat + % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first + % argument, and \hat is not an expandable control sequence. It could + % all be worked out, but why? Either we support ^^ or we don't. + % + % The other change necessary for this was to define \auxhat: + % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter + % and then to call \auxhat in \setq. + % + \catcode`\^=\other + % + % Special characters. Should be turned off anyway, but... + \catcode`\~=\other + \catcode`\[=\other + \catcode`\]=\other + \catcode`\"=\other + \catcode`\_=\other + \catcode`\|=\other + \catcode`\<=\other + \catcode`\>=\other + \catcode`\$=\other + \catcode`\#=\other + \catcode`\&=\other + \catcode`\%=\other + \catcode`+=\other % avoid \+ for paranoia even though we've turned it off + % + % This is to support \ in node names and titles, since the \ + % characters end up in a \csname. It's easier than + % leaving it active and making its active definition an actual \ + % character. What I don't understand is why it works in the *value* + % of the xrdef. Seems like it should be a catcode12 \, and that + % should not typeset properly. But it works, so I'm moving on for + % now. --karl, 15jan04. + \catcode`\\=\other + % + % Make the characters 128-255 be printing characters. + {% + \count1=128 + \def\loop{% + \catcode\count1=\other + \advance\count1 by 1 + \ifnum \count1<256 \loop \fi + }% + }% + % + % @ is our escape character in .aux files, and we need braces. + \catcode`\{=1 + \catcode`\}=2 + \catcode`\@=0 +} + +\def\readdatafile#1{% +\begingroup + \setupdatafile + \input\jobname.#1 +\endgroup} + +\message{insertions,} +% including footnotes. + +\newcount \footnoteno + +% The trailing space in the following definition for supereject is +% vital for proper filling; pages come out unaligned when you do a +% pagealignmacro call if that space before the closing brace is +% removed. (Generally, numeric constants should always be followed by a +% space to prevent strange expansion errors.) +\def\supereject{\par\penalty -20000\footnoteno =0 } + +% @footnotestyle is meaningful for info output only. +\let\footnotestyle=\comment + +{\catcode `\@=11 +% +% Auto-number footnotes. Otherwise like plain. +\gdef\footnote{% + \let\indent=\ptexindent + \let\noindent=\ptexnoindent + \global\advance\footnoteno by \@ne + \edef\thisfootno{$^{\the\footnoteno}$}% + % + % In case the footnote comes at the end of a sentence, preserve the + % extra spacing after we do the footnote number. + \let\@sf\empty + \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi + % + % Remove inadvertent blank space before typesetting the footnote number. + \unskip + \thisfootno\@sf + \dofootnote +}% + +% Don't bother with the trickery in plain.tex to not require the +% footnote text as a parameter. Our footnotes don't need to be so general. +% +% Oh yes, they do; otherwise, @ifset (and anything else that uses +% \parseargline) fails inside footnotes because the tokens are fixed when +% the footnote is read. --karl, 16nov96. +% +\gdef\dofootnote{% + \insert\footins\bgroup + % We want to typeset this text as a normal paragraph, even if the + % footnote reference occurs in (for example) a display environment. + % So reset some parameters. + \hsize=\pagewidth + \interlinepenalty\interfootnotelinepenalty + \splittopskip\ht\strutbox % top baseline for broken footnotes + \splitmaxdepth\dp\strutbox + \floatingpenalty\@MM + \leftskip\z@skip + \rightskip\z@skip + \spaceskip\z@skip + \xspaceskip\z@skip + \parindent\defaultparindent + % + \smallfonts \rm + % + % Because we use hanging indentation in footnotes, a @noindent appears + % to exdent this text, so make it be a no-op. makeinfo does not use + % hanging indentation so @noindent can still be needed within footnote + % text after an @example or the like (not that this is good style). + \let\noindent = \relax + % + % Hang the footnote text off the number. Use \everypar in case the + % footnote extends for more than one paragraph. + \everypar = {\hang}% + \textindent{\thisfootno}% + % + % Don't crash into the line above the footnote text. Since this + % expands into a box, it must come within the paragraph, lest it + % provide a place where TeX can split the footnote. + \footstrut + \futurelet\next\fo@t +} +}%end \catcode `\@=11 + +% In case a @footnote appears in a vbox, save the footnote text and create +% the real \insert just after the vbox finished. Otherwise, the insertion +% would be lost. +% Similarily, if a @footnote appears inside an alignment, save the footnote +% text to a box and make the \insert when a row of the table is finished. +% And the same can be done for other insert classes. --kasal, 16nov03. + +% Replace the \insert primitive by a cheating macro. +% Deeper inside, just make sure that the saved insertions are not spilled +% out prematurely. +% +\def\startsavinginserts{% + \ifx \insert\ptexinsert + \let\insert\saveinsert + \else + \let\checkinserts\relax + \fi +} + +% This \insert replacement works for both \insert\footins{foo} and +% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. +% +\def\saveinsert#1{% + \edef\next{\noexpand\savetobox \makeSAVEname#1}% + \afterassignment\next + % swallow the left brace + \let\temp = +} +\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} +\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} + +\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} + +\def\placesaveins#1{% + \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname + {\box#1}% +} + +% eat @SAVE -- beware, all of them have catcode \other: +{ + \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) + \gdef\gobblesave @SAVE{} +} + +% initialization: +\def\newsaveins #1{% + \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% + \next +} +\def\newsaveinsX #1{% + \csname newbox\endcsname #1% + \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts + \checksaveins #1}% +} + +% initialize: +\let\checkinserts\empty +\newsaveins\footins +\newsaveins\margin + + +% @image. We use the macros from epsf.tex to support this. +% If epsf.tex is not installed and @image is used, we complain. +% +% Check for and read epsf.tex up front. If we read it only at @image +% time, we might be inside a group, and then its definitions would get +% undone and the next image would fail. +\openin 1 = epsf.tex +\ifeof 1 \else + % Do not bother showing banner with epsf.tex v2.7k (available in + % doc/epsf.tex and on ctan). + \def\epsfannounce{\toks0 = }% + \input epsf.tex +\fi +\closein 1 +% +% We will only complain once about lack of epsf.tex. +\newif\ifwarnednoepsf +\newhelp\noepsfhelp{epsf.tex must be installed for images to + work. It is also included in the Texinfo distribution, or you can get + it from ftp://tug.org/tex/epsf.tex.} +% +\def\image#1{% + \ifx\epsfbox\undefined + \ifwarnednoepsf \else + \errhelp = \noepsfhelp + \errmessage{epsf.tex not found, images will be ignored}% + \global\warnednoepsftrue + \fi + \else + \imagexxx #1,,,,,\finish + \fi +} +% +% Arguments to @image: +% #1 is (mandatory) image filename; we tack on .eps extension. +% #2 is (optional) width, #3 is (optional) height. +% #4 is (ignored optional) html alt text. +% #5 is (ignored optional) extension. +% #6 is just the usual extra ignored arg for parsing this stuff. +\newif\ifimagevmode +\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup + \catcode`\^^M = 5 % in case we're inside an example + \normalturnoffactive % allow _ et al. in names + % If the image is by itself, center it. + \ifvmode + \imagevmodetrue + \nobreak\bigskip + % Usually we'll have text after the image which will insert + % \parskip glue, so insert it here too to equalize the space + % above and below. + \nobreak\vskip\parskip + \nobreak + \line\bgroup + \fi + % + % Output the image. + \ifpdf + \dopdfimage{#1}{#2}{#3}% + \else + % \epsfbox itself resets \epsf?size at each figure. + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi + \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi + \epsfbox{#1.eps}% + \fi + % + \ifimagevmode \egroup \bigbreak \fi % space after the image +\endgroup} + + +% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables, +% etc. We don't actually implement floating yet, we always include the +% float "here". But it seemed the best name for the future. +% +\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish} + +% There may be a space before second and/or third parameter; delete it. +\def\eatcommaspace#1, {#1,} + +% #1 is the optional FLOATTYPE, the text label for this float, typically +% "Figure", "Table", "Example", etc. Can't contain commas. If omitted, +% this float will not be numbered and cannot be referred to. +% +% #2 is the optional xref label. Also must be present for the float to +% be referable. +% +% #3 is the optional positioning argument; for now, it is ignored. It +% will somehow specify the positions allowed to float to (here, top, bottom). +% +% We keep a separate counter for each FLOATTYPE, which we reset at each +% chapter-level command. +\let\resetallfloatnos=\empty +% +\def\dofloat#1,#2,#3,#4\finish{% + \let\thiscaption=\empty + \let\thisshortcaption=\empty + % + % don't lose footnotes inside @float. + % + % BEWARE: when the floats start float, we have to issue warning whenever an + % insert appears inside a float which could possibly float. --kasal, 26may04 + % + \startsavinginserts + % + % We can't be used inside a paragraph. + \par + % + \vtop\bgroup + \def\floattype{#1}% + \def\floatlabel{#2}% + \def\floatloc{#3}% we do nothing with this yet. + % + \ifx\floattype\empty + \let\safefloattype=\empty + \else + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + \fi + % + % If label is given but no type, we handle that as the empty type. + \ifx\floatlabel\empty \else + % We want each FLOATTYPE to be numbered separately (Figure 1, + % Table 1, Figure 2, ...). (And if no label, no number.) + % + \expandafter\getfloatno\csname\safefloattype floatno\endcsname + \global\advance\floatno by 1 + % + {% + % This magic value for \thissection is output by \setref as the + % XREFLABEL-title value. \xrefX uses it to distinguish float + % labels (which have a completely different output format) from + % node and anchor labels. And \xrdef uses it to construct the + % lists of floats. + % + \edef\thissection{\floatmagic=\safefloattype}% + \setref{\floatlabel}{Yfloat}% + }% + \fi + % + % start with \parskip glue, I guess. + \vskip\parskip + % + % Don't suppress indentation if a float happens to start a section. + \restorefirstparagraphindent +} + +% we have these possibilities: +% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap +% @float Foo,lbl & no caption: Foo 1.1 +% @float Foo & @caption{Cap}: Foo: Cap +% @float Foo & no caption: Foo +% @float ,lbl & Caption{Cap}: 1.1: Cap +% @float ,lbl & no caption: 1.1 +% @float & @caption{Cap}: Cap +% @float & no caption: +% +\def\Efloat{% + \let\floatident = \empty + % + % In all cases, if we have a float type, it comes first. + \ifx\floattype\empty \else \def\floatident{\floattype}\fi + % + % If we have an xref label, the number comes next. + \ifx\floatlabel\empty \else + \ifx\floattype\empty \else % if also had float type, need tie first. + \appendtomacro\floatident{\tie}% + \fi + % the number. + \appendtomacro\floatident{\chaplevelprefix\the\floatno}% + \fi + % + % Start the printed caption with what we've constructed in + % \floatident, but keep it separate; we need \floatident again. + \let\captionline = \floatident + % + \ifx\thiscaption\empty \else + \ifx\floatident\empty \else + \appendtomacro\captionline{: }% had ident, so need a colon between + \fi + % + % caption text. + \appendtomacro\captionline{\scanexp\thiscaption}% + \fi + % + % If we have anything to print, print it, with space before. + % Eventually this needs to become an \insert. + \ifx\captionline\empty \else + \vskip.5\parskip + \captionline + % + % Space below caption. + \vskip\parskip + \fi + % + % If have an xref label, write the list of floats info. Do this + % after the caption, to avoid chance of it being a breakpoint. + \ifx\floatlabel\empty \else + % Write the text that goes in the lof to the aux file as + % \floatlabel-lof. Besides \floatident, we include the short + % caption if specified, else the full caption if specified, else nothing. + {% + \atdummies + % + % since we read the caption text in the macro world, where ^^M + % is turned into a normal character, we have to scan it back, so + % we don't write the literal three characters "^^M" into the aux file. + \scanexp{% + \xdef\noexpand\gtemp{% + \ifx\thisshortcaption\empty + \thiscaption + \else + \thisshortcaption + \fi + }% + }% + \immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident + \ifx\gtemp\empty \else : \gtemp \fi}}% + }% + \fi + \egroup % end of \vtop + % + % place the captured inserts + % + % BEWARE: when the floats start floating, we have to issue warning + % whenever an insert appears inside a float which could possibly + % float. --kasal, 26may04 + % + \checkinserts +} + +% Append the tokens #2 to the definition of macro #1, not expanding either. +% +\def\appendtomacro#1#2{% + \expandafter\def\expandafter#1\expandafter{#1#2}% +} + +% @caption, @shortcaption +% +\def\caption{\docaption\thiscaption} +\def\shortcaption{\docaption\thisshortcaption} +\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} +\def\defcaption#1#2{\egroup \def#1{#2}} + +% The parameter is the control sequence identifying the counter we are +% going to use. Create it if it doesn't exist and assign it to \floatno. +\def\getfloatno#1{% + \ifx#1\relax + % Haven't seen this figure type before. + \csname newcount\endcsname #1% + % + % Remember to reset this floatno at the next chap. + \expandafter\gdef\expandafter\resetallfloatnos + \expandafter{\resetallfloatnos #1=0 }% + \fi + \let\floatno#1% +} + +% \setref calls this to get the XREFLABEL-snt value. We want an @xref +% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we +% first read the @float command. +% +\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% + +% Magic string used for the XREFLABEL-title value, so \xrefX can +% distinguish floats from other xref types. +\def\floatmagic{!!float!!} + +% #1 is the control sequence we are passed; we expand into a conditional +% which is true if #1 represents a float ref. That is, the magic +% \thissection value which we \setref above. +% +\def\iffloat#1{\expandafter\doiffloat#1==\finish} +% +% #1 is (maybe) the \floatmagic string. If so, #2 will be the +% (safe) float type for this float. We set \iffloattype to #2. +% +\def\doiffloat#1=#2=#3\finish{% + \def\temp{#1}% + \def\iffloattype{#2}% + \ifx\temp\floatmagic +} + +% @listoffloats FLOATTYPE - print a list of floats like a table of contents. +% +\parseargdef\listoffloats{% + \def\floattype{#1}% floattype + {% + % the floattype might have accents or other special characters, + % but we need to use it in a control sequence name. + \indexnofonts + \turnoffactive + \xdef\safefloattype{\floattype}% + }% + % + % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. + \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax + \ifhavexrefs + % if the user said @listoffloats foo but never @float foo. + \message{\linenumber No `\safefloattype' floats to list.}% + \fi + \else + \begingroup + \leftskip=\tocindent % indent these entries like a toc + \let\do=\listoffloatsdo + \csname floatlist\safefloattype\endcsname + \endgroup + \fi +} + +% This is called on each entry in a list of floats. We're passed the +% xref label, in the form LABEL-title, which is how we save it in the +% aux file. We strip off the -title and look up \XRLABEL-lof, which +% has the text we're supposed to typeset here. +% +% Figures without xref labels will not be included in the list (since +% they won't appear in the aux file). +% +\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} +\def\listoffloatsdoentry#1-title\finish{{% + % Can't fully expand XR#1-lof because it can contain anything. Just + % pass the control sequence. On the other hand, XR#1-pg is just the + % page number, and we want to fully expand that so we can get a link + % in pdf output. + \toksA = \expandafter{\csname XR#1-lof\endcsname}% + % + % use the same \entry macro we use to generate the TOC and index. + \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% + \writeentry +}} + +\message{localization,} +% and i18n. + +% @documentlanguage is usually given very early, just after +% @setfilename. If done too late, it may not override everything +% properly. Single argument is the language abbreviation. +% It would be nice if we could set up a hyphenation file here. +% +\parseargdef\documentlanguage{% + \tex % read txi-??.tex file in plain TeX. + % Read the file if it exists. + \openin 1 txi-#1.tex + \ifeof 1 + \errhelp = \nolanghelp + \errmessage{Cannot read language file txi-#1.tex}% + \else + \input txi-#1.tex + \fi + \closein 1 + \endgroup +} +\newhelp\nolanghelp{The given language definition file cannot be found or +is empty. Maybe you need to install it? In the current directory +should work if nowhere else does.} + + +% @documentencoding should change something in TeX eventually, most +% likely, but for now just recognize it. +\let\documentencoding = \comment + + +% Page size parameters. +% +\newdimen\defaultparindent \defaultparindent = 15pt + +\chapheadingskip = 15pt plus 4pt minus 2pt +\secheadingskip = 12pt plus 3pt minus 2pt +\subsecheadingskip = 9pt plus 2pt minus 2pt + +% Prevent underfull vbox error messages. +\vbadness = 10000 + +% Don't be so finicky about underfull hboxes, either. +\hbadness = 2000 + +% Following George Bush, just get rid of widows and orphans. +\widowpenalty=10000 +\clubpenalty=10000 + +% Use TeX 3.0's \emergencystretch to help line breaking, but if we're +% using an old version of TeX, don't do anything. We want the amount of +% stretch added to depend on the line length, hence the dependence on +% \hsize. We call this whenever the paper size is set. +% +\def\setemergencystretch{% + \ifx\emergencystretch\thisisundefined + % Allow us to assign to \emergencystretch anyway. + \def\emergencystretch{\dimen0}% + \else + \emergencystretch = .15\hsize + \fi +} + +% Parameters in order: 1) textheight; 2) textwidth; +% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip; +% 7) physical page height; 8) physical page width. +% +% We also call \setleading{\textleading}, so the caller should define +% \textleading. The caller should also set \parskip. +% +\def\internalpagesizes#1#2#3#4#5#6#7#8{% + \voffset = #3\relax + \topskip = #6\relax + \splittopskip = \topskip + % + \vsize = #1\relax + \advance\vsize by \topskip + \outervsize = \vsize + \advance\outervsize by 2\topandbottommargin + \pageheight = \vsize + % + \hsize = #2\relax + \outerhsize = \hsize + \advance\outerhsize by 0.5in + \pagewidth = \hsize + % + \normaloffset = #4\relax + \bindingoffset = #5\relax + % + \ifpdf + \pdfpageheight #7\relax + \pdfpagewidth #8\relax + \fi + % + \setleading{\textleading} + % + \parindent = \defaultparindent + \setemergencystretch +} + +% @letterpaper (the default). +\def\letterpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % If page is nothing but text, make it come out even. + \internalpagesizes{46\baselineskip}{6in}% + {\voffset}{.25in}% + {\bindingoffset}{36pt}% + {11in}{8.5in}% +}} + +% Use @smallbook to reset parameters for 7x9.25 trim size. +\def\smallbook{{\globaldefs = 1 + \parskip = 2pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.5in}{5in}% + {\voffset}{.25in}% + {\bindingoffset}{16pt}% + {9.25in}{7in}% + % + \lispnarrowing = 0.3in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .5cm +}} + +% Use @smallerbook to reset parameters for 6x9 trim size. +% (Just testing, parameters still in flux.) +\def\smallerbook{{\globaldefs = 1 + \parskip = 1.5pt plus 1pt + \textleading = 12pt + % + \internalpagesizes{7.4in}{4.8in}% + {-.2in}{-.4in}% + {0pt}{14pt}% + {9in}{6in}% + % + \lispnarrowing = 0.25in + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = .4cm +}} + +% Use @afourpaper to print on European A4 paper. +\def\afourpaper{{\globaldefs = 1 + \parskip = 3pt plus 2pt minus 1pt + \textleading = 13.2pt + % + % Double-side printing via postscript on Laserjet 4050 + % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. + % To change the settings for a different printer or situation, adjust + % \normaloffset until the front-side and back-side texts align. Then + % do the same for \bindingoffset. You can set these for testing in + % your texinfo source file like this: + % @tex + % \global\normaloffset = -6mm + % \global\bindingoffset = 10mm + % @end tex + \internalpagesizes{51\baselineskip}{160mm} + {\voffset}{\hoffset}% + {\bindingoffset}{44pt}% + {297mm}{210mm}% + % + \tolerance = 700 + \hfuzz = 1pt + \contentsrightmargin = 0pt + \defbodyindent = 5mm +}} + +% Use @afivepaper to print on European A5 paper. +% From romildo@urano.iceb.ufop.br, 2 July 2000. +% He also recommends making @example and @lisp be small. +\def\afivepaper{{\globaldefs = 1 + \parskip = 2pt plus 1pt minus 0.1pt + \textleading = 12.5pt + % + \internalpagesizes{160mm}{120mm}% + {\voffset}{\hoffset}% + {\bindingoffset}{8pt}% + {210mm}{148mm}% + % + \lispnarrowing = 0.2in + \tolerance = 800 + \hfuzz = 1.2pt + \contentsrightmargin = 0pt + \defbodyindent = 2mm + \tableindent = 12mm +}} + +% A specific text layout, 24x15cm overall, intended for A4 paper. +\def\afourlatex{{\globaldefs = 1 + \afourpaper + \internalpagesizes{237mm}{150mm}% + {\voffset}{4.6mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + % + % Must explicitly reset to 0 because we call \afourpaper. + \globaldefs = 0 +}} + +% Use @afourwide to print on A4 paper in landscape format. +\def\afourwide{{\globaldefs = 1 + \afourpaper + \internalpagesizes{241mm}{165mm}% + {\voffset}{-2.95mm}% + {\bindingoffset}{7mm}% + {297mm}{210mm}% + \globaldefs = 0 +}} + +% @pagesizes TEXTHEIGHT[,TEXTWIDTH] +% Perhaps we should allow setting the margins, \topskip, \parskip, +% and/or leading, also. Or perhaps we should compute them somehow. +% +\parseargdef\pagesizes{\pagesizesyyy #1,,\finish} +\def\pagesizesyyy#1,#2,#3\finish{{% + \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi + \globaldefs = 1 + % + \parskip = 3pt plus 2pt minus 1pt + \setleading{\textleading}% + % + \dimen0 = #1 + \advance\dimen0 by \voffset + % + \dimen2 = \hsize + \advance\dimen2 by \normaloffset + % + \internalpagesizes{#1}{\hsize}% + {\voffset}{\normaloffset}% + {\bindingoffset}{44pt}% + {\dimen0}{\dimen2}% +}} + +% Set default to letter. +% +\letterpaper + + +\message{and turning on texinfo input format.} + +% Define macros to output various characters with catcode for normal text. +\catcode`\"=\other +\catcode`\~=\other +\catcode`\^=\other +\catcode`\_=\other +\catcode`\|=\other +\catcode`\<=\other +\catcode`\>=\other +\catcode`\+=\other +\catcode`\$=\other +\def\normaldoublequote{"} +\def\normaltilde{~} +\def\normalcaret{^} +\def\normalunderscore{_} +\def\normalverticalbar{|} +\def\normalless{<} +\def\normalgreater{>} +\def\normalplus{+} +\def\normaldollar{$}%$ font-lock fix + +% This macro is used to make a character print one way in \tt +% (where it can probably be output as-is), and another way in other fonts, +% where something hairier probably needs to be done. +% +% #1 is what to print if we are indeed using \tt; #2 is what to print +% otherwise. Since all the Computer Modern typewriter fonts have zero +% interword stretch (and shrink), and it is reasonable to expect all +% typewriter fonts to have this, we can check that font parameter. +% +\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} + +% Same as above, but check for italic font. Actually this also catches +% non-italic slanted fonts since it is impossible to distinguish them from +% italic fonts. But since this is only used by $ and it uses \sl anyway +% this is not a problem. +\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} + +% Turn off all special characters except @ +% (and those which the user can use as if they were ordinary). +% Most of these we simply print from the \tt font, but for some, we can +% use math or other variants that look better in normal text. + +\catcode`\"=\active +\def\activedoublequote{{\tt\char34}} +\let"=\activedoublequote +\catcode`\~=\active +\def~{{\tt\char126}} +\chardef\hat=`\^ +\catcode`\^=\active +\def^{{\tt \hat}} + +\catcode`\_=\active +\def_{\ifusingtt\normalunderscore\_} +\let\realunder=_ +% Subroutine for the previous macro. +\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } + +\catcode`\|=\active +\def|{{\tt\char124}} +\chardef \less=`\< +\catcode`\<=\active +\def<{{\tt \less}} +\chardef \gtr=`\> +\catcode`\>=\active +\def>{{\tt \gtr}} +\catcode`\+=\active +\def+{{\tt \char 43}} +\catcode`\$=\active +\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix + +% If a .fmt file is being used, characters that might appear in a file +% name cannot be active until we have parsed the command line. +% So turn them off again, and have \everyjob (or @setfilename) turn them on. +% \otherifyactive is called near the end of this file. +\def\otherifyactive{\catcode`+=\other \catcode`\_=\other} + +% Used sometimes to turn off (effectively) the active characters even after +% parsing them. +\def\turnoffactive{% + \normalturnoffactive + \otherbackslash +} + +\catcode`\@=0 + +% \backslashcurfont outputs one backslash character in current font, +% as in \char`\\. +\global\chardef\backslashcurfont=`\\ +\global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work + +% \realbackslash is an actual character `\' with catcode other, and +% \doublebackslash is two of them (for the pdf outlines). +{\catcode`\\=\other @gdef@realbackslash{\} @gdef@doublebackslash{\\}} + +% In texinfo, backslash is an active character; it prints the backslash +% in fixed width font. +\catcode`\\=\active +@def@normalbackslash{{@tt@backslashcurfont}} +% On startup, @fixbackslash assigns: +% @let \ = @normalbackslash + +% \rawbackslash defines an active \ to do \backslashcurfont. +% \otherbackslash defines an active \ to be a literal `\' character with +% catcode other. +@gdef@rawbackslash{@let\=@backslashcurfont} +@gdef@otherbackslash{@let\=@realbackslash} + +% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of +% the literal character `\'. +% +@def@normalturnoffactive{% + @let\=@normalbackslash + @let"=@normaldoublequote + @let~=@normaltilde + @let^=@normalcaret + @let_=@normalunderscore + @let|=@normalverticalbar + @let<=@normalless + @let>=@normalgreater + @let+=@normalplus + @let$=@normaldollar %$ font-lock fix + @unsepspaces +} + +% Make _ and + \other characters, temporarily. +% This is canceled by @fixbackslash. +@otherifyactive + +% If a .fmt file is being used, we don't want the `\input texinfo' to show up. +% That is what \eatinput is for; after that, the `\' should revert to printing +% a backslash. +% +@gdef@eatinput input texinfo{@fixbackslash} +@global@let\ = @eatinput + +% On the other hand, perhaps the file did not have a `\input texinfo'. Then +% the first `\' in the file would cause an error. This macro tries to fix +% that, assuming it is called before the first `\' could plausibly occur. +% Also turn back on active characters that might appear in the input +% file name, in case not using a pre-dumped format. +% +@gdef@fixbackslash{% + @ifx\@eatinput @let\ = @normalbackslash @fi + @catcode`+=@active + @catcode`@_=@active +} + +% Say @foo, not \foo, in error messages. +@escapechar = `@@ + +% These look ok in all fonts, so just make them not special. +@catcode`@& = @other +@catcode`@# = @other +@catcode`@% = @other + + +@c Local variables: +@c eval: (add-hook 'write-file-hooks 'time-stamp) +@c page-delimiter: "^\\\\message" +@c time-stamp-start: "def\\\\texinfoversion{" +@c time-stamp-format: "%:y-%02m-%02d.%02H" +@c time-stamp-end: "}" +@c End: + +@c vim:sw=2: + +@ignore + arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 +@end ignore
diff --git a/e2fsck/CHANGES b/e2fsck/CHANGES new file mode 100644 index 0000000..fa135b6 --- /dev/null +++ b/e2fsck/CHANGES
@@ -0,0 +1,53 @@ +[tytso:19940101.1200EST] + +Add new options -l and -L, to append to and modify the bad-blocks list. + +Fix bugs in bad-block cloning. + +[tytso:19931230.1832EST] + +Clean up e2fsck and library to be clean even when compiling with full +warnings enabled. + +Make e2fsck deal with zero-length directories correctly. + +Deleted inodes from old ext2fs code (inodes with dtime set but +non-zero link count) are detected, and the user is given the +opportunity to clear them. + +The last bit in the last group of the block bitmap badding was not +being checked; now fixed. + +The free_blocks and free_inodes count in the last group weren't being +checked. Now fixed. + +[tytso:19931101.0007EST] + +Fixed bugs with root reallocation; previously the parent pointers in +the dirinfo structure would get corrupted, causing many different '..' +links to be wrong. Also, the inode link count for the root directory +wasn't always being set correctly. (All of this would be fixed on +the second e2fsck, however). + +Fixed to recognize filesystem corruption caused by mke2fs 0.2b (where +/ and /lost+found had non-zero dtime entries). Offers to fix /'s +dtime entry. + +e2fsck will now expand the /lost+found directory if it runs out of room. + +Fixed dependency on BLOCK_SIZE in pass2. e2fsck will now handle 4k +filesystems w/o problems. + +e2fsck will now move bad blocks found in the inode bitmaps, block +bitmaps, and in the inode tables. (Can't handle bad blocks found in +the superblock and the group descriptors.) (Doesn't update alternate +superblocks, group descriptors.) + +e2fsck now supports the -b option, to allow a user to specify an +alternate superblock. + +The -B option now specifies the blocksize of the filesystem. (If not +specified, and the -b option is specified, e2fsck will attempt to +search through various blocksizes to find the correct one.) + +Added manual page.
diff --git a/e2fsck/Makefile.in b/e2fsck/Makefile.in new file mode 100644 index 0000000..b1ce222 --- /dev/null +++ b/e2fsck/Makefile.in
@@ -0,0 +1,556 @@ +# +# Makefile for e2fsck +# + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +top_builddir = .. +my_dir = e2fsck +INSTALL = @INSTALL@ + +@MCONFIG@ + +PROGS= e2fsck +MANPAGES= e2fsck.8 +FMANPAGES= e2fsck.conf.5 + +LIBS= $(LIBQUOTA) $(LIBEXT2FS) $(LIBCOM_ERR) $(LIBBLKID) $(LIBUUID) \ + $(LIBINTL) $(LIBE2P) $(SYSLIBS) +DEPLIBS= $(DEPLIBQUOTA) $(LIBEXT2FS) $(DEPLIBCOM_ERR) $(DEPLIBBLKID) \ + $(DEPLIBUUID) $(DEPLIBE2P) + +STATIC_LIBS= $(STATIC_LIBQUOTA) $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) \ + $(STATIC_LIBBLKID) $(STATIC_LIBUUID) $(LIBINTL) $(STATIC_LIBE2P) \ + $(SYSLIBS) +STATIC_DEPLIBS= $(DEPSTATIC_LIBQUOTA) $(STATIC_LIBEXT2FS) \ + $(DEPSTATIC_LIBCOM_ERR) $(DEPSTATIC_LIBBLKID) \ + $(DEPSTATIC_LIBUUID) $(DEPSTATIC_LIBE2P) + +PROFILED_LIBS= $(PROFILED_LIBQUOTA) $(PROFILED_LIBEXT2FS) \ + $(PROFILED_LIBCOM_ERR) $(PROFILED_LIBBLKID) $(PROFILED_LIBUUID) \ + $(PROFILED_LIBE2P) $(LIBINTL) $(SYSLIBS) +PROFILED_DEPLIBS= $(DEPPROFILED_LIBQUOTA) $(PROFILED_LIBEXT2FS) \ + $(DEPPROFILED_LIBCOM_ERR) $(DEPPROFILED_LIBBLKID) \ + $(DEPPROFILED_LIBUUID) $(DEPPROFILED_LIBE2P) + +COMPILE_ET=$(top_builddir)/lib/et/compile_et --build-tree + +.c.o: + $(E) " CC $<" + $(Q) $(CC) -c $(ALL_CFLAGS) $< -o $@ + $(Q) $(CHECK_CMD) $(ALL_CFLAGS) $< +@PROFILE_CMT@ $(Q) $(CC) $(ALL_CFLAGS) -g -pg -o profiled/$*.o -c $< + +# +# Flags for doing mtrace --- uncomment to produce mtracing e2fsck +# Note: The optimization flags must include -g +# +#MTRACE= -DMTRACE +#MTRACE_OBJ= mtrace.o +#MTRACE_SRC= $(srcdir)/mtrace.c +#OPT= -g + +# +# Flags for doing mcheck --- uncomment to produce mchecking e2fsck +# Note: The optimization flags must include -g +# +#MCHECK= -DMCHECK + +OBJS= crc32.o dict.o unix.o e2fsck.o super.o pass1.o pass1b.o pass2.o \ + pass3.o pass4.o pass5.o journal.o badblocks.o util.o dirinfo.o \ + dx_dirinfo.o ehandler.o problem.o message.o quota.o recovery.o \ + region.o revoke.o ea_refcount.o rehash.o profile.o prof_err.o \ + logfile.o sigcatcher.o $(MTRACE_OBJ) + +PROFILED_OBJS= profiled/dict.o profiled/unix.o profiled/e2fsck.o \ + profiled/super.o profiled/pass1.o profiled/pass1b.o \ + profiled/pass2.o profiled/pass3.o profiled/pass4.o profiled/pass5.o \ + profiled/journal.o profiled/badblocks.o profiled/util.o \ + profiled/dirinfo.o profiled/dx_dirinfo.o profiled/ehandler.o \ + profiled/message.o profiled/problem.o profiled/quota.o \ + profiled/recovery.o profiled/region.o profiled/revoke.o \ + profiled/ea_refcount.o profiled/rehash.o profiled/profile.o \ + profiled/crc32.o profiled/prof_err.o profiled/logfile.o \ + profiled/sigcatcher.o + +SRCS= $(srcdir)/e2fsck.c \ + $(srcdir)/crc32.c \ + $(srcdir)/gen_crc32table.c \ + $(srcdir)/dict.c \ + $(srcdir)/super.c \ + $(srcdir)/pass1.c \ + $(srcdir)/pass1b.c \ + $(srcdir)/pass2.c \ + $(srcdir)/pass3.c \ + $(srcdir)/pass4.c \ + $(srcdir)/pass5.c \ + $(srcdir)/journal.c \ + $(srcdir)/recovery.c \ + $(srcdir)/revoke.c \ + $(srcdir)/badblocks.c \ + $(srcdir)/util.c \ + $(srcdir)/unix.c \ + $(srcdir)/dirinfo.c \ + $(srcdir)/dx_dirinfo.c \ + $(srcdir)/ehandler.c \ + $(srcdir)/problem.c \ + $(srcdir)/message.c \ + $(srcdir)/ea_refcount.c \ + $(srcdir)/rehash.c \ + $(srcdir)/region.c \ + $(srcdir)/profile.c \ + $(srcdir)/sigcatcher.c \ + $(srcdir)/logfile.c \ + prof_err.c \ + $(srcdir)/quota.c \ + $(MTRACE_SRC) + +all:: profiled $(PROGS) e2fsck $(MANPAGES) $(FMANPAGES) + +@PROFILE_CMT@all:: e2fsck.profiled + +prof_err.c prof_err.h: prof_err.et + $(E) " COMPILE_ET prof_err.et" + $(Q) $(COMPILE_ET) $(srcdir)/prof_err.et + +e2fsck: $(OBJS) $(DEPLIBS) + $(E) " LD $@" + $(Q) $(LD) $(ALL_LDFLAGS) $(RDYNAMIC) -o e2fsck $(OBJS) $(LIBS) + +e2fsck.static: $(OBJS) $(STATIC_DEPLIBS) + $(E) " LD $@" + $(Q) $(LD) $(LDFLAGS_STATIC) -o e2fsck.static $(OBJS) $(STATIC_LIBS) + +e2fsck.profiled: $(OBJS) $(PROFILED_DEPLIBS) + $(E) " LD $@" + $(Q) $(LD) $(ALL_LDFLAGS) -g -pg -o e2fsck.profiled $(PROFILED_OBJS) \ + $(PROFILED_LIBS) + +gen_crc32table: $(srcdir)/gen_crc32table.c + $(E) " CC $@" + $(Q) $(BUILD_CC) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o gen_crc32table \ + $(srcdir)/gen_crc32table.c + +crc32table.h: gen_crc32table + $(E) " GEN32TABLE $@" + $(Q) ./gen_crc32table > crc32table.h + +tst_sigcatcher: $(srcdir)/sigcatcher.c sigcatcher.o + $(E) " CC $@" + $(Q) $(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(RDYNAMIC) \ + $(srcdir)/sigcatcher.c -DDEBUG -o tst_sigcatcher + +tst_problem: $(srcdir)/problem.c $(srcdir)/problem.h $(LIBEXT2FS) \ + $(DEPLIBCOM_ERR) + $(Q) $(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o tst_problem \ + $(srcdir)/problem.c -DUNITTEST $(LIBEXT2FS) $(LIBCOM_ERR) \ + $(LIBINTL) $(SYSLIBS) + +tst_crc32: $(srcdir)/crc32.c $(LIBEXT2FS) $(DEPLIBCOM_ERR) + $(Q) $(CC) $(ALL_LDFLAGS) $(ALL_CFLAGS) -o tst_crc32 $(srcdir)/crc32.c \ + -DUNITTEST $(LIBEXT2FS) $(LIBCOM_ERR) $(SYSLIBS) + +tst_refcount: ea_refcount.c $(DEPLIBCOM_ERR) + $(E) " LD $@" + $(Q) $(CC) -o tst_refcount $(srcdir)/ea_refcount.c \ + $(ALL_CFLAGS) $(ALL_LDFLAGS) -DTEST_PROGRAM \ + $(LIBCOM_ERR) $(LIBEXT2FS) $(SYSLIBS) + +tst_logfile: $(srcdir)/logfile.c + $(E) " LD $@" + $(Q) $(CC) -o tst_logfile $(srcdir)/logfile.c \ + $(ALL_CFLAGS) $(ALL_LDFLAGS) -DTEST_PROGRAM $(SYSLIBS) + +tst_region: region.c $(DEPLIBCOM_ERR) + $(E) " LD $@" + $(Q) $(CC) -o tst_region $(srcdir)/region.c \ + $(ALL_CFLAGS) $(ALL_LDFLAGS) -DTEST_PROGRAM \ + $(LIBCOM_ERR) $(SYSLIBS) + +check:: tst_refcount tst_region tst_crc32 tst_problem + $(TESTENV) ./tst_refcount + $(TESTENV) ./tst_region + $(TESTENV) ./tst_crc32 + $(TESTENV) ./tst_problem + +extend: extend.o + $(E) " LD $@" + $(Q) $(LD) $(ALL_LDFLAGS) -o extend extend.o $(CHECKLIB) + +flushb: flushb.o + $(E) " LD $@" + $(Q) $(LD) $(ALL_LDFLAGS) -o flushb flushb.o $(CHECKLIB) + +iscan: iscan.o util.o ehandler.o $(DEPLIBS) + $(E) " LD $@" + $(Q) $(LD) $(ALL_LDFLAGS) -o iscan iscan.o util.o ehandler.o $(LIBS) + +test_profile: $(srcdir)/profile.c profile_helpers.o argv_parse.o \ + prof_err.o profile.h $(DEPSTATIC_LIBCOM_ERR) + $(E) " LD $@" + $(Q) $(CC) -o test_profile -DDEBUG_PROGRAM $(srcdir)/profile.c prof_err.o \ + profile_helpers.o argv_parse.o $(STATIC_LIBCOM_ERR) \ + $(ALL_CFLAGS) + +profiled: +@PROFILE_CMT@ $(E) " MKDIR $@" +@PROFILE_CMT@ $(Q) mkdir profiled + +e2fsck.8: $(DEP_SUBSTITUTE) $(srcdir)/e2fsck.8.in + $(E) " SUBST $@" + $(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2fsck.8.in e2fsck.8 + +e2fsck.conf.5: $(DEP_SUBSTITUTE) $(srcdir)/e2fsck.conf.5.in + $(E) " SUBST $@" + $(Q) $(SUBSTITUTE_UPTIME) $(srcdir)/e2fsck.conf.5.in e2fsck.conf.5 + +installdirs: + $(E) " MKINSTALLDIRS $(root_sbindir) $(man8dir)" + $(Q) $(MKINSTALLDIRS) $(DESTDIR)$(root_sbindir) \ + $(DESTDIR)$(man8dir) $(DESTDIR)$(man5dir) + +install: $(PROGS) $(MANPAGES) $(FMANPAGES) installdirs + $(Q) for i in $(PROGS); do \ + $(ES) " INSTALL $(root_sbindir)/$$i"; \ + $(INSTALL_PROGRAM) $$i $(DESTDIR)$(root_sbindir)/$$i; \ + done + $(Q) for i in ext2 ext3 ext4 ext4dev; do \ + $(ES) " LINK $(root_sbindir)/fsck.$$i"; \ + (cd $(DESTDIR)$(root_sbindir); \ + $(LN) $(LINK_INSTALL_FLAGS) e2fsck fsck.$$i); \ + done + $(Q) for i in $(MANPAGES); do \ + for j in $(COMPRESS_EXT); do \ + $(RM) -f $(DESTDIR)$(man8dir)/$$i.$$j; \ + done; \ + $(ES) " INSTALL_DATA $(man8dir)/$$i"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(man8dir)/$$i; \ + done + $(Q) for i in $(FMANPAGES); do \ + for j in $(COMPRESS_EXT); do \ + $(RM) -f $(DESTDIR)$(man5dir)/$$i.$$j; \ + done; \ + $(ES) " INSTALL_DATA $(man5dir)/$$i"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(man5dir)/$$i; \ + done + $(Q) for i in ext2 ext3 ext4 ext4dev; do \ + $(ES) " LINK $(man8dir)/fsck.$$i.8"; \ + (cd $(DESTDIR)$(man8dir); \ + $(LN) $(LINK_INSTALL_FLAGS) e2fsck.8 fsck.$$i.8); \ + done + +install-strip: install + $(Q) for i in $(PROGS); do \ + $(ES) " STRIP $(root_sbindir)/$$i"; \ + $(STRIP) $(DESTDIR)$(root_sbindir)/$$i; \ + done + +uninstall: + for i in $(PROGS); do \ + $(RM) -f $(DESTDIR)$(root_sbindir)/$$i; \ + done + $(RM) -f $(DESTDIR)$(root_sbindir)/fsck.ext2 \ + $(DESTDIR)$(root_sbindir)/fsck.ext3 \ + $(DESTDIR)$(root_sbindir)/fsck.ext4 \ + $(DESTDIR)$(root_sbindir)/fsck.ext4dev + for i in $(MANPAGES); do \ + $(RM) -f $(DESTDIR)$(man8dir)/$$i; \ + done + for i in $(FMANPAGES); do \ + $(RM) -f $(DESTDIR)$(man5dir)/$$i; \ + done + $(RM) -f $(DESTDIR)$(root_sbindir)/fsck.ext2 \ + $(DESTDIR)$(root_sbindir)/fsck.ext3 \ + $(DESTDIR)$(root_sbindir)/fsck.ext4 \ + $(DESTDIR)$(root_sbindir)/fsck.ext4dev + +clean:: + $(RM) -f $(PROGS) \#* *\# *.s *.o *.a *~ core e2fsck.static \ + e2fsck.shared e2fsck.profiled flushb e2fsck.8 \ + tst_problem tst_crc32 tst_region tst_refcount gen_crc32table \ + crc32table.h e2fsck.conf.5 prof_err.c prof_err.h \ + test_profile + $(RM) -rf profiled + +mostlyclean: clean +distclean: clean + $(RM) -f .depend Makefile $(srcdir)/TAGS $(srcdir)/Makefile.in.old + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# +e2fsck.o: $(srcdir)/e2fsck.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h +crc32.o: $(srcdir)/crc32.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/crc32defs.h crc32table.h +gen_crc32table.o: $(srcdir)/gen_crc32table.c $(srcdir)/crc32defs.h +dict.o: $(srcdir)/dict.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/dict.h +super.o: $(srcdir)/super.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h +pass1.o: $(srcdir)/pass1.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h +pass1b.o: $(srcdir)/pass1b.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ + $(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h $(srcdir)/dict.h +pass2.o: $(srcdir)/pass2.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h $(srcdir)/dict.h +pass3.o: $(srcdir)/pass3.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h +pass4.o: $(srcdir)/pass4.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h +pass5.o: $(srcdir)/pass5.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h +journal.o: $(srcdir)/journal.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \ + $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h \ + $(srcdir)/problem.h +recovery.o: $(srcdir)/recovery.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \ + $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h +revoke.o: $(srcdir)/revoke.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/jfs_user.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/lib/ext2fs/kernel-jbd.h \ + $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h +badblocks.o: $(srcdir)/badblocks.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/e2fsck.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ + $(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h +util.o: $(srcdir)/util.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h +unix.o: $(srcdir)/unix.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/e2p/e2p.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/et/com_err.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h \ + $(top_srcdir)/version.h +dirinfo.o: $(srcdir)/dirinfo.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(top_srcdir)/lib/ext2fs/tdb.h +dx_dirinfo.o: $(srcdir)/dx_dirinfo.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h +ehandler.o: $(srcdir)/ehandler.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h +problem.o: $(srcdir)/problem.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h $(srcdir)/problemP.h +message.o: $(srcdir)/message.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h +ea_refcount.o: $(srcdir)/ea_refcount.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h +rehash.o: $(srcdir)/rehash.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h +region.o: $(srcdir)/region.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h +profile.o: $(srcdir)/profile.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/profile.h prof_err.h +sigcatcher.o: $(srcdir)/sigcatcher.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h +logfile.o: $(srcdir)/logfile.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h +prof_err.o: prof_err.c +quota.o: $(srcdir)/quota.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2fsck.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext3_extents.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/profile.h prof_err.h $(top_srcdir)/lib/quota/quotaio.h \ + $(top_srcdir)/lib/quota/dqblk_v2.h $(top_srcdir)/lib/quota/quotaio_tree.h \ + $(top_srcdir)/lib/../e2fsck/dict.h $(srcdir)/problem.h
diff --git a/e2fsck/argv_parse.c b/e2fsck/argv_parse.c new file mode 100644 index 0000000..d22f634 --- /dev/null +++ b/e2fsck/argv_parse.c
@@ -0,0 +1,166 @@ +/* + * argv_parse.c --- utility function for parsing a string into a + * argc, argv array. + * + * This file defines a function argv_parse() which parsing a + * passed-in string, handling double quotes and backslashes, and + * creates an allocated argv vector which can be freed using the + * argv_free() function. + * + * See argv_parse.h for the formal definition of the functions. + * + * Copyright 1999 by Theodore Ts'o. + * + * Permission to use, copy, modify, and distribute this software for + * any purpose with or without fee is hereby granted, provided that + * the above copyright notice and this permission notice appear in all + * copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE + * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't + * it sick that the U.S. culture of lawsuit-happy lawyers requires + * this kind of disclaimer?) + * + * Version 1.1, modified 2/27/1999 + */ + +#include "config.h" +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#include <ctype.h> +#include <string.h> +#include "argv_parse.h" + +#define STATE_WHITESPACE 1 +#define STATE_TOKEN 2 +#define STATE_QUOTED 3 + +/* + * Returns 0 on success, -1 on failure. + */ +int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv) +{ + int argc = 0, max_argc = 0; + char **argv, **new_argv, *buf, ch; + char *cp = 0, *outcp = 0; + int state = STATE_WHITESPACE; + + buf = malloc(strlen(in_buf)+1); + if (!buf) + return -1; + + max_argc = 0; argc = 0; argv = 0; + outcp = buf; + for (cp = in_buf; (ch = *cp); cp++) { + if (state == STATE_WHITESPACE) { + if (isspace((int) ch)) + continue; + /* Not whitespace, so start a new token */ + state = STATE_TOKEN; + if (argc >= max_argc) { + max_argc += 3; + new_argv = realloc(argv, + (max_argc+1)*sizeof(char *)); + if (!new_argv) { + free(argv); + free(buf); + return -1; + } + argv = new_argv; + } + argv[argc++] = outcp; + } + if (state == STATE_QUOTED) { + if (ch == '"') + state = STATE_TOKEN; + else + *outcp++ = ch; + continue; + } + /* Must be processing characters in a word */ + if (isspace((int) ch)) { + /* + * Terminate the current word and start + * looking for the beginning of the next word. + */ + *outcp++ = 0; + state = STATE_WHITESPACE; + continue; + } + if (ch == '"') { + state = STATE_QUOTED; + continue; + } + if (ch == '\\') { + ch = *++cp; + switch (ch) { + case '\0': + ch = '\\'; cp--; break; + case 'n': + ch = '\n'; break; + case 't': + ch = '\t'; break; + case 'b': + ch = '\b'; break; + } + } + *outcp++ = ch; + } + if (state != STATE_WHITESPACE) + *outcp++ = '\0'; + if (argv == 0) { + argv = malloc(sizeof(char *)); + free(buf); + } + argv[argc] = 0; + if (ret_argc) + *ret_argc = argc; + if (ret_argv) + *ret_argv = argv; + return 0; +} + +void argv_free(char **argv) +{ + free(*argv); + free(argv); +} + +#ifdef DEBUG +/* + * For debugging + */ + +#include <stdio.h> + +int main(int argc, char **argv) +{ + int ac, ret; + char **av, **cpp; + char buf[256]; + + while (!feof(stdin)) { + if (fgets(buf, sizeof(buf), stdin) == NULL) + break; + ret = argv_parse(buf, &ac, &av); + if (ret != 0) { + printf("Argv_parse returned %d!\n", ret); + continue; + } + printf("Argv_parse returned %d arguments...\n", ac); + for (cpp = av; *cpp; cpp++) { + if (cpp != av) + printf(", "); + printf("'%s'", *cpp); + } + printf("\n"); + argv_free(av); + } + exit(0); +} +#endif /* DEBUG */
diff --git a/e2fsck/argv_parse.h b/e2fsck/argv_parse.h new file mode 100644 index 0000000..86f4564 --- /dev/null +++ b/e2fsck/argv_parse.h
@@ -0,0 +1,43 @@ +/* + * argv_parse.h --- header file for the argv parser. + * + * This file defines the interface for the functions argv_parse() and + * argv_free(). + * + *********************************************************************** + * int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv) + * + * This function takes as its first argument a string which it will + * parse into an argv argument vector, with each white-space separated + * word placed into its own slot in the argv. This function handles + * double quotes and backslashes so that the parsed words can contain + * special characters. The count of the number words found in the + * parsed string, as well as the argument vector, are returned into + * ret_argc and ret_argv, respectively. + *********************************************************************** + * extern void argv_free(char **argv); + * + * This function frees the argument vector created by argv_parse(). + *********************************************************************** + * + * Copyright 1999 by Theodore Ts'o. + * + * Permission to use, copy, modify, and distribute this software for + * any purpose with or without fee is hereby granted, provided that + * the above copyright notice and this permission notice appear in all + * copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE + * AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't + * it sick that the U.S. culture of lawsuit-happy lawyers requires + * this kind of disclaimer?) + * + * Version 1.1, modified 2/27/1999 + */ + +extern int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv); +extern void argv_free(char **argv);
diff --git a/e2fsck/badblocks.c b/e2fsck/badblocks.c new file mode 100644 index 0000000..7f3641b --- /dev/null +++ b/e2fsck/badblocks.c
@@ -0,0 +1,141 @@ +/* + * badblocks.c --- replace/append bad blocks to the bad block inode + * + * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be + * redistributed under the terms of the GNU Public License. + */ + +#include "config.h" +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#include <et/com_err.h> +#include "e2fsck.h" + +static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt, + void *priv_data); + + +static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk) +{ + printf(_("Bad block %u out of range; ignored.\n"), blk); + return; +} + +void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file, + int replace_bad_blocks) +{ + ext2_filsys fs = ctx->fs; + errcode_t retval; + badblocks_list bb_list = 0; + FILE *f; + char buf[1024]; + + e2fsck_read_bitmaps(ctx); + + /* + * Make sure the bad block inode is sane. If there are any + * illegal blocks, clear them. + */ + retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0, + check_bb_inode_blocks, 0); + if (retval) { + com_err("ext2fs_block_iterate", retval, "%s", + _("while sanity checking the bad blocks inode")); + goto fatal; + } + + /* + * If we're appending to the bad blocks inode, read in the + * current bad blocks. + */ + if (!replace_bad_blocks) { + retval = ext2fs_read_bb_inode(fs, &bb_list); + if (retval) { + com_err("ext2fs_read_bb_inode", retval, "%s", + _("while reading the bad blocks inode")); + goto fatal; + } + } + + /* + * Now read in the bad blocks from the file; if + * bad_blocks_file is null, then try to run the badblocks + * command. + */ + if (bad_blocks_file) { + f = fopen(bad_blocks_file, "r"); + if (!f) { + com_err("read_bad_blocks_file", errno, + _("while trying to open %s"), bad_blocks_file); + goto fatal; + } + } else { + sprintf(buf, "badblocks -b %d -X %s%s%s %llu", fs->blocksize, + (ctx->options & E2F_OPT_PREEN) ? "" : "-s ", + (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "", + fs->device_name, ext2fs_blocks_count(fs->super)-1); + f = popen(buf, "r"); + if (!f) { + com_err("read_bad_blocks_file", errno, + _("while trying popen '%s'"), buf); + goto fatal; + } + } + retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block); + if (bad_blocks_file) + fclose(f); + else + pclose(f); + if (retval) { + com_err("ext2fs_read_bb_FILE", retval, "%s", + _("while reading in list of bad blocks from file")); + goto fatal; + } + + /* + * Finally, update the bad blocks from the bad_block_map + */ + printf("%s: Updating bad block inode.\n", ctx->device_name); + retval = ext2fs_update_bb_inode(fs, bb_list); + if (retval) { + com_err("ext2fs_update_bb_inode", retval, "%s", + _("while updating bad block inode")); + goto fatal; + } + + ext2fs_badblocks_list_free(bb_list); + return; + +fatal: + ctx->flags |= E2F_FLAG_ABORT; + if (bb_list) + ext2fs_badblocks_list_free(bb_list); + return; + +} + +static int check_bb_inode_blocks(ext2_filsys fs, + blk_t *block_nr, + int blockcnt EXT2FS_ATTR((unused)), + void *priv_data EXT2FS_ATTR((unused))) +{ + if (!*block_nr) + return 0; + + /* + * If the block number is outrageous, clear it and ignore it. + */ + if (*block_nr >= ext2fs_blocks_count(fs->super) || + *block_nr < fs->super->s_first_data_block) { + printf(_("Warning: illegal block %u found in bad block inode. " + "Cleared.\n"), *block_nr); + *block_nr = 0; + return BLOCK_CHANGED; + } + + return 0; +} +
diff --git a/e2fsck/crc32.c b/e2fsck/crc32.c new file mode 100644 index 0000000..0497a38 --- /dev/null +++ b/e2fsck/crc32.c
@@ -0,0 +1,570 @@ +/* + * crc32.c --- CRC32 function + * + * Copyright (C) 2008 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +/* + * Oct 15, 2000 Matt Domsch <Matt_Domsch@dell.com> + * Nicer crc32 functions/docs submitted by linux@horizon.com. Thanks! + * Code was from the public domain, copyright abandoned. Code was + * subsequently included in the kernel, thus was re-licensed under the + * GNU GPL v2. + * + * Oct 12, 2000 Matt Domsch <Matt_Domsch@dell.com> + * Same crc32 function was used in 5 other places in the kernel. + * I made one version, and deleted the others. + * There are various incantations of crc32(). Some use a seed of 0 or ~0. + * Some xor at the end with ~0. The generic crc32() function takes + * seed as an argument, and doesn't xor at the end. Then individual + * users can do whatever they need. + * drivers/net/smc9194.c uses seed ~0, doesn't xor with ~0. + * fs/jffs2 uses seed 0, doesn't xor with ~0. + * fs/partitions/efi.c uses seed ~0, xor's with ~0. + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include "config.h" +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> + +#ifdef UNITTEST +#undef ENABLE_NLS +#endif +#include "e2fsck.h" + +#include "crc32defs.h" +#if CRC_LE_BITS == 8 +#define tole(x) __constant_cpu_to_le32(x) +#define tobe(x) __constant_cpu_to_be32(x) +#else +#define tole(x) (x) +#define tobe(x) (x) +#endif +#include "crc32table.h" + +#ifdef UNITTEST + +/** + * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32 + * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for + * other uses, or the previous crc32 value if computing incrementally. + * @p: pointer to buffer over which CRC is run + * @len: length of buffer @p + */ +__u32 crc32_le(__u32 crc, unsigned char const *p, size_t len); + +#if CRC_LE_BITS == 1 +/* + * In fact, the table-based code will work in this case, but it can be + * simplified by inlining the table in ?: form. + */ + +__u32 crc32_le(__u32 crc, unsigned char const *p, size_t len) +{ + int i; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); + } + return crc; +} +#else /* Table-based approach */ + +__u32 crc32_le(__u32 crc, unsigned char const *p, size_t len) +{ +# if CRC_LE_BITS == 8 + const __u32 *b =(__u32 *)p; + const __u32 *tab = crc32table_le; + +# ifdef WORDS_BIGENDIAN +# define DO_CRC(x) crc = tab[ ((crc >> 24) ^ (x)) & 255] ^ (crc<<8) +# else +# define DO_CRC(x) crc = tab[ (crc ^ (x)) & 255 ] ^ (crc>>8) +# endif + + crc = __cpu_to_le32(crc); + /* Align it */ + if(unlikely(((long)b)&3 && len)){ + do { + __u8 *p = (__u8 *)b; + DO_CRC(*p++); + b = (void *)p; + } while ((--len) && ((long)b)&3 ); + } + if(likely(len >= 4)){ + /* load data 32 bits wide, xor data 32 bits wide. */ + size_t save_len = len & 3; + len = len >> 2; + --b; /* use pre increment below(*++b) for speed */ + do { + crc ^= *++b; + DO_CRC(0); + DO_CRC(0); + DO_CRC(0); + DO_CRC(0); + } while (--len); + b++; /* point to next byte(s) */ + len = save_len; + } + /* And the last few bytes */ + if(len){ + do { + __u8 *p = (__u8 *)b; + DO_CRC(*p++); + b = (void *)p; + } while (--len); + } + + return __le32_to_cpu(crc); +#undef ENDIAN_SHIFT +#undef DO_CRC + +# elif CRC_LE_BITS == 4 + while (len--) { + crc ^= *p++; + crc = (crc >> 4) ^ crc32table_le[crc & 15]; + crc = (crc >> 4) ^ crc32table_le[crc & 15]; + } + return crc; +# elif CRC_LE_BITS == 2 + while (len--) { + crc ^= *p++; + crc = (crc >> 2) ^ crc32table_le[crc & 3]; + crc = (crc >> 2) ^ crc32table_le[crc & 3]; + crc = (crc >> 2) ^ crc32table_le[crc & 3]; + crc = (crc >> 2) ^ crc32table_le[crc & 3]; + } + return crc; +# endif +} +#endif + +#endif /* UNITTEST */ + +/** + * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32 + * @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for + * other uses, or the previous crc32 value if computing incrementally. + * @p: pointer to buffer over which CRC is run + * @len: length of buffer @p + */ +__u32 crc32_be(__u32 crc, unsigned char const *p, size_t len); + +#if CRC_BE_BITS == 1 +/* + * In fact, the table-based code will work in this case, but it can be + * simplified by inlining the table in ?: form. + */ + +__u32 crc32_be(__u32 crc, unsigned char const *p, size_t len) +{ + int i; + while (len--) { + crc ^= *p++ << 24; + for (i = 0; i < 8; i++) + crc = + (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : + 0); + } + return crc; +} + +#else /* Table-based approach */ +__u32 crc32_be(__u32 crc, unsigned char const *p, size_t len) +{ +# if CRC_BE_BITS == 8 + const __u32 *b =(const __u32 *)p; + const __u32 *tab = crc32table_be; + +# ifdef WORDS_BIGENDIAN +# define DO_CRC(x) crc = tab[ ((crc >> 24) ^ (x)) & 255] ^ (crc<<8) +# else +# define DO_CRC(x) crc = tab[ (crc ^ (x)) & 255 ] ^ (crc>>8) +# endif + + crc = __cpu_to_be32(crc); + /* Align it */ + if(unlikely(((long)b)&3 && len)){ + do { + const __u8 *q = (const __u8 *)b; + DO_CRC(*q++); + b = (const __u32 *)q; + } while ((--len) && ((long)b)&3 ); + } + if(likely(len >= 4)){ + /* load data 32 bits wide, xor data 32 bits wide. */ + size_t save_len = len & 3; + len = len >> 2; + --b; /* use pre increment below(*++b) for speed */ + do { + crc ^= *++b; + DO_CRC(0); + DO_CRC(0); + DO_CRC(0); + DO_CRC(0); + } while (--len); + b++; /* point to next byte(s) */ + len = save_len; + } + /* And the last few bytes */ + if(len){ + do { + const __u8 *q = (const __u8 *)b; + DO_CRC(*q++); + b = (const void *)q; + } while (--len); + } + return __be32_to_cpu(crc); +#undef ENDIAN_SHIFT +#undef DO_CRC + +# elif CRC_BE_BITS == 4 + while (len--) { + crc ^= *p++ << 24; + crc = (crc << 4) ^ crc32table_be[crc >> 28]; + crc = (crc << 4) ^ crc32table_be[crc >> 28]; + } + return crc; +# elif CRC_BE_BITS == 2 + while (len--) { + crc ^= *p++ << 24; + crc = (crc << 2) ^ crc32table_be[crc >> 30]; + crc = (crc << 2) ^ crc32table_be[crc >> 30]; + crc = (crc << 2) ^ crc32table_be[crc >> 30]; + crc = (crc << 2) ^ crc32table_be[crc >> 30]; + } + return crc; +# endif +} +#endif + +/* + * A brief CRC tutorial. + * + * A CRC is a long-division remainder. You add the CRC to the message, + * and the whole thing (message+CRC) is a multiple of the given + * CRC polynomial. To check the CRC, you can either check that the + * CRC matches the recomputed value, *or* you can check that the + * remainder computed on the message+CRC is 0. This latter approach + * is used by a lot of hardware implementations, and is why so many + * protocols put the end-of-frame flag after the CRC. + * + * It's actually the same long division you learned in school, except that + * - We're working in binary, so the digits are only 0 and 1, and + * - When dividing polynomials, there are no carries. Rather than add and + * subtract, we just xor. Thus, we tend to get a bit sloppy about + * the difference between adding and subtracting. + * + * A 32-bit CRC polynomial is actually 33 bits long. But since it's + * 33 bits long, bit 32 is always going to be set, so usually the CRC + * is written in hex with the most significant bit omitted. (If you're + * familiar with the IEEE 754 floating-point format, it's the same idea.) + * + * Note that a CRC is computed over a string of *bits*, so you have + * to decide on the endianness of the bits within each byte. To get + * the best error-detecting properties, this should correspond to the + * order they're actually sent. For example, standard RS-232 serial is + * little-endian; the most significant bit (sometimes used for parity) + * is sent last. And when appending a CRC word to a message, you should + * do it in the right order, matching the endianness. + * + * Just like with ordinary division, the remainder is always smaller than + * the divisor (the CRC polynomial) you're dividing by. Each step of the + * division, you take one more digit (bit) of the dividend and append it + * to the current remainder. Then you figure out the appropriate multiple + * of the divisor to subtract to being the remainder back into range. + * In binary, it's easy - it has to be either 0 or 1, and to make the + * XOR cancel, it's just a copy of bit 32 of the remainder. + * + * When computing a CRC, we don't care about the quotient, so we can + * throw the quotient bit away, but subtract the appropriate multiple of + * the polynomial from the remainder and we're back to where we started, + * ready to process the next bit. + * + * A big-endian CRC written this way would be coded like: + * for (i = 0; i < input_bits; i++) { + * multiple = remainder & 0x80000000 ? CRCPOLY : 0; + * remainder = (remainder << 1 | next_input_bit()) ^ multiple; + * } + * Notice how, to get at bit 32 of the shifted remainder, we look + * at bit 31 of the remainder *before* shifting it. + * + * But also notice how the next_input_bit() bits we're shifting into + * the remainder don't actually affect any decision-making until + * 32 bits later. Thus, the first 32 cycles of this are pretty boring. + * Also, to add the CRC to a message, we need a 32-bit-long hole for it at + * the end, so we have to add 32 extra cycles shifting in zeros at the + * end of every message, + * + * So the standard trick is to rearrage merging in the next_input_bit() + * until the moment it's needed. Then the first 32 cycles can be precomputed, + * and merging in the final 32 zero bits to make room for the CRC can be + * skipped entirely. + * This changes the code to: + * for (i = 0; i < input_bits; i++) { + * remainder ^= next_input_bit() << 31; + * multiple = (remainder & 0x80000000) ? CRCPOLY : 0; + * remainder = (remainder << 1) ^ multiple; + * } + * With this optimization, the little-endian code is simpler: + * for (i = 0; i < input_bits; i++) { + * remainder ^= next_input_bit(); + * multiple = (remainder & 1) ? CRCPOLY : 0; + * remainder = (remainder >> 1) ^ multiple; + * } + * + * Note that the other details of endianness have been hidden in CRCPOLY + * (which must be bit-reversed) and next_input_bit(). + * + * However, as long as next_input_bit is returning the bits in a sensible + * order, we can actually do the merging 8 or more bits at a time rather + * than one bit at a time: + * for (i = 0; i < input_bytes; i++) { + * remainder ^= next_input_byte() << 24; + * for (j = 0; j < 8; j++) { + * multiple = (remainder & 0x80000000) ? CRCPOLY : 0; + * remainder = (remainder << 1) ^ multiple; + * } + * } + * Or in little-endian: + * for (i = 0; i < input_bytes; i++) { + * remainder ^= next_input_byte(); + * for (j = 0; j < 8; j++) { + * multiple = (remainder & 1) ? CRCPOLY : 0; + * remainder = (remainder << 1) ^ multiple; + * } + * } + * If the input is a multiple of 32 bits, you can even XOR in a 32-bit + * word at a time and increase the inner loop count to 32. + * + * You can also mix and match the two loop styles, for example doing the + * bulk of a message byte-at-a-time and adding bit-at-a-time processing + * for any fractional bytes at the end. + * + * The only remaining optimization is to the byte-at-a-time table method. + * Here, rather than just shifting one bit of the remainder to decide + * in the correct multiple to subtract, we can shift a byte at a time. + * This produces a 40-bit (rather than a 33-bit) intermediate remainder, + * but again the multiple of the polynomial to subtract depends only on + * the high bits, the high 8 bits in this case. + * + * The multiple we need in that case is the low 32 bits of a 40-bit + * value whose high 8 bits are given, and which is a multiple of the + * generator polynomial. This is simply the CRC-32 of the given + * one-byte message. + * + * Two more details: normally, appending zero bits to a message which + * is already a multiple of a polynomial produces a larger multiple of that + * polynomial. To enable a CRC to detect this condition, it's common to + * invert the CRC before appending it. This makes the remainder of the + * message+crc come out not as zero, but some fixed non-zero value. + * + * The same problem applies to zero bits prepended to the message, and + * a similar solution is used. Instead of starting with a remainder of + * 0, an initial remainder of all ones is used. As long as you start + * the same way on decoding, it doesn't make a difference. + */ + +#ifdef UNITTEST + +#include <stdlib.h> +#include <stdio.h> + +const __u8 byte_rev_table[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; + +static inline __u8 bitrev8(__u8 byte) +{ + return byte_rev_table[byte]; +} + +static inline __u16 bitrev16(__u16 x) +{ + return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8); +} + +/** + * bitrev32 - reverse the order of bits in a u32 value + * @x: value to be bit-reversed + */ +static __u32 bitrev32(__u32 x) +{ + return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16); +} + +#if 0 /*Not used at present */ + +static void +buf_dump(char const *prefix, unsigned char const *buf, size_t len) +{ + fputs(prefix, stdout); + while (len--) + printf(" %02x", *buf++); + putchar('\n'); + +} +#endif + +static void bytereverse(unsigned char *buf, size_t len) +{ + while (len--) { + unsigned char x = bitrev8(*buf); + *buf++ = x; + } +} + +static void random_garbage(unsigned char *buf, size_t len) +{ + while (len--) + *buf++ = (unsigned char) random(); +} + +#if 0 /* Not used at present */ +static void store_le(__u32 x, unsigned char *buf) +{ + buf[0] = (unsigned char) x; + buf[1] = (unsigned char) (x >> 8); + buf[2] = (unsigned char) (x >> 16); + buf[3] = (unsigned char) (x >> 24); +} +#endif + +static void store_be(__u32 x, unsigned char *buf) +{ + buf[0] = (unsigned char) (x >> 24); + buf[1] = (unsigned char) (x >> 16); + buf[2] = (unsigned char) (x >> 8); + buf[3] = (unsigned char) x; +} + +/* + * This checks that CRC(buf + CRC(buf)) = 0, and that + * CRC commutes with bit-reversal. This has the side effect + * of bytewise bit-reversing the input buffer, and returns + * the CRC of the reversed buffer. + */ +static __u32 test_step(__u32 init, unsigned char *buf, size_t len) +{ + __u32 crc1, crc2; + size_t i; + + crc1 = crc32_be(init, buf, len); + store_be(crc1, buf + len); + crc2 = crc32_be(init, buf, len + 4); + if (crc2) + printf("\nCRC cancellation fail: 0x%08x should be 0\n", + crc2); + + for (i = 0; i <= len + 4; i++) { + crc2 = crc32_be(init, buf, i); + crc2 = crc32_be(crc2, buf + i, len + 4 - i); + if (crc2) + printf("\nCRC split fail: 0x%08x\n", crc2); + } + + /* Now swap it around for the other test */ + + bytereverse(buf, len + 4); + init = bitrev32(init); + crc2 = bitrev32(crc1); + if (crc1 != bitrev32(crc2)) + printf("\nBit reversal fail: 0x%08x -> 0x%08x -> 0x%08x\n", + crc1, crc2, bitrev32(crc2)); + crc1 = crc32_le(init, buf, len); + if (crc1 != crc2) + printf("\nCRC endianness fail: 0x%08x != 0x%08x\n", crc1, + crc2); + crc2 = crc32_le(init, buf, len + 4); + if (crc2) + printf("\nCRC cancellation fail: 0x%08x should be 0\n", + crc2); + + for (i = 0; i <= len + 4; i++) { + crc2 = crc32_le(init, buf, i); + crc2 = crc32_le(crc2, buf + i, len + 4 - i); + if (crc2) + printf("\nCRC split fail: 0x%08x\n", crc2); + } + + return crc1; +} + +#define SIZE 64 +#define INIT1 0 +#define INIT2 0 + +int main(int argc, char **argv) +{ + unsigned char buf1[SIZE + 4]; + unsigned char buf2[SIZE + 4]; + unsigned char buf3[SIZE + 4]; + int i, j; + __u32 crc1, crc2, crc3; + int exit_status = 0; + + for (i = 0; i <= SIZE; i++) { + printf("\rTesting length %d...", i); + fflush(stdout); + random_garbage(buf1, i); + random_garbage(buf2, i); + for (j = 0; j < i; j++) + buf3[j] = buf1[j] ^ buf2[j]; + + crc1 = test_step(INIT1, buf1, i); + crc2 = test_step(INIT2, buf2, i); + /* Now check that CRC(buf1 ^ buf2) = CRC(buf1) ^ CRC(buf2) */ + crc3 = test_step(INIT1 ^ INIT2, buf3, i); + if (crc3 != (crc1 ^ crc2)) { + printf("CRC XOR fail: 0x%08x != 0x%08x ^ 0x%08x\n", + crc3, crc1, crc2); + exit_status++; + } + } + printf("\nAll test complete. No failures expected.\n"); + return 0; +} + +#endif /* UNITTEST */
diff --git a/e2fsck/crc32defs.h b/e2fsck/crc32defs.h new file mode 100644 index 0000000..27414d2 --- /dev/null +++ b/e2fsck/crc32defs.h
@@ -0,0 +1,64 @@ +/* + * There are multiple 16-bit CRC polynomials in common use, but this is + * *the* standard CRC-32 polynomial, first popularized by Ethernet. + * x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 + */ +#define CRCPOLY_LE 0xedb88320 +#define CRCPOLY_BE 0x04c11db7 + +/* How many bits at a time to use. Requires a table of 4<<CRC_xx_BITS bytes. */ +/* For less performance-sensitive, use 4 */ +#ifndef CRC_LE_BITS +# define CRC_LE_BITS 8 +#endif +#ifndef CRC_BE_BITS +# define CRC_BE_BITS 8 +#endif + +/* + * Little-endian CRC computation. Used with serial bit streams sent + * lsbit-first. Be sure to use cpu_to_le32() to append the computed CRC. + */ +#if CRC_LE_BITS > 8 || CRC_LE_BITS < 1 || CRC_LE_BITS & CRC_LE_BITS-1 +# error CRC_LE_BITS must be a power of 2 between 1 and 8 +#endif + +/* + * Big-endian CRC computation. Used with serial bit streams sent + * msbit-first. Be sure to use cpu_to_be32() to append the computed CRC. + */ +#if CRC_BE_BITS > 8 || CRC_BE_BITS < 1 || CRC_BE_BITS & CRC_BE_BITS-1 +# error CRC_BE_BITS must be a power of 2 between 1 and 8 +#endif + +#define ___constant_swab32(x) \ + ((__u32)( \ + (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) + + +#ifdef WORDS_BIGENDIAN +#define __constant_cpu_to_le32(x) ___constant_swab32((x)) +#define __constant_cpu_to_be32(x) (x) +#define __be32_to_cpu(x) (x) +#define __cpu_to_be32(x) (x) +#define __cpu_to_le32(x) (ext2fs_swab32((x))) +#define __le32_to_cpu(x) (ext2fs_swab32((x))) +#else +#define __constant_cpu_to_le32(x) (x) +#define __constant_cpu_to_be32(x) ___constant_swab32((x)) +#define __be32_to_cpu(x) (ext2fs_swab32((x))) +#define __cpu_to_be32(x) (ext2fs_swab32((x))) +#define __cpu_to_le32(x) (x) +#define __le32_to_cpu(x) (x) +#endif + +#if (__GNUC__ >= 3) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif
diff --git a/e2fsck/dict.c b/e2fsck/dict.c new file mode 100644 index 0000000..90c4d84 --- /dev/null +++ b/e2fsck/dict.c
@@ -0,0 +1,1522 @@ +/* + * Dictionary Abstract Data Type + * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net> + * + * Free Software License: + * + * All rights are reserved by the author, with the following exceptions: + * Permission is granted to freely reproduce and distribute this software, + * possibly in exchange for a fee, provided that this copyright notice appears + * intact. Permission is also granted to adapt this software to produce + * derivative works, as long as the modified versions carry this copyright + * notice and additional notices stating that the work has been modified. + * This source code may be translated into executable form and incorporated + * into proprietary software; there is no requirement for such software to + * contain a copyright notice related to this source. + * + * $Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $ + * $Name: kazlib_1_20 $ + */ + +#define NDEBUG + +#ifdef __GNUC__ +#define EXT2FS_ATTR(x) __attribute__(x) +#else +#define EXT2FS_ATTR(x) +#endif + +#include "config.h" +#include <stdlib.h> +#include <stddef.h> +#include <assert.h> +#define DICT_IMPLEMENTATION +#include "dict.h" + +#ifdef KAZLIB_RCSID +static const char rcsid[] = "$Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $"; +#endif + +/* + * These macros provide short convenient names for structure members, + * which are embellished with dict_ prefixes so that they are + * properly confined to the documented namespace. It's legal for a + * program which uses dict to define, for instance, a macro called ``parent''. + * Such a macro would interfere with the dnode_t struct definition. + * In general, highly portable and reusable C modules which expose their + * structures need to confine structure member names to well-defined spaces. + * The resulting identifiers aren't necessarily convenient to use, nor + * readable, in the implementation, however! + */ + +#define left dict_left +#define right dict_right +#define parent dict_parent +#define color dict_color +#define key dict_key +#define data dict_data + +#define nilnode dict_nilnode +#define nodecount dict_nodecount +#define maxcount dict_maxcount +#define compare dict_compare +#define allocnode dict_allocnode +#define freenode dict_freenode +#define context dict_context +#define dupes dict_dupes + +#define dictptr dict_dictptr + +#define dict_root(D) ((D)->nilnode.left) +#define dict_nil(D) (&(D)->nilnode) +#define DICT_DEPTH_MAX 64 + +static dnode_t *dnode_alloc(void *context); +static void dnode_free(dnode_t *node, void *context); + +/* + * Perform a ``left rotation'' adjustment on the tree. The given node P and + * its right child C are rearranged so that the P instead becomes the left + * child of C. The left subtree of C is inherited as the new right subtree + * for P. The ordering of the keys within the tree is thus preserved. + */ + +static void rotate_left(dnode_t *upper) +{ + dnode_t *lower, *lowleft, *upparent; + + lower = upper->right; + upper->right = lowleft = lower->left; + lowleft->parent = upper; + + lower->parent = upparent = upper->parent; + + /* don't need to check for root node here because root->parent is + the sentinel nil node, and root->parent->left points back to root */ + + if (upper == upparent->left) { + upparent->left = lower; + } else { + assert (upper == upparent->right); + upparent->right = lower; + } + + lower->left = upper; + upper->parent = lower; +} + +/* + * This operation is the ``mirror'' image of rotate_left. It is + * the same procedure, but with left and right interchanged. + */ + +static void rotate_right(dnode_t *upper) +{ + dnode_t *lower, *lowright, *upparent; + + lower = upper->left; + upper->left = lowright = lower->right; + lowright->parent = upper; + + lower->parent = upparent = upper->parent; + + if (upper == upparent->right) { + upparent->right = lower; + } else { + assert (upper == upparent->left); + upparent->left = lower; + } + + lower->right = upper; + upper->parent = lower; +} + +/* + * Do a postorder traversal of the tree rooted at the specified + * node and free everything under it. Used by dict_free(). + */ + +static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil) +{ + if (node == nil) + return; + free_nodes(dict, node->left, nil); + free_nodes(dict, node->right, nil); + dict->freenode(node, dict->context); +} + +/* + * This procedure performs a verification that the given subtree is a binary + * search tree. It performs an inorder traversal of the tree using the + * dict_next() successor function, verifying that the key of each node is + * strictly lower than that of its successor, if duplicates are not allowed, + * or lower or equal if duplicates are allowed. This function is used for + * debugging purposes. + */ +#ifndef NDEBUG +static int verify_bintree(dict_t *dict) +{ + dnode_t *first, *next; + + first = dict_first(dict); + + if (dict->dupes) { + while (first && (next = dict_next(dict, first))) { + if (dict->compare(first->key, next->key) > 0) + return 0; + first = next; + } + } else { + while (first && (next = dict_next(dict, first))) { + if (dict->compare(first->key, next->key) >= 0) + return 0; + first = next; + } + } + return 1; +} + +/* + * This function recursively verifies that the given binary subtree satisfies + * three of the red black properties. It checks that every red node has only + * black children. It makes sure that each node is either red or black. And it + * checks that every path has the same count of black nodes from root to leaf. + * It returns the blackheight of the given subtree; this allows blackheights to + * be computed recursively and compared for left and right siblings for + * mismatches. It does not check for every nil node being black, because there + * is only one sentinel nil node. The return value of this function is the + * black height of the subtree rooted at the node ``root'', or zero if the + * subtree is not red-black. + */ + +static unsigned int verify_redblack(dnode_t *nil, dnode_t *root) +{ + unsigned height_left, height_right; + + if (root != nil) { + height_left = verify_redblack(nil, root->left); + height_right = verify_redblack(nil, root->right); + if (height_left == 0 || height_right == 0) + return 0; + if (height_left != height_right) + return 0; + if (root->color == dnode_red) { + if (root->left->color != dnode_black) + return 0; + if (root->right->color != dnode_black) + return 0; + return height_left; + } + if (root->color != dnode_black) + return 0; + return height_left + 1; + } + return 1; +} + +/* + * Compute the actual count of nodes by traversing the tree and + * return it. This could be compared against the stored count to + * detect a mismatch. + */ + +static dictcount_t verify_node_count(dnode_t *nil, dnode_t *root) +{ + if (root == nil) + return 0; + else + return 1 + verify_node_count(nil, root->left) + + verify_node_count(nil, root->right); +} +#endif + +/* + * Verify that the tree contains the given node. This is done by + * traversing all of the nodes and comparing their pointers to the + * given pointer. Returns 1 if the node is found, otherwise + * returns zero. It is intended for debugging purposes. + */ + +static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node) +{ + if (root != nil) { + return root == node + || verify_dict_has_node(nil, root->left, node) + || verify_dict_has_node(nil, root->right, node); + } + return 0; +} + + +#ifdef E2FSCK_NOTUSED +/* + * Dynamically allocate and initialize a dictionary object. + */ + +dict_t *dict_create(dictcount_t maxcount, dict_comp_t comp) +{ + dict_t *new = malloc(sizeof *new); + + if (new) { + new->compare = comp; + new->allocnode = dnode_alloc; + new->freenode = dnode_free; + new->context = NULL; + new->nodecount = 0; + new->maxcount = maxcount; + new->nilnode.left = &new->nilnode; + new->nilnode.right = &new->nilnode; + new->nilnode.parent = &new->nilnode; + new->nilnode.color = dnode_black; + new->dupes = 0; + } + return new; +} +#endif /* E2FSCK_NOTUSED */ + +/* + * Select a different set of node allocator routines. + */ + +void dict_set_allocator(dict_t *dict, dnode_alloc_t al, + dnode_free_t fr, void *context) +{ + assert (dict_count(dict) == 0); + assert ((al == NULL && fr == NULL) || (al != NULL && fr != NULL)); + + dict->allocnode = al ? al : dnode_alloc; + dict->freenode = fr ? fr : dnode_free; + dict->context = context; +} + +#ifdef E2FSCK_NOTUSED +/* + * Free a dynamically allocated dictionary object. Removing the nodes + * from the tree before deleting it is required. + */ + +void dict_destroy(dict_t *dict) +{ + assert (dict_isempty(dict)); + free(dict); +} +#endif + +/* + * Free all the nodes in the dictionary by using the dictionary's + * installed free routine. The dictionary is emptied. + */ + +void dict_free_nodes(dict_t *dict) +{ + dnode_t *nil = dict_nil(dict), *root = dict_root(dict); + free_nodes(dict, root, nil); + dict->nodecount = 0; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; +} + +#ifdef E2FSCK_NOTUSED +/* + * Obsolescent function, equivalent to dict_free_nodes + */ +void dict_free(dict_t *dict) +{ +#ifdef KAZLIB_OBSOLESCENT_DEBUG + assert ("call to obsolescent function dict_free()" && 0); +#endif + dict_free_nodes(dict); +} +#endif + +/* + * Initialize a user-supplied dictionary object. + */ + +dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp) +{ + dict->compare = comp; + dict->allocnode = dnode_alloc; + dict->freenode = dnode_free; + dict->context = NULL; + dict->nodecount = 0; + dict->maxcount = maxcount; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; + dict->nilnode.parent = &dict->nilnode; + dict->nilnode.color = dnode_black; + dict->dupes = 0; + return dict; +} + +#ifdef E2FSCK_NOTUSED +/* + * Initialize a dictionary in the likeness of another dictionary + */ + +void dict_init_like(dict_t *dict, const dict_t *template) +{ + dict->compare = template->compare; + dict->allocnode = template->allocnode; + dict->freenode = template->freenode; + dict->context = template->context; + dict->nodecount = 0; + dict->maxcount = template->maxcount; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; + dict->nilnode.parent = &dict->nilnode; + dict->nilnode.color = dnode_black; + dict->dupes = template->dupes; + + assert (dict_similar(dict, template)); +} + +/* + * Remove all nodes from the dictionary (without freeing them in any way). + */ + +static void dict_clear(dict_t *dict) +{ + dict->nodecount = 0; + dict->nilnode.left = &dict->nilnode; + dict->nilnode.right = &dict->nilnode; + dict->nilnode.parent = &dict->nilnode; + assert (dict->nilnode.color == dnode_black); +} + + +/* + * Verify the integrity of the dictionary structure. This is provided for + * debugging purposes, and should be placed in assert statements. Just because + * this function succeeds doesn't mean that the tree is not corrupt. Certain + * corruptions in the tree may simply cause undefined behavior. + */ + +int dict_verify(dict_t *dict) +{ +#ifndef NDEBUG + dnode_t *nil = dict_nil(dict), *root = dict_root(dict); + + /* check that the sentinel node and root node are black */ + if (root->color != dnode_black) + return 0; + if (nil->color != dnode_black) + return 0; + if (nil->right != nil) + return 0; + /* nil->left is the root node; check that its parent pointer is nil */ + if (nil->left->parent != nil) + return 0; + /* perform a weak test that the tree is a binary search tree */ + if (!verify_bintree(dict)) + return 0; + /* verify that the tree is a red-black tree */ + if (!verify_redblack(nil, root)) + return 0; + if (verify_node_count(nil, root) != dict_count(dict)) + return 0; +#endif + return 1; +} + +/* + * Determine whether two dictionaries are similar: have the same comparison and + * allocator functions, and same status as to whether duplicates are allowed. + */ + +int dict_similar(const dict_t *left, const dict_t *right) +{ + if (left->compare != right->compare) + return 0; + + if (left->allocnode != right->allocnode) + return 0; + + if (left->freenode != right->freenode) + return 0; + + if (left->context != right->context) + return 0; + + if (left->dupes != right->dupes) + return 0; + + return 1; +} +#endif /* E2FSCK_NOTUSED */ + +/* + * Locate a node in the dictionary having the given key. + * If the node is not found, a null a pointer is returned (rather than + * a pointer that dictionary's nil sentinel node), otherwise a pointer to the + * located node is returned. + */ + +dnode_t *dict_lookup(dict_t *dict, const void *key) +{ + dnode_t *root = dict_root(dict); + dnode_t *nil = dict_nil(dict); + dnode_t *saved; + int result; + + /* simple binary search adapted for trees that contain duplicate keys */ + + while (root != nil) { + result = dict->compare(key, root->key); + if (result < 0) + root = root->left; + else if (result > 0) + root = root->right; + else { + if (!dict->dupes) { /* no duplicates, return match */ + return root; + } else { /* could be dupes, find leftmost one */ + do { + saved = root; + root = root->left; + while (root != nil && dict->compare(key, root->key)) + root = root->right; + } while (root != nil); + return saved; + } + } + } + + return NULL; +} + +#ifdef E2FSCK_NOTUSED +/* + * Look for the node corresponding to the lowest key that is equal to or + * greater than the given key. If there is no such node, return null. + */ + +dnode_t *dict_lower_bound(dict_t *dict, const void *key) +{ + dnode_t *root = dict_root(dict); + dnode_t *nil = dict_nil(dict); + dnode_t *tentative = 0; + + while (root != nil) { + int result = dict->compare(key, root->key); + + if (result > 0) { + root = root->right; + } else if (result < 0) { + tentative = root; + root = root->left; + } else { + if (!dict->dupes) { + return root; + } else { + tentative = root; + root = root->left; + } + } + } + + return tentative; +} + +/* + * Look for the node corresponding to the greatest key that is equal to or + * lower than the given key. If there is no such node, return null. + */ + +dnode_t *dict_upper_bound(dict_t *dict, const void *key) +{ + dnode_t *root = dict_root(dict); + dnode_t *nil = dict_nil(dict); + dnode_t *tentative = 0; + + while (root != nil) { + int result = dict->compare(key, root->key); + + if (result < 0) { + root = root->left; + } else if (result > 0) { + tentative = root; + root = root->right; + } else { + if (!dict->dupes) { + return root; + } else { + tentative = root; + root = root->right; + } + } + } + + return tentative; +} +#endif + +/* + * Insert a node into the dictionary. The node should have been + * initialized with a data field. All other fields are ignored. + * The behavior is undefined if the user attempts to insert into + * a dictionary that is already full (for which the dict_isfull() + * function returns true). + */ + +void dict_insert(dict_t *dict, dnode_t *node, const void *key) +{ + dnode_t *where = dict_root(dict), *nil = dict_nil(dict); + dnode_t *parent = nil, *uncle, *grandpa; + int result = -1; + + node->key = key; + + assert (!dict_isfull(dict)); + assert (!dict_contains(dict, node)); + assert (!dnode_is_in_a_dict(node)); + + /* basic binary tree insert */ + + while (where != nil) { + parent = where; + result = dict->compare(key, where->key); + /* trap attempts at duplicate key insertion unless it's explicitly allowed */ + assert (dict->dupes || result != 0); + if (result < 0) + where = where->left; + else + where = where->right; + } + + assert (where == nil); + + if (result < 0) + parent->left = node; + else + parent->right = node; + + node->parent = parent; + node->left = nil; + node->right = nil; + + dict->nodecount++; + + /* red black adjustments */ + + node->color = dnode_red; + + while (parent->color == dnode_red) { + grandpa = parent->parent; + if (parent == grandpa->left) { + uncle = grandpa->right; + if (uncle->color == dnode_red) { /* red parent, red uncle */ + parent->color = dnode_black; + uncle->color = dnode_black; + grandpa->color = dnode_red; + node = grandpa; + parent = grandpa->parent; + } else { /* red parent, black uncle */ + if (node == parent->right) { + rotate_left(parent); + parent = node; + assert (grandpa == parent->parent); + /* rotation between parent and child preserves grandpa */ + } + parent->color = dnode_black; + grandpa->color = dnode_red; + rotate_right(grandpa); + break; + } + } else { /* symmetric cases: parent == parent->parent->right */ + uncle = grandpa->left; + if (uncle->color == dnode_red) { + parent->color = dnode_black; + uncle->color = dnode_black; + grandpa->color = dnode_red; + node = grandpa; + parent = grandpa->parent; + } else { + if (node == parent->left) { + rotate_right(parent); + parent = node; + assert (grandpa == parent->parent); + } + parent->color = dnode_black; + grandpa->color = dnode_red; + rotate_left(grandpa); + break; + } + } + } + + dict_root(dict)->color = dnode_black; + + assert (dict_verify(dict)); +} + +#ifdef E2FSCK_NOTUSED +/* + * Delete the given node from the dictionary. If the given node does not belong + * to the given dictionary, undefined behavior results. A pointer to the + * deleted node is returned. + */ + +dnode_t *dict_delete(dict_t *dict, dnode_t *delete) +{ + dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent; + + /* basic deletion */ + + assert (!dict_isempty(dict)); + assert (dict_contains(dict, delete)); + + /* + * If the node being deleted has two children, then we replace it with its + * successor (i.e. the leftmost node in the right subtree.) By doing this, + * we avoid the traditional algorithm under which the successor's key and + * value *only* move to the deleted node and the successor is spliced out + * from the tree. We cannot use this approach because the user may hold + * pointers to the successor, or nodes may be inextricably tied to some + * other structures by way of embedding, etc. So we must splice out the + * node we are given, not some other node, and must not move contents from + * one node to another behind the user's back. + */ + + if (delete->left != nil && delete->right != nil) { + dnode_t *next = dict_next(dict, delete); + dnode_t *nextparent = next->parent; + dnode_color_t nextcolor = next->color; + + assert (next != nil); + assert (next->parent != nil); + assert (next->left == nil); + + /* + * First, splice out the successor from the tree completely, by + * moving up its right child into its place. + */ + + child = next->right; + child->parent = nextparent; + + if (nextparent->left == next) { + nextparent->left = child; + } else { + assert (nextparent->right == next); + nextparent->right = child; + } + + /* + * Now that the successor has been extricated from the tree, install it + * in place of the node that we want deleted. + */ + + next->parent = delparent; + next->left = delete->left; + next->right = delete->right; + next->left->parent = next; + next->right->parent = next; + next->color = delete->color; + delete->color = nextcolor; + + if (delparent->left == delete) { + delparent->left = next; + } else { + assert (delparent->right == delete); + delparent->right = next; + } + + } else { + assert (delete != nil); + assert (delete->left == nil || delete->right == nil); + + child = (delete->left != nil) ? delete->left : delete->right; + + child->parent = delparent = delete->parent; + + if (delete == delparent->left) { + delparent->left = child; + } else { + assert (delete == delparent->right); + delparent->right = child; + } + } + + delete->parent = NULL; + delete->right = NULL; + delete->left = NULL; + + dict->nodecount--; + + assert (verify_bintree(dict)); + + /* red-black adjustments */ + + if (delete->color == dnode_black) { + dnode_t *parent, *sister; + + dict_root(dict)->color = dnode_red; + + while (child->color == dnode_black) { + parent = child->parent; + if (child == parent->left) { + sister = parent->right; + assert (sister != nil); + if (sister->color == dnode_red) { + sister->color = dnode_black; + parent->color = dnode_red; + rotate_left(parent); + sister = parent->right; + assert (sister != nil); + } + if (sister->left->color == dnode_black + && sister->right->color == dnode_black) { + sister->color = dnode_red; + child = parent; + } else { + if (sister->right->color == dnode_black) { + assert (sister->left->color == dnode_red); + sister->left->color = dnode_black; + sister->color = dnode_red; + rotate_right(sister); + sister = parent->right; + assert (sister != nil); + } + sister->color = parent->color; + sister->right->color = dnode_black; + parent->color = dnode_black; + rotate_left(parent); + break; + } + } else { /* symmetric case: child == child->parent->right */ + assert (child == parent->right); + sister = parent->left; + assert (sister != nil); + if (sister->color == dnode_red) { + sister->color = dnode_black; + parent->color = dnode_red; + rotate_right(parent); + sister = parent->left; + assert (sister != nil); + } + if (sister->right->color == dnode_black + && sister->left->color == dnode_black) { + sister->color = dnode_red; + child = parent; + } else { + if (sister->left->color == dnode_black) { + assert (sister->right->color == dnode_red); + sister->right->color = dnode_black; + sister->color = dnode_red; + rotate_left(sister); + sister = parent->left; + assert (sister != nil); + } + sister->color = parent->color; + sister->left->color = dnode_black; + parent->color = dnode_black; + rotate_right(parent); + break; + } + } + } + + child->color = dnode_black; + dict_root(dict)->color = dnode_black; + } + + assert (dict_verify(dict)); + + return delete; +} +#endif /* E2FSCK_NOTUSED */ + +/* + * Allocate a node using the dictionary's allocator routine, give it + * the data item. + */ + +int dict_alloc_insert(dict_t *dict, const void *key, void *data) +{ + dnode_t *node = dict->allocnode(dict->context); + + if (node) { + dnode_init(node, data); + dict_insert(dict, node, key); + return 1; + } + return 0; +} + +#ifdef E2FSCK_NOTUSED +void dict_delete_free(dict_t *dict, dnode_t *node) +{ + dict_delete(dict, node); + dict->freenode(node, dict->context); +} +#endif + +/* + * Return the node with the lowest (leftmost) key. If the dictionary is empty + * (that is, dict_isempty(dict) returns 1) a null pointer is returned. + */ + +dnode_t *dict_first(dict_t *dict) +{ + dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left; + + if (root != nil) + while ((left = root->left) != nil) + root = left; + + return (root == nil) ? NULL : root; +} + +/* + * Return the node with the highest (rightmost) key. If the dictionary is empty + * (that is, dict_isempty(dict) returns 1) a null pointer is returned. + */ + +dnode_t *dict_last(dict_t *dict) +{ + dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right; + + if (root != nil) + while ((right = root->right) != nil) + root = right; + + return (root == nil) ? NULL : root; +} + +/* + * Return the given node's successor node---the node which has the + * next key in the the left to right ordering. If the node has + * no successor, a null pointer is returned rather than a pointer to + * the nil node. + */ + +dnode_t *dict_next(dict_t *dict, dnode_t *curr) +{ + dnode_t *nil = dict_nil(dict), *parent, *left; + + if (curr->right != nil) { + curr = curr->right; + while ((left = curr->left) != nil) + curr = left; + return curr; + } + + parent = curr->parent; + + while (parent != nil && curr == parent->right) { + curr = parent; + parent = curr->parent; + } + + return (parent == nil) ? NULL : parent; +} + +/* + * Return the given node's predecessor, in the key order. + * The nil sentinel node is returned if there is no predecessor. + */ + +dnode_t *dict_prev(dict_t *dict, dnode_t *curr) +{ + dnode_t *nil = dict_nil(dict), *parent, *right; + + if (curr->left != nil) { + curr = curr->left; + while ((right = curr->right) != nil) + curr = right; + return curr; + } + + parent = curr->parent; + + while (parent != nil && curr == parent->left) { + curr = parent; + parent = curr->parent; + } + + return (parent == nil) ? NULL : parent; +} + +void dict_allow_dupes(dict_t *dict) +{ + dict->dupes = 1; +} + +#undef dict_count +#undef dict_isempty +#undef dict_isfull +#undef dnode_get +#undef dnode_put +#undef dnode_getkey + +dictcount_t dict_count(dict_t *dict) +{ + return dict->nodecount; +} + +int dict_isempty(dict_t *dict) +{ + return dict->nodecount == 0; +} + +int dict_isfull(dict_t *dict) +{ + return dict->nodecount == dict->maxcount; +} + +int dict_contains(dict_t *dict, dnode_t *node) +{ + return verify_dict_has_node(dict_nil(dict), dict_root(dict), node); +} + +static dnode_t *dnode_alloc(void *context EXT2FS_ATTR((unused))) +{ + return malloc(sizeof *dnode_alloc(NULL)); +} + +static void dnode_free(dnode_t *node, void *context EXT2FS_ATTR((unused))) +{ + free(node); +} + +dnode_t *dnode_create(void *data) +{ + dnode_t *new = malloc(sizeof *new); + if (new) { + new->data = data; + new->parent = NULL; + new->left = NULL; + new->right = NULL; + } + return new; +} + +dnode_t *dnode_init(dnode_t *dnode, void *data) +{ + dnode->data = data; + dnode->parent = NULL; + dnode->left = NULL; + dnode->right = NULL; + return dnode; +} + +void dnode_destroy(dnode_t *dnode) +{ + assert (!dnode_is_in_a_dict(dnode)); + free(dnode); +} + +void *dnode_get(dnode_t *dnode) +{ + return dnode->data; +} + +const void *dnode_getkey(dnode_t *dnode) +{ + return dnode->key; +} + +#ifdef E2FSCK_NOTUSED +void dnode_put(dnode_t *dnode, void *data) +{ + dnode->data = data; +} + +int dnode_is_in_a_dict(dnode_t *dnode) +{ + return (dnode->parent && dnode->left && dnode->right); +} + +void dict_process(dict_t *dict, void *context, dnode_process_t function) +{ + dnode_t *node = dict_first(dict), *next; + + while (node != NULL) { + /* check for callback function deleting */ + /* the next node from under us */ + assert (dict_contains(dict, node)); + next = dict_next(dict, node); + function(dict, node, context); + node = next; + } +} + +static void load_begin_internal(dict_load_t *load, dict_t *dict) +{ + load->dictptr = dict; + load->nilnode.left = &load->nilnode; + load->nilnode.right = &load->nilnode; +} + +void dict_load_begin(dict_load_t *load, dict_t *dict) +{ + assert (dict_isempty(dict)); + load_begin_internal(load, dict); +} + +void dict_load_next(dict_load_t *load, dnode_t *newnode, const void *key) +{ + dict_t *dict = load->dictptr; + dnode_t *nil = &load->nilnode; + + assert (!dnode_is_in_a_dict(newnode)); + assert (dict->nodecount < dict->maxcount); + +#ifndef NDEBUG + if (dict->nodecount > 0) { + if (dict->dupes) + assert (dict->compare(nil->left->key, key) <= 0); + else + assert (dict->compare(nil->left->key, key) < 0); + } +#endif + + newnode->key = key; + nil->right->left = newnode; + nil->right = newnode; + newnode->left = nil; + dict->nodecount++; +} + +void dict_load_end(dict_load_t *load) +{ + dict_t *dict = load->dictptr; + dnode_t *tree[DICT_DEPTH_MAX] = { 0 }; + dnode_t *curr, *dictnil = dict_nil(dict), *loadnil = &load->nilnode, *next; + dnode_t *complete = 0; + dictcount_t fullcount = DICTCOUNT_T_MAX, nodecount = dict->nodecount; + dictcount_t botrowcount; + unsigned baselevel = 0, level = 0, i; + + assert (dnode_red == 0 && dnode_black == 1); + + while (fullcount >= nodecount && fullcount) + fullcount >>= 1; + + botrowcount = nodecount - fullcount; + + for (curr = loadnil->left; curr != loadnil; curr = next) { + next = curr->left; + + if (complete == NULL && botrowcount-- == 0) { + assert (baselevel == 0); + assert (level == 0); + baselevel = level = 1; + complete = tree[0]; + + if (complete != 0) { + tree[0] = 0; + complete->right = dictnil; + while (tree[level] != 0) { + tree[level]->right = complete; + complete->parent = tree[level]; + complete = tree[level]; + tree[level++] = 0; + } + } + } + + if (complete == NULL) { + curr->left = dictnil; + curr->right = dictnil; + curr->color = level % 2; + complete = curr; + + assert (level == baselevel); + while (tree[level] != 0) { + tree[level]->right = complete; + complete->parent = tree[level]; + complete = tree[level]; + tree[level++] = 0; + } + } else { + curr->left = complete; + curr->color = (level + 1) % 2; + complete->parent = curr; + tree[level] = curr; + complete = 0; + level = baselevel; + } + } + + if (complete == NULL) + complete = dictnil; + + for (i = 0; i < DICT_DEPTH_MAX; i++) { + if (tree[i] != 0) { + tree[i]->right = complete; + complete->parent = tree[i]; + complete = tree[i]; + } + } + + dictnil->color = dnode_black; + dictnil->right = dictnil; + complete->parent = dictnil; + complete->color = dnode_black; + dict_root(dict) = complete; + + assert (dict_verify(dict)); +} + +void dict_merge(dict_t *dest, dict_t *source) +{ + dict_load_t load; + dnode_t *leftnode = dict_first(dest), *rightnode = dict_first(source); + + assert (dict_similar(dest, source)); + + if (source == dest) + return; + + dest->nodecount = 0; + load_begin_internal(&load, dest); + + for (;;) { + if (leftnode != NULL && rightnode != NULL) { + if (dest->compare(leftnode->key, rightnode->key) < 0) + goto copyleft; + else + goto copyright; + } else if (leftnode != NULL) { + goto copyleft; + } else if (rightnode != NULL) { + goto copyright; + } else { + assert (leftnode == NULL && rightnode == NULL); + break; + } + + copyleft: + { + dnode_t *next = dict_next(dest, leftnode); +#ifndef NDEBUG + leftnode->left = NULL; /* suppress assertion in dict_load_next */ +#endif + dict_load_next(&load, leftnode, leftnode->key); + leftnode = next; + continue; + } + + copyright: + { + dnode_t *next = dict_next(source, rightnode); +#ifndef NDEBUG + rightnode->left = NULL; +#endif + dict_load_next(&load, rightnode, rightnode->key); + rightnode = next; + continue; + } + } + + dict_clear(source); + dict_load_end(&load); +} +#endif /* E2FSCK_NOTUSED */ + +#ifdef KAZLIB_TEST_MAIN + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <stdarg.h> + +typedef char input_t[256]; + +static int tokenize(char *string, ...) +{ + char **tokptr; + va_list arglist; + int tokcount = 0; + + va_start(arglist, string); + tokptr = va_arg(arglist, char **); + while (tokptr) { + while (*string && isspace((unsigned char) *string)) + string++; + if (!*string) + break; + *tokptr = string; + while (*string && !isspace((unsigned char) *string)) + string++; + tokptr = va_arg(arglist, char **); + tokcount++; + if (!*string) + break; + *string++ = 0; + } + va_end(arglist); + + return tokcount; +} + +static int comparef(const void *key1, const void *key2) +{ + return strcmp(key1, key2); +} + +static char *dupstring(char *str) +{ + int sz = strlen(str) + 1; + char *new = malloc(sz); + if (new) + memcpy(new, str, sz); + return new; +} + +static dnode_t *new_node(void *c) +{ + static dnode_t few[5]; + static int count; + + if (count < 5) + return few + count++; + + return NULL; +} + +static void del_node(dnode_t *n, void *c) +{ +} + +static int prompt = 0; + +static void construct(dict_t *d) +{ + input_t in; + int done = 0; + dict_load_t dl; + dnode_t *dn; + char *tok1, *tok2, *val; + const char *key; + char *help = + "p turn prompt on\n" + "q finish construction\n" + "a <key> <val> add new entry\n"; + + if (!dict_isempty(d)) + puts("warning: dictionary not empty!"); + + dict_load_begin(&dl, d); + + while (!done) { + if (prompt) + putchar('>'); + fflush(stdout); + + if (!fgets(in, sizeof(input_t), stdin)) + break; + + switch (in[0]) { + case '?': + puts(help); + break; + case 'p': + prompt = 1; + break; + case 'q': + done = 1; + break; + case 'a': + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { + puts("what?"); + break; + } + key = dupstring(tok1); + val = dupstring(tok2); + dn = dnode_create(val); + + if (!key || !val || !dn) { + puts("out of memory"); + free((void *) key); + free(val); + if (dn) + dnode_destroy(dn); + } + + dict_load_next(&dl, dn, key); + break; + default: + putchar('?'); + putchar('\n'); + break; + } + } + + dict_load_end(&dl); +} + +int main(void) +{ + input_t in; + dict_t darray[10]; + dict_t *d = &darray[0]; + dnode_t *dn; + int i; + char *tok1, *tok2, *val; + const char *key; + + char *help = + "a <key> <val> add value to dictionary\n" + "d <key> delete value from dictionary\n" + "l <key> lookup value in dictionary\n" + "( <key> lookup lower bound\n" + ") <key> lookup upper bound\n" + "# <num> switch to alternate dictionary (0-9)\n" + "j <num> <num> merge two dictionaries\n" + "f free the whole dictionary\n" + "k allow duplicate keys\n" + "c show number of entries\n" + "t dump whole dictionary in sort order\n" + "m make dictionary out of sorted items\n" + "p turn prompt on\n" + "s switch to non-functioning allocator\n" + "q quit"; + + for (i = 0; i < sizeof darray / sizeof *darray; i++) + dict_init(&darray[i], DICTCOUNT_T_MAX, comparef); + + for (;;) { + if (prompt) + putchar('>'); + fflush(stdout); + + if (!fgets(in, sizeof(input_t), stdin)) + break; + + switch(in[0]) { + case '?': + puts(help); + break; + case 'a': + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { + puts("what?"); + break; + } + key = dupstring(tok1); + val = dupstring(tok2); + + if (!key || !val) { + puts("out of memory"); + free((void *) key); + free(val); + } + + if (!dict_alloc_insert(d, key, val)) { + puts("dict_alloc_insert failed"); + free((void *) key); + free(val); + break; + } + break; + case 'd': + if (tokenize(in+1, &tok1, (char **) 0) != 1) { + puts("what?"); + break; + } + dn = dict_lookup(d, tok1); + if (!dn) { + puts("dict_lookup failed"); + break; + } + val = dnode_get(dn); + key = dnode_getkey(dn); + dict_delete_free(d, dn); + + free(val); + free((void *) key); + break; + case 'f': + dict_free(d); + break; + case 'l': + case '(': + case ')': + if (tokenize(in+1, &tok1, (char **) 0) != 1) { + puts("what?"); + break; + } + dn = 0; + switch (in[0]) { + case 'l': + dn = dict_lookup(d, tok1); + break; + case '(': + dn = dict_lower_bound(d, tok1); + break; + case ')': + dn = dict_upper_bound(d, tok1); + break; + } + if (!dn) { + puts("lookup failed"); + break; + } + val = dnode_get(dn); + puts(val); + break; + case 'm': + construct(d); + break; + case 'k': + dict_allow_dupes(d); + break; + case 'c': + printf("%lu\n", (unsigned long) dict_count(d)); + break; + case 't': + for (dn = dict_first(d); dn; dn = dict_next(d, dn)) { + printf("%s\t%s\n", (char *) dnode_getkey(dn), + (char *) dnode_get(dn)); + } + break; + case 'q': + exit(0); + break; + case '\0': + break; + case 'p': + prompt = 1; + break; + case 's': + dict_set_allocator(d, new_node, del_node, NULL); + break; + case '#': + if (tokenize(in+1, &tok1, (char **) 0) != 1) { + puts("what?"); + break; + } else { + int dictnum = atoi(tok1); + if (dictnum < 0 || dictnum > 9) { + puts("invalid number"); + break; + } + d = &darray[dictnum]; + } + break; + case 'j': + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { + puts("what?"); + break; + } else { + int dict1 = atoi(tok1), dict2 = atoi(tok2); + if (dict1 < 0 || dict1 > 9 || dict2 < 0 || dict2 > 9) { + puts("invalid number"); + break; + } + dict_merge(&darray[dict1], &darray[dict2]); + } + break; + default: + putchar('?'); + putchar('\n'); + break; + } + } + + return 0; +} + +#endif
diff --git a/e2fsck/dict.h b/e2fsck/dict.h new file mode 100644 index 0000000..838079d --- /dev/null +++ b/e2fsck/dict.h
@@ -0,0 +1,144 @@ +/* + * Dictionary Abstract Data Type + * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net> + * + * Free Software License: + * + * All rights are reserved by the author, with the following exceptions: + * Permission is granted to freely reproduce and distribute this software, + * possibly in exchange for a fee, provided that this copyright notice appears + * intact. Permission is also granted to adapt this software to produce + * derivative works, as long as the modified versions carry this copyright + * notice and additional notices stating that the work has been modified. + * This source code may be translated into executable form and incorporated + * into proprietary software; there is no requirement for such software to + * contain a copyright notice related to this source. + * + * $Id: dict.h,v 1.22.2.6 2000/11/13 01:36:44 kaz Exp $ + * $Name: kazlib_1_20 $ + */ + +#ifndef DICT_H +#define DICT_H + +#include <limits.h> +#ifdef KAZLIB_SIDEEFFECT_DEBUG +#include "sfx.h" +#endif + +/* + * Blurb for inclusion into C++ translation units + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long dictcount_t; +#define DICTCOUNT_T_MAX ULONG_MAX + +/* + * The dictionary is implemented as a red-black tree + */ + +typedef enum { dnode_red, dnode_black } dnode_color_t; + +typedef struct dnode_t { +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) + struct dnode_t *dict_left; + struct dnode_t *dict_right; + struct dnode_t *dict_parent; + dnode_color_t dict_color; + const void *dict_key; + void *dict_data; +#else + int dict_dummy; +#endif +} dnode_t; + +typedef int (*dict_comp_t)(const void *, const void *); +typedef dnode_t *(*dnode_alloc_t)(void *); +typedef void (*dnode_free_t)(dnode_t *, void *); + +typedef struct dict_t { +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) + dnode_t dict_nilnode; + dictcount_t dict_nodecount; + dictcount_t dict_maxcount; + dict_comp_t dict_compare; + dnode_alloc_t dict_allocnode; + dnode_free_t dict_freenode; + void *dict_context; + int dict_dupes; +#else + int dict_dummmy; +#endif +} dict_t; + +typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *); + +typedef struct dict_load_t { +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) + dict_t *dict_dictptr; + dnode_t dict_nilnode; +#else + int dict_dummmy; +#endif +} dict_load_t; + +extern dict_t *dict_create(dictcount_t, dict_comp_t); +extern void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *); +extern void dict_destroy(dict_t *); +extern void dict_free_nodes(dict_t *); +extern void dict_free(dict_t *); +extern dict_t *dict_init(dict_t *, dictcount_t, dict_comp_t); +extern void dict_init_like(dict_t *, const dict_t *); +extern int dict_verify(dict_t *); +extern int dict_similar(const dict_t *, const dict_t *); +extern dnode_t *dict_lookup(dict_t *, const void *); +extern dnode_t *dict_lower_bound(dict_t *, const void *); +extern dnode_t *dict_upper_bound(dict_t *, const void *); +extern void dict_insert(dict_t *, dnode_t *, const void *); +extern dnode_t *dict_delete(dict_t *, dnode_t *); +extern int dict_alloc_insert(dict_t *, const void *, void *); +extern void dict_delete_free(dict_t *, dnode_t *); +extern dnode_t *dict_first(dict_t *); +extern dnode_t *dict_last(dict_t *); +extern dnode_t *dict_next(dict_t *, dnode_t *); +extern dnode_t *dict_prev(dict_t *, dnode_t *); +extern dictcount_t dict_count(dict_t *); +extern int dict_isempty(dict_t *); +extern int dict_isfull(dict_t *); +extern int dict_contains(dict_t *, dnode_t *); +extern void dict_allow_dupes(dict_t *); +extern int dnode_is_in_a_dict(dnode_t *); +extern dnode_t *dnode_create(void *); +extern dnode_t *dnode_init(dnode_t *, void *); +extern void dnode_destroy(dnode_t *); +extern void *dnode_get(dnode_t *); +extern const void *dnode_getkey(dnode_t *); +extern void dnode_put(dnode_t *, void *); +extern void dict_process(dict_t *, void *, dnode_process_t); +extern void dict_load_begin(dict_load_t *, dict_t *); +extern void dict_load_next(dict_load_t *, dnode_t *, const void *); +extern void dict_load_end(dict_load_t *); +extern void dict_merge(dict_t *, dict_t *); + +#if defined(DICT_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) +#ifdef KAZLIB_SIDEEFFECT_DEBUG +#define dict_isfull(D) (SFX_CHECK(D)->dict_nodecount == (D)->dict_maxcount) +#else +#define dict_isfull(D) ((D)->dict_nodecount == (D)->dict_maxcount) +#endif +#define dict_count(D) ((D)->dict_nodecount) +#define dict_isempty(D) ((D)->dict_nodecount == 0) +#define dnode_get(N) ((N)->dict_data) +#define dnode_getkey(N) ((N)->dict_key) +#define dnode_put(N, X) ((N)->dict_data = (X)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/e2fsck/dirinfo.c b/e2fsck/dirinfo.c new file mode 100644 index 0000000..dab5a13 --- /dev/null +++ b/e2fsck/dirinfo.c
@@ -0,0 +1,464 @@ +/* + * dirinfo.c --- maintains the directory information table for e2fsck. + * + * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#undef DIRINFO_DEBUG + +#include "config.h" +#include "e2fsck.h" +#include <sys/stat.h> +#include <fcntl.h> +#include "uuid/uuid.h" + +#include <ext2fs/tdb.h> + +struct dir_info_db { + int count; + int size; + struct dir_info *array; + struct dir_info *last_lookup; + char *tdb_fn; + TDB_CONTEXT *tdb; +}; + +struct dir_info_iter { + int i; + TDB_DATA tdb_iter; +}; + +struct dir_info_ent { + ext2_ino_t dotdot; /* Parent according to '..' */ + ext2_ino_t parent; /* Parent according to treewalk */ +}; + + +static void e2fsck_put_dir_info(e2fsck_t ctx, struct dir_info *dir); + +static void setup_tdb(e2fsck_t ctx, ext2_ino_t num_dirs) +{ + struct dir_info_db *db = ctx->dir_info; + unsigned int threshold; + errcode_t retval; + mode_t save_umask; + char *tdb_dir, uuid[40]; + int fd, enable; + + profile_get_string(ctx->profile, "scratch_files", "directory", 0, 0, + &tdb_dir); + profile_get_uint(ctx->profile, "scratch_files", + "numdirs_threshold", 0, 0, &threshold); + profile_get_boolean(ctx->profile, "scratch_files", + "dirinfo", 0, 1, &enable); + + if (!enable || !tdb_dir || access(tdb_dir, W_OK) || + (threshold && num_dirs <= threshold)) + return; + + retval = ext2fs_get_mem(strlen(tdb_dir) + 64, &db->tdb_fn); + if (retval) + return; + + uuid_unparse(ctx->fs->super->s_uuid, uuid); + sprintf(db->tdb_fn, "%s/%s-dirinfo-XXXXXX", tdb_dir, uuid); + save_umask = umask(077); + fd = mkstemp(db->tdb_fn); + umask(save_umask); + if (fd < 0) { + db->tdb = NULL; + return; + } + + if (num_dirs < 99991) + num_dirs = 99991; /* largest 5 digit prime */ + + db->tdb = tdb_open(db->tdb_fn, num_dirs, TDB_NOLOCK | TDB_NOSYNC, + O_RDWR | O_CREAT | O_TRUNC, 0600); + close(fd); +} + +static void setup_db(e2fsck_t ctx) +{ + struct dir_info_db *db; + ext2_ino_t num_dirs; + errcode_t retval; + + db = (struct dir_info_db *) + e2fsck_allocate_memory(ctx, sizeof(struct dir_info_db), + "directory map db"); + db->count = db->size = 0; + db->array = 0; + + ctx->dir_info = db; + + retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs); + if (retval) + num_dirs = 1024; /* Guess */ + + setup_tdb(ctx, num_dirs); + + if (db->tdb) { +#ifdef DIRINFO_DEBUG + printf("Note: using tdb!\n"); +#endif + return; + } + + db->size = num_dirs + 10; + db->array = (struct dir_info *) + e2fsck_allocate_memory(ctx, db->size + * sizeof (struct dir_info), + "directory map"); +} + +/* + * This subroutine is called during pass1 to create a directory info + * entry. During pass1, the passed-in parent is 0; it will get filled + * in during pass2. + */ +void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent) +{ + struct dir_info_db *db; + struct dir_info *dir, ent, *old_array; + int i, j; + errcode_t retval; + unsigned long old_size; + +#ifdef DIRINFO_DEBUG + printf("add_dir_info for inode (%lu, %lu)...\n", ino, parent); +#endif + if (!ctx->dir_info) + setup_db(ctx); + db = ctx->dir_info; + + if (ctx->dir_info->count >= ctx->dir_info->size) { + old_size = ctx->dir_info->size * sizeof(struct dir_info); + ctx->dir_info->size += 10; + old_array = ctx->dir_info->array; + retval = ext2fs_resize_mem(old_size, ctx->dir_info->size * + sizeof(struct dir_info), + &ctx->dir_info->array); + if (retval) { + fprintf(stderr, "Couldn't reallocate dir_info " + "structure to %d entries\n", + ctx->dir_info->size); + fatal_error(ctx, 0); + ctx->dir_info->size -= 10; + return; + } + if (old_array != ctx->dir_info->array) + ctx->dir_info->last_lookup = NULL; + } + + ent.ino = ino; + ent.parent = parent; + ent.dotdot = parent; + + if (db->tdb) { + e2fsck_put_dir_info(ctx, &ent); + return; + } + + /* + * Normally, add_dir_info is called with each inode in + * sequential order; but once in a while (like when pass 3 + * needs to recreate the root directory or lost+found + * directory) it is called out of order. In those cases, we + * need to move the dir_info entries down to make room, since + * the dir_info array needs to be sorted by inode number for + * get_dir_info()'s sake. + */ + if (ctx->dir_info->count && + ctx->dir_info->array[ctx->dir_info->count-1].ino >= ino) { + for (i = ctx->dir_info->count-1; i > 0; i--) + if (ctx->dir_info->array[i-1].ino < ino) + break; + dir = &ctx->dir_info->array[i]; + if (dir->ino != ino) + for (j = ctx->dir_info->count++; j > i; j--) + ctx->dir_info->array[j] = ctx->dir_info->array[j-1]; + } else + dir = &ctx->dir_info->array[ctx->dir_info->count++]; + + dir->ino = ino; + dir->dotdot = parent; + dir->parent = parent; +} + +/* + * get_dir_info() --- given an inode number, try to find the directory + * information entry for it. + */ +static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino) +{ + struct dir_info_db *db = ctx->dir_info; + int low, high, mid; + struct dir_info_ent *buf; + static struct dir_info ret_dir_info; + + if (!db) + return 0; + +#ifdef DIRINFO_DEBUG + printf("e2fsck_get_dir_info %d...", ino); +#endif + + if (db->tdb) { + TDB_DATA key, data; + + key.dptr = (unsigned char *) &ino; + key.dsize = sizeof(ext2_ino_t); + + data = tdb_fetch(db->tdb, key); + if (!data.dptr) { + if (tdb_error(db->tdb) != TDB_ERR_NOEXIST) + printf("fetch failed: %s\n", + tdb_errorstr(db->tdb)); + return 0; + } + + buf = (struct dir_info_ent *) data.dptr; + ret_dir_info.ino = ino; + ret_dir_info.dotdot = buf->dotdot; + ret_dir_info.parent = buf->parent; +#ifdef DIRINFO_DEBUG + printf("(%d,%d,%d)\n", ino, buf->dotdot, buf->parent); +#endif + free(data.dptr); + return &ret_dir_info; + } + + if (db->last_lookup && db->last_lookup->ino == ino) + return db->last_lookup; + + low = 0; + high = ctx->dir_info->count-1; + if (ino == ctx->dir_info->array[low].ino) { +#ifdef DIRINFO_DEBUG + printf("(%d,%d,%d)\n", ino, + ctx->dir_info->array[low].dotdot, + ctx->dir_info->array[low].parent); +#endif + return &ctx->dir_info->array[low]; + } + if (ino == ctx->dir_info->array[high].ino) { +#ifdef DIRINFO_DEBUG + printf("(%d,%d,%d)\n", ino, + ctx->dir_info->array[high].dotdot, + ctx->dir_info->array[high].parent); +#endif + return &ctx->dir_info->array[high]; + } + + while (low < high) { + mid = (low+high)/2; + if (mid == low || mid == high) + break; + if (ino == ctx->dir_info->array[mid].ino) { +#ifdef DIRINFO_DEBUG + printf("(%d,%d,%d)\n", ino, + ctx->dir_info->array[mid].dotdot, + ctx->dir_info->array[mid].parent); +#endif + return &ctx->dir_info->array[mid]; + } + if (ino < ctx->dir_info->array[mid].ino) + high = mid; + else + low = mid; + } + return 0; +} + +static void e2fsck_put_dir_info(e2fsck_t ctx, struct dir_info *dir) +{ + struct dir_info_db *db = ctx->dir_info; + struct dir_info_ent buf; + TDB_DATA key, data; + +#ifdef DIRINFO_DEBUG + printf("e2fsck_put_dir_info (%d, %d, %d)...", dir->ino, dir->dotdot, + dir->parent); +#endif + + if (!db->tdb) + return; + + buf.parent = dir->parent; + buf.dotdot = dir->dotdot; + + key.dptr = (unsigned char *) &dir->ino; + key.dsize = sizeof(ext2_ino_t); + data.dptr = (unsigned char *) &buf; + data.dsize = sizeof(buf); + + if (tdb_store(db->tdb, key, data, TDB_REPLACE) == -1) { + printf("store failed: %s\n", tdb_errorstr(db->tdb)); + } + return; +} + +/* + * Free the dir_info structure when it isn't needed any more. + */ +void e2fsck_free_dir_info(e2fsck_t ctx) +{ + if (ctx->dir_info) { + if (ctx->dir_info->tdb) + tdb_close(ctx->dir_info->tdb); + if (ctx->dir_info->tdb_fn) { + unlink(ctx->dir_info->tdb_fn); + free(ctx->dir_info->tdb_fn); + } + if (ctx->dir_info->array) + ext2fs_free_mem(&ctx->dir_info->array); + ctx->dir_info->array = 0; + ctx->dir_info->size = 0; + ctx->dir_info->count = 0; + ext2fs_free_mem(&ctx->dir_info); + ctx->dir_info = 0; + } +} + +/* + * Return the count of number of directories in the dir_info structure + */ +int e2fsck_get_num_dirinfo(e2fsck_t ctx) +{ + return ctx->dir_info ? ctx->dir_info->count : 0; +} + +struct dir_info_iter *e2fsck_dir_info_iter_begin(e2fsck_t ctx) +{ + struct dir_info_iter *iter; + struct dir_info_db *db = ctx->dir_info; + + iter = e2fsck_allocate_memory(ctx, sizeof(struct dir_info_iter), + "dir_info iterator"); + + if (db->tdb) + iter->tdb_iter = tdb_firstkey(db->tdb); + + return iter; +} + +void e2fsck_dir_info_iter_end(e2fsck_t ctx EXT2FS_ATTR((unused)), + struct dir_info_iter *iter) +{ + free(iter->tdb_iter.dptr); + ext2fs_free_mem(&iter); +} + +/* + * A simple interator function + */ +struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, struct dir_info_iter *iter) +{ + TDB_DATA data, key; + struct dir_info_db *db = ctx->dir_info; + struct dir_info_ent *buf; + static struct dir_info ret_dir_info; + + if (!ctx->dir_info || !iter) + return 0; + + if (db->tdb) { + if (iter->tdb_iter.dptr == 0) + return 0; + key = iter->tdb_iter; + data = tdb_fetch(db->tdb, key); + if (!data.dptr) { + printf("iter fetch failed: %s\n", + tdb_errorstr(db->tdb)); + return 0; + } + buf = (struct dir_info_ent *) data.dptr; + ret_dir_info.ino = *((ext2_ino_t *) iter->tdb_iter.dptr); + ret_dir_info.dotdot = buf->dotdot; + ret_dir_info.parent = buf->parent; + iter->tdb_iter = tdb_nextkey(db->tdb, key); + free(key.dptr); + free(data.dptr); + return &ret_dir_info; + } + + if (iter->i >= ctx->dir_info->count) + return 0; + +#ifdef DIRINFO_DEBUG + printf("iter(%d, %d, %d)...", ctx->dir_info->array[iter->i].ino, + ctx->dir_info->array[iter->i].dotdot, + ctx->dir_info->array[iter->i].parent); +#endif + ctx->dir_info->last_lookup = ctx->dir_info->array + iter->i++; + return(ctx->dir_info->last_lookup); +} + +/* + * This function only sets the parent pointer, and requires that + * dirinfo structure has already been created. + */ +int e2fsck_dir_info_set_parent(e2fsck_t ctx, ext2_ino_t ino, + ext2_ino_t parent) +{ + struct dir_info *p; + + p = e2fsck_get_dir_info(ctx, ino); + if (!p) + return 1; + p->parent = parent; + e2fsck_put_dir_info(ctx, p); + return 0; +} + +/* + * This function only sets the dot dot pointer, and requires that + * dirinfo structure has already been created. + */ +int e2fsck_dir_info_set_dotdot(e2fsck_t ctx, ext2_ino_t ino, + ext2_ino_t dotdot) +{ + struct dir_info *p; + + p = e2fsck_get_dir_info(ctx, ino); + if (!p) + return 1; + p->dotdot = dotdot; + e2fsck_put_dir_info(ctx, p); + return 0; +} + +/* + * This function only sets the parent pointer, and requires that + * dirinfo structure has already been created. + */ +int e2fsck_dir_info_get_parent(e2fsck_t ctx, ext2_ino_t ino, + ext2_ino_t *parent) +{ + struct dir_info *p; + + p = e2fsck_get_dir_info(ctx, ino); + if (!p) + return 1; + *parent = p->parent; + return 0; +} + +/* + * This function only sets the dot dot pointer, and requires that + * dirinfo structure has already been created. + */ +int e2fsck_dir_info_get_dotdot(e2fsck_t ctx, ext2_ino_t ino, + ext2_ino_t *dotdot) +{ + struct dir_info *p; + + p = e2fsck_get_dir_info(ctx, ino); + if (!p) + return 1; + *dotdot = p->dotdot; + return 0; +} +
diff --git a/e2fsck/dx_dirinfo.c b/e2fsck/dx_dirinfo.c new file mode 100644 index 0000000..be53fff --- /dev/null +++ b/e2fsck/dx_dirinfo.c
@@ -0,0 +1,155 @@ +/* + * dirinfo.c --- maintains the directory information table for e2fsck. + * + * Copyright (C) 1993 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include "e2fsck.h" +#ifdef ENABLE_HTREE + +/* + * This subroutine is called during pass1 to create a directory info + * entry. During pass1, the passed-in parent is 0; it will get filled + * in during pass2. + */ +void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks) +{ + struct dx_dir_info *dir; + int i, j; + errcode_t retval; + unsigned long old_size; + +#if 0 + printf("add_dx_dir_info for inode %lu...\n", ino); +#endif + if (!ctx->dx_dir_info) { + ctx->dx_dir_info_count = 0; + ctx->dx_dir_info_size = 100; /* Guess */ + ctx->dx_dir_info = (struct dx_dir_info *) + e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size + * sizeof (struct dx_dir_info), + "directory map"); + } + + if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) { + old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info); + ctx->dx_dir_info_size += 10; + retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size * + sizeof(struct dx_dir_info), + &ctx->dx_dir_info); + if (retval) { + fprintf(stderr, "Couldn't reallocate dx_dir_info " + "structure to %d entries\n", + ctx->dx_dir_info_size); + fatal_error(ctx, 0); + ctx->dx_dir_info_size -= 10; + return; + } + } + + /* + * Normally, add_dx_dir_info is called with each inode in + * sequential order; but once in a while (like when pass 3 + * needs to recreate the root directory or lost+found + * directory) it is called out of order. In those cases, we + * need to move the dx_dir_info entries down to make room, since + * the dx_dir_info array needs to be sorted by inode number for + * get_dx_dir_info()'s sake. + */ + if (ctx->dx_dir_info_count && + ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) { + for (i = ctx->dx_dir_info_count-1; i > 0; i--) + if (ctx->dx_dir_info[i-1].ino < ino) + break; + dir = &ctx->dx_dir_info[i]; + if (dir->ino != ino) + for (j = ctx->dx_dir_info_count++; j > i; j--) + ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1]; + } else + dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++]; + + dir->ino = ino; + dir->numblocks = num_blocks; + dir->hashversion = 0; + dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks + * sizeof (struct dx_dirblock_info), + "dx_block info array"); + +} + +/* + * get_dx_dir_info() --- given an inode number, try to find the directory + * information entry for it. + */ +struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino) +{ + int low, high, mid; + + low = 0; + high = ctx->dx_dir_info_count-1; + if (!ctx->dx_dir_info) + return 0; + if (ino == ctx->dx_dir_info[low].ino) + return &ctx->dx_dir_info[low]; + if (ino == ctx->dx_dir_info[high].ino) + return &ctx->dx_dir_info[high]; + + while (low < high) { + mid = (low+high)/2; + if (mid == low || mid == high) + break; + if (ino == ctx->dx_dir_info[mid].ino) + return &ctx->dx_dir_info[mid]; + if (ino < ctx->dx_dir_info[mid].ino) + high = mid; + else + low = mid; + } + return 0; +} + +/* + * Free the dx_dir_info structure when it isn't needed any more. + */ +void e2fsck_free_dx_dir_info(e2fsck_t ctx) +{ + int i; + struct dx_dir_info *dir; + + if (ctx->dx_dir_info) { + dir = ctx->dx_dir_info; + for (i=0; i < ctx->dx_dir_info_count; i++,dir++) { + if (dir->dx_block) { + ext2fs_free_mem(&dir->dx_block); + dir->dx_block = 0; + } + } + ext2fs_free_mem(&ctx->dx_dir_info); + ctx->dx_dir_info = 0; + } + ctx->dx_dir_info_size = 0; + ctx->dx_dir_info_count = 0; +} + +/* + * Return the count of number of directories in the dx_dir_info structure + */ +int e2fsck_get_num_dx_dirinfo(e2fsck_t ctx) +{ + return ctx->dx_dir_info_count; +} + +/* + * A simple interator function + */ +struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control) +{ + if (*control >= ctx->dx_dir_info_count) + return 0; + + return(ctx->dx_dir_info + (*control)++); +} + +#endif /* ENABLE_HTREE */
diff --git a/e2fsck/e2fsck.8.in b/e2fsck/e2fsck.8.in new file mode 100644 index 0000000..f5ed758 --- /dev/null +++ b/e2fsck/e2fsck.8.in
@@ -0,0 +1,417 @@ +.\" -*- nroff -*- +.\" Copyright 1993, 1994, 1995 by Theodore Ts'o. All Rights Reserved. +.\" This file may be copied under the terms of the GNU Public License. +.\" +.TH E2FSCK 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@" +.SH NAME +e2fsck \- check a Linux ext2/ext3/ext4 file system +.SH SYNOPSIS +.B e2fsck +[ +.B \-pacnyrdfkvtDFV +] +[ +.B \-b +.I superblock +] +[ +.B \-B +.I blocksize +] +[ +.BR \-l | \-L +.I bad_blocks_file +] +[ +.B \-C +.I fd +] +@JDEV@[ +@JDEV@.B \-j +@JDEV@.I external-journal +@JDEV@] +[ +.B \-E +.I extended_options +] +.I device +.SH DESCRIPTION +.B e2fsck +is used to check the ext2/ext3/ext4 family of file systems. +For ext3 and ext4 filesystems that use a journal, if the system has been +shut down uncleanly without any errors, normally, after replaying the +committed transactions in the journal, the file system should be +marked as clean. Hence, for filesystems that use journalling, +.B e2fsck +will normally replay the journal and exit, unless its superblock +indicates that further checking is required. +.PP +.I device +is the device file where the filesystem is stored (e.g. +.IR /dev/hdc1 ). +.PP +Note that in general it is not safe to run +.B e2fsck +on mounted filesystems. The only exception is if the +.B \-n +option is specified, and +.BR \-c , +.BR \-l , +or +.B -L +options are +.I not +specified. However, even if it is safe to do so, the results printed by +.B e2fsck +are not valid if the filesystem is mounted. If +.B e2fsck +asks whether or not you should check a filesystem which is mounted, +the only correct answer is ``no''. Only experts who really know what +they are doing should consider answering this question in any other way. +.SH OPTIONS +.TP +.B \-a +This option does the same thing as the +.B \-p +option. It is provided for backwards compatibility only; it is +suggested that people use +.B \-p +option whenever possible. +.TP +.BI \-b " superblock" +Instead of using the normal superblock, use an alternative superblock +specified by +.IR superblock . +This option is normally used when the primary superblock has been +corrupted. The location of the backup superblock is dependent on the +filesystem's blocksize. For filesystems with 1k blocksizes, a backup +superblock can be found at block 8193; for filesystems with 2k +blocksizes, at block 16384; and for 4k blocksizes, at block 32768. +.IP +Additional backup superblocks can be determined by using the +.B mke2fs +program using the +.B \-n +option to print out where the superblocks were created. The +.B \-b +option to +.BR mke2fs , +which specifies blocksize of the filesystem must be specified in order +for the superblock locations that are printed out to be accurate. +.IP +If an alternative superblock is specified and +the filesystem is not opened read-only, e2fsck will make sure that the +primary superblock is updated appropriately upon completion of the +filesystem check. +.TP +.BI \-B " blocksize" +Normally, +.B e2fsck +will search for the superblock at various different +block sizes in an attempt to find the appropriate block size. +This search can be fooled in some cases. This option forces +.B e2fsck +to only try locating the superblock at a particular blocksize. +If the superblock is not found, +.B e2fsck +will terminate with a fatal error. +.TP +.B \-c +This option causes +.B e2fsck +to use +.BR badblocks (8) +program to do a read-only scan of the device in order to find any bad +blocks. If any bad blocks are found, they are added to the bad block +inode to prevent them from being allocated to a file or directory. If +this option is specified twice, then the bad block scan will be done +using a non-destructive read-write test. +.TP +.BI \-C " fd" +This option causes +.B e2fsck +to write completion information to the specified file descriptor +so that the progress of the filesystem +check can be monitored. This option is typically used by programs +which are running +.BR e2fsck . +If the file descriptor number is negative, then absolute value of +the file descriptor will be used, and the progress information will be +suppressed initially. It can later be enabled by sending the +.B e2fsck +process a SIGUSR1 signal. +If the file descriptor specified is 0, +.B e2fsck +will print a completion bar as it goes about its business. This requires +that e2fsck is running on a video console or terminal. +.TP +.B \-d +Print debugging output (useless unless you are debugging +.BR e2fsck ). +.TP +.B \-D +Optimize directories in filesystem. This option causes e2fsck to +try to optimize all directories, either by reindexing them if the +filesystem supports directory indexing, or by sorting and compressing +directories for smaller directories, or for filesystems using +traditional linear directories. +.IP +Even without the +.B \-D +option, +.B e2fsck +may sometimes optimize a few directories --- for example, if +directory indexing is enabled and a directory is not indexed and would +benefit from being indexed, or if the index structures are corrupted +and need to be rebuilt. The +.B \-D +option forces all directories in the filesystem to be optimized. This can +sometimes make them a little smaller and slightly faster to search, but +in practice, you should rarely need to use this option. +.IP +The +.B \-D +option will detect directory entries with duplicate names in a single +directory, which e2fsck normally does not enforce for performance reasons. +.TP +.BI \-E " extended_options" +Set e2fsck extended options. Extended options are comma +separated, and may take an argument using the equals ('=') sign. The +following options are supported: +.RS 1.2i +.TP +.BI ea_ver= extended_attribute_version +Set the version of the extended attribute blocks which +.B e2fsck +will require while checking the filesystem. The version number may +be 1 or 2. The default extended attribute version format is 2. +.TP +.BI journal_only +Only replay the journal if required, but do not perform any further checks +or repairs. +.TP +.BI fragcheck +During pass 1, print a detailed report of any discontiguous blocks for +files in the filesystem. +.TP +.BI discard +Attempt to discard free blocks and unused inode blocks after the full +filesystem check (discarding blocks is useful on solid state devices and sparse +/ thin-provisioned storage). Note that discard is done in pass 5 AFTER the +filesystem has been fully checked and only if it does not contain recognizable +errors. However there might be cases where +.B e2fsck +does not fully recognize a problem and hence in this case this +option may prevent you from further manual data recovery. +.TP +.BI nodiscard +Do not attempt to discard free blocks and unused inode blocks. This option is +exactly the opposite of discard option. This is set as default. +.RE +.TP +.B \-f +Force checking even if the file system seems clean. +.TP +.B \-F +Flush the filesystem device's buffer caches before beginning. Only +really useful for doing +.B e2fsck +time trials. +@JDEV@.TP +@JDEV@.BI \-j " external-journal" +@JDEV@Set the pathname where the external-journal for this filesystem can be +@JDEV@found. +.TP +.BI \-k +When combined with the +.B \-c +option, any existing bad blocks in the bad blocks list are preserved, +and any new bad blocks found by running +.BR badblocks (8) +will be added to the existing bad blocks list. +.TP +.BI \-l " filename" +Add the block numbers listed in the file specified by +.I filename +to the list of bad blocks. The format of this file is the same as the +one generated by the +.BR badblocks (8) +program. Note that the block numbers are based on the blocksize +of the filesystem. Hence, +.BR badblocks (8) +must be given the blocksize of the filesystem in order to obtain correct +results. As a result, it is much simpler and safer to use the +.B -c +option to +.BR e2fsck , +since it will assure that the correct parameters are passed to the +.B badblocks +program. +.TP +.BI \-L " filename" +Set the bad blocks list to be the list of blocks specified by +.IR filename . +(This option is the same as the +.B \-l +option, except the bad blocks list is cleared before the blocks listed +in the file are added to the bad blocks list.) +.TP +.B \-n +Open the filesystem read-only, and assume an answer of `no' to all +questions. Allows +.B e2fsck +to be used non-interactively. This option +may not be specified at the same time as the +.B \-p +or +.B \-y +options. +.TP +.B \-p +Automatically repair ("preen") the file system. This option will cause +.B e2fsck +to automatically +fix any filesystem problems that can be safely fixed without human +intervention. If +.B e2fsck +discovers a problem which may require the system administrator +to take additional corrective action, +.B e2fsck +will print a description of the problem and then exit with the value 4 +logically or'ed into the exit code. (See the \fBEXIT CODE\fR section.) +This option is normally used by the system's boot scripts. It may not +be specified at the same time as the +.B \-n +or +.B \-y +options. +.TP +.B \-r +This option does nothing at all; it is provided only for backwards +compatibility. +.TP +.B \-t +Print timing statistics for +.BR e2fsck . +If this option is used twice, additional timing statistics are printed +on a pass by pass basis. +.TP +.B \-v +Verbose mode. +.TP +.B \-V +Print version information and exit. +.TP +.B \-y +Assume an answer of `yes' to all questions; allows +.B e2fsck +to be used non-interactively. This option +may not be specified at the same time as the +.B \-n +or +.B \-p +options. +.SH EXIT CODE +The exit code returned by +.B e2fsck +is the sum of the following conditions: +.br +\ 0\ \-\ No errors +.br +\ 1\ \-\ File system errors corrected +.br +\ 2\ \-\ File system errors corrected, system should +.br +\ \ \ \ be rebooted +.br +\ 4\ \-\ File system errors left uncorrected +.br +\ 8\ \-\ Operational error +.br +\ 16\ \-\ Usage or syntax error +.br +\ 32\ \-\ E2fsck canceled by user request +.br +\ 128\ \-\ Shared library error +.br +.SH SIGNALS +The following signals have the following effect when sent to +.BR e2fsck . +.TP +.B SIGUSR1 +This signal causes +.B e2fsck +to start displaying a completion bar or emitting progress information. +(See discussion of the +.B \-C +option.) +.TP +.B SIGUSR2 +This signal causes +.B e2fsck +to stop displaying a completion bar or emitting progress information. +.SH REPORTING BUGS +Almost any piece of software will have bugs. If you manage to find a +filesystem which causes +.B e2fsck +to crash, or which +.B e2fsck +is unable to repair, please report it to the author. +.PP +Please include as much information as possible in your bug report. +Ideally, include a complete transcript of the +.B e2fsck +run, so I can see exactly what error messages are displayed. (Make sure +the messages printed by +.B e2fsck +are in English; if your system has been +configured so that +.BR e2fsck 's +messages have been translated into another language, please set the the +.B LC_ALL +environment variable to +.B C +so that the transcript of e2fsck's output will be useful to me.) +If you +have a writable filesystem where the transcript can be stored, the +.BR script (1) +program is a handy way to save the output of +.B e2fsck +to a file. +.PP +It is also useful to send the output of +.BR dumpe2fs (8). +If a specific inode or inodes seems to be giving +.B e2fsck +trouble, try running the +.BR debugfs (8) +command and send the output of the +.BR stat (1u) +command run on the relevant inode(s). If the inode is a directory, the +.B debugfs +.I dump +command will allow you to extract the contents of the directory inode, +which can sent to me after being first run through +.BR uuencode (1). +The most useful data you can send to help reproduce +the bug is a compressed raw image dump of the filesystem, generated using +.BR e2image (8). +See the +.BR e2image (8) +man page for more details. +.PP +Always include the full version string which +.B e2fsck +displays when it is run, so I know which version you are running. +.SH AUTHOR +This version of +.B e2fsck +was written by Theodore Ts'o <tytso@mit.edu>. +.SH SEE ALSO +.BR e2fsck.conf (5), +.BR badblocks (8), +.BR dumpe2fs (8), +.BR debugfs (8), +.BR e2image (8), +.BR mke2fs (8), +.BR tune2fs (8)
diff --git a/e2fsck/e2fsck.c b/e2fsck/e2fsck.c new file mode 100644 index 0000000..0ec1540 --- /dev/null +++ b/e2fsck/e2fsck.c
@@ -0,0 +1,235 @@ +/* + * e2fsck.c - a consistency checker for the new extended file system. + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include "config.h" +#include <errno.h> + +#include "e2fsck.h" +#include "problem.h" + +/* + * This function allocates an e2fsck context + */ +errcode_t e2fsck_allocate_context(e2fsck_t *ret) +{ + e2fsck_t context; + errcode_t retval; + char *time_env; + + retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context); + if (retval) + return retval; + + memset(context, 0, sizeof(struct e2fsck_struct)); + + context->process_inode_size = 256; + context->ext_attr_ver = 2; + context->blocks_per_page = 1; + context->htree_slack_percentage = 255; + + time_env = getenv("E2FSCK_TIME"); + if (time_env) + context->now = strtoul(time_env, NULL, 0); + else { + context->now = time(0); + if (context->now < 1262322000) /* January 1 2010 */ + context->flags |= E2F_FLAG_TIME_INSANE; + } + + *ret = context; + return 0; +} + +/* + * This function resets an e2fsck context; it is called when e2fsck + * needs to be restarted. + */ +errcode_t e2fsck_reset_context(e2fsck_t ctx) +{ + int i; + + ctx->flags &= E2F_RESET_FLAGS; + ctx->lost_and_found = 0; + ctx->bad_lost_and_found = 0; + if (ctx->inode_used_map) { + ext2fs_free_inode_bitmap(ctx->inode_used_map); + ctx->inode_used_map = 0; + } + if (ctx->inode_dir_map) { + ext2fs_free_inode_bitmap(ctx->inode_dir_map); + ctx->inode_dir_map = 0; + } + if (ctx->inode_reg_map) { + ext2fs_free_inode_bitmap(ctx->inode_reg_map); + ctx->inode_reg_map = 0; + } + if (ctx->block_found_map) { + ext2fs_free_block_bitmap(ctx->block_found_map); + ctx->block_found_map = 0; + } + if (ctx->inode_link_info) { + ext2fs_free_icount(ctx->inode_link_info); + ctx->inode_link_info = 0; + } + if (ctx->journal_io) { + if (ctx->fs && ctx->fs->io != ctx->journal_io) + io_channel_close(ctx->journal_io); + ctx->journal_io = 0; + } + if (ctx->fs && ctx->fs->dblist) { + ext2fs_free_dblist(ctx->fs->dblist); + ctx->fs->dblist = 0; + } + e2fsck_free_dir_info(ctx); +#ifdef ENABLE_HTREE + e2fsck_free_dx_dir_info(ctx); +#endif + if (ctx->refcount) { + ea_refcount_free(ctx->refcount); + ctx->refcount = 0; + } + if (ctx->refcount_extra) { + ea_refcount_free(ctx->refcount_extra); + ctx->refcount_extra = 0; + } + if (ctx->block_dup_map) { + ext2fs_free_block_bitmap(ctx->block_dup_map); + ctx->block_dup_map = 0; + } + if (ctx->block_ea_map) { + ext2fs_free_block_bitmap(ctx->block_ea_map); + ctx->block_ea_map = 0; + } + if (ctx->inode_bb_map) { + ext2fs_free_inode_bitmap(ctx->inode_bb_map); + ctx->inode_bb_map = 0; + } + if (ctx->inode_bad_map) { + ext2fs_free_inode_bitmap(ctx->inode_bad_map); + ctx->inode_bad_map = 0; + } + if (ctx->inode_imagic_map) { + ext2fs_free_inode_bitmap(ctx->inode_imagic_map); + ctx->inode_imagic_map = 0; + } + if (ctx->dirs_to_hash) { + ext2fs_u32_list_free(ctx->dirs_to_hash); + ctx->dirs_to_hash = 0; + } + + /* + * Clear the array of invalid meta-data flags + */ + if (ctx->invalid_inode_bitmap_flag) { + ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag); + ctx->invalid_inode_bitmap_flag = 0; + } + if (ctx->invalid_block_bitmap_flag) { + ext2fs_free_mem(&ctx->invalid_block_bitmap_flag); + ctx->invalid_block_bitmap_flag = 0; + } + if (ctx->invalid_inode_table_flag) { + ext2fs_free_mem(&ctx->invalid_inode_table_flag); + ctx->invalid_inode_table_flag = 0; + } + + /* Clear statistic counters */ + ctx->fs_directory_count = 0; + ctx->fs_regular_count = 0; + ctx->fs_blockdev_count = 0; + ctx->fs_chardev_count = 0; + ctx->fs_links_count = 0; + ctx->fs_symlinks_count = 0; + ctx->fs_fast_symlinks_count = 0; + ctx->fs_fifo_count = 0; + ctx->fs_total_count = 0; + ctx->fs_badblocks_count = 0; + ctx->fs_sockets_count = 0; + ctx->fs_ind_count = 0; + ctx->fs_dind_count = 0; + ctx->fs_tind_count = 0; + ctx->fs_fragmented = 0; + ctx->fs_fragmented_dir = 0; + ctx->large_files = 0; + + for (i=0; i < MAX_EXTENT_DEPTH_COUNT; i++) + ctx->extent_depth_count[i] = 0; + + /* Reset the superblock to the user's requested value */ + ctx->superblock = ctx->use_superblock; + + return 0; +} + +void e2fsck_free_context(e2fsck_t ctx) +{ + if (!ctx) + return; + + e2fsck_reset_context(ctx); + if (ctx->blkid) + blkid_put_cache(ctx->blkid); + + if (ctx->profile) + profile_release(ctx->profile); + + if (ctx->filesystem_name) + ext2fs_free_mem(&ctx->filesystem_name); + + if (ctx->device_name) + ext2fs_free_mem(&ctx->device_name); + + if (ctx->log_fn) + free(ctx->log_fn); + + ext2fs_free_mem(&ctx); +} + +/* + * This function runs through the e2fsck passes and calls them all, + * returning restart, abort, or cancel as necessary... + */ +typedef void (*pass_t)(e2fsck_t ctx); + +static pass_t e2fsck_passes[] = { + e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4, + e2fsck_pass5, 0 }; + +#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART) + +int e2fsck_run(e2fsck_t ctx) +{ + int i; + pass_t e2fsck_pass; + +#ifdef HAVE_SETJMP_H + if (setjmp(ctx->abort_loc)) { + ctx->flags &= ~E2F_FLAG_SETJMP_OK; + return (ctx->flags & E2F_FLAG_RUN_RETURN); + } + ctx->flags |= E2F_FLAG_SETJMP_OK; +#endif + + for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) { + if (ctx->flags & E2F_FLAG_RUN_RETURN) + break; + if (e2fsck_mmp_update(ctx->fs)) + fatal_error(ctx, 0); + e2fsck_pass(ctx); + if (ctx->progress) + (void) (ctx->progress)(ctx, 0, 0, 0); + } + ctx->flags &= ~E2F_FLAG_SETJMP_OK; + + if (ctx->flags & E2F_FLAG_RUN_RETURN) + return (ctx->flags & E2F_FLAG_RUN_RETURN); + return 0; +}
diff --git a/e2fsck/e2fsck.conf.5.in b/e2fsck/e2fsck.conf.5.in new file mode 100644 index 0000000..9ebfbbf --- /dev/null +++ b/e2fsck/e2fsck.conf.5.in
@@ -0,0 +1,431 @@ +.\" -*- nroff -*- +.\" Copyright 2006 by Theodore Ts'o. All Rights Reserved. +.\" This file may be copied under the terms of the GNU Public License. +.\" +.TH e2fsck.conf 5 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@" +.SH NAME +e2fsck.conf \- Configuration file for e2fsck +.SH DESCRIPTION +.I e2fsck.conf +is the configuration file for +.BR e2fsck (8). +It controls the default behavior of +.BR e2fsck (8) +while it is checking ext2, ext3, or ext4 filesystems. +.PP +The +.I e2fsck.conf +file uses an INI-style format. Stanzas, or top-level sections, are +delimited by square braces: [ ]. Within each section, each line +defines a relation, which assigns tags to values, or to a subsection, +which contains further relations or subsections. +.\" Tags can be assigned multiple values +An example of the INI-style format used by this configuration file +follows below: +.P + [section1] +.br + tag1 = value_a +.br + tag1 = value_b +.br + tag2 = value_c +.P + [section 2] +.br + tag3 = { +.br + subtag1 = subtag_value_a +.br + subtag1 = subtag_value_b +.br + subtag2 = subtag_value_c +.br + } +.br + tag1 = value_d +.br + tag2 = value_e +.br + } +.P +Comments are delimited by a semicolon (';') or a hash ('#') character +at the beginning of the comment, and are terminated by the end of +line character. +.P +Tags and values must be quoted using double quotes if they contain +spaces. Within a quoted string, the standard backslash interpretations +apply: "\en" (for the newline character), +"\et" (for the tab character), "\eb" (for the backspace character), +and "\e\e" (for the backslash character). +.P +The following stanzas are used in the +.I e2fsck.conf +file. They will be described in more detail in future sections of this +document. +.TP +.I [options] +This stanza contains general configuration parameters for +.BR e2fsck 's +behavior. +.TP +.I [problems] +This stanza allows the administrator to reconfigure how e2fsck handles +various filesystem inconsistencies. +.TP +.I [scratch_files] +This stanza controls when e2fsck will attempt to use scratch files to +reduce the need for memory. +.SH THE [options] STANZA +The following relations are defined in the +.I [options] +stanza. +.TP +.I allow_cancellation +If this relation is set to a boolean value of true, then if the user +interrupts e2fsck using ^C, and the filesystem is not explicitly flagged +as containing errors, e2fsck will exit with an exit status of 0 instead +of 32. This setting defaults to false. +.TP +.I accept_time_fudge +Unfortunately, due to Windows' unfortunate design decision +to configure the hardware clock to tick localtime, instead +of the more proper and less error-prone UTC time, many +users end up in the situation where the system clock is +incorrectly set at the time when e2fsck is run. +.IP +Historically this was usually due to some distributions +having buggy init scripts and/or installers that didn't +correctly detect this case and take appropriate +countermeasures. Unfortunately, this is occasionally +true even today, usually due to a +buggy or misconfigured virtualization manager or the +installer not having access to a network time server +during the installation process. So by default, we allow +the superblock times to be fudged by up to 24 hours. +This can be disabled by setting +.I accept_time_fudge +to the +boolean value of false. This setting defaults to true. +.TP +.I broken_system_clock +The +.BR e2fsck (8) +program has some heuristics that assume that the system clock is +correct. In addition, many system programs make similar assumptions. +For example, the UUID library depends on time not going backwards in +order for it to be able to make its guarantees about issuing universally +unique ID's. Systems with broken system clocks, are well, broken. +However, broken system clocks, particularly in embedded systems, do +exist. E2fsck will attempt to use heuristics to determine if the time +can not be trusted; and to skip time-based checks if this is true. If +this boolean is set to true, then e2fsck will always assume that the +system clock can not be trusted. +.TP +.I buggy_init_scripts +This boolean relation is an alias for +.I accept_time_fudge +for backwards compatibility; it used to +be that the behavior defined by +.I accept_time_fudge +above defaulted to false, and +.I buggy_init_scripts +would enable superblock time field to be wrong by up to 24 hours. When +we changed the default, we also renamed this boolean relation to +.IR accept_time_fudge. +.TP +.I clear_test_fs_flag +This boolean relation controls whether or not +.BR e2fsck (8) +will offer to clear +the test_fs flag if the ext4 filesystem is available on the system. It +defaults to true. +.TP +.I defer_check_on_battery +This boolean relation controls whether or not the interval between +filesystem checks (either based on time or number of mounts) should +be doubled if the system is running on battery. This setting defaults to +true. +.TP +.I indexed_dir_slack_percentage +When +.BR e2fsck (8) +repacks a indexed directory, reserve the specified percentage of +empty space in each leaf nodes so that a few new entries can +be added to the directory without splitting leaf nodes, so that +the average fill ratio of directories can be maintained at a +higher, more efficient level. This relation defaults to 20 +percent. +.TP +.I log_dir +If the +.I log_filename +relation contains a relative pathname, then the log file will be placed +in the directory named by the +.I log_dir +relation. +.TP +.I log_dir_fallback +This relation contains an alternate directory that will be used if the +directory specified by +.I log_dir +is not available or is not writeable. +.TP +.I log_dir_wait +If this boolean relation is true, them if the directories specified by +.I log_dir +or +.I log_dir_fallback +are not available or are not yet writeable, e2fsck will save the output +in a memory buffer, and a child process will periodically test to see if +the log directory has become available after the boot sequence has +mounted the requiste filesytem for reading/writing. This implements the +functionality provided by +.BR logsave (8) +for e2fsck log files. +.TP +.I log_filename +This relation specifies the file name where a copy of e2fsck's output +will be written. If certain problem reports are suppressed using the +.I max_count_problems +relation, (or on a per-problem basis using the +.I max_count +relation), the full set of problem reports will be written to the log +file. The filename may contain various percent-expressions (%D, %T, %N, +etc.) which will be expanded so that the file name for the log file can +include things like date, time, device name, and other run-time +parameters. See the +.B LOGGING +section for more details. +.TP +.I max_count_problems +This relation specifies the maximum number of problem reports of a +particular type will be printed to stdout before further problem reports +of that type are squelched. This can be useful if the console is slow +(i.e., connected to a serial port) and so a large amount of output could +end up delaying the boot process for a long time (potentially hours). +.TP +.I report_features +If this boolean relation is true, e2fsck will print the file system +features as part of its verbose reporting (i.e., if the +.B -v +option is specified) +.TP +.I report_time +If this boolean relation is true, e2fsck will run as if the options +.B -tt +are always specified. This will cause e2fsck to print timing statistics +on a pass by pass basis for full file system checks. +.TP +.I report_verbose +If this boolean relation is true, e2fsck will run as if the option +.B -v +is always specified. This will cause e2fsck to print some additional +information at the end of each full file system check. +.SH THE [problems] STANZA +Each tag in the +.I [problems] +stanza names a problem code specified with a leading "0x" followed by +six hex digits. +The value of the tag is a subsection where the relations in that +subsection override the default treatment of that particular problem +code. +.P +Note that inappropriate settings in this stanza may cause +.B e2fsck +to behave incorrectly, or even crash. Most system administrators should +not be making changes to this section without referring to source code. +.P +Within each problem code's subsection, the following tags may be used: +.TP +.I description +This relation allows the message which is printed when this filesystem +inconsistency is detected to be overridden. +.TP +.I preen_ok +This boolean relation overrides the default behavior controlling +whether this filesystem problem should be automatically fixed when +.B e2fsck +is running in preen mode. +.TP +.I max_count +This integer relation overrides the +.I max_count_problems +parameter (set in the options section) for this particular problem. +.TP +.I no_ok +This boolean relation overrides the default behavior determining +whether or not the filesystem will be marked as inconsistent if the user +declines to fix the reported problem. +.TP +.I no_default +This boolean relation overrides whether the default answer for this +problem (or question) should be "no". +.TP +.I preen_nomessage +This boolean relation overrides the default behavior controlling +whether or not the description for this filesystem problem should +be suppressed when +.B e2fsck +is running in preen mode. +.TP +.I no_nomsg +This boolean relation overrides the default behavior controlling +whether or not the description for this filesystem problem should +be suppressed when a problem forced not to be fixed, either because +.B e2fsck +is run with the +.B -n +option or because the +.I force_no +flag has been set for the problem. +.TP +.I force_no +This boolean option, if set to true, forces a problem to never be fixed. +That is, it will be as if the user problem responds 'no' to the question +of 'should this problem be fixed?'. The +.I force_no +option even overrides the +.B -y +option given on the command-line (just for the specific problem, of course). +.SH THE [scratch_files] STANZA +The following relations are defined in the +.I [scratch_files] +stanza. +.TP +.I directory +If the directory named by this relation exists and is writeable, then +e2fsck will attempt to use this directory to store scratch files instead +of using in-memory data structures. +.TP +.I numdirs_threshold +If this relation is set, then in-memory data structures be used if the +number of directories in the filesystem are fewer than amount specified. +.TP +.I dirinfo +This relation controls whether or not the scratch file directory is used +instead of an in-memory data structure for directory information. It +defaults to true. +.TP +.I icount +This relation controls whether or not the scratch file directory is used +instead of an in-memory data structure when tracking inode counts. It +defaults to true. +.SH LOGGING +E2fsck has the facility to save the information from an e2fsck run in a +directory so that a system administrator can review its output at their +leisure. This allows information captured during the automatic e2fsck +preen run, as well as a manually started e2fsck run, to be saved for +posterity. This facility is controlled by the +.IR log_filename , +.IR log_dir , +.IR log_dir_fallback , +and +.I log_dir_wait +relations in the +.I [options] +stanza. +.PP +The filename in +.I log_filename +may contain the following percent-expressions that will be expanded as +follows. +.TP +.B %d +The current day of the month +.TP +.B %D +The current date; this is a equivalent of +.B %Y%m%d +.TP +.B %h +The hostname of the system. +.TP +.B %H +The current hour in 24-hour format (00..23) +.TP +.B %m +The current month as a two-digit number (01..12) +.TP +.B %M +The current minute (00..59) +.TP +.B %N +The name of the block device containing the file system, with any +directory pathname stripped off. +.TP +.B %p +The pid of the e2fsck process +.TP +.B %s +The current time expressed as the number of seconds since 1970-01-01 +00:00:00 UTC +.TP +.B %S +The current second (00..59) +.TP +.B %T +The current time; this is equivalent of +.B %H%M%S +.TP +.B %u +The name of the user running e2fsck. +.TP +.B %U +This percent expression does not expand to anything, but it signals that +any following date or time expressions should be expressed in UTC time +instead of the local timzeone. +.TP +.B %y +The last two digits of the current year (00..99) +.TP +.B %Y +The current year (i.e., 2012). +.SH EXAMPLES +The following recipe will prevent e2fsck from aborting during the boot +process when a filesystem contains orphaned files. (Of course, this is +not always a good idea, since critical files that are needed for the +security of the system could potentially end up in lost+found, and +starting the system without first having a system administrator check +things out may be dangerous.) +.P +.br + [problems] +.br + 0x040002 = { +.br + preen_ok = true +.br + description = "@u @i %i. " +.br + } +.P +The following recipe will cause an e2fsck logfile to be written to the +directory /var/log/e2fsck, with a filename that contains the device +name, the hostname of the system, the date, and time: e.g., +"e2fsck-sda3.server.INFO.20120314-112142". If the directory containing +/var/log is located on the root file system +which is initially mounted read-only, then the output will be saved in +memory and written out once the root file system has been remounted +read/write. To avoid too much detail from being written to the serial +console (which could potentially slow down the boot sequence), only print +no more than 16 instances of each type of file system corruption. +.P +.br + [options] +.br + max_count_problems = 16 +.br + log_dir = /var/log/e2fsck +.br + log_filename = e2fsck-%N.%h.INFO.%D-%T +.br + log_dir_wait = true +.P +.SH FILES +.TP +.I /etc/e2fsck.conf +The configuration file for +.BR e2fsck (8). +.SH SEE ALSO +.BR e2fsck (8)
diff --git a/e2fsck/e2fsck.h b/e2fsck/e2fsck.h new file mode 100644 index 0000000..f904026 --- /dev/null +++ b/e2fsck/e2fsck.h
@@ -0,0 +1,587 @@ +/* + * e2fsck.h + * + * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be + * redistributed under the terms of the GNU Public License. + * + */ + +#ifndef _E2FSCK_H +#define _E2FSCK_H + +#include <stdio.h> +#include <string.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <stdlib.h> +#include <time.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef HAVE_SETJMP_H +#include <setjmp.h> +#endif + +#if EXT2_FLAT_INCLUDES +#include "ext2_fs.h" +#include "ext2fs.h" +#include "blkid.h" +#else +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fs.h" +#include "blkid/blkid.h" +#endif + +#include "profile.h" +#include "prof_err.h" + +#ifdef ENABLE_NLS +#include <libintl.h> +#include <locale.h> +#define _(a) (gettext (a)) +#ifdef gettext_noop +#define N_(a) gettext_noop (a) +#else +#define N_(a) (a) +#endif +#define P_(singular, plural, n) (ngettext (singular, plural, n)) +#ifndef NLS_CAT_NAME +#define NLS_CAT_NAME "e2fsprogs" +#endif +#ifndef LOCALEDIR +#define LOCALEDIR "/usr/share/locale" +#endif +#else +#define _(a) (a) +#define N_(a) a +#define P_(singular, plural, n) ((n) == 1 ? (singular) : (plural)) +#endif + +#ifdef __GNUC__ +#define E2FSCK_ATTR(x) __attribute__(x) +#else +#define E2FSCK_ATTR(x) +#endif + +#include "quota/quotaio.h" + +/* + * Exit codes used by fsck-type programs + */ +#define FSCK_OK 0 /* No errors */ +#define FSCK_NONDESTRUCT 1 /* File system errors corrected */ +#define FSCK_REBOOT 2 /* System should be rebooted */ +#define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */ +#define FSCK_ERROR 8 /* Operational error */ +#define FSCK_USAGE 16 /* Usage or syntax error */ +#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */ +#define FSCK_LIBRARY 128 /* Shared library error */ + +/* + * The last ext2fs revision level that this version of e2fsck is able to + * support + */ +#define E2FSCK_CURRENT_REV 1 + +/* + * The directory information structure; stores directory information + * collected in earlier passes, to avoid disk i/o in fetching the + * directory information. + */ +struct dir_info { + ext2_ino_t ino; /* Inode number */ + ext2_ino_t dotdot; /* Parent according to '..' */ + ext2_ino_t parent; /* Parent according to treewalk */ +}; + + +/* + * The indexed directory information structure; stores information for + * directories which contain a hash tree index. + */ +struct dx_dir_info { + ext2_ino_t ino; /* Inode number */ + int numblocks; /* number of blocks */ + int hashversion; + short depth; /* depth of tree */ + struct dx_dirblock_info *dx_block; /* Array of size numblocks */ +}; + +#define DX_DIRBLOCK_ROOT 1 +#define DX_DIRBLOCK_LEAF 2 +#define DX_DIRBLOCK_NODE 3 +#define DX_DIRBLOCK_CORRUPT 4 +#define DX_DIRBLOCK_CLEARED 8 + +struct dx_dirblock_info { + int type; + blk64_t phys; + int flags; + blk64_t parent; + ext2_dirhash_t min_hash; + ext2_dirhash_t max_hash; + ext2_dirhash_t node_min_hash; + ext2_dirhash_t node_max_hash; +}; + +#define DX_FLAG_REFERENCED 1 +#define DX_FLAG_DUP_REF 2 +#define DX_FLAG_FIRST 4 +#define DX_FLAG_LAST 8 + +#define RESOURCE_TRACK + +#ifdef RESOURCE_TRACK +/* + * This structure is used for keeping track of how much resources have + * been used for a particular pass of e2fsck. + */ +struct resource_track { + struct timeval time_start; + struct timeval user_start; + struct timeval system_start; + void *brk_start; + unsigned long long bytes_read; + unsigned long long bytes_written; +}; +#endif + +/* + * E2fsck options + */ +#define E2F_OPT_READONLY 0x0001 +#define E2F_OPT_PREEN 0x0002 +#define E2F_OPT_YES 0x0004 +#define E2F_OPT_NO 0x0008 +#define E2F_OPT_TIME 0x0010 +#define E2F_OPT_TIME2 0x0020 +#define E2F_OPT_CHECKBLOCKS 0x0040 +#define E2F_OPT_DEBUG 0x0080 +#define E2F_OPT_FORCE 0x0100 +#define E2F_OPT_WRITECHECK 0x0200 +#define E2F_OPT_COMPRESS_DIRS 0x0400 +#define E2F_OPT_FRAGCHECK 0x0800 +#define E2F_OPT_JOURNAL_ONLY 0x1000 /* only replay the journal */ +#define E2F_OPT_DISCARD 0x2000 + +/* + * E2fsck flags + */ +#define E2F_FLAG_ABORT 0x0001 /* Abort signaled */ +#define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */ +#define E2F_FLAG_SIGNAL_MASK 0x0003 +#define E2F_FLAG_RESTART 0x0004 /* Restart signaled */ +#define E2F_FLAG_RESTART_LATER 0x0008 /* Restart after all iterations done */ + +#define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */ + +#define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */ +#define E2F_FLAG_PROG_SUPPRESS 0x0040 /* Progress suspended */ +#define E2F_FLAG_JOURNAL_INODE 0x0080 /* Create a new ext3 journal inode */ +#define E2F_FLAG_SB_SPECIFIED 0x0100 /* The superblock was explicitly + * specified by the user */ +#define E2F_FLAG_RESTARTED 0x0200 /* E2fsck has been restarted */ +#define E2F_FLAG_RESIZE_INODE 0x0400 /* Request to recreate resize inode */ +#define E2F_FLAG_GOT_DEVSIZE 0x0800 /* Device size has been fetched */ +#define E2F_FLAG_EXITING 0x1000 /* E2fsck exiting due to errors */ +#define E2F_FLAG_TIME_INSANE 0x2000 /* Time is insane */ +#define E2F_FLAG_PROBLEMS_FIXED 0x4000 /* At least one problem was fixed */ + +#define E2F_RESET_FLAGS (E2F_FLAG_TIME_INSANE | E2F_FLAG_PROBLEMS_FIXED) + +/* + * Defines for indicating the e2fsck pass number + */ +#define E2F_PASS_1 1 +#define E2F_PASS_2 2 +#define E2F_PASS_3 3 +#define E2F_PASS_4 4 +#define E2F_PASS_5 5 +#define E2F_PASS_1B 6 + +/* + * Define the extended attribute refcount structure + */ +typedef struct ea_refcount *ext2_refcount_t; + +/* + * This is the global e2fsck structure. + */ +typedef struct e2fsck_struct *e2fsck_t; + +#define MAX_EXTENT_DEPTH_COUNT 5 + +struct e2fsck_struct { + ext2_filsys fs; + const char *program_name; + char *filesystem_name; + char *device_name; + char *io_options; + FILE *logf; + char *log_fn; + int flags; /* E2fsck internal flags */ + int options; + int blocksize; /* blocksize */ + blk64_t use_superblock; /* sb requested by user */ + blk64_t superblock; /* sb used to open fs */ + blk64_t num_blocks; /* Total number of blocks */ + blk64_t free_blocks; + ino_t free_inodes; + int mount_flags; + int openfs_flags; + blkid_cache blkid; /* blkid cache */ + +#ifdef HAVE_SETJMP_H + jmp_buf abort_loc; +#endif + unsigned long abort_code; + + int (*progress)(e2fsck_t ctx, int pass, unsigned long cur, + unsigned long max); + + ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */ + ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */ + ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */ + ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */ + ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */ + ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/ + + ext2fs_block_bitmap block_found_map; /* Blocks which are in use */ + ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */ + ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */ + + /* + * Inode count arrays + */ + ext2_icount_t inode_count; + ext2_icount_t inode_link_info; + + ext2_refcount_t refcount; + ext2_refcount_t refcount_extra; + + /* + * Array of flags indicating whether an inode bitmap, block + * bitmap, or inode table is invalid + */ + int *invalid_inode_bitmap_flag; + int *invalid_block_bitmap_flag; + int *invalid_inode_table_flag; + int invalid_bitmaps; /* There are invalid bitmaps/itable */ + + /* + * Block buffer + */ + char *block_buf; + + /* + * For pass1_check_directory and pass1_get_blocks + */ + ext2_ino_t stashed_ino; + struct ext2_inode *stashed_inode; + + /* + * Location of the lost and found directory + */ + ext2_ino_t lost_and_found; + int bad_lost_and_found; + + /* + * Directory information + */ + struct dir_info_db *dir_info; + + /* + * Indexed directory information + */ + int dx_dir_info_count; + int dx_dir_info_size; + struct dx_dir_info *dx_dir_info; + + /* + * Directories to hash + */ + ext2_u32_list dirs_to_hash; + + /* + * Tuning parameters + */ + int process_inode_size; + int inode_buffer_blocks; + unsigned int htree_slack_percentage; + + /* + * ext3 journal support + */ + io_channel journal_io; + char *journal_name; + + /* + * Ext4 quota support + */ + quota_ctx_t qctx; +#ifdef RESOURCE_TRACK + /* + * For timing purposes + */ + struct resource_track global_rtrack; +#endif + + /* + * How we display the progress update (for unix) + */ + int progress_fd; + int progress_pos; + int progress_last_percent; + unsigned int progress_last_time; + int interactive; /* Are we connected directly to a tty? */ + char start_meta[2], stop_meta[2]; + + /* File counts */ + __u32 fs_directory_count; + __u32 fs_regular_count; + __u32 fs_blockdev_count; + __u32 fs_chardev_count; + __u32 fs_links_count; + __u32 fs_symlinks_count; + __u32 fs_fast_symlinks_count; + __u32 fs_fifo_count; + __u32 fs_total_count; + __u32 fs_badblocks_count; + __u32 fs_sockets_count; + __u32 fs_ind_count; + __u32 fs_dind_count; + __u32 fs_tind_count; + __u32 fs_fragmented; + __u32 fs_fragmented_dir; + __u32 large_files; + __u32 fs_ext_attr_inodes; + __u32 fs_ext_attr_blocks; + __u32 extent_depth_count[MAX_EXTENT_DEPTH_COUNT]; + + /* misc fields */ + time_t now; + time_t time_fudge; /* For working around buggy init scripts */ + int ext_attr_ver; + profile_t profile; + int blocks_per_page; + + /* Reserve blocks for root and l+f re-creation */ + blk64_t root_repair_block, lnf_repair_block; + + /* + * For the use of callers of the e2fsck functions; not used by + * e2fsck functions themselves. + */ + void *priv_data; +}; + +/* Used by the region allocation code */ +typedef __u32 region_addr_t; +typedef struct region_struct *region_t; + +#ifndef HAVE_STRNLEN +#define strnlen(str, x) e2fsck_strnlen((str),(x)) +extern int e2fsck_strnlen(const char * s, int count); +#endif + +/* + * Procedure declarations + */ + +extern void e2fsck_pass1(e2fsck_t ctx); +extern void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf); +extern void e2fsck_pass2(e2fsck_t ctx); +extern void e2fsck_pass3(e2fsck_t ctx); +extern void e2fsck_pass4(e2fsck_t ctx); +extern void e2fsck_pass5(e2fsck_t ctx); + +/* e2fsck.c */ +extern errcode_t e2fsck_allocate_context(e2fsck_t *ret); +extern errcode_t e2fsck_reset_context(e2fsck_t ctx); +extern void e2fsck_free_context(e2fsck_t ctx); +extern int e2fsck_run(e2fsck_t ctx); + + +/* badblock.c */ +extern void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file, + int replace_bad_blocks); + +/* crc32.c */ +extern __u32 crc32_be(__u32 crc, unsigned char const *p, size_t len); + +/* dirinfo.c */ +extern void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent); +extern void e2fsck_free_dir_info(e2fsck_t ctx); +extern int e2fsck_get_num_dirinfo(e2fsck_t ctx); +extern struct dir_info_iter *e2fsck_dir_info_iter_begin(e2fsck_t ctx); +extern struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, + struct dir_info_iter *); +extern void e2fsck_dir_info_iter_end(e2fsck_t ctx, struct dir_info_iter *); +extern int e2fsck_dir_info_set_parent(e2fsck_t ctx, ext2_ino_t ino, + ext2_ino_t parent); +extern int e2fsck_dir_info_set_dotdot(e2fsck_t ctx, ext2_ino_t ino, + ext2_ino_t dotdot); +extern int e2fsck_dir_info_get_parent(e2fsck_t ctx, ext2_ino_t ino, + ext2_ino_t *parent); +extern int e2fsck_dir_info_get_dotdot(e2fsck_t ctx, ext2_ino_t ino, + ext2_ino_t *dotdot); + +/* dx_dirinfo.c */ +extern void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks); +extern struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino); +extern void e2fsck_free_dx_dir_info(e2fsck_t ctx); +extern int e2fsck_get_num_dx_dirinfo(e2fsck_t ctx); +extern struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control); + +/* ea_refcount.c */ +extern errcode_t ea_refcount_create(int size, ext2_refcount_t *ret); +extern void ea_refcount_free(ext2_refcount_t refcount); +extern errcode_t ea_refcount_fetch(ext2_refcount_t refcount, blk64_t blk, int *ret); +extern errcode_t ea_refcount_increment(ext2_refcount_t refcount, + blk64_t blk, int *ret); +extern errcode_t ea_refcount_decrement(ext2_refcount_t refcount, + blk64_t blk, int *ret); +extern errcode_t ea_refcount_store(ext2_refcount_t refcount, + blk64_t blk, int count); +extern blk_t ext2fs_get_refcount_size(ext2_refcount_t refcount); +extern void ea_refcount_intr_begin(ext2_refcount_t refcount); +extern blk64_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret); + +/* ehandler.c */ +extern const char *ehandler_operation(const char *op); +extern void ehandler_init(io_channel channel); + +/* journal.c */ +extern errcode_t e2fsck_check_ext3_journal(e2fsck_t ctx); +extern errcode_t e2fsck_run_ext3_journal(e2fsck_t ctx); +extern void e2fsck_move_ext3_journal(e2fsck_t ctx); +extern int e2fsck_fix_ext3_journal_hint(e2fsck_t ctx); + +/* logfile.c */ +extern void set_up_logging(e2fsck_t ctx); + +/* quota.c */ +extern void e2fsck_hide_quota(e2fsck_t ctx); + +/* pass1.c */ +extern void e2fsck_setup_tdb_icount(e2fsck_t ctx, int flags, + ext2_icount_t *ret); +extern void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int use_shortcuts); +extern int e2fsck_pass1_check_device_inode(ext2_filsys fs, + struct ext2_inode *inode); +extern int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, char *buf); +extern void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino, + struct ext2_inode *inode, int restart_flag, + const char *source); +extern void e2fsck_intercept_block_allocations(e2fsck_t ctx); + +/* pass2.c */ +extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, + ext2_ino_t ino, char *buf); + +/* pass3.c */ +extern int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode); +extern errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir, + int num, int gauranteed_size); +extern ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix); +extern errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, + int adj); + + +/* region.c */ +extern region_t region_create(region_addr_t min, region_addr_t max); +extern void region_free(region_t region); +extern int region_allocate(region_t region, region_addr_t start, int n); + +/* rehash.c */ +errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino); +void e2fsck_rehash_directories(e2fsck_t ctx); + +/* sigcatcher.c */ +void sigcatcher_setup(void); + +/* super.c */ +void check_super_block(e2fsck_t ctx); +int check_backup_super_block(e2fsck_t ctx); +void check_resize_inode(e2fsck_t ctx); + +/* util.c */ +extern void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size, + const char *description); +extern int ask(e2fsck_t ctx, const char * string, int def); +extern int ask_yn(e2fsck_t ctx, const char * string, int def); +extern void fatal_error(e2fsck_t ctx, const char * fmt_string); +extern void log_out(e2fsck_t ctx, const char *fmt, ...) + E2FSCK_ATTR((format(printf, 2, 3))); +extern void log_err(e2fsck_t ctx, const char *fmt, ...) + E2FSCK_ATTR((format(printf, 2, 3))); +extern void e2fsck_read_bitmaps(e2fsck_t ctx); +extern void e2fsck_write_bitmaps(e2fsck_t ctx); +extern void preenhalt(e2fsck_t ctx); +extern char *string_copy(e2fsck_t ctx, const char *str, int len); +extern errcode_t e2fsck_zero_blocks(ext2_filsys fs, blk_t blk, int num, + blk_t *ret_blk, int *ret_count); +extern int fs_proc_check(const char *fs_name); +extern int check_for_modules(const char *fs_name); +#ifdef RESOURCE_TRACK +extern void print_resource_track(e2fsck_t ctx, + const char *desc, + struct resource_track *track, + io_channel channel); +extern void init_resource_track(struct resource_track *track, + io_channel channel); +#else +#define print_resource_track(ctx, desc, track, channel) do { } while (0) +#define init_resource_track(track, channel) do { } while (0) +#endif +extern int inode_has_valid_blocks(struct ext2_inode *inode); +extern void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino, + struct ext2_inode * inode, const char * proc); +extern void e2fsck_read_inode_full(e2fsck_t ctx, unsigned long ino, + struct ext2_inode *inode, + const int bufsize, const char *proc); +extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino, + struct ext2_inode * inode, const char * proc); +extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino, + struct ext2_inode * inode, int bufsize, + const char *proc); +#ifdef MTRACE +extern void mtrace_print(char *mesg); +#endif +extern blk64_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, + const char *name, io_manager manager); +extern int ext2_file_type(unsigned int mode); +extern int write_all(int fd, char *buf, size_t count); +void dump_mmp_msg(struct mmp_struct *mmp, const char *msg); +errcode_t e2fsck_mmp_update(ext2_filsys fs); + +extern void e2fsck_set_bitmap_type(ext2_filsys fs, + unsigned int default_type, + const char *profile_name, + unsigned int *old_type); +extern errcode_t e2fsck_allocate_inode_bitmap(ext2_filsys fs, + const char *descr, + int default_type, + const char *profile_name, + ext2fs_inode_bitmap *ret); +extern errcode_t e2fsck_allocate_block_bitmap(ext2_filsys fs, + const char *descr, + int default_type, + const char *profile_name, + ext2fs_block_bitmap *ret); +extern errcode_t e2fsck_allocate_subcluster_bitmap(ext2_filsys fs, + const char *descr, + int default_type, + const char *profile_name, + ext2fs_block_bitmap *ret); + +/* unix.c */ +extern void e2fsck_clear_progbar(e2fsck_t ctx); +extern int e2fsck_simple_progress(e2fsck_t ctx, const char *label, + float percent, unsigned int dpynum); +#endif /* _E2FSCK_H */
diff --git a/e2fsck/ea_refcount.c b/e2fsck/ea_refcount.c new file mode 100644 index 0000000..fcfaf49 --- /dev/null +++ b/e2fsck/ea_refcount.c
@@ -0,0 +1,461 @@ +/* + * ea_refcount.c + * + * Copyright (C) 2001 Theodore Ts'o. This file may be + * redistributed under the terms of the GNU Public License. + */ + +#include "config.h" +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <string.h> +#include <stdio.h> + +#ifdef TEST_PROGRAM +#undef ENABLE_NLS +#endif +#include "e2fsck.h" + +/* + * The strategy we use for keeping track of EA refcounts is as + * follows. We keep a sorted array of first EA blocks and its + * reference counts. Once the refcount has dropped to zero, it is + * removed from the array to save memory space. Once the EA block is + * checked, its bit is set in the block_ea_map bitmap. + */ +struct ea_refcount_el { + blk64_t ea_blk; + int ea_count; +}; + +struct ea_refcount { + blk_t count; + blk_t size; + blk_t cursor; + struct ea_refcount_el *list; +}; + +void ea_refcount_free(ext2_refcount_t refcount) +{ + if (!refcount) + return; + + if (refcount->list) + ext2fs_free_mem(&refcount->list); + ext2fs_free_mem(&refcount); +} + +errcode_t ea_refcount_create(int size, ext2_refcount_t *ret) +{ + ext2_refcount_t refcount; + errcode_t retval; + size_t bytes; + + retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount); + if (retval) + return retval; + memset(refcount, 0, sizeof(struct ea_refcount)); + + if (!size) + size = 500; + refcount->size = size; + bytes = (size_t) (size * sizeof(struct ea_refcount_el)); +#ifdef DEBUG + printf("Refcount allocated %d entries, %d bytes.\n", + refcount->size, bytes); +#endif + retval = ext2fs_get_mem(bytes, &refcount->list); + if (retval) + goto errout; + memset(refcount->list, 0, bytes); + + refcount->count = 0; + refcount->cursor = 0; + + *ret = refcount; + return 0; + +errout: + ea_refcount_free(refcount); + return(retval); +} + +/* + * collapse_refcount() --- go through the refcount array, and get rid + * of any count == zero entries + */ +static void refcount_collapse(ext2_refcount_t refcount) +{ + unsigned int i, j; + struct ea_refcount_el *list; + + list = refcount->list; + for (i = 0, j = 0; i < refcount->count; i++) { + if (list[i].ea_count) { + if (i != j) + list[j] = list[i]; + j++; + } + } +#if defined(DEBUG) || defined(TEST_PROGRAM) + printf("Refcount_collapse: size was %d, now %d\n", + refcount->count, j); +#endif + refcount->count = j; +} + + +/* + * insert_refcount_el() --- Insert a new entry into the sorted list at a + * specified position. + */ +static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount, + blk64_t blk, int pos) +{ + struct ea_refcount_el *el; + errcode_t retval; + blk_t new_size = 0; + int num; + + if (refcount->count >= refcount->size) { + new_size = refcount->size + 100; +#ifdef DEBUG + printf("Reallocating refcount %d entries...\n", new_size); +#endif + retval = ext2fs_resize_mem((size_t) refcount->size * + sizeof(struct ea_refcount_el), + (size_t) new_size * + sizeof(struct ea_refcount_el), + &refcount->list); + if (retval) + return 0; + refcount->size = new_size; + } + num = (int) refcount->count - pos; + if (num < 0) + return 0; /* should never happen */ + if (num) { + memmove(&refcount->list[pos+1], &refcount->list[pos], + sizeof(struct ea_refcount_el) * num); + } + refcount->count++; + el = &refcount->list[pos]; + el->ea_count = 0; + el->ea_blk = blk; + return el; +} + + +/* + * get_refcount_el() --- given an block number, try to find refcount + * information in the sorted list. If the create flag is set, + * and we can't find an entry, create one in the sorted list. + */ +static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount, + blk64_t blk, int create) +{ + int low, high, mid; + + if (!refcount || !refcount->list) + return 0; +retry: + low = 0; + high = (int) refcount->count-1; + if (create && ((refcount->count == 0) || + (blk > refcount->list[high].ea_blk))) { + if (refcount->count >= refcount->size) + refcount_collapse(refcount); + + return insert_refcount_el(refcount, blk, + (unsigned) refcount->count); + } + if (refcount->count == 0) + return 0; + + if (refcount->cursor >= refcount->count) + refcount->cursor = 0; + if (blk == refcount->list[refcount->cursor].ea_blk) + return &refcount->list[refcount->cursor++]; +#ifdef DEBUG + printf("Non-cursor get_refcount_el: %u\n", blk); +#endif + while (low <= high) { + mid = (low+high)/2; + if (blk == refcount->list[mid].ea_blk) { + refcount->cursor = mid+1; + return &refcount->list[mid]; + } + if (blk < refcount->list[mid].ea_blk) + high = mid-1; + else + low = mid+1; + } + /* + * If we need to create a new entry, it should be right at + * low (where high will be left at low-1). + */ + if (create) { + if (refcount->count >= refcount->size) { + refcount_collapse(refcount); + if (refcount->count < refcount->size) + goto retry; + } + return insert_refcount_el(refcount, blk, low); + } + return 0; +} + +errcode_t ea_refcount_fetch(ext2_refcount_t refcount, blk64_t blk, + int *ret) +{ + struct ea_refcount_el *el; + + el = get_refcount_el(refcount, blk, 0); + if (!el) { + *ret = 0; + return 0; + } + *ret = el->ea_count; + return 0; +} + +errcode_t ea_refcount_increment(ext2_refcount_t refcount, blk64_t blk, int *ret) +{ + struct ea_refcount_el *el; + + el = get_refcount_el(refcount, blk, 1); + if (!el) + return EXT2_ET_NO_MEMORY; + el->ea_count++; + + if (ret) + *ret = el->ea_count; + return 0; +} + +errcode_t ea_refcount_decrement(ext2_refcount_t refcount, blk64_t blk, int *ret) +{ + struct ea_refcount_el *el; + + el = get_refcount_el(refcount, blk, 0); + if (!el || el->ea_count == 0) + return EXT2_ET_INVALID_ARGUMENT; + + el->ea_count--; + + if (ret) + *ret = el->ea_count; + return 0; +} + +errcode_t ea_refcount_store(ext2_refcount_t refcount, blk64_t blk, int count) +{ + struct ea_refcount_el *el; + + /* + * Get the refcount element + */ + el = get_refcount_el(refcount, blk, count ? 1 : 0); + if (!el) + return count ? EXT2_ET_NO_MEMORY : 0; + el->ea_count = count; + return 0; +} + +blk_t ext2fs_get_refcount_size(ext2_refcount_t refcount) +{ + if (!refcount) + return 0; + + return refcount->size; +} + +void ea_refcount_intr_begin(ext2_refcount_t refcount) +{ + refcount->cursor = 0; +} + + +blk64_t ea_refcount_intr_next(ext2_refcount_t refcount, + int *ret) +{ + struct ea_refcount_el *list; + + while (1) { + if (refcount->cursor >= refcount->count) + return 0; + list = refcount->list; + if (list[refcount->cursor].ea_count) { + if (ret) + *ret = list[refcount->cursor].ea_count; + return list[refcount->cursor++].ea_blk; + } + refcount->cursor++; + } +} + + +#ifdef TEST_PROGRAM + +errcode_t ea_refcount_validate(ext2_refcount_t refcount, FILE *out) +{ + errcode_t ret = 0; + int i; + const char *bad = "bad refcount"; + + if (refcount->count > refcount->size) { + fprintf(out, "%s: count > size\n", bad); + return EXT2_ET_INVALID_ARGUMENT; + } + for (i=1; i < refcount->count; i++) { + if (refcount->list[i-1].ea_blk >= refcount->list[i].ea_blk) { + fprintf(out, + "%s: list[%d].blk=%llu, list[%d].blk=%llu\n", + bad, i-1, refcount->list[i-1].ea_blk, + i, refcount->list[i].ea_blk); + ret = EXT2_ET_INVALID_ARGUMENT; + } + } + return ret; +} + +#define BCODE_END 0 +#define BCODE_CREATE 1 +#define BCODE_FREE 2 +#define BCODE_STORE 3 +#define BCODE_INCR 4 +#define BCODE_DECR 5 +#define BCODE_FETCH 6 +#define BCODE_VALIDATE 7 +#define BCODE_LIST 8 +#define BCODE_COLLAPSE 9 + +int bcode_program[] = { + BCODE_CREATE, 5, + BCODE_STORE, 3, 3, + BCODE_STORE, 4, 4, + BCODE_STORE, 1, 1, + BCODE_STORE, 8, 8, + BCODE_STORE, 2, 2, + BCODE_STORE, 4, 0, + BCODE_STORE, 2, 0, + BCODE_STORE, 6, 6, + BCODE_VALIDATE, + BCODE_STORE, 4, 4, + BCODE_STORE, 2, 2, + BCODE_FETCH, 1, + BCODE_FETCH, 2, + BCODE_INCR, 3, + BCODE_INCR, 3, + BCODE_DECR, 4, + BCODE_STORE, 4, 4, + BCODE_VALIDATE, + BCODE_STORE, 20, 20, + BCODE_STORE, 40, 40, + BCODE_STORE, 30, 30, + BCODE_STORE, 10, 10, + BCODE_DECR, 30, + BCODE_FETCH, 30, + BCODE_DECR, 2, + BCODE_DECR, 2, + BCODE_COLLAPSE, + BCODE_LIST, + BCODE_VALIDATE, + BCODE_FREE, + BCODE_END +}; + +int main(int argc, char **argv) +{ + int i = 0; + ext2_refcount_t refcount; + int size, arg; + blk64_t blk; + errcode_t retval; + + while (1) { + switch (bcode_program[i++]) { + case BCODE_END: + exit(0); + case BCODE_CREATE: + size = bcode_program[i++]; + retval = ea_refcount_create(size, &refcount); + if (retval) { + com_err("ea_refcount_create", retval, + "while creating size %d", size); + exit(1); + } else + printf("Creating refcount with size %d\n", + size); + break; + case BCODE_FREE: + ea_refcount_free(refcount); + refcount = 0; + printf("Freeing refcount\n"); + break; + case BCODE_STORE: + blk = (blk_t) bcode_program[i++]; + arg = bcode_program[i++]; + printf("Storing blk %llu with value %d\n", blk, arg); + retval = ea_refcount_store(refcount, blk, arg); + if (retval) + com_err("ea_refcount_store", retval, + "while storing blk %llu", blk); + break; + case BCODE_FETCH: + blk = (blk_t) bcode_program[i++]; + retval = ea_refcount_fetch(refcount, blk, &arg); + if (retval) + com_err("ea_refcount_fetch", retval, + "while fetching blk %llu", blk); + else + printf("bcode_fetch(%llu) returns %d\n", + blk, arg); + break; + case BCODE_INCR: + blk = (blk_t) bcode_program[i++]; + retval = ea_refcount_increment(refcount, blk, &arg); + if (retval) + com_err("ea_refcount_increment", retval, + "while incrementing blk %llu", blk); + else + printf("bcode_increment(%llu) returns %d\n", + blk, arg); + break; + case BCODE_DECR: + blk = (blk_t) bcode_program[i++]; + retval = ea_refcount_decrement(refcount, blk, &arg); + if (retval) + com_err("ea_refcount_decrement", retval, + "while decrementing blk %llu", blk); + else + printf("bcode_decrement(%llu) returns %d\n", + blk, arg); + break; + case BCODE_VALIDATE: + retval = ea_refcount_validate(refcount, stderr); + if (retval) + com_err("ea_refcount_validate", retval, + "while validating"); + else + printf("Refcount validation OK.\n"); + break; + case BCODE_LIST: + ea_refcount_intr_begin(refcount); + while (1) { + blk = ea_refcount_intr_next(refcount, &arg); + if (!blk) + break; + printf("\tblk=%llu, count=%d\n", blk, arg); + } + break; + case BCODE_COLLAPSE: + refcount_collapse(refcount); + break; + } + + } +} + +#endif
diff --git a/e2fsck/ehandler.c b/e2fsck/ehandler.c new file mode 100644 index 0000000..6dddf9c --- /dev/null +++ b/e2fsck/ehandler.c
@@ -0,0 +1,128 @@ +/* + * ehandler.c --- handle bad block errors which come up during the + * course of an e2fsck session. + * + * Copyright (C) 1994 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + */ + +#include "config.h" +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <termios.h> + +#include "e2fsck.h" + +#include <sys/time.h> +#include <sys/resource.h> + +static const char *operation; + +static errcode_t e2fsck_handle_read_error(io_channel channel, + unsigned long block, + int count, + void *data, + size_t size EXT2FS_ATTR((unused)), + int actual EXT2FS_ATTR((unused)), + errcode_t error) +{ + int i; + char *p; + ext2_filsys fs = (ext2_filsys) channel->app_data; + e2fsck_t ctx; + + ctx = (e2fsck_t) fs->priv_data; + if (ctx->flags & E2F_FLAG_EXITING) + return 0; + /* + * If more than one block was read, try reading each block + * separately. We could use the actual bytes read to figure + * out where to start, but we don't bother. + */ + if (count > 1) { + p = (char *) data; + for (i=0; i < count; i++, p += channel->block_size, block++) { + error = io_channel_read_blk64(channel, block, + 1, p); + if (error) + return error; + } + return 0; + } + if (operation) + printf(_("Error reading block %lu (%s) while %s. "), block, + error_message(error), operation); + else + printf(_("Error reading block %lu (%s). "), block, + error_message(error)); + preenhalt(ctx); + if (ask(ctx, _("Ignore error"), 1)) { + if (ask(ctx, _("Force rewrite"), 1)) + io_channel_write_blk64(channel, block, count, data); + return 0; + } + + return error; +} + +static errcode_t e2fsck_handle_write_error(io_channel channel, + unsigned long block, + int count, + const void *data, + size_t size EXT2FS_ATTR((unused)), + int actual EXT2FS_ATTR((unused)), + errcode_t error) +{ + int i; + const char *p; + ext2_filsys fs = (ext2_filsys) channel->app_data; + e2fsck_t ctx; + + ctx = (e2fsck_t) fs->priv_data; + if (ctx->flags & E2F_FLAG_EXITING) + return 0; + + /* + * If more than one block was written, try writing each block + * separately. We could use the actual bytes read to figure + * out where to start, but we don't bother. + */ + if (count > 1) { + p = (const char *) data; + for (i=0; i < count; i++, p += channel->block_size, block++) { + error = io_channel_write_blk64(channel, block, + 1, p); + if (error) + return error; + } + return 0; + } + + if (operation) + printf(_("Error writing block %lu (%s) while %s. "), block, + error_message(error), operation); + else + printf(_("Error writing block %lu (%s). "), block, + error_message(error)); + preenhalt(ctx); + if (ask(ctx, _("Ignore error"), 1)) + return 0; + + return error; +} + +const char *ehandler_operation(const char *op) +{ + const char *ret = operation; + + operation = op; + return ret; +} + +void ehandler_init(io_channel channel) +{ + channel->read_error = e2fsck_handle_read_error; + channel->write_error = e2fsck_handle_write_error; +}
diff --git a/e2fsck/emptydir.c b/e2fsck/emptydir.c new file mode 100644 index 0000000..a3bfd46 --- /dev/null +++ b/e2fsck/emptydir.c
@@ -0,0 +1,194 @@ +/* + * emptydir.c --- clear empty directory blocks + * + * Copyright (C) 1998 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * This file has the necessary routines to search for empty directory + * blocks and get rid of them. + */ + +#include "config.h" +#include "e2fsck.h" +#include "problem.h" + +/* + * For e2fsck.h + */ +struct empty_dir_info_struct { + ext2_dblist empty_dblist; + ext2fs_block_bitmap empty_dir_blocks; + ext2fs_inode_bitmap dir_map; + char *block_buf; + ext2_ino_t ino; + struct ext2_inode inode; + blk64_t logblk; + blk64_t freed_blocks; +}; + +typedef struct empty_dir_info_struct *empty_dir_info; + +extern empty_dir_info init_empty_dir(e2fsck_t ctx); +extern void free_empty_dirblock(empty_dir_info edi); +extern void add_empty_dirblock(empty_dir_info edi, + struct ext2_db_entry2 *db); +extern void process_empty_dirblock(e2fsck_t ctx, empty_dir_info edi); + + +empty_dir_info init_empty_dir(e2fsck_t ctx) +{ + empty_dir_info edi; + errcode_t retval; + + edi = malloc(sizeof(struct empty_dir_info_struct)); + if (!edi) + return NULL; + + memset(edi, 0, sizeof(struct empty_dir_info_struct)); + + retval = ext2fs_init_dblist(ctx->fs, &edi->empty_dblist); + if (retval) + goto errout; + + retval = ext2fs_allocate_block_bitmap(ctx->fs, _("empty dirblocks"), + &edi->empty_dir_blocks); + if (retval) + goto errout; + + retval = ext2fs_allocate_inode_bitmap(ctx->fs, _("empty dir map"), + &edi->dir_map); + if (retval) + goto errout; + + return (edi); + +errout: + free_empty_dirblock(edi); + return NULL; +} + +void free_empty_dirblock(empty_dir_info edi) +{ + if (!edi) + return; + if (edi->empty_dblist) + ext2fs_free_dblist(edi->empty_dblist); + if (edi->empty_dir_blocks) + ext2fs_free_block_bitmap(edi->empty_dir_blocks); + if (edi->dir_map) + ext2fs_free_inode_bitmap(edi->dir_map); + + memset(edi, 0, sizeof(struct empty_dir_info_struct)); + free(edi); +} + +void add_empty_dirblock(empty_dir_info edi, + struct ext2_db_entry2 *db) +{ + if (!edi || !db) + return; + + if (db->ino == 11) + return; /* Inode number 11 is usually lost+found */ + + printf(_("Empty directory block %u (#%d) in inode %u\n"), + db->blk, db->blockcnt, db->ino); + + ext2fs_mark_block_bitmap2(edi->empty_dir_blocks, db->blk); + if (ext2fs_test_inode_bitmap(edi->dir_map, db->ino)) + return; + ext2fs_mark_inode_bitmap(edi->dir_map, db->ino); + + ext2fs_add_dir_block2(edi->empty_dblist, db->ino, + db->blk, db->blockcnt); +} + +/* + * Helper function used by fix_directory. + * + * XXX need to finish this. General approach is to use bmap to + * iterate over all of the logical blocks using the bmap function, and + * copy the block reference as necessary. Big question --- what do + * about error recovery? + * + * Also question --- how to free the indirect blocks. + */ +int empty_pass1(ext2_filsys fs, blk64_t *block_nr, e2_blkcnt_t blockcnt, + blk64_t ref_block, int ref_offset, void *priv_data) +{ + empty_dir_info edi = (empty_dir_info) priv_data; + blk64_t block, new_block; + errcode_t retval; + + if (blockcnt < 0) + return 0; + block = *block_nr; + do { + retval = ext2fs_bmap2(fs, edi->ino, &edi->inode, + edi->block_buf, 0, edi->logblk, 0, + &new_block); + if (retval) + return DIRENT_ABORT; /* XXX what to do? */ + if (new_block == 0) + break; + edi->logblk++; + } while (ext2fs_test_block_bitmap2(edi->empty_dir_blocks, new_block)); + + if (new_block == block) + return 0; + if (new_block == 0) + edi->freed_blocks++; + *block_nr = new_block; + return BLOCK_CHANGED; +} + +static int fix_directory(ext2_filsys fs, + struct ext2_db_entry2 *db, + void *priv_data) +{ + errcode_t retval; + + empty_dir_info edi = (empty_dir_info) priv_data; + + edi->logblk = 0; + edi->freed_blocks = 0; + edi->ino = db->ino; + + retval = ext2fs_read_inode(fs, db->ino, &edi->inode); + if (retval) + return 0; + + retval = ext2fs_block_iterate3(fs, db->ino, 0, edi->block_buf, + empty_pass1, edi); + if (retval) + return 0; + + if (edi->freed_blocks) { + edi->inode.i_size -= edi->freed_blocks * fs->blocksize; + ext2fs_iblk_add_blocks(fs, &edi->inode, edi->freed_blocks); + retval = ext2fs_write_inode(fs, db->ino, &edi->inode); + if (retval) + return 0; + } + return 0; +} + +void process_empty_dirblock(e2fsck_t ctx, empty_dir_info edi) +{ + if (!edi) + return; + + edi->block_buf = malloc(ctx->fs->blocksize * 3); + + if (edi->block_buf) { + (void) ext2fs_dblist_iterate2(edi->empty_dblist, + fix_directory, &edi); + } + free(edi->block_buf); + free_empty_dirblock(edi); +} +
diff --git a/e2fsck/extend.c b/e2fsck/extend.c new file mode 100644 index 0000000..bdb62c3 --- /dev/null +++ b/e2fsck/extend.c
@@ -0,0 +1,82 @@ +/* + * extend.c --- extend a file so that it has at least a specified + * number of blocks. + * + * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. + * + * This file may be redistributed under the terms of the GNU Public + * License. + */ + +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <fcntl.h> +#include "../misc/nls-enable.h" + +static void usage(char *progname) +{ + fprintf(stderr, _("%s: %s filename nblocks blocksize\n"), + progname, progname); + exit(1); +} + + +int main(int argc, char **argv) +{ + char *filename; + int nblocks, blocksize; + int fd; + char *block; + int ret; + + if (argc != 4) + usage(argv[0]); + + filename = argv[1]; + nblocks = strtoul(argv[2], 0, 0) - 1; + blocksize = strtoul(argv[3], 0, 0); + + if (nblocks < 0) { + fprintf(stderr, _("Illegal number of blocks!\n")); + exit(1); + } + + block = malloc(blocksize); + if (block == 0) { + fprintf(stderr, _("Couldn't allocate block buffer (size=%d)\n"), + blocksize); + exit(1); + } + memset(block, 0, blocksize); + + fd = open(filename, O_RDWR); + if (fd < 0) { + perror(filename); + exit(1); + } + ret = lseek(fd, nblocks*blocksize, SEEK_SET); + if (ret < 0) { + perror("lseek"); + exit(1); + } + ret = read(fd, block, blocksize); + if (ret < 0) { + perror("read"); + exit(1); + } + ret = lseek(fd, nblocks*blocksize, SEEK_SET); + if (ret < 0) { + perror("lseek #2"); + exit(1); + } + ret = write(fd, block, blocksize); + if (ret < 0) { + perror("read"); + exit(1); + } + exit(0); +}
diff --git a/e2fsck/flushb.c b/e2fsck/flushb.c new file mode 100644 index 0000000..6100fc6 --- /dev/null +++ b/e2fsck/flushb.c
@@ -0,0 +1,67 @@ +/* + * flushb.c --- This routine flushes the disk buffers for a disk + * + * Copyright 1997, 2000, by Theodore Ts'o. + * + * WARNING: use of flushb on some older 2.2 kernels on a heavily loaded + * system will corrupt filesystems. This program is not really useful + * beyond for benchmarking scripts. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include "config.h" +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/mount.h> +#include "../misc/nls-enable.h" + +/* For Linux, define BLKFLSBUF if necessary */ +#if (!defined(BLKFLSBUF) && defined(__linux__)) +#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ +#endif + +const char *progname; + +static void usage(void) +{ + fprintf(stderr, _("Usage: %s disk\n"), progname); + exit(1); +} + +int main(int argc, char **argv) +{ + int fd; + + progname = argv[0]; + if (argc != 2) + usage(); + + fd = open(argv[1], O_RDONLY, 0); + if (fd < 0) { + perror("open"); + exit(1); + } + /* + * Note: to reread the partition table, use the ioctl + * BLKRRPART instead of BLKFSLBUF. + */ +#ifdef BLKFLSBUF + if (ioctl(fd, BLKFLSBUF, 0) < 0) { + perror("ioctl BLKFLSBUF"); + exit(1); + } + return 0; +#else + fprintf(stderr, + _("BLKFLSBUF ioctl not supported! Can't flush buffers.\n")); + return 1; +#endif +}
diff --git a/e2fsck/gen_crc32table.c b/e2fsck/gen_crc32table.c new file mode 100644 index 0000000..2c1aa8e --- /dev/null +++ b/e2fsck/gen_crc32table.c
@@ -0,0 +1,101 @@ +/* + * gen_crc32table.c --- Generate CRC32 tables. + * + * Copyright (C) 2008 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include <stdio.h> +#include "crc32defs.h" +#include <inttypes.h> + +#define ENTRIES_PER_LINE 4 + +#define LE_TABLE_SIZE (1 << CRC_LE_BITS) +#define BE_TABLE_SIZE (1 << CRC_BE_BITS) + +static uint32_t crc32table_le[LE_TABLE_SIZE]; +static uint32_t crc32table_be[BE_TABLE_SIZE]; + +/** + * crc32init_le() - allocate and initialize LE table data + * + * crc is the crc of the byte i; other entries are filled in based on the + * fact that crctable[i^j] = crctable[i] ^ crctable[j]. + * + */ +static void crc32init_le(void) +{ + unsigned i, j; + uint32_t crc = 1; + + crc32table_le[0] = 0; + + for (i = 1 << (CRC_LE_BITS - 1); i; i >>= 1) { + crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); + for (j = 0; j < LE_TABLE_SIZE; j += 2 * i) + crc32table_le[i + j] = crc ^ crc32table_le[j]; + } +} + +/** + * crc32init_be() - allocate and initialize BE table data + */ +static void crc32init_be(void) +{ + unsigned i, j; + uint32_t crc = 0x80000000; + + crc32table_be[0] = 0; + + for (i = 1; i < BE_TABLE_SIZE; i <<= 1) { + crc = (crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE : 0); + for (j = 0; j < i; j++) + crc32table_be[i + j] = crc ^ crc32table_be[j]; + } +} + +static void output_table(uint32_t table[], int len, const char *trans) +{ + int i; + + for (i = 0; i < len - 1; i++) { + if (i % ENTRIES_PER_LINE == 0) + printf("\n"); + printf("%s(0x%8.8xL), ", trans, table[i]); + } + printf("%s(0x%8.8xL)\n", trans, table[len - 1]); +} + +#ifdef __GNUC__ +#define ATTR(x) __attribute__(x) +#else +#define ATTR(x) +#endif + +int main(int argc ATTR((unused)), char** argv ATTR((unused))) +{ + printf("/* this file is generated - do not edit */\n\n"); + + printf("#ifdef UNITTEST\n"); + if (CRC_LE_BITS > 1) { + crc32init_le(); + printf("static const __u32 crc32table_le[] = {"); + output_table(crc32table_le, LE_TABLE_SIZE, "tole"); + printf("};\n"); + } + printf("#endif /* UNITTEST */\n"); + + if (CRC_BE_BITS > 1) { + crc32init_be(); + printf("static const __u32 crc32table_be[] = {"); + output_table(crc32table_be, BE_TABLE_SIZE, "tobe"); + printf("};\n"); + } + + return 0; +}
diff --git a/e2fsck/iscan.c b/e2fsck/iscan.c new file mode 100644 index 0000000..52cad11 --- /dev/null +++ b/e2fsck/iscan.c
@@ -0,0 +1,139 @@ +/* + * Test to see how quickly we can scan the inode table (not doing + * anything else) + */ + +#include "config.h" +#include <string.h> +#include <fcntl.h> +#include <ctype.h> +#include <termios.h> +#include <time.h> +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#endif +#include <unistd.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/ioctl.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif + +#include "et/com_err.h" +#include "e2fsck.h" +#include "../version.h" + +extern int isatty(int); + +const char * program_name = "iscan"; +const char * device_name = NULL; + +int yflag = 0; +int nflag = 0; +int preen = 0; +int inode_buffer_blocks = 0; +int invalid_bitmaps = 0; + +struct resource_track global_rtrack; + +static void usage(void) +{ + fprintf(stderr, + _("Usage: %s [-F] [-I inode_buffer_blocks] device\n"), + program_name); + exit(1); +} + +static void PRS(int argc, char *argv[]) +{ + int flush = 0; + int c; +#ifdef MTRACE + extern void *mallwatch; +#endif + errcode_t retval; + + setbuf(stdout, NULL); + setbuf(stderr, NULL); + initialize_ext2_error_table(); + + if (argc && *argv) + program_name = *argv; + while ((c = getopt (argc, argv, "FI")) != EOF) + switch (c) { + case 'F': + flush = 1; + break; + case 'I': + inode_buffer_blocks = atoi(optarg); + break; + default: + usage (); + } + device_name = argv[optind]; + if (flush) { + int fd = open(device_name, O_RDONLY, 0); + + if (fd < 0) { + com_err("open", errno, + _("while opening %s for flushing"), device_name); + exit(FSCK_ERROR); + } + if ((retval = ext2fs_sync_device(fd, 1))) { + com_err("ext2fs_sync_device", retval, + _("while trying to flush %s"), device_name); + exit(FSCK_ERROR); + } + close(fd); + } +} + +int main (int argc, char *argv[]) +{ + errcode_t retval = 0; + int exit_value = FSCK_OK; + ext2_filsys fs; + ext2_ino_t ino; + __u32 num_inodes = 0; + struct ext2_inode inode; + ext2_inode_scan scan; + + init_resource_track(&global_rtrack); + + PRS(argc, argv); + + retval = ext2fs_open(device_name, 0, + 0, 0, unix_io_manager, &fs); + if (retval) { + com_err(program_name, retval, _("while trying to open '%s'"), + device_name); + exit(1); + } + + ehandler_init(fs->io); + + retval = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan); + if (retval) { + com_err(program_name, retval, _("while opening inode scan")); + exit(1); + } + + while (1) { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + if (retval) { + com_err(program_name, retval, + _("while getting next inode")); + exit(1); + } + if (ino == 0) + break; + num_inodes++; + } + + print_resource_track(NULL, &global_rtrack); + printf(_("%u inodes scanned.\n"), num_inodes); + + exit(0); +}
diff --git a/e2fsck/jfs_user.h b/e2fsck/jfs_user.h new file mode 100644 index 0000000..bfc1bcd --- /dev/null +++ b/e2fsck/jfs_user.h
@@ -0,0 +1,149 @@ +/* + * Compatibility header file for e2fsck which should be included + * instead of linux/jfs.h + * + * Copyright (C) 2000 Stephen C. Tweedie + * + * This file may be redistributed under the terms of the + * GNU General Public License version 2 or at your discretion + * any later version. + */ + +/* + * Pull in the definition of the e2fsck context structure + */ +#include "e2fsck.h" + +struct buffer_head { + e2fsck_t b_ctx; + io_channel b_io; + int b_size; + unsigned long long b_blocknr; + int b_dirty; + int b_uptodate; + int b_err; + char b_data[1024]; +}; + +struct inode { + e2fsck_t i_ctx; + ext2_ino_t i_ino; + struct ext2_inode i_ext2; +}; + +struct kdev_s { + e2fsck_t k_ctx; + int k_dev; +}; + +#define K_DEV_FS 1 +#define K_DEV_JOURNAL 2 + +typedef struct kdev_s *kdev_t; + +#define lock_buffer(bh) do {} while(0) +#define unlock_buffer(bh) do {} while(0) +#define buffer_req(bh) 1 +#define do_readahead(journal, start) do {} while(0) + +extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */ + +typedef struct { + int object_length; +} lkmem_cache_t; + +#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length) +#define kmem_cache_free(cache,obj) free(obj) +#define kmem_cache_create(name,len,a,b,c,d) do_cache_create(len) +#define kmem_cache_destroy(cache) do_cache_destroy(cache) +#define kmalloc(len,flags) malloc(len) +#define kfree(p) free(p) + +#define cond_resched() do { } while (0) + +typedef unsigned int __be32; +typedef __u64 __be64; + +#define __init + +/* + * Now pull in the real linux/jfs.h definitions. + */ +#include <ext2fs/kernel-jbd.h> + +/* + * We use the standard libext2fs portability tricks for inline + * functions. + */ +#ifdef NO_INLINE_FUNCS +extern lkmem_cache_t * do_cache_create(int len); +extern void do_cache_destroy(lkmem_cache_t *cache); +extern size_t journal_tag_bytes(journal_t *journal); +#endif + +#if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) +#ifdef E2FSCK_INCLUDE_INLINE_FUNCS +#if (__STDC_VERSION__ >= 199901L) +#define _INLINE_ extern inline +#else +#define _INLINE_ inline +#endif +#else /* !E2FSCK_INCLUDE_INLINE FUNCS */ +#if (__STDC_VERSION__ >= 199901L) +#define _INLINE_ inline +#else /* not C99 */ +#ifdef __GNUC__ +#define _INLINE_ extern __inline__ +#else /* For Watcom C */ +#define _INLINE_ extern inline +#endif /* __GNUC__ */ +#endif /* __STDC_VERSION__ >= 199901L */ +#endif /* E2FSCK_INCLUDE_INLINE_FUNCS */ + + +_INLINE_ lkmem_cache_t * do_cache_create(int len) +{ + lkmem_cache_t *new_cache; + new_cache = malloc(sizeof(*new_cache)); + if (new_cache) + new_cache->object_length = len; + return new_cache; +} + +_INLINE_ void do_cache_destroy(lkmem_cache_t *cache) +{ + free(cache); +} + +/* + * helper functions to deal with 32 or 64bit block numbers. + */ +_INLINE_ size_t journal_tag_bytes(journal_t *journal) +{ + if (JFS_HAS_INCOMPAT_FEATURE(journal, JFS_FEATURE_INCOMPAT_64BIT)) + return JBD_TAG_SIZE64; + else + return JBD_TAG_SIZE32; +} + +#undef _INLINE_ +#endif + +/* + * Kernel compatibility functions are defined in journal.c + */ +int journal_bmap(journal_t *journal, blk64_t block, unsigned long long *phys); +struct buffer_head *getblk(kdev_t ctx, blk64_t blocknr, int blocksize); +void sync_blockdev(kdev_t kdev); +void ll_rw_block(int rw, int dummy, struct buffer_head *bh[]); +void mark_buffer_dirty(struct buffer_head *bh); +void mark_buffer_uptodate(struct buffer_head *bh, int val); +void brelse(struct buffer_head *bh); +int buffer_uptodate(struct buffer_head *bh); +void wait_on_buffer(struct buffer_head *bh); + +/* + * Define newer 2.5 interfaces + */ +#define __getblk(dev, blocknr, blocksize) getblk(dev, blocknr, blocksize) +#define set_buffer_uptodate(bh) mark_buffer_uptodate(bh, 1)
diff --git a/e2fsck/journal.c b/e2fsck/journal.c new file mode 100644 index 0000000..3b40e00 --- /dev/null +++ b/e2fsck/journal.c
@@ -0,0 +1,1094 @@ +/* + * journal.c --- code for handling the "ext3" journal + * + * Copyright (C) 2000 Andreas Dilger + * Copyright (C) 2000 Theodore Ts'o + * + * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie + * Copyright (C) 1999 Red Hat Software + * + * This file may be redistributed under the terms of the + * GNU General Public License version 2 or at your discretion + * any later version. + */ + +#include "config.h" +#ifdef HAVE_SYS_MOUNT_H +#include <sys/param.h> +#include <sys/mount.h> +#define MNT_FL (MS_MGC_VAL | MS_RDONLY) +#endif +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#define E2FSCK_INCLUDE_INLINE_FUNCS +#include "jfs_user.h" +#include "problem.h" +#include "uuid/uuid.h" + +#ifdef CONFIG_JBD_DEBUG /* Enabled by configure --enable-jfs-debug */ +static int bh_count = 0; +#endif + +/* + * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths. + * This creates a larger static binary, and a smaller binary using + * shared libraries. It's also probably slightly less CPU-efficient, + * which is why it's not on by default. But, it's a good way of + * testing the functions in inode_io.c and fileio.c. + */ +#undef USE_INODE_IO + +/* Kernel compatibility functions for handling the journal. These allow us + * to use the recovery.c file virtually unchanged from the kernel, so we + * don't have to do much to keep kernel and user recovery in sync. + */ +int journal_bmap(journal_t *journal, blk64_t block, unsigned long long *phys) +{ +#ifdef USE_INODE_IO + *phys = block; + return 0; +#else + struct inode *inode = journal->j_inode; + errcode_t retval; + blk64_t pblk; + + if (!inode) { + *phys = block; + return 0; + } + + retval= ext2fs_bmap2(inode->i_ctx->fs, inode->i_ino, + &inode->i_ext2, NULL, 0, block, 0, &pblk); + *phys = pblk; + return (int) retval; +#endif +} + +struct buffer_head *getblk(kdev_t kdev, blk64_t blocknr, int blocksize) +{ + struct buffer_head *bh; + int bufsize = sizeof(*bh) + kdev->k_ctx->fs->blocksize - + sizeof(bh->b_data); + + bh = e2fsck_allocate_memory(kdev->k_ctx, bufsize, "block buffer"); + if (!bh) + return NULL; + +#ifdef CONFIG_JBD_DEBUG + if (journal_enable_debug >= 3) + bh_count++; +#endif + jfs_debug(4, "getblk for block %llu (%d bytes)(total %d)\n", + (unsigned long long) blocknr, blocksize, bh_count); + + bh->b_ctx = kdev->k_ctx; + if (kdev->k_dev == K_DEV_FS) + bh->b_io = kdev->k_ctx->fs->io; + else + bh->b_io = kdev->k_ctx->journal_io; + bh->b_size = blocksize; + bh->b_blocknr = blocknr; + + return bh; +} + +void sync_blockdev(kdev_t kdev) +{ + io_channel io; + + if (kdev->k_dev == K_DEV_FS) + io = kdev->k_ctx->fs->io; + else + io = kdev->k_ctx->journal_io; + + io_channel_flush(io); +} + +void ll_rw_block(int rw, int nr, struct buffer_head *bhp[]) +{ + errcode_t retval; + struct buffer_head *bh; + + for (; nr > 0; --nr) { + bh = *bhp++; + if (rw == READ && !bh->b_uptodate) { + jfs_debug(3, "reading block %llu/%p\n", + bh->b_blocknr, (void *) bh); + retval = io_channel_read_blk64(bh->b_io, + bh->b_blocknr, + 1, bh->b_data); + if (retval) { + com_err(bh->b_ctx->device_name, retval, + "while reading block %llu\n", + bh->b_blocknr); + bh->b_err = (int) retval; + continue; + } + bh->b_uptodate = 1; + } else if (rw == WRITE && bh->b_dirty) { + jfs_debug(3, "writing block %llu/%p\n", + bh->b_blocknr, + (void *) bh); + retval = io_channel_write_blk64(bh->b_io, + bh->b_blocknr, + 1, bh->b_data); + if (retval) { + com_err(bh->b_ctx->device_name, retval, + "while writing block %llu\n", + bh->b_blocknr); + bh->b_err = (int) retval; + continue; + } + bh->b_dirty = 0; + bh->b_uptodate = 1; + } else { + jfs_debug(3, "no-op %s for block %llu\n", + rw == READ ? "read" : "write", + bh->b_blocknr); + } + } +} + +void mark_buffer_dirty(struct buffer_head *bh) +{ + bh->b_dirty = 1; +} + +static void mark_buffer_clean(struct buffer_head * bh) +{ + bh->b_dirty = 0; +} + +void brelse(struct buffer_head *bh) +{ + if (bh->b_dirty) + ll_rw_block(WRITE, 1, &bh); + jfs_debug(3, "freeing block %llu/%p (total %d)\n", + bh->b_blocknr, (void *) bh, --bh_count); + ext2fs_free_mem(&bh); +} + +int buffer_uptodate(struct buffer_head *bh) +{ + return bh->b_uptodate; +} + +void mark_buffer_uptodate(struct buffer_head *bh, int val) +{ + bh->b_uptodate = val; +} + +void wait_on_buffer(struct buffer_head *bh) +{ + if (!bh->b_uptodate) + ll_rw_block(READ, 1, &bh); +} + + +static void e2fsck_clear_recover(e2fsck_t ctx, int error) +{ + ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; + + /* if we had an error doing journal recovery, we need a full fsck */ + if (error) + ctx->fs->super->s_state &= ~EXT2_VALID_FS; + ext2fs_mark_super_dirty(ctx->fs); +} + +/* + * This is a helper function to check the validity of the journal. + */ +struct process_block_struct { + e2_blkcnt_t last_block; +}; + +static int process_journal_block(ext2_filsys fs, + blk64_t *block_nr, + e2_blkcnt_t blockcnt, + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct process_block_struct *p; + blk64_t blk = *block_nr; + + p = (struct process_block_struct *) priv_data; + + if (!blk || blk < fs->super->s_first_data_block || + blk >= ext2fs_blocks_count(fs->super)) + return BLOCK_ABORT; + + if (blockcnt >= 0) + p->last_block = blockcnt; + return 0; +} + +static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal) +{ + struct process_block_struct pb; + struct ext2_super_block *sb = ctx->fs->super; + struct ext2_super_block jsuper; + struct problem_context pctx; + struct buffer_head *bh; + struct inode *j_inode = NULL; + struct kdev_s *dev_fs = NULL, *dev_journal; + const char *journal_name = 0; + journal_t *journal = NULL; + errcode_t retval = 0; + io_manager io_ptr = 0; + unsigned long long start = 0; + int ext_journal = 0; + int tried_backup_jnl = 0; + + clear_problem_context(&pctx); + + journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal"); + if (!journal) { + return EXT2_ET_NO_MEMORY; + } + + dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev"); + if (!dev_fs) { + retval = EXT2_ET_NO_MEMORY; + goto errout; + } + dev_journal = dev_fs+1; + + dev_fs->k_ctx = dev_journal->k_ctx = ctx; + dev_fs->k_dev = K_DEV_FS; + dev_journal->k_dev = K_DEV_JOURNAL; + + journal->j_dev = dev_journal; + journal->j_fs_dev = dev_fs; + journal->j_inode = NULL; + journal->j_blocksize = ctx->fs->blocksize; + + if (uuid_is_null(sb->s_journal_uuid)) { + if (!sb->s_journal_inum) { + retval = EXT2_ET_BAD_INODE_NUM; + goto errout; + } + j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode), + "journal inode"); + if (!j_inode) { + retval = EXT2_ET_NO_MEMORY; + goto errout; + } + + j_inode->i_ctx = ctx; + j_inode->i_ino = sb->s_journal_inum; + + if ((retval = ext2fs_read_inode(ctx->fs, + sb->s_journal_inum, + &j_inode->i_ext2))) { + try_backup_journal: + if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS || + tried_backup_jnl) + goto errout; + memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode)); + memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks, + EXT2_N_BLOCKS*4); + j_inode->i_ext2.i_size_high = sb->s_jnl_blocks[15]; + j_inode->i_ext2.i_size = sb->s_jnl_blocks[16]; + j_inode->i_ext2.i_links_count = 1; + j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600; + e2fsck_use_inode_shortcuts(ctx, 1); + ctx->stashed_ino = j_inode->i_ino; + ctx->stashed_inode = &j_inode->i_ext2; + tried_backup_jnl++; + } + if (!j_inode->i_ext2.i_links_count || + !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) { + retval = EXT2_ET_NO_JOURNAL; + goto try_backup_journal; + } + if (EXT2_I_SIZE(&j_inode->i_ext2) / journal->j_blocksize < + JFS_MIN_JOURNAL_BLOCKS) { + retval = EXT2_ET_JOURNAL_TOO_SMALL; + goto try_backup_journal; + } + pb.last_block = -1; + retval = ext2fs_block_iterate3(ctx->fs, j_inode->i_ino, + BLOCK_FLAG_HOLE, 0, + process_journal_block, &pb); + if ((pb.last_block + 1) * ctx->fs->blocksize < + (int) EXT2_I_SIZE(&j_inode->i_ext2)) { + retval = EXT2_ET_JOURNAL_TOO_SMALL; + goto try_backup_journal; + } + if (tried_backup_jnl && !(ctx->options & E2F_OPT_READONLY)) { + retval = ext2fs_write_inode(ctx->fs, sb->s_journal_inum, + &j_inode->i_ext2); + if (retval) + goto errout; + } + + journal->j_maxlen = EXT2_I_SIZE(&j_inode->i_ext2) / + journal->j_blocksize; + +#ifdef USE_INODE_IO + retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum, + &j_inode->i_ext2, + &journal_name); + if (retval) + goto errout; + + io_ptr = inode_io_manager; +#else + journal->j_inode = j_inode; + ctx->journal_io = ctx->fs->io; + if ((retval = (errcode_t) journal_bmap(journal, 0, &start)) != 0) + goto errout; +#endif + } else { + ext_journal = 1; + if (!ctx->journal_name) { + char uuid[37]; + + uuid_unparse(sb->s_journal_uuid, uuid); + ctx->journal_name = blkid_get_devname(ctx->blkid, + "UUID", uuid); + if (!ctx->journal_name) + ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev); + } + journal_name = ctx->journal_name; + + if (!journal_name) { + fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx); + retval = EXT2_ET_LOAD_EXT_JOURNAL; + goto errout; + } + + jfs_debug(1, "Using journal file %s\n", journal_name); + io_ptr = unix_io_manager; + } + +#if 0 + test_io_backing_manager = io_ptr; + io_ptr = test_io_manager; +#endif +#ifndef USE_INODE_IO + if (ext_journal) +#endif + { + int flags = IO_FLAG_RW; + if (!(ctx->mount_flags & EXT2_MF_ISROOT && + ctx->mount_flags & EXT2_MF_READONLY)) + flags |= IO_FLAG_EXCLUSIVE; + if ((ctx->mount_flags & EXT2_MF_READONLY) && + (ctx->options & E2F_OPT_FORCE)) + flags &= ~IO_FLAG_EXCLUSIVE; + + + retval = io_ptr->open(journal_name, flags, + &ctx->journal_io); + } + if (retval) + goto errout; + + io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize); + + if (ext_journal) { + blk64_t maxlen; + + start = ext2fs_journal_sb_start(ctx->fs->blocksize) - 1; + bh = getblk(dev_journal, start, ctx->fs->blocksize); + if (!bh) { + retval = EXT2_ET_NO_MEMORY; + goto errout; + } + ll_rw_block(READ, 1, &bh); + if ((retval = bh->b_err) != 0) { + brelse(bh); + goto errout; + } + memcpy(&jsuper, start ? bh->b_data : bh->b_data + SUPERBLOCK_OFFSET, + sizeof(jsuper)); + brelse(bh); +#ifdef WORDS_BIGENDIAN + if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) + ext2fs_swap_super(&jsuper); +#endif + if (jsuper.s_magic != EXT2_SUPER_MAGIC || + !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { + fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx); + retval = EXT2_ET_LOAD_EXT_JOURNAL; + goto errout; + } + /* Make sure the journal UUID is correct */ + if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid, + sizeof(jsuper.s_uuid))) { + fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx); + retval = EXT2_ET_LOAD_EXT_JOURNAL; + goto errout; + } + + maxlen = ext2fs_blocks_count(&jsuper); + journal->j_maxlen = (maxlen < 1ULL << 32) ? maxlen : (1ULL << 32) - 1; + start++; + } + + if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) { + retval = EXT2_ET_NO_MEMORY; + goto errout; + } + + journal->j_sb_buffer = bh; + journal->j_superblock = (journal_superblock_t *)bh->b_data; + +#ifdef USE_INODE_IO + if (j_inode) + ext2fs_free_mem(&j_inode); +#endif + + *ret_journal = journal; + e2fsck_use_inode_shortcuts(ctx, 0); + return 0; + +errout: + e2fsck_use_inode_shortcuts(ctx, 0); + if (dev_fs) + ext2fs_free_mem(&dev_fs); + if (j_inode) + ext2fs_free_mem(&j_inode); + if (journal) + ext2fs_free_mem(&journal); + return retval; +} + +static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx, + struct problem_context *pctx) +{ + struct ext2_super_block *sb = ctx->fs->super; + int recover = ctx->fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_RECOVER; + int has_journal = ctx->fs->super->s_feature_compat & + EXT3_FEATURE_COMPAT_HAS_JOURNAL; + + if (has_journal || sb->s_journal_inum) { + /* The journal inode is bogus, remove and force full fsck */ + pctx->ino = sb->s_journal_inum; + if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) { + if (has_journal && sb->s_journal_inum) + printf("*** ext3 journal has been deleted - " + "filesystem is now ext2 only ***\n\n"); + sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; + sb->s_journal_inum = 0; + ctx->flags |= E2F_FLAG_JOURNAL_INODE; + ctx->fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; + e2fsck_clear_recover(ctx, 1); + return 0; + } + return EXT2_ET_BAD_INODE_NUM; + } else if (recover) { + if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) { + e2fsck_clear_recover(ctx, 1); + return 0; + } + return EXT2_ET_UNSUPP_FEATURE; + } + return 0; +} + +#define V1_SB_SIZE 0x0024 +static void clear_v2_journal_fields(journal_t *journal) +{ + e2fsck_t ctx = journal->j_dev->k_ctx; + struct problem_context pctx; + + clear_problem_context(&pctx); + + if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx)) + return; + + memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0, + ctx->fs->blocksize-V1_SB_SIZE); + mark_buffer_dirty(journal->j_sb_buffer); +} + + +static errcode_t e2fsck_journal_load(journal_t *journal) +{ + e2fsck_t ctx = journal->j_dev->k_ctx; + journal_superblock_t *jsb; + struct buffer_head *jbh = journal->j_sb_buffer; + struct problem_context pctx; + + clear_problem_context(&pctx); + + ll_rw_block(READ, 1, &jbh); + if (jbh->b_err) { + com_err(ctx->device_name, jbh->b_err, "%s", + _("reading journal superblock\n")); + return jbh->b_err; + } + + jsb = journal->j_superblock; + /* If we don't even have JFS_MAGIC, we probably have a wrong inode */ + if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER)) + return e2fsck_journal_fix_bad_inode(ctx, &pctx); + + switch (ntohl(jsb->s_header.h_blocktype)) { + case JFS_SUPERBLOCK_V1: + journal->j_format_version = 1; + if (jsb->s_feature_compat || + jsb->s_feature_incompat || + jsb->s_feature_ro_compat || + jsb->s_nr_users) + clear_v2_journal_fields(journal); + break; + + case JFS_SUPERBLOCK_V2: + journal->j_format_version = 2; + if (ntohl(jsb->s_nr_users) > 1 && + uuid_is_null(ctx->fs->super->s_journal_uuid)) + clear_v2_journal_fields(journal); + if (ntohl(jsb->s_nr_users) > 1) { + fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx); + return EXT2_ET_JOURNAL_UNSUPP_VERSION; + } + break; + + /* + * These should never appear in a journal super block, so if + * they do, the journal is badly corrupted. + */ + case JFS_DESCRIPTOR_BLOCK: + case JFS_COMMIT_BLOCK: + case JFS_REVOKE_BLOCK: + return EXT2_ET_CORRUPT_SUPERBLOCK; + + /* If we don't understand the superblock major type, but there + * is a magic number, then it is likely to be a new format we + * just don't understand, so leave it alone. */ + default: + return EXT2_ET_JOURNAL_UNSUPP_VERSION; + } + + if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES)) + return EXT2_ET_UNSUPP_FEATURE; + + if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES)) + return EXT2_ET_RO_UNSUPP_FEATURE; + + /* We have now checked whether we know enough about the journal + * format to be able to proceed safely, so any other checks that + * fail we should attempt to recover from. */ + if (jsb->s_blocksize != htonl(journal->j_blocksize)) { + com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK, + _("%s: no valid journal superblock found\n"), + ctx->device_name); + return EXT2_ET_CORRUPT_SUPERBLOCK; + } + + if (ntohl(jsb->s_maxlen) < journal->j_maxlen) + journal->j_maxlen = ntohl(jsb->s_maxlen); + else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) { + com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK, + _("%s: journal too short\n"), + ctx->device_name); + return EXT2_ET_CORRUPT_SUPERBLOCK; + } + + journal->j_tail_sequence = ntohl(jsb->s_sequence); + journal->j_transaction_sequence = journal->j_tail_sequence; + journal->j_tail = ntohl(jsb->s_start); + journal->j_first = ntohl(jsb->s_first); + journal->j_last = ntohl(jsb->s_maxlen); + + return 0; +} + +static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb, + journal_t *journal) +{ + char *p; + union { + uuid_t uuid; + __u32 val[4]; + } u; + __u32 new_seq = 0; + int i; + + /* Leave a valid existing V1 superblock signature alone. + * Anything unrecognisable we overwrite with a new V2 + * signature. */ + + if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) || + jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) { + jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); + jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2); + } + + /* Zero out everything else beyond the superblock header */ + + p = ((char *) jsb) + sizeof(journal_header_t); + memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t)); + + jsb->s_blocksize = htonl(ctx->fs->blocksize); + jsb->s_maxlen = htonl(journal->j_maxlen); + jsb->s_first = htonl(1); + + /* Initialize the journal sequence number so that there is "no" + * chance we will find old "valid" transactions in the journal. + * This avoids the need to zero the whole journal (slow to do, + * and risky when we are just recovering the filesystem). + */ + uuid_generate(u.uuid); + for (i = 0; i < 4; i ++) + new_seq ^= u.val[i]; + jsb->s_sequence = htonl(new_seq); + + mark_buffer_dirty(journal->j_sb_buffer); + ll_rw_block(WRITE, 1, &journal->j_sb_buffer); +} + +static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx, + journal_t *journal, + struct problem_context *pctx) +{ + struct ext2_super_block *sb = ctx->fs->super; + int recover = ctx->fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_RECOVER; + + if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) { + if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) { + e2fsck_journal_reset_super(ctx, journal->j_superblock, + journal); + journal->j_transaction_sequence = 1; + e2fsck_clear_recover(ctx, recover); + return 0; + } + return EXT2_ET_CORRUPT_SUPERBLOCK; + } else if (e2fsck_journal_fix_bad_inode(ctx, pctx)) + return EXT2_ET_CORRUPT_SUPERBLOCK; + + return 0; +} + +static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal, + int reset, int drop) +{ + journal_superblock_t *jsb; + + if (drop) + mark_buffer_clean(journal->j_sb_buffer); + else if (!(ctx->options & E2F_OPT_READONLY)) { + jsb = journal->j_superblock; + jsb->s_sequence = htonl(journal->j_transaction_sequence); + if (reset) + jsb->s_start = 0; /* this marks the journal as empty */ + mark_buffer_dirty(journal->j_sb_buffer); + } + brelse(journal->j_sb_buffer); + + if (ctx->journal_io) { + if (ctx->fs && ctx->fs->io != ctx->journal_io) + io_channel_close(ctx->journal_io); + ctx->journal_io = 0; + } + +#ifndef USE_INODE_IO + if (journal->j_inode) + ext2fs_free_mem(&journal->j_inode); +#endif + if (journal->j_fs_dev) + ext2fs_free_mem(&journal->j_fs_dev); + ext2fs_free_mem(&journal); +} + +/* + * This function makes sure that the superblock fields regarding the + * journal are consistent. + */ +errcode_t e2fsck_check_ext3_journal(e2fsck_t ctx) +{ + struct ext2_super_block *sb = ctx->fs->super; + journal_t *journal; + int recover = ctx->fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_RECOVER; + struct problem_context pctx; + problem_t problem; + int reset = 0, force_fsck = 0; + errcode_t retval; + + /* If we don't have any journal features, don't do anything more */ + if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && + !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 && + uuid_is_null(sb->s_journal_uuid)) + return 0; + + clear_problem_context(&pctx); + pctx.num = sb->s_journal_inum; + + retval = e2fsck_get_journal(ctx, &journal); + if (retval) { + if ((retval == EXT2_ET_BAD_INODE_NUM) || + (retval == EXT2_ET_BAD_BLOCK_NUM) || + (retval == EXT2_ET_JOURNAL_TOO_SMALL) || + (retval == EXT2_ET_NO_JOURNAL)) + return e2fsck_journal_fix_bad_inode(ctx, &pctx); + return retval; + } + + retval = e2fsck_journal_load(journal); + if (retval) { + if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) || + ((retval == EXT2_ET_UNSUPP_FEATURE) && + (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT, + &pctx))) || + ((retval == EXT2_ET_RO_UNSUPP_FEATURE) && + (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT, + &pctx))) || + ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) && + (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx)))) + retval = e2fsck_journal_fix_corrupt_super(ctx, journal, + &pctx); + e2fsck_journal_release(ctx, journal, 0, 1); + return retval; + } + + /* + * We want to make the flags consistent here. We will not leave with + * needs_recovery set but has_journal clear. We can't get in a loop + * with -y, -n, or -p, only if a user isn't making up their mind. + */ +no_has_journal: + if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { + recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER; + if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) { + if (recover && + !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx)) + goto no_has_journal; + /* + * Need a full fsck if we are releasing a + * journal stored on a reserved inode. + */ + force_fsck = recover || + (sb->s_journal_inum < EXT2_FIRST_INODE(sb)); + /* Clear all of the journal fields */ + sb->s_journal_inum = 0; + sb->s_journal_dev = 0; + memset(sb->s_journal_uuid, 0, + sizeof(sb->s_journal_uuid)); + e2fsck_clear_recover(ctx, force_fsck); + } else if (!(ctx->options & E2F_OPT_READONLY)) { + sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; + ctx->fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; + ext2fs_mark_super_dirty(ctx->fs); + } + } + + if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL && + !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) && + journal->j_superblock->s_start != 0) { + /* Print status information */ + fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx); + if (ctx->superblock) + problem = PR_0_JOURNAL_RUN_DEFAULT; + else + problem = PR_0_JOURNAL_RUN; + if (fix_problem(ctx, problem, &pctx)) { + ctx->options |= E2F_OPT_FORCE; + sb->s_feature_incompat |= + EXT3_FEATURE_INCOMPAT_RECOVER; + ext2fs_mark_super_dirty(ctx->fs); + } else if (fix_problem(ctx, + PR_0_JOURNAL_RESET_JOURNAL, &pctx)) { + reset = 1; + sb->s_state &= ~EXT2_VALID_FS; + ext2fs_mark_super_dirty(ctx->fs); + } + /* + * If the user answers no to the above question, we + * ignore the fact that journal apparently has data; + * accidentally replaying over valid data would be far + * worse than skipping a questionable recovery. + * + * XXX should we abort with a fatal error here? What + * will the ext3 kernel code do if a filesystem with + * !NEEDS_RECOVERY but with a non-zero + * journal->j_superblock->s_start is mounted? + */ + } + + /* + * If we don't need to do replay the journal, check to see if + * the journal's errno is set; if so, we need to mark the file + * system as being corrupt and clear the journal's s_errno. + */ + if (!(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) && + journal->j_superblock->s_errno) { + ctx->fs->super->s_state |= EXT2_ERROR_FS; + ext2fs_mark_super_dirty(ctx->fs); + journal->j_superblock->s_errno = 0; + mark_buffer_dirty(journal->j_sb_buffer); + } + + e2fsck_journal_release(ctx, journal, reset, 0); + return retval; +} + +static errcode_t recover_ext3_journal(e2fsck_t ctx) +{ + struct problem_context pctx; + journal_t *journal; + errcode_t retval; + + clear_problem_context(&pctx); + + journal_init_revoke_caches(); + retval = e2fsck_get_journal(ctx, &journal); + if (retval) + return retval; + + retval = e2fsck_journal_load(journal); + if (retval) + goto errout; + + retval = journal_init_revoke(journal, 1024); + if (retval) + goto errout; + + retval = -journal_recover(journal); + if (retval) + goto errout; + + if (journal->j_failed_commit) { + pctx.ino = journal->j_failed_commit; + fix_problem(ctx, PR_0_JNL_TXN_CORRUPT, &pctx); + journal->j_superblock->s_errno = -EINVAL; + mark_buffer_dirty(journal->j_sb_buffer); + } + +errout: + journal_destroy_revoke(journal); + journal_destroy_revoke_caches(); + e2fsck_journal_release(ctx, journal, 1, 0); + return retval; +} + +errcode_t e2fsck_run_ext3_journal(e2fsck_t ctx) +{ + io_manager io_ptr = ctx->fs->io->manager; + int blocksize = ctx->fs->blocksize; + errcode_t retval, recover_retval; + io_stats stats = 0; + unsigned long long kbytes_written = 0; + + printf(_("%s: recovering journal\n"), ctx->device_name); + if (ctx->options & E2F_OPT_READONLY) { + printf(_("%s: won't do journal recovery while read-only\n"), + ctx->device_name); + return EXT2_ET_FILE_RO; + } + + if (ctx->fs->flags & EXT2_FLAG_DIRTY) + ext2fs_flush(ctx->fs); /* Force out any modifications */ + + recover_retval = recover_ext3_journal(ctx); + + /* + * Reload the filesystem context to get up-to-date data from disk + * because journal recovery will change the filesystem under us. + */ + if (ctx->fs->super->s_kbytes_written && + ctx->fs->io->manager->get_stats) + ctx->fs->io->manager->get_stats(ctx->fs->io, &stats); + if (stats && stats->bytes_written) + kbytes_written = stats->bytes_written >> 10; + + ext2fs_mmp_stop(ctx->fs); + ext2fs_free(ctx->fs); + retval = ext2fs_open(ctx->filesystem_name, ctx->openfs_flags, + ctx->superblock, blocksize, io_ptr, + &ctx->fs); + if (retval) { + com_err(ctx->program_name, retval, + _("while trying to re-open %s"), + ctx->device_name); + fatal_error(ctx, 0); + } + ctx->fs->priv_data = ctx; + ctx->fs->now = ctx->now; + ctx->fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; + ctx->fs->super->s_kbytes_written += kbytes_written; + + /* Set the superblock flags */ + e2fsck_clear_recover(ctx, recover_retval != 0); + + /* + * Do one last sanity check, and propagate journal->s_errno to + * the EXT2_ERROR_FS flag in the fs superblock if needed. + */ + retval = e2fsck_check_ext3_journal(ctx); + return retval ? retval : recover_retval; +} + +/* + * This function will move the journal inode from a visible file in + * the filesystem directory hierarchy to the reserved inode if necessary. + */ +static const char * const journal_names[] = { + ".journal", "journal", ".journal.dat", "journal.dat", 0 }; + +void e2fsck_move_ext3_journal(e2fsck_t ctx) +{ + struct ext2_super_block *sb = ctx->fs->super; + struct problem_context pctx; + struct ext2_inode inode; + ext2_filsys fs = ctx->fs; + ext2_ino_t ino; + errcode_t retval; + const char * const * cpp; + dgrp_t group; + int mount_flags; + + clear_problem_context(&pctx); + + /* + * If the filesystem is opened read-only, or there is no + * journal, then do nothing. + */ + if ((ctx->options & E2F_OPT_READONLY) || + (sb->s_journal_inum == 0) || + !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) + return; + + /* + * Read in the journal inode + */ + if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0) + return; + + /* + * If it's necessary to backup the journal inode, do so. + */ + if ((sb->s_jnl_backup_type == 0) || + ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) && + memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) { + if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) { + memcpy(sb->s_jnl_blocks, inode.i_block, + EXT2_N_BLOCKS*4); + sb->s_jnl_blocks[15] = inode.i_size_high; + sb->s_jnl_blocks[16] = inode.i_size; + sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; + ext2fs_mark_super_dirty(fs); + fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; + } + } + + /* + * If the journal is already the hidden inode, then do nothing + */ + if (sb->s_journal_inum == EXT2_JOURNAL_INO) + return; + + /* + * The journal inode had better have only one link and not be readable. + */ + if (inode.i_links_count != 1) + return; + + /* + * If the filesystem is mounted, or we can't tell whether + * or not it's mounted, do nothing. + */ + retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags); + if (retval || (mount_flags & EXT2_MF_MOUNTED)) + return; + + /* + * If we can't find the name of the journal inode, then do + * nothing. + */ + for (cpp = journal_names; *cpp; cpp++) { + retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp, + strlen(*cpp), 0, &ino); + if ((retval == 0) && (ino == sb->s_journal_inum)) + break; + } + if (*cpp == 0) + return; + + /* We need the inode bitmap to be loaded */ + retval = ext2fs_read_bitmaps(fs); + if (retval) + return; + + pctx.str = *cpp; + if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx)) + return; + + /* + * OK, we've done all the checks, let's actually move the + * journal inode. Errors at this point mean we need to force + * an ext2 filesystem check. + */ + if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0) + goto err_out; + if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0) + goto err_out; + sb->s_journal_inum = EXT2_JOURNAL_INO; + ext2fs_mark_super_dirty(fs); + fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; + inode.i_links_count = 0; + inode.i_dtime = ctx->now; + if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0) + goto err_out; + + group = ext2fs_group_of_ino(fs, ino); + ext2fs_unmark_inode_bitmap2(fs->inode_map, ino); + ext2fs_mark_ib_dirty(fs); + ext2fs_bg_free_inodes_count_set(fs, group, ext2fs_bg_free_inodes_count(fs, group) + 1); + ext2fs_group_desc_csum_set(fs, group); + fs->super->s_free_inodes_count++; + return; + +err_out: + pctx.errcode = retval; + fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx); + fs->super->s_state &= ~EXT2_VALID_FS; + ext2fs_mark_super_dirty(fs); + return; +} + +/* + * This function makes sure the superblock hint for the external + * journal is correct. + */ +int e2fsck_fix_ext3_journal_hint(e2fsck_t ctx) +{ + struct ext2_super_block *sb = ctx->fs->super; + struct problem_context pctx; + char uuid[37], *journal_name; + struct stat st; + + if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) || + uuid_is_null(sb->s_journal_uuid)) + return 0; + + uuid_unparse(sb->s_journal_uuid, uuid); + journal_name = blkid_get_devname(ctx->blkid, "UUID", uuid); + if (!journal_name) + return 0; + + if (stat(journal_name, &st) < 0) { + free(journal_name); + return 0; + } + + if (st.st_rdev != sb->s_journal_dev) { + clear_problem_context(&pctx); + pctx.num = st.st_rdev; + if (fix_problem(ctx, PR_0_EXTERNAL_JOURNAL_HINT, &pctx)) { + sb->s_journal_dev = st.st_rdev; + ext2fs_mark_super_dirty(ctx->fs); + } + } + + free(journal_name); + return 0; +}
diff --git a/e2fsck/logfile.c b/e2fsck/logfile.c new file mode 100644 index 0000000..e004f31 --- /dev/null +++ b/e2fsck/logfile.c
@@ -0,0 +1,400 @@ +/* + * logfile.c --- set up e2fsck log files + * + * Copyright 1996, 1997 by Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include "config.h" +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "e2fsck.h" +#include <pwd.h> + +extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */ + +struct string { + char *s; + int len; + int end; +}; + +static void alloc_string(struct string *s, int len) +{ + s->s = malloc(len); +/* e2fsck_allocate_memory(ctx, len, "logfile name"); */ + s->len = len; + s->end = 0; +} + +static void append_string(struct string *s, const char *a, int len) +{ + int needlen; + + if (!len) + len = strlen(a); + + needlen = s->end + len + 1; + if (needlen > s->len) { + char *n; + + if (s->len * 2 > needlen) + needlen = s->len * 2; + n = realloc(s->s, needlen); + + if (n) { + s->s = n; + s->len = needlen; + } else { + /* Don't append if we ran out of memory */ + return; + } + } + memcpy(s->s + s->end, a, len); + s->end += len; + s->s[s->end] = 0; +} + +#define FLAG_UTC 0x0001 + +static void expand_percent_expression(e2fsck_t ctx, char ch, + struct string *s, int *flags) +{ + struct tm *tm = NULL, tm_struct; + struct passwd *pw = NULL, pw_struct; + char *cp; + char buf[256]; + + if ((ch == 'D') || (ch == 'd') || (ch == 'm') || (ch == 'y') || + (ch == 'Y') || + (ch == 'T') || (ch == 'H') || (ch == 'M') || (ch == 'S')) { + tzset(); + tm = (*flags & FLAG_UTC) ? gmtime_r(&ctx->now, &tm_struct) : + localtime_r(&ctx->now, &tm_struct); + } + + switch (ch) { + case '%': + append_string(s, "%", 1); + return; + case 'd': + sprintf(buf, "%02d", tm->tm_mday); + break; + case 'D': + sprintf(buf, "%d%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1, + tm->tm_mday); + break; + case 'h': +#ifdef TEST_PROGRAM + strcpy(buf, "server"); +#else + buf[0] = 0; + gethostname(buf, sizeof(buf)); + buf[sizeof(buf)-1] = 0; +#endif + break; + case 'H': + sprintf(buf, "%02d", tm->tm_hour); + break; + case 'm': + sprintf(buf, "%02d", tm->tm_mon + 1); + break; + case 'M': + sprintf(buf, "%02d", tm->tm_min); + break; + case 'N': /* block device name */ + cp = strrchr(ctx->filesystem_name, '/'); + if (cp) + cp++; + else + cp = ctx->filesystem_name; + append_string(s, cp, 0); + return; + case 'p': + sprintf(buf, "%lu", (unsigned long) getpid()); + break; + case 's': + sprintf(buf, "%lu", (unsigned long) ctx->now); + break; + case 'S': + sprintf(buf, "%02d", tm->tm_sec); + break; + case 'T': + sprintf(buf, "%02d%02d%02d", tm->tm_hour, tm->tm_min, + tm->tm_sec); + break; + case 'u': +#ifdef TEST_PROGRAM + strcpy(buf, "tytso"); + break; +#else +#ifdef HAVE_GETPWUID_R + getpwuid_r(getuid(), &pw_struct, buf, sizeof(buf), &pw); +#else + pw = getpwuid(getuid()); +#endif + if (pw) + append_string(s, pw->pw_name, 0); + return; +#endif + case 'U': + *flags |= FLAG_UTC; + return; + case 'y': + sprintf(buf, "%02d", tm->tm_year % 100); + break; + case 'Y': + sprintf(buf, "%d", tm->tm_year + 1900); + break; + } + append_string(s, buf, 0); +} + +static void expand_logfn(e2fsck_t ctx, const char *log_fn, struct string *s) +{ + const char *cp; + int i; + int flags = 0; + + alloc_string(s, 100); + for (cp = log_fn; *cp; cp++) { + if (cp[0] == '%') { + cp++; + expand_percent_expression(ctx, *cp, s, &flags); + continue; + } + for (i = 0; cp[i]; i++) + if (cp[i] == '%') + break; + append_string(s, cp, i); + cp += i-1; + } +} + +static int outbufsize; +static void *outbuf; + +static int do_read(int fd) +{ + int c; + char *n; + char buffer[4096]; + + c = read(fd, buffer, sizeof(buffer)-1); + if (c <= 0) + return c; + + n = realloc(outbuf, outbufsize + c); + if (n) { + outbuf = n; + memcpy(((char *)outbuf)+outbufsize, buffer, c); + outbufsize += c; + } + return c; +} + +/* + * Fork a child process to save the output of the logfile until the + * appropriate file system is mounted read/write. + */ +static FILE *save_output(const char *s0, const char *s1, const char *s2) +{ + int c, fd, fds[2]; + char *cp; + pid_t pid; + FILE *ret; + + if (s0 && *s0 == 0) + s0 = 0; + if (s1 && *s1 == 0) + s1 = 0; + if (s2 && *s2 == 0) + s2 = 0; + + /* At least one potential output file name is valid */ + if (!s0 && !s1 && !s2) + return NULL; + if (pipe(fds) < 0) { + perror("pipe"); + exit(1); + } + + pid = fork(); + if (pid < 0) { + perror("fork"); + exit(1); + } + + if (pid == 0) { + if (e2fsck_global_ctx && e2fsck_global_ctx->progress_fd) + close(e2fsck_global_ctx->progress_fd); + if (daemon(0, 0) < 0) { + perror("daemon"); + exit(1); + } + /* + * Grab the output from our parent + */ + close(fds[1]); + while (do_read(fds[0]) > 0) + ; + close(fds[0]); + + /* OK, now let's try to open the output file */ + fd = -1; + while (1) { + if (fd < 0 && s0) + fd = open(s0, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd < 0 && s1) + fd = open(s1, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd < 0 && s2) + fd = open(s2, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (fd >= 0) + break; + sleep(1); + } + + cp = outbuf; + while (outbufsize > 0) { + c = write(fd, cp, outbufsize); + if (c < 0) { + if ((errno == EAGAIN) || (errno == EINTR)) + continue; + break; + } + outbufsize -= c; + cp += c; + } + exit(0); + } + + close(fds[0]); + ret = fdopen(fds[1], "w"); + if (!ret) + close(fds[1]); + return ret; +} + +#ifndef TEST_PROGRAM +void set_up_logging(e2fsck_t ctx) +{ + struct string s, s1, s2; + char *s0 = 0, *log_dir = 0, *log_fn = 0; + int log_dir_wait = 0; + + s.s = s1.s = s2.s = 0; + + profile_get_boolean(ctx->profile, "options", "log_dir_wait", 0, 0, + &log_dir_wait); + if (ctx->log_fn) + log_fn = string_copy(ctx, ctx->log_fn, 0); + else + profile_get_string(ctx->profile, "options", "log_filename", + 0, 0, &log_fn); + profile_get_string(ctx->profile, "options", "log_dir", 0, 0, &log_dir); + + if (!log_fn || !log_fn[0]) + goto out; + + expand_logfn(ctx, log_fn, &s); + if ((log_fn[0] == '/') || !log_dir || !log_dir[0]) + s0 = s.s; + + if (log_dir && log_dir[0]) { + alloc_string(&s1, strlen(log_dir) + strlen(s.s) + 2); + append_string(&s1, log_dir, 0); + append_string(&s1, "/", 1); + append_string(&s1, s.s, 0); + } + + free(log_dir); + profile_get_string(ctx->profile, "options", "log_dir_fallback", 0, 0, + &log_dir); + if (log_dir && log_dir[0]) { + alloc_string(&s2, strlen(log_dir) + strlen(s.s) + 2); + append_string(&s2, log_dir, 0); + append_string(&s2, "/", 1); + append_string(&s2, s.s, 0); + printf("%s\n", s2.s); + } + + if (s0) + ctx->logf = fopen(s0, "w"); + if (!ctx->logf && s1.s) + ctx->logf = fopen(s1.s, "w"); + if (!ctx->logf && s2.s) + ctx->logf = fopen(s2.s, "w"); + if (!ctx->logf && log_dir_wait) + ctx->logf = save_output(s0, s1.s, s2.s); + +out: + free(s.s); + free(s1.s); + free(s2.s); + free(log_fn); + free(log_dir); + return; +} +#else +void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size, + const char *description) +{ + void *ret; + char buf[256]; + + ret = malloc(size); + if (!ret) { + sprintf(buf, "Can't allocate %s\n", description); + exit(1); + } + memset(ret, 0, size); + return ret; +} + +errcode_t e2fsck_allocate_context(e2fsck_t *ret) +{ + e2fsck_t context; + errcode_t retval; + char *time_env; + + context = malloc(sizeof(struct e2fsck_struct)); + if (!context) + return ENOMEM; + + memset(context, 0, sizeof(struct e2fsck_struct)); + + context->now = 1332006474; + + context->filesystem_name = "/dev/sda3"; + context->device_name = "fslabel"; + + *ret = context; + return 0; +} + +int main(int argc, char **argv) +{ + e2fsck_t ctx; + struct string s; + + putenv("TZ=EST+5:00"); + e2fsck_allocate_context(&ctx); + expand_logfn(ctx, "e2fsck-%N.%h.%u.%D-%T", &s); + printf("%s\n", s.s); + free(s.s); + expand_logfn(ctx, "e2fsck-%N.%h.%u.%Y%m%d-%H%M%S", &s); + printf("%s\n", s.s); + free(s.s); + + return 0; +} +#endif
diff --git a/e2fsck/message.c b/e2fsck/message.c new file mode 100644 index 0000000..97f53fa --- /dev/null +++ b/e2fsck/message.c
@@ -0,0 +1,564 @@ +/* + * message.c --- print e2fsck messages (with compression) + * + * Copyright 1996, 1997 by Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * print_e2fsck_message() prints a message to the user, using + * compression techniques and expansions of abbreviations. + * + * The following % expansions are supported: + * + * %b <blk> block number + * %B <blkcount> interpret blkcount as blkcount + * %c <blk2> block number + * %Di <dirent>->ino inode number + * %Dn <dirent>->name string + * %Dr <dirent>->rec_len + * %Dl <dirent>->name_len + * %Dt <dirent>->filetype + * %d <dir> inode number + * %g <group> integer + * %i <ino> inode number + * %Is <inode> -> i_size + * %IS <inode> -> i_extra_isize + * %Ib <inode> -> i_blocks + * %Il <inode> -> i_links_count + * %Im <inode> -> i_mode + * %IM <inode> -> i_mtime + * %IF <inode> -> i_faddr + * %If <inode> -> i_file_acl + * %Id <inode> -> i_dir_acl + * %Iu <inode> -> i_uid + * %Ig <inode> -> i_gid + * %It <inode type> + * %j <ino2> inode number + * %m <com_err error message> + * %N <num> + * %p ext2fs_get_pathname of directory <ino> + * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as + * the containing directory. (If dirent is NULL + * then return the pathname of directory <ino2>) + * %q ext2fs_get_pathname of directory <dir> + * %Q ext2fs_get_pathname of directory <ino> with <dir> as + * the containing directory. + * %r <blkcount> interpret blkcount as refcount + * %s <str> miscellaneous string + * %S backup superblock + * %X <num> hexadecimal format + * + * The following '@' expansions are supported: + * + * @a extended attribute + * @A error allocating + * @b block + * @B bitmap + * @c compress + * @C conflicts with some other fs block + * @D deleted + * @d directory + * @e entry + * @E Entry '%Dn' in %p (%i) + * @f filesystem + * @F for @i %i (%Q) is + * @g group + * @h HTREE directory inode + * @i inode + * @I illegal + * @j journal + * @l lost+found + * @L is a link + * @m multiply-claimed + * @n invalid + * @o orphaned + * @p problem in + * @q quota + * @r root inode + * @s should be + * @S superblock + * @u unattached + * @v device + * @x extent + * @z zero-length + */ + +#include "config.h" +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> +#include <termios.h> + +#include "e2fsck.h" + +#include "problem.h" + +#ifdef __GNUC__ +#define _INLINE_ __inline__ +#else +#define _INLINE_ +#endif + +/* + * This structure defines the abbreviations used by the text strings + * below. The first character in the string is the index letter. An + * abbreviation of the form '@<i>' is expanded by looking up the index + * letter <i> in the table below. + */ +static const char *abbrevs[] = { + N_("aextended attribute"), + N_("Aerror allocating"), + N_("bblock"), + N_("Bbitmap"), + N_("ccompress"), + N_("Cconflicts with some other fs @b"), + N_("ddirectory"), + N_("Ddeleted"), + N_("eentry"), + N_("E@e '%Dn' in %p (%i)"), + N_("ffilesystem"), + N_("Ffor @i %i (%Q) is"), + N_("ggroup"), + N_("hHTREE @d @i"), + N_("iinode"), + N_("Iillegal"), + N_("jjournal"), + N_("llost+found"), + N_("Lis a link"), + N_("mmultiply-claimed"), + N_("ninvalid"), + N_("oorphaned"), + N_("pproblem in"), + N_("qquota"), + N_("rroot @i"), + N_("sshould be"), + N_("Ssuper@b"), + N_("uunattached"), + N_("vdevice"), + N_("xextent"), + N_("zzero-length"), + "@@", + 0 + }; + +/* + * Give more user friendly names to the "special" inodes. + */ +#define num_special_inodes 11 +static const char *special_inode_name[] = +{ + N_("<The NULL inode>"), /* 0 */ + N_("<The bad blocks inode>"), /* 1 */ + "/", /* 2 */ + N_("<The user quota inode>"), /* 3 */ + N_("<The group quota inode>"), /* 4 */ + N_("<The boot loader inode>"), /* 5 */ + N_("<The undelete directory inode>"), /* 6 */ + N_("<The group descriptor inode>"), /* 7 */ + N_("<The journal inode>"), /* 8 */ + N_("<Reserved inode 9>"), /* 9 */ + N_("<Reserved inode 10>"), /* 10 */ +}; + +/* + * This function does "safe" printing. It will convert non-printable + * ASCII characters using '^' and M- notation. + */ +static void safe_print(FILE *f, const char *cp, int len) +{ + unsigned char ch; + + if (len < 0) + len = strlen(cp); + + while (len--) { + ch = *cp++; + if (ch > 128) { + fputs("M-", f); + ch -= 128; + } + if ((ch < 32) || (ch == 0x7f)) { + fputc('^', f); + ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */ + } + fputc(ch, f); + } +} + + +/* + * This function prints a pathname, using the ext2fs_get_pathname + * function + */ +static void print_pathname(FILE *f, ext2_filsys fs, ext2_ino_t dir, + ext2_ino_t ino) +{ + errcode_t retval = 0; + char *path; + + if (!dir && (ino < num_special_inodes)) { + fputs(_(special_inode_name[ino]), f); + return; + } + + if (fs) + retval = ext2fs_get_pathname(fs, dir, ino, &path); + if (!fs || retval) + fputs("???", f); + else { + safe_print(f, path, -1); + ext2fs_free_mem(&path); + } +} + +static void print_time(FILE *f, time_t t) +{ + const char * time_str; + static int do_gmt = -1; + +#ifdef __dietlibc__ + /* The diet libc doesn't respect the TZ environemnt variable */ + if (do_gmt == -1) { + time_str = getenv("TZ"); + if (!time_str) + time_str = ""; + do_gmt = !strcmp(time_str, "GMT") || + !strcmp(time_str, "GMT0"); + } +#endif + time_str = asctime((do_gmt > 0) ? gmtime(&t) : localtime(&t)); + fprintf(f, "%.24s", time_str); +} + +/* + * This function handles the '@' expansion. We allow recursive + * expansion; an @ expression can contain further '@' and '%' + * expressions. + */ +static _INLINE_ void expand_at_expression(FILE *f, e2fsck_t ctx, char ch, + struct problem_context *pctx, + int *first, int recurse) +{ + const char **cpp, *str; + + /* Search for the abbreviation */ + for (cpp = abbrevs; *cpp; cpp++) { + if (ch == *cpp[0]) + break; + } + if (*cpp && recurse < 10) { + str = _(*cpp) + 1; + if (*first && islower(*str)) { + *first = 0; + fputc(toupper(*str++), f); + } + print_e2fsck_message(f, ctx, str, pctx, *first, recurse+1); + } else + fprintf(f, "@%c", ch); +} + +/* + * This function expands '%IX' expressions + */ +static _INLINE_ void expand_inode_expression(FILE *f, ext2_filsys fs, char ch, + struct problem_context *ctx) +{ + struct ext2_inode *inode; + struct ext2_inode_large *large_inode; + + if (!ctx || !ctx->inode) + goto no_inode; + + inode = ctx->inode; + large_inode = (struct ext2_inode_large *) inode; + + switch (ch) { + case 's': + if (LINUX_S_ISDIR(inode->i_mode)) + fprintf(f, "%u", inode->i_size); + else { +#ifdef EXT2_NO_64_TYPE + if (inode->i_size_high) + fprintf(f, "0x%x%08x", inode->i_size_high, + inode->i_size); + else + fprintf(f, "%u", inode->i_size); +#else + fprintf(f, "%llu", EXT2_I_SIZE(inode)); +#endif + } + break; + case 'S': + fprintf(f, "%u", large_inode->i_extra_isize); + break; + case 'b': + if (fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_HUGE_FILE) + fprintf(f, "%llu", inode->i_blocks + + (((long long) inode->osd2.linux2.l_i_blocks_hi) + << 32)); + else + fprintf(f, "%u", inode->i_blocks); + break; + case 'l': + fprintf(f, "%d", inode->i_links_count); + break; + case 'm': + fprintf(f, "0%o", inode->i_mode); + break; + case 'M': + print_time(f, inode->i_mtime); + break; + case 'F': + fprintf(f, "%u", inode->i_faddr); + break; + case 'f': + fprintf(f, "%llu", ext2fs_file_acl_block(fs, inode)); + break; + case 'd': + fprintf(f, "%u", (LINUX_S_ISDIR(inode->i_mode) ? + inode->i_dir_acl : 0)); + break; + case 'u': + fprintf(f, "%d", inode_uid(*inode)); + break; + case 'g': + fprintf(f, "%d", inode_gid(*inode)); + break; + case 't': + if (LINUX_S_ISREG(inode->i_mode)) + fputs(_("regular file"), f); + else if (LINUX_S_ISDIR(inode->i_mode)) + fputs(_("directory"), f); + else if (LINUX_S_ISCHR(inode->i_mode)) + fputs(_("character device"), f); + else if (LINUX_S_ISBLK(inode->i_mode)) + fputs(_("block device"), f); + else if (LINUX_S_ISFIFO(inode->i_mode)) + fputs(_("named pipe"), f); + else if (LINUX_S_ISLNK(inode->i_mode)) + fputs(_("symbolic link"), f); + else if (LINUX_S_ISSOCK(inode->i_mode)) + fputs(_("socket"), f); + else + fprintf(f, _("unknown file type with mode 0%o"), + inode->i_mode); + break; + default: + no_inode: + fprintf(f, "%%I%c", ch); + break; + } +} + +/* + * This function expands '%dX' expressions + */ +static _INLINE_ void expand_dirent_expression(FILE *f, ext2_filsys fs, char ch, + struct problem_context *ctx) +{ + struct ext2_dir_entry *dirent; + unsigned int rec_len, len; + + if (!ctx || !ctx->dirent) + goto no_dirent; + + dirent = ctx->dirent; + + switch (ch) { + case 'i': + fprintf(f, "%u", dirent->inode); + break; + case 'n': + len = dirent->name_len & 0xFF; + if ((ext2fs_get_rec_len(fs, dirent, &rec_len) == 0) && + (len > rec_len)) + len = rec_len; + safe_print(f, dirent->name, len); + break; + case 'r': + (void) ext2fs_get_rec_len(fs, dirent, &rec_len); + fprintf(f, "%u", rec_len); + break; + case 'l': + fprintf(f, "%u", dirent->name_len & 0xFF); + break; + case 't': + fprintf(f, "%u", dirent->name_len >> 8); + break; + default: + no_dirent: + fprintf(f, "%%D%c", ch); + break; + } +} + +static _INLINE_ void expand_percent_expression(FILE *f, ext2_filsys fs, + char ch, int width, int *first, + struct problem_context *ctx) +{ + e2fsck_t e2fsck_ctx = fs ? (e2fsck_t) fs->priv_data : NULL; + const char *m; + + if (!ctx) + goto no_context; + + switch (ch) { + case '%': + fputc('%', f); + break; + case 'b': +#ifdef EXT2_NO_64_TYPE + fprintf(f, "%*u", width, (unsigned long) ctx->blk); +#else + fprintf(f, "%*llu", width, (unsigned long long) ctx->blk); +#endif + break; + case 'B': + if (ctx->blkcount == BLOCK_COUNT_IND) + m = _("indirect block"); + else if (ctx->blkcount == BLOCK_COUNT_DIND) + m = _("double indirect block"); + else if (ctx->blkcount == BLOCK_COUNT_TIND) + m = _("triple indirect block"); + else if (ctx->blkcount == BLOCK_COUNT_TRANSLATOR) + m = _("translator block"); + else + m = _("block #"); + if (*first && islower(m[0])) + fputc(toupper(*m++), f); + fputs(m, f); + if (ctx->blkcount >= 0) { +#ifdef EXT2_NO_64_TYPE + fprintf(f, "%d", ctx->blkcount); +#else + fprintf(f, "%lld", (long long) ctx->blkcount); +#endif + } + break; + case 'c': +#ifdef EXT2_NO_64_TYPE + fprintf(f, "%*u", width, (unsigned long) ctx->blk2); +#else + fprintf(f, "%*llu", width, (unsigned long long) ctx->blk2); +#endif + break; + case 'd': + fprintf(f, "%*u", width, ctx->dir); + break; + case 'g': + fprintf(f, "%*u", width, ctx->group); + break; + case 'i': + fprintf(f, "%*u", width, ctx->ino); + break; + case 'j': + fprintf(f, "%*u", width, ctx->ino2); + break; + case 'm': + fprintf(f, "%*s", width, error_message(ctx->errcode)); + break; + case 'N': +#ifdef EXT2_NO_64_TYPE + fprintf(f, "%*u", width, ctx->num); +#else + fprintf(f, "%*llu", width, (long long)ctx->num); +#endif + break; + case 'p': + print_pathname(f, fs, ctx->ino, 0); + break; + case 'P': + print_pathname(f, fs, ctx->ino2, + ctx->dirent ? ctx->dirent->inode : 0); + break; + case 'q': + print_pathname(f, fs, ctx->dir, 0); + break; + case 'Q': + print_pathname(f, fs, ctx->dir, ctx->ino); + break; + case 'r': +#ifdef EXT2_NO_64_TYPE + fprintf(f, "%*d", width, ctx->blkcount); +#else + fprintf(f, "%*lld", width, (long long) ctx->blkcount); +#endif + break; + case 'S': + fprintf(f, "%llu", get_backup_sb(NULL, fs, NULL, NULL)); + break; + case 's': + fprintf(f, "%*s", width, ctx->str ? ctx->str : "NULL"); + break; + case 't': + print_time(f, (time_t) ctx->num); + break; + case 'T': + print_time(f, e2fsck_ctx ? e2fsck_ctx->now : time(0)); + break; + case 'x': + fprintf(f, "0x%0*x", width, ctx->csum1); + break; + case 'X': +#ifdef EXT2_NO_64_TYPE + fprintf(f, "0x%0*x", width, ctx->num); +#else + fprintf(f, "0x%0*llx", width, (long long)ctx->num); +#endif + break; + case 'y': + fprintf(f, "0x%0*x", width, ctx->csum2); + break; + default: + no_context: + fprintf(f, "%%%c", ch); + break; + } +} + +void print_e2fsck_message(FILE *f, e2fsck_t ctx, const char *msg, + struct problem_context *pctx, int first, + int recurse) +{ + ext2_filsys fs = ctx->fs; + const char * cp; + int i, width; + + e2fsck_clear_progbar(ctx); + for (cp = msg; *cp; cp++) { + if (cp[0] == '@') { + cp++; + expand_at_expression(f, ctx, *cp, pctx, &first, + recurse); + } else if (cp[0] == '%') { + cp++; + width = 0; + while (isdigit(cp[0])) { + width = (width * 10) + cp[0] - '0'; + cp++; + } + if (cp[0] == 'I') { + cp++; + expand_inode_expression(f, fs, *cp, pctx); + } else if (cp[0] == 'D') { + cp++; + expand_dirent_expression(f, fs, *cp, pctx); + } else { + expand_percent_expression(f, fs, *cp, width, + &first, pctx); + } + } else { + for (i=0; cp[i]; i++) + if ((cp[i] == '@') || cp[i] == '%') + break; + fprintf(f, "%.*s", i, cp); + cp += i-1; + } + first = 0; + } +}
diff --git a/e2fsck/mtrace.awk b/e2fsck/mtrace.awk new file mode 100644 index 0000000..7e96b8a --- /dev/null +++ b/e2fsck/mtrace.awk
@@ -0,0 +1,37 @@ +#!/usr/bin/awk -f +# +# Awk program to analyze mtrace.c output. +# +$1 == "+" { if (allocated[$2] != "") + print "+", $2, "Alloc", NR, "duplicate:", allocated[$2]; + else + allocated[$2] = $3; + } +$1 == "-" { if (allocated[$2] != "") { + allocated[$2] = ""; + if (allocated[$2] != "") + print "DELETE FAILED", $2, allocated[$2]; + } else + print "-", $2, "Free", NR, "was never alloc'd"; + } +$1 == "<" { if (allocated[$2] != "") + allocated[$2] = ""; + else + print "-", $2, "Realloc", NR, "was never alloc'd"; + } +$1 == ">" { if (allocated[$2] != "") + print "+", $2, "Realloc", NR, "duplicate:", allocated[$2]; + else + allocated[$2] = $3; + } + +# Ignore "= Start" +$1 == "=" { } +# Ignore failed realloc attempts for now +$1 == "!" { } + + +END { for (x in allocated) + if (allocated[x] != "") + print "+", x, allocated[x]; + }
diff --git a/e2fsck/mtrace.c b/e2fsck/mtrace.c new file mode 100644 index 0000000..2b7b34a --- /dev/null +++ b/e2fsck/mtrace.c
@@ -0,0 +1,160 @@ +/* More debugging hooks for `malloc'. + Copyright (C) 1991, 1992 Free Software Foundation, Inc. + Written April 2, 1991 by John Gilmore of Cygnus Support. + Based on mcheck.c by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#include "config.h" + +#ifndef _MALLOC_INTERNAL +#define _MALLOC_INTERNAL +#include "./mtrace.h" +#endif + +#include <stdio.h> + +#ifndef __GNU_LIBRARY__ +extern char *getenv (); +#else +#include <stdlib.h> +#endif + +static FILE *mallstream; +static char mallenv[]= "MALLOC_TRACE"; +static char mallbuf[BUFSIZ]; /* Buffer for the output. */ + +/* Address to breakpoint on accesses to... */ +__ptr_t mallwatch; + +/* Old hook values. */ +static void (*tr_old_free_hook) __P ((__ptr_t ptr)); +static __ptr_t (*tr_old_malloc_hook) __P ((size_t size)); +static __ptr_t (*tr_old_realloc_hook) __P ((__ptr_t ptr, size_t size)); + +/* + * Added by TYT, 10/10/93 --- so that we can print + */ +FILE *malloc_get_mallstream() +{ + return mallstream; +} + +/* This function is called when the block being alloc'd, realloc'd, or + freed has an address matching the variable "mallwatch". In a debugger, + set "mallwatch" to the address of interest, then put a breakpoint on + tr_break. */ + +void tr_break __P ((void)); +void +tr_break () +{ +} + +static void tr_freehook __P ((__ptr_t)); +static void +tr_freehook (ptr) + __ptr_t ptr; +{ + fprintf (mallstream, "- %p\n", ptr); /* Be sure to print it first. */ + if (ptr == mallwatch) + tr_break (); + __free_hook = tr_old_free_hook; + free (ptr); + __free_hook = tr_freehook; +} + +static __ptr_t tr_mallochook __P ((size_t)); +static __ptr_t +tr_mallochook (size) + size_t size; +{ + __ptr_t hdr; + + __malloc_hook = tr_old_malloc_hook; + hdr = (__ptr_t) malloc (size); + __malloc_hook = tr_mallochook; + + /* We could be printing a NULL here; that's OK. */ + fprintf (mallstream, "+ %p %d\n", hdr, size); + + if (hdr == mallwatch) + tr_break (); + + return hdr; +} + +static __ptr_t tr_reallochook __P ((__ptr_t, size_t)); +static __ptr_t +tr_reallochook (ptr, size) + __ptr_t ptr; + size_t size; +{ + __ptr_t hdr; + + if (ptr == mallwatch) + tr_break (); + + __free_hook = tr_old_free_hook; + __malloc_hook = tr_old_malloc_hook; + __realloc_hook = tr_old_realloc_hook; + hdr = (__ptr_t) realloc (ptr, size); + __free_hook = tr_freehook; + __malloc_hook = tr_mallochook; + __realloc_hook = tr_reallochook; + if (hdr == NULL) + /* Failed realloc. */ + fprintf (mallstream, "! %p %d\n", ptr, size); + else + fprintf (mallstream, "< %p\n> %p %d\n", ptr, hdr, size); + + if (hdr == mallwatch) + tr_break (); + + return hdr; +} + +/* We enable tracing if either the environment variable MALLOC_TRACE + is set, or if the variable mallwatch has been patched to an address + that the debugging user wants us to stop on. When patching mallwatch, + don't forget to set a breakpoint on tr_break! */ + +void +mtrace () +{ + char *mallfile; + + mallfile = getenv (mallenv); + if (mallfile != NULL || mallwatch != NULL) + { + mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "w"); + if (mallstream != NULL) + { + /* Be sure it doesn't malloc its buffer! */ + setbuf (mallstream, mallbuf); + fprintf (mallstream, "= Start\n"); + tr_old_free_hook = __free_hook; + __free_hook = tr_freehook; + tr_old_malloc_hook = __malloc_hook; + __malloc_hook = tr_mallochook; + tr_old_realloc_hook = __realloc_hook; + __realloc_hook = tr_reallochook; + } + } +}
diff --git a/e2fsck/mtrace.h b/e2fsck/mtrace.h new file mode 100644 index 0000000..2ed20eb --- /dev/null +++ b/e2fsck/mtrace.h
@@ -0,0 +1,231 @@ +/* Declarations for `malloc' and friends. + Copyright 1990, 1991, 1992 Free Software Foundation, Inc. + Written May 1989 by Mike Haertel. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#ifndef _MTRACE_H + +#define _MTRACE_H 1 + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if defined (__cplusplus) || (defined (__STDC__) && __STDC__) +#undef __P +#define __P(args) args +#undef __ptr_t +#define __ptr_t void * +#else /* Not C++ or ANSI C. */ +#undef __P +#define __P(args) () +#undef const +#define const +#undef __ptr_t +#define __ptr_t char * +#endif /* C++ or ANSI C. */ + +#ifndef NULL +#define NULL 0 +#endif + +#ifdef __STDC__ +#include <stddef.h> +#else +#undef size_t +#define size_t unsigned int +#undef ptrdiff_t +#define ptrdiff_t int +#endif + + +/* Allocate SIZE bytes of memory. */ +extern __ptr_t malloc __P ((size_t __size)); +/* Re-allocate the previously allocated block + in __ptr_t, making the new block SIZE bytes long. */ +extern __ptr_t realloc __P ((__ptr_t __ptr, size_t __size)); +/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ +extern __ptr_t calloc __P ((size_t __nmemb, size_t __size)); +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +extern void free __P ((__ptr_t __ptr)); + +/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ +extern __ptr_t memalign __P ((size_t __alignment, size_t __size)); + +/* Allocate SIZE bytes on a page boundary. */ +extern __ptr_t valloc __P ((size_t __size)); + + +#ifdef _MALLOC_INTERNAL + +#include <stdio.h> /* Harmless, gets __GNU_LIBRARY__ defined. */ + +#if defined(__GNU_LIBRARY__) || defined(STDC_HEADERS) || defined(USG) +#include <string.h> +#else +#ifndef memset +#define memset(s, zero, n) bzero ((s), (n)) +#endif +#ifndef memcpy +#define memcpy(d, s, n) bcopy ((s), (d), (n)) +#endif +#endif + + +#if defined(__GNU_LIBRARY__) || defined(__STDC__) +#include <limits.h> +#else +#define CHAR_BIT 8 +#endif + +/* The allocator divides the heap into blocks of fixed size; large + requests receive one or more whole blocks, and small requests + receive a fragment of a block. Fragment sizes are powers of two, + and all fragments of a block are the same size. When all the + fragments in a block have been freed, the block itself is freed. */ +#define INT_BIT (CHAR_BIT * sizeof(int)) +#define BLOCKLOG (INT_BIT > 16 ? 12 : 9) +#define BLOCKSIZE (1 << BLOCKLOG) +#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE) + +/* Determine the amount of memory spanned by the initial heap table + (not an absolute limit). */ +#define HEAP (INT_BIT > 16 ? 4194304 : 65536) + +/* Number of contiguous free blocks allowed to build up at the end of + memory before they will be returned to the system. */ +#define FINAL_FREE_BLOCKS 8 + +/* Data structure giving per-block information. */ +typedef union + { + /* Heap information for a busy block. */ + struct + { + /* Zero for a large block, or positive giving the + logarithm to the base two of the fragment size. */ + int type; + union + { + struct + { + size_t nfree; /* Free fragments in a fragmented block. */ + size_t first; /* First free fragment of the block. */ + } frag; + /* Size (in blocks) of a large cluster. */ + size_t size; + } info; + } busy; + /* Heap information for a free block + (that may be the first of a free cluster). */ + struct + { + size_t size; /* Size (in blocks) of a free cluster. */ + size_t next; /* Index of next free cluster. */ + size_t prev; /* Index of previous free cluster. */ + } free; + } malloc_info; + +/* Pointer to first block of the heap. */ +extern char *_heapbase; + +/* Table indexed by block number giving per-block information. */ +extern malloc_info *_heapinfo; + +/* Address to block number and vice versa. */ +#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) +#define ADDRESS(B) ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase)) + +/* Current search index for the heap table. */ +extern size_t _heapindex; + +/* Limit of valid info table indices. */ +extern size_t _heaplimit; + +/* Doubly linked lists of free fragments. */ +struct list + { + struct list *next; + struct list *prev; + }; + +/* Free list headers for each fragment size. */ +extern struct list _fraghead[]; + +/* List of blocks allocated with `memalign' (or `valloc'). */ +struct alignlist + { + struct alignlist *next; + __ptr_t aligned; /* The address that memaligned returned. */ + __ptr_t exact; /* The address that malloc returned. */ + }; +extern struct alignlist *_aligned_blocks; + +/* Instrumentation. */ +extern size_t _chunks_used; +extern size_t _bytes_used; +extern size_t _chunks_free; +extern size_t _bytes_free; + +/* Internal version of `free' used in `morecore' (malloc.c). */ +extern void _free_internal __P ((__ptr_t __ptr)); + +#endif /* _MALLOC_INTERNAL. */ + +/* Underlying allocation function; successive calls should + return contiguous pieces of memory. */ +extern __ptr_t (*__morecore) __P ((ptrdiff_t __size)); + +/* Default value of `__morecore'. */ +extern __ptr_t __default_morecore __P ((ptrdiff_t __size)); + +/* Nonzero if `malloc' has been called and done its initialization. */ +extern int __malloc_initialized; + +/* Hooks for debugging versions. */ +extern void (*__free_hook) __P ((__ptr_t __ptr)); +extern __ptr_t (*__malloc_hook) __P ((size_t __size)); +extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, size_t __size)); + +/* Activate a standard collection of debugging hooks. */ +extern void mcheck __P ((void (*__func) __P ((void)))); + +/* Activate a standard collection of tracing hooks. */ +extern void mtrace __P ((void)); + +/* Statistics available to the user. */ +struct mstats + { + size_t bytes_total; /* Total size of the heap. */ + size_t chunks_used; /* Chunks allocated by the user. */ + size_t bytes_used; /* Byte total of user-allocated chunks. */ + size_t chunks_free; /* Chunks in the free list. */ + size_t bytes_free; /* Byte total of chunks in the free list. */ + }; + +/* Pick up the current statistics. */ +extern struct mstats mstats __P ((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* mtrace.h */
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c new file mode 100644 index 0000000..3bf481f --- /dev/null +++ b/e2fsck/pass1.c
@@ -0,0 +1,3119 @@ +/* + * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * Pass 1 of e2fsck iterates over all the inodes in the filesystems, + * and applies the following tests to each inode: + * + * - The mode field of the inode must be legal. + * - The size and block count fields of the inode are correct. + * - A data block must not be used by another inode + * + * Pass 1 also gathers the collects the following information: + * + * - A bitmap of which inodes are in use. (inode_used_map) + * - A bitmap of which inodes are directories. (inode_dir_map) + * - A bitmap of which inodes are regular files. (inode_reg_map) + * - A bitmap of which inodes have bad fields. (inode_bad_map) + * - A bitmap of which inodes are in bad blocks. (inode_bb_map) + * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) + * - A bitmap of which blocks are in use. (block_found_map) + * - A bitmap of which blocks are in use by two inodes (block_dup_map) + * - The data blocks of the directory inodes. (dir_map) + * + * Pass 1 is designed to stash away enough information so that the + * other passes should not need to read in the inode information + * during the normal course of a filesystem check. (Althogh if an + * inconsistency is detected, other passes may need to read in an + * inode to fix it.) + * + * Note that pass 1B will be invoked if there are any duplicate blocks + * found. + */ + +#define _GNU_SOURCE 1 /* get strnlen() */ +#include "config.h" +#include <string.h> +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#include "e2fsck.h" +#include <ext2fs/ext2_ext_attr.h> + +#include "problem.h" + +#ifdef NO_INLINE_FUNCS +#define _INLINE_ +#else +#define _INLINE_ inline +#endif + +static int process_block(ext2_filsys fs, blk64_t *blocknr, + e2_blkcnt_t blockcnt, blk64_t ref_blk, + int ref_offset, void *priv_data); +static int process_bad_block(ext2_filsys fs, blk64_t *block_nr, + e2_blkcnt_t blockcnt, blk64_t ref_blk, + int ref_offset, void *priv_data); +static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, + char *block_buf); +static void mark_table_blocks(e2fsck_t ctx); +static void alloc_bb_map(e2fsck_t ctx); +static void alloc_imagic_map(e2fsck_t ctx); +static void mark_inode_bad(e2fsck_t ctx, ino_t ino); +static void handle_fs_bad_blocks(e2fsck_t ctx); +static void process_inodes(e2fsck_t ctx, char *block_buf); +static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b); +static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan, + dgrp_t group, void * priv_data); +static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount, + char *block_buf, int adjust_sign); +/* static char *describe_illegal_block(ext2_filsys fs, blk64_t block); */ + +struct process_block_struct { + ext2_ino_t ino; + unsigned is_dir:1, is_reg:1, clear:1, suppress:1, + fragmented:1, compressed:1, bbcheck:1, + inode_modified:1; + blk64_t num_blocks; + blk64_t max_blocks; + e2_blkcnt_t last_block; + e2_blkcnt_t last_init_lblock; + e2_blkcnt_t last_db_block; + int num_illegal_blocks; + blk64_t previous_block; + struct ext2_inode *inode; + struct problem_context *pctx; + ext2fs_block_bitmap fs_meta_blocks; + e2fsck_t ctx; +}; + +struct process_inode_block { + ext2_ino_t ino; + struct ext2_inode inode; +}; + +struct scan_callback_struct { + e2fsck_t ctx; + char *block_buf; +}; + +/* + * For the inodes to process list. + */ +static struct process_inode_block *inodes_to_process; +static int process_inode_count; + +static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE - + EXT2_MIN_BLOCK_LOG_SIZE + 1]; + +/* + * Free all memory allocated by pass1 in preparation for restarting + * things. + */ +static void unwind_pass1(ext2_filsys fs EXT2FS_ATTR((unused))) +{ + ext2fs_free_mem(&inodes_to_process); + inodes_to_process = 0; +} + +/* + * Check to make sure a device inode is real. Returns 1 if the device + * checks out, 0 if not. + * + * Note: this routine is now also used to check FIFO's and Sockets, + * since they have the same requirement; the i_block fields should be + * zero. + */ +int e2fsck_pass1_check_device_inode(ext2_filsys fs EXT2FS_ATTR((unused)), + struct ext2_inode *inode) +{ + int i; + + /* + * If the index flag is set, then this is a bogus + * device/fifo/socket + */ + if (inode->i_flags & EXT2_INDEX_FL) + return 0; + + /* + * We should be able to do the test below all the time, but + * because the kernel doesn't forcibly clear the device + * inode's additional i_block fields, there are some rare + * occasions when a legitimate device inode will have non-zero + * additional i_block fields. So for now, we only complain + * when the immutable flag is set, which should never happen + * for devices. (And that's when the problem is caused, since + * you can't set or clear immutable flags for devices.) Once + * the kernel has been fixed we can change this... + */ + if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) { + for (i=4; i < EXT2_N_BLOCKS; i++) + if (inode->i_block[i]) + return 0; + } + return 1; +} + +/* + * Check to make sure a symlink inode is real. Returns 1 if the symlink + * checks out, 0 if not. + */ +int e2fsck_pass1_check_symlink(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode, char *buf) +{ + unsigned int len; + int i; + blk64_t blocks; + ext2_extent_handle_t handle; + struct ext2_extent_info info; + struct ext2fs_extent extent; + + if ((inode->i_size_high || inode->i_size == 0) || + (inode->i_flags & EXT2_INDEX_FL)) + return 0; + + if (inode->i_flags & EXT4_EXTENTS_FL) { + if (inode->i_size > fs->blocksize) + return 0; + if (ext2fs_extent_open2(fs, ino, inode, &handle)) + return 0; + i = 0; + if (ext2fs_extent_get_info(handle, &info) || + (info.num_entries != 1) || + (info.max_depth != 0)) + goto exit_extent; + if (ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent) || + (extent.e_lblk != 0) || + (extent.e_len != 1) || + (extent.e_pblk < fs->super->s_first_data_block) || + (extent.e_pblk >= ext2fs_blocks_count(fs->super))) + goto exit_extent; + i = 1; + exit_extent: + ext2fs_extent_free(handle); + return i; + } + + blocks = ext2fs_inode_data_blocks2(fs, inode); + if (blocks) { + if ((inode->i_size >= fs->blocksize) || + (blocks != fs->blocksize >> 9) || + (inode->i_block[0] < fs->super->s_first_data_block) || + (inode->i_block[0] >= ext2fs_blocks_count(fs->super))) + return 0; + + for (i = 1; i < EXT2_N_BLOCKS; i++) + if (inode->i_block[i]) + return 0; + + if (io_channel_read_blk64(fs->io, inode->i_block[0], 1, buf)) + return 0; + + len = strnlen(buf, fs->blocksize); + if (len == fs->blocksize) + return 0; + } else { + if (inode->i_size >= sizeof(inode->i_block)) + return 0; + + len = strnlen((char *)inode->i_block, sizeof(inode->i_block)); + if (len == sizeof(inode->i_block)) + return 0; + } + if (len != inode->i_size) + return 0; + return 1; +} + +/* + * If the immutable (or append-only) flag is set on the inode, offer + * to clear it. + */ +#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL) +static void check_immutable(e2fsck_t ctx, struct problem_context *pctx) +{ + if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS)) + return; + + if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx)) + return; + + pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS; + e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1"); +} + +/* + * If device, fifo or socket, check size is zero -- if not offer to + * clear it + */ +static void check_size(e2fsck_t ctx, struct problem_context *pctx) +{ + struct ext2_inode *inode = pctx->inode; + + if (EXT2_I_SIZE(inode) == 0) + return; + + if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx)) + return; + + ext2fs_inode_size_set(ctx->fs, inode, 0); + e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1"); +} + +static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx) +{ + struct ext2_super_block *sb = ctx->fs->super; + struct ext2_inode_large *inode; + struct ext2_ext_attr_entry *entry; + char *start; + unsigned int storage_size, remain; + problem_t problem = 0; + + inode = (struct ext2_inode_large *) pctx->inode; + storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE - + inode->i_extra_isize; + start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize + sizeof(__u32); + entry = (struct ext2_ext_attr_entry *) start; + + /* scan all entry's headers first */ + + /* take finish entry 0UL into account */ + remain = storage_size - sizeof(__u32); + + while (!EXT2_EXT_IS_LAST_ENTRY(entry)) { + __u32 hash; + + /* header eats this space */ + remain -= sizeof(struct ext2_ext_attr_entry); + + /* is attribute name valid? */ + if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) { + pctx->num = entry->e_name_len; + problem = PR_1_ATTR_NAME_LEN; + goto fix; + } + + /* attribute len eats this space */ + remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len); + + /* check value size */ + if (entry->e_value_size > remain) { + pctx->num = entry->e_value_size; + problem = PR_1_ATTR_VALUE_SIZE; + goto fix; + } + + /* e_value_block must be 0 in inode's ea */ + if (entry->e_value_block != 0) { + pctx->num = entry->e_value_block; + problem = PR_1_ATTR_VALUE_BLOCK; + goto fix; + } + + hash = ext2fs_ext_attr_hash_entry(entry, + start + entry->e_value_offs); + + /* e_hash may be 0 in older inode's ea */ + if (entry->e_hash != 0 && entry->e_hash != hash) { + pctx->num = entry->e_hash; + problem = PR_1_ATTR_HASH; + goto fix; + } + + remain -= entry->e_value_size; + + entry = EXT2_EXT_ATTR_NEXT(entry); + } +fix: + /* + * it seems like a corruption. it's very unlikely we could repair + * EA(s) in automatic fashion -bzzz + */ + if (problem == 0 || !fix_problem(ctx, problem, pctx)) + return; + + /* simply remove all possible EA(s) */ + *((__u32 *)start) = 0UL; + e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode, + EXT2_INODE_SIZE(sb), "pass1"); +} + +static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx) +{ + struct ext2_super_block *sb = ctx->fs->super; + struct ext2_inode_large *inode; + __u32 *eamagic; + int min, max; + + inode = (struct ext2_inode_large *) pctx->inode; + if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) { + /* this isn't large inode. so, nothing to check */ + return; + } + +#if 0 + printf("inode #%u, i_extra_size %d\n", pctx->ino, + inode->i_extra_isize); +#endif + /* i_extra_isize must cover i_extra_isize + i_checksum_hi at least */ + min = sizeof(inode->i_extra_isize) + sizeof(inode->i_checksum_hi); + max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE; + /* + * For now we will allow i_extra_isize to be 0, but really + * implementations should never allow i_extra_isize to be 0 + */ + if (inode->i_extra_isize && + (inode->i_extra_isize < min || inode->i_extra_isize > max)) { + if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx)) + return; + inode->i_extra_isize = min; + e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode, + EXT2_INODE_SIZE(sb), "pass1"); + return; + } + + eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + + inode->i_extra_isize); + if (*eamagic == EXT2_EXT_ATTR_MAGIC) { + /* it seems inode has an extended attribute(s) in body */ + check_ea_in_inode(ctx, pctx); + } +} + +/* + * Check to see if the inode might really be a directory, despite i_mode + * + * This is a lot of complexity for something for which I'm not really + * convinced happens frequently in the wild. If for any reason this + * causes any problems, take this code out. + * [tytso:20070331.0827EDT] + */ +static void check_is_really_dir(e2fsck_t ctx, struct problem_context *pctx, + char *buf) +{ + struct ext2_inode *inode = pctx->inode; + struct ext2_dir_entry *dirent; + errcode_t retval; + blk64_t blk; + unsigned int i, rec_len, not_device = 0; + int extent_fs; + + /* + * If the mode looks OK, we believe it. If the first block in + * the i_block array is 0, this cannot be a directory. If the + * inode is extent-mapped, it is still the case that the latter + * cannot be 0 - the magic number in the extent header would make + * it nonzero. + */ + if (LINUX_S_ISDIR(inode->i_mode) || LINUX_S_ISREG(inode->i_mode) || + LINUX_S_ISLNK(inode->i_mode) || inode->i_block[0] == 0) + return; + + /* + * Check the block numbers in the i_block array for validity: + * zero blocks are skipped (but the first one cannot be zero - + * see above), other blocks are checked against the first and + * max data blocks (from the the superblock) and against the + * block bitmap. Any invalid block found means this cannot be + * a directory. + * + * If there are non-zero blocks past the fourth entry, then + * this cannot be a device file: we remember that for the next + * check. + * + * For extent mapped files, we don't do any sanity checking: + * just try to get the phys block of logical block 0 and run + * with it. + */ + + extent_fs = (ctx->fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_EXTENTS); + if (extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) { + /* extent mapped */ + if (ext2fs_bmap2(ctx->fs, pctx->ino, inode, 0, 0, 0, 0, + &blk)) + return; + /* device files are never extent mapped */ + not_device++; + } else { + for (i=0; i < EXT2_N_BLOCKS; i++) { + blk = inode->i_block[i]; + if (!blk) + continue; + if (i >= 4) + not_device++; + + if (blk < ctx->fs->super->s_first_data_block || + blk >= ext2fs_blocks_count(ctx->fs->super) || + ext2fs_fast_test_block_bitmap2(ctx->block_found_map, + blk)) + return; /* Invalid block, can't be dir */ + } + blk = inode->i_block[0]; + } + + /* + * If the mode says this is a device file and the i_links_count field + * is sane and we have not ruled it out as a device file previously, + * we declare it a device file, not a directory. + */ + if ((LINUX_S_ISCHR(inode->i_mode) || LINUX_S_ISBLK(inode->i_mode)) && + (inode->i_links_count == 1) && !not_device) + return; + + /* read the first block */ + ehandler_operation(_("reading directory block")); + retval = ext2fs_read_dir_block3(ctx->fs, blk, buf, 0); + ehandler_operation(0); + if (retval) + return; + + dirent = (struct ext2_dir_entry *) buf; + retval = ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); + if (retval) + return; + if (((dirent->name_len & 0xFF) != 1) || + (dirent->name[0] != '.') || + (dirent->inode != pctx->ino) || + (rec_len < 12) || + (rec_len % 4) || + (rec_len >= ctx->fs->blocksize - 12)) + return; + + dirent = (struct ext2_dir_entry *) (buf + rec_len); + retval = ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); + if (retval) + return; + if (((dirent->name_len & 0xFF) != 2) || + (dirent->name[0] != '.') || + (dirent->name[1] != '.') || + (rec_len < 12) || + (rec_len % 4)) + return; + + if (fix_problem(ctx, PR_1_TREAT_AS_DIRECTORY, pctx)) { + inode->i_mode = (inode->i_mode & 07777) | LINUX_S_IFDIR; + e2fsck_write_inode_full(ctx, pctx->ino, inode, + EXT2_INODE_SIZE(ctx->fs->super), + "check_is_really_dir"); + } +} + +void e2fsck_setup_tdb_icount(e2fsck_t ctx, int flags, + ext2_icount_t *ret) +{ + unsigned int threshold; + ext2_ino_t num_dirs; + errcode_t retval; + char *tdb_dir; + int enable; + + *ret = 0; + + profile_get_string(ctx->profile, "scratch_files", "directory", 0, 0, + &tdb_dir); + profile_get_uint(ctx->profile, "scratch_files", + "numdirs_threshold", 0, 0, &threshold); + profile_get_boolean(ctx->profile, "scratch_files", + "icount", 0, 1, &enable); + + retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs); + if (retval) + num_dirs = 1024; /* Guess */ + + if (!enable || !tdb_dir || access(tdb_dir, W_OK) || + (threshold && num_dirs <= threshold)) + return; + + retval = ext2fs_create_icount_tdb(ctx->fs, tdb_dir, flags, ret); + if (retval) + *ret = 0; +} + +static void reserve_block_for_root_repair(e2fsck_t ctx) +{ + blk64_t blk = 0; + errcode_t err; + ext2_filsys fs = ctx->fs; + + ctx->root_repair_block = 0; + if (ext2fs_test_inode_bitmap2(ctx->inode_used_map, EXT2_ROOT_INO)) + return; + + err = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk); + if (err) + return; + ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); + ctx->root_repair_block = blk; +} + +static void reserve_block_for_lnf_repair(e2fsck_t ctx) +{ + blk64_t blk = 0; + errcode_t err; + ext2_filsys fs = ctx->fs; + static const char name[] = "lost+found"; + ext2_ino_t ino; + + ctx->lnf_repair_block = 0; + if (!ext2fs_lookup(fs, EXT2_ROOT_INO, name, sizeof(name)-1, 0, &ino)) + return; + + err = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk); + if (err) + return; + ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); + ctx->lnf_repair_block = blk; +} + +void e2fsck_pass1(e2fsck_t ctx) +{ + int i; + __u64 max_sizes; + ext2_filsys fs = ctx->fs; + ext2_ino_t ino = 0; + struct ext2_inode *inode = NULL; + ext2_inode_scan scan = NULL; + char *block_buf = NULL; +#ifdef RESOURCE_TRACK + struct resource_track rtrack; +#endif + unsigned char frag, fsize; + struct problem_context pctx; + struct scan_callback_struct scan_struct; + struct ext2_super_block *sb = ctx->fs->super; + const char *old_op; + unsigned int save_type; + int imagic_fs, extent_fs; + int low_dtime_check = 1; + int inode_size; + + init_resource_track(&rtrack, ctx->fs->io); + clear_problem_context(&pctx); + + if (!(ctx->options & E2F_OPT_PREEN)) + fix_problem(ctx, PR_1_PASS_HEADER, &pctx); + + if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) && + !(ctx->options & E2F_OPT_NO)) { + if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50)) + ctx->dirs_to_hash = 0; + } + +#ifdef MTRACE + mtrace_print("Pass 1"); +#endif + +#define EXT2_BPP(bits) (1ULL << ((bits) - 2)) + + for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) { + max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i); + max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i); + max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i); + max_sizes = (max_sizes * (1UL << i)); + ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes; + } +#undef EXT2_BPP + + imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES); + extent_fs = (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS); + + /* + * Allocate bitmaps structures + */ + pctx.errcode = e2fsck_allocate_inode_bitmap(fs, _("in-use inode map"), + EXT2FS_BMAP64_RBTREE, + "inode_used_map", + &ctx->inode_used_map); + if (pctx.errcode) { + pctx.num = 1; + fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + pctx.errcode = e2fsck_allocate_inode_bitmap(fs, + _("directory inode map"), + EXT2FS_BMAP64_AUTODIR, + "inode_dir_map", &ctx->inode_dir_map); + if (pctx.errcode) { + pctx.num = 2; + fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + pctx.errcode = e2fsck_allocate_inode_bitmap(fs, + _("regular file inode map"), EXT2FS_BMAP64_RBTREE, + "inode_reg_map", &ctx->inode_reg_map); + if (pctx.errcode) { + pctx.num = 6; + fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + pctx.errcode = e2fsck_allocate_subcluster_bitmap(fs, + _("in-use block map"), EXT2FS_BMAP64_RBTREE, + "block_found_map", &ctx->block_found_map); + if (pctx.errcode) { + pctx.num = 1; + fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + e2fsck_setup_tdb_icount(ctx, 0, &ctx->inode_link_info); + if (!ctx->inode_link_info) { + e2fsck_set_bitmap_type(fs, EXT2FS_BMAP64_RBTREE, + "inode_link_info", &save_type); + pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0, + &ctx->inode_link_info); + fs->default_bitmap_type = save_type; + } + + if (pctx.errcode) { + fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + inode_size = EXT2_INODE_SIZE(fs->super); + inode = (struct ext2_inode *) + e2fsck_allocate_memory(ctx, inode_size, "scratch inode"); + + inodes_to_process = (struct process_inode_block *) + e2fsck_allocate_memory(ctx, + (ctx->process_inode_size * + sizeof(struct process_inode_block)), + "array of inodes to process"); + process_inode_count = 0; + + pctx.errcode = ext2fs_init_dblist(fs, 0); + if (pctx.errcode) { + fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + goto endit; + } + + /* + * If the last orphan field is set, clear it, since the pass1 + * processing will automatically find and clear the orphans. + * In the future, we may want to try using the last_orphan + * linked list ourselves, but for now, we clear it so that the + * ext3 mount code won't get confused. + */ + if (!(ctx->options & E2F_OPT_READONLY)) { + if (fs->super->s_last_orphan) { + fs->super->s_last_orphan = 0; + ext2fs_mark_super_dirty(fs); + } + } + + mark_table_blocks(ctx); + pctx.errcode = ext2fs_convert_subcluster_bitmap(fs, + &ctx->block_found_map); + if (pctx.errcode) { + fix_problem(ctx, PR_1_CONVERT_SUBCLUSTER, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + goto endit; + } + block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3, + "block interate buffer"); + e2fsck_use_inode_shortcuts(ctx, 1); + e2fsck_intercept_block_allocations(ctx); + old_op = ehandler_operation(_("opening inode scan")); + pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks, + &scan); + ehandler_operation(old_op); + if (pctx.errcode) { + fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + goto endit; + } + ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0); + ctx->stashed_inode = inode; + scan_struct.ctx = ctx; + scan_struct.block_buf = block_buf; + ext2fs_set_inode_callback(scan, scan_callback, &scan_struct); + if (ctx->progress && ((ctx->progress)(ctx, 1, 0, + ctx->fs->group_desc_count))) + goto endit; + if ((fs->super->s_wtime < fs->super->s_inodes_count) || + (fs->super->s_mtime < fs->super->s_inodes_count) || + (fs->super->s_mkfs_time && + fs->super->s_mkfs_time < fs->super->s_inodes_count)) + low_dtime_check = 0; + + if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) && + fs->super->s_mmp_block > fs->super->s_first_data_block && + fs->super->s_mmp_block < ext2fs_blocks_count(fs->super)) + ext2fs_mark_block_bitmap2(ctx->block_found_map, + fs->super->s_mmp_block); + + while (1) { + if (ino % (fs->super->s_inodes_per_group * 4) == 1) { + if (e2fsck_mmp_update(fs)) + fatal_error(ctx, 0); + } + old_op = ehandler_operation(_("getting next inode from scan")); + pctx.errcode = ext2fs_get_next_inode_full(scan, &ino, + inode, inode_size); + ehandler_operation(old_op); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return; + if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) { + if (!ctx->inode_bb_map) + alloc_bb_map(ctx); + ext2fs_mark_inode_bitmap2(ctx->inode_bb_map, ino); + ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino); + continue; + } + if (pctx.errcode) { + fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + goto endit; + } + if (!ino) + break; + pctx.ino = ino; + pctx.inode = inode; + ctx->stashed_ino = ino; + if (inode->i_links_count) { + pctx.errcode = ext2fs_icount_store(ctx->inode_link_info, + ino, inode->i_links_count); + if (pctx.errcode) { + pctx.num = inode->i_links_count; + fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + goto endit; + } + } + + /* + * Test for incorrect extent flag settings. + * + * On big-endian machines we must be careful: + * When the inode is read, the i_block array is not swapped + * if the extent flag is set. Therefore if we are testing + * for or fixing a wrongly-set flag, we must potentially + * (un)swap before testing, or after fixing. + */ + + /* + * In this case the extents flag was set when read, so + * extent_header_verify is ok. If the inode is cleared, + * no need to swap... so no extra swapping here. + */ + if ((inode->i_flags & EXT4_EXTENTS_FL) && !extent_fs && + (inode->i_links_count || (ino == EXT2_BAD_INO) || + (ino == EXT2_ROOT_INO) || (ino == EXT2_JOURNAL_INO))) { + if ((ext2fs_extent_header_verify(inode->i_block, + sizeof(inode->i_block)) == 0) && + fix_problem(ctx, PR_1_EXTENT_FEATURE, &pctx)) { + sb->s_feature_incompat |= EXT3_FEATURE_INCOMPAT_EXTENTS; + ext2fs_mark_super_dirty(fs); + extent_fs = 1; + } else if (fix_problem(ctx, PR_1_EXTENTS_SET, &pctx)) { + clear_inode: + e2fsck_clear_inode(ctx, ino, inode, 0, "pass1"); + if (ino == EXT2_BAD_INO) + ext2fs_mark_inode_bitmap2(ctx->inode_used_map, + ino); + continue; + } + } + + /* + * For big-endian machines: + * If the inode didn't have the extents flag set when it + * was read, then the i_blocks array was swapped. To test + * as an extents header, we must swap it back first. + * IF we then set the extents flag, the entire i_block + * array must be un/re-swapped to make it proper extents data. + */ + if (extent_fs && !(inode->i_flags & EXT4_EXTENTS_FL) && + (inode->i_links_count || (ino == EXT2_BAD_INO) || + (ino == EXT2_ROOT_INO) || (ino == EXT2_JOURNAL_INO)) && + (LINUX_S_ISREG(inode->i_mode) || + LINUX_S_ISDIR(inode->i_mode))) { + void *ehp; +#ifdef WORDS_BIGENDIAN + __u32 tmp_block[EXT2_N_BLOCKS]; + + for (i = 0; i < EXT2_N_BLOCKS; i++) + tmp_block[i] = ext2fs_swab32(inode->i_block[i]); + ehp = tmp_block; +#else + ehp = inode->i_block; +#endif + if ((ext2fs_extent_header_verify(ehp, + sizeof(inode->i_block)) == 0) && + (fix_problem(ctx, PR_1_UNSET_EXTENT_FL, &pctx))) { + inode->i_flags |= EXT4_EXTENTS_FL; +#ifdef WORDS_BIGENDIAN + memcpy(inode->i_block, tmp_block, + sizeof(inode->i_block)); +#endif + e2fsck_write_inode(ctx, ino, inode, "pass1"); + } + } + + if (ino == EXT2_BAD_INO) { + struct process_block_struct pb; + + if ((inode->i_mode || inode->i_uid || inode->i_gid || + inode->i_links_count || inode->i_file_acl) && + fix_problem(ctx, PR_1_INVALID_BAD_INODE, &pctx)) { + memset(inode, 0, sizeof(struct ext2_inode)); + e2fsck_write_inode(ctx, ino, inode, + "clear bad inode"); + } + + pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map, + &pb.fs_meta_blocks); + if (pctx.errcode) { + pctx.num = 4; + fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + goto endit; + } + pb.ino = EXT2_BAD_INO; + pb.num_blocks = pb.last_block = 0; + pb.last_db_block = -1; + pb.num_illegal_blocks = 0; + pb.suppress = 0; pb.clear = 0; pb.is_dir = 0; + pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0; + pb.inode = inode; + pb.pctx = &pctx; + pb.ctx = ctx; + pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, + block_buf, process_bad_block, &pb); + ext2fs_free_block_bitmap(pb.fs_meta_blocks); + if (pctx.errcode) { + fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + goto endit; + } + if (pb.bbcheck) + if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) { + ctx->flags |= E2F_FLAG_ABORT; + goto endit; + } + ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino); + clear_problem_context(&pctx); + continue; + } else if (ino == EXT2_ROOT_INO) { + /* + * Make sure the root inode is a directory; if + * not, offer to clear it. It will be + * regnerated in pass #3. + */ + if (!LINUX_S_ISDIR(inode->i_mode)) { + if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) + goto clear_inode; + } + /* + * If dtime is set, offer to clear it. mke2fs + * version 0.2b created filesystems with the + * dtime field set for the root and lost+found + * directories. We won't worry about + * /lost+found, since that can be regenerated + * easily. But we will fix the root directory + * as a special case. + */ + if (inode->i_dtime && inode->i_links_count) { + if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) { + inode->i_dtime = 0; + e2fsck_write_inode(ctx, ino, inode, + "pass1"); + } + } + } else if (ino == EXT2_JOURNAL_INO) { + ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino); + if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) { + if (!LINUX_S_ISREG(inode->i_mode) && + fix_problem(ctx, PR_1_JOURNAL_BAD_MODE, + &pctx)) { + inode->i_mode = LINUX_S_IFREG; + e2fsck_write_inode(ctx, ino, inode, + "pass1"); + } + check_blocks(ctx, &pctx, block_buf); + continue; + } + if ((inode->i_links_count || + inode->i_blocks || inode->i_block[0]) && + fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR, + &pctx)) { + memset(inode, 0, inode_size); + ext2fs_icount_store(ctx->inode_link_info, + ino, 0); + e2fsck_write_inode_full(ctx, ino, inode, + inode_size, "pass1"); + } + } else if ((ino == EXT4_USR_QUOTA_INO) || + (ino == EXT4_GRP_QUOTA_INO)) { + ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino); + if ((fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_QUOTA) && + ((fs->super->s_usr_quota_inum == ino) || + (fs->super->s_grp_quota_inum == ino))) { + if (!LINUX_S_ISREG(inode->i_mode) && + fix_problem(ctx, PR_1_QUOTA_BAD_MODE, + &pctx)) { + inode->i_mode = LINUX_S_IFREG; + e2fsck_write_inode(ctx, ino, inode, + "pass1"); + } + check_blocks(ctx, &pctx, block_buf); + continue; + } + if ((inode->i_links_count || + inode->i_blocks || inode->i_block[0]) && + fix_problem(ctx, PR_1_QUOTA_INODE_NOT_CLEAR, + &pctx)) { + memset(inode, 0, inode_size); + ext2fs_icount_store(ctx->inode_link_info, + ino, 0); + e2fsck_write_inode_full(ctx, ino, inode, + inode_size, "pass1"); + } + } else if (ino < EXT2_FIRST_INODE(fs->super)) { + problem_t problem = 0; + + ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino); + if (ino == EXT2_BOOT_LOADER_INO) { + if (LINUX_S_ISDIR(inode->i_mode)) + problem = PR_1_RESERVED_BAD_MODE; + } else if (ino == EXT2_RESIZE_INO) { + if (inode->i_mode && + !LINUX_S_ISREG(inode->i_mode)) + problem = PR_1_RESERVED_BAD_MODE; + } else { + if (inode->i_mode != 0) + problem = PR_1_RESERVED_BAD_MODE; + } + if (problem) { + if (fix_problem(ctx, problem, &pctx)) { + inode->i_mode = 0; + e2fsck_write_inode(ctx, ino, inode, + "pass1"); + } + } + check_blocks(ctx, &pctx, block_buf); + continue; + } + + /* + * Check for inodes who might have been part of the + * orphaned list linked list. They should have gotten + * dealt with by now, unless the list had somehow been + * corrupted. + * + * FIXME: In the future, inodes which are still in use + * (and which are therefore) pending truncation should + * be handled specially. Right now we just clear the + * dtime field, and the normal e2fsck handling of + * inodes where i_size and the inode blocks are + * inconsistent is to fix i_size, instead of releasing + * the extra blocks. This won't catch the inodes that + * was at the end of the orphan list, but it's better + * than nothing. The right answer is that there + * shouldn't be any bugs in the orphan list handling. :-) + */ + if (inode->i_dtime && low_dtime_check && + inode->i_dtime < ctx->fs->super->s_inodes_count) { + if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) { + inode->i_dtime = inode->i_links_count ? + 0 : ctx->now; + e2fsck_write_inode(ctx, ino, inode, + "pass1"); + } + } + + /* + * This code assumes that deleted inodes have + * i_links_count set to 0. + */ + if (!inode->i_links_count) { + if (!inode->i_dtime && inode->i_mode) { + if (fix_problem(ctx, + PR_1_ZERO_DTIME, &pctx)) { + inode->i_dtime = ctx->now; + e2fsck_write_inode(ctx, ino, inode, + "pass1"); + } + } + continue; + } + /* + * n.b. 0.3c ext2fs code didn't clear i_links_count for + * deleted files. Oops. + * + * Since all new ext2 implementations get this right, + * we now assume that the case of non-zero + * i_links_count and non-zero dtime means that we + * should keep the file, not delete it. + * + */ + if (inode->i_dtime) { + if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) { + inode->i_dtime = 0; + e2fsck_write_inode(ctx, ino, inode, "pass1"); + } + } + + ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino); + switch (fs->super->s_creator_os) { + case EXT2_OS_HURD: + frag = inode->osd2.hurd2.h_i_frag; + fsize = inode->osd2.hurd2.h_i_fsize; + break; + default: + frag = fsize = 0; + } + + if (inode->i_faddr || frag || fsize || + (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl)) + mark_inode_bad(ctx, ino); + if ((fs->super->s_creator_os == EXT2_OS_LINUX) && + !(fs->super->s_feature_incompat & + EXT4_FEATURE_INCOMPAT_64BIT) && + inode->osd2.linux2.l_i_file_acl_high != 0) + mark_inode_bad(ctx, ino); + if ((fs->super->s_creator_os == EXT2_OS_LINUX) && + !(fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && + (inode->osd2.linux2.l_i_blocks_hi != 0)) + mark_inode_bad(ctx, ino); + if (inode->i_flags & EXT2_IMAGIC_FL) { + if (imagic_fs) { + if (!ctx->inode_imagic_map) + alloc_imagic_map(ctx); + ext2fs_mark_inode_bitmap2(ctx->inode_imagic_map, + ino); + } else { + if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) { + inode->i_flags &= ~EXT2_IMAGIC_FL; + e2fsck_write_inode(ctx, ino, + inode, "pass1"); + } + } + } + + check_inode_extra_space(ctx, &pctx); + check_is_really_dir(ctx, &pctx, block_buf); + + /* + * ext2fs_inode_has_valid_blocks2 does not actually look + * at i_block[] values, so not endian-sensitive here. + */ + if (extent_fs && (inode->i_flags & EXT4_EXTENTS_FL) && + LINUX_S_ISLNK(inode->i_mode) && + !ext2fs_inode_has_valid_blocks2(fs, inode) && + fix_problem(ctx, PR_1_FAST_SYMLINK_EXTENT_FL, &pctx)) { + inode->i_flags &= ~EXT4_EXTENTS_FL; + e2fsck_write_inode(ctx, ino, inode, "pass1"); + } + + if (LINUX_S_ISDIR(inode->i_mode)) { + ext2fs_mark_inode_bitmap2(ctx->inode_dir_map, ino); + e2fsck_add_dir_info(ctx, ino, 0); + ctx->fs_directory_count++; + } else if (LINUX_S_ISREG (inode->i_mode)) { + ext2fs_mark_inode_bitmap2(ctx->inode_reg_map, ino); + ctx->fs_regular_count++; + } else if (LINUX_S_ISCHR (inode->i_mode) && + e2fsck_pass1_check_device_inode(fs, inode)) { + check_immutable(ctx, &pctx); + check_size(ctx, &pctx); + ctx->fs_chardev_count++; + } else if (LINUX_S_ISBLK (inode->i_mode) && + e2fsck_pass1_check_device_inode(fs, inode)) { + check_immutable(ctx, &pctx); + check_size(ctx, &pctx); + ctx->fs_blockdev_count++; + } else if (LINUX_S_ISLNK (inode->i_mode) && + e2fsck_pass1_check_symlink(fs, ino, inode, + block_buf)) { + check_immutable(ctx, &pctx); + ctx->fs_symlinks_count++; + if (ext2fs_inode_data_blocks(fs, inode) == 0) { + ctx->fs_fast_symlinks_count++; + check_blocks(ctx, &pctx, block_buf); + continue; + } + } + else if (LINUX_S_ISFIFO (inode->i_mode) && + e2fsck_pass1_check_device_inode(fs, inode)) { + check_immutable(ctx, &pctx); + check_size(ctx, &pctx); + ctx->fs_fifo_count++; + } else if ((LINUX_S_ISSOCK (inode->i_mode)) && + e2fsck_pass1_check_device_inode(fs, inode)) { + check_immutable(ctx, &pctx); + check_size(ctx, &pctx); + ctx->fs_sockets_count++; + } else + mark_inode_bad(ctx, ino); + if (!(inode->i_flags & EXT4_EXTENTS_FL)) { + if (inode->i_block[EXT2_IND_BLOCK]) + ctx->fs_ind_count++; + if (inode->i_block[EXT2_DIND_BLOCK]) + ctx->fs_dind_count++; + if (inode->i_block[EXT2_TIND_BLOCK]) + ctx->fs_tind_count++; + } + if (!(inode->i_flags & EXT4_EXTENTS_FL) && + (inode->i_block[EXT2_IND_BLOCK] || + inode->i_block[EXT2_DIND_BLOCK] || + inode->i_block[EXT2_TIND_BLOCK] || + ext2fs_file_acl_block(fs, inode))) { + inodes_to_process[process_inode_count].ino = ino; + inodes_to_process[process_inode_count].inode = *inode; + process_inode_count++; + } else + check_blocks(ctx, &pctx, block_buf); + + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + goto endit; + + if (process_inode_count >= ctx->process_inode_size) { + process_inodes(ctx, block_buf); + + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + goto endit; + } + } + process_inodes(ctx, block_buf); + ext2fs_close_inode_scan(scan); + scan = NULL; + + reserve_block_for_root_repair(ctx); + reserve_block_for_lnf_repair(ctx); + + /* + * If any extended attribute blocks' reference counts need to + * be adjusted, either up (ctx->refcount_extra), or down + * (ctx->refcount), then fix them. + */ + if (ctx->refcount) { + adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1); + ea_refcount_free(ctx->refcount); + ctx->refcount = 0; + } + if (ctx->refcount_extra) { + adjust_extattr_refcount(ctx, ctx->refcount_extra, + block_buf, +1); + ea_refcount_free(ctx->refcount_extra); + ctx->refcount_extra = 0; + } + + if (ctx->invalid_bitmaps) + handle_fs_bad_blocks(ctx); + + /* We don't need the block_ea_map any more */ + if (ctx->block_ea_map) { + ext2fs_free_block_bitmap(ctx->block_ea_map); + ctx->block_ea_map = 0; + } + + if (ctx->flags & E2F_FLAG_RESIZE_INODE) { + clear_problem_context(&pctx); + pctx.errcode = ext2fs_create_resize_inode(fs); + if (pctx.errcode) { + if (!fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, + &pctx)) { + ctx->flags |= E2F_FLAG_ABORT; + goto endit; + } + pctx.errcode = 0; + } + if (!pctx.errcode) { + e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode, + "recreate inode"); + inode->i_mtime = ctx->now; + e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode, + "recreate inode"); + } + ctx->flags &= ~E2F_FLAG_RESIZE_INODE; + } + + if (ctx->flags & E2F_FLAG_RESTART) { + /* + * Only the master copy of the superblock and block + * group descriptors are going to be written during a + * restart, so set the superblock to be used to be the + * master superblock. + */ + ctx->use_superblock = 0; + unwind_pass1(fs); + goto endit; + } + + if (ctx->block_dup_map) { + if (ctx->options & E2F_OPT_PREEN) { + clear_problem_context(&pctx); + fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx); + } + e2fsck_pass1_dupblocks(ctx, block_buf); + } + ext2fs_free_mem(&inodes_to_process); +endit: + e2fsck_use_inode_shortcuts(ctx, 0); + + if (scan) + ext2fs_close_inode_scan(scan); + if (block_buf) + ext2fs_free_mem(&block_buf); + if (inode) + ext2fs_free_mem(&inode); + + if ((ctx->flags & E2F_FLAG_SIGNAL_MASK) == 0) + print_resource_track(ctx, _("Pass 1"), &rtrack, ctx->fs->io); +} + +/* + * When the inode_scan routines call this callback at the end of the + * glock group, call process_inodes. + */ +static errcode_t scan_callback(ext2_filsys fs, + ext2_inode_scan scan EXT2FS_ATTR((unused)), + dgrp_t group, void * priv_data) +{ + struct scan_callback_struct *scan_struct; + e2fsck_t ctx; + + scan_struct = (struct scan_callback_struct *) priv_data; + ctx = scan_struct->ctx; + + process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf); + + if (ctx->progress) + if ((ctx->progress)(ctx, 1, group+1, + ctx->fs->group_desc_count)) + return EXT2_ET_CANCEL_REQUESTED; + + return 0; +} + +/* + * Process the inodes in the "inodes to process" list. + */ +static void process_inodes(e2fsck_t ctx, char *block_buf) +{ + int i; + struct ext2_inode *old_stashed_inode; + ext2_ino_t old_stashed_ino; + const char *old_operation; + char buf[80]; + struct problem_context pctx; + +#if 0 + printf("begin process_inodes: "); +#endif + if (process_inode_count == 0) + return; + old_operation = ehandler_operation(0); + old_stashed_inode = ctx->stashed_inode; + old_stashed_ino = ctx->stashed_ino; + qsort(inodes_to_process, process_inode_count, + sizeof(struct process_inode_block), process_inode_cmp); + clear_problem_context(&pctx); + for (i=0; i < process_inode_count; i++) { + pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode; + pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino; + +#if 0 + printf("%u ", pctx.ino); +#endif + sprintf(buf, _("reading indirect blocks of inode %u"), + pctx.ino); + ehandler_operation(buf); + check_blocks(ctx, &pctx, block_buf); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + break; + } + ctx->stashed_inode = old_stashed_inode; + ctx->stashed_ino = old_stashed_ino; + process_inode_count = 0; +#if 0 + printf("end process inodes\n"); +#endif + ehandler_operation(old_operation); +} + +static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b) +{ + const struct process_inode_block *ib_a = + (const struct process_inode_block *) a; + const struct process_inode_block *ib_b = + (const struct process_inode_block *) b; + int ret; + + ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] - + ib_b->inode.i_block[EXT2_IND_BLOCK]); + if (ret == 0) + /* + * We only call process_inodes() for non-extent + * inodes, so it's OK to pass NULL to + * ext2fs_file_acl_block() here. + */ + ret = ext2fs_file_acl_block(0, &(ib_a->inode)) - + ext2fs_file_acl_block(0, &(ib_b->inode)); + if (ret == 0) + ret = ib_a->ino - ib_b->ino; + return ret; +} + +/* + * Mark an inode as being bad in some what + */ +static void mark_inode_bad(e2fsck_t ctx, ino_t ino) +{ + struct problem_context pctx; + + if (!ctx->inode_bad_map) { + clear_problem_context(&pctx); + + pctx.errcode = e2fsck_allocate_inode_bitmap(ctx->fs, + _("bad inode map"), EXT2FS_BMAP64_RBTREE, + "inode_bad_map", &ctx->inode_bad_map); + if (pctx.errcode) { + pctx.num = 3; + fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); + /* Should never get here */ + ctx->flags |= E2F_FLAG_ABORT; + return; + } + } + ext2fs_mark_inode_bitmap2(ctx->inode_bad_map, ino); +} + + +/* + * This procedure will allocate the inode "bb" (badblock) map table + */ +static void alloc_bb_map(e2fsck_t ctx) +{ + struct problem_context pctx; + + clear_problem_context(&pctx); + pctx.errcode = e2fsck_allocate_inode_bitmap(ctx->fs, + _("inode in bad block map"), EXT2FS_BMAP64_RBTREE, + "inode_bb_map", &ctx->inode_bb_map); + if (pctx.errcode) { + pctx.num = 4; + fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); + /* Should never get here */ + ctx->flags |= E2F_FLAG_ABORT; + return; + } +} + +/* + * This procedure will allocate the inode imagic table + */ +static void alloc_imagic_map(e2fsck_t ctx) +{ + struct problem_context pctx; + + clear_problem_context(&pctx); + pctx.errcode = e2fsck_allocate_inode_bitmap(ctx->fs, + _("imagic inode map"), EXT2FS_BMAP64_RBTREE, + "inode_imagic_map", &ctx->inode_imagic_map); + if (pctx.errcode) { + pctx.num = 5; + fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); + /* Should never get here */ + ctx->flags |= E2F_FLAG_ABORT; + return; + } +} + +/* + * Marks a block as in use, setting the dup_map if it's been set + * already. Called by process_block and process_bad_block. + * + * WARNING: Assumes checks have already been done to make sure block + * is valid. This is true in both process_block and process_bad_block. + */ +static _INLINE_ void mark_block_used(e2fsck_t ctx, blk64_t block) +{ + struct problem_context pctx; + + clear_problem_context(&pctx); + + if (ext2fs_fast_test_block_bitmap2(ctx->block_found_map, block)) { + if (!ctx->block_dup_map) { + pctx.errcode = e2fsck_allocate_block_bitmap(ctx->fs, + _("multiply claimed block map"), + EXT2FS_BMAP64_RBTREE, "block_dup_map", + &ctx->block_dup_map); + if (pctx.errcode) { + pctx.num = 3; + fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, + &pctx); + /* Should never get here */ + ctx->flags |= E2F_FLAG_ABORT; + return; + } + } + ext2fs_fast_mark_block_bitmap2(ctx->block_dup_map, block); + } else { + ext2fs_fast_mark_block_bitmap2(ctx->block_found_map, block); + } +} + +static _INLINE_ void mark_blocks_used(e2fsck_t ctx, blk64_t block, + unsigned int num) +{ + if (ext2fs_test_block_bitmap_range2(ctx->block_found_map, block, num)) + ext2fs_mark_block_bitmap_range2(ctx->block_found_map, block, num); + else + while (num--) + mark_block_used(ctx, block++); +} + +/* + * Adjust the extended attribute block's reference counts at the end + * of pass 1, either by subtracting out references for EA blocks that + * are still referenced in ctx->refcount, or by adding references for + * EA blocks that had extra references as accounted for in + * ctx->refcount_extra. + */ +static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount, + char *block_buf, int adjust_sign) +{ + struct ext2_ext_attr_header *header; + struct problem_context pctx; + ext2_filsys fs = ctx->fs; + blk64_t blk; + __u32 should_be; + int count; + + clear_problem_context(&pctx); + + ea_refcount_intr_begin(refcount); + while (1) { + if ((blk = ea_refcount_intr_next(refcount, &count)) == 0) + break; + pctx.blk = blk; + pctx.errcode = ext2fs_read_ext_attr2(fs, blk, block_buf); + if (pctx.errcode) { + fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx); + return; + } + header = (struct ext2_ext_attr_header *) block_buf; + pctx.blkcount = header->h_refcount; + should_be = header->h_refcount + adjust_sign * count; + pctx.num = should_be; + if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) { + header->h_refcount = should_be; + pctx.errcode = ext2fs_write_ext_attr2(fs, blk, + block_buf); + if (pctx.errcode) { + fix_problem(ctx, PR_1_EXTATTR_WRITE_ABORT, + &pctx); + continue; + } + } + } +} + +/* + * Handle processing the extended attribute blocks + */ +static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx, + char *block_buf) +{ + ext2_filsys fs = ctx->fs; + ext2_ino_t ino = pctx->ino; + struct ext2_inode *inode = pctx->inode; + blk64_t blk; + char * end; + struct ext2_ext_attr_header *header; + struct ext2_ext_attr_entry *entry; + int count; + region_t region = 0; + + blk = ext2fs_file_acl_block(fs, inode); + if (blk == 0) + return 0; + + /* + * If the Extended attribute flag isn't set, then a non-zero + * file acl means that the inode is corrupted. + * + * Or if the extended attribute block is an invalid block, + * then the inode is also corrupted. + */ + if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) || + (blk < fs->super->s_first_data_block) || + (blk >= ext2fs_blocks_count(fs->super))) { + mark_inode_bad(ctx, ino); + return 0; + } + + /* If ea bitmap hasn't been allocated, create it */ + if (!ctx->block_ea_map) { + pctx->errcode = e2fsck_allocate_block_bitmap(fs, + _("ext attr block map"), + EXT2FS_BMAP64_RBTREE, "block_ea_map", + &ctx->block_ea_map); + if (pctx->errcode) { + pctx->num = 2; + fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx); + ctx->flags |= E2F_FLAG_ABORT; + return 0; + } + } + + /* Create the EA refcount structure if necessary */ + if (!ctx->refcount) { + pctx->errcode = ea_refcount_create(0, &ctx->refcount); + if (pctx->errcode) { + pctx->num = 1; + fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx); + ctx->flags |= E2F_FLAG_ABORT; + return 0; + } + } + +#if 0 + /* Debugging text */ + printf("Inode %u has EA block %u\n", ino, blk); +#endif + + /* Have we seen this EA block before? */ + if (ext2fs_fast_test_block_bitmap2(ctx->block_ea_map, blk)) { + if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0) + return 1; + /* Ooops, this EA was referenced more than it stated */ + if (!ctx->refcount_extra) { + pctx->errcode = ea_refcount_create(0, + &ctx->refcount_extra); + if (pctx->errcode) { + pctx->num = 2; + fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx); + ctx->flags |= E2F_FLAG_ABORT; + return 0; + } + } + ea_refcount_increment(ctx->refcount_extra, blk, 0); + return 1; + } + + /* + * OK, we haven't seen this EA block yet. So we need to + * validate it + */ + pctx->blk = blk; + pctx->errcode = ext2fs_read_ext_attr2(fs, blk, block_buf); + if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx)) + goto clear_extattr; + header = (struct ext2_ext_attr_header *) block_buf; + pctx->blk = ext2fs_file_acl_block(fs, inode); + if (((ctx->ext_attr_ver == 1) && + (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) || + ((ctx->ext_attr_ver == 2) && + (header->h_magic != EXT2_EXT_ATTR_MAGIC))) { + if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx)) + goto clear_extattr; + } + + if (header->h_blocks != 1) { + if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx)) + goto clear_extattr; + } + + region = region_create(0, fs->blocksize); + if (!region) { + fix_problem(ctx, PR_1_EA_ALLOC_REGION_ABORT, pctx); + ctx->flags |= E2F_FLAG_ABORT; + return 0; + } + if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) { + if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) + goto clear_extattr; + } + + entry = (struct ext2_ext_attr_entry *)(header+1); + end = block_buf + fs->blocksize; + while ((char *)entry < end && *(__u32 *)entry) { + __u32 hash; + + if (region_allocate(region, (char *)entry - (char *)header, + EXT2_EXT_ATTR_LEN(entry->e_name_len))) { + if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) + goto clear_extattr; + break; + } + if ((ctx->ext_attr_ver == 1 && + (entry->e_name_len == 0 || entry->e_name_index != 0)) || + (ctx->ext_attr_ver == 2 && + entry->e_name_index == 0)) { + if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx)) + goto clear_extattr; + break; + } + if (entry->e_value_block != 0) { + if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx)) + goto clear_extattr; + } + if (entry->e_value_offs + entry->e_value_size > fs->blocksize) { + if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx)) + goto clear_extattr; + break; + } + if (entry->e_value_size && + region_allocate(region, entry->e_value_offs, + EXT2_EXT_ATTR_SIZE(entry->e_value_size))) { + if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) + goto clear_extattr; + } + + hash = ext2fs_ext_attr_hash_entry(entry, block_buf + + entry->e_value_offs); + + if (entry->e_hash != hash) { + pctx->num = entry->e_hash; + if (fix_problem(ctx, PR_1_ATTR_HASH, pctx)) + goto clear_extattr; + entry->e_hash = hash; + } + + entry = EXT2_EXT_ATTR_NEXT(entry); + } + if (region_allocate(region, (char *)entry - (char *)header, 4)) { + if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) + goto clear_extattr; + } + region_free(region); + + count = header->h_refcount - 1; + if (count) + ea_refcount_store(ctx->refcount, blk, count); + mark_block_used(ctx, blk); + ext2fs_fast_mark_block_bitmap2(ctx->block_ea_map, blk); + return 1; + +clear_extattr: + if (region) + region_free(region); + ext2fs_file_acl_block_set(fs, inode, 0); + e2fsck_write_inode(ctx, ino, inode, "check_ext_attr"); + return 0; +} + +/* Returns 1 if bad htree, 0 if OK */ +static int handle_htree(e2fsck_t ctx, struct problem_context *pctx, + ext2_ino_t ino, struct ext2_inode *inode, + char *block_buf) +{ + struct ext2_dx_root_info *root; + ext2_filsys fs = ctx->fs; + errcode_t retval; + blk64_t blk; + + if ((!LINUX_S_ISDIR(inode->i_mode) && + fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) || + (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) && + fix_problem(ctx, PR_1_HTREE_SET, pctx))) + return 1; + + pctx->errcode = ext2fs_bmap2(fs, ino, inode, 0, 0, 0, 0, &blk); + + if ((pctx->errcode) || + (blk == 0) || + (blk < fs->super->s_first_data_block) || + (blk >= ext2fs_blocks_count(fs->super))) { + if (fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) + return 1; + else + return 0; + } + + retval = io_channel_read_blk64(fs->io, blk, 1, block_buf); + if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) + return 1; + + /* XXX should check that beginning matches a directory */ + root = (struct ext2_dx_root_info *) (block_buf + 24); + + if ((root->reserved_zero || root->info_length < 8) && + fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) + return 1; + + pctx->num = root->hash_version; + if ((root->hash_version != EXT2_HASH_LEGACY) && + (root->hash_version != EXT2_HASH_HALF_MD4) && + (root->hash_version != EXT2_HASH_TEA) && + fix_problem(ctx, PR_1_HTREE_HASHV, pctx)) + return 1; + + if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) && + fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx)) + return 1; + + pctx->num = root->indirect_levels; + if ((root->indirect_levels > 1) && + fix_problem(ctx, PR_1_HTREE_DEPTH, pctx)) + return 1; + + return 0; +} + +void e2fsck_clear_inode(e2fsck_t ctx, ext2_ino_t ino, + struct ext2_inode *inode, int restart_flag, + const char *source) +{ + inode->i_flags = 0; + inode->i_links_count = 0; + ext2fs_icount_store(ctx->inode_link_info, ino, 0); + inode->i_dtime = ctx->now; + + ext2fs_unmark_inode_bitmap2(ctx->inode_dir_map, ino); + ext2fs_unmark_inode_bitmap2(ctx->inode_used_map, ino); + if (ctx->inode_reg_map) + ext2fs_unmark_inode_bitmap2(ctx->inode_reg_map, ino); + if (ctx->inode_bad_map) + ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); + + /* + * If the inode was partially accounted for before processing + * was aborted, we need to restart the pass 1 scan. + */ + ctx->flags |= restart_flag; + + if (ino == EXT2_BAD_INO) + memset(inode, 0, sizeof(struct ext2_inode)); + + e2fsck_write_inode(ctx, ino, inode, source); +} + +/* + * Use the multiple-blocks reclamation code to fix alignment problems in + * a bigalloc filesystem. We want a logical cluster to map to *only* one + * physical cluster, and we want the block offsets within that cluster to + * line up. + */ +static int has_unaligned_cluster_map(e2fsck_t ctx, + blk64_t last_pblk, e2_blkcnt_t last_lblk, + blk64_t pblk, blk64_t lblk) +{ + blk64_t cluster_mask; + + if (!ctx->fs->cluster_ratio_bits) + return 0; + cluster_mask = EXT2FS_CLUSTER_MASK(ctx->fs); + + /* + * If the block in the logical cluster doesn't align with the block in + * the physical cluster... + */ + if ((lblk & cluster_mask) != (pblk & cluster_mask)) + return 1; + + /* + * If we cross a physical cluster boundary within a logical cluster... + */ + if (last_pblk && (lblk & cluster_mask) != 0 && + EXT2FS_B2C(ctx->fs, lblk) == EXT2FS_B2C(ctx->fs, last_lblk) && + EXT2FS_B2C(ctx->fs, pblk) != EXT2FS_B2C(ctx->fs, last_pblk)) + return 1; + + return 0; +} + +static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx, + struct process_block_struct *pb, + blk64_t start_block, blk64_t end_block, + blk64_t eof_block, + ext2_extent_handle_t ehandle) +{ + struct ext2fs_extent extent; + blk64_t blk, last_lblk; + e2_blkcnt_t blockcnt; + unsigned int i; + int is_dir, is_leaf; + problem_t problem; + struct ext2_extent_info info; + + pctx->errcode = ext2fs_extent_get_info(ehandle, &info); + if (pctx->errcode) + return; + + pctx->errcode = ext2fs_extent_get(ehandle, EXT2_EXTENT_FIRST_SIB, + &extent); + while (!pctx->errcode && info.num_entries-- > 0) { + is_leaf = extent.e_flags & EXT2_EXTENT_FLAGS_LEAF; + is_dir = LINUX_S_ISDIR(pctx->inode->i_mode); + last_lblk = extent.e_lblk + extent.e_len - 1; + + problem = 0; + if (extent.e_pblk == 0 || + extent.e_pblk < ctx->fs->super->s_first_data_block || + extent.e_pblk >= ext2fs_blocks_count(ctx->fs->super)) + problem = PR_1_EXTENT_BAD_START_BLK; + else if (extent.e_lblk < start_block) + problem = PR_1_OUT_OF_ORDER_EXTENTS; + else if ((end_block && last_lblk > end_block) && + (!(extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT && + last_lblk > eof_block))) + problem = PR_1_EXTENT_END_OUT_OF_BOUNDS; + else if (is_leaf && extent.e_len == 0) + problem = PR_1_EXTENT_LENGTH_ZERO; + else if (is_leaf && + (extent.e_pblk + extent.e_len) > + ext2fs_blocks_count(ctx->fs->super)) + problem = PR_1_EXTENT_ENDS_BEYOND; + else if (is_leaf && is_dir && + ((extent.e_lblk + extent.e_len) > + (1 << (21 - ctx->fs->super->s_log_block_size)))) + problem = PR_1_TOOBIG_DIR; + + /* + * Uninitialized blocks in a directory? Clear the flag and + * we'll interpret the blocks later. + */ + if (is_dir && problem == 0 && + (extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT) && + fix_problem(ctx, PR_1_UNINIT_DBLOCK, pctx)) { + extent.e_flags &= ~EXT2_EXTENT_FLAGS_UNINIT; + pb->inode_modified = 1; + pctx->errcode = ext2fs_extent_replace(ehandle, 0, + &extent); + if (pctx->errcode) + return; + } + + if (problem) { +report_problem: + pctx->blk = extent.e_pblk; + pctx->blk2 = extent.e_lblk; + pctx->num = extent.e_len; + pctx->blkcount = extent.e_lblk + extent.e_len; + if (fix_problem(ctx, problem, pctx)) { + if (ctx->invalid_bitmaps) { + /* + * If fsck knows the bitmaps are bad, + * skip to the next extent and + * try to clear this extent again + * after fixing the bitmaps, by + * restarting fsck. + */ + pctx->errcode = ext2fs_extent_get( + ehandle, + EXT2_EXTENT_NEXT_SIB, + &extent); + ctx->flags |= E2F_FLAG_RESTART_LATER; + if (pctx->errcode == + EXT2_ET_NO_CURRENT_NODE) { + pctx->errcode = 0; + break; + } + continue; + } + e2fsck_read_bitmaps(ctx); + pb->inode_modified = 1; + pctx->errcode = + ext2fs_extent_delete(ehandle, 0); + if (pctx->errcode) { + pctx->str = "ext2fs_extent_delete"; + return; + } + pctx->errcode = ext2fs_extent_fix_parents(ehandle); + if (pctx->errcode && + pctx->errcode != EXT2_ET_NO_CURRENT_NODE) { + pctx->str = "ext2fs_extent_fix_parents"; + return; + } + pctx->errcode = ext2fs_extent_get(ehandle, + EXT2_EXTENT_CURRENT, + &extent); + if (pctx->errcode == EXT2_ET_NO_CURRENT_NODE) { + pctx->errcode = 0; + break; + } + continue; + } + goto next; + } + + if (!is_leaf) { + blk64_t lblk = extent.e_lblk; + + blk = extent.e_pblk; + pctx->errcode = ext2fs_extent_get(ehandle, + EXT2_EXTENT_DOWN, &extent); + if (pctx->errcode) { + pctx->str = "EXT2_EXTENT_DOWN"; + problem = PR_1_EXTENT_HEADER_INVALID; + if (pctx->errcode == EXT2_ET_EXTENT_HEADER_BAD) + goto report_problem; + return; + } + /* The next extent should match this index's logical start */ + if (extent.e_lblk != lblk) { + struct ext2_extent_info e_info; + + ext2fs_extent_get_info(ehandle, &e_info); + pctx->blk = lblk; + pctx->blk2 = extent.e_lblk; + pctx->num = e_info.curr_level - 1; + problem = PR_1_EXTENT_INDEX_START_INVALID; + if (fix_problem(ctx, problem, pctx)) { + pb->inode_modified = 1; + pctx->errcode = + ext2fs_extent_fix_parents(ehandle); + if (pctx->errcode) { + pctx->str = "ext2fs_extent_fix_parents"; + return; + } + } + } + scan_extent_node(ctx, pctx, pb, extent.e_lblk, + last_lblk, eof_block, ehandle); + if (pctx->errcode) + return; + pctx->errcode = ext2fs_extent_get(ehandle, + EXT2_EXTENT_UP, &extent); + if (pctx->errcode) { + pctx->str = "EXT2_EXTENT_UP"; + return; + } + mark_block_used(ctx, blk); + pb->num_blocks++; + goto next; + } + + if ((pb->previous_block != 0) && + (pb->previous_block+1 != extent.e_pblk)) { + if (ctx->options & E2F_OPT_FRAGCHECK) { + char type = '?'; + + if (pb->is_dir) + type = 'd'; + else if (pb->is_reg) + type = 'f'; + + printf(("%6lu(%c): expecting %6lu " + "actual extent " + "phys %6lu log %lu len %lu\n"), + (unsigned long) pctx->ino, type, + (unsigned long) pb->previous_block+1, + (unsigned long) extent.e_pblk, + (unsigned long) extent.e_lblk, + (unsigned long) extent.e_len); + } + pb->fragmented = 1; + } + /* + * If we notice a gap in the logical block mappings of an + * extent-mapped directory, offer to close the hole by + * moving the logical block down, otherwise we'll go mad in + * pass 3 allocating empty directory blocks to fill the hole. + */ + if (is_dir && + pb->last_block + 1 < (e2_blkcnt_t)extent.e_lblk) { + blk64_t new_lblk; + + new_lblk = pb->last_block + 1; + if (EXT2FS_CLUSTER_RATIO(ctx->fs) > 1) + new_lblk = ((new_lblk + + EXT2FS_CLUSTER_RATIO(ctx->fs)) & + EXT2FS_CLUSTER_MASK(ctx->fs)) | + (extent.e_lblk & + EXT2FS_CLUSTER_MASK(ctx->fs)); + pctx->blk = extent.e_lblk; + pctx->blk2 = new_lblk; + if (fix_problem(ctx, PR_1_COLLAPSE_DBLOCK, pctx)) { + extent.e_lblk = new_lblk; + pb->inode_modified = 1; + pctx->errcode = ext2fs_extent_replace(ehandle, + 0, &extent); + if (pctx->errcode) { + pctx->errcode = 0; + goto alloc_later; + } + pctx->errcode = ext2fs_extent_fix_parents(ehandle); + if (pctx->errcode) + goto failed_add_dir_block; + pctx->errcode = ext2fs_extent_goto(ehandle, + extent.e_lblk); + if (pctx->errcode) + goto failed_add_dir_block; + last_lblk = extent.e_lblk + extent.e_len - 1; + } + } +alloc_later: + while (is_dir && (++pb->last_db_block < + (e2_blkcnt_t) extent.e_lblk)) { + pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist, + pb->ino, 0, + pb->last_db_block); + if (pctx->errcode) { + pctx->blk = 0; + pctx->num = pb->last_db_block; + goto failed_add_dir_block; + } + } + if (!ctx->fs->cluster_ratio_bits) { + mark_blocks_used(ctx, extent.e_pblk, extent.e_len); + pb->num_blocks += extent.e_len; + } + for (blk = extent.e_pblk, blockcnt = extent.e_lblk, i = 0; + i < extent.e_len; + blk++, blockcnt++, i++) { + if (ctx->fs->cluster_ratio_bits && + !(pb->previous_block && + (EXT2FS_B2C(ctx->fs, blk) == + EXT2FS_B2C(ctx->fs, pb->previous_block)) && + (blk & EXT2FS_CLUSTER_MASK(ctx->fs)) == + ((unsigned) blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) { + mark_block_used(ctx, blk); + pb->num_blocks++; + } + if (has_unaligned_cluster_map(ctx, pb->previous_block, + pb->last_block, blk, + blockcnt)) { + pctx->blk = blockcnt; + pctx->blk2 = blk; + fix_problem(ctx, PR_1_MISALIGNED_CLUSTER, pctx); + mark_block_used(ctx, blk); + mark_block_used(ctx, blk); + } + pb->last_block = blockcnt; + pb->previous_block = blk; + + if (is_dir) { + pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist, pctx->ino, blk, blockcnt); + if (pctx->errcode) { + pctx->blk = blk; + pctx->num = blockcnt; + failed_add_dir_block: + fix_problem(ctx, PR_1_ADD_DBLOCK, pctx); + /* Should never get here */ + ctx->flags |= E2F_FLAG_ABORT; + return; + } + } + } + if (is_dir && extent.e_len > 0) + pb->last_db_block = blockcnt - 1; + pb->previous_block = extent.e_pblk + extent.e_len - 1; + start_block = pb->last_block = last_lblk; + if (is_leaf && !is_dir && + !(extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT)) + pb->last_init_lblock = last_lblk; + next: + pctx->errcode = ext2fs_extent_get(ehandle, + EXT2_EXTENT_NEXT_SIB, + &extent); + } + if (pctx->errcode == EXT2_ET_EXTENT_NO_NEXT) + pctx->errcode = 0; +} + +static void check_blocks_extents(e2fsck_t ctx, struct problem_context *pctx, + struct process_block_struct *pb) +{ + struct ext2_extent_info info; + struct ext2_inode *inode = pctx->inode; + ext2_extent_handle_t ehandle; + ext2_filsys fs = ctx->fs; + ext2_ino_t ino = pctx->ino; + errcode_t retval; + blk64_t eof_lblk; + + pctx->errcode = ext2fs_extent_open2(fs, ino, inode, &ehandle); + if (pctx->errcode) { + if (fix_problem(ctx, PR_1_READ_EXTENT, pctx)) + e2fsck_clear_inode(ctx, ino, inode, 0, + "check_blocks_extents"); + pctx->errcode = 0; + return; + } + + retval = ext2fs_extent_get_info(ehandle, &info); + if (retval == 0) { + if (info.max_depth >= MAX_EXTENT_DEPTH_COUNT) + info.max_depth = MAX_EXTENT_DEPTH_COUNT-1; + ctx->extent_depth_count[info.max_depth]++; + } + + eof_lblk = ((EXT2_I_SIZE(inode) + fs->blocksize - 1) >> + EXT2_BLOCK_SIZE_BITS(fs->super)) - 1; + scan_extent_node(ctx, pctx, pb, 0, 0, eof_lblk, ehandle); + if (pctx->errcode && + fix_problem(ctx, PR_1_EXTENT_ITERATE_FAILURE, pctx)) { + pb->num_blocks = 0; + inode->i_blocks = 0; + e2fsck_clear_inode(ctx, ino, inode, E2F_FLAG_RESTART, + "check_blocks_extents"); + pctx->errcode = 0; + } + ext2fs_extent_free(ehandle); +} + +/* + * This subroutine is called on each inode to account for all of the + * blocks used by that inode. + */ +static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, + char *block_buf) +{ + ext2_filsys fs = ctx->fs; + struct process_block_struct pb; + ext2_ino_t ino = pctx->ino; + struct ext2_inode *inode = pctx->inode; + unsigned bad_size = 0; + int dirty_inode = 0; + int extent_fs; + __u64 size; + + pb.ino = ino; + pb.num_blocks = 0; + pb.last_block = -1; + pb.last_init_lblock = -1; + pb.last_db_block = -1; + pb.num_illegal_blocks = 0; + pb.suppress = 0; pb.clear = 0; + pb.fragmented = 0; + pb.compressed = 0; + pb.previous_block = 0; + pb.is_dir = LINUX_S_ISDIR(inode->i_mode); + pb.is_reg = LINUX_S_ISREG(inode->i_mode); + pb.max_blocks = 1 << (31 - fs->super->s_log_block_size); + pb.inode = inode; + pb.pctx = pctx; + pb.ctx = ctx; + pb.inode_modified = 0; + pctx->ino = ino; + pctx->errcode = 0; + + extent_fs = (ctx->fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_EXTENTS); + + if (inode->i_flags & EXT2_COMPRBLK_FL) { + if (fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_COMPRESSION) + pb.compressed = 1; + else { + if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) { + inode->i_flags &= ~EXT2_COMPRBLK_FL; + dirty_inode++; + } + } + } + + if (ext2fs_file_acl_block(fs, inode) && + check_ext_attr(ctx, pctx, block_buf)) { + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + goto out; + pb.num_blocks++; + } + + if (ext2fs_inode_has_valid_blocks2(fs, inode)) { + if (extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) + check_blocks_extents(ctx, pctx, &pb); + else { + /* + * If we've modified the inode, write it out before + * iterate() tries to use it. + */ + if (dirty_inode) { + e2fsck_write_inode(ctx, ino, inode, + "check_blocks"); + dirty_inode = 0; + } + pctx->errcode = ext2fs_block_iterate3(fs, ino, + pb.is_dir ? BLOCK_FLAG_HOLE : 0, + block_buf, process_block, &pb); + /* + * We do not have uninitialized extents in non extent + * files. + */ + pb.last_init_lblock = pb.last_block; + /* + * If iterate() changed a block mapping, we have to + * re-read the inode. If we decide to clear the + * inode after clearing some stuff, we'll re-write the + * bad mappings into the inode! + */ + if (pb.inode_modified) + e2fsck_read_inode(ctx, ino, inode, + "check_blocks"); + } + } + end_problem_latch(ctx, PR_LATCH_BLOCK); + end_problem_latch(ctx, PR_LATCH_TOOBIG); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + goto out; + if (pctx->errcode) + fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx); + + if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group) { + if (LINUX_S_ISDIR(inode->i_mode)) + ctx->fs_fragmented_dir++; + else + ctx->fs_fragmented++; + } + + if (pb.clear) { + e2fsck_clear_inode(ctx, ino, inode, E2F_FLAG_RESTART, + "check_blocks"); + return; + } + + if (inode->i_flags & EXT2_INDEX_FL) { + if (handle_htree(ctx, pctx, ino, inode, block_buf)) { + inode->i_flags &= ~EXT2_INDEX_FL; + dirty_inode++; + } else { +#ifdef ENABLE_HTREE + e2fsck_add_dx_dir(ctx, ino, pb.last_block+1); +#endif + } + } + + if (!pb.num_blocks && pb.is_dir) { + if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) { + e2fsck_clear_inode(ctx, ino, inode, 0, "check_blocks"); + ctx->fs_directory_count--; + return; + } + } + + if (ino == EXT2_ROOT_INO || ino >= EXT2_FIRST_INODE(ctx->fs->super)) { + quota_data_add(ctx->qctx, inode, ino, + pb.num_blocks * fs->blocksize); + quota_data_inodes(ctx->qctx, inode, ino, +1); + } + + if (!(fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_HUGE_FILE) || + !(inode->i_flags & EXT4_HUGE_FILE_FL)) + pb.num_blocks *= (fs->blocksize / 512); + pb.num_blocks *= EXT2FS_CLUSTER_RATIO(fs); +#if 0 + printf("inode %u, i_size = %u, last_block = %lld, i_blocks=%llu, num_blocks = %llu\n", + ino, inode->i_size, pb.last_block, ext2fs_inode_i_blocks(fs, inode), + pb.num_blocks); +#endif + if (pb.is_dir) { + int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super); + if (inode->i_size & (fs->blocksize - 1)) + bad_size = 5; + else if (nblock > (pb.last_block + 1)) + bad_size = 1; + else if (nblock < (pb.last_block + 1)) { + if (((pb.last_block + 1) - nblock) > + fs->super->s_prealloc_dir_blocks) + bad_size = 2; + } + } else { + e2_blkcnt_t blkpg = ctx->blocks_per_page; + + size = EXT2_I_SIZE(inode); + if ((pb.last_init_lblock >= 0) && + /* allow allocated blocks to end of PAGE_SIZE */ + (size < (__u64)pb.last_init_lblock * fs->blocksize) && + (pb.last_init_lblock / blkpg * blkpg != pb.last_init_lblock || + size < (__u64)(pb.last_init_lblock & ~(blkpg-1)) * + fs->blocksize)) + bad_size = 3; + else if (!(extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) && + size > ext2_max_sizes[fs->super->s_log_block_size]) + /* too big for a direct/indirect-mapped file */ + bad_size = 4; + else if ((extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) && + size > + ((1ULL << (32 + EXT2_BLOCK_SIZE_BITS(fs->super))) - 1)) + /* too big for an extent-based file - 32bit ee_block */ + bad_size = 6; + } + /* i_size for symlinks is checked elsewhere */ + if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) { + pctx->num = (pb.last_block+1) * fs->blocksize; + pctx->group = bad_size; + if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) { + if (LINUX_S_ISDIR(inode->i_mode)) + pctx->num &= 0xFFFFFFFFULL; + ext2fs_inode_size_set(fs, inode, pctx->num); + dirty_inode++; + } + pctx->num = 0; + } + if (LINUX_S_ISREG(inode->i_mode) && + ext2fs_needs_large_file_feature(EXT2_I_SIZE(inode))) + ctx->large_files++; + if ((fs->super->s_creator_os == EXT2_OS_LINUX) && + ((pb.num_blocks != ext2fs_inode_i_blocks(fs, inode)) || + ((fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && + (inode->i_flags & EXT4_HUGE_FILE_FL) && + (inode->osd2.linux2.l_i_blocks_hi != 0)))) { + pctx->num = pb.num_blocks; + if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) { + inode->i_blocks = pb.num_blocks; + inode->osd2.linux2.l_i_blocks_hi = pb.num_blocks >> 32; + dirty_inode++; + } + pctx->num = 0; + } + + if (ctx->dirs_to_hash && pb.is_dir && + !(inode->i_flags & EXT2_INDEX_FL) && + ((inode->i_size / fs->blocksize) >= 3)) + ext2fs_u32_list_add(ctx->dirs_to_hash, ino); + +out: + if (dirty_inode) + e2fsck_write_inode(ctx, ino, inode, "check_blocks"); +} + +#if 0 +/* + * Helper function called by process block when an illegal block is + * found. It returns a description about why the block is illegal + */ +static char *describe_illegal_block(ext2_filsys fs, blk64_t block) +{ + blk64_t super; + int i; + static char problem[80]; + + super = fs->super->s_first_data_block; + strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block"); + if (block < super) { + sprintf(problem, "< FIRSTBLOCK (%u)", super); + return(problem); + } else if (block >= ext2fs_blocks_count(fs->super)) { + sprintf(problem, "> BLOCKS (%u)", ext2fs_blocks_count(fs->super)); + return(problem); + } + for (i = 0; i < fs->group_desc_count; i++) { + if (block == super) { + sprintf(problem, "is the superblock in group %d", i); + break; + } + if (block > super && + block <= (super + fs->desc_blocks)) { + sprintf(problem, "is in the group descriptors " + "of group %d", i); + break; + } + if (block == ext2fs_block_bitmap_loc(fs, i)) { + sprintf(problem, "is the block bitmap of group %d", i); + break; + } + if (block == ext2fs_inode_bitmap_loc(fs, i)) { + sprintf(problem, "is the inode bitmap of group %d", i); + break; + } + if (block >= ext2fs_inode_table_loc(fs, i) && + (block < ext2fs_inode_table_loc(fs, i) + + fs->inode_blocks_per_group)) { + sprintf(problem, "is in the inode table of group %d", + i); + break; + } + super += fs->super->s_blocks_per_group; + } + return(problem); +} +#endif + +/* + * This is a helper function for check_blocks(). + */ +static int process_block(ext2_filsys fs, + blk64_t *block_nr, + e2_blkcnt_t blockcnt, + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct process_block_struct *p; + struct problem_context *pctx; + blk64_t blk = *block_nr; + int ret_code = 0; + problem_t problem = 0; + e2fsck_t ctx; + + p = (struct process_block_struct *) priv_data; + pctx = p->pctx; + ctx = p->ctx; + + if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) { + /* todo: Check that the comprblk_fl is high, that the + blkaddr pattern looks right (all non-holes up to + first EXT2FS_COMPRESSED_BLKADDR, then all + EXT2FS_COMPRESSED_BLKADDR up to end of cluster), + that the feature_incompat bit is high, and that the + inode is a regular file. If we're doing a "full + check" (a concept introduced to e2fsck by e2compr, + meaning that we look at data blocks as well as + metadata) then call some library routine that + checks the compressed data. I'll have to think + about this, because one particularly important + problem to be able to fix is to recalculate the + cluster size if necessary. I think that perhaps + we'd better do most/all e2compr-specific checks + separately, after the non-e2compr checks. If not + doing a full check, it may be useful to test that + the personality is linux; e.g. if it isn't then + perhaps this really is just an illegal block. */ + return 0; + } + + /* + * For a directory, add logical block zero for processing even if it's + * not mapped or we'll be perennially stuck with broken "." and ".." + * entries. + */ + if (p->is_dir && blockcnt == 0 && blk == 0) { + pctx->errcode = ext2fs_add_dir_block2(fs->dblist, p->ino, 0, 0); + if (pctx->errcode) { + pctx->blk = blk; + pctx->num = blockcnt; + goto failed_add_dir_block; + } + p->last_db_block++; + } + + if (blk == 0) + return 0; + +#if 0 + printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk, + blockcnt); +#endif + + /* + * Simplistic fragmentation check. We merely require that the + * file be contiguous. (Which can never be true for really + * big files that are greater than a block group.) + */ + if (!HOLE_BLKADDR(p->previous_block) && p->ino != EXT2_RESIZE_INO) { + if (p->previous_block+1 != blk) { + if (ctx->options & E2F_OPT_FRAGCHECK) { + char type = '?'; + + if (p->is_dir) + type = 'd'; + else if (p->is_reg) + type = 'f'; + + printf(_("%6lu(%c): expecting %6lu " + "got phys %6lu (blkcnt %lld)\n"), + (unsigned long) pctx->ino, type, + (unsigned long) p->previous_block+1, + (unsigned long) blk, + blockcnt); + } + p->fragmented = 1; + } + } + + if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size))) + problem = PR_1_TOOBIG_DIR; + if (p->is_reg && p->num_blocks+1 >= p->max_blocks) + problem = PR_1_TOOBIG_REG; + if (!p->is_dir && !p->is_reg && blockcnt > 0) + problem = PR_1_TOOBIG_SYMLINK; + + if (blk < fs->super->s_first_data_block || + blk >= ext2fs_blocks_count(fs->super)) + problem = PR_1_ILLEGAL_BLOCK_NUM; + + if (problem) { + p->num_illegal_blocks++; + if (!p->suppress && (p->num_illegal_blocks % 12) == 0) { + if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) { + p->clear = 1; + return BLOCK_ABORT; + } + if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) { + p->suppress = 1; + set_latch_flags(PR_LATCH_BLOCK, + PRL_SUPPRESS, 0); + } + } + pctx->blk = blk; + pctx->blkcount = blockcnt; + if (fix_problem(ctx, problem, pctx)) { + blk = *block_nr = 0; + ret_code = BLOCK_CHANGED; + p->inode_modified = 1; + /* + * If the directory block is too big and is beyond the + * end of the FS, don't bother trying to add it for + * processing -- the kernel would never have created a + * directory this large, and we risk an ENOMEM abort. + * In any case, the toobig handler for extent-based + * directories also doesn't feed toobig blocks to + * pass 2. + */ + if (problem == PR_1_TOOBIG_DIR) + return ret_code; + goto mark_dir; + } else + return 0; + } + + if (p->ino == EXT2_RESIZE_INO) { + /* + * The resize inode has already be sanity checked + * during pass #0 (the superblock checks). All we + * have to do is mark the double indirect block as + * being in use; all of the other blocks are handled + * by mark_table_blocks()). + */ + if (blockcnt == BLOCK_COUNT_DIND) + mark_block_used(ctx, blk); + p->num_blocks++; + } else if (!(ctx->fs->cluster_ratio_bits && + p->previous_block && + (EXT2FS_B2C(ctx->fs, blk) == + EXT2FS_B2C(ctx->fs, p->previous_block)) && + (blk & EXT2FS_CLUSTER_MASK(ctx->fs)) == + ((unsigned) blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) { + mark_block_used(ctx, blk); + p->num_blocks++; + } else if (has_unaligned_cluster_map(ctx, p->previous_block, + p->last_block, blk, blockcnt)) { + pctx->blk = blockcnt; + pctx->blk2 = blk; + fix_problem(ctx, PR_1_MISALIGNED_CLUSTER, pctx); + mark_block_used(ctx, blk); + mark_block_used(ctx, blk); + } + if (blockcnt >= 0) + p->last_block = blockcnt; + p->previous_block = blk; +mark_dir: + if (p->is_dir && (blockcnt >= 0)) { + while (++p->last_db_block < blockcnt) { + pctx->errcode = ext2fs_add_dir_block2(fs->dblist, + p->ino, 0, + p->last_db_block); + if (pctx->errcode) { + pctx->blk = 0; + pctx->num = p->last_db_block; + goto failed_add_dir_block; + } + } + pctx->errcode = ext2fs_add_dir_block2(fs->dblist, p->ino, + blk, blockcnt); + if (pctx->errcode) { + pctx->blk = blk; + pctx->num = blockcnt; + failed_add_dir_block: + fix_problem(ctx, PR_1_ADD_DBLOCK, pctx); + /* Should never get here */ + ctx->flags |= E2F_FLAG_ABORT; + return BLOCK_ABORT; + } + } + return ret_code; +} + +static int process_bad_block(ext2_filsys fs, + blk64_t *block_nr, + e2_blkcnt_t blockcnt, + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct process_block_struct *p; + blk64_t blk = *block_nr; + blk64_t first_block; + dgrp_t i; + struct problem_context *pctx; + e2fsck_t ctx; + + /* + * Note: This function processes blocks for the bad blocks + * inode, which is never compressed. So we don't use HOLE_BLKADDR(). + */ + + if (!blk) + return 0; + + p = (struct process_block_struct *) priv_data; + ctx = p->ctx; + pctx = p->pctx; + + pctx->ino = EXT2_BAD_INO; + pctx->blk = blk; + pctx->blkcount = blockcnt; + + if ((blk < fs->super->s_first_data_block) || + (blk >= ext2fs_blocks_count(fs->super))) { + if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) { + *block_nr = 0; + return BLOCK_CHANGED; + } else + return 0; + } + + if (blockcnt < 0) { + if (ext2fs_test_block_bitmap2(p->fs_meta_blocks, blk)) { + p->bbcheck = 1; + if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) { + *block_nr = 0; + return BLOCK_CHANGED; + } + } else if (ext2fs_test_block_bitmap2(ctx->block_found_map, + blk)) { + p->bbcheck = 1; + if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, + pctx)) { + *block_nr = 0; + return BLOCK_CHANGED; + } + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return BLOCK_ABORT; + } else + mark_block_used(ctx, blk); + return 0; + } +#if 0 + printf ("DEBUG: Marking %u as bad.\n", blk); +#endif + ctx->fs_badblocks_count++; + /* + * If the block is not used, then mark it as used and return. + * If it is already marked as found, this must mean that + * there's an overlap between the filesystem table blocks + * (bitmaps and inode table) and the bad block list. + */ + if (!ext2fs_test_block_bitmap2(ctx->block_found_map, blk)) { + ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); + return 0; + } + /* + * Try to find the where the filesystem block was used... + */ + first_block = fs->super->s_first_data_block; + + for (i = 0; i < fs->group_desc_count; i++ ) { + pctx->group = i; + pctx->blk = blk; + if (!ext2fs_bg_has_super(fs, i)) + goto skip_super; + if (blk == first_block) { + if (i == 0) { + if (fix_problem(ctx, + PR_1_BAD_PRIMARY_SUPERBLOCK, + pctx)) { + *block_nr = 0; + return BLOCK_CHANGED; + } + return 0; + } + fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx); + return 0; + } + if ((blk > first_block) && + (blk <= first_block + fs->desc_blocks)) { + if (i == 0) { + pctx->blk = *block_nr; + if (fix_problem(ctx, + PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) { + *block_nr = 0; + return BLOCK_CHANGED; + } + return 0; + } + fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx); + return 0; + } + skip_super: + if (blk == ext2fs_block_bitmap_loc(fs, i)) { + if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) { + ctx->invalid_block_bitmap_flag[i]++; + ctx->invalid_bitmaps++; + } + return 0; + } + if (blk == ext2fs_inode_bitmap_loc(fs, i)) { + if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) { + ctx->invalid_inode_bitmap_flag[i]++; + ctx->invalid_bitmaps++; + } + return 0; + } + if ((blk >= ext2fs_inode_table_loc(fs, i)) && + (blk < (ext2fs_inode_table_loc(fs, i) + + fs->inode_blocks_per_group))) { + /* + * If there are bad blocks in the inode table, + * the inode scan code will try to do + * something reasonable automatically. + */ + return 0; + } + first_block += fs->super->s_blocks_per_group; + } + /* + * If we've gotten to this point, then the only + * possibility is that the bad block inode meta data + * is using a bad block. + */ + if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) || + (blk == p->inode->i_block[EXT2_DIND_BLOCK]) || + (blk == p->inode->i_block[EXT2_TIND_BLOCK])) { + p->bbcheck = 1; + if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) { + *block_nr = 0; + return BLOCK_CHANGED; + } + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return BLOCK_ABORT; + return 0; + } + + pctx->group = -1; + + /* Warn user that the block wasn't claimed */ + fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx); + + return 0; +} + +static void new_table_block(e2fsck_t ctx, blk64_t first_block, dgrp_t group, + const char *name, int num, blk64_t *new_block) +{ + ext2_filsys fs = ctx->fs; + dgrp_t last_grp; + blk64_t old_block = *new_block; + blk64_t last_block; + dgrp_t flexbg; + unsigned flexbg_size; + int i, is_flexbg; + char *buf; + struct problem_context pctx; + + clear_problem_context(&pctx); + + pctx.group = group; + pctx.blk = old_block; + pctx.str = name; + + /* + * For flex_bg filesystems, first try to allocate the metadata + * within the flex_bg, and if that fails then try finding the + * space anywhere in the filesystem. + */ + is_flexbg = EXT2_HAS_INCOMPAT_FEATURE(fs->super, + EXT4_FEATURE_INCOMPAT_FLEX_BG); + if (is_flexbg) { + flexbg_size = 1 << fs->super->s_log_groups_per_flex; + flexbg = group / flexbg_size; + first_block = ext2fs_group_first_block2(fs, + flexbg_size * flexbg); + last_grp = group | (flexbg_size - 1); + if (last_grp >= fs->group_desc_count) + last_grp = fs->group_desc_count - 1; + last_block = ext2fs_group_last_block2(fs, last_grp); + } else + last_block = ext2fs_group_last_block2(fs, group); + pctx.errcode = ext2fs_get_free_blocks2(fs, first_block, last_block, + num, ctx->block_found_map, + new_block); + if (is_flexbg && (pctx.errcode == EXT2_ET_BLOCK_ALLOC_FAIL)) + pctx.errcode = ext2fs_get_free_blocks2(fs, + fs->super->s_first_data_block, + ext2fs_blocks_count(fs->super), + num, ctx->block_found_map, new_block); + if (pctx.errcode) { + pctx.num = num; + fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx); + ext2fs_unmark_valid(fs); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf); + if (pctx.errcode) { + fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx); + ext2fs_unmark_valid(fs); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + ext2fs_mark_super_dirty(fs); + fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; + pctx.blk2 = *new_block; + fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO : + PR_1_RELOC_TO), &pctx); + pctx.blk2 = 0; + for (i = 0; i < num; i++) { + pctx.blk = i; + ext2fs_mark_block_bitmap2(ctx->block_found_map, (*new_block)+i); + if (old_block) { + pctx.errcode = io_channel_read_blk64(fs->io, + old_block + i, 1, buf); + if (pctx.errcode) + fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx); + } else + memset(buf, 0, fs->blocksize); + + pctx.blk = (*new_block) + i; + pctx.errcode = io_channel_write_blk64(fs->io, pctx.blk, + 1, buf); + if (pctx.errcode) + fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx); + } + ext2fs_free_mem(&buf); +} + +/* + * This routine gets called at the end of pass 1 if bad blocks are + * detected in the superblock, group descriptors, inode_bitmaps, or + * block bitmaps. At this point, all of the blocks have been mapped + * out, so we can try to allocate new block(s) to replace the bad + * blocks. + */ +static void handle_fs_bad_blocks(e2fsck_t ctx) +{ + ext2_filsys fs = ctx->fs; + dgrp_t i; + blk64_t first_block; + blk64_t new_blk; + + for (i = 0; i < fs->group_desc_count; i++) { + first_block = ext2fs_group_first_block2(fs, i); + + if (ctx->invalid_block_bitmap_flag[i]) { + new_blk = ext2fs_block_bitmap_loc(fs, i); + new_table_block(ctx, first_block, i, _("block bitmap"), + 1, &new_blk); + ext2fs_block_bitmap_loc_set(fs, i, new_blk); + } + if (ctx->invalid_inode_bitmap_flag[i]) { + new_blk = ext2fs_inode_bitmap_loc(fs, i); + new_table_block(ctx, first_block, i, _("inode bitmap"), + 1, &new_blk); + ext2fs_inode_bitmap_loc_set(fs, i, new_blk); + } + if (ctx->invalid_inode_table_flag[i]) { + new_blk = ext2fs_inode_table_loc(fs, i); + new_table_block(ctx, first_block, i, _("inode table"), + fs->inode_blocks_per_group, + &new_blk); + ext2fs_inode_table_loc_set(fs, i, new_blk); + ctx->flags |= E2F_FLAG_RESTART; + } + } + ctx->invalid_bitmaps = 0; +} + +/* + * This routine marks all blocks which are used by the superblock, + * group descriptors, inode bitmaps, and block bitmaps. + */ +static void mark_table_blocks(e2fsck_t ctx) +{ + ext2_filsys fs = ctx->fs; + blk64_t b; + dgrp_t i; + unsigned int j; + struct problem_context pctx; + + clear_problem_context(&pctx); + + for (i = 0; i < fs->group_desc_count; i++) { + pctx.group = i; + + ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map); + + /* + * Mark the blocks used for the inode table + */ + if (ext2fs_inode_table_loc(fs, i)) { + for (j = 0, b = ext2fs_inode_table_loc(fs, i); + j < fs->inode_blocks_per_group; + j++, b++) { + if (ext2fs_test_block_bitmap2(ctx->block_found_map, + b)) { + pctx.blk = b; + if (!ctx->invalid_inode_table_flag[i] && + fix_problem(ctx, + PR_1_ITABLE_CONFLICT, &pctx)) { + ctx->invalid_inode_table_flag[i]++; + ctx->invalid_bitmaps++; + } + } else { + ext2fs_mark_block_bitmap2(ctx->block_found_map, + b); + } + } + } + + /* + * Mark block used for the block bitmap + */ + if (ext2fs_block_bitmap_loc(fs, i)) { + if (ext2fs_test_block_bitmap2(ctx->block_found_map, + ext2fs_block_bitmap_loc(fs, i))) { + pctx.blk = ext2fs_block_bitmap_loc(fs, i); + if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) { + ctx->invalid_block_bitmap_flag[i]++; + ctx->invalid_bitmaps++; + } + } else { + ext2fs_mark_block_bitmap2(ctx->block_found_map, + ext2fs_block_bitmap_loc(fs, i)); + } + + } + /* + * Mark block used for the inode bitmap + */ + if (ext2fs_inode_bitmap_loc(fs, i)) { + if (ext2fs_test_block_bitmap2(ctx->block_found_map, + ext2fs_inode_bitmap_loc(fs, i))) { + pctx.blk = ext2fs_inode_bitmap_loc(fs, i); + if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) { + ctx->invalid_inode_bitmap_flag[i]++; + ctx->invalid_bitmaps++; + } + } else { + ext2fs_mark_block_bitmap2(ctx->block_found_map, + ext2fs_inode_bitmap_loc(fs, i)); + } + } + } +} + +/* + * Thes subroutines short circuits ext2fs_get_blocks and + * ext2fs_check_directory; we use them since we already have the inode + * structure, so there's no point in letting the ext2fs library read + * the inode again. + */ +static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino, + blk_t *blocks) +{ + e2fsck_t ctx = (e2fsck_t) fs->priv_data; + int i; + + if ((ino != ctx->stashed_ino) || !ctx->stashed_inode) + return EXT2_ET_CALLBACK_NOTHANDLED; + + for (i=0; i < EXT2_N_BLOCKS; i++) + blocks[i] = ctx->stashed_inode->i_block[i]; + return 0; +} + +static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode) +{ + e2fsck_t ctx = (e2fsck_t) fs->priv_data; + + if ((ino != ctx->stashed_ino) || !ctx->stashed_inode) + return EXT2_ET_CALLBACK_NOTHANDLED; + *inode = *ctx->stashed_inode; + return 0; +} + +static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino, + struct ext2_inode *inode) +{ + e2fsck_t ctx = (e2fsck_t) fs->priv_data; + + if ((ino == ctx->stashed_ino) && ctx->stashed_inode && + (inode != ctx->stashed_inode)) + *ctx->stashed_inode = *inode; + return EXT2_ET_CALLBACK_NOTHANDLED; +} + +static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino) +{ + e2fsck_t ctx = (e2fsck_t) fs->priv_data; + + if ((ino != ctx->stashed_ino) || !ctx->stashed_inode) + return EXT2_ET_CALLBACK_NOTHANDLED; + + if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode)) + return EXT2_ET_NO_DIRECTORY; + return 0; +} + +static errcode_t e2fsck_get_alloc_block(ext2_filsys fs, blk64_t goal, + blk64_t *ret) +{ + e2fsck_t ctx = (e2fsck_t) fs->priv_data; + errcode_t retval; + blk64_t new_block; + + if (ctx->block_found_map) { + retval = ext2fs_new_block2(fs, goal, ctx->block_found_map, + &new_block); + if (retval) + return retval; + if (fs->block_map) { + ext2fs_mark_block_bitmap2(fs->block_map, new_block); + ext2fs_mark_bb_dirty(fs); + } + } else { + if (!fs->block_map) { + retval = ext2fs_read_block_bitmap(fs); + if (retval) + return retval; + } + + retval = ext2fs_new_block2(fs, goal, 0, &new_block); + if (retval) + return retval; + } + + *ret = new_block; + return (0); +} + +static void e2fsck_block_alloc_stats(ext2_filsys fs, blk64_t blk, int inuse) +{ + e2fsck_t ctx = (e2fsck_t) fs->priv_data; + + if (ctx->block_found_map) { + if (inuse > 0) + ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); + else + ext2fs_unmark_block_bitmap2(ctx->block_found_map, blk); + } +} + +void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int use_shortcuts) +{ + ext2_filsys fs = ctx->fs; + + if (use_shortcuts) { + fs->get_blocks = pass1_get_blocks; + fs->check_directory = pass1_check_directory; + fs->read_inode = pass1_read_inode; + fs->write_inode = pass1_write_inode; + ctx->stashed_ino = 0; + } else { + fs->get_blocks = 0; + fs->check_directory = 0; + fs->read_inode = 0; + fs->write_inode = 0; + } +} + +void e2fsck_intercept_block_allocations(e2fsck_t ctx) +{ + ext2fs_set_alloc_block_callback(ctx->fs, e2fsck_get_alloc_block, 0); + ext2fs_set_block_alloc_stats_callback(ctx->fs, + e2fsck_block_alloc_stats, 0); +}
diff --git a/e2fsck/pass1b.c b/e2fsck/pass1b.c new file mode 100644 index 0000000..bb81d5e --- /dev/null +++ b/e2fsck/pass1b.c
@@ -0,0 +1,985 @@ +/* + * pass1b.c --- Pass #1b of e2fsck + * + * This file contains pass1B, pass1C, and pass1D of e2fsck. They are + * only invoked if pass 1 discovered blocks which are in use by more + * than one inode. + * + * Pass1B scans the data blocks of all the inodes again, generating a + * complete list of duplicate blocks and which inodes have claimed + * them. + * + * Pass1C does a tree-traversal of the filesystem, to determine the + * parent directories of these inodes. This step is necessary so that + * e2fsck can print out the pathnames of affected inodes. + * + * Pass1D is a reconciliation pass. For each inode with duplicate + * blocks, the user is prompted if s/he would like to clone the file + * (so that the file gets a fresh copy of the duplicated blocks) or + * simply to delete the file. + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + */ + +#include "config.h" +#include <time.h> +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif + +#ifndef HAVE_INTPTR_T +typedef long intptr_t; +#endif + +/* Needed for architectures where sizeof(int) != sizeof(void *) */ +#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val)) +#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr)) + +#include <et/com_err.h> +#include "e2fsck.h" + +#include "problem.h" +#include "dict.h" + +/* Define an extension to the ext2 library's block count information */ +#define BLOCK_COUNT_EXTATTR (-5) + +struct cluster_el { + blk64_t cluster; + struct cluster_el *next; +}; + +struct inode_el { + ext2_ino_t inode; + struct inode_el *next; +}; + +struct dup_cluster { + int num_bad; + struct inode_el *inode_list; +}; + +/* + * This structure stores information about a particular inode which + * is sharing blocks with other inodes. This information is collected + * to display to the user, so that the user knows what files he or she + * is dealing with, when trying to decide how to resolve the conflict + * of multiply-claimed blocks. + */ +struct dup_inode { + ext2_ino_t dir; + int num_dupblocks; + struct ext2_inode inode; + struct cluster_el *cluster_list; +}; + +static int process_pass1b_block(ext2_filsys fs, blk64_t *blocknr, + e2_blkcnt_t blockcnt, blk64_t ref_blk, + int ref_offset, void *priv_data); +static void delete_file(e2fsck_t ctx, ext2_ino_t ino, + struct dup_inode *dp, char *block_buf); +static errcode_t clone_file(e2fsck_t ctx, ext2_ino_t ino, + struct dup_inode *dp, char* block_buf); +static int check_if_fs_block(e2fsck_t ctx, blk64_t test_block); +static int check_if_fs_cluster(e2fsck_t ctx, blk64_t cluster); + +static void pass1b(e2fsck_t ctx, char *block_buf); +static void pass1c(e2fsck_t ctx, char *block_buf); +static void pass1d(e2fsck_t ctx, char *block_buf); + +static int dup_inode_count = 0; +static int dup_inode_founddir = 0; + +static dict_t clstr_dict, ino_dict; + +static ext2fs_inode_bitmap inode_dup_map; + +static int dict_int_cmp(const void *a, const void *b) +{ + intptr_t ia, ib; + + ia = (intptr_t)a; + ib = (intptr_t)b; + + return (ia-ib); +} + +/* + * Add a duplicate block record + */ +static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk64_t cluster, + struct ext2_inode *inode) +{ + dnode_t *n; + struct dup_cluster *db; + struct dup_inode *di; + struct cluster_el *cluster_el; + struct inode_el *ino_el; + + n = dict_lookup(&clstr_dict, INT_TO_VOIDPTR(cluster)); + if (n) + db = (struct dup_cluster *) dnode_get(n); + else { + db = (struct dup_cluster *) e2fsck_allocate_memory(ctx, + sizeof(struct dup_cluster), "duplicate cluster header"); + db->num_bad = 0; + db->inode_list = 0; + dict_alloc_insert(&clstr_dict, INT_TO_VOIDPTR(cluster), db); + } + ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx, + sizeof(struct inode_el), "inode element"); + ino_el->inode = ino; + ino_el->next = db->inode_list; + db->inode_list = ino_el; + db->num_bad++; + + n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino)); + if (n) + di = (struct dup_inode *) dnode_get(n); + else { + di = (struct dup_inode *) e2fsck_allocate_memory(ctx, + sizeof(struct dup_inode), "duplicate inode header"); + if (ino == EXT2_ROOT_INO) { + di->dir = EXT2_ROOT_INO; + dup_inode_founddir++; + } else + di->dir = 0; + + di->num_dupblocks = 0; + di->cluster_list = 0; + di->inode = *inode; + dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di); + } + cluster_el = (struct cluster_el *) e2fsck_allocate_memory(ctx, + sizeof(struct cluster_el), "cluster element"); + cluster_el->cluster = cluster; + cluster_el->next = di->cluster_list; + di->cluster_list = cluster_el; + di->num_dupblocks++; +} + +/* + * Free a duplicate inode record + */ +static void inode_dnode_free(dnode_t *node, + void *context EXT2FS_ATTR((unused))) +{ + struct dup_inode *di; + struct cluster_el *p, *next; + + di = (struct dup_inode *) dnode_get(node); + for (p = di->cluster_list; p; p = next) { + next = p->next; + free(p); + } + free(di); + free(node); +} + +/* + * Free a duplicate cluster record + */ +static void cluster_dnode_free(dnode_t *node, + void *context EXT2FS_ATTR((unused))) +{ + struct dup_cluster *dc; + struct inode_el *p, *next; + + dc = (struct dup_cluster *) dnode_get(node); + for (p = dc->inode_list; p; p = next) { + next = p->next; + free(p); + } + free(dc); + free(node); +} + + +/* + * Main procedure for handling duplicate blocks + */ +void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf) +{ + ext2_filsys fs = ctx->fs; + struct problem_context pctx; +#ifdef RESOURCE_TRACK + struct resource_track rtrack; +#endif + + clear_problem_context(&pctx); + + pctx.errcode = e2fsck_allocate_inode_bitmap(fs, + _("multiply claimed inode map"), + EXT2FS_BMAP64_RBTREE, "inode_dup_map", + &inode_dup_map); + if (pctx.errcode) { + fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + + dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp); + dict_init(&clstr_dict, DICTCOUNT_T_MAX, dict_int_cmp); + dict_set_allocator(&ino_dict, NULL, inode_dnode_free, NULL); + dict_set_allocator(&clstr_dict, NULL, cluster_dnode_free, NULL); + + init_resource_track(&rtrack, ctx->fs->io); + pass1b(ctx, block_buf); + print_resource_track(ctx, "Pass 1b", &rtrack, ctx->fs->io); + + init_resource_track(&rtrack, ctx->fs->io); + pass1c(ctx, block_buf); + print_resource_track(ctx, "Pass 1c", &rtrack, ctx->fs->io); + + init_resource_track(&rtrack, ctx->fs->io); + pass1d(ctx, block_buf); + print_resource_track(ctx, "Pass 1d", &rtrack, ctx->fs->io); + + /* + * Time to free all of the accumulated data structures that we + * don't need anymore. + */ + dict_free_nodes(&ino_dict); + dict_free_nodes(&clstr_dict); + ext2fs_free_inode_bitmap(inode_dup_map); +} + +/* + * Scan the inodes looking for inodes that contain duplicate blocks. + */ +struct process_block_struct { + e2fsck_t ctx; + ext2_ino_t ino; + int dup_blocks; + blk64_t cur_cluster, phys_cluster; + struct ext2_inode *inode; + struct problem_context *pctx; +}; + +static void pass1b(e2fsck_t ctx, char *block_buf) +{ + ext2_filsys fs = ctx->fs; + ext2_ino_t ino = 0; + struct ext2_inode inode; + ext2_inode_scan scan; + struct process_block_struct pb; + struct problem_context pctx; + + clear_problem_context(&pctx); + + if (!(ctx->options & E2F_OPT_PREEN)) + fix_problem(ctx, PR_1B_PASS_HEADER, &pctx); + pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks, + &scan); + if (pctx.errcode) { + fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + ctx->stashed_inode = &inode; + pb.ctx = ctx; + pb.pctx = &pctx; + pctx.str = "pass1b"; + while (1) { + if (ino % (fs->super->s_inodes_per_group * 4) == 1) { + if (e2fsck_mmp_update(fs)) + fatal_error(ctx, 0); + } + pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode); + if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) + continue; + if (pctx.errcode) { + pctx.ino = ino; + fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + if (!ino) + break; + pctx.ino = ctx->stashed_ino = ino; + if ((ino != EXT2_BAD_INO) && + !ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino)) + continue; + + pb.ino = ino; + pb.dup_blocks = 0; + pb.inode = &inode; + pb.cur_cluster = ~0; + pb.phys_cluster = ~0; + + if (ext2fs_inode_has_valid_blocks2(fs, &inode) || + (ino == EXT2_BAD_INO)) + pctx.errcode = ext2fs_block_iterate3(fs, ino, + BLOCK_FLAG_READ_ONLY, block_buf, + process_pass1b_block, &pb); + /* If the feature is not set, attrs will be cleared later anyway */ + if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) && + ext2fs_file_acl_block(fs, &inode)) { + blk64_t blk = ext2fs_file_acl_block(fs, &inode); + process_pass1b_block(fs, &blk, + BLOCK_COUNT_EXTATTR, 0, 0, &pb); + ext2fs_file_acl_block_set(fs, &inode, blk); + } + if (pb.dup_blocks) { + end_problem_latch(ctx, PR_LATCH_DBLOCK); + if (ino >= EXT2_FIRST_INODE(fs->super) || + ino == EXT2_ROOT_INO) + dup_inode_count++; + } + if (pctx.errcode) + fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); + } + ext2fs_close_inode_scan(scan); + e2fsck_use_inode_shortcuts(ctx, 0); +} + +static int process_pass1b_block(ext2_filsys fs EXT2FS_ATTR((unused)), + blk64_t *block_nr, + e2_blkcnt_t blockcnt, + blk64_t ref_blk EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct process_block_struct *p; + e2fsck_t ctx; + blk64_t lc, pc; + + if (HOLE_BLKADDR(*block_nr)) + return 0; + p = (struct process_block_struct *) priv_data; + ctx = p->ctx; + lc = EXT2FS_B2C(fs, blockcnt); + pc = EXT2FS_B2C(fs, *block_nr); + + if (!ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) + goto finish; + + /* OK, this is a duplicate block */ + if (p->ino != EXT2_BAD_INO) { + p->pctx->blk = *block_nr; + fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx); + } + p->dup_blocks++; + ext2fs_mark_inode_bitmap2(inode_dup_map, p->ino); + + /* + * Qualifications for submitting a block for duplicate processing: + * It's an extent/indirect block (and has a negative logical offset); + * we've crossed a logical cluster boundary; or the physical cluster + * suddenly changed, which indicates that blocks in a logical cluster + * are mapped to multiple physical clusters. + */ + if (blockcnt < 0 || lc != p->cur_cluster || pc != p->phys_cluster) + add_dupe(ctx, p->ino, EXT2FS_B2C(fs, *block_nr), p->inode); + +finish: + p->cur_cluster = lc; + p->phys_cluster = pc; + return 0; +} + +/* + * Pass 1c: Scan directories for inodes with duplicate blocks. This + * is used so that we can print pathnames when prompting the user for + * what to do. + */ +struct search_dir_struct { + int count; + ext2_ino_t first_inode; + ext2_ino_t max_inode; +}; + +static int search_dirent_proc(ext2_ino_t dir, int entry, + struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct search_dir_struct *sd; + struct dup_inode *p; + dnode_t *n; + + sd = (struct search_dir_struct *) priv_data; + + if (dirent->inode > sd->max_inode) + /* Should abort this inode, but not everything */ + return 0; + + if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) || + !ext2fs_test_inode_bitmap2(inode_dup_map, dirent->inode)) + return 0; + + n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode)); + if (!n) + return 0; + p = (struct dup_inode *) dnode_get(n); + if (!p->dir) { + p->dir = dir; + sd->count--; + } + + return(sd->count ? 0 : DIRENT_ABORT); +} + + +static void pass1c(e2fsck_t ctx, char *block_buf) +{ + ext2_filsys fs = ctx->fs; + struct search_dir_struct sd; + struct problem_context pctx; + + clear_problem_context(&pctx); + + if (!(ctx->options & E2F_OPT_PREEN)) + fix_problem(ctx, PR_1C_PASS_HEADER, &pctx); + + /* + * Search through all directories to translate inodes to names + * (by searching for the containing directory for that inode.) + */ + sd.count = dup_inode_count - dup_inode_founddir; + sd.first_inode = EXT2_FIRST_INODE(fs->super); + sd.max_inode = fs->super->s_inodes_count; + ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf, + search_dirent_proc, &sd); +} + +static void pass1d(e2fsck_t ctx, char *block_buf) +{ + ext2_filsys fs = ctx->fs; + struct dup_inode *p, *t; + struct dup_cluster *q; + ext2_ino_t *shared, ino; + int shared_len; + int i; + int file_ok; + int meta_data = 0; + struct problem_context pctx; + dnode_t *n, *m; + struct cluster_el *s; + struct inode_el *r; + + clear_problem_context(&pctx); + + if (!(ctx->options & E2F_OPT_PREEN)) + fix_problem(ctx, PR_1D_PASS_HEADER, &pctx); + e2fsck_read_bitmaps(ctx); + + pctx.num = dup_inode_count; /* dict_count(&ino_dict); */ + fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx); + shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx, + sizeof(ext2_ino_t) * dict_count(&ino_dict), + "Shared inode list"); + for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) { + p = (struct dup_inode *) dnode_get(n); + shared_len = 0; + file_ok = 1; + ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n)); + if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO) + continue; + + /* + * Find all of the inodes which share blocks with this + * one. First we find all of the duplicate blocks + * belonging to this inode, and then search each block + * get the list of inodes, and merge them together. + */ + for (s = p->cluster_list; s; s = s->next) { + m = dict_lookup(&clstr_dict, + INT_TO_VOIDPTR(s->cluster)); + if (!m) + continue; /* Should never happen... */ + q = (struct dup_cluster *) dnode_get(m); + if (q->num_bad > 1) + file_ok = 0; + if (check_if_fs_cluster(ctx, s->cluster)) { + file_ok = 0; + meta_data = 1; + } + + /* + * Add all inodes used by this block to the + * shared[] --- which is a unique list, so + * if an inode is already in shared[], don't + * add it again. + */ + for (r = q->inode_list; r; r = r->next) { + if (r->inode == ino) + continue; + for (i = 0; i < shared_len; i++) + if (shared[i] == r->inode) + break; + if (i == shared_len) { + shared[shared_len++] = r->inode; + } + } + } + + /* + * Report the inode that we are working on + */ + pctx.inode = &p->inode; + pctx.ino = ino; + pctx.dir = p->dir; + pctx.blkcount = p->num_dupblocks; + pctx.num = meta_data ? shared_len+1 : shared_len; + fix_problem(ctx, PR_1D_DUP_FILE, &pctx); + pctx.blkcount = 0; + pctx.num = 0; + + if (meta_data) + fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx); + + for (i = 0; i < shared_len; i++) { + m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i])); + if (!m) + continue; /* should never happen */ + t = (struct dup_inode *) dnode_get(m); + /* + * Report the inode that we are sharing with + */ + pctx.inode = &t->inode; + pctx.ino = shared[i]; + pctx.dir = t->dir; + fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx); + } + /* + * Even if the file shares blocks with itself, we still need to + * clone the blocks. + */ + if (file_ok && (meta_data ? shared_len+1 : shared_len) != 0) { + fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx); + continue; + } + if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) { + pctx.errcode = clone_file(ctx, ino, p, block_buf); + if (pctx.errcode) + fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx); + else + continue; + } + if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx)) + delete_file(ctx, ino, p, block_buf); + else + ext2fs_unmark_valid(fs); + } + ext2fs_free_mem(&shared); +} + +/* + * Drop the refcount on the dup_block structure, and clear the entry + * in the block_dup_map if appropriate. + */ +static void decrement_badcount(e2fsck_t ctx, blk64_t block, + struct dup_cluster *p) +{ + p->num_bad--; + if (p->num_bad <= 0 || + (p->num_bad == 1 && !check_if_fs_block(ctx, block))) { + if (check_if_fs_cluster(ctx, EXT2FS_B2C(ctx->fs, block))) + return; + ext2fs_unmark_block_bitmap2(ctx->block_dup_map, block); + } +} + +static int delete_file_block(ext2_filsys fs, + blk64_t *block_nr, + e2_blkcnt_t blockcnt, + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct process_block_struct *pb; + struct dup_cluster *p; + dnode_t *n; + e2fsck_t ctx; + blk64_t c, lc; + + pb = (struct process_block_struct *) priv_data; + ctx = pb->ctx; + + if (HOLE_BLKADDR(*block_nr)) + return 0; + + c = EXT2FS_B2C(fs, *block_nr); + lc = EXT2FS_B2C(fs, blockcnt); + if (ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) { + n = dict_lookup(&clstr_dict, INT_TO_VOIDPTR(c)); + if (n) { + p = (struct dup_cluster *) dnode_get(n); + if (lc != pb->cur_cluster) + decrement_badcount(ctx, *block_nr, p); + } else + com_err("delete_file_block", 0, + _("internal error: can't find dup_blk for %llu\n"), + *block_nr); + } else { + if ((*block_nr % EXT2FS_CLUSTER_RATIO(ctx->fs)) == 0) + ext2fs_block_alloc_stats2(fs, *block_nr, -1); + pb->dup_blocks++; + } + pb->cur_cluster = lc; + + return 0; +} + +static void delete_file(e2fsck_t ctx, ext2_ino_t ino, + struct dup_inode *dp, char* block_buf) +{ + ext2_filsys fs = ctx->fs; + struct process_block_struct pb; + struct problem_context pctx; + unsigned int count; + + clear_problem_context(&pctx); + pctx.ino = pb.ino = ino; + pb.dup_blocks = 0; + pb.ctx = ctx; + pctx.str = "delete_file"; + pb.cur_cluster = ~0; + + if (ext2fs_inode_has_valid_blocks2(fs, &dp->inode)) + pctx.errcode = ext2fs_block_iterate3(fs, ino, + BLOCK_FLAG_READ_ONLY, + block_buf, + delete_file_block, &pb); + if (pctx.errcode) + fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); + if (ctx->inode_bad_map) + ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); + ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(dp->inode.i_mode)); + quota_data_sub(ctx->qctx, &dp->inode, ino, + pb.dup_blocks * fs->blocksize); + quota_data_inodes(ctx->qctx, &dp->inode, ino, -1); + + /* Inode may have changed by block_iterate, so reread it */ + e2fsck_read_inode(ctx, ino, &dp->inode, "delete_file"); + e2fsck_clear_inode(ctx, ino, &dp->inode, 0, "delete_file"); + if (ext2fs_file_acl_block(fs, &dp->inode) && + (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { + count = 1; + pctx.errcode = ext2fs_adjust_ea_refcount2(fs, + ext2fs_file_acl_block(fs, &dp->inode), + block_buf, -1, &count); + if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { + pctx.errcode = 0; + count = 1; + } + if (pctx.errcode) { + pctx.blk = ext2fs_file_acl_block(fs, &dp->inode); + fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx); + } + /* + * If the count is zero, then arrange to have the + * block deleted. If the block is in the block_dup_map, + * also call delete_file_block since it will take care + * of keeping the accounting straight. + */ + if ((count == 0) || + ext2fs_test_block_bitmap2(ctx->block_dup_map, + ext2fs_file_acl_block(fs, &dp->inode))) { + blk64_t blk = ext2fs_file_acl_block(fs, &dp->inode); + delete_file_block(fs, &blk, + BLOCK_COUNT_EXTATTR, 0, 0, &pb); + ext2fs_file_acl_block_set(fs, &dp->inode, blk); + quota_data_sub(ctx->qctx, &dp->inode, ino, fs->blocksize); + } + } +} + +struct clone_struct { + errcode_t errcode; + blk64_t dup_cluster; + blk64_t alloc_block; + ext2_ino_t dir, ino; + char *buf; + e2fsck_t ctx; + struct ext2_inode *inode; +}; + +static int clone_file_block(ext2_filsys fs, + blk64_t *block_nr, + e2_blkcnt_t blockcnt, + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct dup_cluster *p; + blk64_t new_block; + errcode_t retval; + struct clone_struct *cs = (struct clone_struct *) priv_data; + dnode_t *n; + e2fsck_t ctx; + blk64_t c; + int is_meta = 0; + + ctx = cs->ctx; + + if (HOLE_BLKADDR(*block_nr)) + return 0; + + c = EXT2FS_B2C(fs, blockcnt); + if (check_if_fs_cluster(ctx, EXT2FS_B2C(fs, *block_nr))) + is_meta = 1; + + if (c == cs->dup_cluster && cs->alloc_block) { + new_block = cs->alloc_block; + goto got_block; + } + + if (ext2fs_test_block_bitmap2(ctx->block_dup_map, *block_nr)) { + n = dict_lookup(&clstr_dict, + INT_TO_VOIDPTR(EXT2FS_B2C(fs, *block_nr))); + if (!n) { + com_err("clone_file_block", 0, + _("internal error: can't find dup_blk for %llu\n"), + *block_nr); + return 0; + } + + p = (struct dup_cluster *) dnode_get(n); + if (!is_meta) + decrement_badcount(ctx, *block_nr, p); + + cs->dup_cluster = c; + /* + * Let's try an implied cluster allocation. If we get the same + * cluster back, then we need to find a new block; otherwise, + * we're merely fixing the problem of one logical cluster being + * mapped to multiple physical clusters. + */ + new_block = 0; + retval = ext2fs_map_cluster_block(fs, cs->ino, cs->inode, + blockcnt, &new_block); + if (retval == 0 && new_block != 0 && + EXT2FS_B2C(ctx->fs, new_block) != + EXT2FS_B2C(ctx->fs, *block_nr)) + goto cluster_alloc_ok; + retval = ext2fs_new_block2(fs, 0, ctx->block_found_map, + &new_block); + if (retval) { + cs->errcode = retval; + return BLOCK_ABORT; + } +cluster_alloc_ok: + cs->alloc_block = new_block; + + got_block: + new_block &= ~EXT2FS_CLUSTER_MASK(fs); + new_block += EXT2FS_CLUSTER_MASK(fs) & blockcnt; + if (cs->dir && (blockcnt >= 0)) { + retval = ext2fs_set_dir_block2(fs->dblist, + cs->dir, new_block, blockcnt); + if (retval) { + cs->errcode = retval; + return BLOCK_ABORT; + } + } +#if 0 + printf("Cloning block #%lld from %llu to %llu\n", + blockcnt, *block_nr, new_block); +#endif + retval = io_channel_read_blk64(fs->io, *block_nr, 1, cs->buf); + if (retval) { + cs->errcode = retval; + return BLOCK_ABORT; + } + retval = io_channel_write_blk64(fs->io, new_block, 1, cs->buf); + if (retval) { + cs->errcode = retval; + return BLOCK_ABORT; + } + *block_nr = new_block; + ext2fs_mark_block_bitmap2(ctx->block_found_map, new_block); + ext2fs_mark_block_bitmap2(fs->block_map, new_block); + return BLOCK_CHANGED; + } + return 0; +} + +static errcode_t clone_file(e2fsck_t ctx, ext2_ino_t ino, + struct dup_inode *dp, char* block_buf) +{ + ext2_filsys fs = ctx->fs; + errcode_t retval; + struct clone_struct cs; + struct problem_context pctx; + blk64_t blk, new_blk; + dnode_t *n; + struct inode_el *ino_el; + struct dup_cluster *dc; + struct dup_inode *di; + + clear_problem_context(&pctx); + cs.errcode = 0; + cs.dir = 0; + cs.dup_cluster = ~0; + cs.alloc_block = 0; + cs.ctx = ctx; + cs.ino = ino; + cs.inode = &dp->inode; + retval = ext2fs_get_mem(fs->blocksize, &cs.buf); + if (retval) + return retval; + + if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, ino)) + cs.dir = ino; + + pctx.ino = ino; + pctx.str = "clone_file"; + if (ext2fs_inode_has_valid_blocks2(fs, &dp->inode)) + pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf, + clone_file_block, &cs); + ext2fs_mark_bb_dirty(fs); + if (pctx.errcode) { + fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); + retval = pctx.errcode; + goto errout; + } + if (cs.errcode) { + com_err("clone_file", cs.errcode, "%s", + _("returned from clone_file_block")); + retval = cs.errcode; + goto errout; + } + /* The inode may have changed on disk, so we have to re-read it */ + e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA"); + blk = ext2fs_file_acl_block(fs, &dp->inode); + new_blk = blk; + if (blk && (clone_file_block(fs, &new_blk, + BLOCK_COUNT_EXTATTR, 0, 0, &cs) == + BLOCK_CHANGED)) { + ext2fs_file_acl_block_set(fs, &dp->inode, new_blk); + e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA"); + /* + * If we cloned the EA block, find all other inodes + * which refered to that EA block, and modify + * them to point to the new EA block. + */ + n = dict_lookup(&clstr_dict, + INT_TO_VOIDPTR(EXT2FS_B2C(fs, blk))); + if (!n) { + com_err("clone_file", 0, + _("internal error: couldn't lookup EA " + "block record for %llu"), blk); + retval = 0; /* OK to stumble on... */ + goto errout; + } + dc = (struct dup_cluster *) dnode_get(n); + for (ino_el = dc->inode_list; ino_el; ino_el = ino_el->next) { + if (ino_el->inode == ino) + continue; + n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode)); + if (!n) { + com_err("clone_file", 0, + _("internal error: couldn't lookup EA " + "inode record for %u"), + ino_el->inode); + retval = 0; /* OK to stumble on... */ + goto errout; + } + di = (struct dup_inode *) dnode_get(n); + if (ext2fs_file_acl_block(fs, &di->inode) == blk) { + ext2fs_file_acl_block_set(fs, &di->inode, + ext2fs_file_acl_block(fs, &dp->inode)); + e2fsck_write_inode(ctx, ino_el->inode, + &di->inode, "clone file EA"); + decrement_badcount(ctx, blk, dc); + } + } + } + retval = 0; +errout: + ext2fs_free_mem(&cs.buf); + return retval; +} + +/* + * This routine returns 1 if a block overlaps with one of the superblocks, + * group descriptors, inode bitmaps, or block bitmaps. + */ +static int check_if_fs_block(e2fsck_t ctx, blk64_t test_block) +{ + ext2_filsys fs = ctx->fs; + blk64_t first_block; + dgrp_t i; + + first_block = fs->super->s_first_data_block; + for (i = 0; i < fs->group_desc_count; i++) { + + /* Check superblocks/block group descriptors */ + if (ext2fs_bg_has_super(fs, i)) { + if (test_block >= first_block && + (test_block <= first_block + fs->desc_blocks)) + return 1; + } + + /* Check the inode table */ + if ((ext2fs_inode_table_loc(fs, i)) && + (test_block >= ext2fs_inode_table_loc(fs, i)) && + (test_block < (ext2fs_inode_table_loc(fs, i) + + fs->inode_blocks_per_group))) + return 1; + + /* Check the bitmap blocks */ + if ((test_block == ext2fs_block_bitmap_loc(fs, i)) || + (test_block == ext2fs_inode_bitmap_loc(fs, i))) + return 1; + + first_block += fs->super->s_blocks_per_group; + } + return 0; +} + +/* + * This routine returns 1 if a cluster overlaps with one of the superblocks, + * group descriptors, inode bitmaps, or block bitmaps. + */ +static int check_if_fs_cluster(e2fsck_t ctx, blk64_t cluster) +{ + ext2_filsys fs = ctx->fs; + blk64_t first_block; + dgrp_t i; + + first_block = fs->super->s_first_data_block; + for (i = 0; i < fs->group_desc_count; i++) { + + /* Check superblocks/block group descriptors */ + if (ext2fs_bg_has_super(fs, i)) { + if (cluster >= EXT2FS_B2C(fs, first_block) && + (cluster <= EXT2FS_B2C(fs, first_block + + fs->desc_blocks))) + return 1; + } + + /* Check the inode table */ + if ((ext2fs_inode_table_loc(fs, i)) && + (cluster >= EXT2FS_B2C(fs, + ext2fs_inode_table_loc(fs, i))) && + (cluster <= EXT2FS_B2C(fs, + ext2fs_inode_table_loc(fs, i) + + fs->inode_blocks_per_group - 1))) + return 1; + + /* Check the bitmap blocks */ + if ((cluster == EXT2FS_B2C(fs, + ext2fs_block_bitmap_loc(fs, i))) || + (cluster == EXT2FS_B2C(fs, + ext2fs_inode_bitmap_loc(fs, i)))) + return 1; + + first_block += fs->super->s_blocks_per_group; + } + return 0; +}
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c new file mode 100644 index 0000000..4acddae --- /dev/null +++ b/e2fsck/pass2.c
@@ -0,0 +1,1501 @@ +/* + * pass2.c --- check directory structure + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * Pass 2 of e2fsck iterates through all active directory inodes, and + * applies to following tests to each directory entry in the directory + * blocks in the inodes: + * + * - The length of the directory entry (rec_len) should be at + * least 8 bytes, and no more than the remaining space + * left in the directory block. + * - The length of the name in the directory entry (name_len) + * should be less than (rec_len - 8). + * - The inode number in the directory entry should be within + * legal bounds. + * - The inode number should refer to a in-use inode. + * - The first entry should be '.', and its inode should be + * the inode of the directory. + * - The second entry should be '..'. + * + * To minimize disk seek time, the directory blocks are processed in + * sorted order of block numbers. + * + * Pass 2 also collects the following information: + * - The inode numbers of the subdirectories for each directory. + * + * Pass 2 relies on the following information from previous passes: + * - The directory information collected in pass 1. + * - The inode_used_map bitmap + * - The inode_bad_map bitmap + * - The inode_dir_map bitmap + * + * Pass 2 frees the following data structures + * - The inode_bad_map bitmap + * - The inode_reg_map bitmap + */ + +#define _GNU_SOURCE 1 /* get strnlen() */ +#include "config.h" +#include <string.h> + +#include "e2fsck.h" +#include "problem.h" +#include "dict.h" + +#ifdef NO_INLINE_FUNCS +#define _INLINE_ +#else +#define _INLINE_ inline +#endif + +/* #define DX_DEBUG */ + +/* + * Keeps track of how many times an inode is referenced. + */ +static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf); +static int check_dir_block(ext2_filsys fs, + struct ext2_db_entry2 *dir_blocks_info, + void *priv_data); +static int allocate_dir_block(e2fsck_t ctx, + struct ext2_db_entry2 *dir_blocks_info, + char *buf, struct problem_context *pctx); +static void clear_htree(e2fsck_t ctx, ext2_ino_t ino); +static int htree_depth(struct dx_dir_info *dx_dir, + struct dx_dirblock_info *dx_db); +static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b); + +struct check_dir_struct { + char *buf; + struct problem_context pctx; + int count, max; + e2fsck_t ctx; +}; + +void e2fsck_pass2(e2fsck_t ctx) +{ + struct ext2_super_block *sb = ctx->fs->super; + struct problem_context pctx; + ext2_filsys fs = ctx->fs; + char *buf; +#ifdef RESOURCE_TRACK + struct resource_track rtrack; +#endif + struct check_dir_struct cd; + struct dx_dir_info *dx_dir; + struct dx_dirblock_info *dx_db, *dx_parent; + unsigned int save_type; + int b; + int i, depth; + problem_t code; + int bad_dir; + + init_resource_track(&rtrack, ctx->fs->io); + clear_problem_context(&cd.pctx); + +#ifdef MTRACE + mtrace_print("Pass 2"); +#endif + + if (!(ctx->options & E2F_OPT_PREEN)) + fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx); + + e2fsck_setup_tdb_icount(ctx, EXT2_ICOUNT_OPT_INCREMENT, + &ctx->inode_count); + if (ctx->inode_count) + cd.pctx.errcode = 0; + else { + e2fsck_set_bitmap_type(fs, EXT2FS_BMAP64_RBTREE, + "inode_count", &save_type); + cd.pctx.errcode = ext2fs_create_icount2(fs, + EXT2_ICOUNT_OPT_INCREMENT, + 0, ctx->inode_link_info, + &ctx->inode_count); + fs->default_bitmap_type = save_type; + } + if (cd.pctx.errcode) { + fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize, + "directory scan buffer"); + + /* + * Set up the parent pointer for the root directory, if + * present. (If the root directory is not present, we will + * create it in pass 3.) + */ + (void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO); + + cd.buf = buf; + cd.ctx = ctx; + cd.count = 1; + cd.max = ext2fs_dblist_count2(fs->dblist); + + if (ctx->progress) + (void) (ctx->progress)(ctx, 2, 0, cd.max); + + if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) + ext2fs_dblist_sort2(fs->dblist, special_dir_block_cmp); + + cd.pctx.errcode = ext2fs_dblist_iterate2(fs->dblist, check_dir_block, + &cd); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART) + return; + + if (ctx->flags & E2F_FLAG_RESTART_LATER) { + ctx->flags |= E2F_FLAG_RESTART; + return; + } + + if (cd.pctx.errcode) { + fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + +#ifdef ENABLE_HTREE + for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) { + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return; + if (dx_dir->numblocks == 0) + continue; + clear_problem_context(&pctx); + bad_dir = 0; + pctx.dir = dx_dir->ino; + dx_db = dx_dir->dx_block; + if (dx_db->flags & DX_FLAG_REFERENCED) + dx_db->flags |= DX_FLAG_DUP_REF; + else + dx_db->flags |= DX_FLAG_REFERENCED; + /* + * Find all of the first and last leaf blocks, and + * update their parent's min and max hash values + */ + for (b=0, dx_db = dx_dir->dx_block; + b < dx_dir->numblocks; + b++, dx_db++) { + if ((dx_db->type != DX_DIRBLOCK_LEAF) || + !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST))) + continue; + dx_parent = &dx_dir->dx_block[dx_db->parent]; + /* + * XXX Make sure dx_parent->min_hash > dx_db->min_hash + */ + if (dx_db->flags & DX_FLAG_FIRST) + dx_parent->min_hash = dx_db->min_hash; + /* + * XXX Make sure dx_parent->max_hash < dx_db->max_hash + */ + if (dx_db->flags & DX_FLAG_LAST) + dx_parent->max_hash = dx_db->max_hash; + } + + for (b=0, dx_db = dx_dir->dx_block; + b < dx_dir->numblocks; + b++, dx_db++) { + pctx.blkcount = b; + pctx.group = dx_db->parent; + code = 0; + if (!(dx_db->flags & DX_FLAG_FIRST) && + (dx_db->min_hash < dx_db->node_min_hash)) { + pctx.blk = dx_db->min_hash; + pctx.blk2 = dx_db->node_min_hash; + code = PR_2_HTREE_MIN_HASH; + fix_problem(ctx, code, &pctx); + bad_dir++; + } + if (dx_db->type == DX_DIRBLOCK_LEAF) { + depth = htree_depth(dx_dir, dx_db); + if (depth != dx_dir->depth) { + pctx.num = dx_dir->depth; + code = PR_2_HTREE_BAD_DEPTH; + fix_problem(ctx, code, &pctx); + bad_dir++; + } + } + /* + * This test doesn't apply for the root block + * at block #0 + */ + if (b && + (dx_db->max_hash > dx_db->node_max_hash)) { + pctx.blk = dx_db->max_hash; + pctx.blk2 = dx_db->node_max_hash; + code = PR_2_HTREE_MAX_HASH; + fix_problem(ctx, code, &pctx); + bad_dir++; + } + if (!(dx_db->flags & DX_FLAG_REFERENCED)) { + code = PR_2_HTREE_NOTREF; + fix_problem(ctx, code, &pctx); + bad_dir++; + } else if (dx_db->flags & DX_FLAG_DUP_REF) { + code = PR_2_HTREE_DUPREF; + fix_problem(ctx, code, &pctx); + bad_dir++; + } + } + if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) { + clear_htree(ctx, dx_dir->ino); + dx_dir->numblocks = 0; + } + } + e2fsck_free_dx_dir_info(ctx); +#endif + ext2fs_free_mem(&buf); + ext2fs_free_dblist(fs->dblist); + + if (ctx->inode_bad_map) { + ext2fs_free_inode_bitmap(ctx->inode_bad_map); + ctx->inode_bad_map = 0; + } + if (ctx->inode_reg_map) { + ext2fs_free_inode_bitmap(ctx->inode_reg_map); + ctx->inode_reg_map = 0; + } + + clear_problem_context(&pctx); + if (ctx->large_files) { + if (!(sb->s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_LARGE_FILE) && + fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) { + sb->s_feature_ro_compat |= + EXT2_FEATURE_RO_COMPAT_LARGE_FILE; + fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; + ext2fs_mark_super_dirty(fs); + } + if (sb->s_rev_level == EXT2_GOOD_OLD_REV && + fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) { + ext2fs_update_dynamic_rev(fs); + ext2fs_mark_super_dirty(fs); + } + } + + print_resource_track(ctx, _("Pass 2"), &rtrack, fs->io); +} + +#define MAX_DEPTH 32000 +static int htree_depth(struct dx_dir_info *dx_dir, + struct dx_dirblock_info *dx_db) +{ + int depth = 0; + + while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) { + dx_db = &dx_dir->dx_block[dx_db->parent]; + depth++; + } + return depth; +} + +static int dict_de_cmp(const void *a, const void *b) +{ + const struct ext2_dir_entry *de_a, *de_b; + int a_len, b_len; + + de_a = (const struct ext2_dir_entry *) a; + a_len = de_a->name_len & 0xFF; + de_b = (const struct ext2_dir_entry *) b; + b_len = de_b->name_len & 0xFF; + + if (a_len != b_len) + return (a_len - b_len); + + return strncmp(de_a->name, de_b->name, a_len); +} + +/* + * This is special sort function that makes sure that directory blocks + * with a dirblock of zero are sorted to the beginning of the list. + * This guarantees that the root node of the htree directories are + * processed first, so we know what hash version to use. + */ +static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b) +{ + const struct ext2_db_entry2 *db_a = + (const struct ext2_db_entry2 *) a; + const struct ext2_db_entry2 *db_b = + (const struct ext2_db_entry2 *) b; + + if (db_a->blockcnt && !db_b->blockcnt) + return 1; + + if (!db_a->blockcnt && db_b->blockcnt) + return -1; + + if (db_a->blk != db_b->blk) + return (int) (db_a->blk - db_b->blk); + + if (db_a->ino != db_b->ino) + return (int) (db_a->ino - db_b->ino); + + return (int) (db_a->blockcnt - db_b->blockcnt); +} + + +/* + * Make sure the first entry in the directory is '.', and that the + * directory entry is sane. + */ +static int check_dot(e2fsck_t ctx, + struct ext2_dir_entry *dirent, + ext2_ino_t ino, struct problem_context *pctx) +{ + struct ext2_dir_entry *nextdir; + unsigned int rec_len, new_len; + int status = 0; + int created = 0; + problem_t problem = 0; + + if (!dirent->inode) + problem = PR_2_MISSING_DOT; + else if (((dirent->name_len & 0xFF) != 1) || + (dirent->name[0] != '.')) + problem = PR_2_1ST_NOT_DOT; + else if (dirent->name[1] != '\0') + problem = PR_2_DOT_NULL_TERM; + + (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); + if (problem) { + if (fix_problem(ctx, problem, pctx)) { + if (rec_len < 12) + rec_len = dirent->rec_len = 12; + dirent->inode = ino; + dirent->name_len = 1; + dirent->name[0] = '.'; + dirent->name[1] = '\0'; + status = 1; + created = 1; + } + } + if (dirent->inode != ino) { + if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) { + dirent->inode = ino; + status = 1; + } + } + if (rec_len > 12) { + new_len = rec_len - 12; + if (new_len > 12) { + if (created || + fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) { + nextdir = (struct ext2_dir_entry *) + ((char *) dirent + 12); + dirent->rec_len = 12; + (void) ext2fs_set_rec_len(ctx->fs, new_len, + nextdir); + nextdir->inode = 0; + nextdir->name_len = 0; + status = 1; + } + } + } + return status; +} + +/* + * Make sure the second entry in the directory is '..', and that the + * directory entry is sane. We do not check the inode number of '..' + * here; this gets done in pass 3. + */ +static int check_dotdot(e2fsck_t ctx, + struct ext2_dir_entry *dirent, + ext2_ino_t ino, struct problem_context *pctx) +{ + problem_t problem = 0; + unsigned int rec_len; + + if (!dirent->inode) + problem = PR_2_MISSING_DOT_DOT; + else if (((dirent->name_len & 0xFF) != 2) || + (dirent->name[0] != '.') || + (dirent->name[1] != '.')) + problem = PR_2_2ND_NOT_DOT_DOT; + else if (dirent->name[2] != '\0') + problem = PR_2_DOT_DOT_NULL_TERM; + + (void) ext2fs_get_rec_len(ctx->fs, dirent, &rec_len); + if (problem) { + if (fix_problem(ctx, problem, pctx)) { + if (rec_len < 12) + dirent->rec_len = 12; + /* + * Note: we don't have the parent inode just + * yet, so we will fill it in with the root + * inode. This will get fixed in pass 3. + */ + dirent->inode = EXT2_ROOT_INO; + dirent->name_len = 2; + dirent->name[0] = '.'; + dirent->name[1] = '.'; + dirent->name[2] = '\0'; + return 1; + } + return 0; + } + if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) { + fix_problem(ctx, PR_2_NO_DIRINFO, pctx); + return -1; + } + return 0; +} + +/* + * Check to make sure a directory entry doesn't contain any illegal + * characters. + */ +static int check_name(e2fsck_t ctx, + struct ext2_dir_entry *dirent, + ext2_ino_t dir_ino EXT2FS_ATTR((unused)), + struct problem_context *pctx) +{ + int i; + int fixup = -1; + int ret = 0; + + for ( i = 0; i < (dirent->name_len & 0xFF); i++) { + if (dirent->name[i] == '/' || dirent->name[i] == '\0') { + if (fixup < 0) { + fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx); + } + if (fixup) { + dirent->name[i] = '.'; + ret = 1; + } + } + } + return ret; +} + +/* + * Check the directory filetype (if present) + */ +static _INLINE_ int check_filetype(e2fsck_t ctx, + struct ext2_dir_entry *dirent, + ext2_ino_t dir_ino EXT2FS_ATTR((unused)), + struct problem_context *pctx) +{ + int filetype = dirent->name_len >> 8; + int should_be = EXT2_FT_UNKNOWN; + struct ext2_inode inode; + + if (!(ctx->fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_FILETYPE)) { + if (filetype == 0 || + !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx)) + return 0; + dirent->name_len = dirent->name_len & 0xFF; + return 1; + } + + if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dirent->inode)) { + should_be = EXT2_FT_DIR; + } else if (ext2fs_test_inode_bitmap2(ctx->inode_reg_map, + dirent->inode)) { + should_be = EXT2_FT_REG_FILE; + } else if (ctx->inode_bad_map && + ext2fs_test_inode_bitmap2(ctx->inode_bad_map, + dirent->inode)) + should_be = 0; + else { + e2fsck_read_inode(ctx, dirent->inode, &inode, + "check_filetype"); + should_be = ext2_file_type(inode.i_mode); + } + if (filetype == should_be) + return 0; + pctx->num = should_be; + + if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE, + pctx) == 0) + return 0; + + dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8; + return 1; +} + +#ifdef ENABLE_HTREE +static void parse_int_node(ext2_filsys fs, + struct ext2_db_entry2 *db, + struct check_dir_struct *cd, + struct dx_dir_info *dx_dir, + char *block_buf) +{ + struct ext2_dx_root_info *root; + struct ext2_dx_entry *ent; + struct ext2_dx_countlimit *limit; + struct dx_dirblock_info *dx_db; + int i, expect_limit, count; + blk_t blk; + ext2_dirhash_t min_hash = 0xffffffff; + ext2_dirhash_t max_hash = 0; + ext2_dirhash_t hash = 0, prev_hash; + + if (db->blockcnt == 0) { + root = (struct ext2_dx_root_info *) (block_buf + 24); + +#ifdef DX_DEBUG + printf("Root node dump:\n"); + printf("\t Reserved zero: %u\n", root->reserved_zero); + printf("\t Hash Version: %d\n", root->hash_version); + printf("\t Info length: %d\n", root->info_length); + printf("\t Indirect levels: %d\n", root->indirect_levels); + printf("\t Flags: %d\n", root->unused_flags); +#endif + + ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length); + } else { + ent = (struct ext2_dx_entry *) (block_buf+8); + } + limit = (struct ext2_dx_countlimit *) ent; + +#ifdef DX_DEBUG + printf("Number of entries (count): %d\n", + ext2fs_le16_to_cpu(limit->count)); + printf("Number of entries (limit): %d\n", + ext2fs_le16_to_cpu(limit->limit)); +#endif + + count = ext2fs_le16_to_cpu(limit->count); + expect_limit = (fs->blocksize - ((char *) ent - block_buf)) / + sizeof(struct ext2_dx_entry); + if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) { + cd->pctx.num = ext2fs_le16_to_cpu(limit->limit); + if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx)) + goto clear_and_exit; + } + if (count > expect_limit) { + cd->pctx.num = count; + if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx)) + goto clear_and_exit; + count = expect_limit; + } + + for (i=0; i < count; i++) { + prev_hash = hash; + hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0; +#ifdef DX_DEBUG + printf("Entry #%d: Hash 0x%08x, block %u\n", i, + hash, ext2fs_le32_to_cpu(ent[i].block)); +#endif + blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff; + /* Check to make sure the block is valid */ + if (blk >= (blk_t) dx_dir->numblocks) { + cd->pctx.blk = blk; + if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK, + &cd->pctx)) + goto clear_and_exit; + continue; + } + if (hash < prev_hash && + fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx)) + goto clear_and_exit; + dx_db = &dx_dir->dx_block[blk]; + if (dx_db->flags & DX_FLAG_REFERENCED) { + dx_db->flags |= DX_FLAG_DUP_REF; + } else { + dx_db->flags |= DX_FLAG_REFERENCED; + dx_db->parent = db->blockcnt; + } + if (hash < min_hash) + min_hash = hash; + if (hash > max_hash) + max_hash = hash; + dx_db->node_min_hash = hash; + if ((i+1) < count) + dx_db->node_max_hash = + ext2fs_le32_to_cpu(ent[i+1].hash) & ~1; + else { + dx_db->node_max_hash = 0xfffffffe; + dx_db->flags |= DX_FLAG_LAST; + } + if (i == 0) + dx_db->flags |= DX_FLAG_FIRST; + } +#ifdef DX_DEBUG + printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n", + db->blockcnt, min_hash, max_hash); +#endif + dx_db = &dx_dir->dx_block[db->blockcnt]; + dx_db->min_hash = min_hash; + dx_db->max_hash = max_hash; + return; + +clear_and_exit: + clear_htree(cd->ctx, cd->pctx.ino); + dx_dir->numblocks = 0; +} +#endif /* ENABLE_HTREE */ + +/* + * Given a busted directory, try to salvage it somehow. + * + */ +static void salvage_directory(ext2_filsys fs, + struct ext2_dir_entry *dirent, + struct ext2_dir_entry *prev, + unsigned int *offset) +{ + char *cp = (char *) dirent; + int left; + unsigned int rec_len, prev_rec_len; + unsigned int name_len = dirent->name_len & 0xFF; + + (void) ext2fs_get_rec_len(fs, dirent, &rec_len); + left = fs->blocksize - *offset - rec_len; + + /* + * Special case of directory entry of size 8: copy what's left + * of the directory block up to cover up the invalid hole. + */ + if ((left >= 12) && (rec_len == 8)) { + memmove(cp, cp+8, left); + memset(cp + left, 0, 8); + return; + } + /* + * If the directory entry overruns the end of the directory + * block, and the name is small enough to fit, then adjust the + * record length. + */ + if ((left < 0) && + ((int) rec_len + left > 8) && + ((int) name_len + 8 <= (int) rec_len + left) && + dirent->inode <= fs->super->s_inodes_count && + strnlen(dirent->name, name_len) == name_len) { + (void) ext2fs_set_rec_len(fs, (int) rec_len + left, dirent); + return; + } + /* + * If the record length of the directory entry is a multiple + * of four, and not too big, such that it is valid, let the + * previous directory entry absorb the invalid one. + */ + if (prev && rec_len && (rec_len % 4) == 0 && + (*offset + rec_len <= fs->blocksize)) { + (void) ext2fs_get_rec_len(fs, prev, &prev_rec_len); + prev_rec_len += rec_len; + (void) ext2fs_set_rec_len(fs, prev_rec_len, prev); + *offset += rec_len; + return; + } + /* + * Default salvage method --- kill all of the directory + * entries for the rest of the block. We will either try to + * absorb it into the previous directory entry, or create a + * new empty directory entry the rest of the directory block. + */ + if (prev) { + (void) ext2fs_get_rec_len(fs, prev, &prev_rec_len); + prev_rec_len += fs->blocksize - *offset; + (void) ext2fs_set_rec_len(fs, prev_rec_len, prev); + *offset = fs->blocksize; + } else { + rec_len = fs->blocksize - *offset; + (void) ext2fs_set_rec_len(fs, rec_len, dirent); + dirent->name_len = 0; + dirent->inode = 0; + } +} + +static int check_dir_block(ext2_filsys fs, + struct ext2_db_entry2 *db, + void *priv_data) +{ + struct dx_dir_info *dx_dir; +#ifdef ENABLE_HTREE + struct dx_dirblock_info *dx_db = 0; +#endif /* ENABLE_HTREE */ + struct ext2_dir_entry *dirent, *prev; + ext2_dirhash_t hash; + unsigned int offset = 0; + int dir_modified = 0; + int dot_state; + unsigned int rec_len; + blk64_t block_nr = db->blk; + ext2_ino_t ino = db->ino; + ext2_ino_t subdir_parent; + __u16 links; + struct check_dir_struct *cd; + char *buf; + e2fsck_t ctx; + problem_t problem; + struct ext2_dx_root_info *root; + struct ext2_dx_countlimit *limit; + static dict_t de_dict; + struct problem_context pctx; + int dups_found = 0; + int ret; + + cd = (struct check_dir_struct *) priv_data; + buf = cd->buf; + ctx = cd->ctx; + + if (ctx->flags & E2F_FLAG_SIGNAL_MASK || ctx->flags & E2F_FLAG_RESTART) + return DIRENT_ABORT; + + if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max)) + return DIRENT_ABORT; + + /* + * Make sure the inode is still in use (could have been + * deleted in the duplicate/bad blocks pass. + */ + if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, ino))) + return 0; + + cd->pctx.ino = ino; + cd->pctx.blk = block_nr; + cd->pctx.blkcount = db->blockcnt; + cd->pctx.ino2 = 0; + cd->pctx.dirent = 0; + cd->pctx.num = 0; + + if (db->blk == 0) { + if (allocate_dir_block(ctx, db, buf, &cd->pctx)) + return 0; + block_nr = db->blk; + } + + if (db->blockcnt) + dot_state = 2; + else + dot_state = 0; + + if (ctx->dirs_to_hash && + ext2fs_u32_list_test(ctx->dirs_to_hash, ino)) + dups_found++; + +#if 0 + printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr, + db->blockcnt, ino); +#endif + + ehandler_operation(_("reading directory block")); + cd->pctx.errcode = ext2fs_read_dir_block3(fs, block_nr, buf, 0); + ehandler_operation(0); + if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED) + cd->pctx.errcode = 0; /* We'll handle this ourselves */ + if (cd->pctx.errcode) { + if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) { + ctx->flags |= E2F_FLAG_ABORT; + return DIRENT_ABORT; + } + memset(buf, 0, fs->blocksize); + } +#ifdef ENABLE_HTREE + dx_dir = e2fsck_get_dx_dir_info(ctx, ino); + if (dx_dir && dx_dir->numblocks) { + if (db->blockcnt >= dx_dir->numblocks) { + pctx.dir = ino; + if (fix_problem(ctx, PR_2_UNEXPECTED_HTREE_BLOCK, + &pctx)) { + clear_htree(ctx, ino); + dx_dir->numblocks = 0; + dx_db = 0; + goto out_htree; + } + fatal_error(ctx, _("Can not continue.")); + } + dx_db = &dx_dir->dx_block[db->blockcnt]; + dx_db->type = DX_DIRBLOCK_LEAF; + dx_db->phys = block_nr; + dx_db->min_hash = ~0; + dx_db->max_hash = 0; + + dirent = (struct ext2_dir_entry *) buf; + (void) ext2fs_get_rec_len(fs, dirent, &rec_len); + limit = (struct ext2_dx_countlimit *) (buf+8); + if (db->blockcnt == 0) { + root = (struct ext2_dx_root_info *) (buf + 24); + dx_db->type = DX_DIRBLOCK_ROOT; + dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST; + if ((root->reserved_zero || + root->info_length < 8 || + root->indirect_levels > 1) && + fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) { + clear_htree(ctx, ino); + dx_dir->numblocks = 0; + dx_db = 0; + } + dx_dir->hashversion = root->hash_version; + if ((dx_dir->hashversion <= EXT2_HASH_TEA) && + (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) + dx_dir->hashversion += 3; + dx_dir->depth = root->indirect_levels + 1; + } else if ((dirent->inode == 0) && + (rec_len == fs->blocksize) && + (dirent->name_len == 0) && + (ext2fs_le16_to_cpu(limit->limit) == + ((fs->blocksize-8) / + sizeof(struct ext2_dx_entry)))) + dx_db->type = DX_DIRBLOCK_NODE; + } +out_htree: +#endif /* ENABLE_HTREE */ + + dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp); + prev = 0; + do { + dgrp_t group; + ext2_ino_t first_unused_inode; + + problem = 0; + dirent = (struct ext2_dir_entry *) (buf + offset); + (void) ext2fs_get_rec_len(fs, dirent, &rec_len); + cd->pctx.dirent = dirent; + cd->pctx.num = offset; + if (((offset + rec_len) > fs->blocksize) || + (rec_len < 12) || + ((rec_len % 4) != 0) || + (((dirent->name_len & (unsigned) 0xFF)+8) > rec_len)) { + if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) { + salvage_directory(fs, dirent, prev, &offset); + dir_modified++; + continue; + } else + goto abort_free_dict; + } + + if (dot_state == 0) { + if (check_dot(ctx, dirent, ino, &cd->pctx)) + dir_modified++; + } else if (dot_state == 1) { + ret = check_dotdot(ctx, dirent, ino, &cd->pctx); + if (ret < 0) + goto abort_free_dict; + if (ret) + dir_modified++; + } else if (dirent->inode == ino) { + problem = PR_2_LINK_DOT; + if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) { + dirent->inode = 0; + dir_modified++; + goto next; + } + } + if (!dirent->inode) + goto next; + + /* + * Make sure the inode listed is a legal one. + */ + if (((dirent->inode != EXT2_ROOT_INO) && + (dirent->inode < EXT2_FIRST_INODE(fs->super))) || + (dirent->inode > fs->super->s_inodes_count)) { + problem = PR_2_BAD_INO; + } else if (ctx->inode_bb_map && + (ext2fs_test_inode_bitmap2(ctx->inode_bb_map, + dirent->inode))) { + /* + * If the inode is in a bad block, offer to + * clear it. + */ + problem = PR_2_BB_INODE; + } else if ((dot_state > 1) && + ((dirent->name_len & 0xFF) == 1) && + (dirent->name[0] == '.')) { + /* + * If there's a '.' entry in anything other + * than the first directory entry, it's a + * duplicate entry that should be removed. + */ + problem = PR_2_DUP_DOT; + } else if ((dot_state > 1) && + ((dirent->name_len & 0xFF) == 2) && + (dirent->name[0] == '.') && + (dirent->name[1] == '.')) { + /* + * If there's a '..' entry in anything other + * than the second directory entry, it's a + * duplicate entry that should be removed. + */ + problem = PR_2_DUP_DOT_DOT; + } else if ((dot_state > 1) && + (dirent->inode == EXT2_ROOT_INO)) { + /* + * Don't allow links to the root directory. + * We check this specially to make sure we + * catch this error case even if the root + * directory hasn't been created yet. + */ + problem = PR_2_LINK_ROOT; + } else if ((dot_state > 1) && + (dirent->name_len & 0xFF) == 0) { + /* + * Don't allow zero-length directory names. + */ + problem = PR_2_NULL_NAME; + } + + if (problem) { + if (fix_problem(ctx, problem, &cd->pctx)) { + dirent->inode = 0; + dir_modified++; + goto next; + } else { + ext2fs_unmark_valid(fs); + if (problem == PR_2_BAD_INO) + goto next; + } + } + + /* + * If the inode was marked as having bad fields in + * pass1, process it and offer to fix/clear it. + * (We wait until now so that we can display the + * pathname to the user.) + */ + if (ctx->inode_bad_map && + ext2fs_test_inode_bitmap2(ctx->inode_bad_map, + dirent->inode)) { + if (e2fsck_process_bad_inode(ctx, ino, + dirent->inode, + buf + fs->blocksize)) { + dirent->inode = 0; + dir_modified++; + goto next; + } + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return DIRENT_ABORT; + } + + group = ext2fs_group_of_ino(fs, dirent->inode); + first_unused_inode = group * fs->super->s_inodes_per_group + + 1 + fs->super->s_inodes_per_group - + ext2fs_bg_itable_unused(fs, group); + cd->pctx.group = group; + + /* + * Check if the inode was missed out because + * _INODE_UNINIT flag was set or bg_itable_unused was + * incorrect. If so, clear the _INODE_UNINIT flag and + * restart e2fsck. In the future it would be nice if + * we could call a function in pass1.c that checks the + * newly visible inodes. + */ + if (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT)) { + pctx.num = dirent->inode; + if (fix_problem(ctx, PR_2_INOREF_BG_INO_UNINIT, + &cd->pctx)){ + ext2fs_bg_flags_clear(fs, group, + EXT2_BG_INODE_UNINIT); + ext2fs_mark_super_dirty(fs); + ctx->flags |= E2F_FLAG_RESTART_LATER; + } else { + ext2fs_unmark_valid(fs); + if (problem == PR_2_BAD_INO) + goto next; + } + } else if (dirent->inode >= first_unused_inode) { + pctx.num = dirent->inode; + if (fix_problem(ctx, PR_2_INOREF_IN_UNUSED, &cd->pctx)){ + ext2fs_bg_itable_unused_set(fs, group, 0); + ext2fs_mark_super_dirty(fs); + ctx->flags |= E2F_FLAG_RESTART_LATER; + } else { + ext2fs_unmark_valid(fs); + if (problem == PR_2_BAD_INO) + goto next; + } + } + + /* + * Offer to clear unused inodes; if we are going to be + * restarting the scan due to bg_itable_unused being + * wrong, then don't clear any inodes to avoid zapping + * inodes that were skipped during pass1 due to an + * incorrect bg_itable_unused; we'll get any real + * problems after we restart. + */ + if (!(ctx->flags & E2F_FLAG_RESTART_LATER) && + !(ext2fs_test_inode_bitmap2(ctx->inode_used_map, + dirent->inode))) + problem = PR_2_UNUSED_INODE; + + if (problem) { + if (fix_problem(ctx, problem, &cd->pctx)) { + dirent->inode = 0; + dir_modified++; + goto next; + } else { + ext2fs_unmark_valid(fs); + if (problem == PR_2_BAD_INO) + goto next; + } + } + + if (check_name(ctx, dirent, ino, &cd->pctx)) + dir_modified++; + + if (check_filetype(ctx, dirent, ino, &cd->pctx)) + dir_modified++; + +#ifdef ENABLE_HTREE + if (dx_db) { + ext2fs_dirhash(dx_dir->hashversion, dirent->name, + (dirent->name_len & 0xFF), + fs->super->s_hash_seed, &hash, 0); + if (hash < dx_db->min_hash) + dx_db->min_hash = hash; + if (hash > dx_db->max_hash) + dx_db->max_hash = hash; + } +#endif + + /* + * If this is a directory, then mark its parent in its + * dir_info structure. If the parent field is already + * filled in, then this directory has more than one + * hard link. We assume the first link is correct, + * and ask the user if he/she wants to clear this one. + */ + if ((dot_state > 1) && + (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, + dirent->inode))) { + if (e2fsck_dir_info_get_parent(ctx, dirent->inode, + &subdir_parent)) { + cd->pctx.ino = dirent->inode; + fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx); + goto abort_free_dict; + } + if (subdir_parent) { + cd->pctx.ino2 = subdir_parent; + if (fix_problem(ctx, PR_2_LINK_DIR, + &cd->pctx)) { + dirent->inode = 0; + dir_modified++; + goto next; + } + cd->pctx.ino2 = 0; + } else { + (void) e2fsck_dir_info_set_parent(ctx, + dirent->inode, ino); + } + } + + if (dups_found) { + ; + } else if (dict_lookup(&de_dict, dirent)) { + clear_problem_context(&pctx); + pctx.ino = ino; + pctx.dirent = dirent; + fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx); + if (!ctx->dirs_to_hash) + ext2fs_u32_list_create(&ctx->dirs_to_hash, 50); + if (ctx->dirs_to_hash) + ext2fs_u32_list_add(ctx->dirs_to_hash, ino); + dups_found++; + } else + dict_alloc_insert(&de_dict, dirent, dirent); + + ext2fs_icount_increment(ctx->inode_count, dirent->inode, + &links); + if (links > 1) + ctx->fs_links_count++; + ctx->fs_total_count++; + next: + prev = dirent; + if (dir_modified) + (void) ext2fs_get_rec_len(fs, dirent, &rec_len); + offset += rec_len; + dot_state++; + } while (offset < fs->blocksize); +#if 0 + printf("\n"); +#endif +#ifdef ENABLE_HTREE + if (dx_db) { +#ifdef DX_DEBUG + printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n", + db->blockcnt, dx_db->type, + dx_db->min_hash, dx_db->max_hash); +#endif + cd->pctx.dir = cd->pctx.ino; + if ((dx_db->type == DX_DIRBLOCK_ROOT) || + (dx_db->type == DX_DIRBLOCK_NODE)) + parse_int_node(fs, db, cd, dx_dir, buf); + } +#endif /* ENABLE_HTREE */ + if (offset != fs->blocksize) { + cd->pctx.num = rec_len - fs->blocksize + offset; + if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) { + dirent->rec_len = cd->pctx.num; + dir_modified++; + } + } + if (dir_modified) { + cd->pctx.errcode = ext2fs_write_dir_block3(fs, block_nr, buf, 0); + if (cd->pctx.errcode) { + if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK, + &cd->pctx)) + goto abort_free_dict; + } + ext2fs_mark_changed(fs); + } + dict_free_nodes(&de_dict); + return 0; +abort_free_dict: + ctx->flags |= E2F_FLAG_ABORT; + dict_free_nodes(&de_dict); + return DIRENT_ABORT; +} + +struct del_block { + e2fsck_t ctx; + e2_blkcnt_t num; +}; + +/* + * This function is called to deallocate a block, and is an interator + * functioned called by deallocate inode via ext2fs_iterate_block(). + */ +static int deallocate_inode_block(ext2_filsys fs, + blk64_t *block_nr, + e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct del_block *p = priv_data; + + if (HOLE_BLKADDR(*block_nr)) + return 0; + if ((*block_nr < fs->super->s_first_data_block) || + (*block_nr >= ext2fs_blocks_count(fs->super))) + return 0; + if ((*block_nr % EXT2FS_CLUSTER_RATIO(fs)) == 0) + ext2fs_block_alloc_stats2(fs, *block_nr, -1); + p->num++; + return 0; +} + +/* + * This fuction deallocates an inode + */ +static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) +{ + ext2_filsys fs = ctx->fs; + struct ext2_inode inode; + struct problem_context pctx; + __u32 count; + struct del_block del_block; + + e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); + clear_problem_context(&pctx); + pctx.ino = ino; + + /* + * Fix up the bitmaps... + */ + e2fsck_read_bitmaps(ctx); + ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); + + if (ext2fs_file_acl_block(fs, &inode) && + (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { + pctx.errcode = ext2fs_adjust_ea_refcount2(fs, + ext2fs_file_acl_block(fs, &inode), + block_buf, -1, &count); + if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { + pctx.errcode = 0; + count = 1; + } + if (pctx.errcode) { + pctx.blk = ext2fs_file_acl_block(fs, &inode); + fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + if (count == 0) { + ext2fs_block_alloc_stats2(fs, + ext2fs_file_acl_block(fs, &inode), -1); + } + ext2fs_file_acl_block_set(fs, &inode, 0); + } + + if (!ext2fs_inode_has_valid_blocks2(fs, &inode)) + goto clear_inode; + + if (LINUX_S_ISREG(inode.i_mode) && + ext2fs_needs_large_file_feature(EXT2_I_SIZE(&inode))) + ctx->large_files--; + + del_block.ctx = ctx; + del_block.num = 0; + pctx.errcode = ext2fs_block_iterate3(fs, ino, 0, block_buf, + deallocate_inode_block, + &del_block); + if (pctx.errcode) { + fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } +clear_inode: + /* Inode may have changed by block_iterate, so reread it */ + e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); + e2fsck_clear_inode(ctx, ino, &inode, 0, "deallocate_inode"); +} + +/* + * This fuction clears the htree flag on an inode + */ +static void clear_htree(e2fsck_t ctx, ext2_ino_t ino) +{ + struct ext2_inode inode; + + e2fsck_read_inode(ctx, ino, &inode, "clear_htree"); + inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL; + e2fsck_write_inode(ctx, ino, &inode, "clear_htree"); + if (ctx->dirs_to_hash) + ext2fs_u32_list_add(ctx->dirs_to_hash, ino); +} + + +int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, + ext2_ino_t ino, char *buf) +{ + ext2_filsys fs = ctx->fs; + struct ext2_inode inode; + int inode_modified = 0; + int not_fixed = 0; + unsigned char *frag, *fsize; + struct problem_context pctx; + problem_t problem = 0; + + e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); + + clear_problem_context(&pctx); + pctx.ino = ino; + pctx.dir = dir; + pctx.inode = &inode; + + if (ext2fs_file_acl_block(fs, &inode) && + !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { + if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) { + ext2fs_file_acl_block_set(fs, &inode, 0); + inode_modified++; + } else + not_fixed++; + } + + if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) && + !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) && + !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) && + !(LINUX_S_ISSOCK(inode.i_mode))) + problem = PR_2_BAD_MODE; + else if (LINUX_S_ISCHR(inode.i_mode) + && !e2fsck_pass1_check_device_inode(fs, &inode)) + problem = PR_2_BAD_CHAR_DEV; + else if (LINUX_S_ISBLK(inode.i_mode) + && !e2fsck_pass1_check_device_inode(fs, &inode)) + problem = PR_2_BAD_BLOCK_DEV; + else if (LINUX_S_ISFIFO(inode.i_mode) + && !e2fsck_pass1_check_device_inode(fs, &inode)) + problem = PR_2_BAD_FIFO; + else if (LINUX_S_ISSOCK(inode.i_mode) + && !e2fsck_pass1_check_device_inode(fs, &inode)) + problem = PR_2_BAD_SOCKET; + else if (LINUX_S_ISLNK(inode.i_mode) + && !e2fsck_pass1_check_symlink(fs, ino, &inode, buf)) { + problem = PR_2_INVALID_SYMLINK; + } + + if (problem) { + if (fix_problem(ctx, problem, &pctx)) { + deallocate_inode(ctx, ino, 0); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return 0; + return 1; + } else + not_fixed++; + problem = 0; + } + + if (inode.i_faddr) { + if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) { + inode.i_faddr = 0; + inode_modified++; + } else + not_fixed++; + } + + switch (fs->super->s_creator_os) { + case EXT2_OS_HURD: + frag = &inode.osd2.hurd2.h_i_frag; + fsize = &inode.osd2.hurd2.h_i_fsize; + break; + default: + frag = fsize = 0; + } + if (frag && *frag) { + pctx.num = *frag; + if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) { + *frag = 0; + inode_modified++; + } else + not_fixed++; + pctx.num = 0; + } + if (fsize && *fsize) { + pctx.num = *fsize; + if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) { + *fsize = 0; + inode_modified++; + } else + not_fixed++; + pctx.num = 0; + } + + if ((fs->super->s_creator_os == EXT2_OS_LINUX) && + !(fs->super->s_feature_ro_compat & + EXT4_FEATURE_RO_COMPAT_HUGE_FILE) && + (inode.osd2.linux2.l_i_blocks_hi != 0)) { + pctx.num = inode.osd2.linux2.l_i_blocks_hi; + if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) { + inode.osd2.linux2.l_i_blocks_hi = 0; + inode_modified++; + } + } + + if ((fs->super->s_creator_os == EXT2_OS_LINUX) && + !(fs->super->s_feature_incompat & + EXT4_FEATURE_INCOMPAT_64BIT) && + inode.osd2.linux2.l_i_file_acl_high != 0) { + pctx.num = inode.osd2.linux2.l_i_file_acl_high; + if (fix_problem(ctx, PR_2_I_FILE_ACL_HI_ZERO, &pctx)) { + inode.osd2.linux2.l_i_file_acl_high = 0; + inode_modified++; + } else + not_fixed++; + } + + if (ext2fs_file_acl_block(fs, &inode) && + ((ext2fs_file_acl_block(fs, &inode) < fs->super->s_first_data_block) || + (ext2fs_file_acl_block(fs, &inode) >= ext2fs_blocks_count(fs->super)))) { + if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) { + ext2fs_file_acl_block_set(fs, &inode, 0); + inode_modified++; + } else + not_fixed++; + } + if (inode.i_dir_acl && + LINUX_S_ISDIR(inode.i_mode)) { + if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) { + inode.i_dir_acl = 0; + inode_modified++; + } else + not_fixed++; + } + + if (inode_modified) + e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); + if (!not_fixed && ctx->inode_bad_map) + ext2fs_unmark_inode_bitmap2(ctx->inode_bad_map, ino); + return 0; +} + + +/* + * allocate_dir_block --- this function allocates a new directory + * block for a particular inode; this is done if a directory has + * a "hole" in it, or if a directory has a illegal block number + * that was zeroed out and now needs to be replaced. + */ +static int allocate_dir_block(e2fsck_t ctx, + struct ext2_db_entry2 *db, + char *buf EXT2FS_ATTR((unused)), + struct problem_context *pctx) +{ + ext2_filsys fs = ctx->fs; + blk64_t blk = 0; + char *block; + struct ext2_inode inode; + + if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0) + return 1; + + /* + * Read the inode and block bitmaps in; we'll be messing with + * them. + */ + e2fsck_read_bitmaps(ctx); + + /* + * First, find a free block + */ + e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block"); + pctx->errcode = ext2fs_map_cluster_block(fs, db->ino, &inode, + db->blockcnt, &blk); + if (pctx->errcode || blk == 0) { + pctx->errcode = ext2fs_new_block2(fs, 0, + ctx->block_found_map, &blk); + if (pctx->errcode) { + pctx->str = "ext2fs_new_block"; + fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); + return 1; + } + } + ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); + ext2fs_mark_block_bitmap2(fs->block_map, blk); + ext2fs_mark_bb_dirty(fs); + + /* + * Now let's create the actual data block for the inode + */ + if (db->blockcnt) + pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block); + else + pctx->errcode = ext2fs_new_dir_block(fs, db->ino, + EXT2_ROOT_INO, &block); + + if (pctx->errcode) { + pctx->str = "ext2fs_new_dir_block"; + fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); + return 1; + } + + pctx->errcode = ext2fs_write_dir_block3(fs, blk, block, 0); + ext2fs_free_mem(&block); + if (pctx->errcode) { + pctx->str = "ext2fs_write_dir_block"; + fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); + return 1; + } + + /* + * Update the inode block count + */ + ext2fs_iblk_add_blocks(fs, &inode, 1); + if (EXT2_I_SIZE(&inode) < (db->blockcnt+1) * fs->blocksize) { + pctx->errcode = ext2fs_inode_size_set(fs, &inode, + (db->blockcnt+1) * fs->blocksize); + if (pctx->errcode) { + pctx->str = "ext2fs_inode_size_set"; + fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); + return 1; + } + } + e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block"); + + /* + * Finally, update the block pointers for the inode + */ + db->blk = blk; + pctx->errcode = ext2fs_bmap2(fs, db->ino, &inode, 0, BMAP_SET, + db->blockcnt, 0, &blk); + if (pctx->errcode) { + pctx->str = "ext2fs_block_iterate"; + fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); + return 1; + } + + return 0; +}
diff --git a/e2fsck/pass3.c b/e2fsck/pass3.c new file mode 100644 index 0000000..0274213 --- /dev/null +++ b/e2fsck/pass3.c
@@ -0,0 +1,840 @@ +/* + * pass3.c -- pass #3 of e2fsck: Check for directory connectivity + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * Pass #3 assures that all directories are connected to the + * filesystem tree, using the following algorithm: + * + * First, the root directory is checked to make sure it exists; if + * not, e2fsck will offer to create a new one. It is then marked as + * "done". + * + * Then, pass3 interates over all directory inodes; for each directory + * it attempts to trace up the filesystem tree, using dirinfo.parent + * until it reaches a directory which has been marked "done". If it + * can not do so, then the directory must be disconnected, and e2fsck + * will offer to reconnect it to /lost+found. While it is chasing + * parent pointers up the filesystem tree, if pass3 sees a directory + * twice, then it has detected a filesystem loop, and it will again + * offer to reconnect the directory to /lost+found in to break the + * filesystem loop. + * + * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to + * reconnect inodes to /lost+found; this subroutine is also used by + * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which + * is responsible for creating /lost+found if it does not exist. + * + * Pass 3 frees the following data structures: + * - The dirinfo directory information cache. + */ + +#include "config.h" +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#include "e2fsck.h" +#include "problem.h" + +static void check_root(e2fsck_t ctx); +static int check_directory(e2fsck_t ctx, ext2_ino_t ino, + struct problem_context *pctx); +static void fix_dotdot(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent); + +static ext2fs_inode_bitmap inode_loop_detect = 0; +static ext2fs_inode_bitmap inode_done_map = 0; + +void e2fsck_pass3(e2fsck_t ctx) +{ + ext2_filsys fs = ctx->fs; + struct dir_info_iter *iter = NULL; +#ifdef RESOURCE_TRACK + struct resource_track rtrack; +#endif + struct problem_context pctx; + struct dir_info *dir; + unsigned long maxdirs, count; + + init_resource_track(&rtrack, ctx->fs->io); + clear_problem_context(&pctx); + +#ifdef MTRACE + mtrace_print("Pass 3"); +#endif + + if (!(ctx->options & E2F_OPT_PREEN)) + fix_problem(ctx, PR_3_PASS_HEADER, &pctx); + + /* + * Allocate some bitmaps to do loop detection. + */ + pctx.errcode = e2fsck_allocate_inode_bitmap(fs, _("inode done bitmap"), + EXT2FS_BMAP64_AUTODIR, + "inode_done_map", &inode_done_map); + if (pctx.errcode) { + pctx.num = 2; + fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + goto abort_exit; + } + print_resource_track(ctx, _("Peak memory"), &ctx->global_rtrack, NULL); + + check_root(ctx); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + goto abort_exit; + + ext2fs_mark_inode_bitmap2(inode_done_map, EXT2_ROOT_INO); + + maxdirs = e2fsck_get_num_dirinfo(ctx); + count = 1; + + if (ctx->progress) + if ((ctx->progress)(ctx, 3, 0, maxdirs)) + goto abort_exit; + + iter = e2fsck_dir_info_iter_begin(ctx); + while ((dir = e2fsck_dir_info_iter(ctx, iter)) != 0) { + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + goto abort_exit; + if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs)) + goto abort_exit; + if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, dir->ino)) + if (check_directory(ctx, dir->ino, &pctx)) + goto abort_exit; + } + + /* + * Force the creation of /lost+found if not present + */ + if ((ctx->options & E2F_OPT_READONLY) == 0) + e2fsck_get_lost_and_found(ctx, 1); + + /* + * If there are any directories that need to be indexed or + * optimized, do it here. + */ + e2fsck_rehash_directories(ctx); + +abort_exit: + if (iter) + e2fsck_dir_info_iter_end(ctx, iter); + e2fsck_free_dir_info(ctx); + if (inode_loop_detect) { + ext2fs_free_inode_bitmap(inode_loop_detect); + inode_loop_detect = 0; + } + if (inode_done_map) { + ext2fs_free_inode_bitmap(inode_done_map); + inode_done_map = 0; + } + + if (ctx->lnf_repair_block) { + ext2fs_unmark_block_bitmap2(ctx->block_found_map, + ctx->lnf_repair_block); + ctx->lnf_repair_block = 0; + } + if (ctx->root_repair_block) { + ext2fs_unmark_block_bitmap2(ctx->block_found_map, + ctx->root_repair_block); + ctx->root_repair_block = 0; + } + + print_resource_track(ctx, _("Pass 3"), &rtrack, ctx->fs->io); +} + +/* + * This makes sure the root inode is present; if not, we ask if the + * user wants us to create it. Not creating it is a fatal error. + */ +static void check_root(e2fsck_t ctx) +{ + ext2_filsys fs = ctx->fs; + blk64_t blk; + struct ext2_inode inode; + char * block; + struct problem_context pctx; + + clear_problem_context(&pctx); + + if (ext2fs_test_inode_bitmap2(ctx->inode_used_map, EXT2_ROOT_INO)) { + /* + * If the root inode is not a directory, die here. The + * user must have answered 'no' in pass1 when we + * offered to clear it. + */ + if (!(ext2fs_test_inode_bitmap2(ctx->inode_dir_map, + EXT2_ROOT_INO))) { + fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + } + return; + } + + if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) { + fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + + e2fsck_read_bitmaps(ctx); + + /* + * First, find a free block + */ + if (ctx->root_repair_block) { + blk = ctx->root_repair_block; + ctx->root_repair_block = 0; + goto skip_new_block; + } + pctx.errcode = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk); + if (pctx.errcode) { + pctx.str = "ext2fs_new_block"; + fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); +skip_new_block: + ext2fs_mark_block_bitmap2(fs->block_map, blk); + ext2fs_mark_bb_dirty(fs); + + /* + * Now let's create the actual data block for the inode + */ + pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, + &block); + if (pctx.errcode) { + pctx.str = "ext2fs_new_dir_block"; + fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + + pctx.errcode = ext2fs_write_dir_block3(fs, blk, block, 0); + if (pctx.errcode) { + pctx.str = "ext2fs_write_dir_block3"; + fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + ext2fs_free_mem(&block); + + /* + * Set up the inode structure + */ + memset(&inode, 0, sizeof(inode)); + inode.i_mode = 040755; + inode.i_size = fs->blocksize; + inode.i_atime = inode.i_ctime = inode.i_mtime = ctx->now; + inode.i_links_count = 2; + ext2fs_iblk_set(fs, &inode, 1); + inode.i_block[0] = blk; + + /* + * Write out the inode. + */ + pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode); + if (pctx.errcode) { + pctx.str = "ext2fs_write_inode"; + fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + return; + } + + /* + * Miscellaneous bookkeeping... + */ + e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO); + ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2); + ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2); + + ext2fs_mark_inode_bitmap2(ctx->inode_used_map, EXT2_ROOT_INO); + ext2fs_mark_inode_bitmap2(ctx->inode_dir_map, EXT2_ROOT_INO); + ext2fs_mark_inode_bitmap2(fs->inode_map, EXT2_ROOT_INO); + ext2fs_mark_ib_dirty(fs); +} + +/* + * This subroutine is responsible for making sure that a particular + * directory is connected to the root; if it isn't we trace it up as + * far as we can go, and then offer to connect the resulting parent to + * the lost+found. We have to do loop detection; if we ever discover + * a loop, we treat that as a disconnected directory and offer to + * reparent it to lost+found. + * + * However, loop detection is expensive, because for very large + * filesystems, the inode_loop_detect bitmap is huge, and clearing it + * is non-trivial. Loops in filesystems are also a rare error case, + * and we shouldn't optimize for error cases. So we try two passes of + * the algorithm. The first time, we ignore loop detection and merely + * increment a counter; if the counter exceeds some extreme threshold, + * then we try again with the loop detection bitmap enabled. + */ +static int check_directory(e2fsck_t ctx, ext2_ino_t dir, + struct problem_context *pctx) +{ + ext2_filsys fs = ctx->fs; + ext2_ino_t ino = dir, parent; + int loop_pass = 0, parent_count = 0; + + while (1) { + /* + * Mark this inode as being "done"; by the time we + * return from this function, the inode we either be + * verified as being connected to the directory tree, + * or we will have offered to reconnect this to + * lost+found. + * + * If it was marked done already, then we've reached a + * parent we've already checked. + */ + if (ext2fs_mark_inode_bitmap2(inode_done_map, ino)) + break; + + if (e2fsck_dir_info_get_parent(ctx, ino, &parent)) { + fix_problem(ctx, PR_3_NO_DIRINFO, pctx); + return 0; + } + + /* + * If this directory doesn't have a parent, or we've + * seen the parent once already, then offer to + * reparent it to lost+found + */ + if (!parent || + (loop_pass && + (ext2fs_test_inode_bitmap2(inode_loop_detect, + parent)))) { + pctx->ino = ino; + if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) { + if (e2fsck_reconnect_file(ctx, pctx->ino)) + ext2fs_unmark_valid(fs); + else { + fix_dotdot(ctx, pctx->ino, + ctx->lost_and_found); + parent = ctx->lost_and_found; + } + } + break; + } + ino = parent; + if (loop_pass) { + ext2fs_mark_inode_bitmap2(inode_loop_detect, ino); + } else if (parent_count++ > 2048) { + /* + * If we've run into a path depth that's + * greater than 2048, try again with the inode + * loop bitmap turned on and start from the + * top. + */ + loop_pass = 1; + if (inode_loop_detect) + ext2fs_clear_inode_bitmap(inode_loop_detect); + else { + pctx->errcode = e2fsck_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), EXT2FS_BMAP64_AUTODIR, "inode_loop_detect", &inode_loop_detect); + if (pctx->errcode) { + pctx->num = 1; + fix_problem(ctx, + PR_3_ALLOCATE_IBITMAP_ERROR, pctx); + ctx->flags |= E2F_FLAG_ABORT; + return -1; + } + } + ino = dir; + } + } + + /* + * Make sure that .. and the parent directory are the same; + * offer to fix it if not. + */ + pctx->ino = dir; + if (e2fsck_dir_info_get_dotdot(ctx, dir, &pctx->ino2) || + e2fsck_dir_info_get_parent(ctx, dir, &pctx->dir)) { + fix_problem(ctx, PR_3_NO_DIRINFO, pctx); + return 0; + } + if (pctx->ino2 != pctx->dir) { + if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx)) + fix_dotdot(ctx, dir, pctx->dir); + } + return 0; +} + +/* + * This routine gets the lost_and_found inode, making it a directory + * if necessary + */ +ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix) +{ + ext2_filsys fs = ctx->fs; + ext2_ino_t ino; + blk64_t blk; + errcode_t retval; + struct ext2_inode inode; + char * block; + static const char name[] = "lost+found"; + struct problem_context pctx; + + if (ctx->lost_and_found) + return ctx->lost_and_found; + + clear_problem_context(&pctx); + + retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, + sizeof(name)-1, 0, &ino); + if (retval && !fix) + return 0; + if (!retval) { + if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, ino)) { + ctx->lost_and_found = ino; + return ino; + } + + /* Lost+found isn't a directory! */ + if (!fix) + return 0; + pctx.ino = ino; + if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx)) + return 0; + + /* OK, unlink the old /lost+found file. */ + pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0); + if (pctx.errcode) { + pctx.str = "ext2fs_unlink"; + fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); + return 0; + } + (void) e2fsck_dir_info_set_parent(ctx, ino, 0); + e2fsck_adjust_inode_count(ctx, ino, -1); + } else if (retval != EXT2_ET_FILE_NOT_FOUND) { + pctx.errcode = retval; + fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx); + } + if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0)) + return 0; + + /* + * Read the inode and block bitmaps in; we'll be messing with + * them. + */ + e2fsck_read_bitmaps(ctx); + + /* + * First, find a free block + */ + if (ctx->lnf_repair_block) { + blk = ctx->lnf_repair_block; + ctx->lnf_repair_block = 0; + goto skip_new_block; + } + retval = ext2fs_new_block2(fs, 0, ctx->block_found_map, &blk); + if (retval) { + pctx.errcode = retval; + fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx); + return 0; + } + ext2fs_mark_block_bitmap2(ctx->block_found_map, blk); +skip_new_block: + ext2fs_block_alloc_stats2(fs, blk, +1); + + /* + * Next find a free inode. + */ + retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700, + ctx->inode_used_map, &ino); + if (retval) { + pctx.errcode = retval; + fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx); + return 0; + } + ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino); + ext2fs_mark_inode_bitmap2(ctx->inode_dir_map, ino); + ext2fs_inode_alloc_stats2(fs, ino, +1, 1); + + /* + * Now let's create the actual data block for the inode + */ + retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block); + if (retval) { + pctx.errcode = retval; + fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx); + return 0; + } + + retval = ext2fs_write_dir_block3(fs, blk, block, 0); + ext2fs_free_mem(&block); + if (retval) { + pctx.errcode = retval; + fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx); + return 0; + } + + /* + * Set up the inode structure + */ + memset(&inode, 0, sizeof(inode)); + inode.i_mode = 040700; + inode.i_size = fs->blocksize; + inode.i_atime = inode.i_ctime = inode.i_mtime = ctx->now; + inode.i_links_count = 2; + ext2fs_iblk_set(fs, &inode, 1); + inode.i_block[0] = blk; + + /* + * Next, write out the inode. + */ + pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode); + if (pctx.errcode) { + pctx.str = "ext2fs_write_inode"; + fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); + return 0; + } + /* + * Finally, create the directory link + */ + pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR); + if (pctx.errcode) { + pctx.str = "ext2fs_link"; + fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); + return 0; + } + + /* + * Miscellaneous bookkeeping that needs to be kept straight. + */ + e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO); + e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1); + ext2fs_icount_store(ctx->inode_count, ino, 2); + ext2fs_icount_store(ctx->inode_link_info, ino, 2); + ctx->lost_and_found = ino; + quota_data_add(ctx->qctx, &inode, ino, fs->blocksize); + quota_data_inodes(ctx->qctx, &inode, ino, +1); +#if 0 + printf("/lost+found created; inode #%lu\n", ino); +#endif + return ino; +} + +/* + * This routine will connect a file to lost+found + */ +int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino) +{ + ext2_filsys fs = ctx->fs; + errcode_t retval; + char name[80]; + struct problem_context pctx; + struct ext2_inode inode; + int file_type = 0; + + clear_problem_context(&pctx); + pctx.ino = ino; + + if (!ctx->bad_lost_and_found && !ctx->lost_and_found) { + if (e2fsck_get_lost_and_found(ctx, 1) == 0) + ctx->bad_lost_and_found++; + } + if (ctx->bad_lost_and_found) { + fix_problem(ctx, PR_3_NO_LPF, &pctx); + return 1; + } + + sprintf(name, "#%u", ino); + if (ext2fs_read_inode(fs, ino, &inode) == 0) + file_type = ext2_file_type(inode.i_mode); + retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type); + if (retval == EXT2_ET_DIR_NO_SPACE) { + if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx)) + return 1; + retval = e2fsck_expand_directory(ctx, ctx->lost_and_found, + 1, 0); + if (retval) { + pctx.errcode = retval; + fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx); + return 1; + } + retval = ext2fs_link(fs, ctx->lost_and_found, name, + ino, file_type); + } + if (retval) { + pctx.errcode = retval; + fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx); + return 1; + } + e2fsck_adjust_inode_count(ctx, ino, 1); + + return 0; +} + +/* + * Utility routine to adjust the inode counts on an inode. + */ +errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj) +{ + ext2_filsys fs = ctx->fs; + errcode_t retval; + struct ext2_inode inode; + + if (!ino) + return 0; + + retval = ext2fs_read_inode(fs, ino, &inode); + if (retval) + return retval; + +#if 0 + printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj, + inode.i_links_count); +#endif + + if (adj == 1) { + ext2fs_icount_increment(ctx->inode_count, ino, 0); + if (inode.i_links_count == (__u16) ~0) + return 0; + ext2fs_icount_increment(ctx->inode_link_info, ino, 0); + inode.i_links_count++; + } else if (adj == -1) { + ext2fs_icount_decrement(ctx->inode_count, ino, 0); + if (inode.i_links_count == 0) + return 0; + ext2fs_icount_decrement(ctx->inode_link_info, ino, 0); + inode.i_links_count--; + } + + retval = ext2fs_write_inode(fs, ino, &inode); + if (retval) + return retval; + + return 0; +} + +/* + * Fix parent --- this routine fixes up the parent of a directory. + */ +struct fix_dotdot_struct { + ext2_filsys fs; + ext2_ino_t parent; + int done; + e2fsck_t ctx; +}; + +static int fix_dotdot_proc(struct ext2_dir_entry *dirent, + int offset EXT2FS_ATTR((unused)), + int blocksize EXT2FS_ATTR((unused)), + char *buf EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data; + errcode_t retval; + struct problem_context pctx; + + if ((dirent->name_len & 0xFF) != 2) + return 0; + if (strncmp(dirent->name, "..", 2)) + return 0; + + clear_problem_context(&pctx); + + retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1); + if (retval) { + pctx.errcode = retval; + fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); + } + retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1); + if (retval) { + pctx.errcode = retval; + fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); + } + dirent->inode = fp->parent; + if (fp->ctx->fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_FILETYPE) + dirent->name_len = (dirent->name_len & 0xFF) | + (EXT2_FT_DIR << 8); + else + dirent->name_len = dirent->name_len & 0xFF; + + fp->done++; + return DIRENT_ABORT | DIRENT_CHANGED; +} + +static void fix_dotdot(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent) +{ + ext2_filsys fs = ctx->fs; + errcode_t retval; + struct fix_dotdot_struct fp; + struct problem_context pctx; + + fp.fs = fs; + fp.parent = parent; + fp.done = 0; + fp.ctx = ctx; + +#if 0 + printf("Fixing '..' of inode %lu to be %lu...\n", ino, parent); +#endif + + clear_problem_context(&pctx); + pctx.ino = ino; + retval = ext2fs_dir_iterate(fs, ino, DIRENT_FLAG_INCLUDE_EMPTY, + 0, fix_dotdot_proc, &fp); + if (retval || !fp.done) { + pctx.errcode = retval; + fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR : + PR_3_FIX_PARENT_NOFIND, &pctx); + ext2fs_unmark_valid(fs); + } + (void) e2fsck_dir_info_set_dotdot(ctx, ino, parent); + if (e2fsck_dir_info_set_parent(ctx, ino, ctx->lost_and_found)) + fix_problem(ctx, PR_3_NO_DIRINFO, &pctx); + + return; +} + +/* + * These routines are responsible for expanding a /lost+found if it is + * too small. + */ + +struct expand_dir_struct { + blk64_t num; + e2_blkcnt_t guaranteed_size; + blk64_t newblocks; + blk64_t last_block; + errcode_t err; + e2fsck_t ctx; +}; + +static int expand_dir_proc(ext2_filsys fs, + blk64_t *blocknr, + e2_blkcnt_t blockcnt, + blk64_t ref_block EXT2FS_ATTR((unused)), + int ref_offset EXT2FS_ATTR((unused)), + void *priv_data) +{ + struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; + blk64_t new_blk; + static blk64_t last_blk = 0; + char *block; + errcode_t retval; + e2fsck_t ctx; + + ctx = es->ctx; + + if (es->guaranteed_size && blockcnt >= es->guaranteed_size) + return BLOCK_ABORT; + + if (blockcnt > 0) + es->last_block = blockcnt; + if (*blocknr) { + last_blk = *blocknr; + return 0; + } + + if (blockcnt && + (EXT2FS_B2C(fs, last_blk) == EXT2FS_B2C(fs, last_blk + 1))) + new_blk = last_blk + 1; + else { + last_blk &= ~EXT2FS_CLUSTER_MASK(fs); + retval = ext2fs_new_block2(fs, last_blk, ctx->block_found_map, + &new_blk); + if (retval) { + es->err = retval; + return BLOCK_ABORT; + } + es->newblocks++; + ext2fs_block_alloc_stats2(fs, new_blk, +1); + } + last_blk = new_blk; + + if (blockcnt > 0) { + retval = ext2fs_new_dir_block(fs, 0, 0, &block); + if (retval) { + es->err = retval; + return BLOCK_ABORT; + } + es->num--; + retval = ext2fs_write_dir_block3(fs, new_blk, block, 0); + } else { + retval = ext2fs_get_mem(fs->blocksize, &block); + if (retval) { + es->err = retval; + return BLOCK_ABORT; + } + memset(block, 0, fs->blocksize); + retval = io_channel_write_blk64(fs->io, new_blk, 1, block); + } + if (retval) { + es->err = retval; + return BLOCK_ABORT; + } + ext2fs_free_mem(&block); + *blocknr = new_blk; + ext2fs_mark_block_bitmap2(ctx->block_found_map, new_blk); + + if (es->num == 0) + return (BLOCK_CHANGED | BLOCK_ABORT); + else + return BLOCK_CHANGED; +} + +errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir, + int num, int guaranteed_size) +{ + ext2_filsys fs = ctx->fs; + errcode_t retval; + struct expand_dir_struct es; + struct ext2_inode inode; + blk64_t sz, before, after; + + if (!(fs->flags & EXT2_FLAG_RW)) + return EXT2_ET_RO_FILSYS; + + /* + * Read the inode and block bitmaps in; we'll be messing with + * them. + */ + e2fsck_read_bitmaps(ctx); + + retval = ext2fs_check_directory(fs, dir); + if (retval) + return retval; + + es.num = num; + es.guaranteed_size = guaranteed_size; + es.last_block = 0; + es.err = 0; + es.newblocks = 0; + es.ctx = ctx; + + retval = ext2fs_block_iterate3(fs, dir, BLOCK_FLAG_APPEND, + 0, expand_dir_proc, &es); + + if (es.err) + return es.err; + + /* + * Update the size and block count fields in the inode. + */ + retval = ext2fs_read_inode(fs, dir, &inode); + if (retval) + return retval; + + sz = (es.last_block + 1) * fs->blocksize; + retval = ext2fs_inode_size_set(fs, &inode, sz); + if (retval) + return retval; + ext2fs_iblk_add_blocks(fs, &inode, es.newblocks); + quota_data_add(ctx->qctx, &inode, dir, es.newblocks * fs->blocksize); + + e2fsck_write_inode(ctx, dir, &inode, "expand_directory"); + + return 0; +} +
diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c new file mode 100644 index 0000000..21d93f0 --- /dev/null +++ b/e2fsck/pass4.c
@@ -0,0 +1,198 @@ +/* + * pass4.c -- pass #4 of e2fsck: Check reference counts + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + * Pass 4 frees the following data structures: + * - A bitmap of which inodes are in bad blocks. (inode_bb_map) + * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) + */ + +#include "config.h" +#include "e2fsck.h" +#include "problem.h" +#include <ext2fs/ext2_ext_attr.h> + +/* + * This routine is called when an inode is not connected to the + * directory tree. + * + * This subroutine returns 1 then the caller shouldn't bother with the + * rest of the pass 4 tests. + */ +static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i, + struct ext2_inode *inode) +{ + ext2_filsys fs = ctx->fs; + struct problem_context pctx; + __u32 eamagic = 0; + int extra_size = 0; + + if (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE) { + e2fsck_read_inode_full(ctx, i, inode,EXT2_INODE_SIZE(fs->super), + "pass4: disconnect_inode"); + extra_size = ((struct ext2_inode_large *)inode)->i_extra_isize; + } else { + e2fsck_read_inode(ctx, i, inode, "pass4: disconnect_inode"); + } + clear_problem_context(&pctx); + pctx.ino = i; + pctx.inode = inode; + + if (EXT2_INODE_SIZE(fs->super) -EXT2_GOOD_OLD_INODE_SIZE -extra_size >0) + eamagic = *(__u32 *)(((char *)inode) +EXT2_GOOD_OLD_INODE_SIZE + + extra_size); + /* + * Offer to delete any zero-length files that does not have + * blocks. If there is an EA block, it might have useful + * information, so we won't prompt to delete it, but let it be + * reconnected to lost+found. + */ + if (!inode->i_blocks && eamagic != EXT2_EXT_ATTR_MAGIC && + (LINUX_S_ISREG(inode->i_mode) || LINUX_S_ISDIR(inode->i_mode))) { + if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) { + e2fsck_clear_inode(ctx, i, inode, 0, + "disconnect_inode"); + /* + * Fix up the bitmaps... + */ + e2fsck_read_bitmaps(ctx); + ext2fs_inode_alloc_stats2(fs, i, -1, + LINUX_S_ISDIR(inode->i_mode)); + quota_data_inodes(ctx->qctx, inode, i, -1); + return 0; + } + } + + /* + * Prompt to reconnect. + */ + if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) { + if (e2fsck_reconnect_file(ctx, i)) + ext2fs_unmark_valid(fs); + } else { + /* + * If we don't attach the inode, then skip the + * i_links_test since there's no point in trying to + * force i_links_count to zero. + */ + ext2fs_unmark_valid(fs); + return 1; + } + return 0; +} + + +void e2fsck_pass4(e2fsck_t ctx) +{ + ext2_filsys fs = ctx->fs; + ext2_ino_t i; + struct ext2_inode *inode; +#ifdef RESOURCE_TRACK + struct resource_track rtrack; +#endif + struct problem_context pctx; + __u16 link_count, link_counted; + char *buf = 0; + dgrp_t group, maxgroup; + + init_resource_track(&rtrack, ctx->fs->io); + +#ifdef MTRACE + mtrace_print("Pass 4"); +#endif + + clear_problem_context(&pctx); + + if (!(ctx->options & E2F_OPT_PREEN)) + fix_problem(ctx, PR_4_PASS_HEADER, &pctx); + + group = 0; + maxgroup = fs->group_desc_count; + if (ctx->progress) + if ((ctx->progress)(ctx, 4, 0, maxgroup)) + return; + + inode = e2fsck_allocate_memory(ctx, EXT2_INODE_SIZE(fs->super), + "scratch inode"); + + /* Protect loop from wrap-around if s_inodes_count maxed */ + for (i=1; i <= fs->super->s_inodes_count && i > 0; i++) { + int isdir; + + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + goto errout; + if ((i % fs->super->s_inodes_per_group) == 0) { + group++; + if (ctx->progress) + if ((ctx->progress)(ctx, 4, group, maxgroup)) + goto errout; + } + if (i == EXT2_BAD_INO || + (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super))) + continue; + if (!(ext2fs_test_inode_bitmap2(ctx->inode_used_map, i)) || + (ctx->inode_imagic_map && + ext2fs_test_inode_bitmap2(ctx->inode_imagic_map, i)) || + (ctx->inode_bb_map && + ext2fs_test_inode_bitmap2(ctx->inode_bb_map, i))) + continue; + ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count); + ext2fs_icount_fetch(ctx->inode_count, i, &link_counted); + if (link_counted == 0) { + if (!buf) + buf = e2fsck_allocate_memory(ctx, + fs->blocksize, "bad_inode buffer"); + if (e2fsck_process_bad_inode(ctx, 0, i, buf)) + continue; + if (disconnect_inode(ctx, i, inode)) + continue; + ext2fs_icount_fetch(ctx->inode_link_info, i, + &link_count); + ext2fs_icount_fetch(ctx->inode_count, i, + &link_counted); + } + isdir = ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i); + if (isdir && (link_counted > EXT2_LINK_MAX)) + link_counted = 1; + if (link_counted != link_count) { + e2fsck_read_inode(ctx, i, inode, "pass4"); + pctx.ino = i; + pctx.inode = inode; + if ((link_count != inode->i_links_count) && !isdir && + (inode->i_links_count <= EXT2_LINK_MAX)) { + pctx.num = link_count; + fix_problem(ctx, + PR_4_INCONSISTENT_COUNT, &pctx); + } + pctx.num = link_counted; + /* i_link_count was previously exceeded, but no longer + * is, fix this but don't consider it an error */ + if ((isdir && link_counted > 1 && + (inode->i_flags & EXT2_INDEX_FL) && + link_count == 1 && !(ctx->options & E2F_OPT_NO)) || + fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) { + inode->i_links_count = link_counted; + e2fsck_write_inode(ctx, i, inode, "pass4"); + } + } + } + ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0; + ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0; + ext2fs_free_inode_bitmap(ctx->inode_bb_map); + ctx->inode_bb_map = 0; + ext2fs_free_inode_bitmap(ctx->inode_imagic_map); + ctx->inode_imagic_map = 0; +errout: + if (buf) + ext2fs_free_mem(&buf); + + ext2fs_free_mem(&inode); + print_resource_track(ctx, _("Pass 4"), &rtrack, ctx->fs->io); +} +
diff --git a/e2fsck/pass5.c b/e2fsck/pass5.c new file mode 100644 index 0000000..bc9a32a --- /dev/null +++ b/e2fsck/pass5.c
@@ -0,0 +1,817 @@ +/* + * pass5.c --- check block and inode bitmaps against on-disk bitmaps + * + * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + * + */ + +#include "config.h" +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <errno.h> + +#include "e2fsck.h" +#include "problem.h" + +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) + +static void check_block_bitmaps(e2fsck_t ctx); +static void check_inode_bitmaps(e2fsck_t ctx); +static void check_inode_end(e2fsck_t ctx); +static void check_block_end(e2fsck_t ctx); + +void e2fsck_pass5(e2fsck_t ctx) +{ +#ifdef RESOURCE_TRACK + struct resource_track rtrack; +#endif + struct problem_context pctx; + +#ifdef MTRACE + mtrace_print("Pass 5"); +#endif + + init_resource_track(&rtrack, ctx->fs->io); + clear_problem_context(&pctx); + + if (!(ctx->options & E2F_OPT_PREEN)) + fix_problem(ctx, PR_5_PASS_HEADER, &pctx); + + if (ctx->progress) + if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2)) + return; + + e2fsck_read_bitmaps(ctx); + + check_block_bitmaps(ctx); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return; + check_inode_bitmaps(ctx); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return; + check_inode_end(ctx); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return; + check_block_end(ctx); + if (ctx->flags & E2F_FLAG_SIGNAL_MASK) + return; + + ext2fs_free_inode_bitmap(ctx->inode_used_map); + ctx->inode_used_map = 0; + ext2fs_free_inode_bitmap(ctx->inode_dir_map); + ctx->inode_dir_map = 0; + ext2fs_free_block_bitmap(ctx->block_found_map); + ctx->block_found_map = 0; + + print_resource_track(ctx, _("Pass 5"), &rtrack, ctx->fs->io); +} + +static void e2fsck_discard_blocks(e2fsck_t ctx, blk64_t start, + blk64_t count) +{ + ext2_filsys fs = ctx->fs; + + /* + * If the filesystem has changed it means that there was an corruption + * which should be repaired, but in some cases just one e2fsck run is + * not enough to fix the problem, hence it is not safe to run discard + * in this case. + */ + if (ext2fs_test_changed(fs)) + ctx->options &= ~E2F_OPT_DISCARD; + + if ((ctx->options & E2F_OPT_DISCARD) && + (io_channel_discard(fs->io, start, count))) + ctx->options &= ~E2F_OPT_DISCARD; +} + +/* + * This will try to discard number 'count' inodes starting at + * inode number 'start' within the 'group'. Note that 'start' + * is 1-based, it means that we need to adjust it by -1 in this + * function to compute right offset in the particular inode table. + */ +static void e2fsck_discard_inodes(e2fsck_t ctx, dgrp_t group, + ext2_ino_t start, int count) +{ + ext2_filsys fs = ctx->fs; + blk64_t blk, num; + + /* + * Sanity check for 'start' + */ + if ((start < 1) || (start > EXT2_INODES_PER_GROUP(fs->super))) { + printf("PROGRAMMING ERROR: Got start %d outside of group %d!" + " Disabling discard\n", + start, group); + ctx->options &= ~E2F_OPT_DISCARD; + } + + /* + * Do not attempt to discard if E2F_OPT_DISCARD is not set. And also + * skip the discard on this group if discard does not zero data. + * The reason is that if the inode table is not zeroed discard would + * no help us since we need to zero it anyway, or if the inode table + * is zeroed then the read after discard would not be deterministic + * anyway and we would not be able to assume that this inode table + * was zeroed anymore so we would have to zero it again, which does + * not really make sense. + */ + if (!(ctx->options & E2F_OPT_DISCARD) || + !io_channel_discard_zeroes_data(fs->io)) + return; + + /* + * Start is inode number within the group which starts + * counting from 1, so we need to adjust it. + */ + start -= 1; + + /* + * We can discard only blocks containing only unused + * inodes in the table. + */ + blk = DIV_ROUND_UP(start, + EXT2_INODES_PER_BLOCK(fs->super)); + count -= (blk * EXT2_INODES_PER_BLOCK(fs->super) - start); + blk += ext2fs_inode_table_loc(fs, group); + num = count / EXT2_INODES_PER_BLOCK(fs->super); + + if (num > 0) + e2fsck_discard_blocks(ctx, blk, num); +} + +#define NO_BLK ((blk64_t) -1) + +static void print_bitmap_problem(e2fsck_t ctx, problem_t problem, + struct problem_context *pctx) +{ + switch (problem) { + case PR_5_BLOCK_UNUSED: + if (pctx->blk == pctx->blk2) + pctx->blk2 = 0; + else + problem = PR_5_BLOCK_RANGE_UNUSED; + break; + case PR_5_BLOCK_USED: + if (pctx->blk == pctx->blk2) + pctx->blk2 = 0; + else + problem = PR_5_BLOCK_RANGE_USED; + break; + case PR_5_INODE_UNUSED: + if (pctx->ino == pctx->ino2) + pctx->ino2 = 0; + else + problem = PR_5_INODE_RANGE_UNUSED; + break; + case PR_5_INODE_USED: + if (pctx->ino == pctx->ino2) + pctx->ino2 = 0; + else + problem = PR_5_INODE_RANGE_USED; + break; + } + fix_problem(ctx, problem, pctx); + pctx->blk = pctx->blk2 = NO_BLK; + pctx->ino = pctx->ino2 = 0; +} + +/* Just to be more succint */ +#define B2C(x) EXT2FS_B2C(fs, (x)) +#define EQ_CLSTR(x, y) (B2C(x) == B2C(y)) +#define LE_CLSTR(x, y) (B2C(x) <= B2C(y)) +#define GE_CLSTR(x, y) (B2C(x) >= B2C(y)) + +static void check_block_bitmaps(e2fsck_t ctx) +{ + ext2_filsys fs = ctx->fs; + blk64_t i; + unsigned int *free_array; + dgrp_t g, group = 0; + unsigned int blocks = 0; + blk64_t free_blocks = 0; + blk64_t first_free = ext2fs_blocks_count(fs->super); + unsigned int group_free = 0; + int actual, bitmap; + struct problem_context pctx; + problem_t problem, save_problem; + int fixit, had_problem; + errcode_t retval; + int old_desc_blocks = 0; + int count = 0; + int cmp_block = 0; + int redo_flag = 0; + blk64_t super_blk, old_desc_blk, new_desc_blk; + char *actual_buf, *bitmap_buf; + + actual_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize, + "actual bitmap buffer"); + bitmap_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize, + "bitmap block buffer"); + + clear_problem_context(&pctx); + free_array = (unsigned int *) e2fsck_allocate_memory(ctx, + fs->group_desc_count * sizeof(unsigned int), "free block count array"); + + if ((B2C(fs->super->s_first_data_block) < + ext2fs_get_block_bitmap_start2(ctx->block_found_map)) || + (B2C(ext2fs_blocks_count(fs->super)-1) > + ext2fs_get_block_bitmap_end2(ctx->block_found_map))) { + pctx.num = 1; + pctx.blk = B2C(fs->super->s_first_data_block); + pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1); + pctx.ino = ext2fs_get_block_bitmap_start2(ctx->block_found_map); + pctx.ino2 = ext2fs_get_block_bitmap_end2(ctx->block_found_map); + fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); + + ctx->flags |= E2F_FLAG_ABORT; /* fatal */ + goto errout; + } + + if ((B2C(fs->super->s_first_data_block) < + ext2fs_get_block_bitmap_start2(fs->block_map)) || + (B2C(ext2fs_blocks_count(fs->super)-1) > + ext2fs_get_block_bitmap_end2(fs->block_map))) { + pctx.num = 2; + pctx.blk = B2C(fs->super->s_first_data_block); + pctx.blk2 = B2C(ext2fs_blocks_count(fs->super) - 1); + pctx.ino = ext2fs_get_block_bitmap_start2(fs->block_map); + pctx.ino2 = ext2fs_get_block_bitmap_end2(fs->block_map); + fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); + + ctx->flags |= E2F_FLAG_ABORT; /* fatal */ + goto errout; + } + +redo_counts: + had_problem = 0; + save_problem = 0; + pctx.blk = pctx.blk2 = NO_BLK; + for (i = B2C(fs->super->s_first_data_block); + i < ext2fs_blocks_count(fs->super); + i += EXT2FS_CLUSTER_RATIO(fs)) { + int first_block_in_bg = (B2C(i) - + B2C(fs->super->s_first_data_block)) % + fs->super->s_clusters_per_group == 0; + int n, nbytes = fs->super->s_clusters_per_group / 8; + + actual = ext2fs_fast_test_block_bitmap2(ctx->block_found_map, i); + + /* + * Try to optimize pass5 by extracting a bitmap block + * as expected from what we have on disk, and then + * comparing the two. If they are identical, then + * update the free block counts and go on to the next + * block group. This is much faster than doing the + * individual bit-by-bit comparison. The one downside + * is that this doesn't work if we are asking e2fsck + * to do a discard operation. + */ + if (!first_block_in_bg || + (group == (int)fs->group_desc_count - 1) || + (ctx->options & E2F_OPT_DISCARD)) + goto no_optimize; + + retval = ext2fs_get_block_bitmap_range2(ctx->block_found_map, + B2C(i), fs->super->s_clusters_per_group, + actual_buf); + if (retval) + goto no_optimize; + retval = ext2fs_get_block_bitmap_range2(fs->block_map, + B2C(i), fs->super->s_clusters_per_group, + bitmap_buf); + if (retval) + goto no_optimize; + if (memcmp(actual_buf, bitmap_buf, nbytes) != 0) + goto no_optimize; + n = ext2fs_bitcount(actual_buf, nbytes); + group_free = fs->super->s_clusters_per_group - n; + free_blocks += group_free; + i += EXT2FS_C2B(fs, fs->super->s_clusters_per_group - 1); + goto next_group; + no_optimize: + + if (redo_flag) + bitmap = actual; + else + bitmap = ext2fs_fast_test_block_bitmap2(fs->block_map, i); + + if (!actual == !bitmap) + goto do_counts; + + if (!actual && bitmap) { + /* + * Block not used, but marked in use in the bitmap. + */ + problem = PR_5_BLOCK_UNUSED; + } else { + /* + * Block used, but not marked in use in the bitmap. + */ + problem = PR_5_BLOCK_USED; + + if (ext2fs_bg_flags_test(fs, group, + EXT2_BG_BLOCK_UNINIT)) { + struct problem_context pctx2; + pctx2.blk = i; + pctx2.group = group; + if (fix_problem(ctx, PR_5_BLOCK_UNINIT, + &pctx2)) + ext2fs_bg_flags_clear(fs, group, + EXT2_BG_BLOCK_UNINIT); + } + } + if (pctx.blk == NO_BLK) { + pctx.blk = pctx.blk2 = i; + save_problem = problem; + } else { + if ((problem == save_problem) && + (pctx.blk2 == i - EXT2FS_CLUSTER_RATIO(fs))) + pctx.blk2 += EXT2FS_CLUSTER_RATIO(fs); + else { + print_bitmap_problem(ctx, save_problem, &pctx); + pctx.blk = pctx.blk2 = i; + save_problem = problem; + } + } + ctx->flags |= E2F_FLAG_PROG_SUPPRESS; + had_problem++; + + /* + * If there a problem we should turn off the discard so we + * do not compromise the filesystem. + */ + ctx->options &= ~E2F_OPT_DISCARD; + + do_counts: + if (!bitmap) { + group_free++; + free_blocks++; + if (first_free > i) + first_free = i; + } else if (i > first_free) { + e2fsck_discard_blocks(ctx, first_free, + (i - first_free)); + first_free = ext2fs_blocks_count(fs->super); + } + blocks ++; + if ((blocks == fs->super->s_clusters_per_group) || + (EXT2FS_B2C(fs, i) == + EXT2FS_B2C(fs, ext2fs_blocks_count(fs->super)-1))) { + /* + * If the last block of this group is free, then we can + * discard it as well. + */ + if (!bitmap && i >= first_free) + e2fsck_discard_blocks(ctx, first_free, + (i - first_free) + 1); + next_group: + first_free = ext2fs_blocks_count(fs->super); + + free_array[group] = group_free; + group ++; + blocks = 0; + group_free = 0; + if (ctx->progress) + if ((ctx->progress)(ctx, 5, group, + fs->group_desc_count*2)) + goto errout; + } + } + if (pctx.blk != NO_BLK) + print_bitmap_problem(ctx, save_problem, &pctx); + if (had_problem) + fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP); + else + fixit = -1; + ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS; + + if (fixit == 1) { + ext2fs_free_block_bitmap(fs->block_map); + retval = ext2fs_copy_bitmap(ctx->block_found_map, + &fs->block_map); + if (retval) { + clear_problem_context(&pctx); + fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + goto errout; + } + ext2fs_set_bitmap_padding(fs->block_map); + ext2fs_mark_bb_dirty(fs); + + /* Redo the counts */ + blocks = 0; free_blocks = 0; group_free = 0; group = 0; + memset(free_array, 0, fs->group_desc_count * sizeof(int)); + redo_flag++; + goto redo_counts; + } else if (fixit == 0) + ext2fs_unmark_valid(fs); + + for (g = 0; g < fs->group_desc_count; g++) { + if (free_array[g] != ext2fs_bg_free_blocks_count(fs, g)) { + pctx.group = g; + pctx.blk = ext2fs_bg_free_blocks_count(fs, g); + pctx.blk2 = free_array[g]; + + if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP, + &pctx)) { + ext2fs_bg_free_blocks_count_set(fs, g, free_array[g]); + ext2fs_mark_super_dirty(fs); + } else + ext2fs_unmark_valid(fs); + } + } + free_blocks = EXT2FS_C2B(fs, free_blocks); + if (free_blocks != ext2fs_free_blocks_count(fs->super)) { + pctx.group = 0; + pctx.blk = ext2fs_free_blocks_count(fs->super); + pctx.blk2 = free_blocks; + + if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) { + ext2fs_free_blocks_count_set(fs->super, free_blocks); + ext2fs_mark_super_dirty(fs); + } + } +errout: + ext2fs_free_mem(&free_array); + ext2fs_free_mem(&actual_buf); + ext2fs_free_mem(&bitmap_buf); +} + +static void check_inode_bitmaps(e2fsck_t ctx) +{ + ext2_filsys fs = ctx->fs; + ext2_ino_t i; + unsigned int free_inodes = 0; + int group_free = 0; + int dirs_count = 0; + dgrp_t group = 0; + unsigned int inodes = 0; + ext2_ino_t *free_array; + ext2_ino_t *dir_array; + int actual, bitmap; + errcode_t retval; + struct problem_context pctx; + problem_t problem, save_problem; + int fixit, had_problem; + int csum_flag; + int skip_group = 0; + int redo_flag = 0; + ext2_ino_t first_free = fs->super->s_inodes_per_group + 1; + + clear_problem_context(&pctx); + free_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx, + fs->group_desc_count * sizeof(ext2_ino_t), "free inode count array"); + + dir_array = (ext2_ino_t *) e2fsck_allocate_memory(ctx, + fs->group_desc_count * sizeof(ext2_ino_t), "directory count array"); + + if ((1 < ext2fs_get_inode_bitmap_start2(ctx->inode_used_map)) || + (fs->super->s_inodes_count > + ext2fs_get_inode_bitmap_end2(ctx->inode_used_map))) { + pctx.num = 3; + pctx.blk = 1; + pctx.blk2 = fs->super->s_inodes_count; + pctx.ino = ext2fs_get_inode_bitmap_start2(ctx->inode_used_map); + pctx.ino2 = ext2fs_get_inode_bitmap_end2(ctx->inode_used_map); + fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); + + ctx->flags |= E2F_FLAG_ABORT; /* fatal */ + goto errout; + } + if ((1 < ext2fs_get_inode_bitmap_start2(fs->inode_map)) || + (fs->super->s_inodes_count > + ext2fs_get_inode_bitmap_end2(fs->inode_map))) { + pctx.num = 4; + pctx.blk = 1; + pctx.blk2 = fs->super->s_inodes_count; + pctx.ino = ext2fs_get_inode_bitmap_start2(fs->inode_map); + pctx.ino2 = ext2fs_get_inode_bitmap_end2(fs->inode_map); + fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); + + ctx->flags |= E2F_FLAG_ABORT; /* fatal */ + goto errout; + } + + csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_GDT_CSUM); +redo_counts: + had_problem = 0; + save_problem = 0; + pctx.ino = pctx.ino2 = 0; + if (csum_flag && + (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT))) + skip_group++; + + /* Protect loop from wrap-around if inodes_count is maxed */ + for (i = 1; i <= fs->super->s_inodes_count && i > 0; i++) { + bitmap = 0; + if (skip_group && + i % fs->super->s_inodes_per_group == 1) { + /* + * Current inode is the first inode + * in the current block group. + */ + if (ext2fs_test_inode_bitmap_range( + ctx->inode_used_map, i, + fs->super->s_inodes_per_group)) { + /* + * When the compared inodes in inodes bitmap + * are 0, count the free inode, + * skip the current block group. + */ + first_free = 1; + inodes = fs->super->s_inodes_per_group - 1; + group_free = inodes; + free_inodes += inodes; + i += inodes; + skip_group = 0; + goto do_counts; + } + } + + actual = ext2fs_fast_test_inode_bitmap2(ctx->inode_used_map, i); + if (redo_flag) + bitmap = actual; + else if (!skip_group) + bitmap = ext2fs_fast_test_inode_bitmap2(fs->inode_map, i); + if (!actual == !bitmap) + goto do_counts; + + if (!actual && bitmap) { + /* + * Inode wasn't used, but marked in bitmap + */ + problem = PR_5_INODE_UNUSED; + } else /* if (actual && !bitmap) */ { + /* + * Inode used, but not in bitmap + */ + problem = PR_5_INODE_USED; + + /* We should never hit this, because it means that + * inodes were marked in use that weren't noticed + * in pass1 or pass 2. It is easier to fix the problem + * than to kill e2fsck and leave the user stuck. */ + if (skip_group) { + struct problem_context pctx2; + pctx2.blk = i; + pctx2.group = group; + if (fix_problem(ctx, PR_5_INODE_UNINIT,&pctx2)){ + ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT); + skip_group = 0; + } + } + } + if (pctx.ino == 0) { + pctx.ino = pctx.ino2 = i; + save_problem = problem; + } else { + if ((problem == save_problem) && + (pctx.ino2 == i-1)) + pctx.ino2++; + else { + print_bitmap_problem(ctx, save_problem, &pctx); + pctx.ino = pctx.ino2 = i; + save_problem = problem; + } + } + ctx->flags |= E2F_FLAG_PROG_SUPPRESS; + had_problem++; + /* + * If there a problem we should turn off the discard so we + * do not compromise the filesystem. + */ + ctx->options &= ~E2F_OPT_DISCARD; + +do_counts: + inodes++; + if (bitmap) { + if (ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i)) + dirs_count++; + if (inodes > first_free) { + e2fsck_discard_inodes(ctx, group, first_free, + inodes - first_free); + first_free = fs->super->s_inodes_per_group + 1; + } + } else { + group_free++; + free_inodes++; + if (first_free > inodes) + first_free = inodes; + } + + if ((inodes == fs->super->s_inodes_per_group) || + (i == fs->super->s_inodes_count)) { + /* + * If the last inode is free, we can discard it as well. + */ + if (!bitmap && inodes >= first_free) + e2fsck_discard_inodes(ctx, group, first_free, + inodes - first_free + 1); + /* + * If discard zeroes data and the group inode table + * was not zeroed yet, set itable as zeroed + */ + if ((ctx->options & E2F_OPT_DISCARD) && + io_channel_discard_zeroes_data(fs->io) && + !(ext2fs_bg_flags_test(fs, group, + EXT2_BG_INODE_ZEROED))) { + ext2fs_bg_flags_set(fs, group, + EXT2_BG_INODE_ZEROED); + ext2fs_group_desc_csum_set(fs, group); + } + + first_free = fs->super->s_inodes_per_group + 1; + free_array[group] = group_free; + dir_array[group] = dirs_count; + group ++; + inodes = 0; + skip_group = 0; + group_free = 0; + dirs_count = 0; + if (ctx->progress) + if ((ctx->progress)(ctx, 5, + group + fs->group_desc_count, + fs->group_desc_count*2)) + goto errout; + if (csum_flag && + (i != fs->super->s_inodes_count) && + (ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT) + )) + skip_group++; + } + } + if (pctx.ino) + print_bitmap_problem(ctx, save_problem, &pctx); + + if (had_problem) + fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP); + else + fixit = -1; + ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS; + + if (fixit == 1) { + ext2fs_free_inode_bitmap(fs->inode_map); + retval = ext2fs_copy_bitmap(ctx->inode_used_map, + &fs->inode_map); + if (retval) { + clear_problem_context(&pctx); + fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; + goto errout; + } + ext2fs_set_bitmap_padding(fs->inode_map); + ext2fs_mark_ib_dirty(fs); + + /* redo counts */ + inodes = 0; free_inodes = 0; group_free = 0; + dirs_count = 0; group = 0; + memset(free_array, 0, fs->group_desc_count * sizeof(int)); + memset(dir_array, 0, fs->group_desc_count * sizeof(int)); + redo_flag++; + goto redo_counts; + } else if (fixit == 0) + ext2fs_unmark_valid(fs); + + for (i = 0; i < fs->group_desc_count; i++) { + if (free_array[i] != ext2fs_bg_free_inodes_count(fs, i)) { + pctx.group = i; + pctx.ino = ext2fs_bg_free_inodes_count(fs, i); + pctx.ino2 = free_array[i]; + if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP, + &pctx)) { + ext2fs_bg_free_inodes_count_set(fs, i, free_array[i]); + ext2fs_mark_super_dirty(fs); + } else + ext2fs_unmark_valid(fs); + } + if (dir_array[i] != ext2fs_bg_used_dirs_count(fs, i)) { + pctx.group = i; + pctx.ino = ext2fs_bg_used_dirs_count(fs, i); + pctx.ino2 = dir_array[i]; + + if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP, + &pctx)) { + ext2fs_bg_used_dirs_count_set(fs, i, dir_array[i]); + ext2fs_mark_super_dirty(fs); + } else + ext2fs_unmark_valid(fs); + } + } + if (free_inodes != fs->super->s_free_inodes_count) { + pctx.group = -1; + pctx.ino = fs->super->s_free_inodes_count; + pctx.ino2 = free_inodes; + + if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) { + fs->super->s_free_inodes_count = free_inodes; + ext2fs_mark_super_dirty(fs); + } + } +errout: + ext2fs_free_mem(&free_array); + ext2fs_free_mem(&dir_array); +} + +static void check_inode_end(e2fsck_t ctx) +{ + ext2_filsys fs = ctx->fs; + ext2_ino_t end, save_inodes_count, i; + struct problem_context pctx; + + clear_problem_context(&pctx); + + end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count; + pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end, + &save_inodes_count); + if (pctx.errcode) { + pctx.num = 1; + fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; /* fatal */ + return; + } + if (save_inodes_count == end) + return; + + /* protect loop from wrap-around if end is maxed */ + for (i = save_inodes_count + 1; i <= end && i > save_inodes_count; i++) { + if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) { + if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) { + for (; i <= end; i++) + ext2fs_mark_inode_bitmap(fs->inode_map, + i); + ext2fs_mark_ib_dirty(fs); + } else + ext2fs_unmark_valid(fs); + break; + } + } + + pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, + save_inodes_count, 0); + if (pctx.errcode) { + pctx.num = 2; + fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; /* fatal */ + return; + } +} + +static void check_block_end(e2fsck_t ctx) +{ + ext2_filsys fs = ctx->fs; + blk64_t end, save_blocks_count, i; + struct problem_context pctx; + + clear_problem_context(&pctx); + + end = ext2fs_get_block_bitmap_start2(fs->block_map) + + EXT2_GROUPS_TO_CLUSTERS(fs->super, fs->group_desc_count) - 1; + pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, end, + &save_blocks_count); + if (pctx.errcode) { + pctx.num = 3; + fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; /* fatal */ + return; + } + if (save_blocks_count == end) + return; + + /* Protect loop from wrap-around if end is maxed */ + for (i = save_blocks_count + 1; i <= end && i > save_blocks_count; i++) { + if (!ext2fs_test_block_bitmap2(fs->block_map, + EXT2FS_C2B(fs, i))) { + if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) { + for (; i <= end; i++) + ext2fs_mark_block_bitmap2(fs->block_map, + EXT2FS_C2B(fs, i)); + ext2fs_mark_bb_dirty(fs); + } else + ext2fs_unmark_valid(fs); + break; + } + } + + pctx.errcode = ext2fs_fudge_block_bitmap_end2(fs->block_map, + save_blocks_count, 0); + if (pctx.errcode) { + pctx.num = 4; + fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); + ctx->flags |= E2F_FLAG_ABORT; /* fatal */ + return; + } +} + + +
diff --git a/e2fsck/problem.c b/e2fsck/problem.c new file mode 100644 index 0000000..f442a33 --- /dev/null +++ b/e2fsck/problem.c