pax_global_header00006660000000000000000000000064146716655130014530gustar00rootroot0000000000000052 comment=46da6c398e70635a296245851fcedbc56c35e824 e2tools-0.1.2/000077500000000000000000000000001467166551300131175ustar00rootroot00000000000000e2tools-0.1.2/.github/000077500000000000000000000000001467166551300144575ustar00rootroot00000000000000e2tools-0.1.2/.github/workflows/000077500000000000000000000000001467166551300165145ustar00rootroot00000000000000e2tools-0.1.2/.github/workflows/main.yml000066400000000000000000000054401467166551300201660ustar00rootroot00000000000000name: 'CI build' # Exclude some non-existing example branch on: push: branches-ignore: - html-docs pull_request: branches-ignore: - html-docs env: LC_ALL: C COMMON_CONFIGURE_FLAGS: >- --disable-silent-rules jobs: amb: runs-on: ${{ matrix.os }} name: 'amb ${{ matrix.os }}' strategy: fail-fast: true matrix: os: - ubuntu-latest - macos-latest steps: - uses: actions/checkout@v4 - name: 'Determine number of cores to build on (Linux)' if: runner.os == 'Linux' run: echo NPROC=$(nproc) >> $GITHUB_ENV - name: 'Determine number of cores to build on (macOS)' if: runner.os == 'macOS' run: echo NPROC=$(sysctl -n hw.logicalcpu) >> $GITHUB_ENV # Setting MAKE interferes with Makefile{,.in,.am} using $(MAKE) internally - name: 'Prepare concurrent make' run: if test "x$NPROC" = x; then echo ci_MAKE="make" >> $GITHUB_ENV; echo "NPROC must be set"; exit 1; else echo ci_MAKE="make -j${NPROC} -l${NPROC}" >> $GITHUB_ENV; fi - name: 'Update software database (Linux)' if: runner.os == 'Linux' run: sudo apt-get update - name: 'Update software database (macOS)' if: runner.os == 'macOS' run: brew update - name: 'Install build requirements (Linux)' if: runner.os == 'Linux' run: sudo apt-get install -y libext2fs-dev pkgconf - name: 'Install build requirements (macOS)' if: runner.os == 'macOS' run: | brew install autoconf automake pkg-config e2fsprogs echo PKG_CONFIG_PATH="/opt/homebrew/opt/e2fsprogs/lib/pkgconfig" >> $GITHUB_ENV # - name: 'OS specific build flags (Linux)' # if: runner.os == 'Linux' # run: echo OS_SPECIFIC_CPPFLAGS="" >> $GITHUB_ENV # # FIXME: Fix source to build without the -D_DARWIN_C_SOURCE here # - name: 'OS specific build flags (macOS)' # if: runner.os == 'macOS' # run: echo OS_SPECIFIC_CPPFLAGS="-D_DARWIN_C_SOURCE -I$(brew --prefix)/include" >> $GITHUB_ENV - name: 'autoreconf' run: autoreconf -v -i -f - name: 'configure' run: ./configure ${COMMON_CONFIGURE_FLAGS} --prefix=$PWD/__prefix - name: 'make' run: set -x; ${ci_MAKE} CPPFLAGS="${OS_SPECIFIC_CPPFLAGS}" - name: 'make check' run: set -x; ${ci_MAKE} CPPFLAGS="${OS_SPECIFIC_CPPFLAGS}" check - name: 'make distcheck' run: set -x; ${ci_MAKE} CPPFLAGS="${OS_SPECIFIC_CPPFLAGS}" DISTCHECK_CONFIGURE_FLAGS="${COMMON_CONFIGURE_FLAGS}" distcheck - name: 'make install' run: set -x; ${ci_MAKE} CPPFLAGS="${OS_SPECIFIC_CPPFLAGS}" install - name: 'make installcheck' run: set -x; ${ci_MAKE} CPPFLAGS="${OS_SPECIFIC_CPPFLAGS}" installcheck e2tools-0.1.2/.gitignore000066400000000000000000000010431467166551300151050ustar00rootroot00000000000000# Ignore these in any subdirectory *~ *.i *.o *.s Makefile Makefile.in .deps/ # Ignore these relative to the top directory /aclocal.m4 /autom4te.cache/ /build-aux/compile /build-aux/config.guess /build-aux/config.sub /build-aux/depcomp /build-aux/install-sh /build-aux/missing /build-aux/test-driver /config.h /config.h.in /e2tools-autoconfig.h /e2tools-autoconfig.h.in /config.log /config.status /configure /e2tools /INSTALL /lib/Makefile.in /lib/arg-nonnull.h /lib/c++defs.h /lib/inttypes.h /lib/warn-on-use.h /lib/libgnu.a /lib/sys/ /stamp-h1 e2tools-0.1.2/AUTHORS000066400000000000000000000004211467166551300141640ustar00rootroot00000000000000Keith W Sheffield Hans Ulrich Niedermann Eugene Rudoy Christoph Gysin Collin Mulliner Artur Juraszek Khem Raj e2tools-0.1.2/COPYING000066400000000000000000000432541467166551300141620ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 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 Lesser General Public License instead of this License. e2tools-0.1.2/ChangeLog000066400000000000000000000124631467166551300146770ustar00rootroot000000000000002004-04-06 Keith W. Sheffield * 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 * 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 * configure.in: initial version * Makefile.am: initial version 2002-08-08 Keith W. Sheffield * 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 * 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 * ln.c (create_hard_link): Testing file type before linking to directory. 2002-06-26 Keith W. Sheffield * 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 * 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 * 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 * 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 * copy.c (find_link): Fixed the list ordered search bug. 2002-05-06 Keith W. Sheffield * 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 * 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 * 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 * 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 * ln.c (do_ln): separated the ln/mv operations into two separate functions. b 2002-03-07 Keith W. Sheffield * 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 * 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 * 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 * 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 * 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. e2tools-0.1.2/DEVELOPMENT.md000066400000000000000000000036571467166551300152360ustar00rootroot00000000000000e2tools development notes ========================= This file contains a few notes for developers contributing to `e2tools`. Source code standards ===================== To be determined for e2tools: * C language standard * C standard library requirements * C sourcecode formatting rules Release checklist ================= This checklist outlines some basics for tagging a release on Github. Update the list when you run into and solved issues, such as how to properly release "make dist" generated tarballs using Github. * Is the `AUTHORS` file up to date? * Does the `NEWS.md` summarize all user visible changes? * Does `configure.ac` `AC_INIT` contain the correct version number? * Does the first line of `NEWS.md` contain the correct version number? * Does `make clean && make check` run? * Does `make distcheck` run? * Do the `git commit` and `git push` to the master branch on github. * Wait for Travis CI to finish building successfully. If the build fails, investigate and fix the problem. * Enjoy the [github releases web interface](https://github.com/e2tools/e2tools/releases): * Tag `e2tools` release `1.2.3` as `v1.2.3` beginning with the `v`. * Summarize the changes since the last release in the release notes, formatting it properly using Github flavoured Markdown. `NEWS.md` will come in handy here. * Upload the release tarball generated by `make distcheck` by attaching it to the Github release in the web interface. If that upload fails, make sure NoScript is not blocking some special Github release specific Javascript code. * Update the https://e2tools.github.io/ web page to point to the new Github release. * If necessary, adapt this release checklist and commit the updated `DEVELOPMENT.md` file. * Add a new heading to `NEWS.md` with the next release like `e2tools-1.2.x`, then `git commit` and `git push`. e2tools-0.1.2/INSTALL.from-git000066400000000000000000000003451467166551300156750ustar00rootroot00000000000000To compile from e2tools' git repository, you need to run these steps: $ git clone https://github.com/e2tools/e2tools.git $ cd e2tools $ autoreconf -vis . Now you can compile as if you had just extracted a source tarball. e2tools-0.1.2/Makefile.am000066400000000000000000000060151467166551300151550ustar00rootroot00000000000000######################################################################## # autotools control definitions ######################################################################## ACLOCAL_AMFLAGS = -I m4 -I e2t-m4 ######################################################################## # e2tools variables to append to ######################################################################## # hook targets all_targets = clean_targets = install_targets = uninstall_targets = phony_targets = # list of e2tools like e2ls and e2cp etc e2tools_list = # list of -e 's|||g' arguments to sed for preprocessing *.in files sed_in_commands = ######################################################################## # Automake variables to append to ######################################################################## BUILT_SOURCES = CLEANFILES = EXTRA_DIST = SUFFIXES = TESTS = bin_PROGRAMS = dist_man_MANS = man_MANS = ######################################################################## # Documentation files ######################################################################## EXTRA_DIST += DEVELOPMENT.md EXTRA_DIST += NEWS.md EXTRA_DIST += README.md EXTRA_DIST += TODO ######################################################################## # include files ######################################################################## include src/include.am include tests/include.am ######################################################################## # .in replacement rules ######################################################################## HASHMARK = \# if HAVE_EXT2FS_XATTRS sed_in_commands += -e 's|[@]HAVE_EXT2FS_XATTRS_MAN_FALSE@||g' sed_in_commands += -e 's|[@]HAVE_EXT2FS_XATTRS_MAN_TRUE@|.\\" |g' sed_in_commands += -e 's|[@]HAVE_EXT2FS_XATTRS_FALSE@||g' sed_in_commands += -e 's|[@]HAVE_EXT2FS_XATTRS_TRUE@|$(HASHMARK) |g' else sed_in_commands += -e 's|[@]HAVE_EXT2FS_XATTRS_MAN_FALSE@|.\\" |g' sed_in_commands += -e 's|[@]HAVE_EXT2FS_XATTRS_MAN_TRUE@||g' sed_in_commands += -e 's|[@]HAVE_EXT2FS_XATTRS_FALSE@|$(HASHMARK) |g' sed_in_commands += -e 's|[@]HAVE_EXT2FS_XATTRS_TRUE@||g' endif sed_in_commands += -e 's|[@]top_builddir@|$(top_builddir)|g' sed_in_commands += -e 's|[@]top_srcdir@|$(top_srcdir)|g' sed_in_commands += -e 's|[@]DD@|$(DD)|g' sed_in_commands += -e 's|[@]MKE2FS@|$(MKE2FS)|g' SUFFIXES += .1.in .1 .1.in.1: $(MKDIR_P) $(@D) $(SED) $(sed_in_commands) < $< > $@ SUFFIXES += .sh.in .sh .sh.in.sh: $(MKDIR_P) $(@D) $(SED) $(sed_in_commands) < $< > $@ $(CHMOD) +x $@ ######################################################################## # local hooks we have collected targets in variables for ######################################################################## .PHONY: $(phony_targets) all-local: $(all_targets) install-exec-hook: $(install_targets) uninstall-hook: $(uninstall_targets) clean-local: $(clean_targets) -rm -f *.i *.s ######################################################################## # End of Makefile.am ######################################################################## e2tools-0.1.2/NEWS.md000066400000000000000000000071321467166551300142200ustar00rootroot00000000000000e2tools-0.1.2 (2024-09-16) ========================== * Make the build compatible with Automake 1.17's warning about hash characters in Makefile.am files. * Require at least C99 with stdint.h etc. * Documentation updates. e2tools-0.1.0 (2020-02-07) ========================== * With Keith Sheffield's e2tools home page having disappeared, Christoph Gysin has invited Hans Ulrich Niedermann to join the efforts maintaining e2tools at https://github.com/e2tools/e2tools and make https://e2tools.github.io/ the new homepage (in early 2020). * Merges the diverged Rudoy/Gysin and Niedermann branches. * `e2tail` now accepts the no-op `-v` option. * Enlarged another buffer to make sure the data fits. * Fix a few signed/unsigned integer comparisons in `e2tail` (found via compiler warnings). * Add SELinux support for `e2ls -Z`, which is built only if libext2fs actually contains the functions of the xattrs API. * Moved all e2tool documentation from the `README.md` including the tool examples to the respective man pages. * Added a first simple test script to run during `make check` checking the e2tools actually work. * `make dist` only generates gzip compressed `*.tar.gz` tarballs. * `e2ls` now aborts and exits with an error when it encounters an unrecognized commandline option. e2tools-0.0.16.4 (early 2019, Niedermann branch only) ===================================================== * Fix compiler warnings on undefined functions and unused variables. * Fix one buffer size issue found by compiler warning. e2tools without named releases (mid 2015, Rudoy/Gysin branch only) ================================================================== * Eugene Rudoy and Christoph Gysin clean up the code for use in Debian and other distributions. * Add e2tools executable to which all tools symlink (it used to be the e2cp executable which all other tools symlinked). * Pretty-print file mode in `e2ls` (`-rw-r--r--` and such). * Add `e2ls` option `-n` to show owner and group in numeric form. * `e2tail` stops accepting the no-op `-v` option. e2tools-0.0.16.3 (late 2007) ============================ * Hans Ulrich Niedermann's late 2007 build and compatibility cleanup efforts from https://github.com/ndim/e2tools mostly to help preparing the Fedora e2tools package. * Fix a few signed/unsigned integer comparisons (compiler warning). * Avoid assignment within expression (compiler warning). * This is basically the fork point where the Rudoy/Gysin branch on one side (2015) and the Niedermann branch (2019) on the other side started diverging. e2tools-0.0.16 and earlier (the Keith Sheffield era) ==================================================== * e2tools-0.0.16.tar.gz is the last tarball release from Keith Sheffield. The e2tools capabilities have not changed significantly between that release and 2020. * 2004-04-06 is Keith Sheffield's last ChangeLog entry. * A e2tools-0.0.16.tar.gz link is on the e2tools page (wayback machine capture date 2004-06-09, "Last modified" 2004-04-06). * A e2tools-0.0.15.tar.gz link is on the e2tools page (wayback machine capture date 2004-02-05, "Last modified" 2003-07-12). * e2tools-0.0.13.tar.gz is the first release to be found on [Keith Sheffield's e2tools page](http://home.earthlink.net/~k_sheff/sw/e2tools/) using the [wayback machine](https://web.archive.org/) capture from 2003-02-13. The "Last modified" suggests that it has been released at 2002-08-08 or earlier, but the 2003-02-13 capture date at the very latest. e2tools-0.1.2/README.md000066400000000000000000000067461467166551300144130ustar00rootroot00000000000000About e2tools ============= [![master branch build status](https://api.travis-ci.org/e2tools/e2tools.svg?branch=master)](https://travis-ci.org/e2tools/e2tools) 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) For questions, suggestions, or remarks please open an issue at https://github.com/e2tools/e2tools/issues For patches, please create a pull request at https://github.com/e2tools/e2tools/pulls or open an issue with a patch attached. 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` A few quick ideas: # create 16MB image file dd if=/dev/null of=test.img bs=1 count=1 seek=16M # create filesystem inside image file mkfs.ext2 -F test.img # create directory foo in root directory of filesystem image e2mkdir test.img:/foo # look into root directory of filesystem image e2ls -l test.img: # copy README.md into foo dir e2cp README.md test.img:/foo # look what is inside the foo dir e2ls -l test.img:/foo # remove file again e2rm test.img:/foo/README.md Alternatives ============ There is more than one way to access an ext2 filesystem. We list a few here with a few remarks on each: * Linux kernel ext2 driver. Requires loopback (for image files) and mounting privileges. Also requires the filesystem block size to not be larger than the kernel PAGE_SIZE. * fuse2fs FUSE userspace ext2 driver from e2fsprogs. Requires mounting privileges. e2fsprogs handles any filesystem block size independent of the kernel PAGE_SIZE. * e2tools. Uses the same codebase from e2fsprogs, and thus handles any filesystem block size independent of the kernel PAGE_SIZE. Does not require mounting privileges. Distribution packages ===================== Packaging status The [repology.org e2tools page](https://repology.org/project/e2tools/packages) contains information on many distributions' `e2tools` packages including the releases they are packaging. e2tools-0.1.2/TODO000066400000000000000000000002741467166551300136120ustar00rootroot00000000000000Create 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 e2tools-0.1.2/configure.ac000066400000000000000000000142351467166551300154120ustar00rootroot00000000000000dnl ==================================================================== dnl Process this file with autoconf to produce a configure script. dnl ==================================================================== dnl dnl Relevant build tool versions: dnl dnl 2003-11-06 autoconf 2.59 Original e2tools requirement dnl 2009-07-26 autoconf 2.64 About the time of automake 1.11 dnl 2012-04-24 autoconf 2.69 Latest release for a loooong time dnl dnl 2005-07-10 automake 1.9.6 Original e2tools requirement dnl 2009-05-17 automake 1.11 Adds AM_SILENT_RULES and silent-rules dnl 2024-07-11 automake 1.17 Requires -Wno-portability for # in make vars dnl dnl ==================================================================== AC_PREREQ(2.59) AC_INIT([e2tools], [0.1.2], [https://github.com/e2tools/e2tools/issues], [e2tools], [https://e2tools.github.io/]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADER([e2tools-autoconfig.h]) AC_CONFIG_SRCDIR([src/e2tools.c]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([ -Wall -Werror -Wno-portability 1.9.6 foreign subdir-objects ]) dnl ==================================================================== dnl Checks for programs. dnl ==================================================================== AC_PROG_CC_C99 AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_SED AC_PROG_MAKE_SET AC_ARG_VAR([CHMOD], [chmod command]) AS_VAR_IF([CHMOD], [], [dnl AC_PATH_PROG([CHMOD], [chmod]) ]) AC_MSG_CHECKING([CHMOD value to be used]) AC_MSG_RESULT([$CHMOD]) AC_ARG_VAR([DD], [dd command]) AS_VAR_IF([DD], [], [dnl AC_PATH_PROG([DD], [dd]) ]) AC_MSG_CHECKING([DD value to be used]) AC_MSG_RESULT([$DD]) AM_CONDITIONAL([HAVE_DD_COMMAND], [test "x$DD" != "x" && test "x$DD" != "xno"]) AC_ARG_VAR([MKE2FS], [mke2fs or mkfs.ext2 command]) AS_VAR_IF([MKE2FS], [], [dnl AC_PATH_PROG([MKE2FS], [mke2fs mkfs.ext2]) ]) AC_MSG_CHECKING([MKE2FS value to be used]) AC_MSG_RESULT([$MKE2FS]) AM_CONDITIONAL([HAVE_MKE2FS_COMMAND], [test "x$MKE2FS" != "x" && test "x$MKE2FS" != "xno"]) dnl ==================================================================== dnl Checks for compiler flags dnl ==================================================================== dnl Add compiler flags to CFLAGS, but only if they are actually dnl supported by the GCC compatible compiler (probably gcc or clang). dnl If the user does not want these flags to be used, they can run dnl make with a CFLAGS= parameter. m4_pattern_forbid([E2T_CONDITIONAL_CFLAGS])dnl dnl AS_VAR_IF([GCC], [yes], [dnl E2T_CONDITIONAL_CFLAGS([--std=gnu99]) E2T_CONDITIONAL_CFLAGS([-pedantic]) E2T_CONDITIONAL_CFLAGS([-Wall]) E2T_CONDITIONAL_CFLAGS([-Wextra]) E2T_CONDITIONAL_CFLAGS([-Wmost]) dnl E2T_CONDITIONAL_CFLAGS([-Werror]) E2T_CONDITIONAL_CFLAGS([-Wp,-D_FORTIFY_SOURCE=2]) E2T_CONDITIONAL_CFLAGS([-fstack-clash-protection]) E2T_CONDITIONAL_CFLAGS([-fcf-protection]) ]) dnl ==================================================================== dnl Checks for libraries. dnl E2T_PKG_CHECK_MODULES has the advantage over PKG_CHECK_MODULES dnl that it also thecks the modversion and AC_MSG_RESULTs it for dnl help with debugging issues with different library versions. dnl ==================================================================== m4_pattern_forbid([E2T_PKG_CHECK_MODULES])dnl dnl E2T_PKG_CHECK_MODULES([EXT2FS], [ext2fs >= 1.27], [], [dnl AC_MSG_ERROR([AC_PACKAGE_NAME requires libext2fs (part of e2fsprogs).])]) E2T_PKG_CHECK_MODULES([COM_ERR], [com_err], [], [dnl AC_MSG_ERROR([AC_PACKAGE_NAME requires libcom_err (part of e2fsprogs).])]) dnl ==================================================================== dnl Checks for header files. dnl ==================================================================== AC_HEADER_STDC AC_CHECK_HEADERS([errno.h fcntl.h sys/time.h unistd.h]) dnl ==================================================================== dnl Checks for typedefs, structures, and compiler characteristics. dnl ==================================================================== AC_C_CONST AC_TYPE_MODE_T AC_TYPE_OFF_T AC_HEADER_TIME AC_STRUCT_TM dnl ==================================================================== dnl Checks for library functions. dnl ==================================================================== AC_FUNC_ALLOCA AC_FUNC_UTIME_NULL AC_CHECK_FUNCS([gettimeofday regcomp strdup strtol]) dnl ==================================================================== dnl Check whether libext2fs implements ext2fs_xattrs_read() function dnl ==================================================================== orig_CFLAGS="$CFLAGS" orig_LIBS="$LIBS" CFLAGS="$CFLAGS $EXT2FS_CFLAGS" LIBS="$LIBS $EXT2FS_LIBS" AC_CHECK_LIB([ext2fs], [ext2fs_xattrs_read], [have_ext2fs_xattrs=yes], [have_ext2fs_xattrs=no]) CFLAGS="$orig_CFLAGS" LIBS="$orig_LIBS" AM_CONDITIONAL([HAVE_EXT2FS_XATTRS], [test "x$have_ext2fs_xattrs" = "xyes"]) AM_COND_IF([HAVE_EXT2FS_XATTRS], [dnl AC_DEFINE([HAVE_EXT2FS_XATTRS], [1], [Defined if libext2fs implements ext2fs_xattrs_read]) ]) dnl ==================================================================== dnl Check whether we can compile a function with __attribute__((naked)) dnl ==================================================================== AC_MSG_CHECKING([whether __attribute__((naked)) is available]) orig_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Wall -Wextra -pedantic -Werror" AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ static void test_function(void) __attribute__(( naked )) __attribute__(( used )); static void test_function(void) { switch (0) { case 0: break; } } ]])], [dnl AC_MSG_RESULT([yes]) AC_DEFINE([FUNCTION_ATTRIBUTE_NAKED_IF_POSSIBLE], [__attribute__((naked))], [defined properly when compiling with naked attribute works]) ], [dnl AC_MSG_RESULT([no]) AC_DEFINE([FUNCTION_ATTRIBUTE_NAKED_IF_POSSIBLE], [], [defined empty when compiling with naked attribute fails]) ]) CFLAGS="$orig_CFLAGS" dnl ==================================================================== dnl The end of configure.ac is approaching fast. dnl ==================================================================== AC_CONFIG_FILES([Makefile]) AC_OUTPUT e2tools-0.1.2/e2t-m4/000077500000000000000000000000001467166551300141275ustar00rootroot00000000000000e2tools-0.1.2/e2t-m4/e2t-conditional-cflags.m4000066400000000000000000000014221467166551300206200ustar00rootroot00000000000000dnl Add compiler flags to CFLAGS if and only if they are supported dnl by the compiler. What is done with the augmented CFLAGS variable dnl is up to the caller. dnl dnl Example: dnl E2T_CONDITIONAL_CFLAGS([-Wall]) dnl E2T_CONDITIONAL_CFLAGS([-Wextra]) dnl E2T_CONDITIONAL_CFLAGS([-Werror]) dnl E2T_CONDITIONAL_CFLAGS([-fno-common]) dnl AC_DEFUN([E2T_CONDITIONAL_CFLAGS], [dnl orig_CFLAGS="$CFLAGS" CFLAGS="$orig_CFLAGS -Werror $1" AC_MSG_CHECKING([whether to add $1 to CFLAGS]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char x[16];]])], [dnl AC_MSG_RESULT([yes]) CFLAGS="$orig_CFLAGS $1" ], [dnl AC_MSG_RESULT([no]) CFLAGS="$orig_CFLAGS" ])dnl ])dnl dnl dnl dnl ==================================================================== dnl dnl Local Variables: dnl mode: autoconf dnl End: e2tools-0.1.2/e2t-m4/e2t-pkg-check-modules.m4000066400000000000000000000012371467166551300203660ustar00rootroot00000000000000dnl Like PKG_CHECK_MODULES, but AC_MSG_RESULTs the pkg-config modversion. dnl dnl Example: dnl E2T_PKG_CHECK_MODULES([EXT2FS], [ext2fs >= 1.27], [], [dnl dnl AC_MSG_ERROR([Sorry, but libext2fs (part of e2fsprogs) is required.]) dnl ]) dnl m4_pattern_forbid([PKG_CHECK_MODULES])dnl dnl AC_DEFUN([E2T_PKG_CHECK_MODULES], [dnl PKG_CHECK_MODULES([$1], [$2], [$3], [$4]) $1_MODVERSION=`${PKG_CONFIG} --modversion "$2" 2>/dev/null` AC_SUBST([$1_MODVERSION]) AC_MSG_CHECKING([the $1 modversion]) AC_MSG_RESULT([[$]$1_MODVERSION]) ])dnl dnl dnl dnl ==================================================================== dnl dnl Local Variables: dnl mode: autoconf dnl End: e2tools-0.1.2/m4/000077500000000000000000000000001467166551300134375ustar00rootroot00000000000000e2tools-0.1.2/m4/.gitignore000066400000000000000000000001111467166551300154200ustar00rootroot00000000000000# just an empty .gitignore file to make sure git generates the directory e2tools-0.1.2/src/000077500000000000000000000000001467166551300137065ustar00rootroot00000000000000e2tools-0.1.2/src/compiler-definitions.h000066400000000000000000000047641467166551300202150ustar00rootroot00000000000000#ifndef E2TOOLS_COMPILER_DEFINITIONS_H #define E2TOOLS_COMPILER_DEFINITIONS_H #include "e2tools-autoconfig.h" /** Size of struct member * * Cf. http://stackoverflow.com/a/2129531/182675 */ #define SIZEOF_MEMBER(structname, membername) \ sizeof(((structname *)NULL)->membername) /** Compile time assertion, to be used within a function */ #define COMPILE_TIME_ASSERT(CONDITION) \ switch (0) { \ case 0: \ case (CONDITION): \ break; \ } /** Helper for BARE_COMPILE_TIME_ASSERT() macro * * This is ugly C preprocessor macro hacking to get the value of the * macro __LINE__ to be used in the function name. You need not * understand how this works - just accept that it does. */ #define MAKE_BARE_COMPILE_TIME_ASSERT_NAME \ MAKE_BARE_COMPILE_TIME_ASSERT_NAME1(COMPILE_TIME_ASSERT_fails_in_line, __LINE__) /** Helper for BARE_COMPILE_TIME_ASSERT() macro * * This is ugly C preprocessor macro hacking to get the value of the * macro __LINE__ to be used in the function name. You need not * understand how this works - just accept that it does. */ #define MAKE_BARE_COMPILE_TIME_ASSERT_NAME1(BASE, PARAM) \ MAKE_BARE_COMPILE_TIME_ASSERT_NAME2(BASE, PARAM) /** Helper for BARE_COMPILE_TIME_ASSERT() macro * * This is ugly C preprocessor macro hacking to get the value of the * macro __LINE__ to be used in the function name. You need not * understand how this works - just accept that it does. */ #define MAKE_BARE_COMPILE_TIME_ASSERT_NAME2(BASE, PARAM) \ BASE ## _ ## PARAM /** Compile time assertion, to be used outside a function * * The generated function is generated "naked", so that it does not * actually produce any code in the output. Thus the compile time * assertion does not end up producing any actual code. The * impacto on the object file and the binary should be mainly an * entry in the symbol table which is acceptable. */ #define BARE_COMPILE_TIME_ASSERT(CONDITION) \ static \ void MAKE_BARE_COMPILE_TIME_ASSERT_NAME(void) \ FUNCTION_ATTRIBUTE_NAKED_IF_POSSIBLE \ __attribute__(( used )); \ static \ void MAKE_BARE_COMPILE_TIME_ASSERT_NAME(void) \ { \ COMPILE_TIME_ASSERT(CONDITION); \ } #endif /* !defined(E2TOOLS_COMPILER_DEFINITIONS_H) */ e2tools-0.1.2/src/e2cp.1000066400000000000000000000047041467166551300146260ustar00rootroot00000000000000.TH E2CP 1 "2020\-02\-05" "Linux" "User commands" .\" .SH NAME e2cp \- copies files from/to an e2fs filesystem .\" .SH SYNOPSIS .B e2cp .RI [ options ] " files... dest" .\" .SH DESCRIPTION The \fBe2cp\fP command copies files to/from an e2fs filesystem from/to the machine's filesystem. .\" .SH OPTIONS A single `-' (dash) can be used instead of a file name to indicate standard input/output. .TP .B \-0 Input lines terminated by a null character. .TP .B \-a Absolute directory names \- create directories instead of just copying into the destination. Only valid for copying into an ext2fs filesystem. .TP .B \-d \fIdest_dir\fP Destination of files to be copied. May be in the ext2fs filesystem or the host filesystem. .TP .B \-G \fIgid\fP Set the default group to gid. .TP .B \-O \fIuid\fP Set the default file owner to uid. .TP .B \-p Preserve host file attributes (permissions, times, etc.) when copying files. .TP .B \-P \fImode\fP Set the file permissions (ie 755, 666). .TP .B \-s \fIsrc_dir\fP The source of the files to be copied. .TP .B \-v Be verbose. .\" .SH EXAMPLES .PP Copy a file and use the default permission and ownership of the current user: e2cp README.txt /tmp/boot.img:/tmp .\" .PP Do the same thing, but keep permissions & ownership: e2cp \-p README.txt /tmp/boot.img:/tmp .\" .PP Dump a file to standard out: e2cp /tmp/boot.img:/tmp/README.txt \- | wc .\" .PP 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 .\" .PP 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 .\" .PP 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 .\" .PP 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 .\" .\" .SH SEE ALSO .BR e2tools (7), .BR e2ln (1), .BR e2ls (1), .BR e2mkdir (1), .BR e2mv (1), .BR e2rm (1), .BR e2tail (1). .\" .SH AUTHOR The \fBe2tools\fP were written by Keith Sheffield . .PP This manual page was written by Lucas Wall , for the Debian project (but may be used by others). e2tools-0.1.2/src/e2ln.1000066400000000000000000000017221467166551300146320ustar00rootroot00000000000000.TH E2LN 1 "2020\-02\-05" "Linux" "User commands" .\" .SH NAME e2ln \- create hard links on an ext2 filesystem .\" .SH SYNOPSIS .B e2ln .RI [ options ] " source destination" .\" .SH DESCRIPTION The \fBe2ln\fP command is used to create hard links on an ext2 filesystem. .\" .SH OPTIONS .TP .B \-f Force the operation to remove any existing files. .TP .B \-s Create a symlink. .TP .B \-v Be verbose. .PP Note: creating symlinks is not operational at this time. .\" .SH EXAMPLES .PP 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 .\" .SH SEE ALSO .BR e2tools (7), .BR e2mv (1), .BR e2ls (1), .BR e2mkdir (1), .BR e2cp (1), .BR e2rm (1), .BR e2tail (1). .\" .SH AUTHOR The \fBe2tools\fP were written by Keith Sheffield . .PP This manual page was written by Lucas Wall , for the Debian project (but may be used by others). e2tools-0.1.2/src/e2ls.1.in000066400000000000000000000026451467166551300152510ustar00rootroot00000000000000.\" -*- nroff -*- .TH E2LS 1 "2020\-02\-05" "Linux" "User commands" .\" .SH NAME e2ls \- list files and directories on an ext2 filesystem .\" .SH SYNOPSIS .B e2ls .RI [ options ] " file_specification" .\" .SH DESCRIPTION The \fBe2ls\fP command is used to list files and directories on an ext2 filesystem. .SS Note Files deleted via \fBe2rm(1)\fR sometimes will show up even without the \fB\-D\fR option. It is being investigated. .\" .SH OPTIONS .TP .B \-a Show hidden directories. .TP .B \-c Sort by creation time (must include -t when using -l). .TP .B \-d \fIdir\fP Open the ext2 filesystem specified by dir. .TP .B \-D Show deleted files bracketed with ><. .TP .B \-f No sorting of the file list. .TP .B \-i Show the inodes (very useful for the -l option). .TP .B \-l Long listing. .TP .B \-n Like -l, but list numeric user and group IDs. .TP .B \-r Reverse the sort order. .TP .B \-t Sort by time. @HAVE_EXT2FS_XATTRS_MAN_FALSE@.TP @HAVE_EXT2FS_XATTRS_MAN_FALSE@.B \-Z @HAVE_EXT2FS_XATTRS_MAN_FALSE@List SELinux label from extended attributes. .\" .SH EXAMPLES e2ls \-a boot.img:. e2ls \-l /dev/hdb1:/data .\" .SH SEE ALSO .BR e2tools (7), .BR e2ln (1), .BR e2mv (1), .BR e2mkdir (1), .BR e2cp (1), .BR e2rm (1), .BR e2tail (1). .\" .SH AUTHOR The \fBe2tools\fP were written by Keith Sheffield . .PP This manual page was written by Lucas Wall , for the Debian project (but may be used by others). e2tools-0.1.2/src/e2mkdir.1000066400000000000000000000022321467166551300153240ustar00rootroot00000000000000.TH E2MKDIR 1 "2020\-02\-05" "Linux" "User commands" .\" .SH NAME e2mkdir \- creates a directory on an ext2 filesystem .\" .SH SYNOPSIS .B e2mkdir .RI [ options ] " directory..." .\" .SH DESCRIPTION The \fBe2mkdir\fP command creates directories on an ext2 filesystem. It behaves similar to `mkdir -p'. .\" .SH OPTIONS .TP .B \-G \fIgid\fP Set the default group to gid. .TP .B \-O \fIuid\fP Set the default file owner to uid. .TP .B \-P \fImode\fP Set the file permissions (ie 755, 666). .TP .B \-v Be verbose. .SS Note This program expects to have a full ext2 file specification for each argument. .\" .SH EXAMPLES .PP This creates the directory `/boot/grub` with on `boot.img` with the current user and group ids: e2mkdir boot.img:/boot/grub .PP To override the default ownership and permissions: e2mkdir \-O 100 \-P 700 /dev/hdb1:/data/backup .\" .SH SEE ALSO .BR e2tools (7), .BR e2ln (1), .BR e2ls (1), .BR e2mv (1), .BR e2cp (1), .BR e2rm (1), .BR e2tail (1). .\" .SH AUTHOR The \fBe2tools\fP were written by Keith Sheffield . .PP This manual page was written by Lucas Wall , for the Debian project (but may be used by others). e2tools-0.1.2/src/e2mv.1000066400000000000000000000030141467166551300146370ustar00rootroot00000000000000.TH E2MV 1 "2020\-02\-05" "Linux" "User commands" .\" .SH NAME e2mv \- moves or renames files on an ext2fs filesystem .\" .SH SYNOPSIS .B e2mv .RI [ options ] " files... dest" .\" .SH DESCRIPTION The \fBe2mv\fP command moves or renames files on an ext2fs filesystem. The source files must be explicitly stated. It does not use regular expressions, yet. .\" .SH OPTIONS .TP .B \-f Force the operation to remove any existing files. .TP .B \-s Swap names of the two files. .TP .B \-v Be verbose. .\" .SH EXAMPLES .PP Rename a file: e2cp \-v /tmp/boot.img:/boot/grub/grub.conf /boot/grub/grub.conf.old .\" .PP If `/boot/grub/grub.conf.old` already exists and is not a directory, this will fail. Use `\-f` to force removal. .PP Move a file to a different directory (`/data/processed`): e2cp \-v /dev/hdb1:/data/input0.txt /data/processed .\" .PP To swap the names of two files: e2cp \-vs /tmp/boot.img:/boot/grub/grub.conf /boot/grub/grub.conf.bk .\" .PP 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` and `/boot/grub/grub.c2` is now `/boot/grub/grub.conf` .\" .SH SEE ALSO .BR e2tools (7), .BR e2ln (1), .BR e2ls (1), .BR e2mkdir (1), .BR e2cp (1), .BR e2rm (1), .BR e2tail (1). .\" .SH AUTHOR The \fBe2tools\fP were written by Keith Sheffield . .PP This manual page was written by Lucas Wall , for the Debian project (but may be used by others). e2tools-0.1.2/src/e2rm.1000066400000000000000000000017021467166551300146350ustar00rootroot00000000000000.TH E2RM 1 "2020\-02\-05" "Linux" "User commands" .\" .SH NAME e2rm \- removes files and directories on an ext2 filesystem .\" .SH SYNOPSIS .B e2rm .RI [ options ] " files..." .\" .SH DESCRIPTION The \fBe2rm\fP command removes files and directories on an ext2 filesystem. .\" .SH OPTIONS .TP .B \-r Recursively delete files if a directory name is given. .TP .B \-v Be verbose. .SS Note This program expects to have a full ext2 file specification for each argument. .\" .SH EXAMPLES .PP Remove a file e2rm \-v boot.img:/boot/grub/grub.c1 /boot/grub/grub.c2 .PP Remove a directory and all the files e2rm \-r boot.img:/boot/grub .\" .SH SEE ALSO .BR e2tools (7), .BR e2ln (1), .BR e2ls (1), .BR e2mkdir (1), .BR e2cp (1), .BR e2mv (1), .BR e2tail (1). .\" .SH AUTHOR The \fBe2tools\fP were written by Keith Sheffield . .PP This manual page was written by Lucas Wall , for the Debian project (but may be used by others). e2tools-0.1.2/src/e2tail.1000066400000000000000000000026501467166551300151530ustar00rootroot00000000000000.TH E2TAIL 1 "2020\-02\-05" "Linux" "User commands" .\" .SH NAME e2tail \- a basic version of the tail command for an ext2 filesystem .\" .SH SYNOPSIS .B e2tail .RI [ options ] " file" .\" .SH DESCRIPTION The \fBe2tail(1)\fP command implements a basic version of the \fBtail(1)\fR command. .\" .SH OPTIONS .TP .B \-n \fInum_lines\fP The number of lines to display .TP .B \-f Output appended data as the file grows. This is inode dependent, so if the file is renamed, it will keep checking it. .TP .B \-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. .TP .B \-s \fIsleep_interval\fP The number of seconds to sleep before checking if the file has grown while in 'follow' mode. The default is 1. .\" .SH EXAMPLES .PP Check `/var/log/messages` on `/dev/sdc1` every 10 seconds e2tail \-s 10 \-F /dev/sdc1:/var/log/messages .\" .SH SEE ALSO .BR e2tools (7), .BR e2ln (1), .BR e2ls (1), .BR e2mkdir (1), .BR e2cp (1), .BR e2rm (1), .BR e2mv (1). .\" .SH AUTHOR The \fBe2tools\fP were written by Keith Sheffield . .PP This manual page was written by Lucas Wall , for the Debian project (but may be used by others). e2tools-0.1.2/src/e2tool-e2cp.c000066400000000000000000001026251467166551300161130ustar00rootroot00000000000000/* $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. * */ /* 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" #include "e2tool-e2cp.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 #define OUTBUF_SIZE ((BUF_SIZE)+1) #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]; /* Local Prototypes */ 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); 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: main_e2cp() * * 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 an ext2fs file specification * 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 */ int main_e2cp(int argc, char *argv[]) { ext2_filsys fs = NULL; ext2_ino_t root; ext2_ino_t orig_cwd = -1; ext2_ino_t cwd; char tmpbuf[BUF_SIZE]; char outpath[OUTBUF_SIZE]; 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 = -1; 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))) { 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 = OUTBUF_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); /* Even though the out_file aka outpath buffer has * size OUTBUF_SIZE which is larger than BUF_SIZE, * we still limit the string length to BUF_SIZE as * some other parts of the code might expect that. */ 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))) { 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 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 : "" , 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 : "", 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+128]; if (file_to_file) { snprintf(tmpstr, BUF_SIZE+128, "%s/%s", odir, ofile); tmpstr[BUF_SIZE+128-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; 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); } e2tools-0.1.2/src/e2tool-e2cp.h000066400000000000000000000002701467166551300161110ustar00rootroot00000000000000#ifndef E2TOOL_E2CP_H #define E2TOOL_E2CP_H extern int main_e2cp(int argc, char *argv[]); extern int my_strcmp(const void *n1, const void *n2); #endif /* !defined(E2TOOL_E2CP_H) */ e2tools-0.1.2/src/e2tool-e2ln.c000066400000000000000000000221241467166551300161150ustar00rootroot00000000000000/* $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. * */ /* 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" #include "e2tool-e2ln.h" /* Macros */ #define USAGE "Usage: e2ln [-vfs] source destination\n" /* Name: main_e2ln() * * 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 */ int main_e2ln(int argc, char *argv[]) { int verbose=0; int force=0; int symlink=0; 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))) { 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 */ e2tools-0.1.2/src/e2tool-e2ln.h000066400000000000000000000010761467166551300161250ustar00rootroot00000000000000#ifndef E2TOOL_E2LN_H #define E2TOOL_E2LN_H /* Apparently (and weirdly), ext2fs.h wants some macros like * HAVE_SYS_TYPES_H defined before it is included, so we include * "e2tools-autoconfig.h" before . * * See https://github.com/e2tools/e2tools/issues/1#issuecomment-582913807 */ #include "e2tools-autoconfig.h" #include extern int main_e2ln(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 /* !defined(E2TOOL_E2LN_H) */ e2tools-0.1.2/src/e2tool-e2ls.c000066400000000000000000000644651467166551300161400ustar00rootroot00000000000000/* $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 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 #include #include #include #include #include "e2tools-autoconfig.h" #include "e2tools.h" #include "elist.h" #include "e2tool-e2ls.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 NUMERIC_OPT 0x0080 #define SELINUX_OPT 0x0100 #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); 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(const void *n1, const void *n2); int name_sort(const void *n1, const void *n2); int inode_sort(const void *n1, const void *n2); int mod_time_sort(const void *n1, const void *n2); int creat_time_sort(const void *n1, const 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 UNUSED_PARM(offset), int UNUSED_PARM(blocksize), char UNUSED_PARM(*buf), void *private) { 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(1, sizeof(ls_file_t)))) { 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 */ static void print_usage(FILE *out) { #ifdef HAVE_EXT2FS_XATTRS fputs("Usage: e2ls [-acDfilnrtZ][-d dir] file\n", out); #else fputs("Usage: e2ls [-acDfilnrt][-d dir] file\n", out); #endif } /* 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. */ int main_e2ls(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)(const void *n1, const 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 #ifdef HAVE_EXT2FS_XATTRS while ((c = getopt (argc, argv, "acDd:filnrtZ")) != EOF) #else while ((c = getopt (argc, argv, "acDd:filnrt")) != EOF) #endif { switch (c) { case 'a': ls.options |= HIDDEN_OPT; break; case 'c': ls.options |= CREATE_OPT; break; case 'l': file_disp = long_disp; break; case 'n': file_disp = long_disp; ls.options |= NUMERIC_OPT; 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))) { return EXIT_FAILURE; } 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; #ifdef HAVE_EXT2FS_XATTRS case 'Z': ls.options |= SELINUX_OPT; break; #endif default: fprintf(stderr, "%s: invalid option: %c\n", "e2ls", c); print_usage(stderr); return EXIT_FAILURE; } } if (argc <= optind) { print_usage(stderr); return EXIT_FAILURE; } 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;cdata; 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 UNUSED_PARM(*col), int options) { char lbr, rbr; char modestr[11]; char userstr[9]; char groupstr[9]; 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 = ' '; } sprintf(modestr, "%c%c%c%c%c%c%c%c%c%c", LINUX_S_ISLNK(info->inode.i_mode) ? 'l' : LINUX_S_ISDIR(info->inode.i_mode) ? 'd' : LINUX_S_ISCHR(info->inode.i_mode) ? 'c' : LINUX_S_ISBLK(info->inode.i_mode) ? 'b' : LINUX_S_ISFIFO(info->inode.i_mode) ? 'p' : LINUX_S_ISSOCK(info->inode.i_mode) ? 's' : '-', (info->inode.i_mode & (1 << 8)) ? 'r' : '-', (info->inode.i_mode & (1 << 7)) ? 'w' : '-', (info->inode.i_mode & LINUX_S_ISUID) ? 'S' : (info->inode.i_mode & (1 << 6)) ? 'x' : '-', (info->inode.i_mode & (1 << 5)) ? 'r' : '-', (info->inode.i_mode & (1 << 4)) ? 'w' : '-', (info->inode.i_mode & LINUX_S_ISGID) ? 'S' : (info->inode.i_mode & (1 << 3)) ? 'x' : '-', (info->inode.i_mode & (1 << 2)) ? 'r' : '-', (info->inode.i_mode & (1 << 1)) ? 'w' : '-', (info->inode.i_mode & LINUX_S_ISVTX) ? 'T' : (info->inode.i_mode & (1 << 0)) ? 'x' : '-'); 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, " "); if (options & NUMERIC_OPT) { const int userlen = 5; sprintf(userstr, "%*d", userlen, info->inode.i_uid); sprintf(groupstr, "%*d", userlen, info->inode.i_gid); } else { const int userlen = 8; char buf[1024]; struct passwd pwd, *p_pwd; struct group grp, *p_grp; getpwuid_r(info->inode.i_uid, &pwd, buf, sizeof(buf), &p_pwd); if (p_pwd) snprintf(userstr, userlen+1, "%*s", userlen, pwd.pw_name); else sprintf(userstr, "%*d", userlen, info->inode.i_uid); getgrgid_r(info->inode.i_gid, &grp, buf, sizeof(buf), &p_grp); if (p_grp) snprintf(groupstr, userlen+1, "%*s", userlen, grp.gr_name); else sprintf(groupstr, "%*d", userlen, info->inode.i_gid); } printf("%c%10u%c %10s %s %s ", lbr, info->inode_num, rbr, modestr, userstr, groupstr); if (LINUX_S_ISDIR(info->inode.i_mode)) printf("%7d", info->inode.i_size); else printf("%7" PRIu64, (uint64_t)(info->inode.i_size | ((__u64)info->inode.i_size_high << 32))); printf(" %s %s", datestr, info->name); #ifdef HAVE_EXT2FS_XATTRS if (options & SELINUX_OPT) { struct ext2_xattr_handle *handle; char *val; size_t value_len = 0; ext2fs_xattrs_open(fs, info->inode_num, &handle); if (handle) { ext2fs_xattrs_read(handle); ext2fs_xattr_get(handle, "security.selinux", (void**)&val, &value_len); int i; int l = 16 - strlen(info->name); for (i = 0; i < l; i++) { printf(" "); } if (value_len) { printf(" %s ", val); free(val); } else printf(" - "); ext2fs_xattrs_close(&handle); } else printf(" - "); } #endif printf("\n"); } /* 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 int 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(const void *n1, const 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(const void *n1, const 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(const void *n1, const 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 : (int)(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(const void *n1, const 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 : (int)(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(const void *n1, const 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 : (int)(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; ls_file_t *cd; 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 */ e2tools-0.1.2/src/e2tool-e2ls.h000066400000000000000000000002011467166551300161170ustar00rootroot00000000000000#ifndef E2TOOL_E2LS_H #define E2TOOL_E2LS_H extern int main_e2ls(int argc, char *argv[]); #endif /* !defined(E2TOOL_E2LS_H) */ e2tools-0.1.2/src/e2tool-e2mkdir.c000066400000000000000000000373401467166551300166200ustar00rootroot00000000000000/* $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 * and modified by Robert Sanders * as well as portions of the ext2fs library (C) 1993-1995 Theodore Ts'o */ /* 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" #include "e2tool-e2mkdir.h" /* Local Prototypes */ long create_subdir(ext2_filsys fs, ext2_ino_t root, ext2_ino_t *cwd, char *dirname, struct stat *def_stat); /* Name: main_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. */ int main_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;iblocksize, (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:%ld\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:%ld\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 */ e2tools-0.1.2/src/e2tool-e2mkdir.h000066400000000000000000000005701467166551300166200ustar00rootroot00000000000000#ifndef E2TOOL_E2MKDIR_H #define E2TOOL_E2MKDIR_H extern int main_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); extern long change_cwd(ext2_filsys fs, ext2_ino_t root, ext2_ino_t *cwd, char *dirname); #endif /* !defined(E2TOOL_E2MKDIR_H) */ e2tools-0.1.2/src/e2tool-e2mv.c000066400000000000000000000343301467166551300161300ustar00rootroot00000000000000/* $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. * */ /* 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: main_e2mv() * * 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 */ int main_e2mv(int argc, char *argv[]) { int verbose=0; int force=0; int swap_files=0; 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))) { 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))) { 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 */ e2tools-0.1.2/src/e2tool-e2mv.h000066400000000000000000000004571467166551300161400ustar00rootroot00000000000000#ifndef E2TOOL_E2MV_H #define E2TOOL_E2MV_H extern int main_e2mv(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 /* !defined(E2TOOL_E2MV_H) */ e2tools-0.1.2/src/e2tool-e2rm.c000066400000000000000000000260761467166551300161340ustar00rootroot00000000000000/* $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 * and modified by Robert Sanders * as well as portions of the ext2fs library (C) 1993-1995 Theodore Ts'o */ /* 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 #include "e2tools.h" #include "e2tool-e2rm.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 */ 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: main_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 files 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. */ int main_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;cname_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 UNUSED_PARM(offset), int UNUSED_PARM(blocksize), char *UNUSED_PARM(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); } e2tools-0.1.2/src/e2tool-e2rm.h000066400000000000000000000002011467166551300161170ustar00rootroot00000000000000#ifndef E2TOOL_E2RM_H #define E2TOOL_E2RM_H extern int main_e2rm(int argc, char *argv[]); #endif /* !defined(E2TOOL_E2RM_H) */ e2tools-0.1.2/src/e2tool-e2tail.c000066400000000000000000000277021467166551300164440ustar00rootroot00000000000000/* $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. * */ /* 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 #include "compiler-definitions.h" #include "e2tools.h" #include "e2tool-e2tail.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 /* Check type sizes match for the signedness conversion to work */ BARE_COMPILE_TIME_ASSERT(SIZEOF_MEMBER(struct ext2_inode, i_size) == sizeof(int)) BARE_COMPILE_TIME_ASSERT(sizeof(ext2_off_t) == sizeof(int)) BARE_COMPILE_TIME_ASSERT(SIZEOF_MEMBER(struct ext2_inode, i_size) == sizeof(ext2_off_t)) /* Structures and Unions */ /* External Variables */ /* Global Variables */ /* Local Variables */ /* External Prototypes */ /* Local Prototypes */ static long tail(ext2_filsys *fs, ext2_ino_t root, char *input, int num_lines, int follow, int sleep_int, char *cur_filesys); /* Name: main_e2tail() * * 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. */ int main_e2tail(int argc, char *argv[]) { /* UNUSED 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': /* UNUSED 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))) { 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; 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 (((int32_t)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++; if (0 > write(1, ptr, bytes_read - bytes_to_read - 1)) { perror("writing bytes to stdout"); return -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) { if (0 > write(1, buf, bytes_read)) { perror("writing bytes to stdout"); return -1; } } /* retrieve 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 ((inode.i_size <= INT_MAX) && (cur_pos < ((int)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; 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 <= INT_MAX) { /* the file has grown too large */ fputs("inode.i_size above INT_MAX", stderr); return 0; } else if (((int)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 (((int)inode.i_size) < cur_pos) { /* the file was truncated, so bail */ return(0); } } } return(0); } e2tools-0.1.2/src/e2tool-e2tail.h000066400000000000000000000002111467166551300164330ustar00rootroot00000000000000#ifndef E2TOOL_E2TAIL_H #define E2TOOL_E2TAIL_H extern int main_e2tail(int argc, char *argv[]); #endif /* !defined(E2TOOL_E2TAIL_H) */ e2tools-0.1.2/src/e2tools-toolmap.h000066400000000000000000000004471467166551300171240ustar00rootroot00000000000000/* Note: The corresponding e2tools-toolmap.c file is autogenerated. */ #ifndef E2TOOLS_TOOLMAP_H #define E2TOOLS_TOOLMAP_H struct toolmap_element { char *name; int (*main_func)(int argc, char *argv[]); }; extern struct toolmap_element toolmap[]; #endif /* !defined(E2TOOLS_TOOLMAP_H) */ e2tools-0.1.2/src/e2tools.7000066400000000000000000000034041467166551300153660ustar00rootroot00000000000000.TH E2TOOLS 7 "March 2, 2005" .\" .SH NAME e2tools \- utilities to manipulate files in an ext2/ext3 filesystem .\" .SH DESCRIPTION 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. .PP Supported functionality: .TP .B e2cp copy files .TP .B e2mv move files .TP .B e2rm remove files .TP .B e2mkdir create directory .TP .B e2ln create hard links .TP .B e2ls list files/directories .TP .B e2tail output the last part of a file .PP In general, to specify a directory or file on an ext2 filesystem for the e2tools utilities, use the following form: .IP filesystem:directory_path .PP 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: .IP /tmp/boot.img:/tmp/file1 .IP /tmp/file2 .IP /tmp/file3 .IP /tmp/boot2.img:/tmp/file4 .PP Files 1-3 are on /tmp/boot.img and the last file is on /tmp/boot2.img .\" .SH SEE ALSO .BR e2cp (1), .BR e2ln (1), .BR e2ls (1), .BR e2mkdir (1), .BR e2mv (1), .BR e2rm (1), .BR e2tail (1). .\" .SH AUTHOR The \fBe2tools\fP were written by Keith Sheffield . .PP This manual page was written by Lucas Wall , for the Debian project (but may be used by others). e2tools-0.1.2/src/e2tools.c000066400000000000000000000033511467166551300154430ustar00rootroot00000000000000/* $Header: /home/ksheff/src/e2tools/RCS/e2tools.c,v 0.7 2002/08/08 07:55:03 ksheff Exp $ */ /* * e2tools.c */ /* 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" #include "e2tools-toolmap.h" void usage(void) { fprintf(stderr, "Usage: e2tools [OPTION...]\n"); fprintf(stderr, "\n"); fprintf(stderr, " Commands:\n"); for (unsigned int i=0; toolmap[i].name; ++i) { fprintf(stderr, " %s\n", toolmap[i].name); } } int main(int argc, char *argv[]) { char *ptr; if (NULL != (ptr = strrchr(argv[0], '/'))) ptr++; else ptr = argv[0]; if (strcmp(ptr, "e2tools") == 0) { if (argc < 2) { usage(); exit(1); } ++argv; --argc; ptr = argv[0]; } initialize_ext2_error_table(); for (unsigned int i=0; toolmap[i].name; ++i) { if (strcmp(ptr, toolmap[i].name) == 0) { exit(toolmap[i].main_func(argc, argv)); } } fprintf(stderr, "e2tools command not implemented\n"); return 1; } e2tools-0.1.2/src/e2tools.h000066400000000000000000000043331467166551300154510ustar00rootroot00000000000000#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 #include #include #include #include #include #include #include /* #ifdef HAVE_GETOPT_H #include #else #endif */ #ifdef HAVE_OPTRESET extern int optreset; /* defined by BSD, but not others */ #endif #ifdef HAVE_ERRNO_H #include #endif #include #include #include #include /* Apparently (and weirdly), ext2fs.h wants some macros like * HAVE_SYS_TYPES_H defined before it is included, so we include * "e2tools-autoconfig.h" before . * * See https://github.com/e2tools/e2tools/issues/1#issuecomment-582913807 */ #include "e2tools-autoconfig.h" #include "ext2fs/ext2_fs.h" #include "ext2fs/ext2fs.h" #define E2T_FORCE 1 #define E2T_DO_MV 2 #include "util.h" #include "write.h" #include "progress.h" #include "read.h" #include "e2tool-e2cp.h" #include "e2tool-e2ln.h" #include "e2tool-e2ls.h" #include "e2tool-e2mkdir.h" #include "e2tool-e2mv.h" #include "e2tool-e2rm.h" #include "e2tool-e2tail.h" #if __GNUC__ >= 4 # define UNUSED_PARM(foo) foo __attribute__((unused)) #else # define UNUSED_PARM(foo) foo ## __UNUSED #endif #endif /* !defined(E2TOOLS_H) */ e2tools-0.1.2/src/elist.c000066400000000000000000000066771467166551300152120ustar00rootroot00000000000000/* $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. * */ /* 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 #include #include "elist.h" #ifndef NULL #define NULL ((void *)0) #endif elist_t * elist_new(void) { elist_t *list; list = (elist_t *) calloc(1, sizeof(elist_t)); 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 *)) { 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)(const void *, const 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); } } } e2tools-0.1.2/src/elist.h000066400000000000000000000016411467166551300152010ustar00rootroot00000000000000#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; extern elist_t *elist_new(void); 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)(const void *, const void *), int reverse); #endif /* !defined(ELIST_H) */ e2tools-0.1.2/src/include.am000066400000000000000000000102551467166551300156530ustar00rootroot00000000000000# -*- makefile-automake -*- -*- makefile -*- ######################################################################## # Define e2tools ######################################################################## bin_PROGRAMS += e2tools e2tools_CFLAGS = e2tools_CPPFLAGS = e2tools_LDADD = # e2tools_CFLAGS += -save-temps=obj e2tools_CPPFLAGS += -I$(top_srcdir)/src e2tools_CPPFLAGS += $(EXT2FS_CFLAGS) e2tools_LDADD += $(EXT2FS_LIBS) e2tools_CPPFLAGS += $(COM_ERR_CFLAGS) e2tools_LDADD += $(COM_ERR_LIBS) e2tools_SOURCES = e2tools_SOURCES += %reldir%/compiler-definitions.h e2tools_SOURCES += %reldir%/e2tools.c %reldir%/e2tools.h e2tools_SOURCES += %reldir%/elist.c %reldir%/elist.h e2tools_SOURCES += %reldir%/progress.c %reldir%/progress.h e2tools_SOURCES += %reldir%/read.c %reldir%/read.h e2tools_SOURCES += %reldir%/util.c %reldir%/util.h e2tools_SOURCES += %reldir%/write.c %reldir%/write.h dist_man_MANS += %reldir%/e2tools.7 if HAVE_EXT2FS_XATTRS # EXTRA_DIST += %reldir%/e2chcon.1.in # CLEANFILES += %reldir%/e2chcon.1 # man_MANS += %reldir%/e2chcon.1 # e2tools_list += e2chcon endif e2tools_SOURCES += %reldir%/e2tool-e2cp.c e2tools_SOURCES += %reldir%/e2tool-e2cp.h dist_man_MANS += %reldir%/e2cp.1 e2tools_list += e2cp e2tools_SOURCES += %reldir%/e2tool-e2ln.c e2tools_SOURCES += %reldir%/e2tool-e2ln.h dist_man_MANS += %reldir%/e2ln.1 e2tools_list += e2ln e2tools_SOURCES += %reldir%/e2tool-e2ls.c e2tools_SOURCES += %reldir%/e2tool-e2ls.h EXTRA_DIST += %reldir%/e2ls.1.in CLEANFILES += %reldir%/e2ls.1 man_MANS += %reldir%/e2ls.1 e2tools_list += e2ls %reldir%/e2ls.1 : %reldir%/e2ls.1.in Makefile e2tools_SOURCES += %reldir%/e2tool-e2mkdir.c e2tools_SOURCES += %reldir%/e2tool-e2mkdir.h dist_man_MANS += %reldir%/e2mkdir.1 e2tools_list += e2mkdir e2tools_SOURCES += %reldir%/e2tool-e2mv.c e2tools_SOURCES += %reldir%/e2tool-e2mv.h dist_man_MANS += %reldir%/e2mv.1 e2tools_list += e2mv e2tools_SOURCES += %reldir%/e2tool-e2rm.c e2tools_SOURCES += %reldir%/e2tool-e2rm.h dist_man_MANS += %reldir%/e2rm.1 e2tools_list += e2rm e2tools_SOURCES += %reldir%/e2tool-e2tail.c e2tools_SOURCES += %reldir%/e2tool-e2tail.h dist_man_MANS += %reldir%/e2tail.1 e2tools_list += e2tail # Put this rule after all appends to the e2tools_list variable e2tools_SOURCES += %reldir%/e2tools-toolmap.h BUILT_SOURCES += %reldir%/e2tools-toolmap.c CLEANFILES += %reldir%/e2tools-toolmap.c e2tools_SOURCES += %reldir%/e2tools-toolmap.c %reldir%/e2tools-toolmap.c: Makefile @$(MKDIR_P) "%reldir%" @( \ echo "/* autogenerated from Makefile.am */"; \ echo "#include "; \ echo "#include \"e2tools-toolmap.h\""; \ for tool in $(e2tools_list); do \ echo "#include \"e2tool-$${tool}.h\""; \ done; \ echo "struct toolmap_element toolmap[] = {"; \ for tool in $(e2tools_list); do \ echo " {\"$${tool}\", main_$${tool}},"; \ done; \ echo " {NULL, NULL}"; \ echo "};"; \ ) > %reldir%/e2tools-toolmap.c.tmp @if test -f %reldir%/e2tools-toolmap.c && cmp %reldir%/e2tools-toolmap.c %reldir%/e2tools-toolmap.c.tmp >/dev/null 2>&1; then \ echo "Keeping unchanged e2tools-toolmap.c"; \ rm -f %reldir%/e2tools-toolmap.c.tmp; \ else \ echo "Updating e2tools-toolmap.c"; \ mv -f %reldir%/e2tools-toolmap.c.tmp %reldir%/e2tools-toolmap.c; \ fi all_targets += e2tools-symlinks phony_targets += e2tools-symlinks e2tools-symlinks: e2tools$(EXEEXT) @for symlink in $(e2tools_list); do \ rm -f "$${symlink}"; \ $(LN_S) e2tools "$${symlink}" || exit 1; \ done clean_targets += e2tools-clean phony_targets += e2tools-clean e2tools-clean: -rm -f $(e2tools_list) install_targets += e2tools-install phony_targets += e2tools-install e2tools-install: cd $(DESTDIR)$(bindir) && \ for symlink in $(e2tools_list); do \ rm -f "$${symlink}"; \ $(LN_S) e2tools "$${symlink}" || exit 1; \ done uninstall_targets += e2tools-uninstall phony_targets += e2tools-uninstall e2tools-uninstall: -cd $(DESTDIR)$(bindir) && rm -f $(e2tools_list) ######################################################################## # End of src/include.am ######################################################################## e2tools-0.1.2/src/progress.c000066400000000000000000000100541467166551300157160ustar00rootroot00000000000000/* $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. * */ /* Description */ /* * * */ /* * $Log: progress.c,v $ * Revision 0.1 2002/06/26 11:17:28 ksheff * Initial revision * */ /* Feature Test Switches */ /* System Headers */ #include #include #include #include #include /* 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 = ""; 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 %10ld / %10ld\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(void) { if (prog_start != prog_time) fputs(PROG_CLEAR, stderr); } /* end of finish_progress */ e2tools-0.1.2/src/progress.h000066400000000000000000000003671467166551300157310ustar00rootroot00000000000000#ifndef E2TOOLS_PROGRESS_H #define E2TOOLS_PROGRESS_H extern void init_progress(char *file, struct stat *sbuf); extern void update_progress(unsigned long num_bytes); extern void finish_progress(void); #endif /* !defined(E2TOOLS_PROGRESS_H) */ e2tools-0.1.2/src/read.c000066400000000000000000000172531467166551300147750ustar00rootroot00000000000000/* $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 * */ static char __attribute__ ((used)) copyright[] = "Copyright 2002 Keith W Sheffield"; /* 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" #include "read.h" /* Local Prototypes */ 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) { 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 UNUSED_PARM(dest_fd), ext2_off_t offset, ext2_off_t *ret_pos) { char buf[4096]; unsigned int bytes_read; 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 */ while (1) { ssize_t bytes_written; if ((retval = ext2fs_file_read(infile, buf, sizeof(buf), &bytes_read))) { fputs(error_message(retval), stderr); return retval; } if (bytes_read <= 0) break; bytes_written = write(dest_fd, buf, bytes_read); if (bytes_written < 0) break; if (bytes_read != (size_t)bytes_written) break; } if (bytes_read != 0) { 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); } e2tools-0.1.2/src/read.h000066400000000000000000000007701467166551300147760ustar00rootroot00000000000000#ifndef E2TOOLS_READ_H #define E2TOOLS_READ_H 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 /* !defined(E2TOOLS_READ_H) */ e2tools-0.1.2/src/util.c000066400000000000000000000141651467166551300150360ustar00rootroot00000000000000/* $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 * and modified by Robert Sanders */ /* 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 "util.h" #include /* 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 */ static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr, int blockcnt, void *private); /* translate an 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: %s\n", error_message(retval), name); *fs = NULL; return retval; } if ((retval = ext2fs_read_inode_bitmap(*fs))) { fprintf(stderr, "%s: %s\n", error_message(retval), name); if ((closeval = ext2fs_close(*fs))) fputs(error_message(closeval), stderr); *fs = NULL; return retval; } if ((retval = ext2fs_read_block_bitmap(*fs))) { fprintf(stderr, "%s: %s\n", error_message(retval), name); 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 UNUSED_PARM(blockcnt), void UNUSED_PARM(*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; 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(®); } e2tools-0.1.2/src/util.h000066400000000000000000000014131467166551300150330ustar00rootroot00000000000000#ifndef E2TOOLS_UTIL_H #define E2TOOLS_UTIL_H 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); extern int is_file_regexp(char *ptr); extern regex_t *make_regexp(char *shell); #endif /* !defined(E2TOOLS_UTIL_H) */ e2tools-0.1.2/src/write.c000066400000000000000000000230401467166551300152030ustar00rootroot00000000000000/* $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 * and modified by Robert Sanders */ /* 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 #include "e2tools.h" #include "write.h" #include "progress.h" /* Local Prototypes */ 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 */ e2tools-0.1.2/src/write.h000066400000000000000000000003571467166551300152160ustar00rootroot00000000000000#ifndef E2TOOLS_WRITE_H #define E2TOOLS_WRITE_H 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 /* !defined(E2TOOLS_WRITE_H) */ e2tools-0.1.2/tests/000077500000000000000000000000001467166551300142615ustar00rootroot00000000000000e2tools-0.1.2/tests/include.am000066400000000000000000000011441467166551300162230ustar00rootroot00000000000000# -*- makefile-automake -*- -*- makefile -*- ######################################################################## # Test suite ######################################################################## EXTRA_DIST += %reldir%/simple-test.sh.in CLEANFILES += %reldir%/simple-test.sh if HAVE_DD_COMMAND if HAVE_MKE2FS_COMMAND TESTS += %reldir%/simple-test.sh %reldir%/simple-test.sh : %reldir%/simple-test.sh.in Makefile endif endif ######################################################################## # End of tests/include.am ######################################################################## e2tools-0.1.2/tests/simple-test.sh.in000066400000000000000000000047771467166551300175070ustar00rootroot00000000000000#!/bin/sh # Simple test for e2tools # Copyright (C) 2006 Hans Ulrich Niedermann # Copyright (C) 2020 Hans Ulrich Niedermann # # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA set -ex # Note on compatibility: Both GNU coreutils dd and busybox dd accept # sizes like 16M or 1G, but other dd implementations like OSX dd do # not. So instead of requiring GNU coreutils or busybox, we try to be # cross-platform compatible and use numbers only. # Caution: Even with a sparse image file, a filesystem image of 100G # size needs 1.6GB on disk just to be formatted! for imgsize in 16777216; do testimg="test-${imgsize}.img" trap "" EXIT # create sparse image file full of zeros rm -f "${testimg}" @DD@ if=/dev/null of="${testimg}" bs=1 count=1 seek="$imgsize" # create file system on image file @MKE2FS@ -F "${testimg}" # check a few things @top_builddir@/e2mkdir "${testimg}:/foo" @top_builddir@/e2ls -l "${testimg}:" @top_builddir@/e2mkdir "${testimg}:/bar" @top_builddir@/e2mkdir "${testimg}:/bla" @top_builddir@/e2ls -l "${testimg}:" for srcfile in @top_srcdir@/README.md @top_srcdir@/configure; do @top_builddir@/e2cp "${srcfile}" "${testimg}:/foo" @top_builddir@/e2ls -l "${testimg}:/foo" @top_builddir@/e2ls -ln "${testimg}:/foo" @HAVE_EXT2FS_XATTRS_FALSE@@top_builddir@/e2ls -lnZ "${testimg}:/foo" @HAVE_EXT2FS_XATTRS_FALSE@@top_builddir@/e2ls -lZ "${testimg}:/foo" filebase="$(basename "$srcfile")" trap "rm -f ${filebase}.test-c" EXIT @top_builddir@/e2cp "${testimg}:/foo/${filebase}" "${filebase}.test-c" @top_builddir@/e2rm ${testimg}:/foo/${filebase} @top_builddir@/e2ls -l "${testimg}:/foo" cmp ${srcfile} ${filebase}.test-c rm -f ${filebase}.test-c done # remove the test image rm -f "${testimg}" trap "" EXIT done exit 0