diff options
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | README | 3 | ||||
-rw-r--r-- | TODO | 8 | ||||
-rw-r--r-- | flx/ChangeLog | 5 | ||||
-rw-r--r-- | flx/Makefile | 2 | ||||
-rw-r--r-- | flx/check.c | 4 | ||||
-rw-r--r-- | flx/fct1.c | 5 | ||||
-rw-r--r-- | flx/flx.h | 4 | ||||
-rw-r--r-- | flx/input_fs.c | 32 | ||||
-rwxr-xr-x | scripts/pkg | 6 | ||||
-rw-r--r-- | signfs/AUTHORS | 1 | ||||
-rw-r--r-- | signfs/COPYING | 340 | ||||
-rw-r--r-- | signfs/ChangeLog | 7 | ||||
l--------- | signfs/LICENCE | 1 | ||||
-rw-r--r-- | signfs/Makefile | 46 | ||||
-rw-r--r-- | signfs/README | 20 | ||||
-rw-r--r-- | signfs/TODO | 11 | ||||
-rw-r--r-- | signfs/libtools.c | 1126 | ||||
-rw-r--r-- | signfs/libtools.h | 104 | ||||
-rw-r--r-- | signfs/main.c | 166 | ||||
-rw-r--r-- | signfs/md5.c | 261 | ||||
-rw-r--r-- | signfs/md5.h | 55 | ||||
-rw-r--r-- | signfs/others.c | 74 | ||||
-rw-r--r-- | signfs/others.h | 11 | ||||
-rw-r--r-- | signfs/sample.sign | 32 | ||||
-rw-r--r-- | signfs/signfs.c | 526 | ||||
-rw-r--r-- | signfs/signfs.h | 114 | ||||
-rw-r--r-- | signfs/structure.c | 74 | ||||
-rw-r--r-- | signfs/structure.h | 53 |
29 files changed, 3087 insertions, 23 deletions
@@ -80,11 +80,26 @@ - removed debugging defines from init which prevented it from working anymore in 0.1.24 -2004/12/14 : Version 0.6.9 - - fixed a bug in fct1.c where two different but valid links would +2004/12/14 + - flx: bumped version to 0.6.9 + - flx: fixed a bug in fct1.c where two different but valid links would not be reported as different. 2005/03/01 : - pkg 0.5.0 provides some cross-compilation variables - some makefiles have been modified to support cross-compilation - release 0.1.28 + +2005/03/25 + - pkg 0.5.2 fixes a small bug and provides support for RANLIB + +2005/03/26 + - finally located the old signfs sources, so the binary could be replaced. + nobody should need it anyway, but it's more for cleanness. + +2005/04/09 + - flx: added the '--ignore-dir' option to ignore differences in directories + size/date. + - flx: during a check, do not compute the md5 sums if the user asks to + ignore it. This makes simple diffs a lot faster. + - flx: bumped version to 0.7.1 @@ -1,6 +1,7 @@ Warning !!! - 1) this package should be compiled with the "pkg" command distributed with Formilux + 1) this package should be compiled with the latest version of the "pkg" command distributed + with Formilux, which is the one located in the 'script' directory. 2) dietlibc and sstrip are needed for most small utilities. Since they're not available everywhere, a pre-compiled version of these utilities is provided. To avoid unexpected cleanups, "pkg clean" only cleans the minimum, and you have to use "pkg distclean" to @@ -1,2 +1,10 @@ +- pkg: pack does not recognize compressed man pages, so launching + pkg pack twice makes them disappear from the list of dependencies. +- preinit: shoud provide a prompt if init fails ? - finish "pkg release" : problems when releasing a package which is already released in another arch. +- pkg: how to build several packages from one build.cfg at once ? + eg: ssh, ssh-tcpwrap ? +- pkg: cannot understand a package named xxx-v1.2.3 nor xxx.1.2.3 +- pkg: release should to clean + setpkg + mark files R/O + diff --git a/flx/ChangeLog b/flx/ChangeLog index 4e61cdf..8af9db3 100644 --- a/flx/ChangeLog +++ b/flx/ChangeLog @@ -1,3 +1,8 @@ +2005/04/09 : Version 0.7.1 +- added the '--ignore-dir' option to ignore differences in directories + size/date. +- during a check, do not compute the md5 sums if the user asks to + ignore it. This makes simple diffs a lot faster. 2004/12/14 : Version 0.6.9 - fixed a bug in fct1.c where two different but valid links would not be reported as different. diff --git a/flx/Makefile b/flx/Makefile index 4d0c460..02b7847 100644 --- a/flx/Makefile +++ b/flx/Makefile @@ -26,7 +26,7 @@ NAME=flx -VERSION=0.7.0 +VERSION=0.7.1 SRC=main.c arg.c utils.c md5.c flx.c fct1.c check.c sign.c \ input.c input_fs.c input_file.c \ output.c output_file.c diff --git a/flx/check.c b/flx/check.c index 4c09a47..0a425c3 100644 --- a/flx/check.c +++ b/flx/check.c @@ -50,6 +50,7 @@ static POOL_INIT(t_file_diff); #define O_REWRITE_SRC2 17 #define O_OUTPUT 18 #define O_IGN_DOT 19 +#define O_IGN_DIR 20 t_param flxcheck_poptions[] = { { 'h', "help", O_HELP, 0, @@ -70,6 +71,8 @@ t_param flxcheck_poptions[] = { "--ignore-ldate ignore date on links" }, { 0, "ignore-dot", O_IGN_DOT, 0, "--ignore-dot do not compare '.' and '..'" }, + { 0, "ignore-dir", O_IGN_DIR, 0, + "--ignore-dir do not compare directories" }, { 0, "show-all", O_SH_ALL, 0, "--show-all show all files (same and differs)" }, { 0, "only-new", O_SH_NEW, 0, @@ -524,6 +527,7 @@ int flxcheck_pfct(int opt, t_param *param, char **flag, char **argv) { else if (opt == O_IGN_DATE) UNSET(Diff, DIFF_TIME); else if (opt == O_IGN_LINK) UNSET(Diff, DIFF_LINK); else if (opt == O_IGN_LDATE) UNSET(Diff, DIFF_LDATE); + else if (opt == O_IGN_DIR) UNSET(Diff, DIFF_DIR); else if (opt == O_SH_HR) SET(Options, GOPT_HUMAN_READABLE); else if (opt == O_REWRITE_SRC1) Rewrite_Src1 = strdup(*(argv+1)); else if (opt == O_REWRITE_SRC2) Rewrite_Src2 = strdup(*(argv+1)); @@ -76,8 +76,9 @@ int files_are_the_same(t_file_desc *f1, t_file_desc *f2, int Diff, char *path) f1->stat.st_rdev != f2->stat.st_rdev) diff |= DIFF_DEV; /* minor/major differ for device files */ if (DIFF(TIME) && f1->stat.st_mtime != f2->stat.st_mtime) { - if (DIFF(LDATE) || !(S_ISLNK(f1->stat.st_mode))) - diff |= DIFF_TIME; /* modification times diff */ + if (DIFF(DIR) || !S_ISDIR(f1->stat.st_mode) || !S_ISDIR(f2->stat.st_mode)) + if (DIFF(LDATE) || !(S_ISLNK(f1->stat.st_mode))) + diff |= DIFF_TIME; /* modification times diff */ } if (DIFF(LINK) && S_ISLNK(f1->stat.st_mode) && S_ISLNK(f2->stat.st_mode)) { char temp[BUFFER_LENGTH]; @@ -8,7 +8,7 @@ #include "utils.h" #include "md5.h" -#define COPYRIGHT "Copyright 2002-2004, Benoit DOLEZ <bdolez@ant-computing.com>" +#define COPYRIGHT "Copyright 2002-2005, Benoit DOLEZ <bdolez@ant-computing.com>" #define DUMPBASENAME "formilux-sig.dat" @@ -48,6 +48,7 @@ #define F_LINK 0x0040 #define F_TIME 0x0080 #define F_LDATE 0x0100 +#define F_DIR 0x0200 #define DIFF_TYPE F_TYPE #define DIFF_MODE F_MODE @@ -58,6 +59,7 @@ #define DIFF_LINK F_LINK #define DIFF_TIME F_TIME #define DIFF_LDATE F_LDATE +#define DIFF_DIR F_DIR #define DIFF_NOTFILLED 0x8000 #define DELIM_BASE ':' diff --git a/flx/input_fs.c b/flx/input_fs.c index 042134c..e64f9da 100644 --- a/flx/input_fs.c +++ b/flx/input_fs.c @@ -35,21 +35,25 @@ static t_file_desc *complete_info_from_fs(char *path, t_file_desc *desc) { /* copy stat informations */ memcpy(&desc->stat, &stat, sizeof(stat)); - if (S_ISREG(stat.st_mode) && !desc->md5) /* get md5 checksum */ - desc->md5 = checksum_md5_from_file(path); - else if (S_ISLNK(stat.st_mode) && !desc->link) { - /* get link and md5 associed */ - char temp[BUFFER_LENGTH]; - int l; - - if ((l = readlink(path, temp, BUFFER_LENGTH)) < 0) { - PFERROR("readlink(%s)", path); - } else { - temp[l] = 0; - desc->link = strdup(temp); - desc->md5 = checksum_md5_from_data(temp, l); + if (IS(Diff, DIFF_CHECKSUM)) { + if (S_ISREG(stat.st_mode) && !desc->md5) /* get md5 checksum */ + desc->md5 = checksum_md5_from_file(path); + else if (S_ISLNK(stat.st_mode) && !desc->link) { + /* get link and md5 associed */ + char temp[BUFFER_LENGTH]; + int l; + + if ((l = readlink(path, temp, BUFFER_LENGTH)) < 0) { + PFERROR("readlink(%s)", path); + } else { + temp[l] = 0; + desc->link = strdup(temp); + desc->md5 = checksum_md5_from_data(temp, l); + } } - } + } else + desc->md5 = NULL; + return (desc); } diff --git a/scripts/pkg b/scripts/pkg index d65a14b..e9465ef 100755 --- a/scripts/pkg +++ b/scripts/pkg @@ -1,6 +1,6 @@ #!/bin/bash -# pkg - Formilux package builder - version 0.5.0 - 2005-03-01 +# pkg - Formilux package builder - version 0.5.2 - 2005-03-25 # # Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau # mailto: benoit@ant-computing.com,willy@ant-computing.com @@ -883,7 +883,7 @@ function get_perl_depend { local dep DEP local DEP_FILE=$PKGDIR/compiled/$EXACTPKG-$FLXARCH.dep - DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9-_]*[; '\"]" $filename | \ + DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \ sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \ -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \ sed 's@::@/@g') @@ -1150,6 +1150,7 @@ function set_compiler_options { AS=${AS:-as} LD=${LD:-ld} AR=${AR:-ar} + RANLIB=${RANLIB:-ranlib} STRIP=${STRIP:-strip} OBJDUMP=${OBJDUMP:-objdump} @@ -1165,6 +1166,7 @@ function set_compiler_options { AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS} LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD} AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR} + RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB} STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP} OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP} fi diff --git a/signfs/AUTHORS b/signfs/AUTHORS new file mode 100644 index 0000000..0e11609 --- /dev/null +++ b/signfs/AUTHORS @@ -0,0 +1 @@ +Benoit Dolez <benoit@ant-computing.com> diff --git a/signfs/COPYING b/signfs/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/signfs/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/signfs/ChangeLog b/signfs/ChangeLog new file mode 100644 index 0000000..c8ceb94 --- /dev/null +++ b/signfs/ChangeLog @@ -0,0 +1,7 @@ +2001/12/23 : Version 0.3 +- add checking routing +2001/12/16 : Version 0.2 +- add -x flag to restrict to one filesystem +2001/10/29 : Version 0.1 +- first release + diff --git a/signfs/LICENCE b/signfs/LICENCE new file mode 120000 index 0000000..d24842f --- /dev/null +++ b/signfs/LICENCE @@ -0,0 +1 @@ +COPYING
\ No newline at end of file diff --git a/signfs/Makefile b/signfs/Makefile new file mode 100644 index 0000000..f50b301 --- /dev/null +++ b/signfs/Makefile @@ -0,0 +1,46 @@ +# +# SignFS : Tool to have an image of the filesystem +# +# Copyright (C) 1999-2001, Benoit Dolez <benoit@meta-x.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +# +# File: Makefile +# Version: 0.3 +# Date: Sun Dec 23 14:21:50 CET 2001 +# + + +NAME=signfs +SRC=main.c signfs.c structure.c +OBJ=$(SRC:.c=.o) +COPTS=-Os -march=i386 +CFLAGS=$(COPTS) -Wall +LDFLAGS=-L. -ltools +LIBTOOLS=md5.c libtools.c others.c + +$(NAME): libtools.a $(OBJ) + $(CC) -o $(NAME) $(OBJ) $(LDFLAGS) + #strip -R .note -R .comment signfs + +libtools.a: $(LIBTOOLS:.c=.o) + $(AR) -r libtools.a $(LIBTOOLS:.c=.o) + +clean: + @$(RM) -vf $(NAME) $(OBJ) $(LIBTOOLS:.c=.o) *~ libtools.a core *.bak + + diff --git a/signfs/README b/signfs/README new file mode 100644 index 0000000..8071296 --- /dev/null +++ b/signfs/README @@ -0,0 +1,20 @@ +signfs-0.1, October, 29 2001 +Initial release +---------------------------------------------------- +benoit@ant-computing.com + +INTRODUCTION +------------ +This package is need for formilux future distrib. + +DESCRIPTION +----------- + +REQUIREMENTS +------------- + +USAGE +----- +signfs [filename ...] +This command will show identity informations of any filenames or +current directory recursively. diff --git a/signfs/TODO b/signfs/TODO new file mode 100644 index 0000000..1f2d47d --- /dev/null +++ b/signfs/TODO @@ -0,0 +1,11 @@ +2002/01/20: + - '.' and '..' resolve? + +2001/12/24: + - need to correct all orthographic mistakes :-) + - make the binary capable to tell about its version + - clean the makefile and remove unused files + +2001/10/29: +- Need a complet documentation and manual + diff --git a/signfs/libtools.c b/signfs/libtools.c new file mode 100644 index 0000000..3464bfc --- /dev/null +++ b/signfs/libtools.c @@ -0,0 +1,1126 @@ +/* + * File: libtools.c + * Autors: Willy Tarreau <willy@ant-computing.com> + */ + +/* + * libtools.c : fonctions utilisees par les differents outils + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <time.h> +#include <sys/time.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include "libtools.h" + +#define CONFPARSE ConfParse + +#ifdef CONFPARSE +extern long int CONFPARSE(char *str); +#endif + +static char *loglevel_names[] = LOGLEVEL_NAMES; +static FILE *log = NULL; +unsigned int LogLevel = 0; + +typedef struct s_varlist t_varlist; +/* structure locale pour les variables */ +struct s_varlist { + char id[CONF_IDLEN]; + char *val; + t_varlist *next; +}; + +static t_varlist varlist = { "", NULL, NULL }; + + +/* Arreter avec un ABORT apres avoir affiche un message d'erreur sur STDERR. + * Cette fonction est de type int pour pouvoir etre inseree dans une expression. + * Elle ne retourne jamais. + */ +int Abort(char *fmt, ...) { + va_list argp; + struct timeval tv; + struct tm *tm; + + va_start(argp, fmt); + + gettimeofday(&tv, NULL); + tm=localtime(&tv.tv_sec); + fprintf(stderr, "[ABT] %03d %02d%02d%02d pid=%d, cause=", + tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec, getpid()); + vfprintf(stderr, fmt, argp); + fflush(stderr); + va_end(argp); + abort(); + return 0; // juste pour eviter un warning a la compilation +} + +/* cette fonction extrait la valeur numérique correspondant à la chaine ASCII + * de <nb> chiffres à la position <from> + */ +unsigned long Ascii2Long(char *from, int nb) { + unsigned long ret=0; + while (nb-- && *from) + ret=ret*10+(*from++-'0'); + return ret; +} + + +/* effectue un dump hexa de la structure pointee par <d>, a partir de la position + * <start> et pour <l> octets + */ +void LogDump(char *d, int start, int l) { + int i,j; + if (log == NULL) + Abort("Tentative d'ecriture dans un log non ouvert\n"); + + for (i=start & -16;i<start+l;i+=16) { + fprintf(log,"%04x: ",i); + for (j=0; j<16; j++) { + if ((i+j>=start) && (i+j<start+l)) + fprintf(log,"%02x ",(unsigned char)d[i+j]); + else + fprintf(log,".. "); + if (j==7) fprintf(log,"- "); + } + fprintf(log," "); + for (j=0; j<16; j++) { + if ((i+j>=start) && (i+j<start+l) && isprint(d[i+j])) + fputc(d[i+j],log); + else + fputc('.',log); + } + fputc('\n',log); + } + fflush(log); +} + + +/* effectue un dump de la structure pointee par <d>, a partir de la position + * <start> et pour <l> octets + */ +void RawDump(char *d, int start, int l) { + if (log == NULL) + Abort("Tentative d'ecriture dans un log non ouvert\n"); + + fwrite(d+start,l,1,log); +} + +/* + * ouvre un log vers le fichier <file> en niveau <lev>. + * Si <file> est NULL, le log est envoyé vers <stderr>. + * Le fichier est créé s'il n'existe pas. Dans les cas contraire, les données + * sont ajoutées à la fin. + * Pour le niveau de log, voir l'explication dans la fonction LogSetLevel() + * ci-dessous. + */ +void LogOpen(char *file, unsigned int lev) { + FILE *oldlog=log; + + if (oldlog == stderr && file != NULL) { + int oldlevel; + oldlevel=LogSetLevel(LOG_LALL, LOG_LSTAT); + Log(LOG_LSTAT,"Redirection des logs vers le fichier <%s>.\n", file); + LogSetLevel(LOG_LNONE, oldlevel); + } + else if (oldlog != NULL && log != stderr) { + int oldlevel; + oldlevel=LogSetLevel(LOG_LALL, LOG_LSTAT); + Log(LOG_LWARN|LOG_LSTAT,"!!!!!!! Attention : reouverture du log dans le fichier <%s>.\n", file); + LogSetLevel(LOG_LNONE, oldlevel); + fclose(oldlog); + } + if (file == NULL || ((log=fopen(file, "a+")) == NULL)) + log=stderr; /* si on ne peut pas ouvrir le log, on envoie sur stderr */ + + LogLevel = lev; + + if (log != NULL && log != stderr) { + char logstr[32*4+1+1], *p; + int l,printed=0,oldlevel; + p=logstr; + *p++='['; + for (l=0; l<32; l++) { + if (LogLevel & (1<<l)) { + if (printed++) + *p++=','; + strncpy(p, loglevel_names[l], (logstr+sizeof(logstr)-p)); + p+=strlen(p); + } + } + *p++=']'; *p++=0; + + oldlevel=LogSetLevel(LOG_LALL, LOG_LSTAT); + Log(LOG_LSTAT,"########### ouverture du log, pid %d, %s %s ##############\n", + getpid(), + printed?(printed==1?"niveau":"niveaux"):"AUCUN NIVEAU ACTIF", printed?logstr:""); + LogSetLevel(LOG_LNONE, oldlevel); + } + if (file != NULL && log == stderr) + Log(LOG_LERR,"!!!!!!! Erreur sur l'ouverture du fichier de log <%s>.\n",file); +} + +/* ferme le log */ +void LogClose() { + if (log != NULL && log != stderr) + fclose(log); +} + +/* change le niveau de trace. Effectue un ET logique sur le niveau courant puis un OU logique. + * Exemples : + * LogSetLevel(0, LOGLSOCKET); => ne logue que les sockets + * LogSetLevel(-1, LOGLSOCKET); => ajoute les logs de sockets aux logs courants + * LogSetLevel( ~LOGLSOCKET, 0); => supprime les logs de sockets des logs courants + * LogSetLevel( ~LOGLMEMORY, LOGLFILE); => supprime les logs memoire et ajoute les logs fichiers + * On retourne le niveau précédent; + */ +int LogSetLevel(int and, int or) { + int oldlevel; + LogLevel = ((oldlevel=LogLevel) & and) | or; + return oldlevel; +} + +/* + * envoie une trace au format de printf(). + * Ce log n'est affiché que si le niveau passé en paramètre correspond au niveau courant. + * Si le niveau LOGLPID est actif, le pid est préfixé. Si le niveau LOGLDATE + * est actif, la date est préfixée. + * La sortie subit toujours un fflush() avant le retour. + * on retourne toujours 0, juste pour pouvoir inserer la fonction dans une expression. + */ +int Log(int level, const char *fmt, ...) { + va_list argp; + struct timeval tv; + struct tm *tm; + char logstr[2048], *p; + + if ((level & (LogLevel | LOG_LFATAL)) == 0) + return 0; + + *(p=logstr)='\0'; + va_start(argp, fmt); + if (log) { + int l,printed=0; + *p++='['; + for (l=0; l<32; l++) { + if ((level & (LogLevel)) & (1<<l)) { + if (printed++) + *p++=','; + strncpy(p, loglevel_names[l], (logstr+sizeof(logstr)-p)); + p+=strlen(p); + } + } + *p++=']'; + gettimeofday(&tv, NULL); + tm=localtime(&tv.tv_sec); +#ifdef HAVE_SNPRINTF + snprintf(p, (logstr+sizeof(logstr)-p), " %03d %02d%02d%02d.%03d ", tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec, + ((tv.tv_usec)/1000)%1000); +#else + sprintf(p, " %03d %02d%02d%02d.%03ld ", tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec, ((tv.tv_usec)/1000)%1000); +#endif + p+=strlen(p); + } +#ifdef HAVE_SNPRINTF + vsnprintf(p, (logstr+sizeof(logstr)-p), fmt, argp); +#else + vsprintf(p, fmt, argp); +#endif + write(fileno(log?log:stderr), logstr, strlen(logstr)); + va_end(argp); + return 0; +} + + +/**************************************************************\ + * + * Outils de gestion de configuration + * +\**************************************************************/ + + +/* recherche d'une variable par son nom d'identificateur. + Le pointeur sur la structure est donné en retour. Si le nom n'est pas trouvé, + NULL est retourné. +*/ + +static t_varlist *ptrvar(char *name) { + t_varlist *p; + + p=varlist.next; + while (p) { + if (!strcmp(p->id,name)) + return p; + p=p->next; + } + return NULL; +} + +/* + * Lecture du fichier de configuration dont le nom est passé dans <name>. + * Le contenu de ce fichier est ajouté à la configuration existante. + * On retourne le nombre d'erreurs rencontrées. + */ +int ConfRead(char *name) { + char *p; + FILE *cnf; + char ligne[CONF_LINELEN]; + char tmpval[256]; + int err=0; + + if ((cnf=fopen(name, "r"))==NULL) { + Log(LOG_LWARN, "Impossible d'ouvrir le fichier de configuration <%s>.\n",name); + return -1; + } + + while (ConfReadLine(cnf, ligne, CONF_LINELEN)) { + if ((p=strchr(ligne,'=')) != NULL) { + *p++=0; + ConfDvlpStr(tmpval,p,sizeof(tmpval)); + ConfSetStr(ligne,tmpval); + } + else { + Log(LOG_LERR, "Erreur de syntaxe dans le fichier de configuration <%s>, près de <%s>.\n", name, ligne); + err++; + } + } + fclose(cnf); + return err; +} + + +/* lecture d'une ligne NON VIDE dans le fichier <file>. Celle-ci est + stockée dans <ligne>, d'une longueur maximale <len>, et la valeur + retournée est le pointeur sur cette chaine. A la fin du fichier, + <ligne> est vidée et la valeur retournée est NULL. + Les lignes commencant par ';' ou '#' ne sont pas retournées. +*/ +char *ConfReadLine(FILE *file, char *ligne, int len) { + char *ret; + + /* recherche la prochaine ligne non vide */ + do { + if ((ret=fgets(ligne, len, file)) == NULL) + break; + /* passe tous les premiers séparateurs */ + while (/* *ret &&*/ (*ret==' ' || *ret == '\t' || *ret=='\n' || *ret=='\r')) + ret++; + if (*ret=='#' || *ret==';') + *ret=0; /* marque la fin immédiate */ + } while (!*ret); + + if (!ret) { /* fin de fichier */ + *ligne='\0'; + return NULL; + } + + /* suppression des sauts de lignes et retours inutiles en fin de ligne */ + ret=ligne+strlen(ligne)-1; + while (ret>=ligne && (*ret=='\r' || *ret=='\n')) + *ret--=0; + + return ligne; +} + + +/* affecte la valeur <val> à la variable <id>. + * Si la variable n'existe pas, elle est créée. + */ +void ConfSetStr(char *id, char *val) { + t_varlist *p; + + if ((p=ptrvar(id)) == NULL) { /* nouvelle variable */ + if ((p=malloc(sizeof(t_varlist)))==NULL) + Abort("setvar():malloc()"); + strcpy0(p->id,id); + p->val=NULL; + /* insertion dans la liste */ + p->next=varlist.next; + varlist.next=p; + } + if (p->val) free(p->val); + p->val=(char *)malloc(strlen(val)+1); + strcpy(p->val,val); +} + +/* affecte la valeur entiere <val> à la variable <id>. + * Si la variable n'existe pas, elle est créée. + */ +void ConfSetInt(char *id, long int val) { + char entier[32]; + sprintf(entier,"%ld",val); + ConfSetStr(id,entier); +} + +/* retourne la valeur de la variable ou de la var d'environnement ou "" */ +char *ConfGetStr(char *id) { + t_varlist *p; + char *v; + + /*printf("demande de la variable <%s> : ",id);*/ + if ((p=ptrvar(id)) != NULL) + v=p->val; + else if (!(v=getenv(id))) { + v=""; + } + return v; +} + +/* retourne la valeur entiere de la variable (interne ou env) ou 0 */ +long int ConfGetInt(char *id) { +#ifdef CONFPARSE + return CONFPARSE(ConfGetStr(id)); +#else + return atol(ConfGetStr(id)); +#endif +} + +/* développe une chaine de caractères contenant des variables sous la forme $(var) en une + chaine dans laquelle les variables sont remplacées par leur valeur. La chaine de résultat + fera au plus <lmax> caractères. +*/ + +char *ConfDvlpStr(char *out, char *in, int lmax) { + char *res; + char *p1, *p2; + char var[CONF_LINELEN]; + char tmpvar[CONF_LINELEN]; + int pardepth; + + res=out; + while (lmax && *in) { + while (lmax && *in && (*in!='$')) + *out++=*in++; + if (*in=='$') { + switch (*++in) { + case '$' : /* certains caractères sont réservés. C'est donc un code escape */ + if (lmax) { + *out++=*in++; + lmax--; + } + break; + case '(' : /* parenthese : c'est une variable */ + p1=++in; + pardepth=1; + while (*in && ((*in != ')') || (pardepth>1)) && (in-p1+1<sizeof(var))) { + if (*in == ')') + pardepth--; + else if (*in == '(') + pardepth++; + in++; + } + strncpy0(var,p1,in-p1); /* verifier la longueur .... */ + /*var[in-p1]=0;*/ + p2=ConfGetStr(ConfDvlpStr(tmpvar,var,sizeof(tmpvar))); /* le nom de la variable peut etre variable lui-meme */ + if (strlen(p2)>lmax) { + strncpy(out,p2,lmax); + *(out+=lmax)=0; + } + else { + strcpy(out,p2); + *(out+=strlen(p2))=0; + } + if (*in) in++; /* passe la parenthese fermante */ + break; + case '{' : /* accolade : commande */ + p1=++in; + while (*in && (*in!='}') && (in-p1+1<sizeof(var))) + in++; + strncpy0(var,p1,in-p1); /* verifier la longueur .... */ + /*var[in-p1]=0;*/ + /* mettre dans p2 le resultat de la commande nommée par <var> */ + p2=ConfGetStr(var); + if (strlen(p2)>lmax) { + strncpy(out,p2,lmax); + *(out+=lmax)=0; + } + else { + strcpy(out,p2); + *(out+=strlen(p2))=0; + } + if (*in) in++; /* passe l'accolade fermante */ + break; + default : /* autre: non traite */ + if (lmax) { *out++='$'; lmax--; } + if (lmax) { *out++=*in; lmax--; } + } + } + } + *out=0; + return res; +} + + +/******************************************************************** + * fonctions d'analyse et de résolution d'expressions arithmétiques * + ********************************************************************/ + + +#define PARSESTR ConfGetStr + +#define NEXTCHAR(a) ((*a)++) +#define PREVCHAR(a) ((*a)--) + +#ifdef PARSESTR +extern char *PARSESTR(char *); +#endif + +enum { + OP_SL=1, OP_LE, OP_LT, + OP_SR, OP_GE, OP_GT, + OP_EQ, OP_LG, + OP_NE, OP_NL, OP_NG, + OP_QN, OP_CO, + OP_BO, OP_LO, + OP_BA, OP_LA, + OP_BX, OP_LX, + OP_PW, OP_MU, OP_DI, + OP_MI, OP_PL, + OP_NO, OP_CP +}; + +static int expression(char **arg); + +#ifndef HAVE_INTPOW +static int intpow(a,b) { + int c=1; + if (b>0) { + while (b--) + c*=a; + return c; + } + else if (b==0) + return 1; + else + return a==1; /* (1/a^n = 1) if (a==1), else 0 */ +} +#endif + +static int readchar(char **arg, int c) { + if (c==**arg) { + NEXTCHAR(arg); + return 1; + } + else + return 0; +} + +static int readalnum(char **arg) { + if (isalnum(**arg) || (**arg=='_') || (**arg=='.')) { + NEXTCHAR(arg); + return 1; + } + else + return 0; +} + +static int readnum(char **arg) { + if (isdigit(**arg)) { + NEXTCHAR(arg); + return 1; + } + else + return 0; +} + +static int readspace(char **arg) { + if (isspace(**arg)) { + NEXTCHAR(arg); + return 1; + } + else + return 0; +} + +static int readany(char **arg) { + if (**arg==0) + return 0; + NEXTCHAR(arg); + return 1; +} + +static int readeol(char **arg) { + if (**arg=='\n') { + NEXTCHAR(arg); + return 1; + } + else + return 0; +} + +/* skips all consecutive comments and spaces. returns no-zero if at least one comment was read */ +static int skipcomments(char **arg) { + int comm=0; + while (readspace(arg)); + while (**arg=='#') { + while (!readeol(arg)) + readany(arg); + while (readspace(arg)); + comm=1; + } + return comm; +} + +/* returns the work read */ +static char *readword(char **arg) { + static char token[100]; + int tklen=0; + + skipcomments(arg); + while (readalnum(arg) && (tklen<sizeof(token)-1)) + token[tklen++]=*(*arg-1); + token[tklen]=0; + return token; +} + +static int fetch(char **arg, int c) { + skipcomments(arg); + return readchar(arg,c); +} + +/* returns 1 if the token can be fetched, otherwise 0. */ +static int fetchstr(char **arg, char *tok) { + char *newarg=*arg; + while (*tok && *newarg==*tok) { + newarg++; + tok++; + } + /* not everything matched */ + if (*tok) + return 0; + /* everything matched so let's update arg */ + *arg=newarg; + return 1; +} + + +/* returns 1 if the operator can be fetched, otherwise 0. */ +static int fetchop(char **arg, int op) { + char *oldarg=*arg; + int ret; + /* it's important to match first the longest operators to avoid prefixes collision */ + + if (fetch(arg,'+')) + ret = op==OP_PL; + else if (fetch(arg,'/')) + ret = op==OP_DI; + else if (fetch(arg,'-')) + ret = op==OP_MI; + else if (fetch(arg,'~')) + ret = op==OP_CP; + else if (fetch(arg,'?')) + ret = op==OP_QN; + else if (fetch(arg,':')) + ret = op==OP_CO; + else if (fetch(arg,'<')) { /* <<, <=, <>, < */ + if (fetch(arg,'=')) + ret = op==OP_LE; + else if (fetch(arg,'<')) + ret = op==OP_SL; + else if (fetch(arg,'>')) + ret = op==OP_LG; + else + ret = op==OP_LT; + } + else if (fetch(arg,'>')) { /* >>, >=, > */ + if (fetch(arg,'=')) + ret = op==OP_GE; + else if (fetch(arg,'>')) + ret = op==OP_SR; + else + ret = op==OP_GT; + } + else if (fetch(arg,'!')) { /* !<, !>, !=, ! */ + if (fetch(arg,'<')) + ret = op==OP_NL; + else if (fetch(arg,'>')) + ret = op==OP_NG; + else if (fetch(arg,'=')) + ret = op==OP_NE; + else + ret = op==OP_NO; + } + else if (fetch(arg,'|')) { /* ||, | */ + if (fetch(arg,'|')) + ret = op==OP_BO; + else + ret = op==OP_LO; + } + else if (fetch(arg,'^')) { /* ^^,^ */ + if (fetch(arg,'^')) + ret = op==OP_BX; + else + ret = op==OP_LX; + } + else if (fetch(arg,'&')) { /* &&, & */ + if (fetch(arg,'&')) + ret = op==OP_BA; + else + ret = op==OP_LA; + } + else if (fetch(arg,'*')) { /* **, * */ + if (fetch(arg,'*')) + ret = op==OP_PW; + else + ret = op==OP_MU; + } + else if (fetchstr(arg,"==")) + ret = op==OP_EQ; + else + ret = 0; + + if (!ret) + *arg=oldarg; /* operator not matched */ + return ret; +} + +static int terme(char **arg) { + int a; + if (fetchop(arg, OP_MI)) + a=-terme(arg); + else if (fetchop(arg, OP_CP)) + a=~terme(arg); + else { + if (fetch(arg, '(')) { + a=expression(arg); + fetch(arg, ')'); + } + else if (isdigit(**arg)) + a=atol(readword(arg)); + else +#ifdef PARSESTR + a=ConfParse(PARSESTR(readword(arg))); +#else + a=0; +#endif + + if (fetchop(arg, OP_PW)) /* exponentiation */ + a=intpow(a,terme(arg)); + } + return a; +} + +static int produit(char **arg) { + int a,b; + a=terme(arg); + do { + if (fetchop(arg, OP_MU)) { + a*=terme(arg); + } + else if (fetchop(arg, OP_DI)) { + b=terme(arg); + if (b) + a/=b; + else + a=0; /* dividing anything by 0 will always return 0 */ + } + else + break; + } while (1); + return a; +} + + +static int shifter(char **arg) { + int a; + a=produit(arg); + do { + if (fetchop(arg, OP_SL)) + a<<=produit(arg); + else if (fetchop(arg, OP_SR)) + a>>=produit(arg); + else + break; + } while (1); + return a; +} + +static int log_conj(char **arg) { + int a; + a=shifter(arg); + while (fetchop(arg, OP_LA)) + a&=shifter(arg); + return a; +} + +static int log_disj(char **arg) { + int a; + a=log_conj(arg); + do { + if (fetchop(arg, OP_LO)) + a|=log_conj(arg); + else if (fetchop(arg, OP_LX)) + a^=log_conj(arg); + else + break; + } while (1); + return a; +} + +static int somme(char **arg) { + int a; + a=log_disj(arg); + do { + if (fetchop(arg, OP_PL)) + a+=log_disj(arg); + else if (fetchop(arg, OP_MI)) + a-=log_disj(arg); + else + break; + } while (1); + return a; +} + +static int comp(char **arg) { + int a; + a=somme(arg); + do { + if (fetchop(arg, OP_EQ)) + a=(a==somme(arg)); + else if (fetchop(arg, OP_LE) || fetchop(arg, OP_NG)) + a=(a<=somme(arg)); + else if (fetchop(arg, OP_GE) || fetchop(arg, OP_NL)) + a=(a>=somme(arg)); + else if (fetchop(arg, OP_LG) || fetchop(arg, OP_NE)) + a=(a!=somme(arg)); + else if (fetchop(arg, OP_LT)) + a=(a<somme(arg)); + else if (fetchop(arg, OP_GT)) + a=(a>somme(arg)); + else + break; + } while (1); + return a; +} + +static int boolean(char **arg) { + if (fetchop(arg, OP_NO)) + return !boolean(arg); + else + return comp(arg); +} + + +static int bool_conj(char **arg) { + int a; + a=boolean(arg); + while (fetchop(arg, OP_BA)) + a = a && boolean(arg); + return a; +} + +static int bool_disj(char **arg) { + int a; + a=bool_conj(arg); + do { + if (fetchop(arg, OP_BO)) + a = a || bool_conj(arg); + // else if (fetchop(arg, OP_BX)) + // a = a ^^ bool_conj(arg); + else + break; + } while (1); + return a; +} + + +static int expression(char **arg) { + int cond, exp1, exp2; + cond=bool_disj(arg); + if (fetchop(arg, OP_QN)) { + if (fetchop(arg, OP_CO)) { /* missing expr means keep cond if true */ + exp1=cond; + exp2=expression(arg); + } + else { + exp1=expression(arg); + if (fetchop(arg, OP_CO)) + exp2=expression(arg); + else + exp2=0; /* missing colon means 0 */ + } + return cond ? exp1 : exp2; + } + else + return cond; +} + +/**** la seule fonction exportée ****/ +long int ConfParse(char *arg) { + return expression(&arg); +} +#undef PARSESTR +#undef NEXTCHAR +#undef PREVCHAR + + +/********************************************************** + * fonctions de traitements sur les chaines de caractères * + **********************************************************/ + +/* strncpy avec 0 final. src peut etre NULL. + Attention: <lmax> caracteres sont copiés, et un zéro terminal est + ajouté APRES. <dest> doit donc pouvoir accepter lmax+1 caractères. +*/ + +char *strncpy0(char *dest, const char *src, int lmax) { + register char *p; + p=dest; + if (src) + while (lmax-- && (*p++=*src++)); + *p=0; + return dest; +} + + +/* retourne un pointeur sur la chaine S tronquée à l caractères maximum */ +char *strcut(char *s, int l) { + char *p=s; + + while (*p && l) { + p++; l--; + } + *p=0; + return s; +} + +static char base64tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static int char64to6bits(char c) { + return (c=='/'?63: + c=='+'?62: + (c>='0' && c<='9')?(c-'0'+52): + (c>='a' && c<='z')?(c-'a'+26): + (c>='A' && c<='Z')?(c-'A'+0): + 0); +} + +/* WARNING !!! no boundary checking is done. The caller *MUST* have enough + * space to store the result : outsize = (insize+3)*4/3 + */ +char *asciitobase64(char *ascii, char *base64) { + char *dest=base64; + while (ascii[0] && ascii[1] && ascii[2]) { + *dest++=base64tab[(ascii[0]>>2) & 0x3f]; + *dest++=base64tab[(ascii[0] & 0x03)<<4 | ((ascii[1] >> 4) & 0x0f)]; + *dest++=base64tab[(ascii[1] & 0x0f)<<2 | ((ascii[2] >> 6) & 0x03)]; + *dest++=base64tab[(ascii[2] & 0x3f)]; + ascii+=3; + } + /* only 0, 1 or 2 bytes left */ + if (*ascii) { /* 1 or 2 bytes left */ + *dest++=base64tab[(ascii[0]>>2) & 0x3f]; + if (!ascii[1]) /* 1 byte left */ + *dest++=base64tab[(ascii[0] & 0x03)<<4]; + else { /* 2 bytes left */ + *dest++=base64tab[(ascii[0] & 0x03)<<4 | ((ascii[1] >> 4) & 0x0f)]; + *dest++=base64tab[(ascii[1] & 0x0f)<<2]; + } + *dest++='='; + } + *dest++=0; + return base64; +} + +/* WARNING !!! no boundary checking is done. The caller *MUST* have enough + * space to store the result : outsize = (insize+2)/3*4 + 1 (zero) + */ +char *asciintobase64(char *ascii, int len, char *base64) { + char *dest=base64; + + while (len>2) { + *dest++=base64tab[((unsigned)ascii[0]>>2) & 0x3f]; + *dest++=base64tab[((unsigned)ascii[0] & 0x03)<<4 | (((unsigned)ascii[1] >> 4) & 0x0f)]; + *dest++=base64tab[((unsigned)ascii[1] & 0x0f)<<2 | (((unsigned)ascii[2] >> 6) & 0x03)]; + *dest++=base64tab[((unsigned)ascii[2] & 0x3f)]; + ascii+=3; + len-=3; + } + + /* only 0, 1 or 2 bytes left */ + if (len>0) { /* 1 or 2 bytes left */ + *dest++=base64tab[((unsigned)ascii[0]>>2) & 0x3f]; + if (len==1) /* 1 byte left */ + *dest++=base64tab[((unsigned)ascii[0] & 0x03)<<4]; + else { /* 2 bytes left */ + *dest++=base64tab[((unsigned)ascii[0] & 0x03)<<4 | (((unsigned)ascii[1] >> 4) & 0x0f)]; + *dest++=base64tab[((unsigned)ascii[1] & 0x0f)<<2]; + } + *dest++='='; + } + *dest++=0; + return base64; +} + +/* WARNING !!! no boundary checking is done. The caller *MUST* have enough + * space to store the result : outsize = insize*3/4 + * an empty string correctly returns an empty string. + */ +char *base64toascii(char *ascii, char *base64) { + int i,j; + char *p=ascii; + + do { + for (i=4,j=0;i>0;i--) { + if (*base64=='=' || *base64==0) /* fin */ { + j<<=(6*i); + break; + } + j=(j<<6)|char64to6bits(*base64++); + } + if (i!=4) { /* au moins un caractere lu ? */ + *p++=(j>>16)&255; + if (i!=2) { /* le deuxieme octet est renseigne */ + *p++=(j>>8)&255; + if (i!=1) { /* le troisieme octet est renseigne */ + *p++=(j)&255; + } + } + } + } while (!i); /* tant que i est nul, on a lu 4 caracteres donc 3 octets */ + *p++=0; /* fin de chaine forcee */ + return ascii; +} + +/* reads a string of the form "var=val; var=val; ..." and extracts the desired + "var" specified in <token>. The corresponding "val" is copied into <to> for + at most <len> chars, including the ending 0. The result is <to>, or NULL if + token not found, and <to> is set to an empty string. +*/ +char *extracttoken(const char *from, const char *token, char *to, int len) { + char *s; + s=(char *)from; + *to=0; + while (1) { + if ((s=strstr(s, token)) == NULL) + return NULL; + s+=strlen(token); + if (*s != '=') { + while(*s && !isspace(*s) && (*s!=';')) + s++; + while(*s && (isspace(*s) || (*s!=';'))) + s++; + } + else { + char *t=to; + s++; + while(*s && !isspace(*s) && (*s!=';') && len-->1) + *t++=*s++; + *t++=0; + return to; + } + } +} + +/* + * calculations on timeval structs. Integers are milliseconds. + */ + +/* sets <tv> to the current time */ +struct timeval *tv_now(struct timeval *tv) { + if (tv) + gettimeofday(tv, NULL); + return tv; +} + +/* returns a statically allocated struct timeval initialized with <ms> ms */ +struct timeval *tv_ms(int ms) { + static struct timeval tv; + tv.tv_usec = (ms%1000)*1000; + tv.tv_sec = (ms/1000); + return &tv; +} + +/* adds <ms> ms to tv and returns a pointer to the newly filled struct */ +struct timeval *tv_delay(struct timeval *tv, int ms) { + if (!tv) + return NULL; + tv->tv_usec += (ms%1000)*1000; + tv->tv_sec += (ms/1000); + if (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } + return tv; +} + +/* adds <ms> ms to <from>, set the result to <tv> and returns a pointer <tv> */ +struct timeval *tv_delayfrom(struct timeval *tv, struct timeval *from, int ms) { + if (!tv || !from) + return NULL; + tv->tv_usec = from->tv_usec + (ms%1000)*1000; + tv->tv_sec = from->tv_sec + (ms/1000); + while (tv->tv_usec >= 1000000) { + tv->tv_usec -= 1000000; + tv->tv_sec++; + } + return tv; +} + +/* copies <from> to <tv> and returns a pointer <tv> */ +struct timeval *tv_set(struct timeval *tv, struct timeval *from) { + if (!tv || !from) + return NULL; + tv->tv_usec = from->tv_usec; + tv->tv_sec = from->tv_sec; + return tv; +} + +/* sets tv to now + <ms> ms, and returns a pointer to the newly filled struct */ +struct timeval *tv_wait(struct timeval *tv, int ms) { + if (!tv) + return NULL; + gettimeofday(tv, NULL); + tv_delay(tv, ms); + return tv; +} + +/* compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2 */ +int tv_cmp(struct timeval *tv1, struct timeval *tv2) { + if (tv1->tv_sec > tv2->tv_sec) + return 1; + else if (tv1->tv_sec < tv2->tv_sec) + return -1; + else if (tv1->tv_usec > tv2->tv_usec) + return 1; + else if (tv1->tv_usec < tv2->tv_usec) + return -1; + else return 0; +} + +/* returns 1 if <tv> is in the past (means tv<=gettimeofday()) or 0 if not) */ +int tv_past(struct timeval *tv) { + struct timeval now; + gettimeofday(&now, NULL); + if ( tv_cmp(tv, &now) <= 0 ) + return 1; + else + return 0; +} + +/* returns the absolute difference, in ms, between tv1 and tv2 */ +unsigned long tv_delta(struct timeval *tv1, struct timeval *tv2) { + int cmp; + unsigned long ret; + + + cmp=tv_cmp(tv1, tv2); + if (!cmp) + return 0; /* same dates, null diff */ + else if (cmp<0) { + struct timeval *tmp=tv1; + tv1=tv2; + tv2=tmp; + } + ret=(tv1->tv_sec - tv2->tv_sec)*1000; + if (tv1->tv_usec > tv2->tv_usec) + ret+=(tv1->tv_usec - tv2->tv_usec)/1000; + else + ret-=(tv2->tv_usec - tv1->tv_usec)/1000; + return (unsigned long) ret; +} diff --git a/signfs/libtools.h b/signfs/libtools.h new file mode 100644 index 0000000..e27f63b --- /dev/null +++ b/signfs/libtools.h @@ -0,0 +1,104 @@ +/* + * File: libtools.c + * Autors: Willy Tarreau <willy@ant-computing.com> + */ + +/* + * libtools.h : definition des macros et fonctions utilisees par les differents outils + */ +#ifndef _LIBTOOLS_H +#define _LIBTOOLS_H + +#include <stdio.h> + +/* + * macros spécifiques aux logs + */ + +/* définition des niveaux de log : ces flags peuvent etre combines par un "ou logique" + * lors de l'appel de log_open() ou de log_setlevel(). + */ +#define LOG_LALL (~0) +#define LOG_LNONE (0) + +#define LOG_LFATAL (1<<0) +#define LOG_LERR (1<<1) +#define LOG_LWARN (1<<2) +#define LOG_LSTAT (1<<3) +#define LOG_LFUNC (1<<4) +#define LOG_LPERF (1<<5) +#define LOG_LDEBUG (1<<6) +#define LOG_LAPP (1<<7) +#define LOG_LSEC (1<<8) +#define LOG_LOPEN (1<<26) +#define LOG_LCLOSE (1<<27) +#define LOG_LFILE (LOG_LOPEN | LOG_LCLOSE) +#define LOG_LMALLOC (1<<28) +#define LOG_LFREE (1<<29) +#define LOG_LMEMORY (LOG_LMALLOC | LOG_LFREE) +#define LOG_LSOCKET (1<<30) +#define LOG_LCONNECT (1<<31) + +#define LOGLEVEL_NAMES {"FTL","ERR","WRN","STA","FNC","PRF","DBG","APP", \ + "","","","","","","","",\ + "","","","","","","","",\ + "", "","OPN","CLO","ALC","FRE","SKT","CON"} + +/* imprime un log sur la position courante dans le fichier sous la forme "@<fichier:ligne>\n" */ +#define LOG_DEBUG Log(LOG_LDEBUG,"DBG <%s:%d>\n", __FILE__, __LINE__) + + +/* + * Gestion des variables de configuration + */ + +/* longueur maximale d'un identifiant */ +#define CONF_IDLEN 50 +#define CONF_LINELEN 256 + + +/* + * Traitements sur des chaines + */ + +/* copie avec contrôle de bornes et ajout du zero terminal */ +#define strcpy0(a,b) strncpy0(a,b,sizeof(a)-1) + +/* + * symboles définis dans libtools.c + */ +extern unsigned int LogLevel; + +int Abort(char *fmt, ...); +unsigned long Ascii2Long(char *from, int nb); +void LogDump(char *d, int start, int l); +void RawDump(char *d, int start, int l); +void LogOpen(char *file, unsigned int lev); +void LogClose(); +int LogSetLevel(int and, int or); +int Log(int level, const char *fmt, ...); +int ConfRead(char *name); +char *ConfReadLine(FILE *file, char *ligne, int len); +void ConfSetStr(char *id, char *val); +void ConfSetInt(char *id, long int val); +char *ConfGetStr(char *id); +long int ConfGetInt(char *id); +char *ConfDvlpStr(char *out, char *in, int lmax); +long int ConfParse(char *arg); +char *strncpy0(char *dest, const char *src, int lmax); +char *strcut(char *s, int l); +char *base64toascii(char *ascii, char *base64); +char *asciitobase64(char *ascii, char *base64); +char *asciintobase64(char *ascii, int len, char *base64); +char *extracttoken(const char *from, const char *token, char *to, int len); +struct timeval *tv_delay(struct timeval *tv, int ms); +struct timeval *tv_wait(struct timeval *tv, int ms); +int tv_cmp(struct timeval *tv1, struct timeval *tv2); +int tv_past(struct timeval *tv); +unsigned long tv_delta(struct timeval *tv1, struct timeval *tv2); +struct timeval *tv_ms(int ms); +struct timeval *tv_delayfrom(struct timeval *tv, struct timeval *from, int ms); +struct timeval *tv_now(struct timeval *tv); +struct timeval *tv_set(struct timeval *tv, struct timeval *from); + +#endif /* _LIBTOOLS_H */ diff --git a/signfs/main.c b/signfs/main.c new file mode 100644 index 0000000..24920fa --- /dev/null +++ b/signfs/main.c @@ -0,0 +1,166 @@ +/* + * SignFS : Tool to have an image of the filesystem + * + * Copyright (C) 1999-2001, Benoit Dolez <benoit@meta-x.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * File: main.c + * Object: Signing filesystem + * Version: 0.5 + * Date: Sun Dec 23 14:21:50 CET 2001 + */ + + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "signfs.h" +#include "others.h" + +int CheckMode=0,Argc; +char *source_filename=0,**Argv; +int SingleFileSystem=0,NoDate=0,ShowDiff=0,Show=0xffff,HumanReadable=0; +char *Checkit=NULL; +char *BaseFS=NULL,*BaseFile=NULL,*BaseStrip=NULL; +int CurrentDir=1,OutputLevel=0; +char *Output=NULL; + +int read_param(int argc, char **argv, char ***list) { + int ignore=0,show=0xffff-SHOW_OTHERS; + + Argc=argc; Argv=argv; + ++argv; + while (argc > 1) { + if (**argv == '-') { + if (*(*argv+1) == '-') { + if (!strcmp(*argv+2,"")) break; + if (!strcmp(*argv+2,"help")) return (-1); + else if (!strcmp(*argv+2,"strip")) + if (*(argv+1)) BaseStrip=*(argc--,++argv); + else return (-1); + else if (!strcmp(*argv+2,"base")) + if (*(argv+1)) BaseFile=*(argc--,++argv); + else return (-1); + else if (!strcmp(*argv+2,"root")) + if (*(argv+1)) BaseFS=*(argc--,++argv); + else return (-1); + else if (!strcmp(*argv+2,"check")) ShowDiff=0xffff; + else if (!strcmp(*argv+2,"ignore-perm")) ignore|=(FLAG_MODE|FLAG_UID|FLAG_GID); + else if (!strcmp(*argv+2,"ignore-date")) ignore|=FLAG_MTIME; + else if (!strcmp(*argv+2,"ignore-check")) ignore|=FLAG_MD5SUM; + else if (!strcmp(*argv+2,"ignore-size")) ignore|=FLAG_SIZE; + else if (!strcmp(*argv+2,"ignore-link")) ignore|=FLAG_LINK; + else if (!strcmp(*argv+2,"new-only")) { show-=SHOW_OLD; show|=SHOW_NEW ; } + else if (!strcmp(*argv+2,"old-only")) { show-=SHOW_NEW; show|=SHOW_OLD ; } + else if (!strcmp(*argv+2,"show-all")) { show|=SHOW_ALL ; } + else if (!strcmp(*argv+2,"human-readable")) { HumanReadable=1 ; } + else if (!strcmp(*argv+2,"output-level")) { + if (*(argv+1)) OutputLevel=atoi(*(argc--,++argv)); + else return (-1); + } + else return (-1); + } + else if (!strcmp(*argv+1,"h")) return (-1); + else if (!strcmp(*argv+1,"o")) + if (*(argv+1)) Output=*(argc--,++argv); + else return (-1); + else if (!strcmp(*argv+1,"b")) + if (*(argv+1)) BaseFile=*(argc--,++argv); + else return (-1); + else if (!strcmp(*argv+1,"r")) + if (*(argv+1)) BaseFS=*(argc--,++argv); + else return (-1); + else if (!strcmp(*argv+1,"c")) ShowDiff=0xffff; + else if (!strcmp(*argv+1,"f")) + if (argv+1 && *(argv+1)) + source_filename=*(argc--,CheckMode=1,++argv); + else return (-1); + else if (!strcmp(*argv+1,"x")) SingleFileSystem=1; + else { + printf("Bad option: %s\n",*argv); + return (-1); + } + } else { + break; + } + argc--; + ++argv; + } + *list=argv; + Show=show; + ShowDiff &= ~ignore; + return (argc); +} + +int syntax() { + printf("signfs-0.5, copyright Benoit DOLEZ <benoit@ant-computing.com>\n"); + printf("Usage %s [options] [file] ...\n",Argv[0]); + printf(" -x : only designed file system\n"); + printf(" -b <dir> : base during file reading\n"); + printf(" -r <dir> : base during directory reading\n"); + printf(" --base <dir> : base during file reading\n"); + printf(" --root <dir> : base during directory reading\n"); + printf(" --strip <dir> : base during showing result\n"); + printf(" -c --check : check consistancy (use with -f)\n"); + printf(" -f <file> : read old map from file ('-' for stdin)\n"); + printf(" -h --help : this help\n"); + printf(" --ignore-date : ignore date (use with -c)\n"); + printf(" --ignore-check : ignore checksum (use with -c)\n"); + printf(" --ignore-perm : ignore perm (mode and owner) (use with -c)\n"); + printf(" --ignore-size : ignore size (use with -c)\n"); + printf(" --ignore-link : ignore link (use with -c)\n"); + printf(" --show-all : show same and difference (use with -c)\n"); + printf(" --only-new : show only new files (use with -c)\n"); + printf(" --only-old : show only old files (use with -c)\n"); + printf(" --human-readable : show long format for right and date\n"); + return (1); +} + + +int main(int argc, char **argv) { + t_fileinfo data; + char **begin; + FILE *source; + + bzero(&data,sizeof(data)); + if (read_param(argc,argv,&begin) <= 0) + return (syntax()); + if (CheckMode) { + // read table + if (source_filename && strcmp(source_filename,"-")) { + if (!(source=fopen(source_filename,"ro"))) + return (fatal_error("Fichier source inexistant : %s\n", + source_filename)); + } else { + source=stdin; + } + read_file_fileinfo(&data,source); + if (source != stdin) fclose(source); + } + read_directories_fileinfo(&data, begin); + if (BaseStrip) + print_fileinfo(find_fileinfo(basename(BaseStrip),find_parent(BaseStrip,&data)),"",1,NULL); + else + print_fileinfo(&data,"",1,NULL); + delete_fileinfo(&data); + return (0); +} + + + diff --git a/signfs/md5.c b/signfs/md5.c new file mode 100644 index 0000000..3c42ff6 --- /dev/null +++ b/signfs/md5.c @@ -0,0 +1,261 @@ +/* FIXME: ces routines ne fournissent qu'un résultat sur 64 bits sur ALPHA !!! + ctx->buf[0]=ctx->buf[1]=0. +*/ + + +//#include <endian.h> +#if __BYTE_ORDER == __BIG_ENDIAN +#define HIGHFIRST 1 +#endif + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ +#include <string.h> /* for memcpy() */ +#include "md5.h" + +#ifndef HIGHFIRST +#define byteReverse(buf, len) /* Nothing */ +#else +void byteReverse(unsigned char *buf, unsigned longs); + +#ifndef ASM_MD5 +/* + * Note: this code is harmless on little-endian machines. + */ +void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void ToolsMD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void ToolsMD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + ToolsMD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + ToolsMD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void ToolsMD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + ToolsMD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + ToolsMD5Transform(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void ToolsMD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif diff --git a/signfs/md5.h b/signfs/md5.h new file mode 100644 index 0000000..7e287a6 --- /dev/null +++ b/signfs/md5.h @@ -0,0 +1,55 @@ +/* + * SignFS : Tool to have an image of the filesystem + * + * Copyright (C) 1999-2001, Willy Tarreau <willy@ant-computing.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * File: md5.h + * Object: list and hash functions + * Version: 0.3 + * Date: Sun Dec 23 14:21:50 CET 2001 + * Autors: Willy Tarreau <willy@ant-computing.com> + */ + +#ifndef MD5_H +#define MD5_H + +#ifdef __alpha +typedef unsigned int uint32; +#else +typedef unsigned long uint32; +#endif + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +void ToolsMD5Init(struct MD5Context *context); +void ToolsMD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len); +void ToolsMD5Final(unsigned char digest[16], struct MD5Context *context); +void ToolsMD5Transform(uint32 buf[4], uint32 const in[16]); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ +typedef struct MD5Context MD5_CTX; + +#endif /* !MD5_H */ diff --git a/signfs/others.c b/signfs/others.c new file mode 100644 index 0000000..78df824 --- /dev/null +++ b/signfs/others.c @@ -0,0 +1,74 @@ +#include <string.h> +#include <stdio.h> +#include <dirent.h> +#include <unistd.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdarg.h> +#include "others.h" + + +// fonction to return write in 'ls -l' format +char *right(mode_t m) { + static char dsc[10]; + dsc[0]=(m&S_IRUSR)?'r':'-'; + dsc[1]=(m&S_IWUSR)?'w':'-'; + dsc[2]=(m&S_IXUSR)?'x':'-'; + dsc[3]=(m&S_IRGRP)?'r':'-'; + dsc[4]=(m&S_IWGRP)?'w':'-'; + dsc[5]=(m&S_IXGRP)?'x':'-'; + dsc[6]=(m&S_IROTH)?'r':'-'; + dsc[7]=(m&S_IWOTH)?'w':'-'; + dsc[8]=(m&S_IXOTH)?'x':'-'; + dsc[9]=0; + return(dsc); +} + +// return directory name of a [path/]filename string +// the return value is in static value +char *dirname(char *str) { + static char tmp[8192],*p; + strcpy(tmp,str); + if ((p=strrchr(tmp,'/'))) return (*p=0,tmp); + return (NULL); +} + +// return the filename of a [path/]filename string +char *basename(char *str) { + static char *p; + if (!(p=strrchr(str,'/'))) return str; + return (p+1); +} + +int fatal_error(char *message, ...) { + va_list argp; + char buff[BUFFLEN]; + + va_start(argp,message); + vsnprintf(buff,BUFFLEN,message,argp); + write(2,buff,strlen(buff)); + va_end(argp); + return (2); +} + +int error(char *message, ...) { + va_list argp; + char buff[BUFFLEN]; + + va_start(argp,message); + vsnprintf(buff,BUFFLEN,message,argp); + write(2,buff,strlen(buff)); + va_end(argp); + return (2); +} + +int pferror(char *message, ...) { + va_list argp; + char buff[BUFFLEN]; + + va_start(argp,message); + vsnprintf(buff,BUFFLEN,message,argp); + perror(buff); + va_end(argp); + return (2); +} diff --git a/signfs/others.h b/signfs/others.h new file mode 100644 index 0000000..25d9c2c --- /dev/null +++ b/signfs/others.h @@ -0,0 +1,11 @@ +#include <sys/stat.h> +#include <sys/types.h> +#define BUFFLEN 256 + + +char *right(mode_t mode); +char *dirname(char *); +char *basename(char *); +int error(char *,...); +int fatal_error(char *,...); +int pferror(char *,...); diff --git a/signfs/sample.sign b/signfs/sample.sign new file mode 100644 index 0000000..f51f6cb --- /dev/null +++ b/signfs/sample.sign @@ -0,0 +1,32 @@ +d 0775 101 100 0 -------------------------------- 1011550313 ../signfs-0.4 +- 0664 101 100 40 5856c38f855ff346556a884676d71eb5 1004394000 ../signfs-0.4/AUTHORS +- 0664 101 100 17992 94d55d512a9ba36caa9b7df079bae19f 1004393981 ../signfs-0.4/COPYING +- 0664 101 100 159 37c927c58acc678bfdfb51b50a60e19d 1009102270 ../signfs-0.4/ChangeLog +l 0777 101 100 7 7116ef0705885343c9e1b2171a06be0e 1009183767 ../signfs-0.4/LICENCE COPYING +- 0664 101 100 1265 b9883aac448eca848546377836965fe0 1009183509 ../signfs-0.4/Makefile +- 0644 101 100 384 b4f698ee014cce9486bac07630395e91 1004394283 ../signfs-0.4/README +- 0664 101 100 258 d0dc455418e3b3f562ea8f139f5a00c2 1011550294 ../signfs-0.4/TODO +- 0664 101 100 219 36636bbf1577d74a11805fb358a59eac 1009183433 ../signfs-0.4/TODO~ +- 0664 101 100 20146 c10580cfbba1b78edf4af24d41ef0ff9 1009183528 ../signfs-0.4/libtools.a +- 0664 101 100 26670 5bb8af29d8af01cea3a395d138b38987 1009114108 ../signfs-0.4/libtools.c +- 0664 101 100 3170 d5d80eb52cc7e71aeedf748665583c87 1009114117 ../signfs-0.4/libtools.h +- 0664 101 100 13932 2abdbf3866c5245218ed2c61bc547c35 1009183527 ../signfs-0.4/libtools.o +- 0664 101 100 5549 57acc9ac5ce0dc701348680ce7db2394 1009623975 ../signfs-0.4/main.c +- 0664 101 100 5529 faefc6712ba5bf1e25ff993103cb0808 1009185941 ../signfs-0.4/main.c~ +- 0664 101 100 5312 a8ff92238c956750dcf7fd56d8831d25 1009623979 ../signfs-0.4/main.o +- 0664 101 100 8300 fffb933546ded2c82cfb8d2b5a4c56ba 992786829 ../signfs-0.4/md5.c +- 0664 101 100 1601 264cb0e1385a7de7db84ac6e1759b3a1 1009113940 ../signfs-0.4/md5.h +- 0664 101 100 3352 c5c4c92fbfcec9fbd99c6804fe418536 1009183525 ../signfs-0.4/md5.o +- 0664 101 100 1640 6ba8ecd30a1cbf40e1d78105750ad7af 1009121464 ../signfs-0.4/others.c +- 0664 101 100 220 377a37d705d7b55860403b24acaeaf84 1009121771 ../signfs-0.4/others.h +- 0664 101 100 2008 3624d59e635b47c78832628a52343ba0 1009183528 ../signfs-0.4/others.o +- 0664 101 100 1688 35f7be6a77bee3e67bb9d515a466239a 1004394965 ../signfs-0.4/sample.sign +- 0775 101 100 16752 75353fa6aa2f78b4d90b1f1b249c73c5 1009623979 ../signfs-0.4/signfs +- 0664 101 100 14250 e31d7306198edc65db0fc2cbfbd422d4 1011550362 ../signfs-0.4/signfs.c +- 0664 101 100 14250 e31d7306198edc65db0fc2cbfbd422d4 1009623809 ../signfs-0.4/signfs.c~ +- 0664 101 100 3143 6a720992a796669f8347b387c1f6096c 1009185436 ../signfs-0.4/signfs.h +- 0664 101 100 3117 d289589e18d48b65881902ef6302230e 1009182455 ../signfs-0.4/signfs.h~ +- 0664 101 100 10888 a66f00c6d2c0041a5d9437e2f2b3c45a 1009623814 ../signfs-0.4/signfs.o +- 0664 101 100 1944 4bca0fa129a53b0c146ccdd61fbe90d9 1009121692 ../signfs-0.4/structure.c +- 0664 101 100 1293 d9df60d7b65559fc191eed3e5247bd79 1009113848 ../signfs-0.4/structure.h +- 0664 101 100 1116 fa17ea6e039f158bbdab263b913e9d27 1009183530 ../signfs-0.4/structure.o diff --git a/signfs/signfs.c b/signfs/signfs.c new file mode 100644 index 0000000..efa7e97 --- /dev/null +++ b/signfs/signfs.c @@ -0,0 +1,526 @@ +/* + * SignFS : Tool to have an image of the filesystem + * + * Copyright (C) 1999-2001, Benoit Dolez <benoit@meta-x.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * File: signfs.c + * Object: Signing filesystem functions + * Version: 0.5 + * Date: Sun Dec 23 14:21:50 CET 2001 + */ + +#include <stdio.h> +#include <sys/types.h> +#include <fcntl.h> +#include <dirent.h> +#include <string.h> +#include <stdlib.h> +#include <netinet/in.h> +#include <stdlib.h> +#include <malloc.h> +#include <time.h> +#include "structure.h" +#include "signfs.h" +#include "others.h" + +dev_t SingleDev; +extern int SingleFileSystem,NoDate; +extern int CheckMode; +extern char *BaseFS,*BaseFile; +extern int ShowDiff,Show; +extern int HumanReadable; +extern int CurrentDir; +extern char *Output; + +#define DIFF(f,field) ((SHOWDIFF(f) && (datatemp.flag & (f))==(f) && \ + data->field != datatemp.field)?(f):0) + +// print the data to the standart output +void print_fileinfo(t_fileinfo *data,char *filename,int recurs,FILE *output) { + // recurs = 0 ne pas traiter la recursivité, écriture simple + // recurs = 1 traiter la recursivité, écriture des différences possible + // recurs = 2 ne pas traiter la récurisivité, écriture d'une différence + int s,l,show=1; + static char blk[8192]; + t_list *c; + char directory[8192]; + + if (!filename || !data) return ; + s=0; + if (recurs == 2) { + s+=sprintf(blk+s,"< "); + } + else if (ShowDiff != 0 && recurs == 1) { + if (data->diff) { + print_fileinfo(data->diff,filename,2,output); + s+=sprintf(blk+s,"> "); + } else { + if ((data->filled & (FILLED_FS|FILLED_FILE)) != (FILLED_FS|FILLED_FILE)) + if ((data->filled & FILLED_FS) && (Show & SHOW_NEW)!=0) + s+=sprintf(blk+s,"+ "); + else if ((data->filled & FILLED_FILE) && (Show & SHOW_OLD)!=0) + s+=sprintf(blk+s,"- "); + else show=0; + else if ((Show & SHOW_OTHERS) == 0) show=0; + else s+=sprintf(blk+s,"= "); + } + } + if ( ( show && data->filled) ) { + if (SHOW(FLAG_TYPE)) + s+=sprintf(blk+s,"%c",FILE_TYPE(data->mode)); + + // s+=sprintf(blk+s,"%s ",right(data->mode)); + if (SHOW(FLAG_MODE)) { + if (HumanReadable) + s+=sprintf(blk+s," %04o(%s) ",data->mode & 0007777,right(data->mode)); + else + s+=sprintf(blk+s," %04o ",data->mode & 0007777); + } + + if (SHOW(FLAG_MODE)) + s+=sprintf(blk+s,"%5d %5d ",data->uid,data->gid); + if (SHOW(FLAG_SIZE)) { + if (S_ISBLK(data->mode) || S_ISCHR(data->mode)) { + char tmp[11]; + sprintf(tmp,"%d,%d",major(data->rdev),minor(data->rdev)); + s+=sprintf(blk+s,"%10s ",tmp); + } else { + s+=sprintf(blk+s,"%10ld ",data->size); + } + } + if (SHOW(FLAG_MD5SUM)) { + if (data->have_md5) { + s+=sprintf(blk+s,"%08x%08x",O4(data->md5sum),O4(data->md5sum+4)); + s+=sprintf(blk+s,"%08x%08x ",O4(data->md5sum+8),O4(data->md5sum+12)); + } else { + s+=sprintf(blk+s,"-------------------------------- "); + } + } + if (SHOW(FLAG_MTIME)) { + if (HumanReadable) { + char *c; + c=ctime(&(data->mtime));c[strlen(c)-1]=0; + s+=sprintf(blk+s,"%10ld(%s) ",data->mtime,c); + } + else + s+=sprintf(blk+s,"%10ld ",data->mtime); + } + + s+=sprintf(blk+s,"%s",*filename?filename:"."); + // s+=sprintf(blk+s,"%s",*filename?filename:"[current-directory]"); + + if (SHOW(FLAG_LINK)) + if (S_ISLNK(data->mode) && data->link) { + s+=sprintf(blk+s," %s",data->link); + } + } + if (s > 0 && Output == NULL) { + // écriture sur la sortie standard + write(1,blk,strlen(blk)); + write(1,"\n",1); + } else if (s > 0) { + // écriture dans l'output + fprintf(output,"%s\n",blk); + } else if (Output != NULL) { + // écriture dans l'output y compris le fichier vide qui est la base + } + if (recurs == 1 && (c=data->files)) { + strcpy(directory,filename); + l=strlen(directory); + if (l > 0 && directory[l-1] != '/') + strcpy(directory+l++,"/"); + while(c) { + strcpy(directory+l,((t_fileinfo*)(c->data))->filename); + print_fileinfo((void*)(c->data),directory,recurs,output); + c=c->next; + } + } +} + +// file data struct with filename and stat +t_fileinfo *fill_fileinfo(char *filename, char *pfilename, + struct stat *stat, t_fileinfo *data) { + static MD5_CTX c; + static char blk[8192]; + int fd,s,diff=0; + static t_fileinfo datatemp; + + data->filename=strdup(pfilename); + if (!stat) return (data); + if (ShowDiff != 0) memcpy(&datatemp,data,sizeof(*data)); + data->filled|=FILLED_FS; + data->fsflag=FLAG_ALL; + data->mode=stat->st_mode; + data->uid=stat->st_uid; + data->gid=stat->st_gid; + if (S_ISBLK(data->mode) || S_ISCHR(data->mode)) + data->rdev=stat->st_rdev; + else if (!S_ISDIR(data->mode)) + data->size=stat->st_size; + data->mtime=stat->st_mtime; + if (S_ISREG(data->mode)) { + if ((fd=open(SPD(filename),O_RDONLY)) < 0) { + pferror("open(%s) for checksum",SPD(filename)); + } else { + MD5_Init(&c); + while ((s=read(fd,blk,8192))>0) MD5_Update(&c,blk,s); + MD5_Final(data->md5sum,&c); + close(fd); + data->have_md5=1; + } + } else if (S_ISLNK(data->mode)) { + int l; + if ((l=readlink(SPD(filename),blk,8192)) < 0) { + pferror("readlink(%s)",SPD(filename)); + } else { + blk[l]=0; + MD5_Init(&c); + MD5_Update(&c,blk,l); + MD5_Final(data->md5sum,&c); + data->have_md5=1; + data->link=strdup(blk); + } + } + diff|=DIFF(FLAG_MODE,mode); + diff|=DIFF(FLAG_TYPE,mode); + diff|=DIFF(FLAG_UID,uid); + diff|=DIFF(FLAG_GID,gid); + diff|=DIFF(FLAG_SIZE,size); + diff|=DIFF(FLAG_RDEV,rdev); + diff|=DIFF(FLAG_MTIME,mtime); + if (SHOWDIFF(FLAG_MD5SUM) && (datatemp.flag&FLAG_MD5SUM) && + ((data->have_md5 == datatemp.have_md5 && + memcmp(data->md5sum,datatemp.md5sum,MD5_DIGEST_LENGTH)!=0) || + data->have_md5 != datatemp.have_md5)) { + diff|=FLAG_MD5SUM; + } + if (SHOWDIFF(FLAG_LINK) && (datatemp.flag&FLAG_LINK) && + strcmp(data->link,datatemp.link)) diff|=FLAG_LINK; + if (SHOWDIFF(diff) && + (data->filled&(FILLED_FS|FILLED_FILE))==(FILLED_FS|FILLED_FILE)) { + data->diff=malloc(sizeof(t_fileinfo)); + memcpy(data->diff,&datatemp,sizeof(t_fileinfo)); + } + return (data); +} + +// looking for directory in the current directory tree +t_fileinfo *find_parent(char *directory,t_fileinfo *current) { + char *b,*r,bb[8192]; + t_list *c; + int res; + + strcpy(r=bb,directory); + while(current && *r) { + b=r; + if ((r=strchr(r,'/'))) { *r=0;r++; } + else return (current); + res=1; + for (c=current->files;c;c=c->next) + if ((res=strcmp(((t_fileinfo*)(c->data))->filename,b))>=0) break; + if (res == 0) { // ok + // in the futur, check if directory + current=(void*)(c->data); + } + else { // don't know, + current=build_fileinfo(NULL,b,NULL,current); + current->mode |= S_IFDIR; + } + } + return (current); +} + +// find a file in the current directory +t_fileinfo *find_fileinfo(char *filename, t_fileinfo *current) { + t_list *c; + int res=1; + + if (!current) return (NULL); + // fprintf(stderr,"recherche\n"); + for (c=current->files;c;c=c->next) { + // fprintf(stderr,"%s <-> %s\n",((t_fileinfo*)(c->data))->filename,filename); + if ((res=strcmp(((t_fileinfo*)(c->data))->filename,filename))>=0) break; + } + return (res==0?(t_fileinfo*)(c->data):NULL); +} + +// build data from stat informations +t_fileinfo *build_fileinfo(char *filename, char *pfilename, + struct stat *stat, t_fileinfo *parent) { + t_fileinfo *data; + + if (!parent || !(data=find_fileinfo(pfilename,parent))) { + // inexistant : creation requise + data=malloc(sizeof(*data)); + bzero(data,sizeof(*data)); + data->parent=parent; + fill_fileinfo(filename,pfilename,stat,data); + if (parent) + list_put((void*)&(parent->files),(void*)data,off(t_fileinfo,filename),strcmp); + } else { + fill_fileinfo(filename,pfilename,stat,data); + } + return(data); +} + +// had data from an other readed struct +void complete_fileinfo(t_fileinfo *data,t_fileinfo *n) { + data->filename=n->filename; + data->mode=n->mode; + data->uid=n->uid; + data->gid=n->gid; + data->rdev=n->rdev; + data->size=n->size; + data->mtime=n->mtime; + data->have_md5=n->have_md5; + memcpy(data->md5sum,n->md5sum,MD5_DIGEST_LENGTH); + data->link=n->link; + data->flag=n->flag; +} + +// get directory tree from file +int read_file_fileinfo(t_fileinfo *data, FILE *file) { + char blk[8192],*b,*p,*f; + int status,i,l,parenthesis; + t_fileinfo *c; + + // reading line by line + while(fgets(b=p=blk,8192,file)) { + t_fileinfo *n=malloc(sizeof(*n)); + blk[strlen(blk)-1]=0; + bzero(n,sizeof(*n)); + status=1; + while(*p) { + parenthesis=0; + for (b=p;*p && ( *p!=' ' || parenthesis==1 ) ;p++) { + if (*p == '(' && parenthesis==0) parenthesis=1; + if (*p == ')' && parenthesis==1) parenthesis=0; + } + if (*p) + for (*p=0,p++;*p==' ';p++); + switch (status) { + case 1: + switch(*b) { + case 'l':n->mode=S_IFLNK;break; + case 'd':n->mode=S_IFDIR;break; + case 'c':n->mode=S_IFCHR;break; + case 'b':n->mode=S_IFBLK;break; + case 'f':n->mode=S_IFIFO;break; + case 's':n->mode=S_IFSOCK;break; + case '-':n->mode=S_IFREG;break; + default:break; + } + n->flag|=FLAG_TYPE; + break; + case 2: + if ((f=strchr(b,'('))) { *f=0; } + n->mode+=strtol(b,NULL,8); + n->flag|=FLAG_MODE; + break; + case 3: n->uid=atoi(b); n->flag|=FLAG_UID; break; + case 4: n->gid=atoi(b); n->flag|=FLAG_GID; break; + case 5: + if ((f=strchr(b,','))) { + *f=0;f++; + n->rdev=atoi(b)*256+atoi(f); + } else { + n->size=atoi(b); + } + n->flag|=FLAG_SIZE; + break; + case 6: + n->have_md5=1; + if (!strstr(b,"----")) + for (i=0;i<MD5_DIGEST_LENGTH;i++) + n->md5sum[i]=(unsigned char)(HEXTODEC(b[i*2])*16+HEXTODEC(b[i*2+1])); + else + n->have_md5=0; + n->flag|=FLAG_MD5SUM; + break; + case 7: + if ((f=strchr(b,'('))) { *f=0; } + n->mtime=(time_t)atol(b); + n->flag|=FLAG_MTIME; + break; + case 8: + l=strlen(b); + while (l>0 && b[l-1]=='/') b[--l]=0; + n->parent=data; + if (BaseFile) { + if (!strncmp(b,BaseFile,strlen(BaseFile)) && + (b[strlen(BaseFile)] == 0 || b[strlen(BaseFile)] == '/')) { + b += strlen(BaseFile); + if (*b == '/') b++; + l = strlen(b); + } + } + if (l>0) { + if ((f=strrchr(b,'/'))) { + n->parent=find_parent(b,data); + f++; + } else { + f=b; + } + n->filename=strdup(f); + c=list_put((void*)&(n->parent->files),(void*)n, + off(t_fileinfo,filename),strcmp); + n->filled|=FILLED_FILE; + if (c) { complete_fileinfo(c,n); free(n); n=c ; } + } + else { + n->filename=""; + complete_fileinfo(data,n); + free(n); + n=data; + n->filled|=FILLED_FILE; + } + break; + case 9: n->link=strdup(b); n->flag|=FLAG_LINK; break; + default: break; + } + status++; + } + } + return(1); +} + +// reading data from filesystem +int read_directory_fileinfo(t_fileinfo *data, char *directory) { + DIR *dir; + t_fileinfo *tdata; + struct dirent *dirent; + struct stat stat; + char *temp; + int l; + off_t position; + + l=strlen(directory); + if (!(dir=opendir(SPD(directory)))) { + pferror("opendir(%s)",SPD(directory)); + return(0); + } + if (*directory) { + temp=malloc(strlen(directory)+1+NAME_MAX); + memcpy(temp,directory,l); + if (temp[l-1] != '/') strcpy(temp+l++,"/"); + } else { + temp=malloc(NAME_MAX); + strcpy(temp,""); + } + while ((dirent = readdir(dir))) { + if (dirent->d_name[0] == '.' && + (dirent->d_name[1] == 0 || + (dirent->d_name[1] == '.' && dirent->d_name[2] == 0))) continue; + strcpy(temp+l,dirent->d_name); + if (lstat(temp,&stat)) { + pferror("stat(%s)",temp); + continue; + } + tdata=build_fileinfo(temp,temp+l,&stat,data); + if (S_ISDIR(stat.st_mode) && + !(SingleFileSystem && SingleDev!= stat.st_dev)) { + position=telldir(dir); + closedir(dir); + read_directory_fileinfo(tdata,temp); + dir=opendir(SPD(directory)); + seekdir(dir,position); + } + } + closedir(dir); + free(temp); + return(1); +} + + +// build directory tree from arg and filesystem +int read_directories_fileinfo(t_fileinfo *data, char **argv) { + struct stat stat; + char *temp=""; + char dfile[8192],*file; + int l,dir=0; + t_fileinfo *tdata,*pdata; + + if (*argv == NULL) { + if (CurrentDir) { + if (lstat(".",&stat)) { + pferror("stat(%s)","."); + return(0); + } + SingleDev=stat.st_dev; + // logging for '.' + if (S_ISDIR(stat.st_mode)) { + read_directory_fileinfo(data,"."); + } + } + } else { + while (*argv) { + strcpy(file=dfile,*argv); + l=strlen(file); + if (strcmp(file,"/")) { + if (l>0 && file[l-1]=='/') { + dir=1 ; + file[--l]=0; + } else dir=0; + if (BaseFS) { + // change root in the tree directory + l=strlen(BaseFS); + if (!strncmp(file,BaseFS,strlen(BaseFS)) && + (file[strlen(BaseFS)]==0 || file[strlen(BaseFS)]=='/')) { + file += strlen(BaseFS); + if (*file=='/') file++; + } + } + } + if (lstat(dfile,&stat)) { + error("lstat(%s)",dfile); + return(0); + } + // keep the dev info for xdev option + SingleDev=stat.st_dev; + if (*file) { + if ((temp=dirname(file))) { // looking for parent if it exist + pdata=find_parent(file,data); + // making directory + tdata=build_fileinfo(file,basename(file),&stat,pdata); + } else { + pdata=data; + // making directory + tdata=build_fileinfo(file,file,&stat,pdata); + } + } else { + // if (!find_fileinfo(".",data)) + fill_fileinfo("","",&stat,data); + tdata=data; + } + // had structure to data + if (S_ISDIR(stat.st_mode) || (dir && S_ISLNK(stat.st_mode))) { + read_directory_fileinfo(tdata,dfile); + } + argv++; + } + } + return(1); +} + + +// have to clean the fileinfo structure before existing +int delete_fileinfo(t_fileinfo *data) { + return(1); +} + diff --git a/signfs/signfs.h b/signfs/signfs.h new file mode 100644 index 0000000..f331aa7 --- /dev/null +++ b/signfs/signfs.h @@ -0,0 +1,114 @@ +/* + * SignFS : Tool to have an image of the filesystem + * + * Copyright (C) 1999-2001, Benoit Dolez <benoit@meta-x.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * File: signfs.h + * Object: structs and defines + * Version: 0.3 + * Date: Sun Dec 23 14:21:50 CET 2001 + */ + +#ifndef __DATA_H__ +#define __DATA_H__ + +#include "md5.h" +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#define MD5_Init ToolsMD5Init +#define MD5_Update ToolsMD5Update +#define MD5_Final ToolsMD5Final +#define MD5_DIGEST_LENGTH 16 + +#define FLAG_TYPE 0x0001 +#define FLAG_MODE 0x0002 +#define FLAG_UID 0x0004 +#define FLAG_GID 0x0008 +#define FLAG_SIZE 0x0010 +#define FLAG_MD5SUM 0x0020 +#define FLAG_MTIME 0x0040 +#define FLAG_LINK 0x0080 +#define FLAG_RDEV 0x0010 +#define FLAG_ALL 0x00ff + +#define FILLED_FILE 0x01 +#define FILLED_FS 0x02 + +#define SHOW_OLD 0x0100 +#define SHOW_NEW 0x0200 +#define SHOW_OTHERS 0x0400 +#define SHOW_ALL (SHOW_OLD|SHOW_NEW|SHOW_OTHERS) + + +#define O4(a) (htonl(*(int*)(a))) +#define FILE_TYPE(a) (S_ISLNK(a) ?'l':S_ISDIR(a) ?'d': \ + S_ISCHR(a) ?'c':S_ISBLK(a) ?'b': \ + S_ISFIFO(a)?'f':S_ISSOCK(a)?'s': \ + S_ISREG(a) ?'-':'?') + +#define HEXTODEC(a) (('0'<=(a) && (a)<='9')?(a)-'0':(a)-'a'+10) + +#define SPD(d) (*d?d:".") +#define off(t,field) ((size_t)&(((t*)NULL)->field)) + +#define SHOWDIFF(flag) ((ShowDiff & flag) != 0) +#define SHOW(flag) ((Show & flag) != 0) + + + +// filenames descriptions +typedef struct s_fileinfo t_fileinfo ; + +struct s_fileinfo { + t_fileinfo *parent; + void *files; + char *filename; + char *link; + unsigned char have_md5; + unsigned char md5sum[MD5_DIGEST_LENGTH]; + uid_t uid; + gid_t gid; + off_t size; + dev_t rdev; + mode_t mode; + time_t mtime; + ulong flag; + ulong fsflag; + int filled; + t_fileinfo *diff; +}; + +t_fileinfo *build_fileinfo(char *, char *,struct stat *, t_fileinfo *); +void print_fileinfo(t_fileinfo *,char *,int,FILE *); +t_fileinfo *fill_fileinfo(char *, char *, struct stat *, t_fileinfo *); +t_fileinfo *find_parent(char *,t_fileinfo *); + +t_fileinfo *find_fileinfo(char *filename, t_fileinfo *current); +int read_file_fileinfo(t_fileinfo *data, FILE *file); +int read_directory_fileinfo(t_fileinfo *data, char *directory); +int read_directories_fileinfo(t_fileinfo *data, char **argv); +int delete_fileinfo(t_fileinfo *data); + +#endif + + + diff --git a/signfs/structure.c b/signfs/structure.c new file mode 100644 index 0000000..f0ee779 --- /dev/null +++ b/signfs/structure.c @@ -0,0 +1,74 @@ +/* + * SignFS : Tool to have an image of the filesystem + * + * Copyright (C) 1999-2001, Benoit Dolez <benoit@meta-x.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * File: structure.c + * Object: list and hash functions + * Version: 0.3 + * Date: Sun Dec 23 14:21:50 CET 2001 + */ + +#include <malloc.h> +#include "structure.h" +#include "others.h" + +#define STR(a) #a + +// put data in a sorted list +// if two elements are the same (fct() return 0) return the known data +// if fct==NULL insert at the beginning of the list +void *list_put(t_list **first,char *item,int off,int (*fct)()) { + t_list *n,*c=*first; + int res; + + // create new element + if (!(n=malloc(sizeof(t_list)))) { + pferror("malloc: "); + return (0); + } + n->data=item; + n->next=n->prev=NULL; + if (!c) *first=n; + else { + res=1; + if (fct) + while((res=fct(*(char**)(c->data+off),*(char**)(n->data+off)))<0) { + if (!c->next) break; + c=c->next; + } + else + res=1; + if (res == 0) // data is the same + return ((void*)(c->data)); + else if (res<0) { // insert at the end + c->next=n; + n->prev=c; + } + else { // insert at the beginning + n->next=c; + n->prev=c->prev; + c->prev=n; + if (!n->prev) *first=n; + else n->prev->next=n; + } + } + return (NULL); +} + diff --git a/signfs/structure.h b/signfs/structure.h new file mode 100644 index 0000000..1f8c2e7 --- /dev/null +++ b/signfs/structure.h @@ -0,0 +1,53 @@ +/* + * SignFS : Tool to have an image of the filesystem + * + * Copyright (C) 1999-2001, Benoit Dolez <benoit@meta-x.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * File: structure.h + * Object: list and hash functions prototypes + * Version: 0.3 + * Date: Sun Dec 23 14:21:50 CET 2001 + */ + + +#ifndef __STRUCTURE_H__ +#define __STRUCTURE_H__ + +typedef struct s_list t_list; + +struct s_list { + t_list *prev; + t_list *next; + char *data; +}; + + +typedef struct s_hash t_hash; +#define HASHSIZE 103 + +struct s_hash { + t_list *tab[HASHSIZE]; + int (*fct)(); +}; + +void *list_put(t_list **,char *,int,int (*)()); + +#endif + + |