diff options
author | Hans Ulrich Niedermann <hun@n-dimensional.de> | 2007-12-14 16:08:25 +0100 |
---|---|---|
committer | Hans Ulrich Niedermann <hun@n-dimensional.de> | 2007-12-14 16:08:25 +0100 |
commit | 6749719af90afe9544db14bdd8e2742926f1439c (patch) | |
tree | 9bb8edef05f9625be2ccd9bce5cb245af63effc4 | |
download | e2tools-6749719af90afe9544db14bdd8e2742926f1439c.tar.gz e2tools-6749719af90afe9544db14bdd8e2742926f1439c.tar.xz e2tools-6749719af90afe9544db14bdd8e2742926f1439c.zip |
-rw-r--r-- | AUTHORS | 1 | ||||
-rw-r--r-- | COPYING | 336 | ||||
-rw-r--r-- | ChangeLog | 183 | ||||
-rw-r--r-- | INSTALL | 182 | ||||
-rw-r--r-- | Makefile.am | 29 | ||||
-rw-r--r-- | Makefile.in | 346 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 282 | ||||
-rw-r--r-- | TODO | 8 | ||||
-rw-r--r-- | aclocal.m4 | 137 | ||||
-rwxr-xr-x | configure | 2185 | ||||
-rw-r--r-- | configure.in | 31 | ||||
-rw-r--r-- | copy.c | 1202 | ||||
-rw-r--r-- | e2tools.c | 78 | ||||
-rw-r--r-- | e2tools.h | 138 | ||||
-rw-r--r-- | e2tools.spec | 52 | ||||
-rw-r--r-- | elist.c | 198 | ||||
-rw-r--r-- | elist.h | 39 | ||||
-rwxr-xr-x | install-sh | 251 | ||||
-rw-r--r-- | ln.c | 388 | ||||
-rw-r--r-- | ls.c | 1055 | ||||
-rwxr-xr-x | missing | 190 | ||||
-rw-r--r-- | mkdir.c | 587 | ||||
-rwxr-xr-x | mkinstalldirs | 40 | ||||
-rw-r--r-- | mv.c | 554 | ||||
-rw-r--r-- | progress.c | 198 | ||||
-rw-r--r-- | read.c | 368 | ||||
-rw-r--r-- | rm.c | 413 | ||||
-rw-r--r-- | tail.c | 440 | ||||
-rw-r--r-- | util.c | 320 | ||||
-rw-r--r-- | write.c | 377 |
31 files changed, 10608 insertions, 0 deletions
@@ -0,0 +1 @@ +Keith W Sheffield (sheff@pobox.com) @@ -0,0 +1,336 @@ + GNU GENERAL PUBLIC LICENSE + + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, + Cambridge, MA 02139, USA + + Everyone is permitted to copy and distribute verbatim copies of this + license document, but changing it is not allowed. + + Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to most +of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for this service if you wish), +that you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs; and that you know you +can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny +you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for +a fee, you must give the recipients all the rights that you have. You must make +sure that they, too, receive or can get the source code. And you must show them +these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish +to avoid the danger that redistributors of a free program will individually +obtain patent licenses, in effect making the program proprietary. To prevent +this, we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + + GNU GENERAL PUBLIC LICENSE + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice + placed by the copyright holder saying it may be distributed under the + terms of this General Public License. The "Program", below, refers to any + such program or work, and a "work based on the Program" means either the + Program or any derivative work under copyright law: that is to say, a work + containing the Program or a portion of it, either verbatim or with + modifications and/or translated into another language. (Hereinafter, + translation is included without limitation in the term "modification".) + Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of running + the Program is not restricted, and the output from the Program is covered + only if its contents constitute a work based on the Program (independent + of having been made by running the Program). Whether that is true depends + on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code + as you receive it, in any medium, provided that you conspicuously and + appropriately publish on each copy an appropriate copyright notice and + disclaimer of warranty; keep intact all the notices that refer to this + License and to the absence of any warranty; and give any other recipients + of the Program a copy of this License along with the Program. + + You may charge a fee for the physical act of transferring a copy, and you + may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, + thus forming a work based on the Program, and copy and distribute such + modifications or work under the terms of Section 1 above, provided that + you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any part + thereof, to be licensed as a whole at no charge to all third parties + under the terms of this License. + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the most ordinary way, to print or display an announcement + including an appropriate copyright notice and a notice that there is + no warranty (or else, saying that you provide a warranty) and that + users may redistribute the program under these conditions, and + telling the user how to view a copy of this License. (Exception: if + the Program itself is interactive but does not normally print such an + announcement, your work based on the Program is not required to print + an announcement.) + + These requirements apply to the modified work as a whole. If identifiable + sections of that work are not derived from the Program, and can be + reasonably considered independent and separate works in themselves, then + this License, and its terms, do not apply to those sections when you + distribute them as separate works. But when you distribute the same + sections as part of a whole which is a work based on the Program, the + distribution of the whole must be on the terms of this License, whose + permissions for other licensees extend to the entire whole, and thus to + each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest your + rights to work written entirely by you; rather, the intent is to exercise + the right to control the distribution of derivative or collective works + based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of a + storage or distribution medium does not bring the other work under the + scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under + Section 2) in object code or executable form under the terms of Sections 1 + and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and 2 + above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, + to give any third party, for a charge no more than your cost of + physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed + only for noncommercial distribution and only if you received the + program in object code or executable form with such an offer, in + accord with Subsection b above.) + + The source code for a work means the preferred form of the work for making + modifications to it. For an executable work, complete source code means + all the source code for all modules it contains, plus any associated + interface definition files, plus the scripts used to control compilation + and installation of the executable. However, as a special exception, the + source code distributed need not include anything that is normally + distributed (in either source or binary form) with the major components + (compiler, kernel, and so on) of the operating system on which the + executable runs, unless that component itself accompanies the executable. + + If distribution of executable or object code is made by offering access to + copy from a designated place, then offering equivalent access to copy the + source code from the same place counts as distribution of the source code, + even though third parties are not compelled to copy the source along with + the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as + expressly provided under this License. Any attempt otherwise to copy, + modify, sublicense or distribute the Program is void, and will + automatically terminate your rights under this License. However, parties + who have received copies, or rights, from you under this License will not + have their licenses terminated so long as such parties remain in full + compliance. + +5. You are not required to accept this License, since you have not signed + it. However, nothing else grants you permission to modify or distribute + the Program or its derivative works. These actions are prohibited by law + if you do not accept this License. Therefore, by modifying or distributing + the Program (or any work based on the Program), you indicate your + acceptance of this License to do so, and all its terms and conditions for + copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the original + licensor to copy, distribute or modify the Program subject to these terms + and conditions. You may not impose any further restrictions on the + recipients' exercise of the rights granted herein. You are not responsible + for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot distribute + so as to satisfy simultaneously your obligations under this License and + any other pertinent obligations, then as a consequence you may not + distribute the Program at all. For example, if a patent license would not + permit royalty-free redistribution of the Program by all those who receive + copies directly or indirectly through you, then the only way you could + satisfy both it and this License would be to refrain entirely from + distribution of the Program. + + If any portion of this section is held invalid or unenforceable under any + particular circumstance, the balance of the section is intended to apply + and the section as a whole is intended to apply in other circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any such + claims; this section has the sole purpose of protecting the integrity of + the free software distribution system, which is implemented by public + license practices. Many people have made generous contributions to the + wide range of software distributed through that system in reliance on + consistent application of that system; it is up to the author/donor to + decide if he or she is willing to distribute software through any other + system and a licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed to be a + consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain + countries either by patents or by copyrighted interfaces, the original + copyright holder who places the Program under this License may add an + explicit geographical distribution limitation excluding those countries, + so that distribution is permitted only in or among countries not thus + excluded. In such case, this License incorporates the limitation as if + written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of + the General Public License from time to time. Such new versions will be + similar in spirit to the present version, but may differ in detail to + address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", you have the option of following the terms and conditions + either of that version or of any later version published by the Free + Software Foundation. If the Program does not specify a version number of + this License, you may choose any version ever published by the Free + Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs + whose distribution conditions are different, write to the author to ask + for permission. For software which is copyrighted by the Free Software + Foundation, write to the Free Software Foundation; we sometimes make + exceptions for this. Our decision will be guided by the two goals of + preserving the free status of all derivatives of our free software and of + promoting the sharing and reuse of software generally. + + NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR + THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN + OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES + PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS + TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE + PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, + REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, + INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES + ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT + LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES + SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE + WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + +------------------------------------------------------------------------------- + + Appendix: How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively convey the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <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., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it +starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the program, if necessary. Here is +a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (which makes passes at compilers) written by + James Hacker. + + <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. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..d3d4c89 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,183 @@ +2004-04-06 Keith W. Sheffield <sheff@pobox.com> + + * README: Added some basic user documentation. + + * mkdir.c (e2mkdir): Updated the usage string and modified to + always use the default user and group information. + + * write.c (put_file): Added a default file stat parameter. + + * copy.c (copy): Corrected usage when -d is to a local directory. + Updated the usage string. Modified to pass the default file stat + to put_file(). + + * rm.c (e2rm): Corrected getopt and usage strings. + + * elist.c (elist_delete): Modified to correctly update the + previous and next nodes in the list. + + * ls.c: Modified to print "No files found!" for empty directories, + corrected the directory name display, and fixed REGEX_OPT masking. + +2003-07-12 Keith W. Sheffield <sheff@pobox.com> + + * Makefile.am (install-exec-hook): using $(LN_S) + + * tail.c (do_tail): fixed a bug when no arguments are given + +2003-07-10 Keith W. Sheffield <sheff@pobox.com> + + * configure.in: initial version + + * Makefile.am: initial version + +2002-08-08 Keith W. Sheffield <sheff@pobox.com> + + * e2tools.c: Added a new feature suggested by Ralf Spenneberg: + e2tail. It can operate in follow mode or just dump N lines mode. + + * read.c (retrieve_data): Split out the copy loop into its own + function read_to_eof() which can jump to an offset if needed. + +2002-07-08 Keith W. Sheffield <sheff@pobox.com> + + * mkdir.c (create_dir): fixed a bug in the error reporting that + was truncating the full file name. + + * copy.c: Corrected the destination directory name for verbose and + error output. + +2002-06-30 Keith W. Sheffield <sheff@pobox.com> + + * ln.c (create_hard_link): Testing file type before linking to + directory. + +2002-06-26 Keith W. Sheffield <sheff@pobox.com> + + * write.c (store_data): Added call to update_progress + (put_file): Called ext2fs_flush() before returning + + * copy.c: Corrected copying from stdin and added a call to + initialize the file copy progress information. + + +2002-06-05 Keith W. Sheffield <sheff@pobox.com> + + * ls.c (long_disp): Increased file size field width. + (do_list_dir): Added -f and -D options. Allow for multiple file + specifications. + + * elist.c: Added a new function: elist_delete + +2002-06-03 Keith W. Sheffield <sheff@pobox.com> + + * ls.c (do_list_dir): Added -t -c -r -a -i options and modular + display and sort functions. + (list_dir_proc): Removed display code and just adds inode and + filename information to a linked list. + + * elist.c: Added a new function: elist_sort + +2002-05-31 Keith W. Sheffield <sheff@pobox.com> + + * ls.c: Added regular expression support. + + * rm.c: Added code to handle regular expressions and recursive + directory removal. + + * util.c: Added routines to check if a file is a shell regular + expression and one to create a standard regular expression and + compile it. + +2002-05-21 Keith W. Sheffield <sheff@pobox.com> + + * copy.c (find_link): Fixed the list ordered search bug. + +2002-05-06 Keith W. Sheffield <sheff@pobox.com> + + * copy.c (open_destination): Fixed a bug where if the destination + filespec was just localpath:, the file would not be copied to the + root directory. + +2002-05-02 Keith W. Sheffield <sheff@pobox.com> + + * copy.c (open_destination): Fixed a bug that was causing a file + to be copied to the home directory if the destination file already + existed. + +2002-04-10 Keith W. Sheffield <sheff@pobox.com> + + * e2tools.c (main): new feature: e2rm command + + * e2tools.h: new feature: e2rm() function + + * copy.c: Added the ability to set the file attributes for a + directory from defaults or the values from an existing directory. + + * util.c: Added function init_stat_buf + + * mkdir.c: Added a parameter to contain the default file + attributes for a directory. + +2002-03-21 Keith W. Sheffield <sheff@pobox.com> + + * mv.c (do_swap): new feature: in-place file name swap + + * ln.c (do_ln): Removed code that retrieved the directory name, + directory inode number, and base filename and replaced it with a + function call to get_file_parts(). + +2002-03-20 Keith W. Sheffield <sheff@pobox.com> + + * ln.c (do_ln): separated the ln/mv operations into two separate + functions. b + +2002-03-07 Keith W. Sheffield <sheff@pobox.com> + + * write.c (put_file): Added ability to store the original file's + owner, group, access, modification, and create times. + + * copy.c (copy): Copying hard links to ext2fs correctly, verbose + works + + +2002-03-06 Keith W. Sheffield <sheff@pobox.com> + + * ln.c (do_ln): Modified to perform a file rename/move + + * e2tools.c (main): Added a call to do_ln to implement e2mv + + * util.c (rm_file): checked for return of ext2fs_unlink + +2002-03-05 Keith W. Sheffield <sheff@pobox.com> + + * e2tools.c (main): Added a call to do_ln + + * write.c (put_file): Fixed a bug with reading from stdin. + + * ls.c (do_list_dir): Removed setting optind for SCO + + * mkdir.c (e2mkdir): Removed setting optind for SCO + +2002-02-27 Keith W. Sheffield <sheff@pobox.com> + + * write.c (put_file): Added parameter to pass back the output + file's inode number. + + * copy.c (copy): Added a directory check for file names being read + in from stdin and copied to an ext2fs. + +2002-02-26 Keith W. Sheffield <sheff@pobox.com> + + * Makefile: added definitions to auto-checkout and added new + program e2mkdir. + + * e2tools.c (main): added a call to e2mkdir + + * mkdir.c: Added a new function e2mkdir + + * e2tools.h: Added a section for external prototypes. + + * copy.c (copy): removed unnecessary printf. + + @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..ca4a2bc --- /dev/null +++ b/Makefile.am @@ -0,0 +1,29 @@ +INCLUDES = -I@includedir@ + +.c.o: + $(COMPILE) -c $< + +bin_PROGRAMS = e2cp +e2cp_SOURCES = copy.c \ + e2tools.c e2tools.h \ + elist.c elist.h \ + ln.c \ + ls.c \ + mkdir.c \ + mv.c \ + progress.c \ + read.c \ + rm.c \ + tail.c \ + util.c \ + write.c +e2cp_LDADD = -L@libdir@ -lext2fs -lcom_err +EXTRA_DIST = README TODO e2tools.spec + +install-exec-hook: + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2ln + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2ls + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2mkdir + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2mv + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2rm + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2tail diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..d2b552d --- /dev/null +++ b/Makefile.in @@ -0,0 +1,346 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +CC = @CC@ +LN_S = @LN_S@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +INCLUDES = -I@includedir@ + +bin_PROGRAMS = e2cp +e2cp_SOURCES = copy.c e2tools.c e2tools.h elist.c elist.h ln.c ls.c mkdir.c mv.c progress.c read.c rm.c tail.c util.c write.c + +e2cp_LDADD = -L@libdir@ -lext2fs -lcom_err +EXTRA_DIST = README TODO e2tools.spec +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_CLEAN_FILES = +PROGRAMS = $(bin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +e2cp_OBJECTS = copy.o e2tools.o elist.o ln.o ls.o mkdir.o mv.o \ +progress.o read.o rm.o tail.o util.o write.o +e2cp_DEPENDENCIES = +e2cp_LDFLAGS = +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ +Makefile.in NEWS TODO aclocal.m4 configure configure.in install-sh \ +missing mkinstalldirs + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = gtar +GZIP_ENV = --best +SOURCES = $(e2cp_SOURCES) +OBJECTS = $(e2cp_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ configure.in + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: @MAINTAINER_MODE_TRUE@$(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(bin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +e2cp: $(e2cp_OBJECTS) $(e2cp_DEPENDENCIES) + @rm -f e2cp + $(LINK) $(e2cp_LDFLAGS) $(e2cp_OBJECTS) $(e2cp_LDADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) dist + -rm -rf $(distdir) + @banner="$(distdir).tar.gz is ready for distribution"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +copy.o: copy.c e2tools.h elist.h +e2tools.o: e2tools.c e2tools.h +elist.o: elist.c elist.h +ln.o: ln.c e2tools.h +ls.o: ls.c e2tools.h elist.h +mkdir.o: mkdir.c e2tools.h +mv.o: mv.c e2tools.h +progress.o: progress.c +read.o: read.c e2tools.h +rm.o: rm.c e2tools.h +tail.o: tail.c e2tools.h +util.o: util.c e2tools.h +write.o: write.c e2tools.h + +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-binPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-binPROGRAMS +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(bindir) + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \ + mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-binPROGRAMS clean-compile clean-tags clean-generic \ + mostlyclean-am + +clean: clean-am + +distclean-am: distclean-binPROGRAMS distclean-compile distclean-tags \ + distclean-generic clean-am + +distclean: distclean-am + -rm -f config.status + +maintainer-clean-am: maintainer-clean-binPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + -rm -f config.status + +.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \ +check-am installcheck-am installcheck install-exec-am install-exec \ +install-data-am install-data install-am install uninstall-am uninstall \ +all-redirect all-am all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +.c.o: + $(COMPILE) -c $< + +install-exec-hook: + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2ln + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2ls + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2mkdir + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2mv + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2rm + $(LN_S) -f e2cp $(DESTDIR)$(bindir)/e2tail + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: @@ -0,0 +1,282 @@ +E2tools is a simple set of GPL'ed utilities to read, write, and +manipulate files in an ext2/ext3 filesystem. These utilities access a +filesystem directly using the ext2fs library. I wrote these tools in order +to copy files into a linux filesystem on a machine that does not have ext2 +support. Of course, they can also be used on a linux machine to read/write +to disk images or floppies without having to mount them or have root +access. + +Supported functionality: + +copy files: e2cp +move files: e2mv +remove files: e2rm +create directory: e2mkdir +create hard links: e2ln +list files/directories: e2ls +output the last part of a file: e2tail + +Requirements: + +e2fsprogs-1.27 or later - http://e2fsprogs.sourceforge.net/ +gcc - e2fsprogs will not compile with some proprietary compilers (ie SCO's) + +If you have questions, comments, patches, or feature requests, just email +them to me. I will do my best to respond in a timely manner. + +Keith Sheffield <sheff@pobox.com> + + +Quickstart Documentation +------------------------ + +In general, to specify a directory or file on an ext2 filesystem for the +e2tools utilities, use the following form: + + filesystem:directory_path + +The filesystem can be an unmounted partition or a regular file that's been +formatted to contain an ext2 filesystem. In general, if a command takes +multiple file names on the command line, if the first one contains an ext2 +file specification, the rest of the files are assumed to be on the same +filesystem until another one is explicitly stated: + +/tmp/boot.img:/tmp/file1 /tmp/file2 /tmp/file3 /tmp/boot2.img:/tmp/file4 + +Files 1-3 are on /tmp/boot.img and the last file is on /tmp/boot2.img + + +e2cp +----- + +This program copies files to/from an e2fs filesystem from/to the machine's +native filesystem. + +Usage: + +e2cp [-0apv][-P mode][-O uid][-G gid][-d dest_dir][-s src_dir][file1..N dest] + +-0 Input lines terminated by a null character +-a Absolute directory names - create directories instead of just copying + into the destination. Only valid for copying into an ext2fs filesystem +-d Destination of files to be copied. May be in the ext2fs filesystem or + the host filesystem. +-G Set the default group to gid. +-O Set the default file owner to uid. +-p Preserve host file attributes (permissions, times, etc.) when copying + files. +-P Set the file permissions (ie 755, 666). +-s The source of the files to be copied. +-v Be verbose. + +A - by itself means to use standard input/output + +Examples: + +Copy a file and use the default permission and ownership of the current user: + +e2cp README.txt /tmp/boot.img:/tmp + +Do the same thing, but keep permissions & ownership: + +e2cp -p README.txt /tmp/boot.img:/tmp + +Dump a file to standard out: + +e2cp /tmp/boot.img:/tmp/README.txt - | wc + +Get a file from standard input and put it on an unmounted partition: + +tar cf - /data/logs|gzip| e2cp - /dev/hdb1:/backup/logs.tar.gz + +Copy the files from one directory and put them under another directory on +an unmounted partition, keeping the original paths, permissions & ownership: + +find /data -type f |tee filelist | e2cp -apv -d /dev/hdb1:/mirror + +Copy files from a directory on an unmounted partition to a local directory +(Note: this does not recreate the directories in the local filesystem, +yet). The list of files are read from standard input: + +e2cp -pv -s /dev/hdb1:/mirror -d /data2 < filelist + +Copy a file to a file system and make the group and ownership root + +e2cp -G 0 -O 0 myfile /tmp/boot.img/boot/rootfile + + +e2mv +---- + +This program moves or renames files on an ext2fs filesystem. + +Usage: + +e2mv [-vfs] source1 [... sourceN] destination + +-f Force the operation to remove any existing files +-s Swap names of the two files +-v Be verbose + +Note: The source files must be explicitly stated. It does not use regular +expressions, yet. + +Examples: + +Rename a file: + +e2cp -v /tmp/boot.img:/boot/grub/grub.conf /boot/grub/grub.conf.old + +If /boot/grub/grub.conf.old already exists and is not a directory, this +will fail. Use -f to force removal. + +Move a file to a different directory (/data/processed): + +e2cp -v /dev/hdb1:/data/input0.txt /data/processed + +To swap the names of two files: + +e2cp -vs /tmp/boot.img:/boot/grub/grub.conf /boot/grub/grub.conf.bk + +To swap two files and use a new name for the first one: + +e2cp -vs boot.img:/boot/grub/grub.conf /boot/grub/grub.c2 /boot/grub/grub.c1 + +/boot/grub/grub.conf is now /boot/grub/grub.c1 +/boot/grub/grub.c2 is now /boot/grub/grub.conf + + +e2rm +---- + +This program removes files and directories on an ext2 filesystem. + +Usage: + +e2rm [-vr] filesystem:filepath ...fileN + +-r Recursively delete files if a directory name is givne +-v Be verbose + +Note: This program expects to have a full ext2 file specification for each +argument. + +Examples: + +Remove a file + +e2rm -v boot.img:/boot/grub/grub.c1 /boot/grub/grub.c2 + +Remove a directory and all the files + +e2rm -r boot.img:/boot/grub + + +e2mkdir +------- + +This program creates a directory on an ext2 filesystem. It behaves similar +to 'mkdir -p'. + + +Usage: + +e2mkdir [-G gid][-O uid][-P mode][-v] filesystem:directory...dirN + +-G Set the default group to gid. +-O Set the default file owner to uid. +-P Set the file permissions (ie 755, 666). +-v Be verbose. + +Note: This program expects to have a full ext2 file specification for each +argument. + +Examples: + +This creates the directory /boot/grub with on boot.img with the current +user and group ids: + +e2mkdir boot.img:/boot/grub + +To override the default ownership and permissions: + +e2mkdir -O 100 -P 700 /dev/hdb1:/data/backup + +e2ln +---- + +This program is used to create hard links on an ext2 filesystem. + +Usage: + +e2ln [-vsf] source destination + +-f Force the operation to remove any existing files +-s Create a symlink +-v Be verbose + +Note: creating symlinks is not operational at this time. + +Examples: + +This will remove /data/process_status if it exists and isn't already a hard +link to /data/info/status. + +e2ln -vf /dev/hdb1:/data/info/status /data/process_status + + +e2ls +---- + +This program is used to list files and directories on an ext2 filesystem. + +Usage: + +e2ls [-acDfilrt][-d dir] file_specification + +-a Show hidden directories +-c Sort by creation time (must include -t when using -l) +-d dir Open the ext2 filesystem specified by dir +-D Show deleted files bracketed with ><. +-f No sorting of the file list +-i Show the inodes (very useful for the -l option) +-l Long listing +-r Reverse the sort order +-t Sort by time + +Note: Files deleted via e2rm sometimes will show up even without the -D +option. It is being investigated. + +Examples: + +e2ls -a boot.img:. +e2ls -l /dev/hdb1:/data + + +e2tail +------ + +This program implements a basic version of the tail command. + +Usage: + +e2tail [-n num_lines][-fF][-s sleep_interval] file + +-n The number of lines to display +-f Output appended data as the file grows. This is inode dependent, so if + the file is renamed, it will keep checking it. +-F Output appended data as the file grows. This is file name dependent, + so if the file is renamed, it will check on any new files with the same + name as the original. This is useful for watching log files that may + be rotated out occasionally. This was requested by a person in the + computer security field for monitoring 'honeypot' type machines. +-s The number of seconds to sleep before checking if the file has grown + while in 'follow' mode. The default is 1. + + +Examples: + +Check /var/log/messages on /dev/sdc1 every 10 seconds + +e2tail -s 10 -F /dev/sdc1:/var/log/messages + @@ -0,0 +1,8 @@ +Create user documentation +htree and extended attribute support +automated test suite +Add e2rm with regular expressions +Make copy aware of symbolic links +Add comments +Add e2mknod +Add e2test diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..bd342b7 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,137 @@ +dnl aclocal.m4 generated automatically by aclocal 1.2d + +dnl Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc. +dnl This Makefile.in 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 This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AC_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Add --enable-maintainer-mode option to configure. +# From Jim Meyering + +# serial 1 + +AC_DEFUN(AM_MAINTAINER_MODE, +[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) + dnl maintainer-mode is disabled by default + AC_ARG_ENABLE(maintainer-mode, +[ --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + USE_MAINTAINER_MODE=$enableval, + USE_MAINTAINER_MODE=no) + AC_MSG_RESULT($USE_MAINTAINER_MODE) + AM_CONDITIONAL(MAINTAINER_MODE, test $USE_MAINTAINER_MODE = yes) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST(MAINT)dnl +] +) + +# Define a conditional. + +AC_DEFUN(AM_CONDITIONAL, +[AC_SUBST($1_TRUE) +AC_SUBST($1_FALSE) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi]) + diff --git a/configure b/configure new file mode 100755 index 0000000..9e50cb0 --- /dev/null +++ b/configure @@ -0,0 +1,2185 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +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=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -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 ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$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" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$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) + # 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 << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$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" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + 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) + 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" ;; + + -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 ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=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" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=e2tools.c + +# 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 its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + 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 + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# 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 +# 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" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:559: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/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 + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +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. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&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_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:612: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:669: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=e2tools + +VERSION=0.0.16 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi +cat >> confdefs.h <<EOF +#define PACKAGE "$PACKAGE" +EOF + +cat >> confdefs.h <<EOF +#define VERSION "$VERSION" +EOF + + + +missing_dir=`cd $ac_aux_dir && pwd` +echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 +echo "configure:715: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:728: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:741: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:754: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:767: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:784: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +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 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:814: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_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 $# -gt 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 + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:865: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:897: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 908 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:939: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:944: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:953: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:972: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&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 + +# 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 +# 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" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:1015: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/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 + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +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. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&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_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:1068: checking whether ln -s works" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:1089: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 +echo "configure:1116: checking whether to enable maintainer-specific portions of Makefiles" >&5 + # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then + enableval="$enable_maintainer_mode" + USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + echo "$ac_t""$USE_MAINTAINER_MODE" 1>&6 + + +if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + MAINT=$MAINTAINER_MODE_TRUE + + + + + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1142: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext <<EOF +#line 1157 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1163: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext <<EOF +#line 1174 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1180: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext <<EOF +#line 1191 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1197: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1222: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1227 "configure" +#include "confdefs.h" +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1235: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 1252 "configure" +#include "confdefs.h" +#include <string.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + 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 > conftest.$ac_ext <<EOF +#line 1270 "configure" +#include "confdefs.h" +#include <stdlib.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + 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 > conftest.$ac_ext <<EOF +#line 1291 "configure" +#include "confdefs.h" +#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#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)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1302: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +for ac_hdr in errno.h fcntl.h sys/time.h unistd.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1329: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1334 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1339: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:1367: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1372 "configure" +#include "confdefs.h" + +int main() { + +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:1421: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for mode_t""... $ac_c" 1>&6 +echo "configure:1442: checking for mode_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1447 "configure" +#include "confdefs.h" +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])mode_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_mode_t=yes +else + rm -rf conftest* + ac_cv_type_mode_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_mode_t" 1>&6 +if test $ac_cv_type_mode_t = no; then + cat >> confdefs.h <<\EOF +#define mode_t int +EOF + +fi + +echo $ac_n "checking for off_t""... $ac_c" 1>&6 +echo "configure:1475: checking for off_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1480 "configure" +#include "confdefs.h" +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_off_t=yes +else + rm -rf conftest* + ac_cv_type_off_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_off_t" 1>&6 +if test $ac_cv_type_off_t = no; then + cat >> confdefs.h <<\EOF +#define off_t long +EOF + +fi + +echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 +echo "configure:1508: checking whether time.h and sys/time.h may both be included" >&5 +if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1513 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <sys/time.h> +#include <time.h> +int main() { +struct tm *tp; +; return 0; } +EOF +if { (eval echo configure:1522: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_time=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_time=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_time" 1>&6 +if test $ac_cv_header_time = yes; then + cat >> confdefs.h <<\EOF +#define TIME_WITH_SYS_TIME 1 +EOF + +fi + +echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 +echo "configure:1543: checking whether struct tm is in sys/time.h or time.h" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1548 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <time.h> +int main() { +struct tm *tp; tp->tm_sec; +; return 0; } +EOF +if { (eval echo configure:1556: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_tm=time.h +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_tm=sys/time.h +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_tm" 1>&6 +if test $ac_cv_struct_tm = sys/time.h; then + cat >> confdefs.h <<\EOF +#define TM_IN_SYS_TIME 1 +EOF + +fi + + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 +echo "configure:1580: checking for working alloca.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1585 "configure" +#include "confdefs.h" +#include <alloca.h> +int main() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:1592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_header_alloca_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_alloca_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_alloca_h" 1>&6 +if test $ac_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi + +echo $ac_n "checking for alloca""... $ac_c" 1>&6 +echo "configure:1613: checking for alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1618 "configure" +#include "confdefs.h" + +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include <malloc.h> +# define alloca _alloca +# else +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +int main() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if { (eval echo configure:1646: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_func_alloca_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_func_alloca_works=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_func_alloca_works" 1>&6 +if test $ac_cv_func_alloca_works = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA 1 +EOF + +fi + +if test $ac_cv_func_alloca_works = no; then + # 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=alloca.${ac_objext} + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 +echo "configure:1678: checking whether alloca needs Cray hooks" >&5 +if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1683 "configure" +#include "confdefs.h" +#if defined(CRAY) && ! defined(CRAY2) +webecray +#else +wenotbecray +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "webecray" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_os_cray=yes +else + rm -rf conftest* + ac_cv_os_cray=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_os_cray" 1>&6 +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1708: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1713 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* 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_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1736: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<EOF +#define CRAY_STACKSEG_END $ac_func +EOF + + break +else + echo "$ac_t""no" 1>&6 +fi + +done +fi + +echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 +echo "configure:1763: checking stack direction for C alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat > conftest.$ac_ext <<EOF +#line 1771 "configure" +#include "confdefs.h" +find_stack_direction () +{ + static char *addr = 0; + auto char dummy; + if (addr == 0) + { + addr = &dummy; + return find_stack_direction (); + } + else + return (&dummy > addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +if { (eval echo configure:1790: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_c_stack_direction=1 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_stack_direction=-1 +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 +cat >> confdefs.h <<EOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +EOF + +fi + +echo $ac_n "checking whether utime accepts a null argument""... $ac_c" 1>&6 +echo "configure:1812: checking whether utime accepts a null argument" >&5 +if eval "test \"`echo '$''{'ac_cv_func_utime_null'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata; > conftestdata +# Sequent interprets utime(file, 0) to mean use start of epoch. Wrong. +if test "$cross_compiling" = yes; then + ac_cv_func_utime_null=no +else + cat > conftest.$ac_ext <<EOF +#line 1822 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <sys/stat.h> +main() { +struct stat s, t; +exit(!(stat ("conftestdata", &s) == 0 && utime("conftestdata", (long *)0) == 0 +&& stat("conftestdata", &t) == 0 && t.st_mtime >= s.st_mtime +&& t.st_mtime - s.st_mtime < 120)); +} +EOF +if { (eval echo configure:1833: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_utime_null=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_utime_null=no +fi +rm -fr conftest* +fi + +rm -f core core.* *.core +fi + +echo "$ac_t""$ac_cv_func_utime_null" 1>&6 +if test $ac_cv_func_utime_null = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_UTIME_NULL 1 +EOF + +fi + +for ac_func in gettimeofday regcomp strdup strtol +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:1859: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1864 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* 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_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1887: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + +trap '' 1 2 15 +cat > confcache <<\EOF +# 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. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# 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. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +cat > conftest.defs <<\EOF +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g +s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g +s%\[%\\&%g +s%\]%\\&%g +s%\$%$$%g +EOF +DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` +rm -f conftest.defs + + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@LN_S@%$LN_S%g +s%@MAINTAINER_MODE_TRUE@%$MAINTAINER_MODE_TRUE%g +s%@MAINTAINER_MODE_FALSE@%$MAINTAINER_MODE_FALSE%g +s%@MAINT@%$MAINT%g +s%@CPP@%$CPP%g +s%@ALLOCA@%$ALLOCA%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +EOF +cat >> $CONFIG_STATUS <<EOF + +EOF +cat >> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..366a0bf --- /dev/null +++ b/configure.in @@ -0,0 +1,31 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(e2tools.c) +AM_INIT_AUTOMAKE(e2tools, 0.0.16) + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AM_MAINTAINER_MODE + +dnl Checks for libraries. + + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(errno.h fcntl.h sys/time.h unistd.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_MODE_T +AC_TYPE_OFF_T +AC_HEADER_TIME +AC_STRUCT_TM + +dnl Checks for library functions. +AC_FUNC_ALLOCA +AC_FUNC_UTIME_NULL +AC_CHECK_FUNCS(gettimeofday regcomp strdup strtol) + +AC_OUTPUT(Makefile) @@ -0,0 +1,1202 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/copy.c,v 0.16 2004/04/07 01:15:20 ksheff Exp $ */ +/* + * copy.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + */ + +#ifndef COPY_C +#define COPY_C +#endif + +/* Description */ +/* + * This module contains functions used to copy files to and from an ext2fs + * filesystem + * + */ +/* + * $Log: copy.c,v $ + * Revision 0.16 2004/04/07 01:15:20 ksheff + * Modified to pass the default file stat to put_file() so the user may alter + * the owner, group, or permissions of a file copied to an ext2fs file system. + * + * Revision 0.15 2004/04/07 00:13:38 ksheff + * Corrected behavior when the argument to -d is a local filesystem. + * + * Revision 0.14 2004/04/06 23:26:37 ksheff + * Updated the usage string. + * + * Revision 0.13 2002/07/09 06:43:19 ksheff + * compensated for blank dest_dir. + * + * Revision 0.12 2002/07/09 06:31:41 ksheff + * Forgot to remove debugging printfs. + * + * Revision 0.11 2002/07/09 02:36:51 ksheff + * Verbose was not always reporting the correct output destination - fixed. + * + * Revision 0.10 2002/06/26 11:13:46 ksheff + * Added a call to init_progress() before any copy operation if the verbose + * flag is set. + * + * Revision 0.9 2002/06/19 00:52:00 ksheff + * Fixed read from stdin to filesystem. + * + * Revision 0.8 2002/05/22 03:00:39 ksheff + * Fixed the search order bug in find_link(). + * + * Revision 0.7 2002/05/06 06:37:50 ksheff + * Fixed a bug where if the destination filespec was just localpath:, the file + * would not be copied to the root directory. + * + * Revision 0.6 2002/05/02 07:15:49 ksheff + * Fixed a bug that was causing a file to be copied to the home directory if + * the destination file already existed. + * + * Revision 0.5 2002/04/10 09:29:40 ksheff + * Added the ability to set or keep the ownership, group, and permissions for + * directories being created. + * + * Revision 0.4 2002/03/07 07:16:16 ksheff + * Modified to copy hard links to an ext2fs system correctly. + * + * Revision 0.3 2002/02/27 13:34:16 ksheff + * Added a directory check for file names read from stdin and copied to an + * ext2fs. + * + * Revision 0.2 2002/02/27 05:05:45 ksheff + * Removed unnecessary printf + * + * Revision 0.1 2002/02/27 04:46:46 ksheff + * initial revision + * + */ + +/* Feature Test Switches */ +/* Headers */ + +#include "e2tools.h" +#include "elist.h" + +/* Macros */ +#define USAGE "Usage: e2cp [-0apv][-P mode][-O uid][-G gid][-d dest_dir][-s src_dir][file1...N dest]\n" +#define BUF_SIZE 8192 + +#ifdef isspace +#define ISSPACE(c) isspace(c) +#else +#define ISSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r' \ + || (c) == '\f' || (c) == '\v') +#endif + +/* Structures and Unions */ +typedef enum {NONE, HOST_FS, EXT2_FS} FS_CAT_T; +typedef struct +{ + dev_t dev_no; + ino_t ino_no; + ext2_ino_t new_ino; +} INODE_XREF_T; + +/* Local Variables */ + +elist_t *link_list = NULL; +static char cur_out_dir[BUF_SIZE]; + +/* External Prototypes */ + +extern void init_progress(char *file, struct stat *sbuf); + +/* Local Prototypes */ + +long +copy(int argc, char *argv[]); +long +open_destination(char **dest_dir, char **cur_filesys, ext2_filsys *fs, + ext2_ino_t *root, ext2_ino_t *cwd, char *outfile, + int *absolute, FS_CAT_T *dst_cat, int *allow_non_dir, + struct stat *def_stat); +long +copy_files(int num_files, char **cur_file_names, char *dest_dir, char *dest_fs, + ext2_filsys *fs, ext2_ino_t *root, ext2_ino_t orig_cwd, + char *outpath, char *out_file, int max_file_len, + FS_CAT_T src_category, FS_CAT_T dst_category, int absolute, + int keep, int file_to_file, int verbose, struct stat *def_stat); +static char * +diag_output_name(char *odir, int file_to_file, char *ofile); + +long +dir_changed(char *newdir, ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + ext2_ino_t *newcwd, struct stat *def_stat, char *dest_dir); +int +read_line(char *inbuf); +int +read_string(char *inbuf); + +int +my_strcmp(const void *n1, const void *n2); + +INODE_XREF_T * +find_link(struct stat *sbuf); +long +add_link(struct stat *sbuf, ext2_ino_t newfile); +static long +cp_to_ext2fs(ext2_filsys fs, ext2_ino_t cwd, char *in_file, char *out_file, + struct stat *statbuf, int keep, struct stat *def_stat); + + +/* Name: copy() + * + * Description: + * + * This function will copy one or more files from a host filesystem to a + * ext2fs filesystem and vice versa. The files to be copied are presented + * as command line arguments or are read from standard input. The files are + * in the form: + * + * host filesystem: /this/is/a/file + * ext2fs filesystem: filesystem_path:/this/is/another/file + * + * The - character represents stdin/stdout. The meaning will vary depending if + * it used as a source of destination. + * + * Where filesystem_path represents where the ext2fs is located in the + * host or local filesystem. This can be a regular file containing a + * or block device formatted with ext2fs tools. + * + * The parameters are: + * + * -0 Input lines terminated by a null character + * -a Absolute directory names - create directories instead of just + * copying into the destination. Only valid for copying into an + * ext2fs filesystem + * -d Destination of files to be copied. May be in the ext2fs filesystem + * or the host filesystem + * -p Preserve host file attributes (permissions, times, etc.) when + * copying files. + * -s The source of the files to be copied. + * -v Be verbose. + * + * + * Algorithm: + * + * Parse the command line for flags and special parameters + * If there are any parameters left, they are the files to be copied + * If no -s or -d parameters have been processed + * Retrieve the last parameter which is the destination + * If the destination is a ext2fs file specificiation + * Open the filesystem with write capability + * Test to make sure that is a directory and not a file + * Sort the names of the files to be copied. + * For each file + * If it is an ext2fs file specification + * Check to see if it is the same as the last ext2fs spec + * If not, close the prior ext2fs and open the new one + * If the source and destination files are of the same type + * Print a warning message and continue + * Copy the file + * Otherwise, no parameters are left, file list is on stdin + * For each line of input + * If the -0 is not given, strip whitespace off the end + * If the -a option is given + * determine the dirname of the file + * Compare the directory to the last directory processed + * If different + * Make a new directory + * Copy the file + * Close any open ext2fs filesystems + * + * Global Variables: + * + * None. + * + * Arguments: + * + * int argc; The number of arguments + * char *argv[]; The command line arguments + * + * Return Values: + * + * 0 - everything copied successfully + * the error code of what went wrong + * + * Author: Keith W. Sheffield + * Date: 02/20/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 02/27/02 K. Sheffield Added directory check for file names being + * read from stdin and copied to an ext2fs. + * + * 03/06/02 K. Sheffield Copying hard links to ext2fs correctly + */ +long +copy(int argc, char *argv[]) +{ + ext2_filsys fs = NULL; + ext2_ino_t root; + ext2_ino_t orig_cwd; + ext2_ino_t cwd; + char tmpbuf[BUF_SIZE]; + char outpath[BUF_SIZE]; + char *last_filesys = NULL; + char *cur_filesys = NULL; + int retval; + int c; + char *src_dir = NULL; + char *dest_dir = NULL; + char *in_file = NULL; + char *out_file = NULL; + int max_out_len; + int keep = 0; + int absolute = 0; + int verbose = 0; + FS_CAT_T src_category = NONE; + FS_CAT_T dst_category = NONE; + char **cur_file_name; + int (*read_input)(char *buf) = read_line; + int errcnt = 0; + int num_files; + char *ptr; + int non_directory = 0; + struct stat statbuf; + struct stat def_stat; + INODE_XREF_T *xref; + int tmp_val; + + init_stat_buf(&def_stat); + +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif + while ((c = getopt(argc, argv, "0ad:G:O:pP:s:v")) != EOF) + { + switch (c) + { + case '0': + read_input = read_string; + break; + case 'a': + absolute = 1; + break; + case 'd': + dest_dir = optarg; + break; + case 'G': + def_stat.st_gid = atoi(optarg); + def_stat.st_ino = 1; + break; + case 'O': + def_stat.st_uid = atoi(optarg); + def_stat.st_ino = 1; + break; + case 'P': + def_stat.st_mode = strtol(optarg, NULL, 8); + def_stat.st_ino = 1; + break; + case 'p': + keep = 1; + def_stat.st_ino = 1; + break; + case 's': + src_dir = optarg; + break; + case 'v': + verbose = 1; + break; + default: + errcnt++; + break; + } + } + + if (errcnt) + { + fputs(USAGE, stderr); + return(1); + } + + /* if the source directory has been specified, go to it */ + if (src_dir != NULL) + { + /* check to see if the destination directory is an ext2fs */ + if (NULL != (ptr = strchr(src_dir, ':'))) + { + *ptr++ = '\0'; + cur_filesys = src_dir; + src_dir = ptr; + src_category = EXT2_FS; + if ((retval = open_filesystem(cur_filesys, &fs, &root, 0))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + orig_cwd = root; + cwd = root; + + if ((*src_dir != '\0' && + strcmp(src_dir, ".") != 0 && + strcmp(src_dir, "/") != 0) && + (retval = change_cwd(fs, root, &cwd, src_dir))) + { + fprintf(stderr, "Error changing to input directory %s\n", + src_dir); + return(-1); + } + + src_category = EXT2_FS; + } + else + { /* deal with a normal host directory */ + if (chdir(src_dir)) + { + perror(src_dir); + fprintf(stderr, "Error changing to input directory %s\n", + src_dir); + return(-1); + } + src_category = HOST_FS; + } + /* get rid of any trailing /'s */ + tmp_val = strlen(src_dir) - 1; + if (src_dir[tmp_val] == '/') + src_dir[tmp_val] = '\0'; + + } + + /* open the destination directory */ + if (dest_dir != NULL) + { + non_directory = 0; + if ((retval = open_destination(&dest_dir, &cur_filesys, &fs, &root, + &cwd, outpath, &absolute, &dst_category, + &non_directory, &def_stat))) + { + fprintf(stderr, "Error opening destination %s:%s\n", cur_filesys, + dest_dir); + if (fs) + ext2fs_close(fs); + return(-1); + } + + orig_cwd = cwd; + max_out_len = strlen(outpath); + out_file = outpath + max_out_len; + if (max_out_len > 0) + { + max_out_len++; + *out_file++ = '/'; + } + + max_out_len = BUF_SIZE - max_out_len - 1; + } + + if (src_category != NONE && src_category == dst_category) + { + fputs("The source and destination must be native and ext2fs\n", stderr); + if (fs) + ext2fs_close(fs); + return(-1); + } + + /* copy any remaining files */ + if (argc > optind) + { + num_files = argc - optind; + if (dest_dir == NULL) + { + dest_dir = argv[optind + (--num_files)]; + if (num_files < 1) + { + fputs(USAGE, stderr); + return(1); + } + non_directory = (num_files == 1); + if ((retval = open_destination(&dest_dir, &cur_filesys, &fs, &root, + &cwd, outpath, &absolute, + &dst_category, &non_directory, + &def_stat))) + { + fprintf(stderr, "Error opening destination %s:%s\n", cur_filesys, + dest_dir); + if (fs) + ext2fs_close(fs); + return(-1); + } + + orig_cwd = cwd; + max_out_len = strlen(outpath); + out_file = outpath + max_out_len; + if (max_out_len > 0 && non_directory == 0) + { + max_out_len++; + *out_file++ = '/'; + } + max_out_len = BUF_SIZE - max_out_len - 1; + } /* src_dir & dest_dir == NULL? */ + + if (num_files > 1 && dest_dir != NULL) + qsort(argv+optind, num_files, sizeof(char *), my_strcmp); + + cur_file_name = argv + optind; + + if ((retval = copy_files(num_files, cur_file_name, dest_dir, cur_filesys, + &fs, &root, orig_cwd, outpath, out_file, + max_out_len, src_category, dst_category, + absolute, keep, non_directory, verbose, + &def_stat))) + { + fputs("Error encountered copying files\n", stderr); + if (fs) + ext2fs_close(fs); + return(-1); + } + } + else + { + /******************************************************************/ + /* read from standard input */ + /******************************************************************/ + + if (src_dir == NULL && dest_dir == NULL) + { + fputs("No input source or destination selected\n", stderr); + if (fs) + ext2fs_close(fs); + return(-1); + } + + if (dest_dir == NULL && dst_category == NONE) + { + dest_dir = outpath; + out_file = outpath; + max_out_len = BUF_SIZE - 1; + } + + if (dst_category == EXT2_FS) + { + strncpy(cur_out_dir, (dest_dir) ? dest_dir : ".", BUF_SIZE); + cur_out_dir[BUF_SIZE-1] = '\0'; + } + + while (-1 != (c = (read_input)(tmpbuf))) + { + if (c < 1) + continue; + + in_file = tmpbuf; + + if (verbose) + init_progress(in_file, &statbuf); + + if (dst_category == EXT2_FS) + { + if (stat(in_file, &statbuf) != 0) + { + perror(in_file); + continue; + } + + if (S_ISDIR(statbuf.st_mode)) + { + if (absolute && + (retval = dir_changed(in_file, fs, root, + orig_cwd, &cwd, + (keep)?&statbuf:&def_stat, + dest_dir))) + { + fprintf(stderr,"Error creating output directory %s\n", + dest_dir); + if (fs) + ext2fs_close(fs); + return(-1); + } + continue; + } + + /* can't handle anything other than regular files right now */ + if (!S_ISREG(statbuf.st_mode)) + continue; + + + if (NULL != (ptr = strrchr(in_file, '/'))) + { + *ptr = '\0'; + + if (absolute && + (retval = dir_changed(in_file, fs, root, orig_cwd, + &cwd, &def_stat, dest_dir))) + { + fprintf(stderr,"Error creating output directory %s\n", + dest_dir); + if (fs) + ext2fs_close(fs); + return(-1); + } + + *ptr = '/'; + out_file = ptr + 1; + } /* partial path included ? */ + else + { + cwd = orig_cwd; + out_file = in_file; + } + + if (statbuf.st_nlink > 1) + { + if (NULL != (xref = find_link(&statbuf))) + { + if ((retval = create_hard_link(fs, cwd, xref->new_ino, + out_file, E2T_FORCE))) + { + fprintf(stderr, "Error creating link for %s/%s\n", + cur_out_dir, out_file); + if (fs) + ext2fs_close(fs); + elist_free(link_list, free); + return(1); + } + if (verbose) + fprintf(stderr, "Copied %s to %s:%s\n", in_file, + cur_filesys, cur_out_dir); + continue; + } + } + if ((retval = cp_to_ext2fs(fs, cwd, in_file, out_file, + &statbuf, keep, &def_stat))) + { + fprintf(stderr, "Error copying file %s to %s:%s\n", + in_file, cur_filesys, dest_dir); + if (fs) + ext2fs_close(fs); + return retval; + } + if (verbose) + fprintf(stderr, "Copied %s to %s:%s\n", in_file, cur_filesys, + cur_out_dir); + + } + else + { /* copy to the local file system */ + + /* get the basename of the file */ + if (NULL != (ptr = strrchr(in_file, '/'))) + ++ptr; + else + ptr = in_file; + + if (dest_dir != NULL) + { + /* create output file name */ + strncpy(out_file, ptr, max_out_len); + outpath[BUF_SIZE-1] = '\0'; + } + + if ((retval = get_file(fs, root, cwd, in_file, + (dest_dir == NULL) ? NULL:outpath, keep))) + { + fprintf(stderr, "Error copying file %s to %s\n", + in_file, outpath); + if (fs) + ext2fs_close(fs); + return retval; + } + + if (verbose) + fprintf(stderr, "Copied %s:%s/%s to %s\n", cur_filesys, + src_dir, in_file, + (dest_dir == NULL) ? outpath : dest_dir); + } + + } + } + + if (fs) + ext2fs_close(fs); + + return(0); +} /* end of copy */ + +long +open_destination(char **dest_dir, char **cur_filesys, ext2_filsys *fs, + ext2_ino_t *root, ext2_ino_t *cwd, char *outfile, + int *absolute, FS_CAT_T *dst_cat, int *allow_non_dir, + struct stat *def_stat) +{ + char *ptr; + struct stat statbuf; + char *dptr; + int retval; + ext2_ino_t inode; + int new_dir = 1; + + if (dest_dir == NULL || cur_filesys == NULL || fs == NULL || root == NULL || + cwd == NULL || outfile == NULL) + { + fputs("Invalid parameters\n", stderr); + return(-1); + } + + dptr = *dest_dir; + *outfile = '\0'; + + /* check to see if the destination directory is an ext2fs */ + if (NULL != (ptr = strchr(dptr, ':'))) + { + if (*fs != NULL) + { + fputs("An Ext2fs filesystem is already open!", stderr); + return(-1); + } + + *ptr++ = '\0'; + *cur_filesys = dptr; + dptr = ptr; + *dst_cat = EXT2_FS; + if ((retval = open_filesystem(*cur_filesys, fs, root, 1))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + + *cwd = *root; + + if ((*dptr != '\0' && + strcmp(dptr, ".") != 0 && + strcmp(dptr, "/") != 0)) + { + + if (*allow_non_dir == 1) + { + ptr = NULL; + new_dir = 0; + /* check to see if it exists */ + if ((retval = ext2fs_namei(*fs, *root, *cwd, dptr, &inode)) || + (retval = ext2fs_check_directory(*fs, inode))) + { + if ((retval != EXT2_ET_FILE_NOT_FOUND) && + (retval != EXT2_ET_NO_DIRECTORY)) + { + fprintf(stderr, "%s\n", error_message(retval)); + return(retval); + } + + /* ok, so it doesn't exist or isn't a directory + *...let's see if it's parent does + */ + if (NULL != (ptr = strrchr(dptr, '/'))) + { + *ptr = '\0'; + if (ptr[1] == '\0') + *allow_non_dir = 0; + new_dir = 1; + + if ((retval = ext2fs_namei(*fs, *root, *cwd, dptr, + &inode))) + { + if (retval != EXT2_ET_FILE_NOT_FOUND) + { + fprintf(stderr, "%s\n", error_message(retval)); + return(retval); + } + /* it doesn't exist either */ + } + else + { + if ((retval = ext2fs_check_directory(*fs, inode))) + { + /* ok, it exists, but it's not a directory... */ + fprintf(stderr, "%s\n", error_message(retval)); + return(retval); + } + *cwd = inode; + new_dir = 0; + } + } + } + else + { + /* ok, the directory exists */ + *cwd = inode; + *allow_non_dir = 0; + } + } + + if (new_dir == 1 && + (retval = create_dir(*fs, *root, cwd, dptr, def_stat))) + { + fprintf(stderr, "Error creating output directory %s\n", + dptr); + return(-1); + } + /* see if we need to copy the file into the output path */ + if (*allow_non_dir == 1) + { + strncpy(outfile, (ptr != NULL) ? ++ptr : dptr, BUF_SIZE); + outfile[BUF_SIZE-1] = '\0'; + } + } + else + { + if (*allow_non_dir == 1) + { + *allow_non_dir = 0; + dptr = NULL; + } + } + } + else + { /* deal with a normal host directory */ + *absolute = 0; + if (strcmp(dptr, "-") == 0) + dptr = NULL; + else + { + strncpy(outfile, dptr, BUF_SIZE); + outfile[BUF_SIZE-1] = '\0'; + + if (0 > stat(outfile, &statbuf) || + !S_ISDIR(statbuf.st_mode)) + { + if (*allow_non_dir == 0) + { + fprintf(stderr, "%s is not a directory!\n", outfile); + return(-1); + } + } + else + *allow_non_dir = 0; + } + + *dst_cat = HOST_FS; + } + *dest_dir = dptr; + return(0); +} + +long +copy_files(int num_files, char **cur_file_names, char *dest_dir, char *dest_fs, + ext2_filsys *fs, ext2_ino_t *root, ext2_ino_t orig_cwd, + char *outpath, char *out_file, int max_file_len, + FS_CAT_T src_category, FS_CAT_T dst_category, int absolute, + int keep, int file_to_file, int verbose, struct stat *def_stat) +{ + char *in_file; + char *dst_file; + char *ptr; + char *last_filesys = NULL; + char *cur_filesys = dest_fs; + ext2_ino_t cwd = orig_cwd; + int retval; + int i; + struct stat statbuf; + INODE_XREF_T *xref; + + strncpy(cur_out_dir, (dest_dir) ? dest_dir : ".", BUF_SIZE); + cur_out_dir[BUF_SIZE-1] = '\0'; + + for(i=0;i<num_files;i++) + { + in_file = *cur_file_names++; + + if (verbose) + init_progress(in_file, &statbuf); + /* dealing with a filesystem or a regular file */ + if (NULL != (ptr = strchr(in_file, ':'))) + { + if (dst_category == EXT2_FS) + { + fputs("Already copying to an ext2fs!\n", stderr); + return(-1); + } + if (src_category == EXT2_FS) + { + fputs("The source is already an ext2fs!\n", stderr); + return(-1); + } + + /* separate the filesystem name from the file name */ + *ptr++ = '\0'; + cur_filesys = in_file; + in_file = ptr; + + if (dest_dir != NULL) + { + if (!file_to_file) + { + /* get the basename of the file */ + if (NULL != (ptr = strrchr(in_file, '/'))) + ++ptr; + else + ptr = in_file; + + /* create output file name */ + strncpy(out_file, ptr, max_file_len); + outpath[BUF_SIZE-1] = '\0'; + } + } + + /* check to see if the filesystem has changed */ + if (last_filesys == NULL || + strcmp(last_filesys, cur_filesys) != 0) + { + if (last_filesys != NULL && + (retval = ext2fs_close(*fs))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + + if ((retval = open_filesystem(cur_filesys, fs, root, 0))) + { + fprintf(stderr, "%s\n", error_message(retval)); + fprintf(stderr, "Error opening fileystem %s\n", + cur_filesys); + return retval; + } + cwd = *root; + last_filesys = cur_filesys; + } /* end of filesystem change? */ + + if ((retval = get_file(*fs, *root, cwd, in_file, + (dest_dir == NULL) ? NULL:outpath, keep))) + { + fprintf(stderr, "Error copying file %s to %s\n", + in_file, outpath); + return retval; + } + } /* end of do we have a filesystem spec? */ + else + { + if (dst_category == HOST_FS) + { + fputs("Already copying to a native filesystem!\n", + stderr); + continue; + } + + + memset(&statbuf, 0, sizeof(statbuf)); + if (strcmp(in_file, "-") == 0) + { + statbuf.st_mode = S_IFREG; + in_file = NULL; + } + + if (in_file != NULL && stat(in_file, &statbuf) != 0) + { + perror(in_file); + continue; + } + + /* can't handle anything other than regular files right now */ + if (!S_ISREG(statbuf.st_mode)) + continue; + + if (file_to_file) + dst_file = outpath; + else + dst_file = in_file; + + if (NULL != (ptr = strrchr(dst_file, '/'))) + { + *ptr = '\0'; + + if (absolute) + { + if ((retval = dir_changed(dst_file, *fs, *root, orig_cwd, + &cwd, def_stat, dest_dir))) + { + fprintf(stderr,"Error creating output directory %s\n", + dst_file); + return(-1); + } + } + *ptr = '/'; + out_file = ptr + 1; + } + else + { + cwd = orig_cwd; + out_file = dst_file; + } + + if (statbuf.st_nlink > 1) + { + if (NULL != (xref = find_link(&statbuf))) + { + if ((retval = create_hard_link(*fs, cwd, xref->new_ino, + out_file, E2T_FORCE))) + { + fprintf(stderr, "Error creating link for %s/%s\n", + cur_out_dir, out_file); + elist_free(link_list, free); + return(1); + } + + if (verbose) + fprintf(stderr, "Copied %s to %s:%s\n", in_file, + cur_filesys, diag_output_name(cur_out_dir, + file_to_file, + outpath)); + + continue; + } + } + + if ((retval = cp_to_ext2fs(*fs, cwd, in_file, out_file, &statbuf, + keep, def_stat))) + { + fprintf(stderr, "Error copying file %s to %s:%s\n", + (in_file) ? in_file : "<stdin>" , cur_filesys, + diag_output_name(cur_out_dir, file_to_file, outpath)); + return retval; + } + if (verbose) + fprintf(stderr, "Copied %s to %s:%s\n", + (in_file) ? in_file : "<stdin>", cur_filesys, + diag_output_name(cur_out_dir, file_to_file, outpath)); + } + } + + return(0); +} + +static char * +diag_output_name(char *odir, int file_to_file, char *ofile) +{ + static char tmpstr[BUF_SIZE]; + if (file_to_file) + { + snprintf(tmpstr, BUF_SIZE, "%s/%s", odir, ofile); + tmpstr[BUF_SIZE-1] = '\0'; + return(tmpstr); + } + else + return(odir); +} + + +long +dir_changed(char *newdir, ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + ext2_ino_t *newcwd, struct stat *def_stat, char *dest_dir) +{ + static char last_cwd[BUF_SIZE]; + static int first = 1; + long retval; + + + if (first || strcmp(last_cwd, newdir)) + { + first = 0; + + *newcwd = cwd; + if ((*newdir != '\0' && + strcmp(newdir, ".") != 0) && + (retval = create_dir(fs, root, newcwd, newdir, def_stat))) + { + fprintf(stderr,"Error creating output " + "directory %s\n", newdir); + return(-1); + } + strncpy(last_cwd, newdir, BUF_SIZE); + last_cwd[BUF_SIZE-1] = '\0'; + + if (*newdir == '/' || dest_dir == NULL || *dest_dir == '\0') + strncpy(cur_out_dir, newdir, BUF_SIZE); + else + snprintf(cur_out_dir, BUF_SIZE, "%s/%s", dest_dir, newdir); + + cur_out_dir[BUF_SIZE-1] = '\0'; + } + return(0); +} + + +int +read_line(char *inbuf) +{ + char *ptr; + char c; + + *inbuf = '\0'; + + if (NULL == fgets(inbuf, BUF_SIZE, stdin)) + { + if (ferror(stdin)) + perror("read_line"); + return(-1); + } + + ptr = inbuf + strlen(inbuf); + ptr--; + + while (ptr >= inbuf) + { + c = *ptr; + if (!ISSPACE(c)) + break; + ptr--; + } + ptr++; + *ptr = '\0'; + return(strlen(inbuf)); +} + +int +read_string(char *inbuf) +{ + char *ptr; + char *boundary; + int c; + int cnt; + + boundary = inbuf + BUF_SIZE - 1; + ptr = inbuf; + *ptr = '\0'; + while ((c = getchar()) != EOF && c != '\0') + { + if (ptr < boundary) + *ptr++ = c; + else + break; + } + + if (c == EOF) + { + if (ferror(stdin)) + { + perror("read_string"); + return(-1); + } + else if (feof(stdin)) + return(-1); + } + *ptr = '\0'; + return(strlen(inbuf)); +} + +int +my_strcmp(const void *n1, const void *n2) +{ + char *s1 = *((char **)n1); + char *s2 = *((char **)n2); + + return(strcmp(s1, s2)); +} + +INODE_XREF_T * +find_link(struct stat *sbuf) +{ + elist_t *n; + INODE_XREF_T *xref; + + n = link_list; + + while (n != NULL) + { + if ((xref = n->data) != NULL) + { + if (xref->dev_no > sbuf->st_dev) + return(NULL); + else if (xref->dev_no == sbuf->st_dev) + { + if (xref->ino_no > sbuf->st_ino) + return(NULL); + else if (xref->ino_no == sbuf->st_ino) + return(xref); + } + } + n = n->next; + } + + return(NULL); +} + +long +add_link(struct stat *sbuf, ext2_ino_t newfile) +{ + INODE_XREF_T *xref; + INODE_XREF_T *x_node; + elist_t *n; + + if (NULL == (xref = malloc(sizeof(INODE_XREF_T)))) + { + perror("malloc"); + return(1); + } + + xref->dev_no = sbuf->st_dev; + xref->ino_no = sbuf->st_ino; + xref->new_ino = newfile; + + if (link_list == NULL) + { + if (NULL == (link_list = elist_new())) + { + perror("elist_new"); + free(xref); + return(1); + } + } + + n = link_list->next; + while (n != NULL) + { + if (NULL != (x_node = n->data)) + { + if (x_node->dev_no > xref->dev_no || + (x_node->dev_no == xref->dev_no && + x_node->ino_no > xref->ino_no)) + { + if (NULL == elist_insert(n, xref)) + { + perror("elist_insert"); + free(xref); + return(1); + } + return(0); + } + } + n = n->next; + } + + if (NULL == elist_append(link_list, xref)) + { + perror("elist_append"); + free(xref); + return(1); + } + return(0); +} + +static long +cp_to_ext2fs(ext2_filsys fs, ext2_ino_t cwd, char *in_file, char *out_file, + struct stat *statbuf, int keep, struct stat *def_stat) +{ + long retval; + ext2_ino_t out_file_ino; + + if ((retval = put_file(fs, cwd, in_file, out_file, + &out_file_ino, keep, def_stat))) + { + elist_free(link_list, free); + return retval; + } + if (statbuf->st_nlink > 1) + { + if ((retval = add_link(statbuf, out_file_ino))) + { + fprintf(stderr, "Error adding link info for %s to list\n", + out_file); + elist_free(link_list, free); + return retval; + } + } + return(0); +} diff --git a/e2tools.c b/e2tools.c new file mode 100644 index 0000000..abb61c5 --- /dev/null +++ b/e2tools.c @@ -0,0 +1,78 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/e2tools.c,v 0.7 2002/08/08 07:55:03 ksheff Exp $ */ +/* + * e2tools.c + */ + +#ifndef E2TOOLS_C +#define E2TOOLS_C +#endif + +/* Description */ +/* + * + * + */ +/* + * $Log: e2tools.c,v $ + * Revision 0.7 2002/08/08 07:55:03 ksheff + * Added e2tail + * + * Revision 0.6 2002/04/10 10:43:09 ksheff + * Added e2rm + * + * Revision 0.5 2002/03/21 04:38:14 ksheff + * Created a separate do_mv function instead of overloading do_ln. + * + * Revision 0.4 2002/03/07 07:17:24 ksheff + * Added ability to move files on an ext2fs. + * + * Revision 0.3 2002/03/05 14:02:30 ksheff + * Added a call to do_ln() if the user wants to invoke the ln program. + * + * Revision 0.2 2002/02/27 05:26:22 ksheff + * Added a call to e2mkdir if the user wants to invoke the mkdir program. + * + * Revision 0.1 2002/02/27 04:47:21 ksheff + * initial revision + * + */ + +/* Feature Test Switches */ +/* Headers */ + +#include "e2tools.h" + +int +main(int argc, char *argv[]) +{ + char *ptr; + + if (NULL != (ptr = strrchr(argv[0], '/'))) + ptr++; + else + ptr = argv[0]; + + initialize_ext2_error_table(); + + if (strcmp(ptr, "e2ls") == 0) + exit(do_list_dir(argc, argv)); + else if (strcmp(ptr, "e2cp") == 0) + exit(copy(argc, argv)); + else if (strcmp(ptr, "e2mkdir") == 0) + exit(e2mkdir(argc, argv)); + else if (strcmp(ptr, "e2ln") == 0) + exit(do_ln(argc, argv)); + else if (strcmp(ptr, "e2mv") == 0) + exit(do_mv(argc, argv)); + else if (strcmp(ptr, "e2rm") == 0) + exit(e2rm(argc, argv)); + else if (strcmp(ptr, "e2tail") == 0) + exit(do_tail(argc, argv)); + else + { + fprintf(stderr, "Not implemented\n"); + exit(1); + } + return(0); +} + diff --git a/e2tools.h b/e2tools.h new file mode 100644 index 0000000..285f776 --- /dev/null +++ b/e2tools.h @@ -0,0 +1,138 @@ +#ifndef E2TOOLS_H +#define E2TOOLS_H + +/* $Header: /home/ksheff/src/e2tools/RCS/e2tools.h,v 0.7 2004/04/07 01:15:55 ksheff Exp $ */ + +/* Copyright 2002 Keith W. Sheffield */ + +/* Description */ +/* + * $Log: e2tools.h,v $ + * Revision 0.7 2004/04/07 01:15:55 ksheff + * Added the parameter struct stat *def_stat to put_file(). + * + * Revision 0.6 2002/08/08 07:57:04 ksheff + * Added new routine do_tail() from tail.c + * Added new routine read_to_eof() from read.c + * Made retrieve_data() from read.c a public routine + * + * Revision 0.5 2002/04/10 10:43:27 ksheff + * Added e2rm(). + * + * Revision 0.4 2002/04/10 09:33:26 ksheff + * Modified prototypes for functions involved with setting directory + * attributes. + * + * Revision 0.3 2002/03/21 09:05:16 ksheff + * Added function prototypes from mv.c and altered do_ln() slightly. + * + * Revision 0.2 2002/03/07 07:26:02 ksheff + * Added function prototypes and defined the macros E2T_FORCE and E2T_DO_MV + * + * Revision 0.1 2002/02/27 04:47:44 ksheff + * initial revision + * + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#include <utime.h> +/* +#ifdef HAVE_GETOPT_H +#include <getopt.h> +#else +#endif +*/ + +#ifdef HAVE_OPTRESET +extern int optreset; /* defined by BSD, but not others */ +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fs.h" + +#define E2T_FORCE 1 +#define E2T_DO_MV 2 + +#ifndef COPY_C +extern long copy(int argc, char *argv[]); +extern int my_strcmp(const void *n1, const void *n2); +#endif + +#ifdef LN_C +extern long do_ln(int argc, char *argv[]); + +extern long create_hard_link(ext2_filsys fs, ext2_ino_t cwd, ext2_ino_t + new_file_ino, char *newfile, int ln_flags); +#endif + +#ifndef LS_C +extern long do_list_dir(int argc, char *argv[]); +#endif + +#ifndef MKDIR_C +extern long e2mkdir(int argc, char *argv[]); +extern long create_dir(ext2_filsys fs, ext2_ino_t root, ext2_ino_t *cwd, + char *dirname, struct stat *def_stat); +#endif + +#ifdef MV_C +extern long do_mv(int argc, char *argv[]); +extern long get_file_parts(ext2_filsys fs, ext2_ino_t root, char *pathname, + ext2_ino_t *dir_ino, char **dir_name, + char **base_name); + +#endif + + +#ifndef READ_C +extern long get_file(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + char *infile, char *outfile, int keep); +extern long retrieve_data(ext2_filsys fs, ext2_ino_t src, int dest_fd, + char *dest_name, int keep, ext2_off_t offset, + ext2_off_t *ret_pos); +extern long read_to_eof(ext2_file_t infile, int dest_fd, ext2_off_t offset, + ext2_off_t *ret_pos); +#endif + +#ifndef RM_C +extern long e2rm(int argc, char *argv[]); +#endif + +#ifndef TAIL_C +extern long do_tail(int argc, char *argv[]); +#endif + +#ifndef UTIL_C +extern mode_t ext2_mode_xlate(__u16 lmode); +extern __u16 host_mode_xlate(mode_t hmode); +extern long open_filesystem(char *name, ext2_filsys *fs, ext2_ino_t *root, int + rw_mode); +extern long read_inode(ext2_filsys fs, ext2_ino_t file, struct ext2_inode + *inode); +extern long write_inode(ext2_filsys fs, ext2_ino_t file, struct ext2_inode + *inode); +extern long rm_file(ext2_filsys fs, ext2_ino_t cwd, char *outfile, ext2_ino_t + delfile); +extern long delete_file(ext2_filsys fs, ext2_ino_t inode); +extern void init_stat_buf(struct stat *buf); +#endif + +#ifndef WRITE_C +extern long +put_file(ext2_filsys fs, ext2_ino_t cwd, char *infile, char *outfile, + ext2_ino_t *outfile_ino, int keep, struct stat *def_stat); +#endif + +#endif + + diff --git a/e2tools.spec b/e2tools.spec new file mode 100644 index 0000000..00d5971 --- /dev/null +++ b/e2tools.spec @@ -0,0 +1,52 @@ +Summary: Tools to access files on an unmounted ext2 filesystem +Name: e2tools +Version: 0.0.16 +Release: 1 +Copyright: GPL +Group: Applications/filesystems +Source0: http://ksheff.net/sw/e2tools/%{name}-%{version}.tar.gz +Patch1: e2tools.diff +BuildRoot: /var/tmp/%{name}-root +Prefix: /usr +Packager: Keith W. Sheffield <sheff@pobox.com> +Requires: e2fsprogs > 1.25 +BuildRequires: e2fsprogs-devel > 1.25 + +%description +E2tools is a simple set of GPL'ed utilities to read, write, and manipulate +files in an ext2/ext3 filesystem. I wrote these tools in order to copy files +into a linux filesystem on a machine that does not have ext2 support. Of +course, they can also be used on a linux machine to read/write to disk images +or floppies without having to mount them. + + +%prep +%setup + +chmod 755 configure +autoconf + +%build +./configure --prefix=$RPM_BUILD_ROOT/usr +make +%install +rm -rf $RPM_BUILD_ROOT +make install +mv -f $RPM_BUILD_ROOT/usr/bin $RPM_BUILD_ROOT/usr/sbin + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%attr(755,root,root) /usr/sbin/ +%doc README TODO COPYING ChangeLog + +%changelog +* Tue Apr 06 2004 Keith Sheffield +- Updated version due to bug fix release. +* Wed Jul 09 2003 Keith Sheffield +- autoconfiscated the build system +* Thu Aug 08 2002 Ralf Spenneberg <ralf@spenneberg.de> +- first release + @@ -0,0 +1,198 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/elist.c,v 0.6 2004/04/06 19:34:44 ksheff Exp $ */ +/* + * elist.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + */ + +#ifndef ELIST_C +#define ELIST_C +#endif + +/* Description */ +/* + * + * + */ +/* + * $Log: elist.c,v $ + * Revision 0.6 2004/04/06 19:34:44 ksheff + * Corrected elist_delete to update the previous node if it exists. + * + * Revision 0.5 2002/06/05 22:05:01 ksheff + * Added elist_delete. + * + * Revision 0.4 2002/06/03 23:02:01 ksheff + * Added the function elist_sort(). + * + * Revision 0.3 2002/04/23 01:49:48 ksheff + * Added a define for NULL if it doesn't exist. + * + * Revision 0.2 2002/03/07 07:33:28 ksheff + * silenced compiler warnings for calloc return value. + * + * Revision 0.1 2002/03/07 07:24:35 ksheff + * initial revision + * + */ + +/* Feature Test Switches */ +/* Headers */ +#include <memory.h> +#include "elist.h" + +#ifndef NULL +#define NULL ((void *)0) +#endif + +elist_t * +elist_new() +{ + elist_t *list; + + list = (elist_t *) calloc(sizeof(elist_t), 1); + return list; +} + +elist_t * +elist_delete(elist_t *l, void (*data_free)(void *)) +{ + elist_t *n; + + if (l) + { + n = l->next; + if (n) + n->prev = l->prev; + if (l->prev) + l->prev->next = n; + if (data_free && l->data) + (*data_free)(l->data); + free(l); + l = n; + } + return(l); +} + +void +elist_free(elist_t *l, void (*data_free)(void *)) +{ + elist_t *n; + + if (l) + { + do + { + l = elist_delete(l, data_free); + } while (l); + } +} + +elist_t * +elist_append(elist_t *l, void *data) +{ + elist_t *n; + elist_t *t; + + if (NULL == (n = elist_new())) + return(NULL); + + n->data = data; + + if (l) + { + t = l; + while (t->next != NULL) t = t->next; + t->next = n; + n->prev = t; + } + else + l = n; + + return(l); +} + +elist_t * +elist_insert(elist_t *l, void *data) +{ + elist_t *n; + + if (NULL == (n = elist_new())) + return(NULL); + n->data = data; + + if (l) + { + n->prev = l->prev; + l->prev = n; + n->next = l; + if (n->prev) + n->prev->next = n; + } + l = n; + + return(l); +} + +void elist_sort(elist_t *l, int (sort_func)(void *, void *), int reverse) +{ + int c=0; + elist_t *tl; + void **data; + void **dptr; + + if (l != NULL && sort_func != NULL) + { + /* count the number of nodes */ + tl = l; + while (tl != NULL) + { + c++; + tl = tl->next; + } + + /* if there are more than 1 nodes, allocate a lookup table */ + if (c > 1 && (NULL != (data = (void **) malloc(c*sizeof(void*))))) + { + /* fill in the lookup table */ + tl = l; + dptr = data; + while (tl != NULL) + { + *dptr++ = tl->data; + tl = tl->next; + } + + qsort(data, c, sizeof(dptr), sort_func); + + /* now fill in the data pointers in the linked list with the + * data nodes in the correct order + */ + tl = l; + if (reverse) + { + dptr = data + c - 1; + while (tl != NULL) + { + tl->data = *dptr--; + tl = tl->next; + } + } + else + { + dptr = data; + while (tl != NULL) + { + tl->data = *dptr++; + tl = tl->next; + } + } + free(data); + } + } +} + + + @@ -0,0 +1,39 @@ +#ifndef ELIST_H +#define ELIST_H + +/* $Header: /home/ksheff/src/e2tools/RCS/elist.h,v 0.3 2002/06/05 22:04:13 ksheff Exp $ */ + +/* Copyright 2002 Keith W. Sheffield */ + +/* + * $Log: elist.h,v $ + * Revision 0.3 2002/06/05 22:04:13 ksheff + * Added elist_delete. + * + * Revision 0.2 2002/06/03 21:02:39 ksheff + * Added elist_sort() definition. + * + * Revision 0.1 2002/03/07 07:24:50 ksheff + * initial revision + * + */ + + +typedef struct _elist_t +{ + struct _elist_t *prev; + struct _elist_t *next; + void *data; +} elist_t; + +#ifndef ELIST_C +extern elist_t * elist_new(); +extern elist_t *elist_delete(elist_t *l, void (*data_free)(void *)); +extern void elist_free(elist_t *l, void (*data_free)(void *)); +extern elist_t * elist_append(elist_t *l, void *data); +extern elist_t * elist_insert(elist_t *l, void *data); +extern void +elist_sort(elist_t *l, int (sort_func)(void *, void *), int reverse); +#endif + +#endif diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..e9de238 --- /dev/null +++ b/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, 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 name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# 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. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# 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}" + +transformbasename="" +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=: + chmodcmd="" + 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 @@ -0,0 +1,388 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/ln.c,v 0.3 2002/06/30 05:54:02 ksheff Exp $ */ +/* + * ln.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + */ + +#ifndef LN_C +#define LN_C +#endif + +/* Description */ +/* + * Module to create links + * + */ +/* + * $Log: ln.c,v $ + * Revision 0.3 2002/06/30 05:54:02 ksheff + * Modified create_hard_link() to check file type before linking to current + * directory. This was not being done before and it was causing problems if a + * non regular file was renamed. + * + * Revision 0.2 2002/03/21 09:04:40 ksheff + * Split the mv operation into its own module. + * + * Revision 0.1 2002/03/07 07:23:41 ksheff + * initial revision. + * + */ + +/* Feature Test Switches */ +/* Headers */ +#include "e2tools.h" + +/* Macros */ +#define USAGE "Usage: e2ln [-vfs] source destination\n" + +/* Local Prototypes */ +long +do_ln(int argc, char *argv[]); + +long +create_hard_link(ext2_filsys fs, ext2_ino_t cwd, ext2_ino_t new_file_ino, + char *newfile, int ln_flags); + +/* Name: do_ln() + * + * Description: + * + * This function reads the command line arguments and creates a link + * in an ext2fs file system + * + * Algorithm: + * + * Read any command line switches + * Get the source file specification + * Open the file system + * Get the directory and basename of the source file + * Determine the inode number for the source file + * If the destination file is not given or if it's a . + * use the current directory and the basename of the source file + * Otherwise + * Get the directory and basename of the destination file + * Create the link + * + * Global Variables: + * + * None + * + * Arguments: + * + * int argc; The number of arguments + * char *argv[]; The command line arguments + * + * Return Values: + * + * 0 - the link was created successfully + * an error occurred. + * + * Author: Keith W. Sheffield + * Date: 03/05/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 03/06/02 K. Sheffield Modified to perform file moves + * 03/20/02 K. Sheffield Moved the mv operation to a separate file + */ +long +do_ln(int argc, char *argv[]) +{ + int verbose=0; + int force=0; + int symlink=0; + int num_files; + int errcnt=0; + char *cur_filesys = NULL; + ext2_filsys fs = NULL; + ext2_ino_t root; + ext2_ino_t srcd; + ext2_ino_t destd; + ext2_ino_t source_file; + char *src_dir; + char *dest_dir; + char *src_name; + char *dest_name; + long retval; + int c; + +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif + while ((c = getopt(argc, argv, "vfs")) != EOF) + { + switch (c) + { + case 'v': + verbose = 1; + break; + case 'f': + force = E2T_FORCE; + break; + case 's': + symlink = 1; + break; + default: + errcnt++; + break; + } + } + + if (errcnt || argc == optind) + { + fputs(USAGE, stderr); + return(1); + } + + if (symlink) + { + fputs("Not implemented yet\n", stderr); + return(1); + } + + cur_filesys = argv[optind++]; + if (NULL == (src_dir = strchr(cur_filesys, ':'))) + { + fprintf(stderr, "Invalid file specification: %s\n", cur_filesys); + return(1); + } + *src_dir++ = '\0'; + + if (*src_dir == '\0') + { + fputs(USAGE, stderr); + return(1); + } + + if ((retval = open_filesystem(cur_filesys, &fs, &root, 1))) + { + fprintf(stderr, "%s: %s\n", error_message(retval), cur_filesys); + return retval; + } + + /* move to the source directory */ + + if (get_file_parts(fs, root, src_dir, &srcd, &src_dir, &src_name)) + { + ext2fs_close(fs); + return(-1); + } + + /* get the inode number for the source file */ + if ((retval = ext2fs_namei(fs, srcd, srcd, src_name, &source_file))) + { + fprintf(stderr, "%s: source file %s\n",error_message(retval), src_name); + ext2fs_close(fs); + return(retval); + } + + /* get the destination directory */ + destd = root; + if (argc == optind || strcmp(dest_dir = argv[optind], ".") == 0) + dest_name = src_name; + else + { + if (get_file_parts(fs, root, dest_dir, &destd, &dest_dir, + &dest_name)) + { + ext2fs_close(fs); + return(-1); + } + } + + /* now create the link */ + if ((retval = create_hard_link(fs, destd, source_file, dest_name, force))) + { + fprintf(stderr, "Error linking %s/%s as %s/%s\n", + ((src_dir == NULL) ? "." : src_dir), src_name, + ((dest_dir == NULL) ? "." : dest_dir), dest_name); + ext2fs_close(fs); + return(1); + } + + if (verbose) + fprintf(stderr, "linked %s/%s as %s/%s\n", + ((src_dir == NULL) ? "." : src_dir), src_name, + ((dest_dir == NULL) ? "." : dest_dir), dest_name); + + ext2fs_close(fs); + return(0); + +} /* end of do_ln */ + +/* Name: create_hard_link() + * + * Description: + * + * This function creates a hard link to an existing file + * + * Algorithm: + * + * Check input parameters + * Check to see if the new file name already exists + * Make sure the new file is not an existing directory + * If the file exists, remove it if the del_current flag is set + * Add the new file name and it's inode to the current directory. + * Get the inode structure for the current inode number + * update the number of links + * Write the inode structure back out to the file system. + * + * Global Variables: + * + * None. + * + * Arguments: + * + * ext2_filsys fs; The current file system + * ext2_ino_t cwd; The current working directory + * ext2_ino_t new_file_ino; The inode number of the new file + * char *newfile; The name of the new file + * int ln_flags; Flags affecting hard_link action + * + * Return Values: + * + * 0 - the new file link was created successfully + * any other value indicates an error + * + * Author: Keith W. Sheffield + * Date: 03/05/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 06/30/02 K.Sheffield Directory link flag is now based on the + * type of file being linked. This was + * causing problems if a directory was + * renamed. + */ +long +create_hard_link(ext2_filsys fs, ext2_ino_t cwd, ext2_ino_t new_file_ino, + char *newfile, int ln_flags) +{ + ext2_ino_t curr_ino; + struct ext2_inode inode; + long retval; + int dir_flag; + + if (fs == NULL || newfile == NULL) + { + fputs("Invalid input parameter. Exiting create_hard_link() with -1\n", + stderr); + return (-1); + } + + /* check to see if the file name already exists in the current directory */ + if ((retval = ext2fs_namei(fs, cwd, cwd, newfile, &curr_ino))) + { + if (retval != EXT2_ET_FILE_NOT_FOUND) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + + } + /* file name exists, let's see if is a directory */ + else if ((retval = ext2fs_check_directory(fs, curr_ino))) + { + if (retval != EXT2_ET_NO_DIRECTORY) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + + /* delete the existing file if needed */ + if ((ln_flags & E2T_FORCE) && + (curr_ino != new_file_ino)) + { + if ((retval = rm_file(fs, cwd, newfile, curr_ino))) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + } + else + { + fprintf(stderr, "ln: %s: File exists\n", newfile); + return(1); + } + } + else + { + /* if we get here, then it's an existing directory */ + fprintf(stderr, "%s is a directory!\n", newfile); + return(1); + } + + /* read the inode associated with the file */ + if ((retval = read_inode(fs, new_file_ino, &inode))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return (retval); + } + + /* determine how to link into the directory based on the type of file */ + switch(inode.i_mode & LINUX_S_IFMT) + { + case LINUX_S_IFREG: + dir_flag = EXT2_FT_REG_FILE; + break; + case LINUX_S_IFLNK: + dir_flag = EXT2_FT_SYMLINK; + break; + case LINUX_S_IFDIR: + dir_flag = EXT2_FT_DIR; + break; + case LINUX_S_IFSOCK: + dir_flag = EXT2_FT_SOCK; + break; + case LINUX_S_IFBLK: + dir_flag = EXT2_FT_BLKDEV; + break; + case LINUX_S_IFCHR: + dir_flag = EXT2_FT_CHRDEV; + break; + case LINUX_S_IFIFO: + dir_flag = EXT2_FT_FIFO; + break; + default: + dir_flag = EXT2_FT_UNKNOWN; + break; + } + + + if ((retval = ext2fs_link(fs, cwd, newfile, new_file_ino, dir_flag))) + { + /* check to see if we ran out of space in the directory */ + if (retval == EXT2_ET_DIR_NO_SPACE) + { + /* try resizing the directory and try again */ + if (0 == (retval = ext2fs_expand_dir(fs, cwd))) + retval = ext2fs_link(fs, cwd, newfile, new_file_ino, dir_flag); + } + if (retval) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + } + + + /* update the inode stat information */ + if ((ln_flags & E2T_DO_MV) == 0) + { + inode.i_links_count++; + if ((retval = write_inode(fs, new_file_ino, &inode))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return (retval); + } + } + + return(0); + +} /* end of create_hard_link */ + @@ -0,0 +1,1055 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/ls.c,v 0.8 2004/04/07 03:30:49 ksheff Exp $ */ +/* + * ls.c --- list directories + * + * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed + * under the terms of the GNU Public License. + * + * Modified by Keith W. Sheffield <shefff@pobox.com> for inclusion with e2tools + */ +/* + * $Log: ls.c,v $ + * Revision 0.8 2004/04/07 03:30:49 ksheff + * Updated usage string. + * + * Revision 0.7 2004/04/07 02:41:50 ksheff + * Modified to bracket files with an inode number of 0 with >< characters. + * + * Revision 0.6 2004/04/06 20:27:26 ksheff + * Modified to print "No files found!" for empty directories, corrected the + * directory name display, and fixed REGEX_OPT masking. + * + * Revision 0.5 2002/06/05 23:14:11 ksheff + * Fixed short display with respect to displaying the contents of multiple + * directories. + * + * Revision 0.4 2002/06/05 23:07:34 ksheff + * Allowed for multiple directory and file specifications. Added the -f + * option for no sorting. + * + * Revision 0.3 2002/06/03 23:00:51 ksheff + * Removed display code from directory iterator. A list of displayable files + * is now generated. This list can be sorted and displayed in a variety of + * ways. The -a, -c, -i, -r, and -t options are now accepted. + * + * Revision 0.2 2002/03/05 12:12:52 ksheff + * Removed setting optind for SCO. + * + * Revision 0.1 2002/02/27 04:46:21 ksheff + * initial revision + * + */ + + +#include "e2tools.h" +#include "elist.h" +#include <regex.h> + +/* + * list directory + */ + +#define LONG_OPT 0x0001 +#define DELETED_OPT 0x0002 +#define REGEX_OPT 0x0004 +#define REVERSE_OPT 0x0008 +#define HIDDEN_OPT 0x0010 +#define CREATE_OPT 0x0020 +#define INODE_OPT 0x0040 + +#define DIRECTORY_TYPE -1 +#define NORMAL_TYPE 0 + +struct list_dir_struct +{ + int options; + regex_t *reg; + elist_t *files; +}; + +typedef struct list_file_struct +{ + + char *name; + struct ext2_inode inode; + ext2_ino_t dir; + ext2_ino_t inode_num; + int entry; + long type; +} ls_file_t; + +static const char *monstr[] = +{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static ext2_filsys fs; +static int max_name_len = 0; + +static int +list_dir_proc(ext2_ino_t dir, int entry, struct ext2_dir_entry *dirent, + int offset, int blocksize, char *buf, void *private); +void +free_ls_file_t(void *f); +long +do_list_dir(int argc, char *argv[]); +void +long_disp(ls_file_t *info, int *col, int options); +void +short_disp(ls_file_t *info, int *col, int options); +int +no_sort(void *n1, void *n2); +int +name_sort(void *n1, void *n2); +int +inode_sort(void *n1, void *n2); +int +mod_time_sort(void *n1, void *n2); +int +creat_time_sort(void *n1, void *n2); +long +add_ls_file(char *name, int namelen, ext2_ino_t dir, ext2_ino_t ino, + int entry, int type, struct list_dir_struct *ls); +elist_t * +remove_ls_dups(elist_t *list); + +/* Name: list_dir_proc() + * + * Description: + * + * + * Algorithm: + * + * + * Global Variables: + * + * None + * + * Arguments: + * + * + * Return Values: + * + * + * Author: Theodore Ts'o + * Date: 1997 + * + * Modification History: + * + * MM/DD/YY Name Description + * 02/27/02 K.Sheffield Modified for use with e2tools + */ +static int +list_dir_proc(ext2_ino_t dir, int entry, struct ext2_dir_entry *dirent, + int offset, int blocksize, char *buf, void *private) +{ + struct ext2_inode inode; + char name[EXT2_NAME_LEN]; + struct list_dir_struct *ls = (struct list_dir_struct *) private; + int thislen; + + thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ? + (dirent->name_len & 0xFF) : EXT2_NAME_LEN; + strncpy(name, dirent->name, thislen); + name[thislen] = '\0'; + + /* skip hidden files unless we ask for them */ + if (0 == (ls->options & HIDDEN_OPT) && + name[0] == '.') + return(0); + + if ((ls->options & REGEX_OPT) && + regexec(ls->reg, name, 0, NULL, 0)) + return(0); + + return(add_ls_file(name, thislen, dir, dirent->inode, entry, NORMAL_TYPE, + ls)); + +} + +/* Name: add_ls_file() + * + * Description: + * + * + * Algorithm: + * + * + * Global Variables: + * + * None + * + * Arguments: + * + * + * Return Values: + * + * + * Author: K.Sheffield + * Date: 02/27/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + */ +long +add_ls_file(char *name, int namelen, ext2_ino_t dir, ext2_ino_t ino, + int entry, int type, struct list_dir_struct *ls) +{ + ls_file_t *file_info; + elist_t *flist; + + if (NULL == (file_info = calloc(sizeof(ls_file_t),1))) + { + perror("list_dir"); + return(0); + } + + file_info->dir = dir; + + if (entry == DIRENT_DELETED_FILE) + file_info->inode_num = 0; + else + file_info->inode_num = ino; + + file_info->entry = entry; + file_info->type = type; + + if (file_info->inode_num) + { + if (read_inode(fs, file_info->inode_num, &file_info->inode)) + { + free(file_info); + return 0; + } + } + + if (name) + file_info->name = strdup(name); + + if (NULL == (flist = elist_insert(ls->files, file_info))) + { + perror("list_dir"); + free_ls_file_t(file_info); + return 0; + } + ls->files = flist; + + if (max_name_len < namelen) + max_name_len = namelen; + + return 0; +} + +/* Name: free_ls_file_t() + * + * Description: + * + * This function is used to free an ls_file_t structure. + * + * Algorithm: + * + * Free the file's name if it is not NULL + * Free the ls_file_t structure + * Check to make sure the ls_file_t structure is not NULL + * + * Global Variables: + * + * None. + * + * Arguments: + * + * void *f; The structure to free + * + * Return Values: + * + * none + * + * Author: Keith W. Sheffield + * Date: 06/03/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +void free_ls_file_t(void *f) +{ + ls_file_t *n = (ls_file_t *) f; + + if (n != NULL) + { + if (n->name != NULL) + free(n->name); + free(n); + } +} /* end of free_ls_file_t */ + +/* Name: do_list_dir() + * + * Description: + * + * + * Algorithm: + * + * + * Global Variables: + * + * None + * + * Arguments: + * + * + * Return Values: + * + * + * Author: Theodore Ts'o + * Date: 1997 + * + * Modification History: + * + * MM/DD/YY Name Description + * 02/27/02 K.Sheffield Modified for use with e2tools + * 04/06/04 K.Sheffield Modified to print "No Files Found!" for + * each empty directory. Corrected masking + * out REGEX_OPT. + */ + +long +do_list_dir(int argc, char *argv[]) +{ + ext2_ino_t root; + ext2_ino_t cwd; + ext2_ino_t inode=0; + int retval; + int c; + int flags; + struct list_dir_struct ls; + char *fs_name; + char *last_fs_name; + char *path = NULL; + char *dup_path = NULL; + char *dir_name; + char *base_name; + int (*file_sort)(void *n1, void *n2) = name_sort; + void (*file_disp)(ls_file_t *n, int *col, int options) = short_disp; + elist_t *files=NULL; + int col=0; + ls_file_t *cur_file; + long last_type = 1; + + memset(&ls, 0, sizeof(ls)); + + last_fs_name = NULL; +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif + while ((c = getopt (argc, argv, "acDd:filrt")) != EOF) + { + switch (c) + { + case 'a': + ls.options |= HIDDEN_OPT; + break; + case 'c': + ls.options |= CREATE_OPT; + break; + case 'l': + file_disp = long_disp; + break; + case 'D': + ls.options |= DELETED_OPT; + break; + case 'd': + fs_name = optarg; + if (NULL != (path = strchr(fs_name, ':'))) + *path++ = '\0'; + if ((retval = open_filesystem(fs_name, &fs, &root, 0))) + { + fputs(error_message(retval), stderr); + return(1); + } + last_fs_name = fs_name; + break; + case 'f': + file_sort = no_sort; + break; + case 't': + file_sort = mod_time_sort; + break; + case 'r': + ls.options |= REVERSE_OPT; + break; + case 'i': + file_sort = inode_sort; + ls.options |= INODE_OPT; + break; + } + } + + if (argc <= optind) + { + fputs("Usage: e2ls [-acDfilrt][-d dir] file\n", stderr); + return(1); + } + + if (ls.options & CREATE_OPT && + (file_sort == mod_time_sort || file_disp != long_disp)) + file_sort = creat_time_sort; + + /* sort the remaining command line arguments */ + qsort(argv+optind, argc-optind, sizeof(char *), my_strcmp); + + for(c=optind;c<argc;c++) + { + fs_name = argv[c]; + + if (NULL != (path = strchr(fs_name, ':'))) + *path++ = '\0'; + else if (last_fs_name != NULL) + { + path = fs_name; + fs_name = last_fs_name; + } + + /* keep a copy of the file path for later because get_file_parts() is + * destructive. + */ + + if (dup_path) + { + free(dup_path); + dup_path = NULL; + } + + if (path) + dup_path = strdup(path); + + if (last_fs_name == NULL || strcmp(last_fs_name, fs_name)) + { + if (last_fs_name != NULL) + ext2fs_close(fs); + + if ((retval = open_filesystem(fs_name, &fs, &root, 0))) + { + fputs(error_message(retval), stderr); + return(1); + } + last_fs_name = fs_name; + } + + dir_name = NULL; + cwd = root; + ls.options &= (~REGEX_OPT); + + if (path != NULL && *path != '\0') + { + if (get_file_parts(fs, root, path, &cwd, &dir_name, &base_name)) + { + ext2fs_close(fs); + return(-1); + } + + if (is_file_regexp(base_name)) + { + if (NULL == (ls.reg = (regex_t *) make_regexp(base_name))) + { + fprintf(stderr, + "Error creating regular expression for %s\n", + base_name); + return(1); + } + ls.options |= REGEX_OPT; + inode = cwd; + + } + /* check to see if the file name exists in the current directory + */ + else if ((retval = ext2fs_namei(fs, cwd, cwd, base_name, &inode))) + { + fputs(error_message(retval), stderr); + ext2fs_close(fs); + return(1); + } + } + else + inode = root; + + if(!dir_name) + dir_name = "."; + + if (!inode) + continue; + + flags = DIRENT_FLAG_INCLUDE_EMPTY; + if (ls.options & DELETED_OPT) + flags |= DIRENT_FLAG_INCLUDE_REMOVED; + + if (retval = ext2fs_check_directory(fs, inode)) + { + if (retval != EXT2_ET_NO_DIRECTORY) + { + fputs(error_message(retval), stderr); + ext2fs_close(fs); + return(1); + } + + if(add_ls_file(dir_name, 0, cwd, 0, 0, DIRECTORY_TYPE, &ls)) + { + fputs(error_message(retval), stderr); + ext2fs_close(fs); + return(1); + } + + if(add_ls_file(base_name, strlen(base_name), cwd, inode, 0, + NORMAL_TYPE, &ls)) + { + fputs(error_message(retval), stderr); + ext2fs_close(fs); + return(1); + } + } + else + { + if (ls.options & REGEX_OPT || path == NULL || *path == '\0') + path = dir_name; + else if (dup_path) + path = dup_path; + + + // if(add_ls_file((ls.options & REGEX_OPT) ? dir_name : path, 0, inode, 0, + if(add_ls_file(path, 0, inode, 0, 0, DIRECTORY_TYPE, &ls)) + { + fputs(error_message(retval), stderr); + ext2fs_close(fs); + return(1); + } + + retval = ext2fs_dir_iterate2(fs, inode, flags, 0, list_dir_proc, + &ls); + if (retval) + { + fputs(error_message(retval), stderr); + ext2fs_close(fs); + return(1); + } + } + } + + + elist_sort(ls.files, file_sort, ls.options & REVERSE_OPT); + + ls.files = files = remove_ls_dups(ls.files); + + if (files == NULL) + printf("No files found!"); + else + { + while(files != NULL) + { + cur_file = (ls_file_t *)files->data; + if (cur_file->type == DIRECTORY_TYPE) + { + if (col > 0) + { + putchar('\n'); + col = 0; + } + if (last_type == DIRECTORY_TYPE) + printf("No files found!\n"); + + printf("%s:", cur_file->name); + } + else + { + if (last_type == DIRECTORY_TYPE) + putchar('\n'); + (file_disp)(cur_file, &col, ls.options); + } + + last_type = cur_file->type; + + files = files->next; + } + if (last_type == DIRECTORY_TYPE) + printf("No files found!"); + } + + putchar('\n'); + + elist_free(ls.files, free_ls_file_t); + + ext2fs_close(fs); + return(0); +} + +/* Name: long_disp() + * + * Description: + * + * This function displays a file's information for a long listing + * + * Algorithm: + * + * Generate the time string for the modification time + * Display the file's permission bits, owner, group, mod time, and name + * + * Global Variables: + * + * none + * + * Arguments: + * + * ls_file_t *info; The structure containing the file information + * int *col; The current column - unused + * int options; Options to ls + * + * Return Values: + * + * None + * + * Author: Keith W. Sheffield + * Date: 06/03/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 06/06/02 K.Sheffield Increased file size width + * 04/06/04 K.Sheffield Modified to show entries with an inode of 0 + * as deleted. + */ +void long_disp(ls_file_t *info, int *col, int options) +{ + char lbr, rbr; + char datestr[80]; + time_t modtime; + struct tm *tm_p; + + + if (info->entry == DIRENT_DELETED_FILE || + info->inode_num == 0) + { + lbr = '>'; + rbr = '<'; + } + else + { + lbr = rbr = ' '; + } + + + if (info->inode_num) + { + if (options & CREATE_OPT) + modtime = info->inode.i_ctime; + else + modtime = info->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, " "); + + printf("%c%6u%c %6o %5d %5d ", lbr, info->inode_num, rbr, + info->inode.i_mode, info->inode.i_uid, info->inode.i_gid); + if (LINUX_S_ISDIR(info->inode.i_mode)) + printf("%7d", info->inode.i_size); + else + printf("%7lld", info->inode.i_size | + ((__u64)info->inode.i_size_high << 32)); + printf(" %s %s\n", datestr, info->name); + +} /* end of long_disp */ + + +/* Name: short_disp() + * + * Description: + * + * This function displays a file's information for a long listing + * + * Algorithm: + * + * Display the file's name at the appropriate column. + * + * Global Variables: + * + * none + * + * Arguments: + * + * ls_file_t *info; The structure containing the file information + * int *col; The current column + * int options; Options to ls + * + * Return Values: + * + * None + * + * Author: Keith W. Sheffield + * Date: 06/03/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 04/06/04 K.Sheffield Modified to show entries with an inode of 0 + * as deleted. + */ +void short_disp(ls_file_t *info, int *col, int options) +{ + char lbr, rbr; + char tmp[300]; + int thislen; + static max_col_size = 0; + + if (max_col_size == 0) + { + max_col_size = 80/(max_name_len + 2 + ((options & INODE_OPT) ? 8 : 0)); + if (max_col_size == 0) + max_col_size = -1; + else + max_col_size = 80/max_col_size; + } + + + if (info->entry == DIRENT_DELETED_FILE || + info->inode_num == 0) + { + lbr = '>'; + rbr = '<'; + } + else + { + lbr = 0; + rbr = ' '; + } + + if (lbr == 0) + { + if (options & INODE_OPT) + sprintf(tmp, "%7d %s%c", info->inode_num, info->name, rbr); + else + sprintf(tmp, "%s%c", info->name, rbr); + } + else + { + if (options & INODE_OPT) + sprintf(tmp, "%7d %c%s%c", info->inode_num, lbr, info->name, rbr); + else + sprintf(tmp, "%c%s%c", lbr, info->name, rbr); + } + + thislen = strlen(tmp); + + if (*col + thislen > 80) + { + putchar('\n'); + *col = 0; + } + thislen = max_col_size - thislen; + if (thislen < 0) + thislen = 0; + + printf("%s%*.*s", tmp, thislen, thislen, ""); + *col += max_col_size; +} + +/* Name: no_sort() + * + * Description: + * + * This function sorts two ls_file_t structures by the file name + * + * Algorithm: + * + * Assign two ls_file_t pointers from the input void pointers + * Return the result of the comparison of the directories & type + * + * Global Variables: + * + * None + * + * Arguments: + * + * void *n1; The first node being compared + * void *n2; The second node being compared + * + * Return Values: + * + * >0 - n1 > n2 + * =0 - n1 == n2 + * <0 - n1 < n2 + * + * Author: Keith W. Sheffield + * Date: 06/03/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +int no_sort(void *n1, void *n2) +{ + ls_file_t *f1 = *((ls_file_t **) n1); + ls_file_t *f2 = *((ls_file_t **) n2); + int retval; + + return((retval = (f1->dir - f2->dir)) ? retval : (f1->type - f2->type)); + +} /* end of name_sort */ + +/* Name: name_sort() + * + * Description: + * + * This function sorts two ls_file_t structures by the file name + * + * Algorithm: + * + * Assign two ls_file_t pointers from the input void pointers + * Return the result of the comparison of the names + * + * Global Variables: + * + * None + * + * Arguments: + * + * void *n1; The first node being compared + * void *n2; The second node being compared + * + * Return Values: + * + * >0 - n1 > n2 + * =0 - n1 == n2 + * <0 - n1 < n2 + * + * Author: Keith W. Sheffield + * Date: 06/03/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +int name_sort(void *n1, void *n2) +{ + ls_file_t *f1 = *((ls_file_t **) n1); + ls_file_t *f2 = *((ls_file_t **) n2); + int retval; + + return((retval = (f1->dir - f2->dir)) ? retval : + ((retval = (f1->type - f2->type)) ? retval : + strcmp(f1->name, f2->name))); +} /* end of name_sort */ + +/* Name: inode_sort() + * + * Description: + * + * This function sorts two ls_file_t structures by the file inode number + * + * Algorithm: + * + * Assign two ls_file_t pointers from the input void pointers + * Return the result of the comparison of the inode numbers + * + * Global Variables: + * + * None + * + * Arguments: + * + * void *n1; The first node being compared + * void *n2; The second node being compared + * + * Return Values: + * + * >0 - n1 > n2 + * =0 - n1 == n2 + * <0 - n1 < n2 + * + * Author: Keith W. Sheffield + * Date: 06/03/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +int inode_sort(void *n1, void *n2) +{ + ls_file_t *f1 = *((ls_file_t **) n1); + ls_file_t *f2 = *((ls_file_t **) n2); + int retval; + + return((retval = (f1->dir - f2->dir)) ? retval : + ((retval = (f1->type - f2->type)) ? retval : + (f1->inode_num - f2->inode_num))); +} /* end of inode_sort */ + +/* Name: mod_time_sort() + * + * Description: + * + * This function sorts two ls_file_t structures by the file modification time + * + * Algorithm: + * + * Assign two ls_file_t pointers from the input void pointers + * Return the result of the comparison of the modification time + * + * Global Variables: + * + * None + * + * Arguments: + * + * void *n1; The first node being compared + * void *n2; The second node being compared + * + * Return Values: + * + * >0 - n1 > n2 + * =0 - n1 == n2 + * <0 - n1 < n2 + * + * Author: Keith W. Sheffield + * Date: 06/03/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +int mod_time_sort(void *n1, void *n2) +{ + ls_file_t *f1 = *((ls_file_t **) n1); + ls_file_t *f2 = *((ls_file_t **) n2); + int retval; + + return((retval = (f1->dir - f2->dir)) ? retval : + ((retval = (f1->type - f2->type)) ? retval : + (f2->inode.i_mtime - f1->inode.i_mtime))); + +} /* end of mod_time_sort */ + +/* Name: creat_time_sort() + * + * Description: + * + * This function sorts two ls_file_t structures by the file creation time + * + * Algorithm: + * + * Assign two ls_file_t pointers from the input void pointers + * Return the result of the comparison of the creation time + * + * Global Variables: + * + * None + * + * Arguments: + * + * void *n1; The first node being compared + * void *n2; The second node being compared + * + * Return Values: + * + * >0 - n1 > n2 + * =0 - n1 == n2 + * <0 - n1 < n2 + * + * Author: Keith W. Sheffield + * Date: 06/03/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +int creat_time_sort(void *n1, void *n2) +{ + ls_file_t *f1 = *((ls_file_t **) n1); + ls_file_t *f2 = *((ls_file_t **) n2); + int retval; + + return((retval = (f1->dir - f2->dir)) ? retval : + ((retval = (f1->type - f2->type)) ? retval : + (f2->inode.i_ctime - f1->inode.i_ctime))); +} /* end of creat_time_sort */ + +/* Name: remove_ls_dups() + * + * Description: + * + * This function will remove the first directory node if it is the only one + * found. It will also remove bogus entries. + * + * Algorithm: + * + * For each node in the linked list + * If the current node has no data + * Remove it from the linked list + * If the current entry is a DIRECTORY_TYPE + * Increment the number of directories. + * Return the starting node in the linked list + * + * Global Variables: + * + * None. + * + * Arguments: + * + * elist *list; The linked list to process + * + * Return Values: + * + * The starting node in the linked list. + * + * Author: Keith W. Sheffield + * Date: 06/05/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 04/06/04 K.Sheffield Modified to just remove the first directory + * node if it is the only one found. + * + */ +elist_t * remove_ls_dups(elist_t *list) +{ + elist_t *start = list; + elist_t *next; + ls_file_t *cd; + ls_file_t *nd; + int cnt=0; + + while(list != NULL) + { + cd = (ls_file_t *) list->data; + if (cd == NULL) + { + /* remove any empty nodes */ + if (list == start) + start = list->next; + list = elist_delete(list, free_ls_file_t); + continue; + } + else if (cd->type == DIRECTORY_TYPE) + { + cnt++; + } + list = list->next; + } + + /* if there is only one directory entry, delete it */ + if (cnt == 1) + start = elist_delete(start, free_ls_file_t); + + return(start); + +} /* end of remove_ls_dups */ @@ -0,0 +1,190 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing - GNU libit 0.0" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`configure.in'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`configure.in'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`configure.in'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 @@ -0,0 +1,587 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/mkdir.c,v 0.8 2004/04/07 03:19:32 ksheff Exp $ */ +/* + * mkdir.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + * Derived from debugfs.c Copyright (C) 1993 Theodore Ts'o <tytso@mit.edu> + * and modified by Robert Sanders <gt8134b@prism.gatech.edu> + * as well as portions of the ext2fs library (C) 1993-1995 Theodore Ts'o + */ + +#ifndef MKDIR_C +#define MKDIR_C +#endif + +/* Description */ +/* + * This file contains the functions used to create a directory in an ext2fs + * filesystem. + * + */ +/* + * $Log: mkdir.c,v $ + * Revision 0.8 2004/04/07 03:19:32 ksheff + * Modified to always apply the default user and group information. + * + * Revision 0.7 2004/04/07 02:55:44 ksheff + * Updated usage string. + * + * Revision 0.6 2002/07/09 02:15:23 ksheff + * Fixed a error reporting bug that was not displaying the full file name. + * + * Revision 0.5 2002/04/10 09:30:28 ksheff + * Added the ability to set the mode, owner, group, etc. for a directory. + * + * Revision 0.4 2002/03/05 13:42:12 ksheff + * Fixed minor indentation. + * + * Revision 0.3 2002/03/05 12:14:10 ksheff + * Removed setting optind for SCO. + * + * Revision 0.2 2002/02/27 05:34:43 ksheff + * Added the function e2mkdir which is run by a user to create directories in + * an ext2fs filesystem. + * + * Revision 0.1 2002/02/27 04:48:30 ksheff + * initial revision + * + */ + +/* Headers */ +#include "e2tools.h" + +/* Local Prototypes */ +long +e2mkdir(int argc, char *argv[]); + +long +create_dir(ext2_filsys fs, ext2_ino_t root, ext2_ino_t *cwd, + char *dirname, struct stat *def_stat); +long +create_subdir(ext2_filsys fs, ext2_ino_t root, ext2_ino_t *cwd, + char *dirname, struct stat *def_stat); +/* Name: e2mkdir() + * + * Description: + * + * This function extracts the command line parameters and creates + * directories based on user input + * + * Algorithm: + * + * Extract any command line switches + * Sort the remaining arguments + * For each argument + * Open a new filesystem if needed + * Create the directory + * + * Global Variables: + * + * None + * + * Arguments: + * + * int argc; The number of arguments + * char *argv[]; the command line arguments + * + * Return Values: + * + * 0 - the directories were created successfully + * otherwise, an error code is returned + * + * Author: Keith W. Sheffield + * Date: 02/26/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 03/05/02 K. Sheffield Removed setting optind for SCO + * 04/10/02 K.Sheffield Added a default directory permission + * 04/06/04 K.Sheffield Modified to apply the default user and + * group. + */ +long +e2mkdir(int argc, char *argv[]) +{ + int verbose=0; + int num_files; + int errcnt=0; + char *last_filesys = NULL; + char *cur_filesys = NULL; + ext2_filsys fs = NULL; + ext2_ino_t root; + ext2_ino_t cwd; + char **cur_opt; + char *filespec; + int i; + char *ptr; + int c; + long retval; + struct stat def_stat; + + init_stat_buf(&def_stat); + def_stat.st_ino = 1; + +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif + while ((c = getopt(argc, argv, "G:O:P:v")) != EOF) + { + switch (c) + { + case 'v': + verbose = 1; + break; + case 'G': + def_stat.st_gid = atoi(optarg); + break; + case 'O': + def_stat.st_uid = atoi(optarg); + break; + case 'P': + def_stat.st_mode = strtol(optarg, NULL, 8); + break; + default: + errcnt++; + break; + } + } + + if (errcnt || argc == optind) + { + fputs("Usage: e2mkdir [-G gid][-O uid][-P mode][-v] filesystem:directory...\n", stderr); + return(1); + } + + num_files = argc - optind; + + cur_opt = argv + optind; + if (num_files > 1 ) + qsort(cur_opt, num_files, sizeof(char *), my_strcmp); + + for(i=0;i<num_files;i++) + { + filespec = *cur_opt++; + + /* dealing with a filesystem or a regular file */ + if (NULL != (ptr = strchr(filespec, ':'))) + { + /* separate the filesystem name from the file name */ + *ptr++ = '\0'; + cur_filesys = filespec; + filespec = ptr; + + /* check to see if the filesystem has changed */ + if (last_filesys == NULL || + strcmp(last_filesys, cur_filesys) != 0) + { + if (last_filesys != NULL && + (retval = ext2fs_close(fs))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + + if ((retval = open_filesystem(cur_filesys, &fs, &root, 1))) + { + fprintf(stderr, "%s\n", error_message(retval)); + fprintf(stderr, "Error opening fileystem %s\n", + cur_filesys); + return retval; + } + cwd = root; + last_filesys = cur_filesys; + } /* end of filesystem change? */ + if ((retval = create_dir(fs, root, &cwd, filespec, &def_stat))) + { + fprintf(stderr, "Error creating %s:%s\n", cur_filesys, filespec); + return(-1); + } + cwd = root; /* reset the current directory */ + if (verbose) + printf("Created directory %s:%s\n", cur_filesys, filespec); + } + else if (verbose) + { + printf("%s is not a valid e2fs filesystem specification. skipping\n", + filespec); + } + } + if (fs != NULL && + (retval = ext2fs_close(fs))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + return(0); + +} /* end of e2mkdir */ + +/* Name: create_dir() + * + * Description: + * + * This function will create a directory in the given ext2fs file system. + * It will re-create all the parent directories if necessary (similar + * to mkdir -p). The current working directory is then set to this new + * directory. + * + * Algorithm: + * + * Check the input parameters + * Check to see if the directory name contains a / + * If it exists + * Break the entire path into specific directory names + * For each section of the path + * Check to see if the name exists in the current directory + * If it doesn't + * Call create_subdir for that section of the path + * Otherwise + * If it is a symbolic link, follow it + * Read the inode structure for the current section of the path + * If it is not a directory + * Print an error message and return an error. + * Otherwise + * Call create_subdir for that section of the path + * + * Global Variables: + * + * None. + * + * Arguments: + * + * ext2_filsys fs; The current file system + * ext2_ino_t root; The inode number of the root directory + * ext2_ino_t *cwd; Pointer to the inode number of the current + * directory + * char *dirname; The directory to create + * struct stat *def_stat; Default directory status, owner, group, etc. + * + * Return Values: + * + * 0 - the directory was created successfully + * error code of what went wrong + * + * Author: Keith W. Sheffield + * Date: 02/18/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 04/10/02 K.Sheffield Added a default directory permission + * 07/08/02 K.Sheffield Fixed bugs in error reporting + */ +long +create_dir(ext2_filsys fs, ext2_ino_t root, ext2_ino_t *cwd, + char *dirname, struct stat *def_stat) +{ + char *ptr; /* working pointer to /'s */ + ext2_ino_t parent; /* the parent directory inode number*/ + ext2_ino_t child; /* the inode number of the new directory */ + struct ext2_inode inode; /* inode of file/directory dirname */ + char *name; /* basename of the new directory */ + long retval; /* function return value */ + char *buf; + int len; + char c; + char *dname; /* name of the sub directory */ + + /* make sure we have valid parameters */ + if (fs == NULL || cwd == NULL || dirname == NULL || *dirname == '\0') + { + fputs("create_dir: invalid parameter\n", stderr); + return(-1); + } + + EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + /* check to see if there are any sub directories or absolute paths given + */ + if (NULL != (ptr = strchr(dirname, '/'))) + { + + dname = dirname; + /* if the directory name starts with / the starting parent directory + * is the root directory. + */ + if (*dirname == '/') + { + parent = root; + dname++; + } + else + parent = *cwd; + + /* allocate memory for the lookups */ + if ((retval = ext2fs_get_mem(fs->blocksize, (void **) &buf))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + + c = *dname; + ptr = dname; + while (c != '\0') + { + len = 0; + /* skip ahead to the next / character */ + while ((c = *ptr) != '/' && c != '\0') + { + len++; + ptr++; + } + + if (c == '/') + *ptr++ = '\0'; + + /* multiple /'s in a row or trailing / */ + if (len == 0) + { + /* restore /'s */ + if (dname > dirname) + *--dname = '/'; + + dname = ptr; + continue; + } + + /* check to see if this file is in the parent directory */ + if ((retval = ext2fs_lookup(fs, parent, dname, len, buf, &child))) + { + if (retval == EXT2_ET_FILE_NOT_FOUND) + { + /* ok, it's not there, so just create it */ + if ((retval = create_subdir(fs, root, &parent, dname, + def_stat))) + { + fprintf(stderr, + "create_dir: error creating directory %s/%s:%d\n", + dirname, dname, retval); + ext2fs_free_mem((void **) &buf); + return(retval); + } + } + else + { + fprintf(stderr, "%s\n", error_message(retval)); + ext2fs_free_mem((void **) &buf); + return retval; + } + } + else + { + /* ok, so the name exists...follow it if it's a symlink + * otherwise, it's a directory so set the parent directory to + * the child inode number + */ + if ((retval = ext2fs_follow_link(fs, root, parent, child, + &parent))) + { + fprintf(stderr, "%s\n", error_message(retval)); + ext2fs_free_mem((void **) &buf); + return retval; + } + + /* now check to see if it's a directory */ + if ((retval = ext2fs_read_inode(fs, parent, &inode))) + { + fprintf(stderr, "%s\n", error_message(retval)); + ext2fs_free_mem((void **) &buf); + return retval; + } + + /* not a directory? something's wrong */ + if (!LINUX_S_ISDIR(inode.i_mode)) + { + fprintf(stderr, "create_dir: %s/%s is not a directory: %o\n", + dirname, dname, inode.i_mode); + ext2fs_free_mem((void **) &buf); + return(-1); + } + } + + /* restore /'s */ + if (dname > dirname) + *--dname = '/'; + dname = ptr; + } + ext2fs_free_mem((void **) &buf); + *cwd = parent; + } + else + { + if ((retval = create_subdir(fs, root, cwd, dirname, def_stat))) + { + fprintf(stderr, + "create_dir: error creating directory %s:%d\n", + dirname, retval); + return(retval); + } + } + return(0); +} /* end of create_dir */ + +/* Name: create_subdir() + * + * Description: + * + * This function will create a sub directory in the given ext2fs file system. + * The current working directory is then set to this new directory. + * + * Algorithm: + * + * Find a new inode number to use + * Create the directory + * + * Global Variables: + * + * None. + * + * Arguments: + * + * ext2_filsys fs; The current file system + * ext2_ino_t root; The inode number of the root directory + * ext2_ino_t *cwd; Pointer to the inode number of the current + * or parent directory + * char *dirname; The directory to create + * struct stat *def_stat; Default directory status, owner, group, etc. + * + * Return Values: + * + * 0 - the directory was created successfully + * error code of what went wrong + * + * Author: Keith W. Sheffield + * Date: 02/18/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 04/10/02 K.Sheffield Added a default directory permission + * + */ +long create_subdir(ext2_filsys fs, ext2_ino_t root, ext2_ino_t *cwd, + char *dirname, struct stat *def_stat) +{ + ext2_ino_t parent; /* the parent directory inode number*/ + ext2_ino_t child; /* the inode number of the new directory */ + long retval; /* function return value */ + struct ext2_inode inode; + + parent = *cwd; + + if ((retval = ext2fs_namei(fs, root, parent, dirname, &child))) + { + if (retval != EXT2_ET_FILE_NOT_FOUND) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + } + /* file name exists, let's see if is a directory */ + else if ((retval = ext2fs_check_directory(fs, child))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return(retval); + } + else + { + /* if we get here, then it's an existing directory */ + *cwd = child; + return(0); + } + + /* ok, the directory doesn't exist + /* get a new inode number */ + if ((retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, 0, &child))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + + /* now create the directory */ + if ((retval = ext2fs_mkdir(fs, parent, child, dirname))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + + *cwd = child; + if (def_stat != NULL && def_stat->st_ino != 0) + { + if ((retval = read_inode(fs, child, &inode))) + return(retval); + + if (def_stat->st_mode != 0) + inode.i_mode = LINUX_S_IFDIR | host_mode_xlate(def_stat->st_mode); + + inode.i_uid = def_stat->st_uid; + inode.i_gid = def_stat->st_gid; + inode.i_atime = def_stat->st_atime; + inode.i_ctime = def_stat->st_ctime; + inode.i_mtime = def_stat->st_mtime; + + if ((retval = write_inode(fs, child, &inode))) + return(retval); + } + + return(0); +} /* end of create_subdir */ + +/* Name: change_cwd() + * + * Description: + * + * This function changes the current working directory + * + * Algorithm: + * + * Look up the inode number for the input string + * check to see if it's a directory + * Assign it as the current working directory if it is. + * + * Global Variables: + * + * None + * + * Arguments: + * + * ext2_filsys fs; The current filesystem + * ext_ino_t root; The root directory + * ext_ino_t *cwd; The current working directory + * char *dirname; The name of the directory we want to change to + * + * Return Values: + * + * 0 - changed to the directory successfully + * the error code of what went wrong + * + * Author: Keith W Sheffield + * Date: 02/21/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +long +change_cwd(ext2_filsys fs, ext2_ino_t root, ext2_ino_t *cwd, char *dirname) +{ + ext2_ino_t inode; + long retval; + + if ((retval = ext2fs_namei(fs, root, *cwd, dirname, &inode))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + else if ((retval = ext2fs_check_directory(fs, inode))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + *cwd = inode; + return(0); +} /* end of change_cwd */ diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 0000000..4f58503 --- /dev/null +++ b/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 @@ -0,0 +1,554 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/mv.c,v 0.1 2002/03/21 09:03:25 ksheff Exp $ */ +/* + * mv.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + */ + + +#ifndef MV_C +#define MV_C +#endif + +/* Description */ +/* + * Module to move/rename files + * + */ +/* + * $Log: mv.c,v $ + * Revision 0.1 2002/03/21 09:03:25 ksheff + * initial revision. + * + */ + +/* Feature Test Switches */ +/* Headers */ +#include "e2tools.h" + +/* Macros */ +#define USAGE "Usage: e2mv [-vfs] source1 [... sourceN] destination\n" + +/* Local Prototypes */ +static long +do_swap(int force, int verbose, int curidx, int argc, char **argv); + +/* Name: do_mv() + * + * Description: + * + * This function reads the command line arguments and moves or renames files + * in an ext2fs file system + * + * Algorithm: + * + * Read any command line switches + * Get the first source file specification + * If we are performing a file swap, call do_swap() + * Open the file system + * Get the destination and determine if it is a directory + * If not, then get the destination's directory and basename + * Also check that the number of source files are no more than one + * For each source file + * Get the directory and basename of the source file + * Determine the inode number for the source file + * Create the link + * Unlink the original source file. + * + * Global Variables: + * + * None + * + * Arguments: + * + * int argc; The number of arguments + * char *argv[]; The command line arguments + * + * Return Values: + * + * 0 - the file was move successfully + * an error occurred. + * + * Author: Keith W. Sheffield + * Date: 03/20/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + */ +long +do_mv(int argc, char *argv[]) +{ + int verbose=0; + int force=0; + int swap_files=0; + int num_files; + int errcnt=0; + char *cur_filesys = NULL; + ext2_filsys fs = NULL; + ext2_ino_t root; + ext2_ino_t srcd; + ext2_ino_t destd; + ext2_ino_t source_file; + char *src_dir; + char *dest_dir; + char *src_name; + char *dest_name; + char *result_name; + long retval; + int c; + int curidx; + +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif + while ((c = getopt(argc, argv, "vfs")) != EOF) + { + switch (c) + { + case 'v': + verbose = 1; + break; + case 'f': + force = E2T_FORCE; + break; + case 's': + swap_files = 1; + break; + default: + errcnt++; + break; + } + } + + curidx = optind; + + force |= E2T_DO_MV; + + if (errcnt || argc < curidx+2) + { + fputs(USAGE, stderr); + return(1); + } + + if (swap_files) + return(do_swap(force, verbose, curidx, argc, argv)); + + cur_filesys = argv[curidx++]; + if (NULL == (src_dir = strchr(cur_filesys, ':'))) + { + fprintf(stderr, "Invalid file specification: %s\n", cur_filesys); + return(1); + } + *src_dir++ = '\0'; + + if ((retval = open_filesystem(cur_filesys, &fs, &root, 1))) + { + fprintf(stderr, "%s: %s\n", error_message(retval), cur_filesys); + return retval; + } + + + /* get the destination directory */ + dest_name = NULL; + if (strcmp(dest_dir = argv[argc-1], ".") != 0) + { + /* check to see if the file name already exists in the current + * directory and also see if it is a directory. + */ + if ((retval = ext2fs_namei(fs, root, root, dest_dir, &destd)) || + (retval = ext2fs_check_directory(fs, destd))) + { + if (retval != EXT2_ET_FILE_NOT_FOUND && + retval != EXT2_ET_NO_DIRECTORY) + { + fprintf(stderr, "%s\n",error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + /* ok, so it's either not there or it's not a directory, so + * get the real destination directory and file name. + */ + if (curidx+1 < argc) + { + fprintf(stderr, "%s must be a directory!\n", dest_dir); + ext2fs_close(fs); + return(1); + } + + if (get_file_parts(fs, root, dest_dir, &destd, &dest_dir, + &dest_name)) + { + ext2fs_close(fs); + return(-1); + } + } + else /* we have a directory!!! */ + dest_name = NULL; + } + else + { + destd = root; + dest_name = NULL; + } + + do + { + /* move to the source directory */ + if (get_file_parts(fs, root, src_dir, &srcd, &src_dir, &src_name)) + { + ext2fs_close(fs); + return(-1); + } + + /* get the inode number for the source file */ + if ((retval = ext2fs_namei(fs, srcd, srcd, src_name, &source_file))) + { + fprintf(stderr, "%s: source file %s\n",error_message(retval), + src_name); + ext2fs_close(fs); + return(retval); + } + + result_name = (dest_name) ? dest_name : src_name; + + /* now create the link */ + if ((retval = create_hard_link(fs, destd, source_file, result_name, + force))) + { + fprintf(stderr, "Error renaming %s/%s as %s/%s\n", + ((src_dir == NULL) ? "." : src_dir), src_name, + ((dest_dir == NULL) ? "." : dest_dir), result_name); + ext2fs_close(fs); + return(1); + } + + if ((retval = ext2fs_unlink(fs, srcd, src_name, 0, 0))) + { + fprintf(stderr, "%s - %s\n", src_name, error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + if (verbose) + fprintf(stderr, "moved %s/%s as %s/%s\n", + ((src_dir == NULL) ? "." : src_dir), src_name, + ((dest_dir == NULL) ? "." : dest_dir), result_name); + src_dir = argv[curidx++]; + } + while (curidx < argc); + + ext2fs_close(fs); + return(0); + +} /* end of do_mv */ + +/* Name: get_file_parts() + * + * Description: + * + * This function returns each of the following file 'parts': directory name, + * base name, inode number of the directory + * + * Algorithm: + * + * Use the root directory as the current working directory + * Find the last / in the full pathname + * If none are found, set the basename to the full pathname, + * and the directory to NULL + * Otherwise, + * Separate the basename from the directory + * Change the working directory + * Set the return pointers. + * + * Global Variables: + * + * None. + * + * Arguments: + * + * ext2_filsys fs; the filesystem being used + * ext2_ino_t root; the root directory of the filesystem + * char *pathname; the full pathname of the file + * ext2_ino_t *dir_ino; The inode number of the directory + * char **dir_name; the directory the file is in + * char **base_name; The basename of the file + * + * Return Values: + * + * 0 - retrieved the information ok + * otherwise the error code of what went wrong + * + * Author: Keith W. Sheffield + * Date: 03/21/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +long +get_file_parts(ext2_filsys fs, ext2_ino_t root, char *pathname, + ext2_ino_t *dir_ino, char **dir_name, char **base_name) +{ + char *fname; + long retval; + + /* move to the source directory */ + *dir_name = pathname; + *dir_ino = root; + if (NULL == (fname = strrchr(pathname, '/'))) + { + fname = pathname; + *dir_name = NULL; + } + else + { + *fname++ = '\0'; + if ((*pathname != '\0' && strcmp(pathname, ".") != 0) && + (retval = change_cwd(fs, root, dir_ino, pathname))) + { + fprintf(stderr, "Error changing to directory %s\n", + pathname); + return(retval); + } + } + + *base_name = fname; + return(0); +} /* end of get_file_parts */ + + +/* Name: do_swap() + * + * Description: + * + * This function swaps the names of two files and optionally assigns the + * first file a new name: + * + * file1 file2 file3 + * + * After the operation, file1 will reference the file that was originally file2, and file3 will reference the what used to be file1. + * + * Algorithm: + * + * check input parameters + * Get the directory and inode numbers for the first two files + * If a third file exists + * Get the directory info for the file + * Rename the first file to the third + * Rename the 2nd file to the first + * Otherwise + * Remove the first file from its directory + * Rename the 2nd file to the first + * Add the first file back as the 2nd file. + * + * Global Variables: + * + * None. + * + * Arguments: + * + * int force; Flag indicating if existing files are to be removed + * int verbose; Flag to print lots of output + * int curidx; The current index in the command line args + * int argc; The total number of arguments + * char **argv; Pointer to an array of argument strings. + * + * Return Values: + * + * 0 - the operation was successful + * otherwise the error code of what went wrong. + * + * Author: Keith W. Sheffield + * Date: 03/21/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ + +static long +do_swap(int force, int verbose, int curidx, int argc, char **argv) +{ + char *cur_filesys = NULL; + ext2_filsys fs = NULL; + ext2_ino_t root; + ext2_ino_t file1_dirno; + ext2_ino_t file2_dirno; + ext2_ino_t file3_dirno; + ext2_ino_t file1_no; + ext2_ino_t file2_no; + char *file1_dir; + char *file2_dir; + char *file3_dir; + char *file1_name; + char *file2_name; + char *file3_name; + long retval; + + if (curidx + 2 > argc) + { + fputs(USAGE, stderr); + return(1); + } + + cur_filesys = argv[curidx++]; + if (NULL == (file1_dir = strchr(cur_filesys, ':'))) + { + fprintf(stderr, "Invalid file specification: %s\n", cur_filesys); + return(1); + } + *file1_dir++ = '\0'; + + if ((retval = open_filesystem(cur_filesys, &fs, &root, 1))) + { + fprintf(stderr, "%s: %s\n", error_message(retval), cur_filesys); + return retval; + } + + /* move to the file 1 directory */ + if (get_file_parts(fs, root, file1_dir, &file1_dirno, &file1_dir, + &file1_name)) + { + ext2fs_close(fs); + return(-1); + } + + /* get the inode number for the file 1 file */ + if ((retval = ext2fs_namei(fs, file1_dirno, file1_dirno, file1_name, + &file1_no))) + { + fprintf(stderr, "%s: file 1 file %s\n",error_message(retval), + file1_name); + ext2fs_close(fs); + return(retval); + } + + + /* move to the file 2 directory */ + if (get_file_parts(fs, root, argv[curidx++], &file2_dirno, &file2_dir, + &file2_name)) + { + ext2fs_close(fs); + return(-1); + } + + /* get the inode number for the file 2 file */ + if ((retval = ext2fs_namei(fs, file2_dirno, file2_dirno, file2_name, + &file2_no))) + { + fprintf(stderr, "%s: file 2 file %s\n",error_message(retval), + file2_name); + ext2fs_close(fs); + return(retval); + } + + if (curidx < argc) + { + /* move to the file 3 directory */ + if (get_file_parts(fs, root, argv[curidx++], &file3_dirno, &file3_dir, + &file3_name)) + { + ext2fs_close(fs); + return(-1); + } + + /* now move the first file to the 3rd */ + if ((retval = create_hard_link(fs, file3_dirno, file1_no, file3_name, + force))) + { + fprintf(stderr, "Error renaming %s/%s as %s/%s\n", + ((file1_dir == NULL) ? "." : file1_dir), file1_name, + ((file3_dir == NULL) ? "." : file3_dir), file3_name); + ext2fs_close(fs); + return(1); + } + + if ((retval = ext2fs_unlink(fs, file1_dirno, file1_name, 0, 0))) + { + fprintf(stderr, "%s - %s\n", file1_name, error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + + /* now move the 2nd file to the 1st */ + if ((retval = create_hard_link(fs, file1_dirno, file2_no, file1_name, + force))) + { + fprintf(stderr, "Error renaming %s/%s as %s/%s\n", + ((file2_dir == NULL) ? "." : file2_dir), file2_name, + ((file1_dir == NULL) ? "." : file1_dir), file1_name); + ext2fs_close(fs); + return(1); + } + + if ((retval = ext2fs_unlink(fs, file2_dirno, file2_name, 0, 0))) + { + fprintf(stderr, "%s - %s\n", file2_name, error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + if (verbose) + fprintf(stderr, "renamed file %s/%s as %s/%s\n" + "renamed file %s/%s as %s/%s\n", + ((file1_dir == NULL) ? "." : file1_dir), file1_name, + ((file3_dir == NULL) ? "." : file3_dir), file3_name, + ((file2_dir == NULL) ? "." : file2_dir), file2_name, + ((file1_dir == NULL) ? "." : file1_dir), file1_name); + } + else + { + /* now remove the first file */ + if ((retval = ext2fs_unlink(fs, file1_dirno, file1_name, 0, 0))) + { + fprintf(stderr, "%s - %s\n", file1_name, error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + /* now move the 2nd file to the 1st */ + if ((retval = create_hard_link(fs, file1_dirno, file2_no, file1_name, + force))) + { + fprintf(stderr, "Error renaming %s/%s as %s/%s\n", + ((file2_dir == NULL) ? "." : file2_dir), file2_name, + ((file1_dir == NULL) ? "." : file1_dir), file1_name); + ext2fs_close(fs); + return(1); + } + + if ((retval = ext2fs_unlink(fs, file2_dirno, file2_name, 0, 0))) + { + fprintf(stderr, "%s - %s\n", file2_name, error_message(retval)); + ext2fs_close(fs); + return(retval); + } + + if ((retval = create_hard_link(fs, file2_dirno, file1_no, file2_name, + force))) + { + fprintf(stderr, "Error renaming %s/%s as %s/%s\n", + ((file1_dir == NULL) ? "." : file1_dir), file1_name, + ((file2_dir == NULL) ? "." : file2_dir), file2_name); + ext2fs_close(fs); + return(1); + } + + if (verbose) + fprintf(stderr, "swapped files %s/%s <-> %s/%s\n", + ((file1_dir == NULL) ? "." : file1_dir), file1_name, + ((file2_dir == NULL) ? "." : file2_dir), file2_name); + + } + + ext2fs_close(fs); + return(0); + +} /* end of do_swap */ diff --git a/progress.c b/progress.c new file mode 100644 index 0000000..ac44cac --- /dev/null +++ b/progress.c @@ -0,0 +1,198 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/progress.c,v 0.1 2002/06/26 11:17:28 ksheff Exp $ */ +/* + * progress.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + */ + +#ifndef PROGRESS_C +#define PROGRESS_C +#endif + +/* Description */ +/* + * + * + */ +/* + * $Log: progress.c,v $ + * Revision 0.1 2002/06/26 11:17:28 ksheff + * Initial revision + * + */ + +/* Feature Test Switches */ +/* System Headers */ +#include <stdio.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/time.h> + +/* Macros */ +#define PROG_FILE_SIZE 50 +#define PROG_CLEAR \ +" \r" +/* Local Variables */ + +static char prog_file[PROG_FILE_SIZE+1]; +static struct stat *prog_sbuf = NULL; +static long prog_start; +static long prog_time; + +/* Name: init_progress() + * + * Description: + * + * This function initializes the progress status variables for a particular + * file operation + * . + * + * Algorithm: + * + * Determine the size of the file name + * Copy the last PROG_FILE_SIZE characters of the filename + * Copy the pointer to the file statistics structure + * + * Global Variables: + * + * char prog_file[PROG_FILE_SIZE+1]; The file being operated on + * struct stat *prog_sbuf; prog_file's information + * long prog_start; The initial start time + * long prog_time; The last update time + * + * Arguments: + * + * char *file; The file to watch + * struct stat *sbuf; The file's information + * + * Return Values: + * + * None + * + * Author: Keith W. Sheffield + * Date: 06/26/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +void init_progress(char *file, struct stat *sbuf) +{ + int len; + struct timeval tv; + + if (file != NULL && sbuf != NULL) + { + if (strcmp(file, "-") == 0) + file = "<stdin>"; + + len = strlen(file); + if (len > PROG_FILE_SIZE) + { + file += (len - PROG_FILE_SIZE); + len = PROG_FILE_SIZE; + } + memset(prog_file, ' ', PROG_FILE_SIZE); + memcpy(prog_file, file, len); + prog_file[PROG_FILE_SIZE] = '\0'; + prog_sbuf = sbuf; + gettimeofday(&tv, NULL); + prog_start = prog_time = tv.tv_sec; + } + else + { + prog_file[0] = '\0'; + prog_sbuf = NULL; + prog_start = prog_time = 0; + } + +} /* end of init_progress */ + +/* Name: update_progress() + * + * Description: + * + * This function updates the current file progress display. + * + * Algorithm: + * + * Get the system time in seconds. + * If different from the last update + * Save the system time + * Display the file name, current byte total, and total file size + * + * Global Variables: + * + * char prog_file[PROG_FILE_SIZE+1]; The file being operated on + * struct stat *prog_sbuf; prog_file's information + * long prog_time; The last update time + * + * Arguments: + * + * unsigned long num_bytes; The number of bytes transferred + * + * Return Values: + * + * None + * + * Author: Keith W. Sheffield + * Date: 06/26/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +void update_progress(unsigned long num_bytes) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + if (prog_sbuf != NULL && prog_time != tv.tv_sec) + { + prog_time = tv.tv_sec; + fprintf(stderr, "%s %10d / %10d\r", prog_file, num_bytes, + prog_sbuf->st_size); + fflush(stderr); + } +} /* end of update_progress */ + +/* Name: finish_progress() + * + * Description: + * + * This function clears the current progress line if needed. + * + * Algorithm: + * + * Check to see if prog_start is different than prog_time + * Clear the progress line + * + * Global Variables: + * + * + * Arguments: + * + * None + * + * Return Values: + * + * None + * + * Author: Keith W. Sheffield + * Date: 06/26/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +void finish_progress() +{ + if (prog_start != prog_time) + fputs(PROG_CLEAR, stderr); + +} /* end of finish_progress */ @@ -0,0 +1,368 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/read.c,v 0.2 2002/08/08 07:58:35 ksheff Exp $ */ +/* + * read.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + * Derived from dump.c Copyright (C) 1994 Theodore Ts'o <tytso@mit.edu> + * + */ + +static char rcsid[] = "$Id: read.c,v 0.2 2002/08/08 07:58:35 ksheff Exp $"; + +static char copyright[] = "Copyright 2002 Keith W Sheffield"; + +#ifndef READ_C +#define READ_C +#endif + +/* Description */ +/* + * + * + */ +/* + * $Log: read.c,v $ + * Revision 0.2 2002/08/08 07:58:35 ksheff + * Split the read loop from retrieve_data() out to its own function: + * read_to_eof() and made retrieve_data() able to seek to an offset before + * starting to read. + * + * Revision 0.1 2002/02/27 04:48:52 ksheff + * initial revision + * + */ + +/* Feature Test Switches */ +/* Headers */ +#include "e2tools.h" + +/* Local Prototypes */ + +long +get_file(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + char *infile, char *outfile, int keep); + +long +retrieve_data(ext2_filsys fs, ext2_ino_t src, int dest_fd, + char *dest_name, int keep, ext2_off_t offset, + ext2_off_t *ret_pos); + +long +read_to_eof(ext2_file_t infile, int dest_fd, ext2_off_t offset, + ext2_off_t *ret_pos); + + +static void +fix_perms(const struct ext2_inode *inode, int fd, const char *name); + +/* Name: get_file() + * + * Description: + * + * This function copies a file from the current ext2fs directory to disk + * or stdout. + * + * Algorithm: + * + * Check input parameters + * If the output file is NULL + * Get the file descriptor for stdout + * Otherwise + * Open the output file + * Get the inode number for the input file + * Copy the contents to the output file + * Close output file + * + * Global Variables: + * + * None + * + * Arguments: + * + * ext2_filsys fs; The current file system + * ext2_ino_t root; The root directory + * ext2_ino_t cwd; The current working directory + * char *infile; The name of the input file + * char *outfile; The name of the output file + * int keep; Flag indicating if the permissions should be kept + * + * Return Values: + * + * 0 - the file was copied successfully + * the error code of whatever went wrong. + * + * Author: Keith W. Sheffield + * Date: 02/20/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ + +long +get_file(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, + char *infile, char *outfile, int keep) +{ + int fd; + ext2_ino_t src; + int dest; + int retval; + + if (fs == NULL || infile == NULL) + { + fputs("Invalid input parameter. Exiting get_file() with -1\n", + stderr); + return (-1); + } + + /* open the output file if we need to */ + if (outfile == NULL) + dest = fileno(stdout); + else if (-1 == (dest = open(outfile, O_CREAT | O_WRONLY | O_TRUNC, 0666))) + { + perror(outfile); + return(-1); + } + + /* get the inode number associated with the input file */ + if ((retval = ext2fs_namei(fs, root, cwd, infile, &src))) + { + if (retval == EXT2_ET_FILE_NOT_FOUND) + { + fprintf(stderr, "%s not found\n", infile); + if (outfile) + { + close(dest); +#ifndef DEBUG + unlink(outfile); +#endif + } + return(0); + } + fputs(error_message(retval), stderr); + return retval; + } + + /* get the data from the ext2fs */ + if ((retval = retrieve_data(fs, src, dest, outfile, keep, 0, NULL))) + { + if (outfile) + { + close(dest); +#ifndef DEBUG + unlink(outfile); +#endif + } + return(retval); + } + if (outfile) + close(dest); + return(0); + +} /* end of get_file */ + + +/* Name: retrieve_data() + * + * Description: + * + * This function retrieves the data stored as a file in an ext2fs file + * system. + * + * Algorithm: + * + * Get the inode associated with the file name + * Open the file in the ext2fs file system + * Copy the contents of the ext2fs file to the output file descriptor + * Close the ext2fs file + * If the permissions are to be kept + * Call fix_perms + * + * Global Variables: + * + * None + * + * Arguments: + * + * ext2_filsys fs; The filesystem being read from + * ext2_ino_t src; The source inode number + * int dest_fd; The destination file descriptor + * char *dest_name; The name of the destination file + * int keep; Keep the permissions/ownership, etc. from ext2fs + * + * Return Values: + * + * 0 - file read successfully + * error code of what went wrong. + * + * Author: Keith W. Sheffield + * Date: 02/20/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 08/07/02 K.Sheffield Moved the copy loop to read_to_eof() + * + */ + +long +retrieve_data(ext2_filsys fs, ext2_ino_t src, int dest_fd, + char *dest_name, int keep, ext2_off_t offset, + ext2_off_t *ret_pos) +{ + struct ext2_inode inode; + ext2_file_t infile; + int retval; + + if (keep && (retval = ext2fs_read_inode(fs, src, &inode))) + { + fputs(error_message(retval), stderr); + return retval; + } + + if ((retval = ext2fs_file_open(fs, src, 0, &infile))) + { + fputs(error_message(retval), stderr); + return retval; + } + + if (read_to_eof(infile, dest_fd, offset, ret_pos)) + { + if ((retval = ext2fs_file_close(infile))) + fputs(error_message(retval), stderr); + return(-1); + } + + if ((retval = ext2fs_file_close(infile))) + { + fputs(error_message(retval), stderr); + return retval; + } + + if (keep) + fix_perms(&inode, dest_fd, dest_name); + + return(0); + +} /* end of retrieve_data */ + +/* Name: read_to_eof() + * + * Description: + * + * This function reads from an ext2_file_t file and outputs the contents + * to a standard file descriptor. + * + * Algorithm: + * + * Seek to the desired location + * While one is able to read data from the ext2fs file + * Write data to the output file descriptor. + * + * Global Variables: + * + * None. + * + * Arguments: + * + * ext2_file_t infile; Input file + * int dest_fd; The destination file descriptor + * ext2_off_t offset; The offset in the file to seek + * ext2_off_t *ret_pos; The returned file position + * + * Return Values: + * + * + * Author: Keith W. Sheffield + * Date: 08/07/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * + */ +long +read_to_eof(ext2_file_t infile, int dest_fd, ext2_off_t offset, + ext2_off_t *ret_pos) +{ + char buf[4096]; + unsigned int bytes_read; + int bytes_written; + int retval; + + if (offset != 0 && + (retval = ext2fs_file_lseek(infile, offset, EXT2_SEEK_SET, NULL))) + { + fputs(error_message(retval), stderr); + return retval; + } + + /* read all that we can and dump it to the output file descriptor */ + do + { + if ((retval = ext2fs_file_read(infile, buf, sizeof(buf), &bytes_read))) + { + fputs(error_message(retval), stderr); + return retval; + } + } + while (bytes_read > 0 && + bytes_read == (bytes_written = write(dest_fd, buf, bytes_read))); + + if (bytes_read) + { + perror("read_to_eof"); + return(-1); + } + + if (ret_pos != NULL && + (retval = ext2fs_file_lseek(infile, 0, EXT2_SEEK_CUR, ret_pos))) + { + fputs(error_message(retval), stderr); + return retval; + } + + return(0); + +} /* end of read_to_eof */ + +/* blatantly copied from code written by T Ts'o w/ minor changes */ +static void +fix_perms(const struct ext2_inode *inode, int fd, const char *name) +{ + struct utimbuf ut; + int i; + + if (fd != -1) + i = fchmod(fd, ext2_mode_xlate(inode->i_mode)); + else + i = chmod(name, ext2_mode_xlate(inode->i_mode)); + if (i == -1) + perror(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) + perror(name); + + if (fd != -1) + close(fd); + + ut.actime = inode->i_atime; + ut.modtime = inode->i_mtime; + if (utime(name, &ut) == -1) + perror(name); + +} + + + @@ -0,0 +1,413 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/rm.c,v 0.3 2004/04/06 23:39:28 ksheff Exp $ */ +/* + * rm.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + * Derived from debugfs.c Copyright (C) 1993 Theodore Ts'o <tytso@mit.edu> + * and modified by Robert Sanders <gt8134b@prism.gatech.edu> + * as well as portions of the ext2fs library (C) 1993-1995 Theodore Ts'o + */ + +#ifndef RM_C +#define RM_C +#endif + +/* Description */ +/* + * This file contains function used to remove files in an ext2fs filesystem. + * + */ +/* + * $Log: rm.c,v $ + * Revision 0.3 2004/04/06 23:39:28 ksheff + * Corrected getopt and usage strings. + * + * Revision 0.2 2002/06/05 23:39:13 ksheff + * Added ability to delete files based on a regular expression and recursive + * deletion of directories. + * + * Revision 0.1 2002/04/10 10:42:40 ksheff + * initial revision + * + */ + + +/* Headers */ +#include "e2tools.h" +#include <regex.h> + +static ext2_filsys gbl_fs = NULL; +static char *gbl_filesys = NULL; +static char *gbl_path_end = NULL; +static char gbl_dir_name[8192]; + +struct regexp_args +{ + int verbose; + int recursive; + regex_t *reg; +}; + +/* Local Prototypes */ +long +e2rm(int argc, char *argv[]); +static +int rm_dir_proc(ext2_ino_t dir,int entry, struct ext2_dir_entry *dirent, + int offset, int blocksize, char *buf, void *verbose); +static int +recursive_rm(ext2_ino_t dir, char *name, struct ext2_dir_entry *dirent, + int verbose); +static int +rm_regex_proc(ext2_ino_t dir, int entry, struct ext2_dir_entry *dirent, + int offset, int blocksize, char *buf, void *private); + +/* Name: e2rm() + * + * Description: + * + * This function extracts the command line parameters and creates + * directories based on user input + * + * Algorithm: + * + * Extract any command line switches + * Sort the remaining arguments + * For each argument + * Open a new filesystem if needed + * Remove the file if it exists. + * + * Global Variables: + * + * None + * + * Arguments: + * + * int argc; The number of arguments + * char *argv[]; the command line arguments + * + * Return Values: + * + * 0 - the filess were created successfully + * otherwise, an error code is returned + * + * Author: Keith W. Sheffield + * Date: 04/10/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 04/06/04 K.Sheffield Corrected getopt and usage strings. + */ +long +e2rm(int argc, char *argv[]) +{ + int verbose=0; + int errcnt=0; + int recursive=0; + char *last_filesys = NULL; + char *cur_filesys = NULL; + ext2_filsys fs = NULL; + ext2_ino_t root; + ext2_ino_t cwd; + char **cur_opt; + char *filespec; + long retval; + char *dir_name; + char *base_name; + ext2_ino_t curr_ino; + int c; + int num_files; + char *ptr; + struct regexp_args reg; + +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif + while ((c = getopt(argc, argv, "vr")) != EOF) + { + switch (c) + { + case 'v': + verbose = 1; + break; + case 'r': + recursive = 1; + break; + default: + errcnt++; + break; + } + } + + if (errcnt || argc == optind) + { + fputs("Usage: e2rm [-vr] filesystem:filepath...\n", stderr); + return(1); + } + + num_files = argc - optind; + + cur_opt = argv + optind; + if (num_files > 1 ) + qsort(cur_opt, num_files, sizeof(char *), my_strcmp); + + for(c=0;c<num_files;c++) + { + filespec = *cur_opt++; + + /* dealing with a filesystem or a regular file */ + if (NULL != (ptr = strchr(filespec, ':'))) + { + /* separate the filesystem name from the file name */ + *ptr++ = '\0'; + cur_filesys = filespec; + filespec = ptr; + + /* check to see if the filesystem has changed */ + if (last_filesys == NULL || + strcmp(last_filesys, cur_filesys) != 0) + { + if (last_filesys != NULL && + (retval = ext2fs_close(fs))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + + if ((retval = open_filesystem(cur_filesys, &fs, &root, 1))) + { + fprintf(stderr, "%s\n", error_message(retval)); + fprintf(stderr, "Error opening fileystem %s\n", + cur_filesys); + return retval; + } + cwd = root; + last_filesys = cur_filesys; + } /* end of filesystem change? */ + + + if (get_file_parts(fs, root, filespec, &cwd, &dir_name, &base_name)) + { + ext2fs_close(fs); + return(-1); + } + + if (is_file_regexp(base_name)) + { + if (NULL == (reg.reg = (regex_t *) make_regexp(base_name))) + { + fprintf(stderr, + "Error creating regular expression for %s\n", + base_name); + continue; + } + + gbl_fs = fs; + gbl_filesys = cur_filesys; + + reg.verbose = verbose; + reg.recursive = recursive; + + strcpy(gbl_dir_name, dir_name); + gbl_path_end = gbl_dir_name + strlen(gbl_dir_name); + + retval = ext2fs_dir_iterate2(gbl_fs, cwd, + DIRENT_FLAG_INCLUDE_EMPTY, 0, + rm_regex_proc, (void *) ®); + regfree(reg.reg); + continue; + } + + /* check to see if the file name exists in the current directory */ + else if ((retval = ext2fs_namei(fs, cwd, cwd, base_name, &curr_ino))) + { + if (retval != EXT2_ET_FILE_NOT_FOUND) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + } + /* file name exists, let's see if is a directory */ + else if ((retval = ext2fs_check_directory(fs, curr_ino)) == 0) + { + if (recursive) + { + gbl_fs = fs; + gbl_filesys = cur_filesys; + + sprintf(gbl_dir_name, "%s/%s", (dir_name == NULL)?".": + dir_name, base_name); + gbl_path_end = gbl_dir_name + strlen(gbl_dir_name); + + retval = ext2fs_dir_iterate2(gbl_fs, curr_ino, + DIRENT_FLAG_INCLUDE_EMPTY, 0, + rm_dir_proc, + (void *) + (verbose) ? &verbose : NULL); + } + else + { + printf("%s:%s/%s is a directory! Not removed\n", cur_filesys, + (dir_name == NULL)?".": dir_name, base_name); + continue; + } + } + if (retval != 0 && retval != EXT2_ET_NO_DIRECTORY) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + /* delete the existing file if needed */ + if ((retval = rm_file(fs, cwd, base_name, curr_ino))) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + + if (verbose) + printf("Removed %s:%s/%s\n", cur_filesys, + (dir_name == NULL)?".":dir_name, base_name); + } + + else if (verbose) + { + printf("%s is not a valid e2fs filesystem specification. skipping\n", + filespec); + } + } + + if (fs != NULL && + (retval = ext2fs_close(fs))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + } + return(0); + +} /* end of e2rm */ + +static int rm_dir_proc(ext2_ino_t dir, int entry, + struct ext2_dir_entry *dirent, int offset, + int blocksize, char *buf, void *verbose) +{ + char name[EXT2_NAME_LEN]; + int thislen; + + thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ? + (dirent->name_len & 0xFF) : EXT2_NAME_LEN; + + if (dirent->name[0] == '.' && + (thislen == 1 || (thislen == 2 && dirent->name[1] == '.'))) + return 0; + + strncpy(name, dirent->name, thislen); + name[thislen] = '\0'; + + if (entry == DIRENT_DELETED_FILE) + return 0; + + return (recursive_rm(dir, name, dirent, (verbose) ? 1 : 0)); +} + +static int +recursive_rm(ext2_ino_t dir, char *name, struct ext2_dir_entry *dirent, + int verbose) +{ + long retval; + + /* file name exists, let's see if is a directory */ + if ((retval = ext2fs_check_directory(gbl_fs, dirent->inode)) == 0) + { + *gbl_path_end++ = '/'; + strncpy(gbl_path_end, dirent->name, dirent->name_len); + gbl_path_end += dirent->name_len; + *gbl_path_end = '\0'; + + retval = ext2fs_dir_iterate2(gbl_fs, dirent->inode, + DIRENT_FLAG_INCLUDE_EMPTY, 0, + rm_dir_proc, (verbose) ? &verbose : NULL); + + while (gbl_path_end > gbl_dir_name && *gbl_path_end != '/') + gbl_path_end--; + *gbl_path_end = '\0'; + } + + if (retval !=0 && retval != EXT2_ET_NO_DIRECTORY) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + /* delete the existing file if needed */ + if ((retval = rm_file(gbl_fs, dir, name, dirent->inode))) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + + if (verbose) + printf("Removed %s:%s/%s\n", gbl_filesys, gbl_dir_name, name); + + return 0; +} + +static int +rm_regex_proc(ext2_ino_t dir, int entry, struct ext2_dir_entry *dirent, + int offset, int blocksize, char *buf, void *arg) +{ + long retval; + char name[EXT2_NAME_LEN]; + int thislen; + struct regexp_args *reg = (struct regexp_args *) arg; + + thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ? + (dirent->name_len & 0xFF) : EXT2_NAME_LEN; + + if (dirent->name[0] == '.' && + (thislen == 1 || (thislen == 2 && dirent->name[1] == '.'))) + return 0; + + strncpy(name, dirent->name, thislen); + name[thislen] = '\0'; + + if (entry == DIRENT_DELETED_FILE) + return 0; + + if (0 == (retval = regexec(reg->reg, name, 0, NULL, 0))) + { + if (reg->recursive) + return (recursive_rm(dir, name, dirent, (reg->verbose) ? 1 : 0)); + else + { + if ((retval = ext2fs_check_directory(gbl_fs, dirent->inode))) + { + if (retval != EXT2_ET_NO_DIRECTORY) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + /* delete the existing file if needed */ + if ((retval = rm_file(gbl_fs, dir, name, dirent->inode))) + { + fprintf(stderr, "%s\n",error_message(retval)); + return(retval); + } + + if (reg->verbose) + printf("Removed %s:%s/%s\n", gbl_filesys, gbl_dir_name, name); + } + else + { + printf("%s:%s/%s is a directory! Not removed\n", gbl_filesys, + gbl_dir_name, name); + } + } + } + return (0); +} + + + + + @@ -0,0 +1,440 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/tail.c,v 0.2 2003/07/12 16:33:11 ksheff Exp $ */ +/* + * tail.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + */ +#ifndef TAIL_C +#define TAIL_C +#endif + +/* Description */ +/* This module implements a basic version of the tail command. + * + * The user can specify the number of lines to view from the bottom of the + * file. This is done by specifying -n #of_lines on the command line. The + * default is 5. + * + * The user can also run in 'follow' mode which prints new lines as they are + * appended to the end of the file. This can be specified by the -f option, + * which is dependent on the initial inode of the file being tailed or the -F + * option which will always use the inode associated with the file name. The + * latter can be useful for log files that get switched out. + * + * The -s #seconds option allows the user to specify the sleep interval while + * in follow mode. The default is 1. + * + */ +/* + * $Log: tail.c,v $ + * Revision 0.2 2003/07/12 16:33:11 ksheff + * fixed a bug when no arguments are given. + * + * Revision 0.1 2002/08/08 08:01:51 ksheff + * Initial revision. + * + */ + +/* Feature Test Switches */ +/* Headers */ + +#include "e2tools.h" + + +/* Macros */ +#define USAGE "Usage: e2tail [-n num_lines][-fF][-s sleep_interval] file\n" +#define BLK_SIZE 4096 + +#define FOLLOW_INODE 1 +#define FOLLOW_NAME 2 + +/* Structures and Unions */ + +/* External Variables */ + +/* Global Variables */ + +/* Local Variables */ + +/* External Prototypes */ + +/* Local Prototypes */ +long +do_tail(int argc, char *argv[]); +static long +tail(ext2_filsys *fs, ext2_ino_t root, char *input, int num_lines, + int follow, int sleep_int, char *cur_filesys); + + +/* Name: do_tail() + * + * Description: + * + * This function reads the command line arguments and displays the last lines + * at the end of a file in an ext2 file system. + * + * Algorithm: + * + * Read any command line switches + * Get the file specification for the file we are going to display. + * Open the file system read only + * Tail the file + * Close the file system + * return the status of the tail + * + * Global Variables: + * + * None + * + * Arguments: + * + * int argc; The number of arguments + * char *argv[]; The command line arguments + * + * Return Values: + * + * 0 - the last number of lines was displayed correctly. + * an error occurred. + * + * Author: Keith W. Sheffield + * Date: 08/07/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 07/12/03 K.Sheffield fixed a bug when no arguments are given. + */ +long +do_tail(int argc, char *argv[]) +{ + int verbose=0; + int follow=0; + int num_lines = 5; + int sleep_int = 1; + int errcnt=0; + char *cur_filesys = NULL; + ext2_filsys fs = NULL; + ext2_ino_t root; + long retval; + int curidx; + char *tail_dir; + int c; + + +#ifdef HAVE_OPTRESET + optreset = 1; /* Makes BSD getopt happy */ +#endif + while ((c = getopt(argc, argv, "vFfn:s:")) != EOF) + { + switch (c) + { + case 'v': + verbose = 1; + break; + case 'f': + follow = FOLLOW_INODE; + break; + case 'F': + follow = FOLLOW_NAME; + break; + case 'n': + num_lines = atoi(optarg); + break; + case 's': + sleep_int = atoi(optarg); + if (sleep_int < 1) + errcnt++; + break; + default: + errcnt++; + break; + } + } + + curidx = optind; + + if (errcnt || argc <= curidx) + { + fputs(USAGE, stderr); + return(1); + } + + cur_filesys = argv[curidx++]; + if (NULL == (tail_dir = strchr(cur_filesys, ':'))) + { + fprintf(stderr, "Invalid file specification: %s\n", cur_filesys); + return(1); + } + *tail_dir++ = '\0'; + + if ((retval = open_filesystem(cur_filesys, &fs, &root, 0))) + { + fprintf(stderr, "%s: %s\n", error_message(retval), cur_filesys); + return retval; + } + + retval = tail(&fs, root, tail_dir, num_lines, follow, sleep_int, + cur_filesys) ? -1 : 0; + ext2fs_close(fs); + return(retval); +} + +/* Name: tail() + * + * Description: + * + * This function displays the last lines at the end of a file in an ext2 + * file system. + * + * Algorithm: + * + * Get the directory and basename of the file + * Determine the inode number for the file + * Open the file for reading + * Skip to the last block in the file + * While we have not found the last num_lines of newline characters + * Skip backwards in the file one block and read it + * Display the contents of the block from that point on. + * Display the rest of the file if not contained in the block + * Save the current location of the file. + * If we are following the file as it grows + * While forever + * Sleep + * Re-read the inode for the file + * If the size has changed + * Display the file from the saved point on + * Save the current location of the file. + * + * + * Global Variables: + * + * None + * + * Arguments: + * + * ext2_filsys *fs; Our filesystem + * ext2_ino_t root; The root directory inode number + * char *input; The name of the input file to tail + * int num_lines; The number of lines to display + * int follow; Flag indicating if the we should follow any + * new contents to the file. + * int sleep_int; The number of seconds to sleep between checking + * for new lines + * char *cur_filesys + * + * Return Values: + * + * 0 - the last number of lines was displayed correctly. + * an error occurred. + * + * Author: Keith W. Sheffield + * Date: 08/07/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + */ +static long +tail(ext2_filsys *fs_ptr, ext2_ino_t root, char *input, int num_lines, + int follow, int sleep_int, char *cur_filesys) +{ + ext2_filsys fs = *fs_ptr; + ext2_ino_t cwd; + ext2_ino_t tail_ino; + ext2_ino_t t_tail_ino; + char *tail_dir; + char *tail_name; + long retval; + char buf[BLK_SIZE]; + unsigned int bytes_to_read; + unsigned int bytes_read; + char *ptr; + off_t pos; + struct ext2_inode inode; + ext2_file_t tail_fd; + ext2_off_t offset; + ext2_off_t cur_pos; + + if (get_file_parts(fs, root, input, &cwd, &tail_dir, &tail_name)) + { + ext2fs_close(fs); + return(-1); + } + + /* get the inode number for the source file */ + if ((retval = ext2fs_namei(fs, cwd, cwd, tail_name, &tail_ino))) + { + fprintf(stderr, "%s: file %s\n",error_message(retval), + tail_name); + return(retval); + } + + /* open the file */ + if ((retval = ext2fs_file_open(fs, tail_ino, 0, &tail_fd))) + { + fputs(error_message(retval), stderr); + return retval; + } + + /* get the length of the file and determine where to start reading */ + inode.i_size = offset = ext2fs_file_get_size(tail_fd); + bytes_to_read = offset % BLK_SIZE; + if (bytes_to_read == 0) + bytes_to_read = BLK_SIZE; + + offset -= bytes_to_read; + if (offset < 0) + offset = 0; + + do + { + /* seek to the start of the last block in the file */ + if ((retval = ext2fs_file_lseek(tail_fd, offset, EXT2_SEEK_SET, NULL))) + { + fputs(error_message(retval), stderr); + return retval; + } + /* read the last block in the file */ + if ((retval = ext2fs_file_read(tail_fd, buf, bytes_to_read, + &bytes_read))) + { + fputs(error_message(retval), stderr); + return retval; + } + if (bytes_to_read != bytes_read) + { + fputs("error reading file\n", stderr); + return(-1); + } + + ptr = buf + bytes_read - 1; + while (bytes_to_read--) + { + if (*ptr == '\n' && num_lines-- == 0) + { + /* if the newline wasn't the last character in the buffer, then + * print what's remaining. + */ + if (bytes_to_read != bytes_read - 1) + { + ptr++; + write(1, ptr, bytes_read - bytes_to_read - 1); + } + offset = 0; /* make sure we break out of the main loop */ + break; + } + ptr--; + } + + offset -= (offset < BLK_SIZE) ? offset : BLK_SIZE; + bytes_to_read = BLK_SIZE; + } + while (offset > 0); + + /* if we are here and have any lines left, we hit the beginning, so + * dump the rest of what's in memory out. + */ + + if (num_lines > 0) + write(1, buf, bytes_read); + + /* retreive the current position in the file */ + if ((retval = ext2fs_file_lseek(tail_fd, 0, EXT2_SEEK_CUR, &cur_pos))) + { + fputs(error_message(retval), stderr); + return retval; + } + + /* ok, if we are before the end of the file, then dump the rest of it */ + if (cur_pos < inode.i_size) + { + if ((retval = read_to_eof(tail_fd, 1, cur_pos, &cur_pos))) + { + return retval; + } + } + + if ((retval = ext2fs_file_close(tail_fd))) + { + fputs(error_message(retval), stderr); + return retval; + } + + if (follow) + { + while(1) + { + sleep(sleep_int); + /* I don't know how to force a re-read of the file system info yet, + * so, just close the file system and reopen it. + */ + ext2fs_close(fs); + if ((retval = open_filesystem(cur_filesys, &fs, &root, 0))) + { + *fs_ptr = NULL; + fprintf(stderr, "%s: %s\n", error_message(retval), cur_filesys); + return retval; + } + *fs_ptr = fs; + + /* if we are following the name, find the directory and file name + * again. + */ + if (follow == FOLLOW_NAME) + { + cwd = root; + + if (tail_dir != NULL && *tail_dir != '\0' && + strcmp(tail_dir, ",") != 0 && + (retval = change_cwd(fs, root, &cwd, tail_dir))) + { + fprintf(stderr, "Error changing to directory %s\n", + tail_dir); + return(retval); + } + + /* get the inode number for the source file */ + if ((retval = ext2fs_namei(fs, cwd, cwd, tail_name, + &t_tail_ino))) + { + fprintf(stderr, "%s: file %s\n",error_message(retval), + tail_name); + return(retval); + } + + /* if we are dealing with a new file, then start from the + * beginning. + */ + + if (t_tail_ino != tail_ino) + { + tail_ino = t_tail_ino; + cur_pos = 0; + } + } + + if ((retval = ext2fs_read_inode(fs, tail_ino, &inode))) + { + fputs(error_message(retval), stderr); + return retval; + } + if (inode.i_size > cur_pos) + { + if ((retval = retrieve_data(fs, tail_ino, 1, NULL, 0, cur_pos, + &cur_pos))) + { + fputs(error_message(retval), stderr); + return retval; + } + } + else if (inode.i_size < cur_pos) + { + /* the file was truncated, so bail */ + return(0); + } + } + } + return(0); +} @@ -0,0 +1,320 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/util.c,v 0.4 2002/06/05 20:38:16 ksheff Exp $ */ +/* + * util.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + * Derived from debugfs.c Copyright (C) 1993 Theodore Ts'o <tytso@mit.edu> + * and modified by Robert Sanders <gt8134b@prism.gatech.edu> + */ + +#ifndef UTIL_C +#define UTIL_C +#endif + +/* Description */ +/* + * Misc. utility functions + * + */ +/* + * $Log: util.c,v $ + * Revision 0.4 2002/06/05 20:38:16 ksheff + * Added regular expression routines. + * + * Revision 0.3 2002/04/10 09:31:21 ksheff + * Added function init_stat_buf(). + * + * Revision 0.2 2002/03/07 07:27:45 ksheff + * checked for return of ext2fs_unlink in rm_file(). + * + * Revision 0.1 2002/02/27 04:49:11 ksheff + * initial revision + * + */ + +/* Headers */ +#include "e2tools.h" +#include <regex.h> + +/* Macros */ + +/* Structures and Unions */ +typedef struct +{ + __u16 lmask; + mode_t mask; +} MODE_XLAT_T; + +static MODE_XLAT_T xlat_tbl[] = +{ + { LINUX_S_IFREG, S_IFREG }, + { LINUX_S_IFDIR, S_IFDIR }, + { LINUX_S_IFCHR, S_IFCHR }, + { LINUX_S_IFIFO, S_IFIFO }, + { LINUX_S_ISUID, S_ISUID }, + { LINUX_S_ISGID, S_ISGID }, + { LINUX_S_ISVTX, S_ISVTX }, + { 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 } +}; + +/* External Variables */ + +/* Global Variables */ + +/* Local Variables */ + +/* External Prototypes */ + +/* Local Prototypes */ + +mode_t +ext2_mode_xlate(__u16 lmode); +__u16 +host_mode_xlate(mode_t hmode); +static int +release_blocks_proc(ext2_filsys fs, blk_t *blocknr, + int blockcnt, void *private); +long +delete_file(ext2_filsys fs, ext2_ino_t inode); + +/* translate a ext2 mode to the host OS representation */ +mode_t ext2_mode_xlate(__u16 lmode) +{ + mode_t mode = 0; + int i; + + for (i=0; xlat_tbl[i].lmask; i++) + { + if (lmode & xlat_tbl[i].lmask) + mode |= xlat_tbl[i].mask; + } + return mode; +} + +/* translate a host OS mode to the ext2 representation */ +__u16 host_mode_xlate(mode_t hmode) +{ + __u16 mode = 0; + int i; + + for (i=0; xlat_tbl[i].lmask; i++) + { + if (hmode & xlat_tbl[i].mask) + mode |= xlat_tbl[i].lmask; + } + return mode; +} + +long +open_filesystem(char *name, ext2_filsys *fs, ext2_ino_t *root, int rw_mode) +{ + int retval; + int closeval; + + + if ((retval = ext2fs_open(name, (rw_mode) ? EXT2_FLAG_RW : 0, 0, 0, + unix_io_manager, fs))) + { + fprintf(stderr, "%s\n", error_message(retval)); + *fs = NULL; + return retval; + } + + if ((retval = ext2fs_read_inode_bitmap(*fs))) + { + fprintf(stderr, "%s\n", error_message(retval)); + if ((closeval = ext2fs_close(*fs))) + fputs(error_message(closeval), stderr); + *fs = NULL; + return retval; + } + + if ((retval = ext2fs_read_block_bitmap(*fs))) + { + fprintf(stderr, "%s\n", error_message(retval)); + if ((closeval = ext2fs_close(*fs))) + fputs(error_message(closeval), stderr); + *fs = NULL; + return retval; + } + + *root = EXT2_ROOT_INO; + return(0); +} + +long +read_inode(ext2_filsys fs, ext2_ino_t file, struct ext2_inode *inode) +{ + long retval; + + if ((retval = ext2fs_read_inode(fs, file, inode))) + fprintf(stderr, "%s\n", error_message(retval)); + return retval; +} + +long +write_inode(ext2_filsys fs, ext2_ino_t file, struct ext2_inode *inode) +{ + long retval; + + if ((retval = ext2fs_write_inode(fs, file, inode))) + fprintf(stderr, "%s\n", error_message(retval)); + return retval; + +} + +long +rm_file(ext2_filsys fs, ext2_ino_t cwd, char *outfile, ext2_ino_t delfile) +{ + struct ext2_inode inode; + long retval; + + if ((retval = read_inode(fs, delfile, &inode))) + return(retval); + + --inode.i_links_count; + if ((retval = write_inode(fs, delfile, &inode))) + return(retval); + + if ((retval = ext2fs_unlink(fs, cwd, outfile, 0, 0))) + return(retval); + + if (inode.i_links_count == 0) + return(delete_file(fs, delfile)); + + return(0); +} + +long +delete_file(ext2_filsys fs, ext2_ino_t inode) +{ + struct ext2_inode inode_buf; + long retval; + + if ((retval = read_inode(fs, inode, &inode_buf))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return(retval); + } + + inode_buf.i_dtime = time(NULL); + if ((retval = write_inode(fs, inode, &inode_buf))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return(retval); + } + + if ((retval = ext2fs_block_iterate(fs, inode, 0, NULL, + release_blocks_proc, NULL))) + { + fprintf(stderr, "%s\n", error_message(retval)); + return(retval); + } + + ext2fs_inode_alloc_stats(fs, inode, -1); + + return(0); +} + +static int +release_blocks_proc(ext2_filsys fs, blk_t *blocknr, + int blockcnt, void *private) +{ + blk_t block; + + block = *blocknr; + ext2fs_block_alloc_stats(fs, block, -1); + return 0; +} + +void +init_stat_buf(struct stat *buf) +{ + if (buf) + { + memset(buf, 0, sizeof(struct stat)); + buf->st_atime = buf->st_ctime = buf->st_mtime = time(NULL); + buf->st_uid = getuid(); + buf->st_gid = getgid(); + } +} + +int +is_file_regexp(char *ptr) +{ + char c; + + while ((c = *ptr++) != '\0') + { + switch(c) + { + case '*': + case '[': + case ']': + case '?': + return(1); + break; + } + } + return(0); +} + +regex_t * +make_regexp(char *shell) +{ + char *tmpstr; + char *ptr; + static regex_t reg; + int l; + char c; + + if (NULL == (tmpstr = alloca((strlen(shell)) << 1 + 3))) + { + perror("make_regexp"); + return(NULL); + } + + ptr = tmpstr; + *ptr++ = '^'; + + while ((c = *shell++) != '\0') + { + switch(c) + { + case '*': + *ptr++ = '.'; + *ptr++ = c; + break; + case '?': + *ptr++ = '.'; + break; + case '.': + *ptr++ = '\\'; + *ptr++ = '.'; + break; + default: + *ptr++ = c; + } + } + *ptr++ = '$'; + *ptr = '\0'; + + if (regcomp(®, tmpstr, REG_NOSUB)) + { + perror("make_regexp"); + return(NULL); + } + + return(®); +} @@ -0,0 +1,377 @@ +/* $Header: /home/ksheff/src/e2tools/RCS/write.c,v 0.5 2004/04/07 01:12:30 ksheff Exp $ */ +/* + * write.c + * + * Copyright (C) 2002 Keith W Sheffield. This file may be redistributed + * under the terms of the GNU Public License. + * + * Derived from debugfs.c Copyright (C) 1993 Theodore Ts'o <tytso@mit.edu> + * and modified by Robert Sanders <gt8134b@prism.gatech.edu> + */ + +static char rcsid[] = "$Id: write.c,v 0.5 2004/04/07 01:12:30 ksheff Exp $"; + +#ifndef WRITE_C +#define WRITE_C +#endif + +/* Description */ +/* This file contains the functions used to write a file to an ext2fs + * filesystem. + * + */ +/* + * $Log: write.c,v $ + * Revision 0.5 2004/04/07 01:12:30 ksheff + * Modified to use a default file stat specified by the user. + * + * Revision 0.4 2002/07/08 11:16:11 ksheff + * Additional error messages after perror(). + * + * Revision 0.3 2002/06/26 11:12:48 ksheff + * Modified to call update_progress() so that the user can know the state of + * the file copy operation. The put_file function also calls ext2fs_flush() + * before exiting now. + * + * Revision 0.2 2002/03/07 07:15:40 ksheff + * Added parameter to put_file so that the original file's owner, group, + * permission bits, access, modification, and creation times would be used. + * + * Revision 0.1 2002/02/27 04:49:32 ksheff + * initial revision + * + */ + +/* Headers */ + +#include "e2tools.h" + +/* External Prototypes */ + +extern void init_progress(char *file, struct stat *sbuf); +extern void update_progress(unsigned long num_bytes); +extern void finish_progress(); + +/* Local Prototypes */ + +long +put_file(ext2_filsys fs, ext2_ino_t cwd, char *infile, char *outfile, + ext2_ino_t *outfile_ino, int keep, struct stat *def_stat); + +static long +store_data(ext2_filsys fs, int fd, ext2_ino_t newfile, off_t *file_size); + +/* Name: put_file() + * + * Description: + * + * This function copies a file from disk or stdin to the current directory + * + * Algorithm: + * + * Check input parameters + * If the input file is NULL + * Get the file descriptor for stdin + * Initialize a file stat structure + * Otherwise + * Open the input file + * Get the file stat structure for the file + * Get a new inode for the file + * Link the inode to the currect directory + * If this fails because there isn't enough room in the directory + * Expand the directory and try again + * Set the file statistics for the current inode + * If the file is a regular file + * Copy it to the current inode + * Close the input file + * + * Global Variables: + * + * None. + * + * Arguments: + * + * ext2_filsys fs; The current file system + * ext2_ino_t cwd; The current working directory + * char *infile; The name of the input file + * char *outfile; The name of the output file + * int keep; Flag indicating to use the input file's stat info + * struct stat *def_stat; The default file stat information + * + * Return Values: + * + * 0 - the file was copied successfully + * any other value indicates an error + * + * Author: Keith W. Sheffield + * Date: 02/17/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 02/27/02 K.Sheffield Added parameter to pass back to caller the + * inode number of the output file. + * 03/05/02 K.Sheffield Fixed a bug with reading from stdin + * 03/06/02 K.Sheffield Added time/owner/group keep flag + * 06/26/02 K.Sheffield Flush file system added at the end + * 07/08/02 K.Sheffield Additional error messages after perror() + * 04/06/04 K.Sheffield Added a default file stat parameter + */ +long +put_file(ext2_filsys fs, ext2_ino_t cwd, char *infile, char *outfile, + ext2_ino_t *outfile_ino, int keep, struct stat *def_stat) +{ + int fd; + struct stat statbuf; + ext2_ino_t newfile; + long retval; + struct ext2_inode inode; + mode_t cur_umask; + + if (fs == NULL || outfile == NULL) + { + fputs("Invalid input parameter. Exiting put_file() with -1\n", + stderr); + return (-1); + } + + if (infile == NULL) + { + fd = fileno(stdin); + memset(&statbuf, 0, sizeof(statbuf)); + } + else + { + if (0 > (fd = open(infile, O_RDONLY))) + { + perror(infile); + fprintf(stderr, "Error opening input file: %s\n", infile); + return(-1); + } + if (0 > fstat(fd, &statbuf)) + { + perror(infile); + fprintf(stderr, "Error stat()'ing input file: %s\n", infile); + close(fd); + return(-1); + } + } + + if (keep == 0 || infile == NULL) + { + statbuf.st_atime = statbuf.st_ctime = statbuf.st_mtime = time(NULL); + umask(cur_umask = umask(0)); /* get the current umask */ + if (def_stat != NULL) + { + statbuf.st_mode = S_IFREG | + ((def_stat->st_mode == 0) ? (0666 & ~cur_umask):def_stat->st_mode); + statbuf.st_uid = def_stat->st_uid; + statbuf.st_gid = def_stat->st_gid; + } + else + { + statbuf.st_mode = S_IFREG | (0666 & ~cur_umask); + statbuf.st_uid = getuid(); + statbuf.st_gid = getgid(); + } + } + + if ((retval = ext2fs_namei(fs, cwd, cwd, outfile, &newfile))) + { + if (retval != EXT2_ET_FILE_NOT_FOUND) + { + fprintf(stderr, "%s\n",error_message(retval)); + close(fd); + return(retval); + } + + } + /* file name exists, let's see if is a directory */ + else if ((retval = ext2fs_check_directory(fs, newfile))) + { + if (retval != EXT2_ET_NO_DIRECTORY || + (retval = rm_file(fs, cwd, outfile, newfile))) + { + fprintf(stderr, "%s\n",error_message(retval)); + close(fd); + return(retval); + } + } + else + { + /* if we get here, then it's an existing directory */ + fprintf(stderr, "%s is a directory!\n", outfile); + return(1); + } + + /* ok, create a new inode and directory entry */ + if ((retval = ext2fs_new_inode(fs, cwd, 010755, 0, &newfile))) + { + fprintf(stderr, "%s\n", error_message(retval)); + close(fd); + return retval; + } + + if ((retval = ext2fs_link(fs, cwd, outfile, newfile, EXT2_FT_REG_FILE))) + { + /* check to see if we ran out of space in the directory */ + if (retval == EXT2_ET_DIR_NO_SPACE) + { + /* try resizing the directory and try again */ + if (0 == (retval = ext2fs_expand_dir(fs, cwd))) + retval = ext2fs_link(fs, cwd, outfile, newfile, + EXT2_FT_REG_FILE); + } + if (retval) + { + fprintf(stderr, "%s\n", error_message(retval)); + close(fd); + return retval; + } + } + ext2fs_inode_alloc_stats(fs, newfile, +1); + memset(&inode, 0, sizeof(inode)); + inode.i_mode = host_mode_xlate(statbuf.st_mode); + inode.i_atime = statbuf.st_atime; + inode.i_ctime = statbuf.st_ctime; + inode.i_mtime = statbuf.st_mtime; + inode.i_links_count = 1; + inode.i_size = statbuf.st_size; + inode.i_uid = statbuf.st_uid; + inode.i_gid = statbuf.st_gid; + + if ((retval = write_inode(fs, newfile, &inode))) + { + close(fd); + return (retval); + } + + if (LINUX_S_ISREG(inode.i_mode) && + (retval = store_data(fs, fd, newfile, &statbuf.st_size))) + { + close(fd); +#ifndef DEBUG + rm_file(fs, cwd, outfile, newfile); + +#endif + return(retval); + } + + close(fd); + + /* if we were reading from standard input, figure out the size of + * the file and save it. + */ + + if (infile == NULL) + { + if ((retval = read_inode(fs, newfile, &inode))) + return(retval); + + inode.i_size = statbuf.st_size; + + if ((retval = write_inode(fs, newfile, &inode))) + return(retval); + } + + /* save the files inode number for later use */ + if (outfile_ino != NULL) + *outfile_ino = newfile; + + return(ext2fs_flush(fs)); + +} /* end of put_file */ + +/* Name: store_data() + * + * Description: + * + * This function stores the contents of a file descriptor into the current ext2 + * file system + * + * Algorithm: + * + * Open a new file in the ext2 file system + * While data can be read from the input file descriptor + * Write the data to the file on the ext2 filesystem + * Close the file + * + * Global Variables: + * + * None + * + * Arguments: + * + * ext2_filsys fs; The current file system + * int fd; Input file descriptor + * ext2_ino_t newfile; Inode number of the new file + * off_t *file_size; The size of the file written + * + * Return Values: + * + * 0 - file copied successfully + * otherwise the error code of what went wrong + * + * Author: Keith W. Sheffield + * Date: 02/18/2002 + * + * Modification History: + * + * MM/DD/YY Name Description + * 06/26/02 K.Sheffield Added a call to update_progress() + */ +static long +store_data(ext2_filsys fs, int fd, ext2_ino_t newfile, off_t *file_size) +{ + ext2_file_t outfile; + long retval; + int bytes_read; + unsigned int bytes_written; + char buf[8192]; + char *ptr; + off_t total = 0; + + if ((retval = ext2fs_file_open(fs, newfile, EXT2_FILE_WRITE, &outfile))) + { + fprintf(stderr, "%s\n", error_message(retval)); + ext2fs_file_close(outfile); + *file_size = 0; + return retval; + } + + while (0 < (bytes_read = read(fd, buf, sizeof(buf)))) + { + ptr = buf; + while (bytes_read > 0) + { + if ((retval = ext2fs_file_write(outfile, ptr, bytes_read, + &bytes_written))) + { + fprintf(stderr, "%s\n", error_message(retval)); + ext2fs_file_close(outfile); + *file_size = total; + return retval; + } + bytes_read -= bytes_written; + total += bytes_written; + ptr += bytes_written; + } + update_progress((unsigned long) total); + } + + if (bytes_read < 0) + { + perror("store_data"); + retval = errno; + } + else + retval = 0; + + finish_progress(); + + ext2fs_file_close(outfile); + *file_size = total; + return retval; + +} /* end of store_data */ + |