aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--README3
-rw-r--r--TODO8
-rw-r--r--flx/ChangeLog5
-rw-r--r--flx/Makefile2
-rw-r--r--flx/check.c4
-rw-r--r--flx/fct1.c5
-rw-r--r--flx/flx.h4
-rw-r--r--flx/input_fs.c32
-rwxr-xr-xscripts/pkg6
-rw-r--r--signfs/AUTHORS1
-rw-r--r--signfs/COPYING340
-rw-r--r--signfs/ChangeLog7
l---------signfs/LICENCE1
-rw-r--r--signfs/Makefile46
-rw-r--r--signfs/README20
-rw-r--r--signfs/TODO11
-rw-r--r--signfs/libtools.c1126
-rw-r--r--signfs/libtools.h104
-rw-r--r--signfs/main.c166
-rw-r--r--signfs/md5.c261
-rw-r--r--signfs/md5.h55
-rw-r--r--signfs/others.c74
-rw-r--r--signfs/others.h11
-rw-r--r--signfs/sample.sign32
-rw-r--r--signfs/signfs.c526
-rw-r--r--signfs/signfs.h114
-rw-r--r--signfs/structure.c74
-rw-r--r--signfs/structure.h53
29 files changed, 3087 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index b94fb29..a45a808 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/README b/README
index 61fa0cb..fb5d7f7 100644
--- a/README
+++ b/README
@@ -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
diff --git a/TODO b/TODO
index 94d877a..1e35815 100644
--- a/TODO
+++ b/TODO
@@ -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));
diff --git a/flx/fct1.c b/flx/fct1.c
index 622add7..c074a7a 100644
--- a/flx/fct1.c
+++ b/flx/fct1.c
@@ -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];
diff --git a/flx/flx.h b/flx/flx.h
index 6c71355..3315ded 100644
--- a/flx/flx.h
+++ b/flx/flx.h
@@ -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
+
+