summaryrefslogtreecommitdiff
path: root/pkgtools/rdigest
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools/rdigest')
-rw-r--r--pkgtools/rdigest/DESCR50
-rw-r--r--pkgtools/rdigest/Makefile13
-rw-r--r--pkgtools/rdigest/PLIST3
-rw-r--r--pkgtools/rdigest/distinfo5
-rw-r--r--pkgtools/rdigest/patches/patch-aa60
-rw-r--r--pkgtools/rdigest/patches/patch-ab89
-rw-r--r--pkgtools/rdigest/patches/patch-ac204
7 files changed, 424 insertions, 0 deletions
diff --git a/pkgtools/rdigest/DESCR b/pkgtools/rdigest/DESCR
new file mode 100644
index 00000000000..fec28fe43ca
--- /dev/null
+++ b/pkgtools/rdigest/DESCR
@@ -0,0 +1,50 @@
+This utility is a wrapper for the md5(3), sha1(3) and rmd160(3)
+routines.
+
+The utility is linked statically, so that it can be used without any
+shared libraries installed on the system.
+
+It is remarkably similar to the digest package, except that it
+can recursively checksum directory trees.
+
+While a simple checksum on a tar file is usually satisfactory, once
+said archive has been extracted, it is virtually impossible to
+repackage the extracted tree in a form that can yield a repeatable
+checksum. To be specific, changes in timestamps and ownership, and
+changes in file ordering within directories can affect the checksum of
+the archive, while not really impacting the actual code at all.
+
+The algorithm used to checksum a directory in this implementation is
+as follows:
+
+ cd into directory
+ initialize MASTER_HASH
+ walk directory tree, sorting all entries
+ foreach entry
+ if it is a directory:
+ skip it if it is named "RCS", "CVS", or "SCCS"
+ initialize SLAVE_HASH
+ add the string "d " into SLAVE_HASH
+ add the pathname of the directory into SLAVE_HASH
+ finish SLAVE_HASH
+ fold the hexified SLAVE_HASH result into MASTER_HASH
+ if it is a file:
+ initialize SLAVE_HASH
+ add the string "f " into SLAVE_HASH
+ add the pathname of the file into SLAVE_HASH
+ finish SLAVE_HASH
+ fold the hexified SLAVE_HASH result into MASTER_HASH
+ initialize SLAVE_HASH
+ add the contents of the file into SLAVE_HASH
+ finish SLAVE_HASH
+ fold the hexified SLAVE_HASH result into MASTER_HASH
+ if it is a symbolic link
+ initialize SLAVE_HASH
+ add the string "l " into SLAVE_HASH
+ add the pathname of the link into SLAVE_HASH
+ finish SLAVE_HASH
+ fold the hexified SLAVE_HASH result into MASTER_HASH
+ initialize SLAVE_HASH
+ add the contents of the link into SLAVE_HASH
+ finish SLAVE_HASH
+ fold the hexified SLAVE_HASH result into MASTER_HASH
diff --git a/pkgtools/rdigest/Makefile b/pkgtools/rdigest/Makefile
new file mode 100644
index 00000000000..3286b2ac4ce
--- /dev/null
+++ b/pkgtools/rdigest/Makefile
@@ -0,0 +1,13 @@
+# $NetBSD: Makefile,v 1.1.1.1 2003/07/24 05:21:05 atatat Exp $
+
+DISTNAME= rdigest-${VERSION}
+CATEGORIES= # be quiet pkglint
+MASTER_SITES= # be quiet pkglint
+
+MAINTAINER= atatat@netbsd.org
+COMMENT= Recursive message digest wrapper utility
+
+DIGESTDIR= ${.CURDIR}/../../pkgtools/digest
+FILESDIR= ${DIGESTDIR}/files
+
+.include "${DIGESTDIR}/Makefile"
diff --git a/pkgtools/rdigest/PLIST b/pkgtools/rdigest/PLIST
new file mode 100644
index 00000000000..5484aa3449d
--- /dev/null
+++ b/pkgtools/rdigest/PLIST
@@ -0,0 +1,3 @@
+@comment $NetBSD: PLIST,v 1.1.1.1 2003/07/24 05:21:04 atatat Exp $
+bin/rdigest
+man/man1/rdigest.1
diff --git a/pkgtools/rdigest/distinfo b/pkgtools/rdigest/distinfo
new file mode 100644
index 00000000000..dfb2312e8aa
--- /dev/null
+++ b/pkgtools/rdigest/distinfo
@@ -0,0 +1,5 @@
+$NetBSD: distinfo,v 1.1.1.1 2003/07/24 05:21:05 atatat Exp $
+
+SHA1 (patch-aa) = a1ed803a43925ef4c82e2c468bd2ee922b1998b6
+SHA1 (patch-ab) = b34e588443c030e0111edaff19ccf0882bf74a13
+SHA1 (patch-ac) = b67e1db9ec7bce6a1b1e3a398251584f9194a1c7
diff --git a/pkgtools/rdigest/patches/patch-aa b/pkgtools/rdigest/patches/patch-aa
new file mode 100644
index 00000000000..8320f06d514
--- /dev/null
+++ b/pkgtools/rdigest/patches/patch-aa
@@ -0,0 +1,60 @@
+$NetBSD: patch-aa,v 1.1.1.1 2003/07/24 05:21:05 atatat Exp $
+
+--- Makefile.in.orig 2002-12-20 23:06:12.000000000 -0500
++++ Makefile.in
+@@ -56,7 +56,7 @@ missing mkinstalldirs regress.sh
+ .c.o:
+ $(COMPILE) -c $< -o $@
+
+-all: digest
++all: rdigest
+
+ digest-types.h: bits
+ ./bits digest-types.h
+@@ -64,10 +64,10 @@ digest-types.h: bits
+ bits: bits.o
+ $(LINK) $(bits_OBJS) $(LIBS)
+
+-digest: $(digest_OBJS)
++rdigest: $(digest_OBJS)
+ $(LINK) $(digest_OBJS) $(LIBS)
+
+-check: digest
++check: rdigest
+ @SHELL@ $(srcdir)/regress.sh
+
+ digest.o: digest-types.h
+@@ -81,7 +81,7 @@ sha1.o: digest-types.h
+ sha1hl.o: digest-types.h
+
+ clean:
+- rm -f *.o digest bits digest-types.h
++ rm -f *.o rdigest bits digest-types.h
+
+ distclean: clean
+ rm -f Makefile config.h
+@@ -90,18 +90,18 @@ distclean: clean
+ maintainer-clean: distclean
+ rm -f configure config.h.in
+
+-install: digest
++install: rdigest
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+- @f=`echo digest|sed '$(transform)'`; \
+- echo "$(INSTALL_PROGRAM) digest $(DESTDIR)$(bindir)/$$f"; \
+- $(INSTALL_PROGRAM) digest $(DESTDIR)$(bindir)/$$f
++ @f=`echo rdigest|sed '$(transform)'`; \
++ echo "$(INSTALL_PROGRAM) rdigest $(DESTDIR)$(bindir)/$$f"; \
++ $(INSTALL_PROGRAM) rdigest $(DESTDIR)$(bindir)/$$f
+ $(mkinstalldirs) $(DESTDIR)$(mandir)/man1
+- @f=`echo digest.1|sed '$(transform)'`; \
++ @f=`echo rdigest.1|sed '$(transform)'`; \
+ echo "$(INSTALL_DATA) digest.1 $(DESTDIR)$(mandir)/man1/$$f"; \
+ $(INSTALL_DATA) digest.1 $(DESTDIR)$(mandir)/man1/$$f
+
+ uninstall:
+- @f=`echo digest|sed '$(transform)'`; \
++ @f=`echo rdigest|sed '$(transform)'`; \
+ echo " rm -f $(DESTDIR)$(bindir)/$$f"; \
+ rm -f $(DESTDIR)$(bindir)/$$f
+
diff --git a/pkgtools/rdigest/patches/patch-ab b/pkgtools/rdigest/patches/patch-ab
new file mode 100644
index 00000000000..c25703f6988
--- /dev/null
+++ b/pkgtools/rdigest/patches/patch-ab
@@ -0,0 +1,89 @@
+$NetBSD: patch-ab,v 1.1.1.1 2003/07/24 05:21:07 atatat Exp $
+
+--- digest.1.orig 2002-02-16 15:24:32.000000000 -0500
++++ digest.1
+@@ -31,21 +31,29 @@
+ .\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ .\"
+ .\"
+-.Dd February 28, 2001
+-.Dt DIGEST 1
++.Dd July 24, 2003
++.Dt RDIGEST 1
+ .Os
+ .Sh NAME
+-.Nm digest
+-.Nd calculate message digests
++.Nm rdigest
++.Nd calculate message digests of files and directories
+ .Sh SYNOPSIS
+ .Nm
++.Op Fl x Ar directory
+ .Ar algorithm
+ .Op file ...
+ .Sh DESCRIPTION
+ The
+ .Nm
+-utility calculates message digests of files or,
++utility calculates message digests of files, directories, or,
+ if no file is specified, standard input.
++The
++.Fl x
++option can be used as many times as required to indicate directories
++not to be included in a directory's hash.
++This allows you to skip, eg, CVS subdirectories in a given tree, which
++can have relatively volatile contents not pertinent to the hash.
++.Pp
+ The list of possible algorithms is:
+ .Bl -tag -width Ds
+ .It md5
+@@ -81,11 +89,32 @@ algorithm implementations, which are loc
+ C library, and was designed to be scalable as new message digest
+ algorithms are developed.
+ .Pp
++The checksum for a directory is implemented as the hash over a list of
++one or two hashes for each of the items in the tree.
++.Bl -bullet
++.It
++For a file, the string
++.Li Dq f \&
++along with the path make up the data for one hash, and the contents of
++the file is used for the second hash.
++.It
++For a symbolic link, the string
++.Li Dq l \&
++along with the path to the symbolic link make up the data for one
++hash, and the target of the symbolic link is used for the second hash.
++.It
++For a directory, the string
++.Li Dq d \&
++along with the path make up the data for one hash.
++There is no second hash for a directory.
++.El
++.Pp
+ The
+ .Nm
+ utility exits 0 on success, and >0 if an error occurs.
+ .Sh SEE ALSO
+ .Xr cksum 1 ,
++.Xr digest 1 ,
+ .Xr md5 3 ,
+ .Xr rmd160 3 ,
+ .Xr sha1 3
+@@ -93,9 +122,13 @@ utility exits 0 on success, and >0 if an
+ The
+ .Nm
+ utility first appeared in
+-.Nx 1.6 .
++.Nx 2.0 .
+ .Sh AUTHORS
+ The
++.Xr digest 1
++utility was written by Alistair G. Crooks \*[Lt]agc@netbsd.org\*[Gt].
+ .Nm
+-utility was written by
+-.An Alistair G. Crooks Aq agc@netbsd.org .
++was implemented by Andrew Brown \*[Lt]atatat@netbsd.org\*[Gt] as a
++patch to
++.Xr digest 1
++to add recursive capabilities.
diff --git a/pkgtools/rdigest/patches/patch-ac b/pkgtools/rdigest/patches/patch-ac
new file mode 100644
index 00000000000..a3bf6e32e2f
--- /dev/null
+++ b/pkgtools/rdigest/patches/patch-ac
@@ -0,0 +1,204 @@
+$NetBSD: patch-ac,v 1.1.1.1 2003/07/24 05:21:07 atatat Exp $
+
+--- digest.c.orig 2003-07-23 20:27:09.000000000 -0400
++++ digest.c
+@@ -43,9 +43,14 @@ __RCSID("$NetBSD: digest.c,v 1.8 2003/07
+ #endif
+
+
++#include <sys/queue.h>
++#include <sys/stat.h>
++
+ #ifdef HAVE_ERRNO_H
+ #include <errno.h>
+ #endif
++#include <fcntl.h>
++#include <fts.h>
+ #ifdef HAVE_LOCALE_H
+ #include <locale.h>
+ #endif
+@@ -147,21 +152,172 @@ digest_file(char *fn, alg_t *alg)
+ return (rc);
+ }
+
++struct excl {
++ LIST_ENTRY(excl) n;
++ const char *p;
++};
++
++LIST_HEAD(, excl) excl = LIST_HEAD_INITIALIZER(excl);
++
++static void
++exclude(const char *p)
++{
++ struct excl *e;
++
++ e = malloc(sizeof(struct excl));
++ e->p = p;
++ LIST_INSERT_HEAD(&excl, e, n);
++}
++
++static int
++skip(const char *p)
++{
++ struct excl *e;
++
++ LIST_FOREACH(e, &excl, n)
++ if (strcmp(e->p, p) == 0)
++ return (1);
++
++ return (0);
++}
++
++static int
++compar(const FTSENT **fa, const FTSENT **fb)
++{
++ return (strcmp((*fa)->fts_name, (*fb)->fts_name));
++}
++
++static int
++digest_directory(char *dn, alg_t *alg)
++{
++ char in[BUFSIZ * 20], dot[2];
++ char *digest;
++ int cc, rc, l, fd, cwd;
++ char *pathlist[2];
++ FTS *ftsp;
++ FTSENT *f;
++
++ rc = 1;
++ l = alg->hash_len * 2;
++ digest = malloc(l + 1);
++ sprintf(dot, ".");
++ pathlist[0] = dot;
++ pathlist[1] = NULL;
++
++ if ((cwd = open(".", O_RDONLY)) == -1 ||
++ chdir(dn) == -1 ||
++ (ftsp = fts_open(pathlist,
++ FTS_COMFOLLOW | FTS_NOCHDIR | FTS_PHYSICAL,
++ compar)) == NULL) {
++ (void) fprintf(stderr, "%s\n", dn);
++ free(digest);
++ return (0);
++ }
++
++ (*alg->hash_init)(&alg->hash_ctx);
++
++ while ((f = fts_read(ftsp)) != NULL) {
++ /* skip the second pass on a directory */
++ if (f->fts_info == FTS_DP)
++ continue;
++
++ /* skip directories named CVS, RCS, or SCCS */
++ if ((f->fts_info == FTS_NS ||
++ S_ISDIR(f->fts_statp->st_mode)) &&
++ skip(f->fts_name)) {
++ fts_set(ftsp, f, FTS_SKIP);
++ continue;
++ }
++
++ /* try to handle things based on stat info */
++ if (f->fts_info != FTS_NS) {
++ /* only mention directories */
++ if (S_ISDIR(f->fts_statp->st_mode)) {
++ (*alg->hash_init)(&alg->hash_ctx2);
++ (*alg->hash_update)(&alg->hash_ctx2, "d ", 2);
++ (*alg->hash_update)(&alg->hash_ctx2, f->fts_path, f->fts_pathlen);
++ (*alg->hash_end)(&alg->hash_ctx2, digest);
++ digest[l] = '\n';
++ (*alg->hash_update)(&alg->hash_ctx, digest, l + 1);
++
++ /* hash the filename and then the contents separately */
++ } else if (S_ISREG(f->fts_statp->st_mode)) {
++ if ((fd = open(f->fts_path, O_RDONLY)) != -1) {
++ (*alg->hash_init)(&alg->hash_ctx2);
++ (*alg->hash_update)(&alg->hash_ctx2, "f ", 2);
++ (*alg->hash_update)(&alg->hash_ctx2, f->fts_path, f->fts_pathlen);
++ (*alg->hash_end)(&alg->hash_ctx2, &digest[0]);
++ digest[l] = '\n';
++ (*alg->hash_update)(&alg->hash_ctx, digest, 33);
++
++ (*alg->hash_init)(&alg->hash_ctx2);
++ while ((cc = read(fd, in, sizeof(in))) > 0) {
++ (*alg->hash_update)(&alg->hash_ctx2, in, cc);
++ }
++ close(fd);
++ (*alg->hash_end)(&alg->hash_ctx2, digest);
++ digest[l] = '\n';
++ (*alg->hash_update)(&alg->hash_ctx, digest, l + 1);
++ } else {
++ (void) fprintf(stderr, "%s\n", f->fts_path);
++ rc = 0;
++ }
++
++ /* hash in symlinks as well, along with the link contents */
++ } else if (S_ISLNK(f->fts_statp->st_mode)) {
++ if ((cc = readlink(f->fts_path, in, sizeof(in))) > 0) {
++ (*alg->hash_init)(&alg->hash_ctx2);
++ (*alg->hash_update)(&alg->hash_ctx2, "l ", 2);
++ (*alg->hash_update)(&alg->hash_ctx2, f->fts_path, f->fts_pathlen);
++ (*alg->hash_end)(&alg->hash_ctx2, digest);
++ digest[l] = '\n';
++ (*alg->hash_update)(&alg->hash_ctx, digest, l + 1);
++
++ (*alg->hash_init)(&alg->hash_ctx2);
++ (*alg->hash_update)(&alg->hash_ctx2, in, cc);
++ (*alg->hash_end)(&alg->hash_ctx2, digest);
++ digest[l] = '\n';
++ (*alg->hash_update)(&alg->hash_ctx, digest, l + 1);
++ } else {
++ (void) fprintf(stderr, "%s\n", f->fts_path);
++ rc = 0;
++ }
++ }
++ }
++ }
++
++ fts_close(ftsp);
++ fchdir(cwd);
++ close(cwd);
++
++ if (rc == 1) {
++ (*alg->hash_end)(&alg->hash_ctx, digest);
++ (void) printf("%s (%s) = %s\n", alg->name, dn, digest);
++ }
++
++ free(digest);
++ return (rc);
++}
++
+ int
+ main(int argc, char **argv)
+ {
+ alg_t *alg;
+ int rval;
+ int i;
++ struct stat st;
+
+ #ifdef HAVE_SETLOCALE
+ (void) setlocale(LC_ALL, "");
+ #endif
+- while ((i = getopt(argc, argv, "V")) != -1) {
++ while ((i = getopt(argc, argv, "Vx:")) != -1) {
+ switch(i) {
+ case 'V':
+ printf("%s\n", VERSION);
+ return EXIT_SUCCESS;
++ case 'x':
++ exclude(optarg);
++ break;
+ }
+ }
+ argc -= optind;
+@@ -186,7 +342,9 @@ main(int argc, char **argv)
+ }
+ } else {
+ for (i = 0 ; i < argc ; i++) {
+- if (!digest_file(argv[i], alg)) {
++ if (stat(argv[i], &st) == -1 ||
++ (S_ISREG(st.st_mode) && !digest_file(argv[i], alg)) ||
++ (S_ISDIR(st.st_mode) && !digest_directory(argv[i], alg))) {
+ (void) fprintf(stderr, "%s\n", argv[i]);
+ rval = EXIT_FAILURE;
+ }