Check in Berkeley Database code version 1.85
authorPaul Park <pjpark@mit.edu>
Fri, 26 May 1995 22:42:39 +0000 (22:42 +0000)
committerPaul Park <pjpark@mit.edu>
Fri, 26 May 1995 22:42:39 +0000 (22:42 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@5895 dc483132-0cff-0310-8789-dd5450dbe970

65 files changed:
src/util/berk_db/.Sanitize [new file with mode: 0644]
src/util/berk_db/.cvsignore [new file with mode: 0644]
src/util/berk_db/ChangeLog [new file with mode: 0644]
src/util/berk_db/Makefile.in [new file with mode: 0644]
src/util/berk_db/PORT/.Sanitize [new file with mode: 0644]
src/util/berk_db/PORT/README [new file with mode: 0644]
src/util/berk_db/PORT/clib/.Sanitize [new file with mode: 0644]
src/util/berk_db/PORT/clib/memmove.c [new file with mode: 0644]
src/util/berk_db/PORT/clib/mktemp.c [new file with mode: 0644]
src/util/berk_db/PORT/clib/snprintf.c [new file with mode: 0644]
src/util/berk_db/PORT/clib/strerror.c [new file with mode: 0644]
src/util/berk_db/PORT/include/.Sanitize [new file with mode: 0644]
src/util/berk_db/PORT/include/cdefs.h [new file with mode: 0644]
src/util/berk_db/PORT/include/compat.h [new file with mode: 0644]
src/util/berk_db/PORT/include/ndbm.h [new file with mode: 0644]
src/util/berk_db/PORT/include/queue.h [new file with mode: 0644]
src/util/berk_db/PORT/krb5/.Sanitize [new file with mode: 0644]
src/util/berk_db/PORT/krb5/include/.Sanitize [new file with mode: 0644]
src/util/berk_db/PORT/krb5/include/compat.h [new file with mode: 0644]
src/util/berk_db/PORT/krb5/sys/.Sanitize [new file with mode: 0644]
src/util/berk_db/PORT/krb5/sys/cdefs.h [new file with mode: 0644]
src/util/berk_db/README [new file with mode: 0644]
src/util/berk_db/README.krb5 [new file with mode: 0644]
src/util/berk_db/changelog [new file with mode: 0644]
src/util/berk_db/configure.in [new file with mode: 0644]
src/util/berk_db/hash/.Sanitize [new file with mode: 0644]
src/util/berk_db/hash/.cvsignore [new file with mode: 0644]
src/util/berk_db/hash/Makefile.in [new file with mode: 0644]
src/util/berk_db/hash/README [new file with mode: 0644]
src/util/berk_db/hash/configure.in [new file with mode: 0644]
src/util/berk_db/hash/extern.h [new file with mode: 0644]
src/util/berk_db/hash/hash.c [new file with mode: 0644]
src/util/berk_db/hash/hash.h [new file with mode: 0644]
src/util/berk_db/hash/hash_bigkey.c [new file with mode: 0644]
src/util/berk_db/hash/hash_buf.c [new file with mode: 0644]
src/util/berk_db/hash/hash_func.c [new file with mode: 0644]
src/util/berk_db/hash/hash_log2.c [new file with mode: 0644]
src/util/berk_db/hash/hash_page.c [new file with mode: 0644]
src/util/berk_db/hash/hsearch.c [new file with mode: 0644]
src/util/berk_db/hash/krb5_ndbm.c [new file with mode: 0644]
src/util/berk_db/hash/ndbm.c [new file with mode: 0644]
src/util/berk_db/hash/page.h [new file with mode: 0644]
src/util/berk_db/hash/search.h [new file with mode: 0644]
src/util/berk_db/include/.Sanitize [new file with mode: 0644]
src/util/berk_db/include/db.h [new file with mode: 0644]
src/util/berk_db/include/mpool.h [new file with mode: 0644]
src/util/berk_db/man/.Sanitize [new file with mode: 0644]
src/util/berk_db/man/hash.3 [new file with mode: 0644]
src/util/berk_db/test/.Sanitize [new file with mode: 0644]
src/util/berk_db/test/.cvsignore [new file with mode: 0644]
src/util/berk_db/test/Makefile.in [new file with mode: 0644]
src/util/berk_db/test/README [new file with mode: 0644]
src/util/berk_db/test/configure.in [new file with mode: 0644]
src/util/berk_db/test/dbtest.c [new file with mode: 0644]
src/util/berk_db/test/hash.tests/.Sanitize [new file with mode: 0644]
src/util/berk_db/test/hash.tests/driver2.c [new file with mode: 0644]
src/util/berk_db/test/hash.tests/makedb.sh [new file with mode: 0644]
src/util/berk_db/test/hash.tests/tcreat3.c [new file with mode: 0644]
src/util/berk_db/test/hash.tests/tdel.c [new file with mode: 0644]
src/util/berk_db/test/hash.tests/testit [new file with mode: 0644]
src/util/berk_db/test/hash.tests/thash4.c [new file with mode: 0644]
src/util/berk_db/test/hash.tests/tread2.c [new file with mode: 0644]
src/util/berk_db/test/hash.tests/tseq.c [new file with mode: 0644]
src/util/berk_db/test/hash.tests/tverify.c [new file with mode: 0644]
src/util/berk_db/test/run.test [new file with mode: 0644]

diff --git a/src/util/berk_db/.Sanitize b/src/util/berk_db/.Sanitize
new file mode 100644 (file)
index 0000000..0f8b396
--- /dev/null
@@ -0,0 +1,44 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+.cvsignore
+ChangeLog
+Makefile.in
+PORT
+README
+README.krb5
+changelog
+configure
+cofigure.in
+hash
+include
+man
+test
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/.cvsignore b/src/util/berk_db/.cvsignore
new file mode 100644 (file)
index 0000000..e8c05a6
--- /dev/null
@@ -0,0 +1 @@
+configure
diff --git a/src/util/berk_db/ChangeLog b/src/util/berk_db/ChangeLog
new file mode 100644 (file)
index 0000000..be426f5
--- /dev/null
@@ -0,0 +1,13 @@
+
+Fri May 26 16:07:52 EDT 1995   Paul Park       (pjpark@mit.edu)
+       Bring in version 1.85 of the Berkeley database code.  We only
+       use the hashed database, so that's all that's here.  There are
+       slight modifications to the code to fix one bug and to tailor
+       it for usage with Kerberos.
+
+
+Fri May 26 16:06:46 EDT 1995   Paul Park       (pjpark@mit.edu)
+       Bring in version 1.85 of the Berkeley database code.  We only
+       use the hashed database, so that's all that's here.  There are
+       slight modifications which were done to the code.
+
diff --git a/src/util/berk_db/Makefile.in b/src/util/berk_db/Makefile.in
new file mode 100644 (file)
index 0000000..3d743a0
--- /dev/null
@@ -0,0 +1,58 @@
+##DOSBUILDTOP = ..\..
+##DOS!include $(BUILDTOP)\config\windows.in
+
+TST=if test -n "`cat DONE`" ; then
+
+LIB_SUBDIRS= hash
+
+LIBUPDATE= $(BUILDTOP)/util/libupdate
+
+all:: all-$(WHAT)
+
+all-unix::
+
+all-windows::
+
+libdb_ranlib: libdb.a
+       $(RANLIB) libdb.a
+       touch $@
+
+libdb.a: hash/DONE
+       if test -f $@ ; then \
+               for i in $(LIB_SUBDIRS) ; \
+               do \
+                       $(LIBUPDATE) $@ $$i/DONE $$i ; \
+               done ; \
+       else \
+               for i in $(LIB_SUBDIRS) ; \
+               do \
+                       $(LIBUPDATE) --force $@ $$i/DONE $$i ; \
+               done ; \
+       fi
+       touch libdb.stamp
+
+install:: libdb_ranlib
+       $(INSTALL_DATA) libdb.a $(DESTDIR)$(KRB5_LIBDIR)/libdb.a
+       $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/libdb.a
+
+clean:: clean-$(WHAT)
+
+clean-unix::
+       $(RM) libdb.$(LIBEXT) libdb_ranlib libdb.stamp
+
+clean-windows::
+       $(RM) db.lib db.bak
+
+all-windows::
+       cd BERK_DB
+       @echo Making in berk_db
+       -$(MAKE) -$(MFLAGS) LIBCMD=$(LIBCMD)
+       cd ..
+
+clean-windows::
+       cd BERK_DB
+       @echo Making clean in berk_db
+       -$(MAKE) -$(MFLAGS) clean
+       cd ..
+       @echo Making clean locally
+
diff --git a/src/util/berk_db/PORT/.Sanitize b/src/util/berk_db/PORT/.Sanitize
new file mode 100644 (file)
index 0000000..213ab70
--- /dev/null
@@ -0,0 +1,35 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+README
+clib
+include
+krb5
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/PORT/README b/src/util/berk_db/PORT/README
new file mode 100644 (file)
index 0000000..6d47281
--- /dev/null
@@ -0,0 +1,131 @@
+#      @(#)README      8.6 (Berkeley) 6/20/94
+
+This is the area for building the libdb library.  There are a number
+of porting directories, for various architecture/OS combinations.  Pick
+the one that's closest to yours and try "make".  For the rest of this
+file, I'll use "MACH" as a fake architecture/OS name.
+
+To PORT to a new system, create the following subdirectories and
+symbolic links.
+
+       mkdir MACH              (for example: mkdir sunos.4.0)
+       cd MACH
+       cp ../Makefile .
+       chmod 664 Makefile
+       ln -s ../clib .
+       mkdir include
+       ln -s include sys
+       cd include
+       ln -s ../../include/*.h .
+       rm compat.h
+       cp ../../include/compat.h .
+       chmod 664 compat.h
+       cd ..
+
+The basic idea is that you now have a local area that you can modify.
+In particular, you have local copies of the Makefile and the include
+file compat.h.  Read through the Makefile and compat.h and make whatever
+changes are appropriate to your system.  If there's an architecture
+that's close to yours, you probably should diff the Makefile and
+compat.h in that tree against the standard ones and see what changes
+were necessary, as they're probably necessary for you as well.  Then,
+enter "make" and see what happens!
+
+There are several subroutines that are found in POSIX 1003.2, ANSI
+C, or 4.4BSD that you may not have.  Once you get libdb.a to compile,
+go through the list of undefined routines and add entries to the MISC
+line in the Makefile as necessary.
+
+If you have to add some functions that are missing (and which aren't
+in the PORT/clib directory), please don't add them in the PORT/clib
+directory.  Add them in a MACH/local directory, and add lines of the
+form:
+
+       function.o: local/function.o
+               ${CL} -Ilocal local/function.o
+
+to your local Makefile.
+
+Hopefully, over time, we'll develop a set of system directories that
+are known to work.  If you send me the changes that were necessary to
+make your system work, this will happen much more quickly.
+
+In some of the system directories, you'll see a file named OTHER_PATCHES.
+This is a set of patches which you'll have to make from the top-level db
+directory to get libdb.a to run on this system:
+
+       cd ..
+       patch < PORT/MACH/OTHER_PATCHES
+
+If patch prompts you for the name of the file to modify (some versions
+of patch don't figure it out on their own) use the file name which patch
+displays.
+
+Some knobs you may have to turn:
+
+In include/db.h:
+       Before attempting to build libdb, you should look through the
+       db.h file, and adjust it as necessary for your system.  The
+       only adjustments that you should need to make are for the
+       fixed sized typedef's at the top of the file.  Make sure they're
+       right for your system.
+
+In include/compat.h:
+       Before attempting to build libdb, you should look through the
+       compat.h file, and adjust it as necessary for your system.
+       It's possible to use the #ifndef construct to figure out if a
+       #ifdef has been set, but C provides no similar method to figure
+       out if a typedef has been done.  Your compile errors should
+       give you a good indication of which ones you need.
+
+You may see warning messages about illegal pointer combinations.  You may
+also see lots of warning messages about #define's being redefined.  These
+can mostly be ignored.  I usually ignore warning messages until something
+doesn't work.  Some systems produce thousands of lines of useless warnings,
+bless their little hearts.
+
+The other parts of the PORT directory are as follows:
+
+       The directory PORT/clib is a set of functions that the 4.4BSD
+       C library had and which your system may not have.  They are
+       added to the MISC line of the Makefile if they aren't defined
+       when you try and load libdb.a.
+       
+       The directory PORT/include is header files that the 4.4BSD
+       system had which your system may not have.  There is also
+       one really important extra one, named compat.h, which is a
+       set of compatibility work-arounds that you'll almost certainly
+       have to copy and modify for a new system.
+
+       The symbolic link PORT/sys points to the PORT/include directory
+       so that includes of the form <sys/include.h> work.
+
+Some of the more common portability problems:
+
+       If you don't have:
+
+               memmove(3):     add memmove.o
+               mkstemp(3):     add mktemp.o
+
+                       ... to the MISC line in the Makefile.
+
+       If you don't have snprintf/vsnprintf(3), add snprintf.o to the
+       MISC line in the Makefile.  This workaround depends on your
+       system having vsprintf(3) -- if you don't, there's no workaround
+       other than changing the source code to not use the snprintf calls.
+       If you have to make that change, check to see if your vsprintf
+       returns a length or a char *; if it's the latter, make sure you
+       set VSPRINTF_CHARSTAR in the MACH/include/compat.h file.
+
+Installing the DB library:
+
+       The Makefile builds a C library named libdb.a.  This file needs
+       to be installed in a place where the loader will automatically
+       look for it (or, if you're building it for a single project,
+       wherever that project's Makefile loads it from).
+
+       In addition, the header file PORT/include/db.h must be copied to
+       a directory (often /usr/include/) where programs that use the
+       db package can include it in their source.  (If you intend to use
+       the ndbm interface to libdb, you'll need to copy the header file
+       PORT/include/ndbm.h as well.)
diff --git a/src/util/berk_db/PORT/clib/.Sanitize b/src/util/berk_db/PORT/clib/.Sanitize
new file mode 100644 (file)
index 0000000..b9d7ef5
--- /dev/null
@@ -0,0 +1,35 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+memmove.c
+mktemp.c
+snprintf.c
+strerror.c
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/PORT/clib/memmove.c b/src/util/berk_db/PORT/clib/memmove.c
new file mode 100644 (file)
index 0000000..f90b09c
--- /dev/null
@@ -0,0 +1,139 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bcopy.c    8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/cdefs.h>
+#include <string.h>
+
+/*
+ * sizeof(word) MUST BE A POWER OF TWO
+ * SO THAT wmask BELOW IS ALL ONES
+ */
+typedef        int word;               /* "word" used for optimal copy speed */
+
+#define        wsize   sizeof(word)
+#define        wmask   (wsize - 1)
+
+/*
+ * Copy a block of memory, handling overlap.
+ * This is the routine that actually implements
+ * (the portable versions of) bcopy, memcpy, and memmove.
+ */
+#ifdef MEMCOPY
+void *
+memcpy(dst0, src0, length)
+#else
+#ifdef MEMMOVE
+void *
+memmove(dst0, src0, length)
+#else
+void
+bcopy(src0, dst0, length)
+#endif
+#endif
+       void *dst0;
+       const void *src0;
+       register size_t length;
+{
+       register char *dst = dst0;
+       register const char *src = src0;
+       register size_t t;
+
+       if (length == 0 || dst == src)          /* nothing to do */
+               goto done;
+
+       /*
+        * Macros: loop-t-times; and loop-t-times, t>0
+        */
+#define        TLOOP(s) if (t) TLOOP1(s)
+#define        TLOOP1(s) do { s; } while (--t)
+
+       if ((unsigned long)dst < (unsigned long)src) {
+               /*
+                * Copy forward.
+                */
+               t = (int)src;   /* only need low bits */
+               if ((t | (int)dst) & wmask) {
+                       /*
+                        * Try to align operands.  This cannot be done
+                        * unless the low bits match.
+                        */
+                       if ((t ^ (int)dst) & wmask || length < wsize)
+                               t = length;
+                       else
+                               t = wsize - (t & wmask);
+                       length -= t;
+                       TLOOP1(*dst++ = *src++);
+               }
+               /*
+                * Copy whole words, then mop up any trailing bytes.
+                */
+               t = length / wsize;
+               TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
+               t = length & wmask;
+               TLOOP(*dst++ = *src++);
+       } else {
+               /*
+                * Copy backwards.  Otherwise essentially the same.
+                * Alignment works as before, except that it takes
+                * (t&wmask) bytes to align, not wsize-(t&wmask).
+                */
+               src += length;
+               dst += length;
+               t = (int)src;
+               if ((t | (int)dst) & wmask) {
+                       if ((t ^ (int)dst) & wmask || length <= wsize)
+                               t = length;
+                       else
+                               t &= wmask;
+                       length -= t;
+                       TLOOP1(*--dst = *--src);
+               }
+               t = length / wsize;
+               TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
+               t = length & wmask;
+               TLOOP(*--dst = *--src);
+       }
+done:
+#if defined(MEMCOPY) || defined(MEMMOVE)
+       return (dst0);
+#else
+       return;
+#endif
+}
diff --git a/src/util/berk_db/PORT/clib/mktemp.c b/src/util/berk_db/PORT/clib/mktemp.c
new file mode 100644 (file)
index 0000000..3cdd572
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 1987, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mktemp.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+
+static int _gettemp();
+
+#if    !HAVE_MKSTEMP
+mkstemp(path)
+       char *path;
+{
+       int fd;
+
+       return (_gettemp(path, &fd) ? fd : -1);
+}
+#endif /* !HAVE_MKSTEMP */
+
+#if    !HAVE_MKTEMP
+char *
+mktemp(path)
+       char *path;
+{
+       return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
+}
+#endif /* !HAVE_MKTEMP */
+
+#if    !HAVE_MKTEMP || !HAVE_MKSTEMP
+static
+_gettemp(path, doopen)
+       char *path;
+       register int *doopen;
+{
+       extern int errno;
+       register char *start, *trv;
+       struct stat sbuf;
+       u_int pid;
+
+       pid = getpid();
+       for (trv = path; *trv; ++trv);          /* extra X's get set to 0's */
+       while (*--trv == 'X') {
+               *trv = (pid % 10) + '0';
+               pid /= 10;
+       }
+
+       /*
+        * check the target directory; if you have six X's and it
+        * doesn't exist this runs for a *very* long time.
+        */
+       for (start = trv + 1;; --trv) {
+               if (trv <= path)
+                       break;
+               if (*trv == '/') {
+                       *trv = '\0';
+                       if (stat(path, &sbuf))
+                               return(0);
+                       if (!S_ISDIR(sbuf.st_mode)) {
+                               errno = ENOTDIR;
+                               return(0);
+                       }
+                       *trv = '/';
+                       break;
+               }
+       }
+
+       for (;;) {
+               if (doopen) {
+                       if ((*doopen =
+                           open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+                               return(1);
+                       if (errno != EEXIST)
+                               return(0);
+               }
+               else if (stat(path, &sbuf))
+                       return(errno == ENOENT ? 1 : 0);
+
+               /* tricky little algorithm for backward compatibility */
+               for (trv = start;;) {
+                       if (!*trv)
+                               return(0);
+                       if (*trv == 'z')
+                               *trv++ = 'a';
+                       else {
+                               if (isdigit(*trv))
+                                       *trv = 'a';
+                               else
+                                       ++*trv;
+                               break;
+                       }
+               }
+       }
+       /*NOTREACHED*/
+}
+#endif /* !HAVE_MKTEMP || !HAVE_MKSTEMP */
diff --git a/src/util/berk_db/PORT/clib/snprintf.c b/src/util/berk_db/PORT/clib/snprintf.c
new file mode 100644 (file)
index 0000000..2863fa2
--- /dev/null
@@ -0,0 +1,54 @@
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+#include <compat.h>
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+int
+#ifdef __STDC__
+snprintf(char *str, size_t n, const char *fmt, ...)
+#else
+snprintf(str, n, fmt, va_alist)
+       char *str;
+       size_t n;
+       const char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+       char *rp;
+       int rval;
+#ifdef __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+#ifdef VSPRINTF_CHARSTAR
+       rp = vsprintf(str, fmt, ap);
+       va_end(ap);
+       return (strlen(rp));
+#else
+       rval = vsprintf(str, fmt, ap);
+       va_end(ap);
+       return (rval);
+#endif
+}
+
+int
+vsnprintf(str, n, fmt, ap)
+       char *str;
+       size_t n;
+       const char *fmt;
+       va_list ap;
+{
+#ifdef VSPRINTF_CHARSTAR
+       return (strlen(vsprintf(str, fmt, ap)));
+#else
+       return (vsprintf(str, fmt, ap));
+#endif
+}
diff --git a/src/util/berk_db/PORT/clib/strerror.c b/src/util/berk_db/PORT/clib/strerror.c
new file mode 100644 (file)
index 0000000..53f374b
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+
+char *
+strerror(num)
+       int num;
+{
+       extern int sys_nerr;
+       extern char *sys_errlist[];
+#define        UPREFIX "Unknown error: "
+       static char ebuf[40] = UPREFIX;         /* 64-bit number + slop */
+       register unsigned int errnum;
+       register char *p, *t;
+       char tmp[40];
+
+       errnum = num;                           /* convert to unsigned */
+       if (errnum < sys_nerr)
+               return(sys_errlist[errnum]);
+
+       /* Do this by hand, so we don't include stdio(3). */
+       t = tmp;
+       do {
+               *t++ = "0123456789"[errnum % 10];
+       } while (errnum /= 10);
+       for (p = ebuf + sizeof(UPREFIX) - 1;;) {
+               *p++ = *--t;
+               if (t <= tmp)
+                       break;
+       }
+       return(ebuf);
+}
diff --git a/src/util/berk_db/PORT/include/.Sanitize b/src/util/berk_db/PORT/include/.Sanitize
new file mode 100644 (file)
index 0000000..77efe8c
--- /dev/null
@@ -0,0 +1,35 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+cdefs.h
+compat.h
+ndbm.h
+queue.h
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/PORT/include/cdefs.h b/src/util/berk_db/PORT/include/cdefs.h
new file mode 100644 (file)
index 0000000..c104b9e
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)cdefs.h     8.7 (Berkeley) 1/21/94
+ */
+
+#ifndef        _CDEFS_H_
+#define        _CDEFS_H_
+
+#if defined(__cplusplus)
+#define        __BEGIN_DECLS   extern "C" {
+#define        __END_DECLS     };
+#else
+#define        __BEGIN_DECLS
+#define        __END_DECLS
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments.  __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define        __P(protos)     protos          /* full-blown ANSI C */
+#define        __CONCAT(x,y)   x ## y
+#define        __STRING(x)     #x
+
+#define        __const         const           /* define reserved names to standard */
+#define        __signed        signed
+#define        __volatile      volatile
+#if defined(__cplusplus)
+#define        __inline        inline          /* convert to C++ keyword */
+#else
+#ifndef __GNUC__
+#define        __inline                        /* delete GCC keyword */
+#endif /* !__GNUC__ */
+#endif /* !__cplusplus */
+
+#else  /* !(__STDC__ || __cplusplus) */
+#define        __P(protos)     ()              /* traditional C preprocessor */
+#define        __CONCAT(x,y)   x/**/y
+#define        __STRING(x)     "x"
+
+#ifndef __GNUC__
+#define        __const                         /* delete pseudo-ANSI C keywords */
+#define        __inline
+#define        __signed
+#define        __volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef        NO_ANSI_KEYWORDS
+#define        const                           /* delete ANSI C keywords */
+#define        inline
+#define        signed
+#define        volatile
+#endif
+#endif /* !__GNUC__ */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC2 uses a new, peculiar __attribute__((attrs)) style.  All of
+ * these work for GNU C++ (modulo a slight glitch in the C++ grammar
+ * in the distribution version of 2.5.5).
+ */
+#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
+#define        __attribute__(x)        /* delete __attribute__ if non-gcc or gcc1 */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define        __dead          __volatile
+#define        __pure          __const
+#endif
+#endif
+
+/* Delete pseudo-keywords wherever they are not available or needed. */
+#ifndef __dead
+#define        __dead
+#define        __pure
+#endif
+
+#endif /* !_CDEFS_H_ */
diff --git a/src/util/berk_db/PORT/include/compat.h b/src/util/berk_db/PORT/include/compat.h
new file mode 100644 (file)
index 0000000..2bd360a
--- /dev/null
@@ -0,0 +1,231 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)compat.h    8.13 (Berkeley) 2/21/94
+ */
+
+#ifndef        _COMPAT_H_
+#define        _COMPAT_H_
+
+#include <sys/types.h>
+
+/*
+ * If your system doesn't typedef u_long, u_short, or u_char, change
+ * the 0 to a 1.
+ */
+#if 0
+typedef unsigned char  u_char;         /* 4.[34]BSD names. */
+typedef unsigned int   u_int;
+typedef unsigned long  u_long;
+typedef unsigned short u_short;
+#endif
+
+/* If your system doesn't typedef size_t, change the 0 to a 1. */
+#if 0
+typedef unsigned int   size_t;         /* POSIX, 4.[34]BSD names. */
+#endif
+
+/* If your system doesn't typedef ssize_t, change the 0 to a 1. */
+#if 0
+typedef        int             ssize_t;        /* POSIX names. */
+#endif
+
+/*
+ * If your system doesn't have the POSIX type for a signal mask,
+ * change the 0 to a 1.
+ */
+#if 0                                  /* POSIX 1003.1 signal mask type. */
+typedef unsigned int   sigset_t;
+#endif
+
+/*
+ * If your system's vsprintf returns a char *, not an int,
+ * change the 0 to a 1.
+ */
+#if 0
+#define        VSPRINTF_CHARSTAR
+#endif
+
+/*
+ * If you don't have POSIX 1003.1 signals, the signal code surrounding the 
+ * temporary file creation is intended to block all of the possible signals
+ * long enough to create the file and unlink it.  All of this stuff is
+ * intended to use old-style BSD calls to fake POSIX 1003.1 calls.
+ */
+#ifdef NO_POSIX_SIGNALS
+#define        sigemptyset(set)        (*(set) = 0)
+#define        sigfillset(set)         (*(set) = ~(sigset_t)0, 0)
+#define        sigaddset(set,signo)    (*(set) |= sigmask(signo), 0)
+#define        sigdelset(set,signo)    (*(set) &= ~sigmask(signo), 0)
+#define        sigismember(set,signo)  ((*(set) & sigmask(signo)) != 0)
+
+#define        SIG_BLOCK       1
+#define        SIG_UNBLOCK     2
+#define        SIG_SETMASK     3
+
+static int __sigtemp;          /* For the use of sigprocmask */
+
+/* Repeated test of oset != NULL is to avoid "*0". */
+#define        sigprocmask(how, set, oset)                                     \
+       ((__sigtemp =                                                   \
+       (((how) == SIG_BLOCK) ?                                         \
+               sigblock(0) | *(set) :                                  \
+       (((how) == SIG_UNBLOCK) ?                                       \
+               sigblock(0) & ~(*(set)) :                               \
+       ((how) == SIG_SETMASK ?                                         \
+               *(set) : sigblock(0))))),                               \
+       ((oset) ? (*(oset ? oset : set) = sigsetmask(__sigtemp)) :      \
+               sigsetmask(__sigtemp)), 0)
+#endif
+
+/*
+ * If your system doesn't have an include file with the appropriate
+ * byte order set, make sure you specify the correct one.
+ */
+#ifndef BYTE_ORDER
+#define        LITTLE_ENDIAN   1234            /* LSB first: i386, vax */
+#define        BIG_ENDIAN      4321            /* MSB first: 68000, ibm, net */
+#define        BYTE_ORDER      BIG_ENDIAN      /* Set for your system. */
+#endif
+
+#if defined(SYSV) || defined(SYSTEM5)
+#define        index(a, b)             strchr(a, b)
+#define        rindex(a, b)            strrchr(a, b)
+#define        bzero(a, b)             memset(a, 0, b)
+#define        bcmp(a, b, n)           memcmp(a, b, n)
+#define        bcopy(a, b, n)          memmove(b, a, n)
+#endif
+
+#if defined(BSD) || defined(BSD4_3)
+#define        strchr(a, b)            index(a, b)
+#define        strrchr(a, b)           rindex(a, b)
+#define        memcmp(a, b, n)         bcmp(a, b, n)
+#define        memmove(a, b, n)        bcopy(b, a, n)
+#endif
+
+/*
+ * 32-bit machine.  The db routines are theoretically independent of
+ * the size of u_shorts and u_longs, but I don't know that anyone has
+ * ever actually tried it.  At a minimum, change the following #define's
+ * if you are trying to compile on a different type of system.
+ */
+#ifndef USHRT_MAX
+#define        USHRT_MAX               0xFFFF
+#define        ULONG_MAX               0xFFFFFFFF
+#endif
+
+#ifndef O_ACCMODE                      /* POSIX 1003.1 access mode mask. */
+#define        O_ACCMODE       (O_RDONLY|O_WRONLY|O_RDWR)
+#endif
+
+#ifndef        _POSIX2_RE_DUP_MAX              /* POSIX 1003.2 RE limit. */
+#define        _POSIX2_RE_DUP_MAX      255
+#endif
+
+/*
+ * If you can't provide lock values in the open(2) call.  Note, this
+ * allows races to happen.
+ */
+#ifndef O_EXLOCK                       /* 4.4BSD extension. */
+#define        O_EXLOCK        0
+#endif
+
+#ifndef O_SHLOCK                       /* 4.4BSD extension. */
+#define        O_SHLOCK        0
+#endif
+
+#ifndef EFTYPE
+#define        EFTYPE          EINVAL          /* POSIX 1003.1 format errno. */
+#endif
+
+#ifndef        WCOREDUMP                       /* 4.4BSD extension */
+#define        WCOREDUMP(a)    0
+#endif
+
+#ifndef        STDERR_FILENO
+#define        STDIN_FILENO    0               /* ANSI C #defines */
+#define        STDOUT_FILENO   1
+#define        STDERR_FILENO   2
+#endif
+
+#ifndef SEEK_END
+#define        SEEK_SET        0               /* POSIX 1003.1 seek values */
+#define        SEEK_CUR        1
+#define        SEEK_END        2
+#endif
+
+#ifndef _POSIX_VDISABLE                        /* POSIX 1003.1 disabling char. */
+#define        _POSIX_VDISABLE 0               /* Some systems used 0. */
+#endif
+
+#ifndef        TCSASOFT                        /* 4.4BSD extension. */
+#define        TCSASOFT        0
+#endif
+
+#ifndef _POSIX2_RE_DUP_MAX             /* POSIX 1003.2 values. */
+#define        _POSIX2_RE_DUP_MAX      255
+#endif
+
+#ifndef NULL                           /* ANSI C #defines NULL everywhere. */
+#define        NULL            0
+#endif
+
+#ifndef        MAX                             /* Usually found in <sys/param.h>. */
+#define        MAX(_a,_b)      ((_a)<(_b)?(_b):(_a))
+#endif
+#ifndef        MIN                             /* Usually found in <sys/param.h>. */
+#define        MIN(_a,_b)      ((_a)<(_b)?(_a):(_b))
+#endif
+
+/* Default file permissions. */
+#ifndef DEFFILEMODE                    /* 4.4BSD extension. */
+#define        DEFFILEMODE     (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
+#endif
+
+#ifndef S_ISDIR                                /* POSIX 1003.1 file type tests. */
+#define        S_ISDIR(m)      ((m & 0170000) == 0040000)      /* directory */
+#define        S_ISCHR(m)      ((m & 0170000) == 0020000)      /* char special */
+#define        S_ISBLK(m)      ((m & 0170000) == 0060000)      /* block special */
+#define        S_ISREG(m)      ((m & 0170000) == 0100000)      /* regular file */
+#define        S_ISFIFO(m)     ((m & 0170000) == 0010000)      /* fifo */
+#endif
+#ifndef S_ISLNK                                /* BSD POSIX 1003.1 extensions */
+#define        S_ISLNK(m)      ((m & 0170000) == 0120000)      /* symbolic link */
+#define        S_ISSOCK(m)     ((m & 0170000) == 0140000)      /* socket */
+#endif
+
+/* The type of a va_list. */
+#ifndef _BSD_VA_LIST_                  /* 4.4BSD #define. */
+#define        _BSD_VA_LIST_   char *
+#endif
+
+#endif /* !_COMPAT_H_ */
diff --git a/src/util/berk_db/PORT/include/ndbm.h b/src/util/berk_db/PORT/include/ndbm.h
new file mode 100644 (file)
index 0000000..a545bca
--- /dev/null
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)ndbm.h      8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _NDBM_H_
+#define        _NDBM_H_
+
+#include <db.h>
+
+/* Map dbm interface onto db(3). */
+#define DBM_RDONLY     O_RDONLY
+
+/* Flags to dbm_store(). */
+#define DBM_INSERT      0
+#define DBM_REPLACE     1
+
+/*
+ * The db(3) support for ndbm(3) always appends this suffix to the
+ * file name to avoid overwriting the user's original database.
+ */
+#define        DBM_SUFFIX      ".db"
+
+typedef struct {
+       char *dptr;
+       int dsize;
+} datum;
+
+typedef DB DBM;
+#define        dbm_pagfno(a)   DBM_PAGFNO_NOT_AVAILABLE
+
+__BEGIN_DECLS
+void    dbm_close __P((DBM *));
+int     dbm_delete __P((DBM *, datum));
+datum   dbm_fetch __P((DBM *, datum));
+datum   dbm_firstkey __P((DBM *));
+long    dbm_forder __P((DBM *, datum));
+datum   dbm_nextkey __P((DBM *));
+DBM    *dbm_open __P((const char *, int, int));
+int     dbm_store __P((DBM *, datum, datum, int));
+int     dbm_dirfno __P((DBM *));
+__END_DECLS
+
+#endif /* !_NDBM_H_ */
diff --git a/src/util/berk_db/PORT/include/queue.h b/src/util/berk_db/PORT/include/queue.h
new file mode 100644 (file)
index 0000000..40d32cc
--- /dev/null
@@ -0,0 +1,245 @@
+/* 
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)queue.h     8.3 (Berkeley) 12/13/93
+ */
+
+#ifndef        _QUEUE_H_
+#define        _QUEUE_H_
+
+/*
+ * This file defines three types of data structures: lists, tail queues,
+ * and circular queues.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list after
+ * an existing element or at the head of the list. A list may only be
+ * traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A tail queue may only be traversed in the forward direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type)                                          \
+struct name {                                                          \
+       struct type *lh_first;  /* first element */                     \
+}
+
+#define LIST_ENTRY(type)                                               \
+struct {                                                               \
+       struct type *le_next;   /* next element */                      \
+       struct type **le_prev;  /* address of previous next element */  \
+}
+
+/*
+ * List functions.
+ */
+#define        LIST_INIT(head) {                                               \
+       (head)->lh_first = NULL;                                        \
+}
+
+#define LIST_INSERT_AFTER(listelm, elm, field) {                       \
+       if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
+               (listelm)->field.le_next->field.le_prev =               \
+                   &(elm)->field.le_next;                              \
+       (listelm)->field.le_next = (elm);                               \
+       (elm)->field.le_prev = &(listelm)->field.le_next;               \
+}
+
+#define LIST_INSERT_HEAD(head, elm, field) {                           \
+       if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
+               (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+       (head)->lh_first = (elm);                                       \
+       (elm)->field.le_prev = &(head)->lh_first;                       \
+}
+
+#define LIST_REMOVE(elm, field) {                                      \
+       if ((elm)->field.le_next != NULL)                               \
+               (elm)->field.le_next->field.le_prev =                   \
+                   (elm)->field.le_prev;                               \
+       *(elm)->field.le_prev = (elm)->field.le_next;                   \
+}
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type)                                         \
+struct name {                                                          \
+       struct type *tqh_first; /* first element */                     \
+       struct type **tqh_last; /* addr of last next element */         \
+}
+
+#define TAILQ_ENTRY(type)                                              \
+struct {                                                               \
+       struct type *tqe_next;  /* next element */                      \
+       struct type **tqe_prev; /* address of previous next element */  \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define        TAILQ_INIT(head) {                                              \
+       (head)->tqh_first = NULL;                                       \
+       (head)->tqh_last = &(head)->tqh_first;                          \
+}
+
+#define TAILQ_INSERT_HEAD(head, elm, field) {                          \
+       if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        \
+               (elm)->field.tqe_next->field.tqe_prev =                 \
+                   &(elm)->field.tqe_next;                             \
+       else                                                            \
+               (head)->tqh_last = &(elm)->field.tqe_next;              \
+       (head)->tqh_first = (elm);                                      \
+       (elm)->field.tqe_prev = &(head)->tqh_first;                     \
+}
+
+#define TAILQ_INSERT_TAIL(head, elm, field) {                          \
+       (elm)->field.tqe_next = NULL;                                   \
+       (elm)->field.tqe_prev = (head)->tqh_last;                       \
+       *(head)->tqh_last = (elm);                                      \
+       (head)->tqh_last = &(elm)->field.tqe_next;                      \
+}
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) {                        \
+       if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+               (elm)->field.tqe_next->field.tqe_prev =                 \
+                   &(elm)->field.tqe_next;                             \
+       else                                                            \
+               (head)->tqh_last = &(elm)->field.tqe_next;              \
+       (listelm)->field.tqe_next = (elm);                              \
+       (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             \
+}
+
+#define TAILQ_REMOVE(head, elm, field) {                               \
+       if (((elm)->field.tqe_next) != NULL)                            \
+               (elm)->field.tqe_next->field.tqe_prev =                 \
+                   (elm)->field.tqe_prev;                              \
+       else                                                            \
+               (head)->tqh_last = (elm)->field.tqe_prev;               \
+       *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 \
+}
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type)                                       \
+struct name {                                                          \
+       struct type *cqh_first;         /* first element */             \
+       struct type *cqh_last;          /* last element */              \
+}
+
+#define CIRCLEQ_ENTRY(type)                                            \
+struct {                                                               \
+       struct type *cqe_next;          /* next element */              \
+       struct type *cqe_prev;          /* previous element */          \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define        CIRCLEQ_INIT(head) {                                            \
+       (head)->cqh_first = (void *)(head);                             \
+       (head)->cqh_last = (void *)(head);                              \
+}
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) {              \
+       (elm)->field.cqe_next = (listelm)->field.cqe_next;              \
+       (elm)->field.cqe_prev = (listelm);                              \
+       if ((listelm)->field.cqe_next == (void *)(head))                \
+               (head)->cqh_last = (elm);                               \
+       else                                                            \
+               (listelm)->field.cqe_next->field.cqe_prev = (elm);      \
+       (listelm)->field.cqe_next = (elm);                              \
+}
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) {             \
+       (elm)->field.cqe_next = (listelm);                              \
+       (elm)->field.cqe_prev = (listelm)->field.cqe_prev;              \
+       if ((listelm)->field.cqe_prev == (void *)(head))                \
+               (head)->cqh_first = (elm);                              \
+       else                                                            \
+               (listelm)->field.cqe_prev->field.cqe_next = (elm);      \
+       (listelm)->field.cqe_prev = (elm);                              \
+}
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) {                                \
+       (elm)->field.cqe_next = (head)->cqh_first;                      \
+       (elm)->field.cqe_prev = (void *)(head);                         \
+       if ((head)->cqh_last == (void *)(head))                         \
+               (head)->cqh_last = (elm);                               \
+       else                                                            \
+               (head)->cqh_first->field.cqe_prev = (elm);              \
+       (head)->cqh_first = (elm);                                      \
+}
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) {                                \
+       (elm)->field.cqe_next = (void *)(head);                         \
+       (elm)->field.cqe_prev = (head)->cqh_last;                       \
+       if ((head)->cqh_first == (void *)(head))                        \
+               (head)->cqh_first = (elm);                              \
+       else                                                            \
+               (head)->cqh_last->field.cqe_next = (elm);               \
+       (head)->cqh_last = (elm);                                       \
+}
+
+#define        CIRCLEQ_REMOVE(head, elm, field) {                              \
+       if ((elm)->field.cqe_next == (void *)(head))                    \
+               (head)->cqh_last = (elm)->field.cqe_prev;               \
+       else                                                            \
+               (elm)->field.cqe_next->field.cqe_prev =                 \
+                   (elm)->field.cqe_prev;                              \
+       if ((elm)->field.cqe_prev == (void *)(head))                    \
+               (head)->cqh_first = (elm)->field.cqe_next;              \
+       else                                                            \
+               (elm)->field.cqe_prev->field.cqe_next =                 \
+                   (elm)->field.cqe_next;                              \
+}
+#endif /* !_QUEUE_H_ */
diff --git a/src/util/berk_db/PORT/krb5/.Sanitize b/src/util/berk_db/PORT/krb5/.Sanitize
new file mode 100644 (file)
index 0000000..0dbbe7d
--- /dev/null
@@ -0,0 +1,33 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+include
+sys
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/PORT/krb5/include/.Sanitize b/src/util/berk_db/PORT/krb5/include/.Sanitize
new file mode 100644 (file)
index 0000000..2f4e847
--- /dev/null
@@ -0,0 +1,32 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+compat.h
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/PORT/krb5/include/compat.h b/src/util/berk_db/PORT/krb5/include/compat.h
new file mode 100644 (file)
index 0000000..fde6c38
--- /dev/null
@@ -0,0 +1,258 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)compat.h    8.13 (Berkeley) 2/21/94
+ */
+
+#ifndef        _COMPAT_H_
+#define        _COMPAT_H_
+
+#include <sys/types.h>
+
+/*
+ * If your system doesn't typedef u_long, u_short, or u_char, change
+ * the 0 to a 1.
+ */
+#if 0
+typedef unsigned char  u_char;         /* 4.[34]BSD names. */
+typedef unsigned int   u_int;
+typedef unsigned long  u_long;
+typedef unsigned short u_short;
+#endif
+
+/* If your system doesn't typedef size_t, change the 0 to a 1. */
+#if 0
+typedef unsigned int   size_t;         /* POSIX, 4.[34]BSD names. */
+#endif
+
+/* If your system doesn't typedef ssize_t, change the 0 to a 1. */
+#if 0
+typedef        int             ssize_t;        /* POSIX names. */
+#endif
+
+/*
+ * If your system doesn't have the POSIX type for a signal mask,
+ * change the 0 to a 1.
+ */
+#if !POSIX_SIGNALS                     /* POSIX 1003.1 signal mask type. */
+typedef unsigned int   sigset_t;
+#endif
+
+/*
+ * If your system's vsprintf returns a char *, not an int,
+ * change the 0 to a 1.
+ */
+#if 0
+#define        VSPRINTF_CHARSTAR
+#endif
+
+/*
+ * If you don't have POSIX 1003.1 signals, the signal code surrounding the 
+ * temporary file creation is intended to block all of the possible signals
+ * long enough to create the file and unlink it.  All of this stuff is
+ * intended to use old-style BSD calls to fake POSIX 1003.1 calls.
+ */
+#if    !POSIX_SIGNALS
+#define        sigemptyset(set)        (*(set) = 0)
+#define        sigfillset(set)         (*(set) = ~(sigset_t)0, 0)
+#define        sigaddset(set,signo)    (*(set) |= sigmask(signo), 0)
+#define        sigdelset(set,signo)    (*(set) &= ~sigmask(signo), 0)
+#define        sigismember(set,signo)  ((*(set) & sigmask(signo)) != 0)
+
+#define        SIG_BLOCK       1
+#define        SIG_UNBLOCK     2
+#define        SIG_SETMASK     3
+
+static int __sigtemp;          /* For the use of sigprocmask */
+
+/* Repeated test of oset != NULL is to avoid "*0". */
+#define        sigprocmask(how, set, oset)                                     \
+       ((__sigtemp =                                                   \
+       (((how) == SIG_BLOCK) ?                                         \
+               sigblock(0) | *(set) :                                  \
+       (((how) == SIG_UNBLOCK) ?                                       \
+               sigblock(0) & ~(*(set)) :                               \
+       ((how) == SIG_SETMASK ?                                         \
+               *(set) : sigblock(0))))),                               \
+       ((oset) ? (*(oset ? oset : set) = sigsetmask(__sigtemp)) :      \
+               sigsetmask(__sigtemp)), 0)
+#endif
+
+/*
+ * If your system doesn't have an include file with the appropriate
+ * byte order set, make sure you specify the correct one.
+ */
+#ifndef BYTE_ORDER
+#define        LITTLE_ENDIAN   1234            /* LSB first: i386, vax */
+#define        BIG_ENDIAN      4321            /* MSB first: 68000, ibm, net */
+#define        BYTE_ORDER      LITTLE_ENDIAN   /* Set for your system. */
+#endif
+
+#if defined(SYSV) || defined(SYSTEM5)
+#define        index(a, b)             strchr(a, b)
+#define        rindex(a, b)            strrchr(a, b)
+#define        bzero(a, b)             memset(a, 0, b)
+#define        bcmp(a, b, n)           memcmp(a, b, n)
+#define        bcopy(a, b, n)          memmove(b, a, n)
+#endif
+
+#if defined(BSD) || defined(BSD4_3)
+#define        strchr(a, b)            index(a, b)
+#define        strrchr(a, b)           rindex(a, b)
+#define        memcmp(a, b, n)         bcmp(a, b, n)
+#define        memmove(a, b, n)        bcopy(b, a, n)
+#endif
+
+/*
+ * 32-bit machine.  The db routines are theoretically independent of
+ * the size of u_shorts and u_longs, but I don't know that anyone has
+ * ever actually tried it.  At a minimum, change the following #define's
+ * if you are trying to compile on a different type of system.
+ */
+#ifndef        USHRT_MAX
+#if    (SIZEOF_SHORT == 2)
+#define        USHRT_MAX               0xffff
+#elif  (SIZEOF_SHORT == 4)
+#define        USHRT_MAX               0xffffffff
+#else
+error : dont know how to deal with short size
+#endif
+#endif /* USHRT_MAX */
+
+#ifndef        UINT_MAX
+#if    (SIZEOF_INT == 2)
+#define        UINT_MAX                0xffff
+#elif  (SIZEOF_INT == 4)
+#define        UINT_MAX                0xffffffff
+#elif  (SIZEOF_INT == 8)
+#define        UINT_MAX                0xffffffffffffffff
+#else
+error : dont know how to deal with int size
+#endif
+#endif /* UINT_MAX */
+
+#ifndef        ULONG_MAX
+#if    (SIZEOF_LONG == 4)
+#define        ULONG_MAX               0xFFFFFFFF
+#elif  (SIZEOF_LONG == 8)
+#define        ULONG_MAX               0xffffffffffffffff
+#else
+error : dont know how to deal with long size
+#endif
+#endif /* ULONG_MAX */
+
+#ifndef O_ACCMODE                      /* POSIX 1003.1 access mode mask. */
+#define        O_ACCMODE       (O_RDONLY|O_WRONLY|O_RDWR)
+#endif
+
+#ifndef        _POSIX2_RE_DUP_MAX              /* POSIX 1003.2 RE limit. */
+#define        _POSIX2_RE_DUP_MAX      255
+#endif
+
+/*
+ * If you can't provide lock values in the open(2) call.  Note, this
+ * allows races to happen.
+ */
+#ifndef O_EXLOCK                       /* 4.4BSD extension. */
+#define        O_EXLOCK        0
+#endif
+
+#ifndef O_SHLOCK                       /* 4.4BSD extension. */
+#define        O_SHLOCK        0
+#endif
+
+#ifndef EFTYPE
+#define        EFTYPE          EINVAL          /* POSIX 1003.1 format errno. */
+#endif
+
+#ifndef        WCOREDUMP                       /* 4.4BSD extension */
+#define        WCOREDUMP(a)    0
+#endif
+
+#ifndef        STDERR_FILENO
+#define        STDIN_FILENO    0               /* ANSI C #defines */
+#define        STDOUT_FILENO   1
+#define        STDERR_FILENO   2
+#endif
+
+#ifndef SEEK_END
+#define        SEEK_SET        0               /* POSIX 1003.1 seek values */
+#define        SEEK_CUR        1
+#define        SEEK_END        2
+#endif
+
+#ifndef _POSIX_VDISABLE                        /* POSIX 1003.1 disabling char. */
+#define        _POSIX_VDISABLE 0               /* Some systems used 0. */
+#endif
+
+#ifndef        TCSASOFT                        /* 4.4BSD extension. */
+#define        TCSASOFT        0
+#endif
+
+#ifndef _POSIX2_RE_DUP_MAX             /* POSIX 1003.2 values. */
+#define        _POSIX2_RE_DUP_MAX      255
+#endif
+
+#ifndef NULL                           /* ANSI C #defines NULL everywhere. */
+#define        NULL            0
+#endif
+
+#ifndef        MAX                             /* Usually found in <sys/param.h>. */
+#define        MAX(_a,_b)      ((_a)<(_b)?(_b):(_a))
+#endif
+#ifndef        MIN                             /* Usually found in <sys/param.h>. */
+#define        MIN(_a,_b)      ((_a)<(_b)?(_a):(_b))
+#endif
+
+/* Default file permissions. */
+#ifndef DEFFILEMODE                    /* 4.4BSD extension. */
+#define        DEFFILEMODE     (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
+#endif
+
+#ifndef S_ISDIR                                /* POSIX 1003.1 file type tests. */
+#define        S_ISDIR(m)      ((m & 0170000) == 0040000)      /* directory */
+#define        S_ISCHR(m)      ((m & 0170000) == 0020000)      /* char special */
+#define        S_ISBLK(m)      ((m & 0170000) == 0060000)      /* block special */
+#define        S_ISREG(m)      ((m & 0170000) == 0100000)      /* regular file */
+#define        S_ISFIFO(m)     ((m & 0170000) == 0010000)      /* fifo */
+#endif
+#ifndef S_ISLNK                                /* BSD POSIX 1003.1 extensions */
+#define        S_ISLNK(m)      ((m & 0170000) == 0120000)      /* symbolic link */
+#define        S_ISSOCK(m)     ((m & 0170000) == 0140000)      /* socket */
+#endif
+
+/* The type of a va_list. */
+#ifndef _BSD_VA_LIST_                  /* 4.4BSD #define. */
+#define        _BSD_VA_LIST_   char *
+#endif
+
+#endif /* !_COMPAT_H_ */
diff --git a/src/util/berk_db/PORT/krb5/sys/.Sanitize b/src/util/berk_db/PORT/krb5/sys/.Sanitize
new file mode 100644 (file)
index 0000000..e99e014
--- /dev/null
@@ -0,0 +1,32 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+cdefs.h
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/PORT/krb5/sys/cdefs.h b/src/util/berk_db/PORT/krb5/sys/cdefs.h
new file mode 100644 (file)
index 0000000..c104b9e
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)cdefs.h     8.7 (Berkeley) 1/21/94
+ */
+
+#ifndef        _CDEFS_H_
+#define        _CDEFS_H_
+
+#if defined(__cplusplus)
+#define        __BEGIN_DECLS   extern "C" {
+#define        __END_DECLS     };
+#else
+#define        __BEGIN_DECLS
+#define        __END_DECLS
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments.  __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define        __P(protos)     protos          /* full-blown ANSI C */
+#define        __CONCAT(x,y)   x ## y
+#define        __STRING(x)     #x
+
+#define        __const         const           /* define reserved names to standard */
+#define        __signed        signed
+#define        __volatile      volatile
+#if defined(__cplusplus)
+#define        __inline        inline          /* convert to C++ keyword */
+#else
+#ifndef __GNUC__
+#define        __inline                        /* delete GCC keyword */
+#endif /* !__GNUC__ */
+#endif /* !__cplusplus */
+
+#else  /* !(__STDC__ || __cplusplus) */
+#define        __P(protos)     ()              /* traditional C preprocessor */
+#define        __CONCAT(x,y)   x/**/y
+#define        __STRING(x)     "x"
+
+#ifndef __GNUC__
+#define        __const                         /* delete pseudo-ANSI C keywords */
+#define        __inline
+#define        __signed
+#define        __volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef        NO_ANSI_KEYWORDS
+#define        const                           /* delete ANSI C keywords */
+#define        inline
+#define        signed
+#define        volatile
+#endif
+#endif /* !__GNUC__ */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC2 uses a new, peculiar __attribute__((attrs)) style.  All of
+ * these work for GNU C++ (modulo a slight glitch in the C++ grammar
+ * in the distribution version of 2.5.5).
+ */
+#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
+#define        __attribute__(x)        /* delete __attribute__ if non-gcc or gcc1 */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define        __dead          __volatile
+#define        __pure          __const
+#endif
+#endif
+
+/* Delete pseudo-keywords wherever they are not available or needed. */
+#ifndef __dead
+#define        __dead
+#define        __pure
+#endif
+
+#endif /* !_CDEFS_H_ */
diff --git a/src/util/berk_db/README b/src/util/berk_db/README
new file mode 100644 (file)
index 0000000..bed2c92
--- /dev/null
@@ -0,0 +1,40 @@
+#      @(#)README      8.27 (Berkeley) 9/1/94
+
+This is version 1.85 of the Berkeley DB code.
+
+For information on compiling and installing this software, see the file
+PORT/README.
+
+Newer versions of this software will periodically be made available by
+anonymous ftp from ftp.cs.berkeley.edu.  An archive in compressed format
+is in ucb/4bsd/db.tar.Z, or in gzip format in ucb/4bsd/db.tar.gz.  If
+you'd like to receive announcements of future releases of this software,
+send email to the contact address below.
+
+Email questions may be addressed to Keith Bostic at bostic@cs.berkeley.edu.
+
+============================================
+Distribution contents:
+
+Makefile.inc   Ignore this, it's the 4.4BSD subsystem Makefile.
+PORT           The per OS/architecture directories to use to build
+               libdb.a, if you're not running 4.4BSD.  See the file
+               PORT/README for more information.
+README         This file.
+btree          The B+tree routines.
+changelog      List of changes, per version.
+db             The dbopen(3) interface routine.
+docs           Various USENIX papers, and the formatted manual pages.
+hash           The extended linear hashing routines.
+man            The unformatted manual pages.
+mpool          The memory pool routines.
+recno          The fixed/variable length record routines.
+test           Test package.
+
+============================================
+Debugging:
+
+If you're running a memory checker (e.g. Purify) on DB, make sure that
+you recompile it with "-DPURIFY" in the CFLAGS, first.  By default,
+allocated pages are not initialized by the DB code, and they will show
+up as reads of uninitialized memory in the buffer write routines.
diff --git a/src/util/berk_db/README.krb5 b/src/util/berk_db/README.krb5
new file mode 100644 (file)
index 0000000..1f57823
--- /dev/null
@@ -0,0 +1,17 @@
+
+Kerberos notes:
+---------------
+
+What is here is only a small subset of the Berkeley database code.
+Only the hashed database code has been kept.
+
+hash/krb5_ndbm.c has been added to better tune the database code to
+Kerberos' large keys.  This supercedes hash/ndbm.c.
+
+A bug in hash/hash_bigkey.c which caused deletion of elements in
+collided buckets to fail or discard other collided elements has been
+fixed.
+
+
+
+
diff --git a/src/util/berk_db/changelog b/src/util/berk_db/changelog
new file mode 100644 (file)
index 0000000..1540ca8
--- /dev/null
@@ -0,0 +1,103 @@
+1.84 -> 1.85
+       recno:  #ifdef out use of mmap, it's not portable enough.
+
+1.83 -> 1.84   Thu Aug 18 15:46:07 EDT 1994
+       recno:  Rework fixed-length records so that closing and reopening
+               the file now works.  Pad short records on input.  Never do
+               signed comparison in recno input reading functions.
+
+1.82 -> 1.83   Tue Jul 26 15:33:44 EDT 1994
+       btree:  Rework cursor deletion code yet again; bugs with
+               deleting empty pages that only contained the cursor
+               record.
+
+1.81 -> 1.82   Sat Jul 16 11:01:50 EDT 1994
+       btree:  Fix bugs introduced by new cursor/deletion code.
+               Replace return kbuf/dbuf with real DBT's.
+
+1.80 -> 1.81
+       btree:  Fix bugs introduced by new cursor/deletion code.
+       all:    Add #defines for Purify.
+
+1.79 -> 1.80   Wed Jul 13 22:41:54 EDT 1994
+       btree   Change deletion to coalesce empty pages.  This is a major
+               change, cursors and duplicate pages all had to be reworked.
+               Return to a fixed stack.
+       recno:  Affected by cursor changes.  New cursor structures should
+               permit multiple cursors in the future.
+
+1.78 -> 1.79   Mon Jun 20 17:36:47 EDT 1994
+       all:    Minor cleanups of 1.78 for porting reasons; only
+               major change was inlining check of NULL pointer
+               so that __fix_realloc goes away.
+
+1.77 -> 1.78   Thu Jun 16 19:06:43 EDT 1994
+       all:    Move "standard" size typedef's into db.h.
+
+1.76 -> 1.77   Thu Jun 16 16:48:38 EDT 1994
+       hash:   Delete __init_ routine, has special meaning to OSF 2.0.
+
+1.74 -> 1.76
+       all:    Finish up the port to the Alpha.
+
+1.73 -> 1.74
+       recno:  Don't put the record if rec_search fails, in rec_rdelete.
+               Create fixed-length intermediate records past "end" of DB
+               correctly.
+               Realloc bug when reading in fixed records.
+       all:    First cut at port to Alpha (64-bit architecture) using
+               4.4BSD basic integral types typedef's.
+               Cast allocation pointers to shut up old compilers.
+               Rework PORT directory into OS/machine directories.
+
+1.72 -> 1.73
+       btree:  If enough duplicate records were inserted and then deleted
+               that internal pages had references to empty pages of the
+               duplicate keys, the search function ended up on the wrong
+               page.
+
+1.7  -> 1.72   12 Oct 1993
+       hash:   Support NET/2 hash formats.
+
+1.7  -> 1.71   16 Sep 1993
+       btree/recno:
+               Fix bug in internal search routines that caused
+               return of invalid pointers.
+
+1.6  -> 1.7    07 Sep 1993
+       hash:   Fixed big key overflow bugs.
+       test:   Portability hacks, rewrite test script, Makefile.
+       btree/recno:
+               Stop copying non-overflow key/data pairs.
+       PORT:   Break PORT directory up into per architecture/OS
+               subdirectories.
+
+1.5  -> 1.6    06 Jun 1993
+       hash:   In PAIRFITS, the first comparison should look at (P)[2].
+               The hash_realloc function was walking off the end of memory.
+               The overflow page number was wrong when bumping splitpoint.
+
+1.4  -> 1.5    23 May 1993
+       hash:   Set hash default fill factor dynamically.
+       recno:  Fixed bug in sorted page splits.
+               Add page size parameter support.
+               Allow recno to specify the name of the underlying btree;
+                       used for vi recovery.
+       btree/recno:
+               Support 64K pages.
+       btree/hash/recno:
+               Provide access to an underlying file descriptor.
+               Change sync routines to take a flag argument, recno
+                       uses this to sync out the underlying btree.
+
+1.3  -> 1.4    10 May 1993
+       recno:  Delete the R_CURSORLOG flag from the recno interface.
+               Zero-length record fix for non-mmap reads.
+               Try and make SIZE_T_MAX test in open portable.
+
+1.2  -> 1.3    01 May 1993
+       btree:  Ignore user byte-order setting when reading already
+               existing database.  Fixes to byte-order conversions.
+
+1.1  -> 1.2    15 Apr 1993
+               No bug fixes, only compatibility hacks.
diff --git a/src/util/berk_db/configure.in b/src/util/berk_db/configure.in
new file mode 100644 (file)
index 0000000..03052c6
--- /dev/null
@@ -0,0 +1,15 @@
+AC_INIT(configure.in)
+AC_SET_BUILDTOP
+WITH_CCOPTS
+WITH_KRB5ROOT
+CONFIG_RULES
+CONFIG_DIRS(hash test)
+AC_PROG_ARCHIVE
+AC_PROG_ARCHIVE_ADD
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+MAKE_SUBDIRS("making",all)
+MAKE_SUBDIRS("cleaning",clean)
+MAKE_SUBDIRS("checking",check)
+AppendRule([all:: libdb.a libdb_ranlib])
+V5_AC_OUTPUT_MAKEFILE
diff --git a/src/util/berk_db/hash/.Sanitize b/src/util/berk_db/hash/.Sanitize
new file mode 100644 (file)
index 0000000..52ccdaf
--- /dev/null
@@ -0,0 +1,49 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+.cvsignore
+Makefile.in
+README
+configure
+configure.in
+extern.h
+hash.c
+hash.h
+hash_bigkey.c
+hash_buf.c
+hash_func.c
+hash_log2.c
+hash_page.c
+hsearch.c
+krb5_ndbm.c
+ndbm.c
+page.h
+search.h
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/hash/.cvsignore b/src/util/berk_db/hash/.cvsignore
new file mode 100644 (file)
index 0000000..e8c05a6
--- /dev/null
@@ -0,0 +1 @@
+configure
diff --git a/src/util/berk_db/hash/Makefile.in b/src/util/berk_db/hash/Makefile.in
new file mode 100644 (file)
index 0000000..cdaf4d4
--- /dev/null
@@ -0,0 +1,46 @@
+HASH_DEBUGOPTS=
+# DEBUG4 does not compile
+# DEBUG1 does not work
+#HASH_DEBUGOPTS=       -DHASH_STATISTICS -DDEBUG -DDEBUG2 -DDEBUG3 -DPURIFY
+
+.c.o:
+       $(CC) $(CFLAGS) -c $(srcdir)/$*.c
+
+CFLAGS = $(CCOPTS) $(DEFS) -D__DBINTERFACE_PRIVATE $(LOCALINCLUDE) $(HASH_DEBUGOPTS)
+
+##DOSBUILDTOP = ..\..\..
+##DOSLIBNAME=..\db.lib
+##DOS!include $(BUILDTOP)\config\windows.in
+
+LOCALINCLUDE=-I$(srcdir)/../PORT/krb5          \
+       -I$(srcdir)/../PORT/krb5/include        \
+       -I$(srcdir)/../PORT/include             \
+       -I$(srcdir)/../include                  \
+       -I$(srcdir)
+
+OBJS=  hash.$(OBJEXT)          \
+       hash_bigkey.$(OBJEXT)   \
+       hash_buf.$(OBJEXT)      \
+       hash_func.$(OBJEXT)     \
+       hash_log2.$(OBJEXT)     \
+       hash_page.$(OBJEXT)     \
+       hsearch.$(OBJEXT)       \
+       krb5_ndbm.$(OBJEXT)     \
+       mktemp.$(OBJEXT)
+
+
+SRCS=  $(srcdir)/hash.c        \
+       $(srcdir)/hash_bigkey.c \
+       $(srcdir)/hash_buf.c    \
+       $(srcdir)/hash_func.c   \
+       $(srcdir)/hash_log2.c   \
+       $(srcdir)/hash_page.c   \
+       $(srcdir)/hsearch.c     \
+       $(srcdir)/krb5_ndbm.c   \
+       $(srcdir)/../PORT/clib/mktemp.c
+
+mktemp.o:      $(srcdir)/../PORT/clib/mktemp.c
+       $(CC) $(CFLAGS) -c $(srcdir)/../PORT/clib/mktemp.c
+
+all:: $(OBJS)
+
diff --git a/src/util/berk_db/hash/README b/src/util/berk_db/hash/README
new file mode 100644 (file)
index 0000000..f29ccf7
--- /dev/null
@@ -0,0 +1,72 @@
+#      @(#)README      8.1 (Berkeley) 6/4/93
+
+This package implements a superset of the hsearch and dbm/ndbm libraries.
+
+Test Programs:
+       All test programs which need key/data pairs expect them entered
+       with key and data on separate lines
+
+       tcreat3.c       
+               Takes 
+                       bucketsize (bsize), 
+                       fill factor (ffactor), and
+                       initial number of elements (nelem).  
+               Creates a hash table named hashtest containing the 
+               keys/data pairs entered from standard in.
+       thash4.c
+               Takes
+                       bucketsize (bsize), 
+                       fill factor (ffactor), 
+                       initial number of elements (nelem)
+                       bytes of cache (ncached), and
+                       file from which to read data  (fname)
+               Creates a table from the key/data pairs on standard in and
+               then does a read of each key/data in fname
+       tdel.c
+               Takes
+                       bucketsize (bsize), and
+                       fill factor (ffactor).
+                       file from which to read data (fname)
+               Reads each key/data pair from fname and deletes the
+               key from the hash table hashtest
+       tseq.c
+               Reads the key/data pairs in the file hashtest and writes them
+               to standard out.
+       tread2.c
+               Takes
+                       butes of cache (ncached).
+               Reads key/data pairs from standard in and looks them up
+               in the file hashtest.
+       tverify.c
+               Reads key/data pairs from standard in, looks them up
+               in the file hashtest, and verifies that the data is
+               correct.
+
+NOTES:
+
+The file search.h is provided for using the hsearch compatible interface
+on BSD systems.  On System V derived systems, search.h should appear in 
+/usr/include.
+
+The man page ../man/db.3 explains the interface to the hashing system.
+The file hash.ps is a postscript copy of a paper explaining
+the history, implementation, and performance of the hash package.
+
+"bugs" or idiosyncracies
+
+If you have a lot of overflows, it is possible to run out of overflow
+pages.  Currently, this will cause a message to be printed on stderr.
+Eventually, this will be indicated by a return error code.
+
+If you are using the ndbm interface and exit without flushing or closing the
+file, you may lose updates since the package buffers all writes.  Also,
+the db interface only creates a single database file.  To avoid overwriting
+the user's original file, the suffix ".db" is appended to the file name
+passed to dbm_open.  Additionally, if your code "knows" about the historic
+.dir and .pag files, it will break.  
+
+There is a fundamental difference between this package and the old hsearch.
+Hsearch requires the user to maintain the keys and data in the application's
+allocated memory while hash takes care of all storage management.  The down
+side is that the byte strings passed in the ENTRY structure must be null
+terminated (both the keys and the data).
diff --git a/src/util/berk_db/hash/configure.in b/src/util/berk_db/hash/configure.in
new file mode 100644 (file)
index 0000000..bac927b
--- /dev/null
@@ -0,0 +1,16 @@
+AC_INIT(configure.in)
+WITH_CCOPTS
+CONFIG_RULES
+AC_SET_BUILDTOP
+WITH_NETLIB
+AC_PROG_ARCHIVE
+AC_PROG_ARCHIVE_ADD
+AC_PROG_RANLIB
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+AC_HAVE_FUNCS(mktemp mkstemp)
+CHECK_SIGNALS
+SubdirLibraryRule([$(OBJS)])
+KRB_INCLUDE
+V5_AC_OUTPUT_MAKEFILE
diff --git a/src/util/berk_db/hash/extern.h b/src/util/berk_db/hash/extern.h
new file mode 100644 (file)
index 0000000..3167e6d
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)extern.h    8.4 (Berkeley) 6/16/94
+ */
+
+BUFHEAD        *__add_ovflpage __P((HTAB *, BUFHEAD *));
+int     __addel __P((HTAB *, BUFHEAD *, const DBT *, const DBT *));
+int     __big_delete __P((HTAB *, BUFHEAD *));
+int     __big_insert __P((HTAB *, BUFHEAD *, const DBT *, const DBT *));
+int     __big_keydata __P((HTAB *, BUFHEAD *, DBT *, DBT *, int));
+int     __big_return __P((HTAB *, BUFHEAD *, int, DBT *, int));
+int     __big_split __P((HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *,
+               int, u_int32_t, SPLIT_RETURN *));
+int     __buf_free __P((HTAB *, int, int));
+void    __buf_init __P((HTAB *, int));
+u_int32_t       __call_hash __P((HTAB *, char *, int));
+int     __delpair __P((HTAB *, BUFHEAD *, int));
+int     __expand_table __P((HTAB *));
+int     __find_bigpair __P((HTAB *, BUFHEAD *, int, char *, int));
+u_int16_t       __find_last_page __P((HTAB *, BUFHEAD **));
+void    __free_ovflpage __P((HTAB *, BUFHEAD *));
+BUFHEAD        *__get_buf __P((HTAB *, u_int32_t, BUFHEAD *, int));
+int     __get_page __P((HTAB *, char *, u_int32_t, int, int, int));
+int     __ibitmap __P((HTAB *, int, int, int));
+u_int32_t       __log2 __P((u_int32_t));
+int     __put_page __P((HTAB *, char *, u_int32_t, int, int));
+void    __reclaim_buf __P((HTAB *, BUFHEAD *));
+int     __split_page __P((HTAB *, u_int32_t, u_int32_t));
+
+/* Default hash routine. */
+extern u_int32_t (*__default_hash) __P((const void *, size_t));
+
+#ifdef HASH_STATISTICS
+extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
+#endif
diff --git a/src/util/berk_db/hash/hash.c b/src/util/berk_db/hash/hash.c
new file mode 100644 (file)
index 0000000..4b7b732
--- /dev/null
@@ -0,0 +1,994 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash.c     8.9 (Berkeley) 6/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int   alloc_segs __P((HTAB *, int));
+static int   flush_meta __P((HTAB *));
+static int   hash_access __P((HTAB *, ACTION, DBT *, DBT *));
+static int   hash_close __P((DB *));
+static int   hash_delete __P((const DB *, const DBT *, u_int32_t));
+static int   hash_fd __P((const DB *));
+static int   hash_get __P((const DB *, const DBT *, DBT *, u_int32_t));
+static int   hash_put __P((const DB *, DBT *, const DBT *, u_int32_t));
+static void *hash_realloc __P((SEGMENT **, int, int));
+static int   hash_seq __P((const DB *, DBT *, DBT *, u_int32_t));
+static int   hash_sync __P((const DB *, u_int32_t));
+static int   hdestroy __P((HTAB *));
+static HTAB *init_hash __P((HTAB *, const char *, HASHINFO *));
+static int   init_htab __P((HTAB *, int));
+#if BYTE_ORDER == LITTLE_ENDIAN
+static void  swap_header __P((HTAB *));
+static void  swap_header_copy __P((HASHHDR *, HASHHDR *));
+#endif
+
+/* Fast arithmetic, relying on powers of 2, */
+#define MOD(x, y)              ((x) & ((y) - 1))
+
+#define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; }
+
+/* Return values */
+#define        SUCCESS  (0)
+#define        ERROR   (-1)
+#define        ABNORMAL (1)
+
+#ifdef HASH_STATISTICS
+int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
+#endif
+
+/************************** INTERFACE ROUTINES ***************************/
+/* OPEN/CLOSE */
+
+extern DB *
+__hash_open(file, flags, mode, info, dflags)
+       const char *file;
+       int flags, mode, dflags;
+       const HASHINFO *info;   /* Special directives for create */
+{
+       HTAB *hashp;
+       struct stat statbuf;
+       DB *dbp;
+       int bpages, hdrsize, new_table, nsegs, save_errno;
+
+       if ((flags & O_ACCMODE) == O_WRONLY) {
+               errno = EINVAL;
+               return (NULL);
+       }
+
+       if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
+               return (NULL);
+       hashp->fp = -1;
+
+       /*
+        * Even if user wants write only, we need to be able to read
+        * the actual file, so we need to open it read/write. But, the
+        * field in the hashp structure needs to be accurate so that
+        * we can check accesses.
+        */
+       hashp->flags = flags;
+
+       new_table = 0;
+       if (!file || (flags & O_TRUNC) ||
+           (stat(file, &statbuf) && (errno == ENOENT))) {
+               if (errno == ENOENT)
+                       errno = 0; /* Just in case someone looks at errno */
+               new_table = 1;
+       }
+       if (file) {
+               if ((hashp->fp = open(file, flags, mode)) == -1)
+                       RETURN_ERROR(errno, error0);
+               (void)fcntl(hashp->fp, F_SETFD, 1);
+       }
+       if (new_table) {
+               if (!(hashp = init_hash(hashp, file, (HASHINFO *)info)))
+                       RETURN_ERROR(errno, error1);
+       } else {
+               /* Table already exists */
+               if (info && info->hash)
+                       hashp->hash = info->hash;
+               else
+                       hashp->hash = __default_hash;
+
+               hdrsize = read(hashp->fp, &hashp->hdr, sizeof(HASHHDR));
+#if BYTE_ORDER == LITTLE_ENDIAN
+               swap_header(hashp);
+#endif
+               if (hdrsize == -1)
+                       RETURN_ERROR(errno, error1);
+               if (hdrsize != sizeof(HASHHDR))
+                       RETURN_ERROR(EFTYPE, error1);
+               /* Verify file type, versions and hash function */
+               if (hashp->MAGIC != HASHMAGIC)
+                       RETURN_ERROR(EFTYPE, error1);
+#define        OLDHASHVERSION  1
+               if (hashp->VERSION != HASHVERSION &&
+                   hashp->VERSION != OLDHASHVERSION)
+                       RETURN_ERROR(EFTYPE, error1);
+               if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
+                       RETURN_ERROR(EFTYPE, error1);
+               /*
+                * Figure out how many segments we need.  Max_Bucket is the
+                * maximum bucket number, so the number of buckets is
+                * max_bucket + 1.
+                */
+               nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
+                        hashp->SGSIZE;
+               hashp->nsegs = 0;
+               if (alloc_segs(hashp, nsegs))
+                       /*
+                        * If alloc_segs fails, table will have been destroyed
+                        * and errno will have been set.
+                        */
+                       return (NULL);
+               /* Read in bitmaps */
+               bpages = (hashp->SPARES[hashp->OVFL_POINT] +
+                   (hashp->BSIZE << BYTE_SHIFT) - 1) >>
+                   (hashp->BSHIFT + BYTE_SHIFT);
+
+               hashp->nmaps = bpages;
+               (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *));
+       }
+
+       /* Initialize Buffer Manager */
+       if (info && info->cachesize)
+               __buf_init(hashp, info->cachesize);
+       else
+               __buf_init(hashp, DEF_BUFSIZE);
+
+       hashp->new_file = new_table;
+       hashp->save_file = file && (hashp->flags & O_RDWR);
+       hashp->cbucket = -1;
+       if (!(dbp = (DB *)malloc(sizeof(DB)))) {
+               save_errno = errno;
+               hdestroy(hashp);
+               errno = save_errno;
+               return (NULL);
+       }
+       dbp->internal = hashp;
+       dbp->close = hash_close;
+       dbp->del = hash_delete;
+       dbp->fd = hash_fd;
+       dbp->get = hash_get;
+       dbp->put = hash_put;
+       dbp->seq = hash_seq;
+       dbp->sync = hash_sync;
+       dbp->type = DB_HASH;
+
+#ifdef DEBUG
+       (void)fprintf(stderr,
+"%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
+           "init_htab:",
+           "TABLE POINTER   ", hashp,
+           "BUCKET SIZE     ", hashp->BSIZE,
+           "BUCKET SHIFT    ", hashp->BSHIFT,
+           "DIRECTORY SIZE  ", hashp->DSIZE,
+           "SEGMENT SIZE    ", hashp->SGSIZE,
+           "SEGMENT SHIFT   ", hashp->SSHIFT,
+           "FILL FACTOR     ", hashp->FFACTOR,
+           "MAX BUCKET      ", hashp->MAX_BUCKET,
+           "OVFL POINT      ", hashp->OVFL_POINT,
+           "LAST FREED      ", hashp->LAST_FREED,
+           "HIGH MASK       ", hashp->HIGH_MASK,
+           "LOW  MASK       ", hashp->LOW_MASK,
+           "NSEGS           ", hashp->nsegs,
+           "NKEYS           ", hashp->NKEYS);
+#endif
+#ifdef HASH_STATISTICS
+       hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0;
+#endif
+       return (dbp);
+
+error1:
+       if (hashp != NULL)
+               (void)close(hashp->fp);
+
+error0:
+       free(hashp);
+       errno = save_errno;
+       return (NULL);
+}
+
+static int
+hash_close(dbp)
+       DB *dbp;
+{
+       HTAB *hashp;
+       int retval;
+
+       if (!dbp)
+               return (ERROR);
+
+       hashp = (HTAB *)dbp->internal;
+       retval = hdestroy(hashp);
+       free(dbp);
+       return (retval);
+}
+
+static int
+hash_fd(dbp)
+       const DB *dbp;
+{
+       HTAB *hashp;
+
+       if (!dbp)
+               return (ERROR);
+
+       hashp = (HTAB *)dbp->internal;
+       if (hashp->fp == -1) {
+               errno = ENOENT;
+               return (-1);
+       }
+       return (hashp->fp);
+}
+
+/************************** LOCAL CREATION ROUTINES **********************/
+static HTAB *
+init_hash(hashp, file, info)
+       HTAB *hashp;
+       const char *file;
+       HASHINFO *info;
+{
+       struct stat statbuf;
+       int nelem;
+
+       nelem = 1;
+       hashp->NKEYS = 0;
+       hashp->LORDER = BYTE_ORDER;
+       hashp->BSIZE = DEF_BUCKET_SIZE;
+       hashp->BSHIFT = DEF_BUCKET_SHIFT;
+       hashp->SGSIZE = DEF_SEGSIZE;
+       hashp->SSHIFT = DEF_SEGSIZE_SHIFT;
+       hashp->DSIZE = DEF_DIRSIZE;
+       hashp->FFACTOR = DEF_FFACTOR;
+       hashp->hash = __default_hash;
+       memset(hashp->SPARES, 0, sizeof(hashp->SPARES));
+       memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS));
+
+       /* Fix bucket size to be optimal for file system */
+       if (file != NULL) {
+               if (stat(file, &statbuf))
+                       return (NULL);
+               hashp->BSIZE = statbuf.st_blksize;
+               hashp->BSHIFT = __log2(hashp->BSIZE);
+       }
+
+       if (info) {
+               if (info->bsize) {
+                       /* Round pagesize up to power of 2 */
+                       hashp->BSHIFT = __log2(info->bsize);
+                       hashp->BSIZE = 1 << hashp->BSHIFT;
+                       if (hashp->BSIZE > MAX_BSIZE) {
+                               errno = EINVAL;
+                               return (NULL);
+                       }
+               }
+               if (info->ffactor)
+                       hashp->FFACTOR = info->ffactor;
+               if (info->hash)
+                       hashp->hash = info->hash;
+               if (info->nelem)
+                       nelem = info->nelem;
+               if (info->lorder) {
+                       if (info->lorder != BIG_ENDIAN &&
+                           info->lorder != LITTLE_ENDIAN) {
+                               errno = EINVAL;
+                               return (NULL);
+                       }
+                       hashp->LORDER = info->lorder;
+               }
+       }
+       /* init_htab should destroy the table and set errno if it fails */
+       if (init_htab(hashp, nelem))
+               return (NULL);
+       else
+               return (hashp);
+}
+/*
+ * This calls alloc_segs which may run out of memory.  Alloc_segs will destroy
+ * the table and set errno, so we just pass the error information along.
+ *
+ * Returns 0 on No Error
+ */
+static int
+init_htab(hashp, nelem)
+       HTAB *hashp;
+       int nelem;
+{
+       register int nbuckets, nsegs;
+       int l2;
+
+       /*
+        * Divide number of elements by the fill factor and determine a
+        * desired number of buckets.  Allocate space for the next greater
+        * power of two number of buckets.
+        */
+       nelem = (nelem - 1) / hashp->FFACTOR + 1;
+
+       l2 = __log2(MAX(nelem, 2));
+       nbuckets = 1 << l2;
+
+       hashp->SPARES[l2] = l2 + 1;
+       hashp->SPARES[l2 + 1] = l2 + 1;
+       hashp->OVFL_POINT = l2;
+       hashp->LAST_FREED = 2;
+
+       /* First bitmap page is at: splitpoint l2 page offset 1 */
+       if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0))
+               return (-1);
+
+       hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1;
+       hashp->HIGH_MASK = (nbuckets << 1) - 1;
+       hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >>
+           hashp->BSHIFT) + 1;
+
+       nsegs = (nbuckets - 1) / hashp->SGSIZE + 1;
+       nsegs = 1 << __log2(nsegs);
+
+       if (nsegs > hashp->DSIZE)
+               hashp->DSIZE = nsegs;
+       return (alloc_segs(hashp, nsegs));
+}
+
+/********************** DESTROY/CLOSE ROUTINES ************************/
+
+/*
+ * Flushes any changes to the file if necessary and destroys the hashp
+ * structure, freeing all allocated space.
+ */
+static int
+hdestroy(hashp)
+       HTAB *hashp;
+{
+       int i, save_errno;
+
+       save_errno = 0;
+
+#ifdef HASH_STATISTICS
+       (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n",
+           hash_accesses, hash_collisions);
+       (void)fprintf(stderr, "hdestroy: expansions %ld\n",
+           hash_expansions);
+       (void)fprintf(stderr, "hdestroy: overflows %ld\n",
+           hash_overflows);
+       (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n",
+           hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs);
+
+       for (i = 0; i < NCACHED; i++)
+               (void)fprintf(stderr,
+                   "spares[%d] = %d\n", i, hashp->SPARES[i]);
+#endif
+       /*
+        * Call on buffer manager to free buffers, and if required,
+        * write them to disk.
+        */
+       if (__buf_free(hashp, 1, hashp->save_file))
+               save_errno = errno;
+       if (hashp->dir) {
+               free(*hashp->dir);      /* Free initial segments */
+               /* Free extra segments */
+               while (hashp->exsegs--)
+                       free(hashp->dir[--hashp->nsegs]);
+               free(hashp->dir);
+       }
+       if (flush_meta(hashp) && !save_errno)
+               save_errno = errno;
+       /* Free Bigmaps */
+       for (i = 0; i < hashp->nmaps; i++)
+               if (hashp->mapp[i])
+                       free(hashp->mapp[i]);
+
+       if (hashp->fp != -1)
+               (void)close(hashp->fp);
+
+       free(hashp);
+
+       if (save_errno) {
+               errno = save_errno;
+               return (ERROR);
+       }
+       return (SUCCESS);
+}
+/*
+ * Write modified pages to disk
+ *
+ * Returns:
+ *      0 == OK
+ *     -1 ERROR
+ */
+static int
+hash_sync(dbp, flags)
+       const DB *dbp;
+       u_int32_t flags;
+{
+       HTAB *hashp;
+
+       if (flags != 0) {
+               errno = EINVAL;
+               return (ERROR);
+       }
+
+       if (!dbp)
+               return (ERROR);
+
+       hashp = (HTAB *)dbp->internal;
+       if (!hashp->save_file)
+               return (0);
+       if (__buf_free(hashp, 0, 1) || flush_meta(hashp))
+               return (ERROR);
+       hashp->new_file = 0;
+       return (0);
+}
+
+/*
+ * Returns:
+ *      0 == OK
+ *     -1 indicates that errno should be set
+ */
+static int
+flush_meta(hashp)
+       HTAB *hashp;
+{
+       HASHHDR *whdrp;
+#if BYTE_ORDER == LITTLE_ENDIAN
+       HASHHDR whdr;
+#endif
+       int fp, i, wsize;
+
+       if (!hashp->save_file)
+               return (0);
+       hashp->MAGIC = HASHMAGIC;
+       hashp->VERSION = HASHVERSION;
+       hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY));
+
+       fp = hashp->fp;
+       whdrp = &hashp->hdr;
+#if BYTE_ORDER == LITTLE_ENDIAN
+       whdrp = &whdr;
+       swap_header_copy(&hashp->hdr, whdrp);
+#endif
+       if ((lseek(fp, (off_t)0, SEEK_SET) == -1) ||
+           ((wsize = write(fp, whdrp, sizeof(HASHHDR))) == -1))
+               return (-1);
+       else
+               if (wsize != sizeof(HASHHDR)) {
+                       errno = EFTYPE;
+                       hashp->errno = errno;
+                       return (-1);
+               }
+       for (i = 0; i < NCACHED; i++)
+               if (hashp->mapp[i])
+                       if (__put_page(hashp, (char *)hashp->mapp[i],
+                               hashp->BITMAPS[i], 0, 1))
+                               return (-1);
+       return (0);
+}
+
+/*******************************SEARCH ROUTINES *****************************/
+/*
+ * All the access routines return
+ *
+ * Returns:
+ *      0 on SUCCESS
+ *      1 to indicate an external ERROR (i.e. key not found, etc)
+ *     -1 to indicate an internal ERROR (i.e. out of memory, etc)
+ */
+static int
+hash_get(dbp, key, data, flag)
+       const DB *dbp;
+       const DBT *key;
+       DBT *data;
+       u_int32_t flag;
+{
+       HTAB *hashp;
+
+       hashp = (HTAB *)dbp->internal;
+       if (flag) {
+               hashp->errno = errno = EINVAL;
+               return (ERROR);
+       }
+       return (hash_access(hashp, HASH_GET, (DBT *)key, data));
+}
+
+static int
+hash_put(dbp, key, data, flag)
+       const DB *dbp;
+       DBT *key;
+       const DBT *data;
+       u_int32_t flag;
+{
+       HTAB *hashp;
+
+       hashp = (HTAB *)dbp->internal;
+       if (flag && flag != R_NOOVERWRITE) {
+               hashp->errno = errno = EINVAL;
+               return (ERROR);
+       }
+       if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
+               hashp->errno = errno = EPERM;
+               return (ERROR);
+       }
+       return (hash_access(hashp, flag == R_NOOVERWRITE ?
+           HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data));
+}
+
+static int
+hash_delete(dbp, key, flag)
+       const DB *dbp;
+       const DBT *key;
+       u_int32_t flag;         /* Ignored */
+{
+       HTAB *hashp;
+
+       hashp = (HTAB *)dbp->internal;
+       if (flag && flag != R_CURSOR) {
+               hashp->errno = errno = EINVAL;
+               return (ERROR);
+       }
+       if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
+               hashp->errno = errno = EPERM;
+               return (ERROR);
+       }
+       return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
+}
+
+/*
+ * Assume that hashp has been set in wrapper routine.
+ */
+static int
+hash_access(hashp, action, key, val)
+       HTAB *hashp;
+       ACTION action;
+       DBT *key, *val;
+{
+       register BUFHEAD *rbufp;
+       BUFHEAD *bufp, *save_bufp;
+       register u_int16_t *bp;
+       register int n, ndx, off, size;
+       register char *kp;
+       u_int16_t pageno;
+
+#ifdef HASH_STATISTICS
+       hash_accesses++;
+#endif
+
+       off = hashp->BSIZE;
+       size = key->size;
+       kp = (char *)key->data;
+       rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0);
+       if (!rbufp)
+               return (ERROR);
+       save_bufp = rbufp;
+
+       /* Pin the bucket chain */
+       rbufp->flags |= BUF_PIN;
+       for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;)
+               if (bp[1] >= REAL_KEY) {
+                       /* Real key/data pair */
+                       if (size == off - *bp &&
+                           memcmp(kp, rbufp->page + *bp, size) == 0)
+                               goto found;
+                       off = bp[1];
+#ifdef HASH_STATISTICS
+                       hash_collisions++;
+#endif
+                       bp += 2;
+                       ndx += 2;
+               } else if (bp[1] == OVFLPAGE) {
+                       rbufp = __get_buf(hashp, *bp, rbufp, 0);
+                       if (!rbufp) {
+                               save_bufp->flags &= ~BUF_PIN;
+                               return (ERROR);
+                       }
+                       /* FOR LOOP INIT */
+                       bp = (u_int16_t *)rbufp->page;
+                       n = *bp++;
+                       ndx = 1;
+                       off = hashp->BSIZE;
+               } else if (bp[1] < REAL_KEY) {
+                       if ((ndx =
+                           __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0)
+                               goto found;
+                       if (ndx == -2) {
+                               bufp = rbufp;
+                               if (!(pageno =
+                                   __find_last_page(hashp, &bufp))) {
+                                       ndx = 0;
+                                       rbufp = bufp;
+                                       break;  /* FOR */
+                               }
+                               rbufp = __get_buf(hashp, pageno, bufp, 0);
+                               if (!rbufp) {
+                                       save_bufp->flags &= ~BUF_PIN;
+                                       return (ERROR);
+                               }
+                               /* FOR LOOP INIT */
+                               bp = (u_int16_t *)rbufp->page;
+                               n = *bp++;
+                               ndx = 1;
+                               off = hashp->BSIZE;
+                       } else {
+                               save_bufp->flags &= ~BUF_PIN;
+                               return (ERROR);
+                       }
+               }
+
+       /* Not found */
+       switch (action) {
+       case HASH_PUT:
+       case HASH_PUTNEW:
+               if (__addel(hashp, rbufp, key, val)) {
+                       save_bufp->flags &= ~BUF_PIN;
+                       return (ERROR);
+               } else {
+                       save_bufp->flags &= ~BUF_PIN;
+                       return (SUCCESS);
+               }
+       case HASH_GET:
+       case HASH_DELETE:
+       default:
+               save_bufp->flags &= ~BUF_PIN;
+               return (ABNORMAL);
+       }
+
+found:
+       switch (action) {
+       case HASH_PUTNEW:
+               save_bufp->flags &= ~BUF_PIN;
+               return (ABNORMAL);
+       case HASH_GET:
+               bp = (u_int16_t *)rbufp->page;
+               if (bp[ndx + 1] < REAL_KEY) {
+                       if (__big_return(hashp, rbufp, ndx, val, 0))
+                               return (ERROR);
+               } else {
+                       val->data = (u_char *)rbufp->page + (int)bp[ndx + 1];
+                       val->size = bp[ndx] - bp[ndx + 1];
+               }
+               break;
+       case HASH_PUT:
+               if ((__delpair(hashp, rbufp, ndx)) ||
+                   (__addel(hashp, rbufp, key, val))) {
+                       save_bufp->flags &= ~BUF_PIN;
+                       return (ERROR);
+               }
+               break;
+       case HASH_DELETE:
+               if (__delpair(hashp, rbufp, ndx))
+                       return (ERROR);
+               break;
+       default:
+               abort();
+       }
+       save_bufp->flags &= ~BUF_PIN;
+       return (SUCCESS);
+}
+
+static int
+hash_seq(dbp, key, data, flag)
+       const DB *dbp;
+       DBT *key, *data;
+       u_int32_t flag;
+{
+       register u_int32_t bucket;
+       register BUFHEAD *bufp;
+       HTAB *hashp;
+       u_int16_t *bp, ndx;
+
+       hashp = (HTAB *)dbp->internal;
+       if (flag && flag != R_FIRST && flag != R_NEXT) {
+               hashp->errno = errno = EINVAL;
+               return (ERROR);
+       }
+#ifdef HASH_STATISTICS
+       hash_accesses++;
+#endif
+       if ((hashp->cbucket < 0) || (flag == R_FIRST)) {
+               hashp->cbucket = 0;
+               hashp->cndx = 1;
+               hashp->cpage = NULL;
+       }
+
+       for (bp = NULL; !bp || !bp[0]; ) {
+               if (!(bufp = hashp->cpage)) {
+                       for (bucket = hashp->cbucket;
+                           bucket <= hashp->MAX_BUCKET;
+                           bucket++, hashp->cndx = 1) {
+                               bufp = __get_buf(hashp, bucket, NULL, 0);
+                               if (!bufp)
+                                       return (ERROR);
+                               hashp->cpage = bufp;
+                               bp = (u_int16_t *)bufp->page;
+                               if (bp[0])
+                                       break;
+                       }
+                       hashp->cbucket = bucket;
+                       if (hashp->cbucket > hashp->MAX_BUCKET) {
+                               hashp->cbucket = -1;
+                               return (ABNORMAL);
+                       }
+               } else
+                       bp = (u_int16_t *)hashp->cpage->page;
+
+#ifdef DEBUG
+               assert(bp);
+               assert(bufp);
+#endif
+               while (bp[hashp->cndx + 1] == OVFLPAGE) {
+                       bufp = hashp->cpage =
+                           __get_buf(hashp, bp[hashp->cndx], bufp, 0);
+                       if (!bufp)
+                               return (ERROR);
+                       bp = (u_int16_t *)(bufp->page);
+                       hashp->cndx = 1;
+               }
+               if (!bp[0]) {
+                       hashp->cpage = NULL;
+                       ++hashp->cbucket;
+               }
+       }
+       ndx = hashp->cndx;
+       if (bp[ndx + 1] < REAL_KEY) {
+               if (__big_keydata(hashp, bufp, key, data, 1))
+                       return (ERROR);
+       } else {
+               key->data = (u_char *)hashp->cpage->page + bp[ndx];
+               key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
+               data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
+               data->size = bp[ndx] - bp[ndx + 1];
+               ndx += 2;
+               if (ndx > bp[0]) {
+                       hashp->cpage = NULL;
+                       hashp->cbucket++;
+                       hashp->cndx = 1;
+               } else
+                       hashp->cndx = ndx;
+       }
+       return (SUCCESS);
+}
+
+/********************************* UTILITIES ************************/
+
+/*
+ * Returns:
+ *      0 ==> OK
+ *     -1 ==> Error
+ */
+extern int
+__expand_table(hashp)
+       HTAB *hashp;
+{
+       u_int32_t old_bucket, new_bucket;
+       int dirsize, new_segnum, spare_ndx;
+
+#ifdef HASH_STATISTICS
+       hash_expansions++;
+#endif
+       new_bucket = ++hashp->MAX_BUCKET;
+       old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK);
+
+       new_segnum = new_bucket >> hashp->SSHIFT;
+
+       /* Check if we need a new segment */
+       if (new_segnum >= hashp->nsegs) {
+               /* Check if we need to expand directory */
+               if (new_segnum >= hashp->DSIZE) {
+                       /* Reallocate directory */
+                       dirsize = hashp->DSIZE * sizeof(SEGMENT *);
+                       if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1))
+                               return (-1);
+                       hashp->DSIZE = dirsize << 1;
+               }
+               if ((hashp->dir[new_segnum] =
+                   (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL)
+                       return (-1);
+               hashp->exsegs++;
+               hashp->nsegs++;
+       }
+       /*
+        * If the split point is increasing (MAX_BUCKET's log base 2
+        * * increases), we need to copy the current contents of the spare
+        * split bucket to the next bucket.
+        */
+       spare_ndx = __log2(hashp->MAX_BUCKET + 1);
+       if (spare_ndx > hashp->OVFL_POINT) {
+               hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT];
+               hashp->OVFL_POINT = spare_ndx;
+       }
+
+       if (new_bucket > hashp->HIGH_MASK) {
+               /* Starting a new doubling */
+               hashp->LOW_MASK = hashp->HIGH_MASK;
+               hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK;
+       }
+       /* Relocate records to the new bucket */
+       return (__split_page(hashp, old_bucket, new_bucket));
+}
+
+/*
+ * If realloc guarantees that the pointer is not destroyed if the realloc
+ * fails, then this routine can go away.
+ */
+static void *
+hash_realloc(p_ptr, oldsize, newsize)
+       SEGMENT **p_ptr;
+       int oldsize, newsize;
+{
+       register void *p;
+
+       if (p = malloc(newsize)) {
+               memmove(p, *p_ptr, oldsize);
+               memset((char *)p + oldsize, 0, newsize - oldsize);
+               free(*p_ptr);
+               *p_ptr = p;
+       }
+       return (p);
+}
+
+extern u_int32_t
+__call_hash(hashp, k, len)
+       HTAB *hashp;
+       char *k;
+       int len;
+{
+       int n, bucket;
+
+       n = hashp->hash(k, len);
+       bucket = n & hashp->HIGH_MASK;
+       if (bucket > hashp->MAX_BUCKET)
+               bucket = bucket & hashp->LOW_MASK;
+       return (bucket);
+}
+
+/*
+ * Allocate segment table.  On error, destroy the table and set errno.
+ *
+ * Returns 0 on success
+ */
+static int
+alloc_segs(hashp, nsegs)
+       HTAB *hashp;
+       int nsegs;
+{
+       register int i;
+       register SEGMENT store;
+
+       int save_errno;
+
+       if ((hashp->dir =
+           (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) {
+               save_errno = errno;
+               (void)hdestroy(hashp);
+               errno = save_errno;
+               return (-1);
+       }
+       /* Allocate segments */
+       if ((store =
+           (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) {
+               save_errno = errno;
+               (void)hdestroy(hashp);
+               errno = save_errno;
+               return (-1);
+       }
+       for (i = 0; i < nsegs; i++, hashp->nsegs++)
+               hashp->dir[i] = &store[i << hashp->SSHIFT];
+       return (0);
+}
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+/*
+ * Hashp->hdr needs to be byteswapped.
+ */
+static void
+swap_header_copy(srcp, destp)
+       HASHHDR *srcp, *destp;
+{
+       int i;
+
+       P_32_COPY(srcp->magic, destp->magic);
+       P_32_COPY(srcp->version, destp->version);
+       P_32_COPY(srcp->lorder, destp->lorder);
+       P_32_COPY(srcp->bsize, destp->bsize);
+       P_32_COPY(srcp->bshift, destp->bshift);
+       P_32_COPY(srcp->dsize, destp->dsize);
+       P_32_COPY(srcp->ssize, destp->ssize);
+       P_32_COPY(srcp->sshift, destp->sshift);
+       P_32_COPY(srcp->ovfl_point, destp->ovfl_point);
+       P_32_COPY(srcp->last_freed, destp->last_freed);
+       P_32_COPY(srcp->max_bucket, destp->max_bucket);
+       P_32_COPY(srcp->high_mask, destp->high_mask);
+       P_32_COPY(srcp->low_mask, destp->low_mask);
+       P_32_COPY(srcp->ffactor, destp->ffactor);
+       P_32_COPY(srcp->nkeys, destp->nkeys);
+       P_32_COPY(srcp->hdrpages, destp->hdrpages);
+       P_32_COPY(srcp->h_charkey, destp->h_charkey);
+       for (i = 0; i < NCACHED; i++) {
+               P_32_COPY(srcp->spares[i], destp->spares[i]);
+               P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]);
+       }
+}
+
+static void
+swap_header(hashp)
+       HTAB *hashp;
+{
+       HASHHDR *hdrp;
+       int i;
+
+       hdrp = &hashp->hdr;
+
+       M_32_SWAP(hdrp->magic);
+       M_32_SWAP(hdrp->version);
+       M_32_SWAP(hdrp->lorder);
+       M_32_SWAP(hdrp->bsize);
+       M_32_SWAP(hdrp->bshift);
+       M_32_SWAP(hdrp->dsize);
+       M_32_SWAP(hdrp->ssize);
+       M_32_SWAP(hdrp->sshift);
+       M_32_SWAP(hdrp->ovfl_point);
+       M_32_SWAP(hdrp->last_freed);
+       M_32_SWAP(hdrp->max_bucket);
+       M_32_SWAP(hdrp->high_mask);
+       M_32_SWAP(hdrp->low_mask);
+       M_32_SWAP(hdrp->ffactor);
+       M_32_SWAP(hdrp->nkeys);
+       M_32_SWAP(hdrp->hdrpages);
+       M_32_SWAP(hdrp->h_charkey);
+       for (i = 0; i < NCACHED; i++) {
+               M_32_SWAP(hdrp->spares[i]);
+               M_16_SWAP(hdrp->bitmaps[i]);
+       }
+}
+#endif
diff --git a/src/util/berk_db/hash/hash.h b/src/util/berk_db/hash/hash.h
new file mode 100644 (file)
index 0000000..913e82b
--- /dev/null
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)hash.h      8.3 (Berkeley) 5/31/94
+ */
+
+/* Operations */
+typedef enum {
+       HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT
+} ACTION;
+
+/* Buffer Management structures */
+typedef struct _bufhead BUFHEAD;
+
+struct _bufhead {
+       BUFHEAD         *prev;          /* LRU links */
+       BUFHEAD         *next;          /* LRU links */
+       BUFHEAD         *ovfl;          /* Overflow page buffer header */
+       u_int32_t        addr;          /* Address of this page */
+       char            *page;          /* Actual page data */
+       char            flags;
+#define        BUF_MOD         0x0001
+#define BUF_DISK       0x0002
+#define        BUF_BUCKET      0x0004
+#define        BUF_PIN         0x0008
+};
+
+#define IS_BUCKET(X)   ((X) & BUF_BUCKET)
+
+typedef BUFHEAD **SEGMENT;
+
+/* Hash Table Information */
+typedef struct hashhdr {               /* Disk resident portion */
+       int             magic;          /* Magic NO for hash tables */
+       int             version;        /* Version ID */
+       u_int32_t       lorder;         /* Byte Order */
+       int             bsize;          /* Bucket/Page Size */
+       int             bshift;         /* Bucket shift */
+       int             dsize;          /* Directory Size */
+       int             ssize;          /* Segment Size */
+       int             sshift;         /* Segment shift */
+       int             ovfl_point;     /* Where overflow pages are being 
+                                        * allocated */
+       int             last_freed;     /* Last overflow page freed */
+       int             max_bucket;     /* ID of Maximum bucket in use */
+       int             high_mask;      /* Mask to modulo into entire table */
+       int             low_mask;       /* Mask to modulo into lower half of 
+                                        * table */
+       int             ffactor;        /* Fill factor */
+       int             nkeys;          /* Number of keys in hash table */
+       int             hdrpages;       /* Size of table header */
+       int             h_charkey;      /* value of hash(CHARKEY) */
+#define NCACHED        32                      /* number of bit maps and spare 
+                                        * points */
+       int             spares[NCACHED];/* spare pages for overflow */
+       u_int16_t       bitmaps[NCACHED];       /* address of overflow page 
+                                                * bitmaps */
+} HASHHDR;
+
+typedef struct htab     {              /* Memory resident data structure */
+       HASHHDR         hdr;            /* Header */
+       int             nsegs;          /* Number of allocated segments */
+       int             exsegs;         /* Number of extra allocated 
+                                        * segments */
+       u_int32_t                       /* Hash function */
+           (*hash)__P((const void *, size_t));
+       int             flags;          /* Flag values */
+       int             fp;             /* File pointer */
+       char            *tmp_buf;       /* Temporary Buffer for BIG data */
+       char            *tmp_key;       /* Temporary Buffer for BIG keys */
+       BUFHEAD         *cpage;         /* Current page */
+       int             cbucket;        /* Current bucket */
+       int             cndx;           /* Index of next item on cpage */
+       int             errno;          /* Error Number -- for DBM 
+                                        * compatability */
+       int             new_file;       /* Indicates if fd is backing store 
+                                        * or no */
+       int             save_file;      /* Indicates whether we need to flush 
+                                        * file at
+                                        * exit */
+       u_int32_t       *mapp[NCACHED]; /* Pointers to page maps */
+       int             nmaps;          /* Initial number of bitmaps */
+       int             nbufs;          /* Number of buffers left to 
+                                        * allocate */
+       BUFHEAD         bufhead;        /* Header of buffer lru list */
+       SEGMENT         *dir;           /* Hash Bucket directory */
+} HTAB;
+
+/*
+ * Constants
+ */
+#define        MAX_BSIZE               65536           /* 2^16 */
+#define MIN_BUFFERS            6
+#define MINHDRSIZE             512
+#define DEF_BUFSIZE            65536           /* 64 K */
+#define DEF_BUCKET_SIZE                4096
+#define DEF_BUCKET_SHIFT       12              /* log2(BUCKET) */
+#define DEF_SEGSIZE            256
+#define DEF_SEGSIZE_SHIFT      8               /* log2(SEGSIZE)         */
+#define DEF_DIRSIZE            256
+#define DEF_FFACTOR            65536
+#define MIN_FFACTOR            4
+#define SPLTMAX                        8
+#define CHARKEY                        "%$sniglet^&"
+#define NUMKEY                 1038583
+#define BYTE_SHIFT             3
+#define INT_TO_BYTE            2
+#define INT_BYTE_SHIFT         5
+#define ALL_SET                        ((u_int32_t)0xFFFFFFFF)
+#define ALL_CLEAR              0
+
+#define PTROF(X)       ((BUFHEAD *)((ptrdiff_t)(X)&~0x3))
+#define ISMOD(X)       ((u_int32_t)(ptrdiff_t)(X)&0x1)
+#define DOMOD(X)       ((X) = (char *)((ptrdiff_t)(X)|0x1))
+#define ISDISK(X)      ((u_int32_t)(ptrdiff_t)(X)&0x2)
+#define DODISK(X)      ((X) = (char *)((ptrdiff_t)(X)|0x2))
+
+#define BITS_PER_MAP   32
+
+/* Given the address of the beginning of a big map, clear/set the nth bit */
+#define CLRBIT(A, N)   ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
+#define SETBIT(A, N)   ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
+#define ISSET(A, N)    ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
+
+/* Overflow management */
+/*
+ * Overflow page numbers are allocated per split point.  At each doubling of
+ * the table, we can allocate extra pages.  So, an overflow page number has
+ * the top 5 bits indicate which split point and the lower 11 bits indicate
+ * which page at that split point is indicated (pages within split points are
+ * numberered starting with 1).
+ */
+
+#define SPLITSHIFT     11
+#define SPLITMASK      0x7FF
+#define SPLITNUM(N)    (((u_int32_t)(N)) >> SPLITSHIFT)
+#define OPAGENUM(N)    ((N) & SPLITMASK)
+#define        OADDR_OF(S,O)   ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O))
+
+#define BUCKET_TO_PAGE(B) \
+       (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0)
+#define OADDR_TO_PAGE(B)       \
+       BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B));
+
+/*
+ * page.h contains a detailed description of the page format.
+ *
+ * Normally, keys and data are accessed from offset tables in the top of
+ * each page which point to the beginning of the key and data.  There are
+ * four flag values which may be stored in these offset tables which indicate
+ * the following:
+ *
+ *
+ * OVFLPAGE    Rather than a key data pair, this pair contains
+ *             the address of an overflow page.  The format of
+ *             the pair is:
+ *                 OVERFLOW_PAGE_NUMBER OVFLPAGE
+ *
+ * PARTIAL_KEY This must be the first key/data pair on a page
+ *             and implies that page contains only a partial key.
+ *             That is, the key is too big to fit on a single page
+ *             so it starts on this page and continues on the next.
+ *             The format of the page is:
+ *                 KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE
+ *             
+ *                 KEY_OFF -- offset of the beginning of the key
+ *                 PARTIAL_KEY -- 1
+ *                 OVFL_PAGENO - page number of the next overflow page
+ *                 OVFLPAGE -- 0
+ *
+ * FULL_KEY    This must be the first key/data pair on the page.  It
+ *             is used in two cases.
+ *
+ *             Case 1:
+ *                 There is a complete key on the page but no data
+ *                 (because it wouldn't fit).  The next page contains
+ *                 the data.
+ *
+ *                 Page format it:
+ *                 KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
+ *
+ *                 KEY_OFF -- offset of the beginning of the key
+ *                 FULL_KEY -- 2
+ *                 OVFL_PAGENO - page number of the next overflow page
+ *                 OVFLPAGE -- 0
+ *
+ *             Case 2:
+ *                 This page contains no key, but part of a large
+ *                 data field, which is continued on the next page.
+ *
+ *                 Page format it:
+ *                 DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
+ *
+ *                 KEY_OFF -- offset of the beginning of the data on
+ *                             this page
+ *                 FULL_KEY -- 2
+ *                 OVFL_PAGENO - page number of the next overflow page
+ *                 OVFLPAGE -- 0
+ *
+ * FULL_KEY_DATA 
+ *             This must be the first key/data pair on the page.
+ *             There are two cases:
+ *
+ *             Case 1:
+ *                 This page contains a key and the beginning of the
+ *                 data field, but the data field is continued on the
+ *                 next page.
+ *
+ *                 Page format is:
+ *                 KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF
+ *
+ *                 KEY_OFF -- offset of the beginning of the key
+ *                 FULL_KEY_DATA -- 3
+ *                 OVFL_PAGENO - page number of the next overflow page
+ *                 DATA_OFF -- offset of the beginning of the data
+ *
+ *             Case 2:
+ *                 This page contains the last page of a big data pair.
+ *                 There is no key, only the  tail end of the data
+ *                 on this page.
+ *
+ *                 Page format is:
+ *                 DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE>
+ *
+ *                 DATA_OFF -- offset of the beginning of the data on
+ *                             this page
+ *                 FULL_KEY_DATA -- 3
+ *                 OVFL_PAGENO - page number of the next overflow page
+ *                 OVFLPAGE -- 0
+ *
+ *                 OVFL_PAGENO and OVFLPAGE are optional (they are
+ *                 not present if there is no next page).
+ */
+
+#define OVFLPAGE       0
+#define PARTIAL_KEY    1
+#define FULL_KEY       2
+#define FULL_KEY_DATA  3
+#define        REAL_KEY        4
+
+/* Short hands for accessing structure */
+#define BSIZE          hdr.bsize
+#define BSHIFT         hdr.bshift
+#define DSIZE          hdr.dsize
+#define SGSIZE         hdr.ssize
+#define SSHIFT         hdr.sshift
+#define LORDER         hdr.lorder
+#define OVFL_POINT     hdr.ovfl_point
+#define        LAST_FREED      hdr.last_freed
+#define MAX_BUCKET     hdr.max_bucket
+#define FFACTOR                hdr.ffactor
+#define HIGH_MASK      hdr.high_mask
+#define LOW_MASK       hdr.low_mask
+#define NKEYS          hdr.nkeys
+#define HDRPAGES       hdr.hdrpages
+#define SPARES         hdr.spares
+#define BITMAPS                hdr.bitmaps
+#define VERSION                hdr.version
+#define MAGIC          hdr.magic
+#define NEXT_FREE      hdr.next_free
+#define H_CHARKEY      hdr.h_charkey
diff --git a/src/util/berk_db/hash/hash_bigkey.c b/src/util/berk_db/hash/hash_bigkey.c
new file mode 100644 (file)
index 0000000..952f385
--- /dev/null
@@ -0,0 +1,667 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_bigkey.c      8.3 (Berkeley) 5/31/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * PACKAGE: hash
+ * DESCRIPTION:
+ *     Big key/data handling for the hashing package.
+ *
+ * ROUTINES:
+ * External
+ *     __big_keydata
+ *     __big_split
+ *     __big_insert
+ *     __big_return
+ *     __big_delete
+ *     __find_last_page
+ * Internal
+ *     collect_key
+ *     collect_data
+ */
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int collect_key __P((HTAB *, BUFHEAD *, int, DBT *, int));
+static int collect_data __P((HTAB *, BUFHEAD *, int, int));
+
+/*
+ * Big_insert
+ *
+ * You need to do an insert and the key/data pair is too big
+ *
+ * Returns:
+ * 0 ==> OK
+ *-1 ==> ERROR
+ */
+extern int
+__big_insert(hashp, bufp, key, val)
+       HTAB *hashp;
+       BUFHEAD *bufp;
+       const DBT *key, *val;
+{
+       register u_int16_t *p;
+       int key_size, n, val_size;
+       u_int16_t space, move_bytes, off;
+       char *cp, *key_data, *val_data;
+
+       cp = bufp->page;                /* Character pointer of p. */
+       p = (u_int16_t *)cp;
+
+       key_data = (char *)key->data;
+       key_size = key->size;
+       val_data = (char *)val->data;
+       val_size = val->size;
+
+       /* First move the Key */
+       for (space = FREESPACE(p) - BIGOVERHEAD; key_size;
+           space = FREESPACE(p) - BIGOVERHEAD) {
+               move_bytes = MIN(space, key_size);
+               off = OFFSET(p) - move_bytes;
+               memmove(cp + off, key_data, move_bytes);
+               key_size -= move_bytes;
+               key_data += move_bytes;
+               n = p[0];
+               p[++n] = off;
+               p[0] = ++n;
+               FREESPACE(p) = off - PAGE_META(n);
+               OFFSET(p) = off;
+               p[n] = PARTIAL_KEY;
+               bufp = __add_ovflpage(hashp, bufp);
+               if (!bufp)
+                       return (-1);
+               n = p[0];
+               if (!key_size)
+                       if (FREESPACE(p)) {
+                               move_bytes = MIN(FREESPACE(p), val_size);
+                               off = OFFSET(p) - move_bytes;
+                               p[n] = off;
+                               memmove(cp + off, val_data, move_bytes);
+                               val_data += move_bytes;
+                               val_size -= move_bytes;
+                               p[n - 2] = FULL_KEY_DATA;
+                               FREESPACE(p) = FREESPACE(p) - move_bytes;
+                               OFFSET(p) = off;
+                       } else
+                               p[n - 2] = FULL_KEY;
+               p = (u_int16_t *)bufp->page;
+               cp = bufp->page;
+               bufp->flags |= BUF_MOD;
+       }
+
+       /* Now move the data */
+       for (space = FREESPACE(p) - BIGOVERHEAD; val_size;
+           space = FREESPACE(p) - BIGOVERHEAD) {
+               move_bytes = MIN(space, val_size);
+               /*
+                * Here's the hack to make sure that if the data ends on the
+                * same page as the key ends, FREESPACE is at least one.
+                */
+               if (space == val_size && val_size == val->size)
+                       move_bytes--;
+               off = OFFSET(p) - move_bytes;
+               memmove(cp + off, val_data, move_bytes);
+               val_size -= move_bytes;
+               val_data += move_bytes;
+               n = p[0];
+               p[++n] = off;
+               p[0] = ++n;
+               FREESPACE(p) = off - PAGE_META(n);
+               OFFSET(p) = off;
+               if (val_size) {
+                       p[n] = FULL_KEY;
+                       bufp = __add_ovflpage(hashp, bufp);
+                       if (!bufp)
+                               return (-1);
+                       cp = bufp->page;
+                       p = (u_int16_t *)cp;
+               } else
+                       p[n] = FULL_KEY_DATA;
+               bufp->flags |= BUF_MOD;
+       }
+       return (0);
+}
+
+/*
+ * Called when bufp's page  contains a partial key (index should be 1)
+ *
+ * All pages in the big key/data pair except bufp are freed.  We cannot
+ * free bufp because the page pointing to it is lost and we can't get rid
+ * of its pointer.
+ *
+ * Returns:
+ * 0 => OK
+ *-1 => ERROR
+ */
+extern int
+__big_delete(hashp, bufp)
+       HTAB *hashp;
+       BUFHEAD *bufp;
+{
+       register BUFHEAD *last_bfp, *rbufp;
+       u_int16_t *bp, pageno;
+       int key_done, n;
+
+       rbufp = bufp;
+       last_bfp = NULL;
+       bp = (u_int16_t *)bufp->page;
+       pageno = 0;
+       key_done = 0;
+
+       while (!key_done || (bp[2] != FULL_KEY_DATA)) {
+               if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA)
+                       key_done = 1;
+
+               /*
+                * If there is freespace left on a FULL_KEY_DATA page, then
+                * the data is short and fits entirely on this page, and this
+                * is the last page.
+                */
+               if (bp[2] == FULL_KEY_DATA && FREESPACE(bp))
+                       break;
+               pageno = bp[bp[0] - 1];
+               rbufp->flags |= BUF_MOD;
+               rbufp = __get_buf(hashp, pageno, rbufp, 0);
+               if (last_bfp)
+                       __free_ovflpage(hashp, last_bfp);
+               last_bfp = rbufp;
+               if (!rbufp)
+                       return (-1);            /* Error. */
+               bp = (u_int16_t *)rbufp->page;
+       }
+
+       /*
+        * If we get here then rbufp points to the last page of the big
+        * key/data pair.  Bufp points to the first one -- it should now be
+        * empty pointing to the next page after this pair.  Can't free it
+        * because we don't have the page pointing to it.
+        */
+
+       /* This is information from the last page of the pair. */
+       n = bp[0];
+       pageno = bp[n - 1];
+
+       /* Now, bp is the first page of the pair. */
+       bp = (u_int16_t *)bufp->page;
+       if (n > 2) {
+               /* There is an overflow page. */
+               bp[1] = pageno;
+               bp[2] = OVFLPAGE;
+               bufp->ovfl = rbufp->ovfl;
+       } else
+               /* This is the last page. */
+               bufp->ovfl = NULL;
+       n -= 2;
+       bp[0] = n;
+       FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
+       OFFSET(bp) = hashp->BSIZE - 1;
+
+       bufp->flags |= BUF_MOD;
+       if (rbufp && (rbufp != bufp))
+               __free_ovflpage(hashp, rbufp);
+       if (last_bfp && (last_bfp != rbufp))
+               __free_ovflpage(hashp, last_bfp);
+
+       hashp->NKEYS--;
+       return (0);
+}
+/*
+ * Returns:
+ *  0 = key not found
+ * -1 = get next overflow page
+ * -2 means key not found and this is big key/data
+ * -3 error
+ */
+extern int
+__find_bigpair(hashp, bufp, ndx, key, size)
+       HTAB *hashp;
+       BUFHEAD *bufp;
+       int ndx;
+       char *key;
+       int size;
+{
+       register u_int16_t *bp;
+       register char *p;
+       int ksize;
+       u_int16_t bytes;
+       char *kkey;
+
+       bp = (u_int16_t *)bufp->page;
+       p = bufp->page;
+       ksize = size;
+       kkey = key;
+
+       for (bytes = hashp->BSIZE - bp[ndx];
+           bytes <= size && bp[ndx + 1] == PARTIAL_KEY;
+           bytes = hashp->BSIZE - bp[ndx]) {
+               if (memcmp(p + bp[ndx], kkey, bytes))
+                       return (-2);
+               kkey += bytes;
+               ksize -= bytes;
+               bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0);
+               if (!bufp)
+                       return (-3);
+               p = bufp->page;
+               bp = (u_int16_t *)p;
+               ndx = 1;
+       }
+
+       if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) {
+#ifdef HASH_STATISTICS
+               ++hash_collisions;
+#endif
+               return (-2);
+       } else
+               return (ndx);
+}
+
+/*
+ * Given the buffer pointer of the first overflow page of a big pair,
+ * find the end of the big pair
+ *
+ * This will set bpp to the buffer header of the last page of the big pair.
+ * It will return the pageno of the overflow page following the last page
+ * of the pair; 0 if there isn't any (i.e. big pair is the last key in the
+ * bucket)
+ */
+extern u_int16_t
+__find_last_page(hashp, bpp)
+       HTAB *hashp;
+       BUFHEAD **bpp;
+{
+       BUFHEAD *bufp;
+       u_int16_t *bp, pageno;
+       int n;
+
+       bufp = *bpp;
+       bp = (u_int16_t *)bufp->page;
+       for (;;) {
+               n = bp[0];
+
+               /*
+                * This is the last page if: the tag is FULL_KEY_DATA and
+                * either only 2 entries OVFLPAGE marker is explicit there
+                * is freespace on the page.
+                */
+               if (bp[2] == FULL_KEY_DATA &&
+                   ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp))))
+                       break;
+
+               pageno = bp[n - 1];
+               bufp = __get_buf(hashp, pageno, bufp, 0);
+               if (!bufp)
+                       return (0);     /* Need to indicate an error! */
+               bp = (u_int16_t *)bufp->page;
+       }
+
+       *bpp = bufp;
+       if (bp[0] > 2)
+               return (bp[3]);
+       else
+               return (0);
+}
+
+/*
+ * Return the data for the key/data pair that begins on this page at this
+ * index (index should always be 1).
+ */
+extern int
+__big_return(hashp, bufp, ndx, val, set_current)
+       HTAB *hashp;
+       BUFHEAD *bufp;
+       int ndx;
+       DBT *val;
+       int set_current;
+{
+       BUFHEAD *save_p;
+       u_int16_t *bp, len, off, save_addr;
+       char *tp;
+
+       bp = (u_int16_t *)bufp->page;
+       while (bp[ndx + 1] == PARTIAL_KEY) {
+               bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+               if (!bufp)
+                       return (-1);
+               bp = (u_int16_t *)bufp->page;
+               ndx = 1;
+       }
+
+       if (bp[ndx + 1] == FULL_KEY) {
+               bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+               if (!bufp)
+                       return (-1);
+               bp = (u_int16_t *)bufp->page;
+               save_p = bufp;
+               save_addr = save_p->addr;
+               off = bp[1];
+               len = 0;
+       } else
+               if (!FREESPACE(bp)) {
+                       /*
+                        * This is a hack.  We can't distinguish between
+                        * FULL_KEY_DATA that contains complete data or
+                        * incomplete data, so we require that if the data
+                        * is complete, there is at least 1 byte of free
+                        * space left.
+                        */
+                       off = bp[bp[0]];
+                       len = bp[1] - off;
+                       save_p = bufp;
+                       save_addr = bufp->addr;
+                       bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+                       if (!bufp)
+                               return (-1);
+                       bp = (u_int16_t *)bufp->page;
+               } else {
+                       /* The data is all on one page. */
+                       tp = (char *)bp;
+                       off = bp[bp[0]];
+                       val->data = (u_char *)tp + off;
+                       val->size = bp[1] - off;
+                       if (set_current) {
+                               if (bp[0] == 2) {       /* No more buckets in
+                                                        * chain */
+                                       hashp->cpage = NULL;
+                                       hashp->cbucket++;
+                                       hashp->cndx = 1;
+                               } else {
+                                       hashp->cpage = __get_buf(hashp,
+                                           bp[bp[0] - 1], bufp, 0);
+                                       if (!hashp->cpage)
+                                               return (-1);
+                                       hashp->cndx = 1;
+                                       if (!((u_int16_t *)
+                                           hashp->cpage->page)[0]) {
+                                               hashp->cbucket++;
+                                               hashp->cpage = NULL;
+                                       }
+                               }
+                       }
+                       return (0);
+               }
+
+       val->size = collect_data(hashp, bufp, (int)len, set_current);
+       if (val->size == -1)
+               return (-1);
+       if (save_p->addr != save_addr) {
+               /* We are pretty short on buffers. */
+               errno = EINVAL;                 /* OUT OF BUFFERS */
+               return (-1);
+       }
+       memmove(hashp->tmp_buf, (save_p->page) + off, len);
+       val->data = (u_char *)hashp->tmp_buf;
+       return (0);
+}
+/*
+ * Count how big the total datasize is by recursing through the pages.  Then
+ * allocate a buffer and copy the data as you recurse up.
+ */
+static int
+collect_data(hashp, bufp, len, set)
+       HTAB *hashp;
+       BUFHEAD *bufp;
+       int len, set;
+{
+       register u_int16_t *bp;
+       register char *p;
+       BUFHEAD *xbp;
+       u_int16_t save_addr;
+       int mylen, totlen;
+
+       p = bufp->page;
+       bp = (u_int16_t *)p;
+       mylen = hashp->BSIZE - bp[1];
+       save_addr = bufp->addr;
+
+       if (bp[2] == FULL_KEY_DATA) {           /* End of Data */
+               totlen = len + mylen;
+               if (hashp->tmp_buf)
+                       free(hashp->tmp_buf);
+               if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL)
+                       return (-1);
+               if (set) {
+                       hashp->cndx = 1;
+                       if (bp[0] == 2) {       /* No more buckets in chain */
+                               hashp->cpage = NULL;
+                               hashp->cbucket++;
+                       } else {
+                               hashp->cpage =
+                                   __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+                               if (!hashp->cpage)
+                                       return (-1);
+                               else if (!((u_int16_t *)hashp->cpage->page)[0]) {
+                                       hashp->cbucket++;
+                                       hashp->cpage = NULL;
+                               }
+                       }
+               }
+       } else {
+               xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+               if (!xbp || ((totlen =
+                   collect_data(hashp, xbp, len + mylen, set)) < 1))
+                       return (-1);
+       }
+       if (bufp->addr != save_addr) {
+               errno = EINVAL;                 /* Out of buffers. */
+               return (-1);
+       }
+       memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen);
+       return (totlen);
+}
+
+/*
+ * Fill in the key and data for this big pair.
+ */
+extern int
+__big_keydata(hashp, bufp, key, val, set)
+       HTAB *hashp;
+       BUFHEAD *bufp;
+       DBT *key, *val;
+       int set;
+{
+       key->size = collect_key(hashp, bufp, 0, val, set);
+       if (key->size == -1)
+               return (-1);
+       key->data = (u_char *)hashp->tmp_key;
+       return (0);
+}
+
+/*
+ * Count how big the total key size is by recursing through the pages.  Then
+ * collect the data, allocate a buffer and copy the key as you recurse up.
+ */
+static int
+collect_key(hashp, bufp, len, val, set)
+       HTAB *hashp;
+       BUFHEAD *bufp;
+       int len;
+       DBT *val;
+       int set;
+{
+       BUFHEAD *xbp;
+       char *p;
+       int mylen, totlen;
+       u_int16_t *bp, save_addr;
+
+       p = bufp->page;
+       bp = (u_int16_t *)p;
+       mylen = hashp->BSIZE - bp[1];
+
+       save_addr = bufp->addr;
+       totlen = len + mylen;
+       if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) {    /* End of Key. */
+               if (hashp->tmp_key != NULL)
+                       free(hashp->tmp_key);
+               if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL)
+                       return (-1);
+               if (__big_return(hashp, bufp, 1, val, set))
+                       return (-1);
+       } else {
+               xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+               if (!xbp || ((totlen =
+                   collect_key(hashp, xbp, totlen, val, set)) < 1))
+                       return (-1);
+       }
+       if (bufp->addr != save_addr) {
+               errno = EINVAL;         /* MIS -- OUT OF BUFFERS */
+               return (-1);
+       }
+       memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen);
+       return (totlen);
+}
+
+/*
+ * Returns:
+ *  0 => OK
+ * -1 => error
+ */
+extern int
+__big_split(hashp, op, np, big_keyp, addr, obucket, ret)
+       HTAB *hashp;
+       BUFHEAD *op;    /* Pointer to where to put keys that go in old bucket */
+       BUFHEAD *np;    /* Pointer to new bucket page */
+                       /* Pointer to first page containing the big key/data */
+       BUFHEAD *big_keyp;
+       int addr;       /* Address of big_keyp */
+       u_int32_t   obucket;/* Old Bucket */
+       SPLIT_RETURN *ret;
+{
+       register BUFHEAD *tmpp;
+       register u_int16_t *tp;
+       BUFHEAD *bp;
+       DBT key, val;
+       u_int32_t change;
+       u_int16_t free_space, n, off;
+
+       bp = big_keyp;
+
+       /* Now figure out where the big key/data goes */
+       if (__big_keydata(hashp, big_keyp, &key, &val, 0))
+               return (-1);
+       change = (__call_hash(hashp, key.data, key.size) != obucket);
+
+       if (ret->next_addr = __find_last_page(hashp, &big_keyp)) {
+               if (!(ret->nextp =
+                   __get_buf(hashp, ret->next_addr, big_keyp, 0)))
+                       return (-1);;
+       } else
+               ret->nextp = NULL;
+
+       /* Now make one of np/op point to the big key/data pair */
+#ifdef DEBUG
+       assert(np->ovfl == NULL);
+#endif
+       if (change)
+               tmpp = np;
+       else
+               tmpp = op;
+
+       tmpp->flags |= BUF_MOD;
+#ifdef DEBUG1
+       (void)fprintf(stderr,
+           "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
+           (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0));
+#endif
+       tmpp->ovfl = bp;        /* one of op/np point to big_keyp */
+       tp = (u_int16_t *)tmpp->page;
+#ifdef DEBUG
+       assert(FREESPACE(tp) >= OVFLSIZE);
+#endif
+       n = tp[0];
+       off = OFFSET(tp);
+       free_space = FREESPACE(tp);
+       tp[++n] = (u_int16_t)addr;
+       tp[++n] = OVFLPAGE;
+       tp[0] = n;
+       OFFSET(tp) = off;
+       FREESPACE(tp) = free_space - OVFLSIZE;
+
+       /*
+        * Finally, set the new and old return values. BIG_KEYP contains a
+        * pointer to the last page of the big key_data pair. Make sure that
+        * big_keyp has no following page (2 elements) or create an empty
+        * following page.
+        */
+
+       ret->newp = np;
+       ret->oldp = op;
+
+       tp = (u_int16_t *)big_keyp->page;
+       big_keyp->flags |= BUF_MOD;
+       if (tp[0] > 2) {
+               /*
+                * There may be either one or two offsets on this page.  If
+                * there is one, then the overflow page is linked on normally
+                * and tp[4] is OVFLPAGE.  If there are two, tp[4] contains
+                * the second offset and needs to get stuffed in after the
+                * next overflow page is added.
+                */
+               n = tp[4];
+               free_space = FREESPACE(tp);
+               off = OFFSET(tp);
+               tp[0] -= 2;
+               FREESPACE(tp) = free_space + OVFLSIZE;
+               OFFSET(tp) = off;
+               tmpp = __add_ovflpage(hashp, big_keyp);
+               if (!tmpp)
+                       return (-1);
+               tp[4] = n;
+       } else
+               tmpp = big_keyp;
+
+       if (change)
+               ret->newp = tmpp;
+       else
+               ret->oldp = tmpp;
+       return (0);
+}
diff --git a/src/util/berk_db/hash/hash_buf.c b/src/util/berk_db/hash/hash_buf.c
new file mode 100644 (file)
index 0000000..92e1f93
--- /dev/null
@@ -0,0 +1,355 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * PACKAGE: hash
+ *
+ * DESCRIPTION:
+ *     Contains buffer management
+ *
+ * ROUTINES:
+ * External
+ *     __buf_init
+ *     __get_buf
+ *     __buf_free
+ *     __reclaim_buf
+ * Internal
+ *     newbuf
+ */
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static BUFHEAD *newbuf __P((HTAB *, u_int32_t, BUFHEAD *));
+
+/* Unlink B from its place in the lru */
+#define BUF_REMOVE(B) { \
+       (B)->prev->next = (B)->next; \
+       (B)->next->prev = (B)->prev; \
+}
+
+/* Insert B after P */
+#define BUF_INSERT(B, P) { \
+       (B)->next = (P)->next; \
+       (B)->prev = (P); \
+       (P)->next = (B); \
+       (B)->next->prev = (B); \
+}
+
+#define        MRU     hashp->bufhead.next
+#define        LRU     hashp->bufhead.prev
+
+#define MRU_INSERT(B)  BUF_INSERT((B), &hashp->bufhead)
+#define LRU_INSERT(B)  BUF_INSERT((B), LRU)
+
+/*
+ * We are looking for a buffer with address "addr".  If prev_bp is NULL, then
+ * address is a bucket index.  If prev_bp is not NULL, then it points to the
+ * page previous to an overflow page that we are trying to find.
+ *
+ * CAVEAT:  The buffer header accessed via prev_bp's ovfl field may no longer
+ * be valid.  Therefore, you must always verify that its address matches the
+ * address you are seeking.
+ */
+extern BUFHEAD *
+__get_buf(hashp, addr, prev_bp, newpage)
+       HTAB *hashp;
+       u_int32_t addr;
+       BUFHEAD *prev_bp;
+       int newpage;    /* If prev_bp set, indicates a new overflow page. */
+{
+       register BUFHEAD *bp;
+       register u_int32_t is_disk_mask;
+       register int is_disk, segment_ndx;
+       SEGMENT segp;
+
+       is_disk = 0;
+       is_disk_mask = 0;
+       if (prev_bp) {
+               bp = prev_bp->ovfl;
+               if (!bp || (bp->addr != addr))
+                       bp = NULL;
+               if (!newpage)
+                       is_disk = BUF_DISK;
+       } else {
+               /* Grab buffer out of directory */
+               segment_ndx = addr & (hashp->SGSIZE - 1);
+
+               /* valid segment ensured by __call_hash() */
+               segp = hashp->dir[addr >> hashp->SSHIFT];
+#ifdef DEBUG
+               assert(segp != NULL);
+#endif
+               bp = PTROF(segp[segment_ndx]);
+               is_disk_mask = ISDISK(segp[segment_ndx]);
+               is_disk = is_disk_mask || !hashp->new_file;
+       }
+
+       if (!bp) {
+               bp = newbuf(hashp, addr, prev_bp);
+               if (!bp ||
+                   __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0))
+                       return (NULL);
+               if (!prev_bp)
+                       segp[segment_ndx] =
+                           (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask);
+       } else {
+               BUF_REMOVE(bp);
+               MRU_INSERT(bp);
+       }
+       return (bp);
+}
+
+/*
+ * We need a buffer for this page. Either allocate one, or evict a resident
+ * one (if we have as many buffers as we're allowed) and put this one in.
+ *
+ * If newbuf finds an error (returning NULL), it also sets errno.
+ */
+static BUFHEAD *
+newbuf(hashp, addr, prev_bp)
+       HTAB *hashp;
+       u_int32_t addr;
+       BUFHEAD *prev_bp;
+{
+       register BUFHEAD *bp;           /* The buffer we're going to use */
+       register BUFHEAD *xbp;          /* Temp pointer */
+       register BUFHEAD *next_xbp;
+       SEGMENT segp;
+       int segment_ndx;
+       u_int16_t oaddr, *shortp;
+
+       oaddr = 0;
+       bp = LRU;
+       /*
+        * If LRU buffer is pinned, the buffer pool is too small. We need to
+        * allocate more buffers.
+        */
+       if (hashp->nbufs || (bp->flags & BUF_PIN)) {
+               /* Allocate a new one */
+               if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL)
+                       return (NULL);
+#ifdef PURIFY
+               memset(bp, 0xff, sizeof(BUFHEAD));
+#endif
+               if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) {
+                       free(bp);
+                       return (NULL);
+               }
+#ifdef PURIFY
+               memset(bp->page, 0xff, hashp->BSIZE);
+#endif
+               if (hashp->nbufs)
+                       hashp->nbufs--;
+       } else {
+               /* Kick someone out */
+               BUF_REMOVE(bp);
+               /*
+                * If this is an overflow page with addr 0, it's already been
+                * flushed back in an overflow chain and initialized.
+                */
+               if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) {
+                       /*
+                        * Set oaddr before __put_page so that you get it
+                        * before bytes are swapped.
+                        */
+                       shortp = (u_int16_t *)bp->page;
+                       if (shortp[0])
+                               oaddr = shortp[shortp[0] - 1];
+                       if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page,
+                           bp->addr, (int)IS_BUCKET(bp->flags), 0))
+                               return (NULL);
+                       /*
+                        * Update the pointer to this page (i.e. invalidate it).
+                        *
+                        * If this is a new file (i.e. we created it at open
+                        * time), make sure that we mark pages which have been
+                        * written to disk so we retrieve them from disk later,
+                        * rather than allocating new pages.
+                        */
+                       if (IS_BUCKET(bp->flags)) {
+                               segment_ndx = bp->addr & (hashp->SGSIZE - 1);
+                               segp = hashp->dir[bp->addr >> hashp->SSHIFT];
+#ifdef DEBUG
+                               assert(segp != NULL);
+#endif
+
+                               if (hashp->new_file &&
+                                   ((bp->flags & BUF_MOD) ||
+                                   ISDISK(segp[segment_ndx])))
+                                       segp[segment_ndx] = (BUFHEAD *)BUF_DISK;
+                               else
+                                       segp[segment_ndx] = NULL;
+                       }
+                       /*
+                        * Since overflow pages can only be access by means of
+                        * their bucket, free overflow pages associated with
+                        * this bucket.
+                        */
+                       for (xbp = bp; xbp->ovfl;) {
+                               next_xbp = xbp->ovfl;
+                               xbp->ovfl = 0;
+                               xbp = next_xbp;
+
+                               /* Check that ovfl pointer is up date. */
+                               if (IS_BUCKET(xbp->flags) ||
+                                   (oaddr != xbp->addr))
+                                       break;
+
+                               shortp = (u_int16_t *)xbp->page;
+                               if (shortp[0])
+                                       /* set before __put_page */
+                                       oaddr = shortp[shortp[0] - 1];
+                               if ((xbp->flags & BUF_MOD) && __put_page(hashp,
+                                   xbp->page, xbp->addr, 0, 0))
+                                       return (NULL);
+                               xbp->addr = 0;
+                               xbp->flags = 0;
+                               BUF_REMOVE(xbp);
+                               LRU_INSERT(xbp);
+                       }
+               }
+       }
+
+       /* Now assign this buffer */
+       bp->addr = addr;
+#ifdef DEBUG1
+       (void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n",
+           bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0);
+#endif
+       bp->ovfl = NULL;
+       if (prev_bp) {
+               /*
+                * If prev_bp is set, this is an overflow page, hook it in to
+                * the buffer overflow links.
+                */
+#ifdef DEBUG1
+               (void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n",
+                   prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0),
+                   (bp ? bp->addr : 0));
+#endif
+               prev_bp->ovfl = bp;
+               bp->flags = 0;
+       } else
+               bp->flags = BUF_BUCKET;
+       MRU_INSERT(bp);
+       return (bp);
+}
+
+extern void
+__buf_init(hashp, nbytes)
+       HTAB *hashp;
+       int nbytes;
+{
+       BUFHEAD *bfp;
+       int npages;
+
+       bfp = &(hashp->bufhead);
+       npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT;
+       npages = MAX(npages, MIN_BUFFERS);
+
+       hashp->nbufs = npages;
+       bfp->next = bfp;
+       bfp->prev = bfp;
+       /*
+        * This space is calloc'd so these are already null.
+        *
+        * bfp->ovfl = NULL;
+        * bfp->flags = 0;
+        * bfp->page = NULL;
+        * bfp->addr = 0;
+        */
+}
+
+extern int
+__buf_free(hashp, do_free, to_disk)
+       HTAB *hashp;
+       int do_free, to_disk;
+{
+       BUFHEAD *bp;
+
+       /* Need to make sure that buffer manager has been initialized */
+       if (!LRU)
+               return (0);
+       for (bp = LRU; bp != &hashp->bufhead;) {
+               /* Check that the buffer is valid */
+               if (bp->addr || IS_BUCKET(bp->flags)) {
+                       if (to_disk && (bp->flags & BUF_MOD) &&
+                           __put_page(hashp, bp->page,
+                           bp->addr, IS_BUCKET(bp->flags), 0))
+                               return (-1);
+               }
+               /* Check if we are freeing stuff */
+               if (do_free) {
+                       if (bp->page)
+                               free(bp->page);
+                       BUF_REMOVE(bp);
+                       free(bp);
+                       bp = LRU;
+               } else
+                       bp = bp->prev;
+       }
+       return (0);
+}
+
+extern void
+__reclaim_buf(hashp, bp)
+       HTAB *hashp;
+       BUFHEAD *bp;
+{
+       bp->ovfl = 0;
+       bp->addr = 0;
+       bp->flags = 0;
+       BUF_REMOVE(bp);
+       LRU_INSERT(bp);
+}
diff --git a/src/util/berk_db/hash/hash_func.c b/src/util/berk_db/hash/hash_func.c
new file mode 100644 (file)
index 0000000..a5ec434
--- /dev/null
@@ -0,0 +1,212 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_func.c        8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static u_int32_t hash1 __P((const void *, size_t));
+static u_int32_t hash2 __P((const void *, size_t));
+static u_int32_t hash3 __P((const void *, size_t));
+static u_int32_t hash4 __P((const void *, size_t));
+
+/* Global default hash function */
+u_int32_t (*__default_hash) __P((const void *, size_t)) = hash4;
+
+/*
+ * HASH FUNCTIONS
+ *
+ * Assume that we've already split the bucket to which this key hashes,
+ * calculate that bucket, and check that in fact we did already split it.
+ *
+ * This came from ejb's hsearch.
+ */
+
+#define PRIME1         37
+#define PRIME2         1048583
+
+static u_int32_t
+hash1(keyarg, len)
+       const void *keyarg;
+       register size_t len;
+{
+       register const u_char *key;
+       register u_int32_t h;
+
+       /* Convert string to integer */
+       for (key = keyarg, h = 0; len--;)
+               h = h * PRIME1 ^ (*key++ - ' ');
+       h %= PRIME2;
+       return (h);
+}
+
+/*
+ * Phong's linear congruential hash
+ */
+#define dcharhash(h, c)        ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
+
+static u_int32_t
+hash2(keyarg, len)
+       const void *keyarg;
+       size_t len;
+{
+       register const u_char *e, *key;
+       register u_int32_t h;
+       register u_char c;
+
+       key = keyarg;
+       e = key + len;
+       for (h = 0; key != e;) {
+               c = *key++;
+               if (!c && key > e)
+                       break;
+               dcharhash(h, c);
+       }
+       return (h);
+}
+
+/*
+ * This is INCREDIBLY ugly, but fast.  We break the string up into 8 byte
+ * units.  On the first time through the loop we get the "leftover bytes"
+ * (strlen % 8).  On every other iteration, we perform 8 HASHC's so we handle
+ * all 8 bytes.  Essentially, this saves us 7 cmp & branch instructions.  If
+ * this routine is heavily used enough, it's worth the ugly coding.
+ *
+ * OZ's original sdbm hash
+ */
+static u_int32_t
+hash3(keyarg, len)
+       const void *keyarg;
+       register size_t len;
+{
+       register const u_char *key;
+       register size_t loop;
+       register u_int32_t h;
+
+#define HASHC   h = *key++ + 65599 * h
+
+       h = 0;
+       key = keyarg;
+       if (len > 0) {
+               loop = (len + 8 - 1) >> 3;
+
+               switch (len & (8 - 1)) {
+               case 0:
+                       do {
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 7:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 6:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 5:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 4:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 3:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 2:
+                               HASHC;
+                               /* FALLTHROUGH */
+               case 1:
+                               HASHC;
+                       } while (--loop);
+               }
+       }
+       return (h);
+}
+
+/* Hash function from Chris Torek. */
+static u_int32_t
+hash4(keyarg, len)
+       const void *keyarg;
+       register size_t len;
+{
+       register const u_char *key;
+       register size_t loop;
+       register u_int32_t h;
+
+#define HASH4a   h = (h << 5) - h + *key++;
+#define HASH4b   h = (h << 5) + h + *key++;
+#define HASH4 HASH4b
+
+       h = 0;
+       key = keyarg;
+       if (len > 0) {
+               loop = (len + 8 - 1) >> 3;
+
+               switch (len & (8 - 1)) {
+               case 0:
+                       do {
+                               HASH4;
+                               /* FALLTHROUGH */
+               case 7:
+                               HASH4;
+                               /* FALLTHROUGH */
+               case 6:
+                               HASH4;
+                               /* FALLTHROUGH */
+               case 5:
+                               HASH4;
+                               /* FALLTHROUGH */
+               case 4:
+                               HASH4;
+                               /* FALLTHROUGH */
+               case 3:
+                               HASH4;
+                               /* FALLTHROUGH */
+               case 2:
+                               HASH4;
+                               /* FALLTHROUGH */
+               case 1:
+                               HASH4;
+                       } while (--loop);
+               }
+       }
+       return (h);
+}
diff --git a/src/util/berk_db/hash/hash_log2.c b/src/util/berk_db/hash/hash_log2.c
new file mode 100644 (file)
index 0000000..c8c56bf
--- /dev/null
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_log2.c        8.2 (Berkeley) 5/31/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <db.h>
+
+u_int32_t
+__log2(num)
+       u_int32_t num;
+{
+       register u_int32_t i, limit;
+
+       limit = 1;
+       for (i = 0; limit < num; limit = limit << 1, i++);
+       return (i);
+}
diff --git a/src/util/berk_db/hash/hash_page.c b/src/util/berk_db/hash/hash_page.c
new file mode 100644 (file)
index 0000000..e1dfe6b
--- /dev/null
@@ -0,0 +1,944 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_page.c        8.7 (Berkeley) 8/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * PACKAGE:  hashing
+ *
+ * DESCRIPTION:
+ *     Page manipulation for hashing package.
+ *
+ * ROUTINES:
+ *
+ * External
+ *     __get_page
+ *     __add_ovflpage
+ * Internal
+ *     overflow_page
+ *     open_temp
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static u_int32_t       *fetch_bitmap __P((HTAB *, int));
+static u_int32_t        first_free __P((u_int32_t));
+static int      open_temp __P((HTAB *));
+static u_int16_t        overflow_page __P((HTAB *));
+static void     putpair __P((char *, const DBT *, const DBT *));
+static void     squeeze_key __P((u_int16_t *, const DBT *, const DBT *));
+static int      ugly_split
+                   __P((HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int));
+
+#define        PAGE_INIT(P) { \
+       ((u_int16_t *)(P))[0] = 0; \
+       ((u_int16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_int16_t); \
+       ((u_int16_t *)(P))[2] = hashp->BSIZE; \
+}
+
+/*
+ * This is called AFTER we have verified that there is room on the page for
+ * the pair (PAIRFITS has returned true) so we go right ahead and start moving
+ * stuff on.
+ */
+static void
+putpair(p, key, val)
+       char *p;
+       const DBT *key, *val;
+{
+       register u_int16_t *bp, n, off;
+
+       bp = (u_int16_t *)p;
+
+       /* Enter the key first. */
+       n = bp[0];
+
+       off = OFFSET(bp) - key->size;
+       memmove(p + off, key->data, key->size);
+       bp[++n] = off;
+
+       /* Now the data. */
+       off -= val->size;
+       memmove(p + off, val->data, val->size);
+       bp[++n] = off;
+
+       /* Adjust page info. */
+       bp[0] = n;
+       bp[n + 1] = off - ((n + 3) * sizeof(u_int16_t));
+       bp[n + 2] = off;
+}
+
+/*
+ * Returns:
+ *      0 OK
+ *     -1 error
+ */
+extern int
+__delpair(hashp, bufp, ndx)
+       HTAB *hashp;
+       BUFHEAD *bufp;
+       register int ndx;
+{
+       register u_int16_t *bp, newoff;
+       register int n;
+       u_int16_t pairlen;
+
+       bp = (u_int16_t *)bufp->page;
+       n = bp[0];
+
+       if (bp[ndx + 1] < REAL_KEY)
+               return (__big_delete(hashp, bufp));
+       if (ndx != 1)
+               newoff = bp[ndx - 1];
+       else
+               newoff = hashp->BSIZE;
+       pairlen = newoff - bp[ndx + 1];
+
+       if (ndx != (n - 1)) {
+               /* Hard Case -- need to shuffle keys */
+               register int i;
+               register char *src = bufp->page + (int)OFFSET(bp);
+               register char *dst = src + (int)pairlen;
+               memmove(dst, src, bp[ndx + 1] - OFFSET(bp));
+
+               /* Now adjust the pointers */
+               for (i = ndx + 2; i <= n; i += 2) {
+                       if (bp[i + 1] == OVFLPAGE) {
+                               bp[i - 2] = bp[i];
+                               bp[i - 1] = bp[i + 1];
+                       } else {
+                               bp[i - 2] = bp[i] + pairlen;
+                               bp[i - 1] = bp[i + 1] + pairlen;
+                       }
+               }
+       }
+       /* Finally adjust the page data */
+       bp[n] = OFFSET(bp) + pairlen;
+       bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t);
+       bp[0] = n - 2;
+       hashp->NKEYS--;
+
+       bufp->flags |= BUF_MOD;
+       return (0);
+}
+/*
+ * Returns:
+ *      0 ==> OK
+ *     -1 ==> Error
+ */
+extern int
+__split_page(hashp, obucket, nbucket)
+       HTAB *hashp;
+       u_int32_t obucket, nbucket;
+{
+       register BUFHEAD *new_bufp, *old_bufp;
+       register u_int16_t *ino;
+       register char *np;
+       DBT key, val;
+       int n, ndx, retval;
+       u_int16_t copyto, diff, off, moved;
+       char *op;
+
+       copyto = (u_int16_t)hashp->BSIZE;
+       off = (u_int16_t)hashp->BSIZE;
+       old_bufp = __get_buf(hashp, obucket, NULL, 0);
+       if (old_bufp == NULL)
+               return (-1);
+       new_bufp = __get_buf(hashp, nbucket, NULL, 0);
+       if (new_bufp == NULL)
+               return (-1);
+
+       old_bufp->flags |= (BUF_MOD | BUF_PIN);
+       new_bufp->flags |= (BUF_MOD | BUF_PIN);
+
+       ino = (u_int16_t *)(op = old_bufp->page);
+       np = new_bufp->page;
+
+       moved = 0;
+
+       for (n = 1, ndx = 1; n < ino[0]; n += 2) {
+               if (ino[n + 1] < REAL_KEY) {
+                       retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
+                           (int)copyto, (int)moved);
+                       old_bufp->flags &= ~BUF_PIN;
+                       new_bufp->flags &= ~BUF_PIN;
+                       return (retval);
+
+               }
+               key.data = (u_char *)op + ino[n];
+               key.size = off - ino[n];
+
+               if (__call_hash(hashp, key.data, key.size) == obucket) {
+                       /* Don't switch page */
+                       diff = copyto - off;
+                       if (diff) {
+                               copyto = ino[n + 1] + diff;
+                               memmove(op + copyto, op + ino[n + 1],
+                                   off - ino[n + 1]);
+                               ino[ndx] = copyto + ino[n] - ino[n + 1];
+                               ino[ndx + 1] = copyto;
+                       } else
+                               copyto = ino[n + 1];
+                       ndx += 2;
+               } else {
+                       /* Switch page */
+                       val.data = (u_char *)op + ino[n + 1];
+                       val.size = ino[n] - ino[n + 1];
+                       putpair(np, &key, &val);
+                       moved += 2;
+               }
+
+               off = ino[n + 1];
+       }
+
+       /* Now clean up the page */
+       ino[0] -= moved;
+       FREESPACE(ino) = copyto - sizeof(u_int16_t) * (ino[0] + 3);
+       OFFSET(ino) = copyto;
+
+#ifdef DEBUG3
+       (void)fprintf(stderr, "split %d/%d\n",
+           ((u_int16_t *)np)[0] / 2,
+           ((u_int16_t *)op)[0] / 2);
+#endif
+       /* unpin both pages */
+       old_bufp->flags &= ~BUF_PIN;
+       new_bufp->flags &= ~BUF_PIN;
+       return (0);
+}
+
+/*
+ * Called when we encounter an overflow or big key/data page during split
+ * handling.  This is special cased since we have to begin checking whether
+ * the key/data pairs fit on their respective pages and because we may need
+ * overflow pages for both the old and new pages.
+ *
+ * The first page might be a page with regular key/data pairs in which case
+ * we have a regular overflow condition and just need to go on to the next
+ * page or it might be a big key/data pair in which case we need to fix the
+ * big key/data pair.
+ *
+ * Returns:
+ *      0 ==> success
+ *     -1 ==> failure
+ */
+static int
+ugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved)
+       HTAB *hashp;
+       u_int32_t obucket;      /* Same as __split_page. */
+       BUFHEAD *old_bufp, *new_bufp;
+       int copyto;     /* First byte on page which contains key/data values. */
+       int moved;      /* Number of pairs moved to new page. */
+{
+       register BUFHEAD *bufp; /* Buffer header for ino */
+       register u_int16_t *ino;        /* Page keys come off of */
+       register u_int16_t *np; /* New page */
+       register u_int16_t *op; /* Page keys go on to if they aren't moving */
+
+       BUFHEAD *last_bfp;      /* Last buf header OVFL needing to be freed */
+       DBT key, val;
+       SPLIT_RETURN ret;
+       u_int16_t n, off, ov_addr, scopyto;
+       char *cino;             /* Character value of ino */
+
+       bufp = old_bufp;
+       ino = (u_int16_t *)old_bufp->page;
+       np = (u_int16_t *)new_bufp->page;
+       op = (u_int16_t *)old_bufp->page;
+       last_bfp = NULL;
+       scopyto = (u_int16_t)copyto;    /* ANSI */
+
+       n = ino[0] - 1;
+       while (n < ino[0]) {
+               if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
+                       if (__big_split(hashp, old_bufp,
+                           new_bufp, bufp, bufp->addr, obucket, &ret))
+                               return (-1);
+                       old_bufp = ret.oldp;
+                       if (!old_bufp)
+                               return (-1);
+                       op = (u_int16_t *)old_bufp->page;
+                       new_bufp = ret.newp;
+                       if (!new_bufp)
+                               return (-1);
+                       np = (u_int16_t *)new_bufp->page;
+                       bufp = ret.nextp;
+                       if (!bufp)
+                               return (0);
+                       cino = (char *)bufp->page;
+                       ino = (u_int16_t *)cino;
+                       last_bfp = ret.nextp;
+               } else if (ino[n + 1] == OVFLPAGE) {
+                       ov_addr = ino[n];
+                       /*
+                        * Fix up the old page -- the extra 2 are the fields
+                        * which contained the overflow information.
+                        */
+                       ino[0] -= (moved + 2);
+                       FREESPACE(ino) =
+                           scopyto - sizeof(u_int16_t) * (ino[0] + 3);
+                       OFFSET(ino) = scopyto;
+
+                       bufp = __get_buf(hashp, ov_addr, bufp, 0);
+                       if (!bufp)
+                               return (-1);
+
+                       ino = (u_int16_t *)bufp->page;
+                       n = 1;
+                       scopyto = hashp->BSIZE;
+                       moved = 0;
+
+                       if (last_bfp)
+                               __free_ovflpage(hashp, last_bfp);
+                       last_bfp = bufp;
+               }
+               /* Move regular sized pairs of there are any */
+               off = hashp->BSIZE;
+               for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
+                       cino = (char *)ino;
+                       key.data = (u_char *)cino + ino[n];
+                       key.size = off - ino[n];
+                       val.data = (u_char *)cino + ino[n + 1];
+                       val.size = ino[n] - ino[n + 1];
+                       off = ino[n + 1];
+
+                       if (__call_hash(hashp, key.data, key.size) == obucket) {
+                               /* Keep on old page */
+                               if (PAIRFITS(op, (&key), (&val)))
+                                       putpair((char *)op, &key, &val);
+                               else {
+                                       old_bufp =
+                                           __add_ovflpage(hashp, old_bufp);
+                                       if (!old_bufp)
+                                               return (-1);
+                                       op = (u_int16_t *)old_bufp->page;
+                                       putpair((char *)op, &key, &val);
+                               }
+                               old_bufp->flags |= BUF_MOD;
+                       } else {
+                               /* Move to new page */
+                               if (PAIRFITS(np, (&key), (&val)))
+                                       putpair((char *)np, &key, &val);
+                               else {
+                                       new_bufp =
+                                           __add_ovflpage(hashp, new_bufp);
+                                       if (!new_bufp)
+                                               return (-1);
+                                       np = (u_int16_t *)new_bufp->page;
+                                       putpair((char *)np, &key, &val);
+                               }
+                               new_bufp->flags |= BUF_MOD;
+                       }
+               }
+       }
+       if (last_bfp)
+               __free_ovflpage(hashp, last_bfp);
+       return (0);
+}
+
+/*
+ * Add the given pair to the page
+ *
+ * Returns:
+ *     0 ==> OK
+ *     1 ==> failure
+ */
+extern int
+__addel(hashp, bufp, key, val)
+       HTAB *hashp;
+       BUFHEAD *bufp;
+       const DBT *key, *val;
+{
+       register u_int16_t *bp, *sop;
+       int do_expand;
+
+       bp = (u_int16_t *)bufp->page;
+       do_expand = 0;
+       while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY))
+               /* Exception case */
+               if (bp[2] == FULL_KEY_DATA && bp[0] == 2)
+                       /* This is the last page of a big key/data pair
+                          and we need to add another page */
+                       break;
+               else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
+                       bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+                       if (!bufp)
+                               return (-1);
+                       bp = (u_int16_t *)bufp->page;
+               } else
+                       /* Try to squeeze key on this page */
+                       if (FREESPACE(bp) > PAIRSIZE(key, val)) {
+                               squeeze_key(bp, key, val);
+                               return (0);
+                       } else {
+                               bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+                               if (!bufp)
+                                       return (-1);
+                               bp = (u_int16_t *)bufp->page;
+                       }
+
+       if (PAIRFITS(bp, key, val))
+               putpair(bufp->page, key, val);
+       else {
+               do_expand = 1;
+               bufp = __add_ovflpage(hashp, bufp);
+               if (!bufp)
+                       return (-1);
+               sop = (u_int16_t *)bufp->page;
+
+               if (PAIRFITS(sop, key, val))
+                       putpair((char *)sop, key, val);
+               else
+                       if (__big_insert(hashp, bufp, key, val))
+                               return (-1);
+       }
+       bufp->flags |= BUF_MOD;
+       /*
+        * If the average number of keys per bucket exceeds the fill factor,
+        * expand the table.
+        */
+       hashp->NKEYS++;
+       if (do_expand ||
+           (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
+               return (__expand_table(hashp));
+       return (0);
+}
+
+/*
+ *
+ * Returns:
+ *     pointer on success
+ *     NULL on error
+ */
+extern BUFHEAD *
+__add_ovflpage(hashp, bufp)
+       HTAB *hashp;
+       BUFHEAD *bufp;
+{
+       register u_int16_t *sp;
+       u_int16_t ndx, ovfl_num;
+#ifdef DEBUG1
+       int tmp1, tmp2;
+#endif
+       sp = (u_int16_t *)bufp->page;
+
+       /* Check if we are dynamically determining the fill factor */
+       if (hashp->FFACTOR == DEF_FFACTOR) {
+               hashp->FFACTOR = sp[0] >> 1;
+               if (hashp->FFACTOR < MIN_FFACTOR)
+                       hashp->FFACTOR = MIN_FFACTOR;
+       }
+       bufp->flags |= BUF_MOD;
+       ovfl_num = overflow_page(hashp);
+#ifdef DEBUG1
+       tmp1 = bufp->addr;
+       tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;
+#endif
+       if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1)))
+               return (NULL);
+       bufp->ovfl->flags |= BUF_MOD;
+#ifdef DEBUG1
+       (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",
+           tmp1, tmp2, bufp->ovfl->addr);
+#endif
+       ndx = sp[0];
+       /*
+        * Since a pair is allocated on a page only if there's room to add
+        * an overflow page, we know that the OVFL information will fit on
+        * the page.
+        */
+       sp[ndx + 4] = OFFSET(sp);
+       sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;
+       sp[ndx + 1] = ovfl_num;
+       sp[ndx + 2] = OVFLPAGE;
+       sp[0] = ndx + 2;
+#ifdef HASH_STATISTICS
+       hash_overflows++;
+#endif
+       return (bufp->ovfl);
+}
+
+/*
+ * Returns:
+ *      0 indicates SUCCESS
+ *     -1 indicates FAILURE
+ */
+extern int
+__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
+       HTAB *hashp;
+       char *p;
+       u_int32_t bucket;
+       int is_bucket, is_disk, is_bitmap;
+{
+       register int fd, page, size;
+       int rsize;
+       u_int16_t *bp;
+
+       fd = hashp->fp;
+       size = hashp->BSIZE;
+
+       if ((fd == -1) || !is_disk) {
+               PAGE_INIT(p);
+               return (0);
+       }
+       if (is_bucket)
+               page = BUCKET_TO_PAGE(bucket);
+       else
+               page = OADDR_TO_PAGE(bucket);
+       if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
+           ((rsize = read(fd, p, size)) == -1))
+               return (-1);
+       bp = (u_int16_t *)p;
+       if (!rsize)
+               bp[0] = 0;      /* We hit the EOF, so initialize a new page */
+       else
+               if (rsize != size) {
+                       errno = EFTYPE;
+                       return (-1);
+               }
+       if (!is_bitmap && !bp[0]) {
+               PAGE_INIT(p);
+       } else
+               if (hashp->LORDER != BYTE_ORDER) {
+                       register int i, max;
+
+                       if (is_bitmap) {
+                               max = hashp->BSIZE >> 2; /* divide by 4 */
+                               for (i = 0; i < max; i++)
+                                       M_32_SWAP(((int *)p)[i]);
+                       } else {
+                               M_16_SWAP(bp[0]);
+                               max = bp[0] + 2;
+                               for (i = 1; i <= max; i++)
+                                       M_16_SWAP(bp[i]);
+                       }
+               }
+       return (0);
+}
+
+/*
+ * Write page p to disk
+ *
+ * Returns:
+ *      0 ==> OK
+ *     -1 ==>failure
+ */
+extern int
+__put_page(hashp, p, bucket, is_bucket, is_bitmap)
+       HTAB *hashp;
+       char *p;
+       u_int32_t bucket;
+       int is_bucket, is_bitmap;
+{
+       register int fd, page, size;
+       int wsize;
+
+       size = hashp->BSIZE;
+       if ((hashp->fp == -1) && open_temp(hashp))
+               return (-1);
+       fd = hashp->fp;
+
+       if (hashp->LORDER != BYTE_ORDER) {
+               register int i;
+               register int max;
+
+               if (is_bitmap) {
+                       max = hashp->BSIZE >> 2;        /* divide by 4 */
+                       for (i = 0; i < max; i++)
+                               M_32_SWAP(((int *)p)[i]);
+               } else {
+                       max = ((u_int16_t *)p)[0] + 2;
+                       for (i = 0; i <= max; i++)
+                               M_16_SWAP(((u_int16_t *)p)[i]);
+               }
+       }
+       if (is_bucket)
+               page = BUCKET_TO_PAGE(bucket);
+       else
+               page = OADDR_TO_PAGE(bucket);
+       if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
+           ((wsize = write(fd, p, size)) == -1))
+               /* Errno is set */
+               return (-1);
+       if (wsize != size) {
+               errno = EFTYPE;
+               return (-1);
+       }
+       return (0);
+}
+
+#define BYTE_MASK      ((1 << INT_BYTE_SHIFT) -1)
+/*
+ * Initialize a new bitmap page.  Bitmap pages are left in memory
+ * once they are read in.
+ */
+extern int
+__ibitmap(hashp, pnum, nbits, ndx)
+       HTAB *hashp;
+       int pnum, nbits, ndx;
+{
+       u_int32_t *ip;
+       int clearbytes, clearints;
+
+       if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)
+               return (1);
+       hashp->nmaps++;
+       clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;
+       clearbytes = clearints << INT_TO_BYTE;
+       (void)memset((char *)ip, 0, clearbytes);
+       (void)memset(((char *)ip) + clearbytes, 0xFF,
+           hashp->BSIZE - clearbytes);
+       ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
+       SETBIT(ip, 0);
+       hashp->BITMAPS[ndx] = (u_int16_t)pnum;
+       hashp->mapp[ndx] = ip;
+       return (0);
+}
+
+static u_int32_t
+first_free(map)
+       u_int32_t map;
+{
+       register u_int32_t i, mask;
+
+       mask = 0x1;
+       for (i = 0; i < BITS_PER_MAP; i++) {
+               if (!(mask & map))
+                       return (i);
+               mask = mask << 1;
+       }
+       return (i);
+}
+
+static u_int16_t
+overflow_page(hashp)
+       HTAB *hashp;
+{
+       register u_int32_t *freep;
+       register int max_free, offset, splitnum;
+       u_int16_t addr;
+       int bit, first_page, free_bit, free_page, i, in_use_bits, j;
+#ifdef DEBUG2
+       int tmp1, tmp2;
+#endif
+       splitnum = hashp->OVFL_POINT;
+       max_free = hashp->SPARES[splitnum];
+
+       free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);
+       free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);
+
+       /* Look through all the free maps to find the first free block */
+       first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT);
+       for ( i = first_page; i <= free_page; i++ ) {
+               if (!(freep = (u_int32_t *)hashp->mapp[i]) &&
+                   !(freep = fetch_bitmap(hashp, i)))
+                       return (0);
+               if (i == free_page)
+                       in_use_bits = free_bit;
+               else
+                       in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;
+               
+               if (i == first_page) {
+                       bit = hashp->LAST_FREED &
+                           ((hashp->BSIZE << BYTE_SHIFT) - 1);
+                       j = bit / BITS_PER_MAP;
+                       bit = bit & ~(BITS_PER_MAP - 1);
+               } else {
+                       bit = 0;
+                       j = 0;
+               }
+               for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
+                       if (freep[j] != ALL_SET)
+                               goto found;
+       }
+
+       /* No Free Page Found */
+       hashp->LAST_FREED = hashp->SPARES[splitnum];
+       hashp->SPARES[splitnum]++;
+       offset = hashp->SPARES[splitnum] -
+           (splitnum ? hashp->SPARES[splitnum - 1] : 0);
+
+#define        OVMSG   "HASH: Out of overflow pages.  Increase page size\n"
+       if (offset > SPLITMASK) {
+               if (++splitnum >= NCACHED) {
+                       (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+                       return (0);
+               }
+               hashp->OVFL_POINT = splitnum;
+               hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
+               hashp->SPARES[splitnum-1]--;
+               offset = 1;
+       }
+
+       /* Check if we need to allocate a new bitmap page */
+       if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {
+               free_page++;
+               if (free_page >= NCACHED) {
+                       (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+                       return (0);
+               }
+               /*
+                * This is tricky.  The 1 indicates that you want the new page
+                * allocated with 1 clear bit.  Actually, you are going to
+                * allocate 2 pages from this map.  The first is going to be
+                * the map page, the second is the overflow page we were
+                * looking for.  The init_bitmap routine automatically, sets
+                * the first bit of itself to indicate that the bitmap itself
+                * is in use.  We would explicitly set the second bit, but
+                * don't have to if we tell init_bitmap not to leave it clear
+                * in the first place.
+                */
+               if (__ibitmap(hashp,
+                   (int)OADDR_OF(splitnum, offset), 1, free_page))
+                       return (0);
+               hashp->SPARES[splitnum]++;
+#ifdef DEBUG2
+               free_bit = 2;
+#endif
+               offset++;
+               if (offset > SPLITMASK) {
+                       if (++splitnum >= NCACHED) {
+                               (void)write(STDERR_FILENO, OVMSG,
+                                   sizeof(OVMSG) - 1);
+                               return (0);
+                       }
+                       hashp->OVFL_POINT = splitnum;
+                       hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
+                       hashp->SPARES[splitnum-1]--;
+                       offset = 0;
+               }
+       } else {
+               /*
+                * Free_bit addresses the last used bit.  Bump it to address
+                * the first available bit.
+                */
+               free_bit++;
+               SETBIT(freep, free_bit);
+       }
+
+       /* Calculate address of the new overflow page */
+       addr = OADDR_OF(splitnum, offset);
+#ifdef DEBUG2
+       (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
+           addr, free_bit, free_page);
+#endif
+       return (addr);
+
+found:
+       bit = bit + first_free(freep[j]);
+       SETBIT(freep, bit);
+#ifdef DEBUG2
+       tmp1 = bit;
+       tmp2 = i;
+#endif
+       /*
+        * Bits are addressed starting with 0, but overflow pages are addressed
+        * beginning at 1. Bit is a bit addressnumber, so we need to increment
+        * it to convert it to a page number.
+        */
+       bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));
+       if (bit >= hashp->LAST_FREED)
+               hashp->LAST_FREED = bit - 1;
+
+       /* Calculate the split number for this page */
+       for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
+       offset = (i ? bit - hashp->SPARES[i - 1] : bit);
+       if (offset >= SPLITMASK)
+               return (0);     /* Out of overflow pages */
+       addr = OADDR_OF(i, offset);
+#ifdef DEBUG2
+       (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
+           addr, tmp1, tmp2);
+#endif
+
+       /* Allocate and return the overflow page */
+       return (addr);
+}
+
+/*
+ * Mark this overflow page as free.
+ */
+extern void
+__free_ovflpage(hashp, obufp)
+       HTAB *hashp;
+       BUFHEAD *obufp;
+{
+       register u_int16_t addr;
+       u_int32_t *freep;
+       int bit_address, free_page, free_bit;
+       u_int16_t ndx;
+
+       addr = obufp->addr;
+#ifdef DEBUG1
+       (void)fprintf(stderr, "Freeing %d\n", addr);
+#endif
+       ndx = (((u_int16_t)addr) >> SPLITSHIFT);
+       bit_address =
+           (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
+        if (bit_address < hashp->LAST_FREED)
+               hashp->LAST_FREED = bit_address;
+       free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));
+       free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);
+
+       if (!(freep = hashp->mapp[free_page]))
+               freep = fetch_bitmap(hashp, free_page);
+#ifdef DEBUG
+       /*
+        * This had better never happen.  It means we tried to read a bitmap
+        * that has already had overflow pages allocated off it, and we
+        * failed to read it from the file.
+        */
+       if (!freep)
+               assert(0);
+#endif
+       CLRBIT(freep, free_bit);
+#ifdef DEBUG2
+       (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
+           obufp->addr, free_bit, free_page);
+#endif
+       __reclaim_buf(hashp, obufp);
+}
+
+/*
+ * Returns:
+ *      0 success
+ *     -1 failure
+ */
+static int
+open_temp(hashp)
+       HTAB *hashp;
+{
+       sigset_t set, oset;
+       static char namestr[] = "_hashXXXXXX";
+
+       /* Block signals; make sure file goes away at process exit. */
+       (void)sigfillset(&set);
+       (void)sigprocmask(SIG_BLOCK, &set, &oset);
+       if ((hashp->fp = mkstemp(namestr)) != -1) {
+               (void)unlink(namestr);
+               (void)fcntl(hashp->fp, F_SETFD, 1);
+       }
+       (void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
+       return (hashp->fp != -1 ? 0 : -1);
+}
+
+/*
+ * We have to know that the key will fit, but the last entry on the page is
+ * an overflow pair, so we need to shift things.
+ */
+static void
+squeeze_key(sp, key, val)
+       u_int16_t *sp;
+       const DBT *key, *val;
+{
+       register char *p;
+       u_int16_t free_space, n, off, pageno;
+
+       p = (char *)sp;
+       n = sp[0];
+       free_space = FREESPACE(sp);
+       off = OFFSET(sp);
+
+       pageno = sp[n - 1];
+       off -= key->size;
+       sp[n - 1] = off;
+       memmove(p + off, key->data, key->size);
+       off -= val->size;
+       sp[n] = off;
+       memmove(p + off, val->data, val->size);
+       sp[0] = n + 2;
+       sp[n + 1] = pageno;
+       sp[n + 2] = OVFLPAGE;
+       FREESPACE(sp) = free_space - PAIRSIZE(key, val);
+       OFFSET(sp) = off;
+}
+
+static u_int32_t *
+fetch_bitmap(hashp, ndx)
+       HTAB *hashp;
+       int ndx;
+{
+       if (ndx >= hashp->nmaps)
+               return (NULL);
+       if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)
+               return (NULL);
+       if (__get_page(hashp,
+           (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) {
+               free(hashp->mapp[ndx]);
+               return (NULL);
+       }
+       return (hashp->mapp[ndx]);
+}
+
+#ifdef DEBUG4
+int
+print_chain(addr)
+       int addr;
+{
+       BUFHEAD *bufp;
+       short *bp, oaddr;
+
+       (void)fprintf(stderr, "%d ", addr);
+       bufp = __get_buf(hashp, addr, NULL, 0);
+       bp = (short *)bufp->page;
+       while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||
+               ((bp[0] > 2) && bp[2] < REAL_KEY))) {
+               oaddr = bp[bp[0] - 1];
+               (void)fprintf(stderr, "%d ", (int)oaddr);
+               bufp = __get_buf(hashp, (int)oaddr, bufp, 0);
+               bp = (short *)bufp->page;
+       }
+       (void)fprintf(stderr, "\n");
+}
+#endif
diff --git a/src/util/berk_db/hash/hsearch.c b/src/util/berk_db/hash/hsearch.c
new file mode 100644 (file)
index 0000000..cc8f7a4
--- /dev/null
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hsearch.c  8.4 (Berkeley) 7/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <string.h>
+
+#include <db.h>
+#include "search.h"
+
+static DB *dbp = NULL;
+static ENTRY retval;
+
+extern int
+hcreate(nel)
+       u_int nel;
+{
+       HASHINFO info;
+
+       info.nelem = nel;
+       info.bsize = 256;
+       info.ffactor = 8;
+       info.cachesize = 0;
+       info.hash = NULL;
+       info.lorder = 0;
+       dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR, 0600, &info, 0);
+       return ((int)dbp);
+}
+
+extern ENTRY *
+hsearch(item, action)
+       ENTRY item;
+       ACTION action;
+{
+       DBT key, val;
+       int status;
+
+       if (!dbp)
+               return (NULL);
+       key.data = (u_char *)item.key;
+       key.size = strlen(item.key) + 1;
+
+       if (action == ENTER) {
+               val.data = (u_char *)item.data;
+               val.size = strlen(item.data) + 1;
+               status = (dbp->put)(dbp, &key, &val, R_NOOVERWRITE);
+               if (status)
+                       return (NULL);
+       } else {
+               /* FIND */
+               status = (dbp->get)(dbp, &key, &val, 0);
+               if (status)
+                       return (NULL);
+               else
+                       item.data = (char *)val.data;
+       }
+       retval.key = item.key;
+       retval.data = item.data;
+       return (&retval);
+}
+
+extern void
+hdestroy()
+{
+       if (dbp) {
+               (void)(dbp->close)(dbp);
+               dbp = NULL;
+       }
+}
diff --git a/src/util/berk_db/hash/krb5_ndbm.c b/src/util/berk_db/hash/krb5_ndbm.c
new file mode 100644 (file)
index 0000000..7baa032
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * util/berk_db/krb5_ndbm.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * krb5_ndbm.c - Customize the dbm wrapper for Kerberos.
+ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ndbm.c     8.4 (Berkeley) 7/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * This package provides a dbm compatible interface to the new hashing
+ * package described in db(3).
+ */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <ndbm.h>
+#include "hash.h"
+
+/*
+ * For Kerberos, we make some generalizations about kdb records.  We assume
+ * that records are on average KRB5_DBENT_ASIZE in length.
+ *
+ * Increasing KRB5_DB_BUCKETSIZE doesn't get you much of anything.
+ */
+#define        KRB5_DB_BUCKETSIZE      1024
+#define        KRB5_DBENT_ASIZE        512
+#define        KRB5_DB_MINBUCKET       512
+#define        KRB5_DB_INITSIZE        128
+
+/*
+ * Returns:
+ *     *DBM on success
+ *      NULL on failure
+ */
+extern DBM *
+db_dbm_open(file, flags, mode)
+       const char *file;
+       int flags, mode;
+{
+       HASHINFO info;
+       char path[MAXPATHLEN];
+
+       info.bsize = KRB5_DB_BUCKETSIZE;
+       /*
+        * if (info.bsize < KRB5_DB_MINBUCKET) info.bsize = KRB5_DB_MINBUCKET;
+        */
+       info.ffactor = info.bsize / KRB5_DBENT_ASIZE; 
+       info.nelem = KRB5_DB_INITSIZE;
+       info.cachesize = 0;
+       info.hash = NULL;
+       /* Always store databases in big endian (e.g. network order) */
+       info.lorder = BIG_ENDIAN;
+       (void)strcpy(path, file);
+       (void)strcat(path, DBM_SUFFIX);
+       return ((DBM *)__hash_open(path, flags, mode, &info, 0));
+}
+
+extern void
+db_dbm_close(db)
+       DBM *db;
+{
+       (void)(db->close)(db);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+extern datum
+db_dbm_fetch(db, key)
+       DBM *db;
+       datum key;
+{
+       datum retval;
+       int status;
+
+       status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
+       if (status) {
+               retval.dptr = NULL;
+               retval.dsize = 0;
+       }
+       return (retval);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+extern datum
+db_dbm_firstkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+extern datum
+db_dbm_nextkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ */
+extern int
+db_dbm_delete(db, key)
+       DBM *db;
+       datum key;
+{
+       int status;
+
+       status = (db->del)(db, (DBT *)&key, 0);
+       if (status)
+               return (-1);
+       else
+               return (0);
+}
+
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ *      1 if DBM_INSERT and entry exists
+ */
+extern int
+db_dbm_store(db, key, content, flags)
+       DBM *db;
+       datum key, content;
+       int flags;
+{
+       return ((db->put)(db, (DBT *)&key, (DBT *)&content,
+           (flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
+}
+
+extern int
+db_dbm_error(db)
+       DBM *db;
+{
+       HTAB *hp;
+
+       hp = (HTAB *)db->internal;
+       return (hp->errno);
+}
+
+extern int
+db_dbm_clearerr(db)
+       DBM *db;
+{
+       HTAB *hp;
+
+       hp = (HTAB *)db->internal;
+       hp->errno = 0;
+       return (0);
+}
+
+extern int
+db_dbm_dirfno(db)
+       DBM *db;
+{
+       return(((HTAB *)db->internal)->fp);
+}
diff --git a/src/util/berk_db/hash/ndbm.c b/src/util/berk_db/hash/ndbm.c
new file mode 100644 (file)
index 0000000..2cbbe91
--- /dev/null
@@ -0,0 +1,202 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ndbm.c     8.4 (Berkeley) 7/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * This package provides a dbm compatible interface to the new hashing
+ * package described in db(3).
+ */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <ndbm.h>
+#include "hash.h"
+
+/*
+ * Returns:
+ *     *DBM on success
+ *      NULL on failure
+ */
+extern DBM *
+dbm_open(file, flags, mode)
+       const char *file;
+       int flags, mode;
+{
+       HASHINFO info;
+       char path[MAXPATHLEN];
+
+       info.bsize = 4096;
+       info.ffactor = 40;
+       info.nelem = 1;
+       info.cachesize = 0;
+       info.hash = NULL;
+       info.lorder = 0;
+       (void)strcpy(path, file);
+       (void)strcat(path, DBM_SUFFIX);
+       return ((DBM *)__hash_open(path, flags, mode, &info, 0));
+}
+
+extern void
+dbm_close(db)
+       DBM *db;
+{
+       (void)(db->close)(db);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+extern datum
+dbm_fetch(db, key)
+       DBM *db;
+       datum key;
+{
+       datum retval;
+       int status;
+
+       status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
+       if (status) {
+               retval.dptr = NULL;
+               retval.dsize = 0;
+       }
+       return (retval);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+extern datum
+dbm_firstkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+
+/*
+ * Returns:
+ *     DATUM on success
+ *     NULL on failure
+ */
+extern datum
+dbm_nextkey(db)
+       DBM *db;
+{
+       int status;
+       datum retdata, retkey;
+
+       status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
+       if (status)
+               retkey.dptr = NULL;
+       return (retkey);
+}
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ */
+extern int
+dbm_delete(db, key)
+       DBM *db;
+       datum key;
+{
+       int status;
+
+       status = (db->del)(db, (DBT *)&key, 0);
+       if (status)
+               return (-1);
+       else
+               return (0);
+}
+
+/*
+ * Returns:
+ *      0 on success
+ *     <0 failure
+ *      1 if DBM_INSERT and entry exists
+ */
+extern int
+dbm_store(db, key, content, flags)
+       DBM *db;
+       datum key, content;
+       int flags;
+{
+       return ((db->put)(db, (DBT *)&key, (DBT *)&content,
+           (flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
+}
+
+extern int
+dbm_error(db)
+       DBM *db;
+{
+       HTAB *hp;
+
+       hp = (HTAB *)db->internal;
+       return (hp->errno);
+}
+
+extern int
+dbm_clearerr(db)
+       DBM *db;
+{
+       HTAB *hp;
+
+       hp = (HTAB *)db->internal;
+       hp->errno = 0;
+       return (0);
+}
+
+extern int
+dbm_dirfno(db)
+       DBM *db;
+{
+       return(((HTAB *)db->internal)->fp);
+}
diff --git a/src/util/berk_db/hash/page.h b/src/util/berk_db/hash/page.h
new file mode 100644 (file)
index 0000000..0fc0d5a
--- /dev/null
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)page.h      8.2 (Berkeley) 5/31/94
+ */
+
+/*
+ * Definitions for hashing page file format.
+ */
+
+/*
+ * routines dealing with a data page
+ *
+ * page format:
+ *     +------------------------------+
+ * p   | n | keyoff | datoff | keyoff |
+ *     +------------+--------+--------+
+ *     | datoff | free  |  ptr  | --> |
+ *     +--------+---------------------+
+ *     |        F R E E A R E A       |
+ *     +--------------+---------------+
+ *     |  <---- - - - | data          |
+ *     +--------+-----+----+----------+
+ *     |  key   | data     | key      |
+ *     +--------+----------+----------+
+ *
+ * Pointer to the free space is always:  p[p[0] + 2]
+ * Amount of free space on the page is:  p[p[0] + 1]
+ */
+
+/*
+ * How many bytes required for this pair?
+ *     2 shorts in the table at the top of the page + room for the
+ *     key and room for the data
+ *
+ * We prohibit entering a pair on a page unless there is also room to append
+ * an overflow page. The reason for this it that you can get in a situation
+ * where a single key/data pair fits on a page, but you can't append an
+ * overflow page and later you'd have to split the key/data and handle like
+ * a big pair.
+ * You might as well do this up front.
+ */
+
+#define        PAIRSIZE(K,D)   (2*sizeof(u_int16_t) + (K)->size + (D)->size)
+#define BIGOVERHEAD    (4*sizeof(u_int16_t))
+#define KEYSIZE(K)     (4*sizeof(u_int16_t) + (K)->size);
+#define OVFLSIZE       (2*sizeof(u_int16_t))
+#define FREESPACE(P)   ((P)[(P)[0]+1])
+#define        OFFSET(P)       ((P)[(P)[0]+2])
+#define PAIRFITS(P,K,D) \
+       (((P)[2] >= REAL_KEY) && \
+           (PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P)))
+#define PAGE_META(N)   (((N)+3) * sizeof(u_int16_t))
+
+typedef struct {
+       BUFHEAD *newp;
+       BUFHEAD *oldp;
+       BUFHEAD *nextp;
+       u_int16_t next_addr;
+}       SPLIT_RETURN;
diff --git a/src/util/berk_db/hash/search.h b/src/util/berk_db/hash/search.h
new file mode 100644 (file)
index 0000000..4d3b914
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)search.h    8.1 (Berkeley) 6/4/93
+ */
+
+/* Backward compatibility to hsearch interface. */
+typedef struct entry {
+       char *key;
+       char *data;
+} ENTRY;
+
+typedef enum {
+       FIND, ENTER
+} ACTION;
+
+int     hcreate __P((unsigned int));
+void    hdestroy __P((void));
+ENTRY  *hsearch __P((ENTRY, ACTION));
diff --git a/src/util/berk_db/include/.Sanitize b/src/util/berk_db/include/.Sanitize
new file mode 100644 (file)
index 0000000..1768af4
--- /dev/null
@@ -0,0 +1,33 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+db.h
+mpool.h
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/include/db.h b/src/util/berk_db/include/db.h
new file mode 100644 (file)
index 0000000..47044f0
--- /dev/null
@@ -0,0 +1,239 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)db.h        8.7 (Berkeley) 6/16/94
+ */
+
+#ifndef _DB_H_
+#define        _DB_H_
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+#include <limits.h>
+
+#ifdef __DBINTERFACE_PRIVATE
+#include <compat.h>
+#endif
+
+#define        RET_ERROR       -1              /* Return values. */
+#define        RET_SUCCESS      0
+#define        RET_SPECIAL      1
+
+#ifndef        __BIT_TYPES_DEFINED__
+#define        __BIT_TYPES_DEFINED__
+typedef        __signed char              int8_t;
+typedef        unsigned char            u_int8_t;
+typedef        short                     int16_t;
+typedef        unsigned short          u_int16_t;
+typedef        int                       int32_t;
+typedef        unsigned int            u_int32_t;
+#ifdef WE_DONT_NEED_QUADS
+typedef        long long                 int64_t;
+typedef        unsigned long long      u_int64_t;
+#endif
+#endif
+
+#define        MAX_PAGE_NUMBER 0xffffffff      /* >= # of pages in a file */
+typedef u_int32_t      pgno_t;
+#define        MAX_PAGE_OFFSET 65535           /* >= # of bytes in a page */
+typedef u_int16_t      indx_t;
+#define        MAX_REC_NUMBER  0xffffffff      /* >= # of records in a tree */
+typedef u_int32_t      recno_t;
+
+/* Key/data structure -- a Data-Base Thang. */
+typedef struct {
+       void    *data;                  /* data */
+       size_t   size;                  /* data length */
+} DBT;
+
+/* Routine flags. */
+#define        R_CURSOR        1               /* del, put, seq */
+#define        __R_UNUSED      2               /* UNUSED */
+#define        R_FIRST         3               /* seq */
+#define        R_IAFTER        4               /* put (RECNO) */
+#define        R_IBEFORE       5               /* put (RECNO) */
+#define        R_LAST          6               /* seq (BTREE, RECNO) */
+#define        R_NEXT          7               /* seq */
+#define        R_NOOVERWRITE   8               /* put */
+#define        R_PREV          9               /* seq (BTREE, RECNO) */
+#define        R_SETCURSOR     10              /* put (RECNO) */
+#define        R_RECNOSYNC     11              /* sync (RECNO) */
+
+typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
+
+/*
+ * !!!
+ * The following flags are included in the dbopen(3) call as part of the
+ * open(2) flags.  In order to avoid conflicts with the open flags, start
+ * at the top of the 16 or 32-bit number space and work our way down.  If
+ * the open flags were significantly expanded in the future, it could be
+ * a problem.  Wish I'd left another flags word in the dbopen call.
+ *
+ * !!!
+ * None of this stuff is implemented yet.  The only reason that it's here
+ * is so that the access methods can skip copying the key/data pair when
+ * the DB_LOCK flag isn't set.
+ */
+/*
+ * Kerberos: This used to be #if UINT_MAX > 65535, but Ultrix gags on this.
+ */
+#if SIZEOF_INT > 2
+#define        DB_LOCK         0x20000000      /* Do locking. */
+#define        DB_SHMEM        0x40000000      /* Use shared memory. */
+#define        DB_TXN          0x80000000      /* Do transactions. */
+#else
+#define        DB_LOCK             0x2000      /* Do locking. */
+#define        DB_SHMEM            0x4000      /* Use shared memory. */
+#define        DB_TXN              0x8000      /* Do transactions. */
+#endif
+
+/* Access method description structure. */
+typedef struct __db {
+       DBTYPE type;                    /* Underlying db type. */
+       int (*close)    __P((struct __db *));
+       int (*del)      __P((const struct __db *, const DBT *, u_int));
+       int (*get)      __P((const struct __db *, const DBT *, DBT *, u_int));
+       int (*put)      __P((const struct __db *, DBT *, const DBT *, u_int));
+       int (*seq)      __P((const struct __db *, DBT *, DBT *, u_int));
+       int (*sync)     __P((const struct __db *, u_int));
+       void *internal;                 /* Access method private. */
+       int (*fd)       __P((const struct __db *));
+} DB;
+
+#define        BTREEMAGIC      0x053162
+#define        BTREEVERSION    3
+
+/* Structure used to pass parameters to the btree routines. */
+typedef struct {
+#define        R_DUP           0x01    /* duplicate keys */
+       u_long  flags;
+       u_int   cachesize;      /* bytes to cache */
+       int     maxkeypage;     /* maximum keys per page */
+       int     minkeypage;     /* minimum keys per page */
+       u_int   psize;          /* page size */
+       int     (*compare)      /* comparison function */
+           __P((const DBT *, const DBT *));
+       size_t  (*prefix)       /* prefix function */
+           __P((const DBT *, const DBT *));
+       int     lorder;         /* byte order */
+} BTREEINFO;
+
+#define        HASHMAGIC       0x061561
+#define        HASHVERSION     2
+
+/* Structure used to pass parameters to the hashing routines. */
+typedef struct {
+       u_int   bsize;          /* bucket size */
+       u_int   ffactor;        /* fill factor */
+       u_int   nelem;          /* number of elements */
+       u_int   cachesize;      /* bytes to cache */
+       u_int32_t               /* hash function */
+               (*hash) __P((const void *, size_t));
+       int     lorder;         /* byte order */
+} HASHINFO;
+
+/* Structure used to pass parameters to the record routines. */
+typedef struct {
+#define        R_FIXEDLEN      0x01    /* fixed-length records */
+#define        R_NOKEY         0x02    /* key not required */
+#define        R_SNAPSHOT      0x04    /* snapshot the input */
+       u_long  flags;
+       u_int   cachesize;      /* bytes to cache */
+       u_int   psize;          /* page size */
+       int     lorder;         /* byte order */
+       size_t  reclen;         /* record length (fixed-length records) */
+       u_char  bval;           /* delimiting byte (variable-length records */
+       char    *bfname;        /* btree file name */ 
+} RECNOINFO;
+
+#ifdef __DBINTERFACE_PRIVATE
+/*
+ * Little endian <==> big endian 32-bit swap macros.
+ *     M_32_SWAP       swap a memory location
+ *     P_32_SWAP       swap a referenced memory location
+ *     P_32_COPY       swap from one location to another
+ */
+#define        M_32_SWAP(a) {                                                  \
+       u_int32_t _tmp = a;                                             \
+       ((char *)&a)[0] = ((char *)&_tmp)[3];                           \
+       ((char *)&a)[1] = ((char *)&_tmp)[2];                           \
+       ((char *)&a)[2] = ((char *)&_tmp)[1];                           \
+       ((char *)&a)[3] = ((char *)&_tmp)[0];                           \
+}
+#define        P_32_SWAP(a) {                                                  \
+       u_int32_t _tmp = *(u_int32_t *)a;                               \
+       ((char *)a)[0] = ((char *)&_tmp)[3];                            \
+       ((char *)a)[1] = ((char *)&_tmp)[2];                            \
+       ((char *)a)[2] = ((char *)&_tmp)[1];                            \
+       ((char *)a)[3] = ((char *)&_tmp)[0];                            \
+}
+#define        P_32_COPY(a, b) {                                               \
+       ((char *)&(b))[0] = ((char *)&(a))[3];                          \
+       ((char *)&(b))[1] = ((char *)&(a))[2];                          \
+       ((char *)&(b))[2] = ((char *)&(a))[1];                          \
+       ((char *)&(b))[3] = ((char *)&(a))[0];                          \
+}
+
+/*
+ * Little endian <==> big endian 16-bit swap macros.
+ *     M_16_SWAP       swap a memory location
+ *     P_16_SWAP       swap a referenced memory location
+ *     P_16_COPY       swap from one location to another
+ */
+#define        M_16_SWAP(a) {                                                  \
+       u_int16_t _tmp = a;                                             \
+       ((char *)&a)[0] = ((char *)&_tmp)[1];                           \
+       ((char *)&a)[1] = ((char *)&_tmp)[0];                           \
+}
+#define        P_16_SWAP(a) {                                                  \
+       u_int16_t _tmp = *(u_int16_t *)a;                               \
+       ((char *)a)[0] = ((char *)&_tmp)[1];                            \
+       ((char *)a)[1] = ((char *)&_tmp)[0];                            \
+}
+#define        P_16_COPY(a, b) {                                               \
+       ((char *)&(b))[0] = ((char *)&(a))[1];                          \
+       ((char *)&(b))[1] = ((char *)&(a))[0];                          \
+}
+#endif
+
+__BEGIN_DECLS
+DB *dbopen __P((const char *, int, int, DBTYPE, const void *));
+
+#ifdef __DBINTERFACE_PRIVATE
+DB     *__bt_open __P((const char *, int, int, const BTREEINFO *, int));
+DB     *__hash_open __P((const char *, int, int, const HASHINFO *, int));
+DB     *__rec_open __P((const char *, int, int, const RECNOINFO *, int));
+void    __dbpanic __P((DB *dbp));
+#endif
+__END_DECLS
+#endif /* !_DB_H_ */
diff --git a/src/util/berk_db/include/mpool.h b/src/util/berk_db/include/mpool.h
new file mode 100644 (file)
index 0000000..40d1022
--- /dev/null
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)mpool.h     8.2 (Berkeley) 7/14/94
+ */
+
+#include <sys/queue.h>
+
+/*
+ * The memory pool scheme is a simple one.  Each in-memory page is referenced
+ * by a bucket which is threaded in up to two of three ways.  All active pages
+ * are threaded on a hash chain (hashed by page number) and an lru chain.
+ * Inactive pages are threaded on a free chain.  Each reference to a memory
+ * pool is handed an opaque MPOOL cookie which stores all of this information.
+ */
+#define        HASHSIZE        128
+#define        HASHKEY(pgno)   ((pgno - 1) % HASHSIZE)
+
+/* The BKT structures are the elements of the queues. */
+typedef struct _bkt {
+       CIRCLEQ_ENTRY(_bkt) hq;         /* hash queue */
+       CIRCLEQ_ENTRY(_bkt) q;          /* lru queue */
+       void    *page;                  /* page */
+       pgno_t   pgno;                  /* page number */
+
+#define        MPOOL_DIRTY     0x01            /* page needs to be written */
+#define        MPOOL_PINNED    0x02            /* page is pinned into memory */
+       u_int8_t flags;                 /* flags */
+} BKT;
+
+typedef struct MPOOL {
+       CIRCLEQ_HEAD(_lqh, _bkt) lqh;   /* lru queue head */
+                                       /* hash queue array */
+       CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE];
+       pgno_t  curcache;               /* current number of cached pages */
+       pgno_t  maxcache;               /* max number of cached pages */
+       pgno_t  npages;                 /* number of pages in the file */
+       u_long  pagesize;               /* file page size */
+       int     fd;                     /* file descriptor */
+                                       /* page in conversion routine */
+       void    (*pgin) __P((void *, pgno_t, void *));
+                                       /* page out conversion routine */
+       void    (*pgout) __P((void *, pgno_t, void *));
+       void    *pgcookie;              /* cookie for page in/out routines */
+#ifdef STATISTICS
+       u_long  cachehit;
+       u_long  cachemiss;
+       u_long  pagealloc;
+       u_long  pageflush;
+       u_long  pageget;
+       u_long  pagenew;
+       u_long  pageput;
+       u_long  pageread;
+       u_long  pagewrite;
+#endif
+} MPOOL;
+
+__BEGIN_DECLS
+MPOOL  *mpool_open __P((void *, int, pgno_t, pgno_t));
+void    mpool_filter __P((MPOOL *, void (*)(void *, pgno_t, void *),
+           void (*)(void *, pgno_t, void *), void *));
+void   *mpool_new __P((MPOOL *, pgno_t *));
+void   *mpool_get __P((MPOOL *, pgno_t, u_int));
+int     mpool_put __P((MPOOL *, void *, u_int));
+int     mpool_sync __P((MPOOL *));
+int     mpool_close __P((MPOOL *));
+#ifdef STATISTICS
+void    mpool_stat __P((MPOOL *));
+#endif
+__END_DECLS
diff --git a/src/util/berk_db/man/.Sanitize b/src/util/berk_db/man/.Sanitize
new file mode 100644 (file)
index 0000000..7db6c8c
--- /dev/null
@@ -0,0 +1,32 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+hash.3
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/man/hash.3 b/src/util/berk_db/man/hash.3
new file mode 100644 (file)
index 0000000..4367031
--- /dev/null
@@ -0,0 +1,159 @@
+.\" Copyright (c) 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)hash.3      8.6 (Berkeley) 8/18/94
+.\"
+.TH HASH 3 "August 18, 1994"
+.UC 7
+.SH NAME
+hash \- hash database access method
+.SH SYNOPSIS
+.nf
+.ft B
+#include <sys/types.h>
+#include <db.h>
+.ft R
+.fi
+.SH DESCRIPTION
+The routine
+.IR dbopen
+is the library interface to database files.
+One of the supported file formats is hash files.
+The general description of the database access methods is in
+.IR dbopen (3),
+this manual page describes only the hash specific information.
+.PP
+The hash data structure is an extensible, dynamic hashing scheme.
+.PP
+The access method specific data structure provided to
+.I dbopen
+is defined in the <db.h> include file as follows:
+.sp
+typedef struct {
+.RS
+u_int bsize;
+.br
+u_int ffactor;
+.br
+u_int nelem;
+.br
+u_int cachesize;
+.br
+u_int32_t (*hash)(const void *, size_t);
+.br
+int lorder;
+.RE
+} HASHINFO;
+.PP
+The elements of this structure are as follows:
+.TP
+bsize
+.I Bsize
+defines the hash table bucket size, and is, by default, 256 bytes.
+It may be preferable to increase the page size for disk-resident tables
+and tables with large data items.
+.TP
+ffactor
+.I Ffactor
+indicates a desired density within the hash table.
+It is an approximation of the number of keys allowed to accumulate in any
+one bucket, determining when the hash table grows or shrinks.
+The default value is 8.
+.TP
+nelem
+.I Nelem
+is an estimate of the final size of the hash table.
+If not set or set too low, hash tables will expand gracefully as keys
+are entered, although a slight performance degradation may be noticed.
+The default value is 1.
+.TP
+cachesize
+A suggested maximum size, in bytes, of the memory cache.
+This value is
+.B only
+advisory, and the access method will allocate more memory rather
+than fail.
+.TP
+hash
+.I Hash
+is a user defined hash function.
+Since no hash function performs equally well on all possible data, the
+user may find that the built-in hash function does poorly on a particular
+data set.
+User specified hash functions must take two arguments (a pointer to a byte
+string and a length) and return a 32-bit quantity to be used as the hash
+value.
+.TP
+lorder
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example, 
+big endian order would be the number 4,321.
+If
+.I lorder
+is 0 (no order is specified) the current host order is used.
+If the  file already exists, the specified value is ignored and the
+value specified when the tree was created is used.
+.PP
+If the file already exists (and the O_TRUNC flag is not specified), the
+values specified for the parameters bsize, ffactor, lorder and nelem are
+ignored and the values specified when the tree was created are used.
+.PP
+If a hash function is specified,
+.I hash_open
+will attempt to determine if the hash function specified is the same as
+the one with which the database was created, and will fail if it is not.
+.PP
+Backward compatible interfaces to the routines described in
+.IR dbm (3),
+and
+.IR ndbm (3)
+are provided, however these interfaces are not compatible with
+previous file formats.
+.SH ERRORS
+The
+.I hash
+access method routines may fail and set
+.I errno
+for any of the errors specified for the library routine
+.IR dbopen (3).
+.SH "SEE ALSO"
+.IR btree (3),
+.IR dbopen (3),
+.IR mpool (3),
+.IR recno (3)
+.sp
+.IR "Dynamic Hash Tables" ,
+Per-Ake Larson, Communications of the ACM, April 1988.
+.sp
+.IR "A New Hash Package for UNIX" ,
+Margo Seltzer, USENIX Proceedings, Winter 1991.
+.SH BUGS
+Only big and little endian byte order is supported.
diff --git a/src/util/berk_db/test/.Sanitize b/src/util/berk_db/test/.Sanitize
new file mode 100644 (file)
index 0000000..f90865d
--- /dev/null
@@ -0,0 +1,39 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+.cvsignore
+Makefile.in
+README
+configure
+configure.in
+dbtest.c
+hash.tests
+run.test
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/test/.cvsignore b/src/util/berk_db/test/.cvsignore
new file mode 100644 (file)
index 0000000..e8c05a6
--- /dev/null
@@ -0,0 +1 @@
+configure
diff --git a/src/util/berk_db/test/Makefile.in b/src/util/berk_db/test/Makefile.in
new file mode 100644 (file)
index 0000000..88fbf39
--- /dev/null
@@ -0,0 +1,30 @@
+PORTDIR=$(srcdir)/../PORT/krb5
+#      @(#)Makefile    8.15 (Berkeley) 7/28/94
+
+PROG=  dbtest
+OBJS=  dbtest.o strerror.o
+
+# Uncomment the STAT line get hash and btree statistical use info.  This
+# also forces ld to load the btree debug functions for use by gdb, which
+# is useful.  The db library has to be compiled with -DSTATISTICS as well.
+INC=   -I${PORTDIR}/include -I${PORTDIR} -I${PORTDIR}/../../include -I${PORTDIR}/../../../include
+OORG=  -g
+#STAT= -DSTATISTICS
+CFLAGS=        -D__DBINTERFACE_PRIVATE -DDEBUG ${STAT} ${OORG} ${INC}
+
+dbtest: ${OBJS} ../libdb.a
+       ${CC} -o $@ ${OBJS} ../libdb.a
+
+strerror.o: ${PORTDIR}/../clib/strerror.c
+       ${CC} -c ${PORTDIR}/../clib/strerror.c
+
+clean::
+       rm -f dbtest.core gmon.out ${OBJS} ${PROG} t1 t2 t3
+
+${OBJS}: Makefile
+
+check::        dbtest
+       /bin/sh $(srcdir)/run.test hash
+
+all::
+
diff --git a/src/util/berk_db/test/README b/src/util/berk_db/test/README
new file mode 100644 (file)
index 0000000..0c0cd13
--- /dev/null
@@ -0,0 +1,74 @@
+#      @(#)README      8.8 (Berkeley) 7/31/94
+
+To build this portably, try something like:
+
+    make PORTDIR="../PORT/MACH"
+
+where MACH is the machine, i.e. "sunos.4.1.1".
+
+To run the tests, enter "sh run.test".  If your system dictionary isn't
+in /usr/share/dict/words, edit run.test to reflect the correct place.
+
+Fairly large files (the command files) are built in this directory during
+the test runs, and even larger files (the database files) are created in
+"/var/tmp".  If the latter directory doesn't exist, set the environmental
+variable TMPDIR to a directory where the files can be built.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+The script file consists of lines with an initial character which is
+the command for that line, or an initial character indicating a key
+or data entry for a previous command.
+
+Legal command characters are as follows:
+
+c: compare a record
+       + must be followed by [kK][dD]; the data value in the database
+         associated with the specified key is compared to the specified
+         data value.
+e: echo a string
+       + writes out the rest of the line into the output file; if the
+         last character is not a carriage-return, a newline is appended.
+f: set the flags for the next command
+       + no value zero's the flags
+g: do a get command
+       + must be followed by [kK]
+       + writes out the retrieved data DBT.
+o [r]: dump [reverse]
+       + dump the database out, if 'r' is set, in reverse order.
+p: do a put command
+       + must be followed by [kK][dD]
+r: do a del command
+       + must be followed by [kK] unless R_CURSOR flag set.
+S: sync the database
+s: do a seq command
+       + must be followed by [kK] if R_CURSOR flag set.
+       + writes out the retrieved data DBT.
+
+Legal key/data characters are as follows:
+
+D [file]: data file
+       + set the current data value to the contents of the file
+d [data]:
+       + set the current key value to the contents of the line.
+K [file]: key file
+       + set the current key value to the contents of the file
+k [data]:
+       + set the current key value to the contents of the line.
+
+Blank lines, lines with leading white space, and lines with leading
+hash marks (#) are ignored.
+
+Options to dbtest are as follows:
+
+       -d: Set the DB_LOCK flag.
+       -f: Use the file argument as the database file.
+       -i: Use the rest of the argument to set elements in the info
+           structure.  If the type is btree, then "-i cachesize=10240"
+           will set BTREEINFO.cachesize to 10240.
+       -o: The rest of the argument is the output file instead of
+           using stdout.
+       -s: Don't delete the database file before opening it, i.e.
+           use the database file from a previous run.
+
+Dbtest requires two arguments, the type of access "hash", "recno"
+or "btree", and the script name or "-" to indicate stdin.
diff --git a/src/util/berk_db/test/configure.in b/src/util/berk_db/test/configure.in
new file mode 100644 (file)
index 0000000..b6f9e01
--- /dev/null
@@ -0,0 +1,6 @@
+AC_INIT(configure.in)
+AC_SET_BUILDTOP
+WITH_CCOPTS
+WITH_KRB5ROOT
+CONFIG_RULES
+V5_AC_OUTPUT_MAKEFILE
diff --git a/src/util/berk_db/test/dbtest.c b/src/util/berk_db/test/dbtest.c
new file mode 100644 (file)
index 0000000..3cc0e77
--- /dev/null
@@ -0,0 +1,759 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1992, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)dbtest.c   8.17 (Berkeley) 9/1/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA };
+
+void    compare __P((DBT *, DBT *));
+DBTYPE  dbtype __P((char *));
+void    dump __P((DB *, int));
+void    err __P((const char *, ...));
+void    get __P((DB *, DBT *));
+void    getdata __P((DB *, DBT *, DBT *));
+void    put __P((DB *, DBT *, DBT *));
+void    rem __P((DB *, DBT *));
+char   *sflags __P((int));
+void    synk __P((DB *));
+void   *rfile __P((char *, size_t *));
+void    seq __P((DB *, DBT *));
+u_int   setflags __P((char *));
+void   *setinfo __P((DBTYPE, char *));
+void    usage __P((void));
+void   *xmalloc __P((char *, size_t));
+
+DBTYPE type;                           /* Database type. */
+void *infop;                           /* Iflags. */
+u_long lineno;                         /* Current line in test script. */
+u_int flags;                           /* Current DB flags. */
+int ofd = STDOUT_FILENO;               /* Standard output fd. */
+
+DB *XXdbp;                             /* Global for gdb. */
+int XXlineno;                          /* Fast breakpoint for gdb. */
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       extern int optind;
+       extern char *optarg;
+       enum S command, state;
+       DB *dbp;
+       DBT data, key, keydata;
+       size_t len;
+       int ch, oflags, sflag;
+       char *fname, *infoarg, *p, *t, buf[8 * 1024];
+
+       infoarg = NULL;
+       fname = NULL;
+       oflags = O_CREAT | O_RDWR;
+       sflag = 0;
+       while ((ch = getopt(argc, argv, "f:i:lo:s")) != EOF)
+               switch (ch) {
+               case 'f':
+                       fname = optarg;
+                       break;
+               case 'i':
+                       infoarg = optarg;
+                       break;
+               case 'l':
+                       oflags |= DB_LOCK;
+                       break;
+               case 'o':
+                       if ((ofd = open(optarg,
+                           O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
+                               err("%s: %s", optarg, strerror(errno));
+                       break;
+               case 's':
+                       sflag = 1;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 2)
+               usage();
+
+       /* Set the type. */
+       type = dbtype(*argv++);
+
+       /* Open the descriptor file. */
+        if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL)
+           err("%s: %s", *argv, strerror(errno));
+
+       /* Set up the db structure as necessary. */
+       if (infoarg == NULL)
+               infop = NULL;
+       else
+               for (p = strtok(infoarg, ",\t "); p != NULL;
+                   p = strtok(0, ",\t "))
+                       if (*p != '\0')
+                               infop = setinfo(type, p);
+
+       /*
+        * Open the DB.  Delete any preexisting copy, you almost never
+        * want it around, and it often screws up tests.
+        */
+       if (fname == NULL) {
+               p = getenv("TMPDIR");
+               if (p == NULL)
+                       p = "/var/tmp";
+               (void)sprintf(buf, "%s/__dbtest", p);
+               fname = buf;
+               (void)unlink(buf);
+       } else  if (!sflag)
+               (void)unlink(fname);
+
+#ifdef MIT_notdef
+       if ((dbp = dbopen(fname,
+           oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL)
+               err("dbopen: %s", strerror(errno));
+#else  /* MIT_notdef */
+       if ((dbp = __hash_open(fname,
+           oflags, S_IRUSR | S_IWUSR, infop, type)) == NULL)
+               err("dbopen: %s", strerror(errno));
+#endif /* MIT_notdef */
+       XXdbp = dbp;
+
+       state = COMMAND;
+       for (lineno = 1;
+           (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) {
+               /* Delete the newline, displaying the key/data is easier. */
+               if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL)
+                       *t = '\0';
+               if ((len = strlen(buf)) == 0 || isspace(*p) || *p == '#')
+                       continue;
+
+               /* Convenient gdb break point. */
+               if (XXlineno == lineno)
+                       XXlineno = 1;
+               switch (*p) {
+               case 'c':                       /* compare */
+                       if (state != COMMAND)
+                               err("line %lu: not expecting command", lineno);
+                       state = KEY;
+                       command = COMPARE;
+                       break;
+               case 'e':                       /* echo */
+                       if (state != COMMAND)
+                               err("line %lu: not expecting command", lineno);
+                       /* Don't display the newline, if CR at EOL. */
+                       if (p[len - 2] == '\r')
+                               --len;
+                       if (write(ofd, p + 1, len - 1) != len - 1 ||
+                           write(ofd, "\n", 1) != 1)
+                               err("write: %s", strerror(errno));
+                       break;
+               case 'g':                       /* get */
+                       if (state != COMMAND)
+                               err("line %lu: not expecting command", lineno);
+                       state = KEY;
+                       command = GET;
+                       break;
+               case 'p':                       /* put */
+                       if (state != COMMAND)
+                               err("line %lu: not expecting command", lineno);
+                       state = KEY;
+                       command = PUT;
+                       break;
+               case 'r':                       /* remove */
+                       if (state != COMMAND)
+                               err("line %lu: not expecting command", lineno);
+                        if (flags == R_CURSOR) {
+                               rem(dbp, &key);
+                               state = COMMAND;
+                        } else {
+                               state = KEY;
+                               command = REMOVE;
+                       }
+                       break;
+               case 'S':                       /* sync */
+                       if (state != COMMAND)
+                               err("line %lu: not expecting command", lineno);
+                       synk(dbp);
+                       state = COMMAND;
+                       break;
+               case 's':                       /* seq */
+                       if (state != COMMAND)
+                               err("line %lu: not expecting command", lineno);
+                       if (flags == R_CURSOR) {
+                               state = KEY;
+                               command = SEQ;
+                       } else
+                               seq(dbp, &key);
+                       break;
+               case 'f':
+                       flags = setflags(p + 1);
+                       break;
+               case 'D':                       /* data file */
+                       if (state != DATA)
+                               err("line %lu: not expecting data", lineno);
+                       data.data = rfile(p + 1, &data.size);
+                       goto ldata;
+               case 'd':                       /* data */
+                       if (state != DATA)
+                               err("line %lu: not expecting data", lineno);
+                       data.data = xmalloc(p + 1, len - 1);
+                       data.size = len - 1;
+ldata:                 switch (command) {
+                       case COMPARE:
+                               compare(&keydata, &data);
+                               break;
+                       case PUT:
+                               put(dbp, &key, &data);
+                               break;
+                       default:
+                               err("line %lu: command doesn't take data",
+                                   lineno);
+                       }
+                       if (type != DB_RECNO)
+                               free(key.data);
+                       free(data.data);
+                       state = COMMAND;
+                       break;
+               case 'K':                       /* key file */
+                       if (state != KEY)
+                               err("line %lu: not expecting a key", lineno);
+                       if (type == DB_RECNO)
+                               err("line %lu: 'K' not available for recno",
+                                   lineno);
+                       key.data = rfile(p + 1, &key.size);
+                       goto lkey;
+               case 'k':                       /* key */
+                       if (state != KEY)
+                               err("line %lu: not expecting a key", lineno);
+                       if (type == DB_RECNO) {
+                               static recno_t recno;
+                               recno = atoi(p + 1);
+                               key.data = &recno;
+                               key.size = sizeof(recno);
+                       } else {
+                               key.data = xmalloc(p + 1, len - 1);
+                               key.size = len - 1;
+                       }
+lkey:                  switch (command) {
+                       case COMPARE:
+                               getdata(dbp, &key, &keydata);
+                               state = DATA;
+                               break;
+                       case GET:
+                               get(dbp, &key);
+                               if (type != DB_RECNO)
+                                       free(key.data);
+                               state = COMMAND;
+                               break;
+                       case PUT:
+                               state = DATA;
+                               break;
+                       case REMOVE:
+                               rem(dbp, &key);
+                               if ((type != DB_RECNO) && (flags != R_CURSOR))
+                                       free(key.data);
+                               state = COMMAND;
+                               break;
+                       case SEQ:
+                               seq(dbp, &key);
+                               if ((type != DB_RECNO) && (flags != R_CURSOR))
+                                       free(key.data);
+                               state = COMMAND;
+                               break;
+                       default:
+                               err("line %lu: command doesn't take a key",
+                                   lineno);
+                       }
+                       break;
+               case 'o':
+                       dump(dbp, p[1] == 'r');
+                       break;
+               default:
+                       err("line %lu: %s: unknown command character",
+                           lineno, p);
+               }
+       }
+#ifdef STATISTICS
+       /*
+        * -l must be used (DB_LOCK must be set) for this to be
+        * used, otherwise a page will be locked and it will fail.
+        */
+       if (type == DB_BTREE && oflags & DB_LOCK)
+               __bt_stat(dbp);
+#endif
+       if (dbp->close(dbp))
+               err("db->close: %s", strerror(errno));
+       (void)close(ofd);
+       exit(0);
+}
+
+#define        NOOVERWRITE     "put failed, would overwrite key\n"
+
+void
+compare(db1, db2)
+       DBT *db1, *db2;
+{
+       register size_t len;
+       register u_char *p1, *p2;
+
+       if (db1->size != db2->size)
+               printf("compare failed: key->data len %lu != data len %lu\n",
+                   db1->size, db2->size);
+
+       len = MIN(db1->size, db2->size);
+       for (p1 = db1->data, p2 = db2->data; len--;)
+               if (*p1++ != *p2++) {
+                       printf("compare failed at offset %d\n",
+                           p1 - (u_char *)db1->data);
+                       break;
+               }
+}
+
+void
+get(dbp, kp)
+       DB *dbp;
+       DBT *kp;
+{
+       DBT data;
+
+       switch (dbp->get(dbp, kp, &data, flags)) {
+       case 0:
+               (void)write(ofd, data.data, data.size);
+               if (ofd == STDOUT_FILENO)
+                       (void)write(ofd, "\n", 1);
+               break;
+       case -1:
+               err("line %lu: get: %s", lineno, strerror(errno));
+               /* NOTREACHED */
+       case 1:
+#define        NOSUCHKEY       "get failed, no such key\n"
+               if (ofd != STDOUT_FILENO)
+                       (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+               else
+                       (void)fprintf(stderr, "%d: %.*s: %s",
+                           lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+#undef NOSUCHKEY
+               break;
+       }
+}
+
+void
+getdata(dbp, kp, dp)
+       DB *dbp;
+       DBT *kp, *dp;
+{
+       switch (dbp->get(dbp, kp, dp, flags)) {
+       case 0:
+               return;
+       case -1:
+               err("line %lu: getdata: %s", lineno, strerror(errno));
+               /* NOTREACHED */
+       case 1:
+               err("line %lu: getdata failed, no such key", lineno);
+               /* NOTREACHED */
+       }
+}
+
+void
+put(dbp, kp, dp)
+       DB *dbp;
+       DBT *kp, *dp;
+{
+       switch (dbp->put(dbp, kp, dp, flags)) {
+       case 0:
+               break;
+       case -1:
+               err("line %lu: put: %s", lineno, strerror(errno));
+               /* NOTREACHED */
+       case 1:
+               (void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1);
+               break;
+       }
+}
+
+void
+rem(dbp, kp)
+       DB *dbp;
+       DBT *kp;
+{
+       switch (dbp->del(dbp, kp, flags)) {
+       case 0:
+               break;
+       case -1:
+               err("line %lu: rem: %s", lineno, strerror(errno));
+               /* NOTREACHED */
+       case 1:
+#define        NOSUCHKEY       "rem failed, no such key\n"
+               if (ofd != STDOUT_FILENO)
+                       (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+               else if (flags != R_CURSOR)
+                       (void)fprintf(stderr, "%d: %.*s: %s", 
+                           lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+               else
+                       (void)fprintf(stderr,
+                           "%d: rem of cursor failed\n", lineno);
+#undef NOSUCHKEY
+               break;
+       }
+}
+
+void
+synk(dbp)
+       DB *dbp;
+{
+       switch (dbp->sync(dbp, flags)) {
+       case 0:
+               break;
+       case -1:
+               err("line %lu: synk: %s", lineno, strerror(errno));
+               /* NOTREACHED */
+       }
+}
+
+void
+seq(dbp, kp)
+       DB *dbp;
+       DBT *kp;
+{
+       DBT data;
+
+       switch (dbp->seq(dbp, kp, &data, flags)) {
+       case 0:
+               (void)write(ofd, data.data, data.size);
+               if (ofd == STDOUT_FILENO)
+                       (void)write(ofd, "\n", 1);
+               break;
+       case -1:
+               err("line %lu: seq: %s", lineno, strerror(errno));
+               /* NOTREACHED */
+       case 1:
+#define        NOSUCHKEY       "seq failed, no such key\n"
+               if (ofd != STDOUT_FILENO)
+                       (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+               else if (flags == R_CURSOR)
+                       (void)fprintf(stderr, "%d: %.*s: %s", 
+                           lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+               else
+                       (void)fprintf(stderr,
+                           "%d: seq (%s) failed\n", lineno, sflags(flags));
+#undef NOSUCHKEY
+               break;
+       }
+}
+
+void
+dump(dbp, rev)
+       DB *dbp;
+       int rev;
+{
+       DBT key, data;
+       int flags, nflags;
+
+       if (rev) {
+               flags = R_LAST;
+               nflags = R_PREV;
+       } else {
+               flags = R_FIRST;
+               nflags = R_NEXT;
+       }
+       for (;; flags = nflags)
+               switch (dbp->seq(dbp, &key, &data, flags)) {
+               case 0:
+                       (void)write(ofd, data.data, data.size);
+                       if (ofd == STDOUT_FILENO)
+                               (void)write(ofd, "\n", 1);
+                       break;
+               case 1:
+                       goto done;
+               case -1:
+                       err("line %lu: (dump) seq: %s",
+                           lineno, strerror(errno));
+                       /* NOTREACHED */
+               }
+done:  return;
+}
+       
+u_int
+setflags(s)
+       char *s;
+{
+       char *p, *index();
+
+       for (; isspace(*s); ++s);
+       if (*s == '\n' || *s == '\0')
+               return (0);
+       if ((p = index(s, '\n')) != NULL)
+               *p = '\0';
+       if (!strcmp(s, "R_CURSOR"))             return (R_CURSOR);
+       if (!strcmp(s, "R_FIRST"))              return (R_FIRST);
+       if (!strcmp(s, "R_IAFTER"))             return (R_IAFTER);
+       if (!strcmp(s, "R_IBEFORE"))            return (R_IBEFORE);
+       if (!strcmp(s, "R_LAST"))               return (R_LAST);
+       if (!strcmp(s, "R_NEXT"))               return (R_NEXT);
+       if (!strcmp(s, "R_NOOVERWRITE"))        return (R_NOOVERWRITE);
+       if (!strcmp(s, "R_PREV"))               return (R_PREV);
+       if (!strcmp(s, "R_SETCURSOR"))          return (R_SETCURSOR);
+
+       err("line %lu: %s: unknown flag", lineno, s);
+       /* NOTREACHED */
+}
+
+char *
+sflags(flags)
+       int flags;
+{
+       switch (flags) {
+       case R_CURSOR:          return ("R_CURSOR");
+       case R_FIRST:           return ("R_FIRST");
+       case R_IAFTER:          return ("R_IAFTER");
+       case R_IBEFORE:         return ("R_IBEFORE");
+       case R_LAST:            return ("R_LAST");
+       case R_NEXT:            return ("R_NEXT");
+       case R_NOOVERWRITE:     return ("R_NOOVERWRITE");
+       case R_PREV:            return ("R_PREV");
+       case R_SETCURSOR:       return ("R_SETCURSOR");
+       }
+
+       return ("UNKNOWN!");
+}
+       
+DBTYPE
+dbtype(s)
+       char *s;
+{
+       if (!strcmp(s, "btree"))
+               return (DB_BTREE);
+       if (!strcmp(s, "hash"))
+               return (DB_HASH);
+       if (!strcmp(s, "recno"))
+               return (DB_RECNO);
+       err("%s: unknown type (use btree, hash or recno)", s);
+       /* NOTREACHED */
+}
+
+void *
+setinfo(type, s)
+       DBTYPE type;
+       char *s;
+{
+       static BTREEINFO ib;
+       static HASHINFO ih;
+       static RECNOINFO rh;
+       char *eq, *index();
+
+       if ((eq = index(s, '=')) == NULL)
+               err("%s: illegal structure set statement", s);
+       *eq++ = '\0';
+       if (!isdigit(*eq))
+               err("%s: structure set statement must be a number", s);
+               
+       switch (type) {
+       case DB_BTREE:
+               if (!strcmp("flags", s)) {
+                       ib.flags = atoi(eq);
+                       return (&ib);
+               }
+               if (!strcmp("cachesize", s)) {
+                       ib.cachesize = atoi(eq);
+                       return (&ib);
+               }
+               if (!strcmp("maxkeypage", s)) {
+                       ib.maxkeypage = atoi(eq);
+                       return (&ib);
+               }
+               if (!strcmp("minkeypage", s)) {
+                       ib.minkeypage = atoi(eq);
+                       return (&ib);
+               }
+               if (!strcmp("lorder", s)) {
+                       ib.lorder = atoi(eq);
+                       return (&ib);
+               }
+               if (!strcmp("psize", s)) {
+                       ib.psize = atoi(eq);
+                       return (&ib);
+               }
+               break;
+       case DB_HASH:
+               if (!strcmp("bsize", s)) {
+                       ih.bsize = atoi(eq);
+                       return (&ih);
+               }
+               if (!strcmp("ffactor", s)) {
+                       ih.ffactor = atoi(eq);
+                       return (&ih);
+               }
+               if (!strcmp("nelem", s)) {
+                       ih.nelem = atoi(eq);
+                       return (&ih);
+               }
+               if (!strcmp("cachesize", s)) {
+                       ih.cachesize = atoi(eq);
+                       return (&ih);
+               }
+               if (!strcmp("lorder", s)) {
+                       ih.lorder = atoi(eq);
+                       return (&ih);
+               }
+               break;
+       case DB_RECNO:
+               if (!strcmp("flags", s)) {
+                       rh.flags = atoi(eq);
+                       return (&rh);
+               }
+               if (!strcmp("cachesize", s)) {
+                       rh.cachesize = atoi(eq);
+                       return (&rh);
+               }
+               if (!strcmp("lorder", s)) {
+                       rh.lorder = atoi(eq);
+                       return (&rh);
+               }
+               if (!strcmp("reclen", s)) {
+                       rh.reclen = atoi(eq);
+                       return (&rh);
+               }
+               if (!strcmp("bval", s)) {
+                       rh.bval = atoi(eq);
+                       return (&rh);
+               }
+               if (!strcmp("psize", s)) {
+                       rh.psize = atoi(eq);
+                       return (&rh);
+               }
+               break;
+       }
+       err("%s: unknown structure value", s);
+       /* NOTREACHED */
+}
+
+void *
+rfile(name, lenp)
+       char *name;
+       size_t *lenp;
+{
+       struct stat sb;
+       void *p;
+       int fd;
+       char *np, *index();
+
+       for (; isspace(*name); ++name);
+       if ((np = index(name, '\n')) != NULL)
+               *np = '\0';
+       if ((fd = open(name, O_RDONLY, 0)) < 0 ||
+           fstat(fd, &sb))
+               err("%s: %s\n", name, strerror(errno));
+#ifdef NOT_PORTABLE
+       if (sb.st_size > (off_t)SIZE_T_MAX)
+               err("%s: %s\n", name, strerror(E2BIG));
+#endif
+       if ((p = (void *)malloc((u_int)sb.st_size)) == NULL)
+               err("%s", strerror(errno));
+       (void)read(fd, p, (int)sb.st_size);
+       *lenp = sb.st_size;
+       (void)close(fd);
+       return (p);
+}
+
+void *
+xmalloc(text, len)
+       char *text;
+       size_t len;
+{
+       void *p;
+
+       if ((p = (void *)malloc(len)) == NULL)
+               err("%s", strerror(errno));
+       memmove(p, text, len);
+       return (p);
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr,
+           "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n");
+       exit(1);
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+       char *fmt;
+        va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)fprintf(stderr, "dbtest: ");
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       (void)fprintf(stderr, "\n");
+       exit(1);
+       /* NOTREACHED */
+}
diff --git a/src/util/berk_db/test/hash.tests/.Sanitize b/src/util/berk_db/test/hash.tests/.Sanitize
new file mode 100644 (file)
index 0000000..197f68c
--- /dev/null
@@ -0,0 +1,40 @@
+# Sanitize.in for Kerberos V5
+
+# Each directory to survive it's way into a release will need a file
+# like this one called "./.Sanitize".  All keyword lines must exist,
+# and must exist in the order specified by this file.  Each directory
+# in the tree will be processed, top down, in the following order.
+
+# Hash started lines like this one are comments and will be deleted
+# before anything else is done.  Blank lines will also be squashed
+# out.
+
+# The lines between the "Do-first:" line and the "Things-to-keep:"
+# line are executed as a /bin/sh shell script before anything else is
+# done in this 
+
+Do-first:
+
+# All files listed between the "Things-to-keep:" line and the
+# "Files-to-sed:" line will be kept.  All other files will be removed.
+# Directories listed in this section will have their own Sanitize
+# called.  Directories not listed will be removed in their entirety
+# with rm -rf.
+
+Things-to-keep:
+
+driver2.c
+makedb.sh
+tcreat3.c
+tdel.c
+testit
+thash4.c
+tread2.c
+tseq.c
+tverify.c
+
+Things-to-lose:
+
+Do-last:
+
+# End of file.
diff --git a/src/util/berk_db/test/hash.tests/driver2.c b/src/util/berk_db/test/hash.tests/driver2.c
new file mode 100644 (file)
index 0000000..2008a28
--- /dev/null
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)driver2.c  8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+/*
+ * Test driver, to try to tackle the large ugly-split problem.
+ */
+
+#include <sys/file.h>
+#include <stdio.h>
+#include "ndbm.h"
+
+int my_hash(key, len)
+       char    *key;
+       int     len;
+{
+       return(17);             /* So I'm cruel... */
+}
+
+main(argc, argv)
+       int     argc;
+{
+       DB      *db;
+       DBT     key, content;
+       char    keybuf[2049];
+       char    contentbuf[2049];
+       char    buf[256];
+       int     i;
+       HASHINFO        info;
+
+       info.bsize = 1024;
+       info.ffactor = 5;
+       info.nelem = 1;
+       info.cachesize = NULL;
+#ifdef HASH_ID_PROGRAM_SPECIFIED
+       info.hash_id = HASH_ID_PROGRAM_SPECIFIED;
+       info.hash_func = my_hash;
+#else
+       info.hash = my_hash;
+#endif
+       info.lorder = 0;
+       if (!(db = dbopen("bigtest", O_RDWR | O_CREAT, 0644, DB_HASH, &info))) {
+               sprintf(buf, "dbopen: failed on file bigtest");
+               perror(buf);
+               exit(1);
+       }
+       srandom(17);
+       key.data = keybuf;
+       content.data = contentbuf;
+       bzero(keybuf, sizeof(keybuf));
+       bzero(contentbuf, sizeof(contentbuf));
+       for (i=1; i <= 500; i++) {
+               key.size = 128 + (random()&1023);
+               content.size = 128 + (random()&1023);
+/*             printf("%d: Key size %d, data size %d\n", i, key.size,
+                      content.size); */
+               sprintf(keybuf, "Key #%d", i);
+               sprintf(contentbuf, "Contents #%d", i);
+               if ((db->put)(db, &key, &content, R_NOOVERWRITE)) {
+                       sprintf(buf, "dbm_store #%d", i);
+                       perror(buf);
+               }
+       }
+       if ((db->close)(db)) {
+               perror("closing hash file");
+               exit(1);
+       }
+       exit(0);
+}
+
+       
+
diff --git a/src/util/berk_db/test/hash.tests/makedb.sh b/src/util/berk_db/test/hash.tests/makedb.sh
new file mode 100644 (file)
index 0000000..f28e281
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+#      @(#)makedb.sh   8.1 (Berkeley) 6/4/93
+
+awk '{i++; print $0; print i;}' /usr/share/dict/words > WORDS
+ls /bin /usr/bin /usr/ucb /etc | egrep '^(...|....|.....|......)$' | \
+sort | uniq | \
+awk '{
+       printf "%s\n", $0
+       for (i = 0; i < 1000; i++)
+               printf "%s+", $0
+       printf "\n"
+}' > LONG.DATA
diff --git a/src/util/berk_db/test/hash.tests/tcreat3.c b/src/util/berk_db/test/hash.tests/tcreat3.c
new file mode 100644 (file)
index 0000000..bd125ac
--- /dev/null
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tcreat3.c  8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL        25000
+#define MAXWORDS    25000             /* # of elements in search table */
+
+char   wp1[8192];
+char   wp2[8192];
+main(argc, argv)
+char **argv;
+{
+       DBT item, key;
+       DB      *dbp;
+       HASHINFO ctl;
+       FILE *fp;
+       int     trash;
+
+       int i = 0;
+
+       argv++;
+       ctl.hash = NULL;
+       ctl.bsize = atoi(*argv++);
+       ctl.ffactor = atoi(*argv++);
+       ctl.nelem = atoi(*argv++);
+       ctl.lorder = 0;
+       if (!(dbp = dbopen( "hashtest",
+           O_CREAT|O_TRUNC|O_RDWR, 0600, DB_HASH, &ctl))){
+               /* create table */
+               fprintf(stderr, "cannot create: hash table (size %d)\n",
+                       INITIAL);
+               exit(1);
+       }
+
+       key.data = wp1;
+       item.data = wp2;
+       while ( fgets(wp1, 8192, stdin) &&
+               fgets(wp2, 8192, stdin) &&
+               i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+               key.size = strlen(wp1);
+               item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+               if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+                       fprintf(stderr, "cannot enter: key %s\n",
+                               item.data);
+                       exit(1);
+               }                       
+       }
+
+       (dbp->close)(dbp);
+       exit(0);
+}
diff --git a/src/util/berk_db/test/hash.tests/tdel.c b/src/util/berk_db/test/hash.tests/tdel.c
new file mode 100644 (file)
index 0000000..ed3f90a
--- /dev/null
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tdel.c     8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <db.h>
+#include <stdio.h>
+
+#define INITIAL        25000
+#define MAXWORDS    25000             /* # of elements in search table */
+
+/* Usage: thash pagesize fillfactor file */
+char   wp1[8192];
+char   wp2[8192];
+main(argc, argv)
+char **argv;
+{
+       DBT item, key;
+       DB      *dbp;
+       HASHINFO ctl;
+       FILE *fp;
+       int     stat;
+
+       int i = 0;
+
+       argv++;
+       ctl.nelem = INITIAL;
+       ctl.hash = NULL;
+       ctl.bsize = atoi(*argv++);
+       ctl.ffactor = atoi(*argv++);
+       ctl.cachesize = 1024 * 1024;    /* 1 MEG */
+       ctl.lorder = 0;
+       argc -= 2;
+       if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR, 0400, DB_HASH, &ctl))) {
+               /* create table */
+               fprintf(stderr, "cannot create: hash table size %d)\n",
+                       INITIAL);
+               exit(1);
+       }
+
+       key.data = wp1;
+       item.data = wp2;
+       while ( fgets(wp1, 8192, stdin) &&
+               fgets(wp2, 8192, stdin) &&
+               i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+               key.size = strlen(wp1);
+               item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+               if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+                       fprintf(stderr, "cannot enter: key %s\n",
+                               item.data);
+                       exit(1);
+               }                       
+       }
+
+       if ( --argc ) {
+               fp = fopen ( argv[0], "r");
+               i = 0;
+               while ( fgets(wp1, 8192, fp) &&
+                       fgets(wp2, 8192, fp) &&
+                       i++ < MAXWORDS) {
+                   key.size = strlen(wp1);
+                   stat = (dbp->del)(dbp, &key, 0);
+                   if (stat) {
+                       fprintf ( stderr, "Error retrieving %s\n", key.data );
+                       exit(1);
+                   } 
+               }
+               fclose(fp);
+       }
+       (dbp->close)(dbp);
+       exit(0);
+}
diff --git a/src/util/berk_db/test/hash.tests/testit b/src/util/berk_db/test/hash.tests/testit
new file mode 100644 (file)
index 0000000..039457a
--- /dev/null
@@ -0,0 +1,147 @@
+#!/bin/csh -f
+#
+#      @(#)testit      8.1 (Berkeley) 6/4/93
+#
+
+echo ""
+echo "PAGE FILL "
+set name=WORDS
+       set i = 256
+       foreach j ( 11 14 21 )
+           thash4 $i $j 25000 65536 $name < $name
+       end
+       set i = 512
+       foreach j ( 21 28 43 )
+           thash4 $i $j 25000 65536  $name < $name
+       end
+       set i = 1024
+       foreach j ( 43 57 85 )
+           thash4 $i $j 25000 65536 $name < $name
+       end
+       set i = 2048
+       foreach j ( 85 114 171 )
+           thash4 $i $j 25000 65536 $name < $name
+       end
+       set i = 4096
+       foreach j ( 171 228 341 )
+           thash4 $i $j 25000 65536 $name < $name
+       end
+       set i = 8192
+       foreach j ( 341 455 683 )
+           thash4 $i $j 25000 65536 $name < $name
+       end
+       echo "PAGE FILL "
+       set i = 256
+       foreach j ( 11 14 21 )
+           echo "$i"_"$j"
+           tcreat3 $i $j 25000 $name < $name
+           tread2 65536 < $name
+           tverify $name < $name
+           tseq > /dev/null
+           tdel $i $j  $name < $name
+       end
+       set i = 512
+       foreach j ( 21 28 43 )
+           echo "$i"_"$j"
+           tcreat3 $i $j 25000 $name < $name
+           tread2 65536 < $name
+           tverify $name < $name
+           tseq > /dev/null
+           tdel $i $j  $name < $name
+       end
+       set i = 1024
+       foreach j ( 43 57 85 )
+           echo "$i"_"$j"
+           tcreat3 $i $j 25000 $name < $name
+           tread2 65536 < $name
+           tverify $name < $name
+           tseq > /dev/null
+           tdel $i $j  $name < $name
+       end
+       set i = 2048
+       foreach j ( 85 114 171 )
+           echo "$i"_"$j"
+           tcreat3 $i $j 25000 $name < $name
+           tread2 65536 < $name
+           tverify $name < $name
+           tseq > /dev/null
+           tdel $i $j  $name < $name
+       end
+       set i = 4096
+       foreach j ( 171 228 341 )
+           echo "$i"_"$j"
+           tcreat3 $i $j 25000 $name < $name
+           tread2 65536 < $name
+           tverify $name < $name
+           tseq > /dev/null
+           tdel $i $j  $name < $name
+       end
+       set i = 8192
+       foreach j ( 341 455 683 )
+           echo "$i"_"$j"
+           tcreat3 $i $j 25000 $name < $name
+           tread2 65536 < $name
+           tverify $name < $name
+           tseq > /dev/null
+           tdel $i $j  $name < $name
+       end
+set name=LONG.DATA
+       set i = 1024
+       foreach j ( 1 2 4 )
+           echo thash4 $i $j 600 65536 $name 
+           thash4 $i $j 600 65536 $name < $name
+       end
+
+       set i = 2048
+       foreach j ( 1 2 4 )
+           echo thash4 $i $j 600 65536 $name 
+           thash4 $i $j 600 65536 $name < $name
+       end
+       set i = 4096
+       foreach j ( 1 2 4 )
+           echo thash4 $i $j 600 65536 $name 
+           thash4 $i $j 600 65536 $name < $name
+       end
+       set i = 8192
+       foreach j ( 2 4 8 )
+           echo thash4 $i $j 600 65536 $name 
+           thash4 $i $j 600 65536 $name < $name
+       end
+       echo "PAGE FILL "
+       set i = 1024
+       foreach j ( 1 2 4 )
+           echo "$i"_"$j"
+           tcreat3 $i $j 600 $name < $name
+           tread2 65536 < $name
+           tverify $name < $name
+           tseq > /dev/null
+           tdel $i $j  $name < $name
+       end
+       set i = 2048
+       foreach j ( 1 2 4 )
+           echo "$i"_"$j"
+           tcreat3 $i $j 600 $name < $name
+           tread2 65536 < $name
+           tverify $name < $name
+           tseq > /dev/null
+           tdel $i $j  $name < $name
+       end
+       set i = 4096
+       foreach j ( 1 2 4 )
+           echo "$i"_"$j"
+           tcreat3 $i $j 600 $name < $name
+           tread2 65536 < $name
+           tverify $name < $name
+           tseq > /dev/null
+           tdel $i $j  $name < $name
+       end
+       set i = 8192
+       foreach j ( 2 4 8 )
+           echo "$i"_"$j"
+           tcreat3 $i $j 600 $name < $name
+           tread2 65536 < $name
+           tverify $name < $name
+           tseq > /dev/null
+           tdel $i $j  $name < $name
+       end
+driver2
diff --git a/src/util/berk_db/test/hash.tests/thash4.c b/src/util/berk_db/test/hash.tests/thash4.c
new file mode 100644 (file)
index 0000000..9e344cb
--- /dev/null
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)thash4.c   8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/timeb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <db.h>
+
+#define INITIAL        25000
+#define MAXWORDS    25000             /* # of elements in search table */
+
+/* Usage: thash pagesize fillfactor file */
+char   wp1[8192];
+char   wp2[8192];
+main(argc, argv)
+char **argv;
+{
+       DBT item, key, res;
+       DB *dbp;
+       HASHINFO ctl;
+       FILE *fp;
+       int     stat;
+       time_t  t;
+
+       int i = 0;
+
+       argv++;
+       ctl.hash = NULL;
+       ctl.bsize = atoi(*argv++);
+       ctl.ffactor = atoi(*argv++);
+       ctl.nelem = atoi(*argv++);
+       ctl.cachesize = atoi(*argv++);
+       ctl.lorder = 0;
+       if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR, 0400, DB_HASH, &ctl))) {
+               /* create table */
+               fprintf(stderr, "cannot create: hash table size %d)\n",
+                       INITIAL);
+               fprintf(stderr, "\terrno: %d\n", errno);
+               exit(1);
+       }
+
+       key.data = wp1;
+       item.data = wp2;
+       while ( fgets(wp1, 8192, stdin) && 
+               fgets(wp2, 8192, stdin) && 
+               i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+               key.size = strlen(wp1);
+               item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+               if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+                       fprintf(stderr, "cannot enter: key %s\n",
+                               item.data);
+                       fprintf(stderr, "\terrno: %d\n", errno);
+                       exit(1);
+               }                       
+       }
+
+       if ( --argc ) {
+               fp = fopen ( argv[0], "r");
+               i = 0;
+               while ( fgets(wp1, 256, fp) && 
+                       fgets(wp2, 8192, fp) && 
+                       i++ < MAXWORDS) {
+
+                   key.size = strlen(wp1);
+                   stat = (dbp->get)(dbp, &key, &res, 0);
+                   if (stat < 0 ) {
+                       fprintf ( stderr, "Error retrieving %s\n", key.data );
+                       fprintf(stderr, "\terrno: %d\n", errno);
+                       exit(1);
+                   } else if ( stat > 0 ) {
+                       fprintf ( stderr, "%s not found\n", key.data );
+                       fprintf(stderr, "\terrno: %d\n", errno);
+                       exit(1);
+                   }
+               }
+               fclose(fp);
+       }
+       dbp->close(dbp);
+       exit(0);
+}
diff --git a/src/util/berk_db/test/hash.tests/tread2.c b/src/util/berk_db/test/hash.tests/tread2.c
new file mode 100644 (file)
index 0000000..8f01556
--- /dev/null
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tread2.c   8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL        25000
+#define MAXWORDS    25000             /* # of elements in search table */
+
+typedef struct {                      /* info to be stored */
+       int num, siz;
+} info;
+
+char   wp1[8192];
+char   wp2[8192];
+main(argc, argv)
+char **argv;
+{
+       DBT item, key, res;
+       DB      *dbp;
+       HASHINFO ctl;
+       int     stat;
+
+       int i = 0;
+
+       ctl.nelem = INITIAL;
+       ctl.hash = NULL;
+       ctl.bsize = 64;
+       ctl.ffactor = 1;
+       ctl.cachesize = atoi(*argv++);
+       ctl.lorder = 0;
+       if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, &ctl))) {
+               /* create table */
+               fprintf(stderr, "cannot open: hash table\n" );
+               exit(1);
+       }
+
+       key.data = wp1;
+       item.data = wp2;
+       while ( fgets(wp1, 8192, stdin) &&
+               fgets(wp2, 8192, stdin) &&
+               i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+               key.size = strlen(wp1);
+               item.size = strlen(wp2);
+
+               stat = (dbp->get)(dbp, &key, &res,0);
+               if (stat < 0) {
+                   fprintf ( stderr, "Error retrieving %s\n", key.data );
+                   exit(1);
+               } else if ( stat > 0 ) {
+                   fprintf ( stderr, "%s not found\n", key.data );
+                   exit(1);
+               }
+       }
+       (dbp->close)(dbp);
+       exit(0);
+}
diff --git a/src/util/berk_db/test/hash.tests/tseq.c b/src/util/berk_db/test/hash.tests/tseq.c
new file mode 100644 (file)
index 0000000..f45700e
--- /dev/null
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tseq.c     8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL        25000
+#define MAXWORDS    25000             /* # of elements in search table */
+
+
+char   wp[8192];
+char   cp[8192];
+main(argc, argv)
+char **argv;
+{
+       DBT item, key, res;
+       DB      *dbp;
+       FILE *fp;
+       int     stat;
+
+       if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, NULL))) {
+               /* create table */
+               fprintf(stderr, "cannot open: hash table\n" );
+               exit(1);
+       }
+
+/*
+* put info in structure, and structure in the item
+*/
+       for ( stat = (dbp->seq) (dbp, &res, &item, 1 ); 
+             stat == 0;
+             stat = (dbp->seq) (dbp, &res, &item, 0 ) ) {
+
+             bcopy ( res.data, wp, res.size );
+             wp[res.size] = 0;
+             bcopy ( item.data, cp, item.size );
+             cp[item.size] = 0;
+
+             printf ( "%s %s\n", wp, cp );
+       }
+       (dbp->close)(dbp);
+       exit(0);
+}
diff --git a/src/util/berk_db/test/hash.tests/tverify.c b/src/util/berk_db/test/hash.tests/tverify.c
new file mode 100644 (file)
index 0000000..ac5d2f9
--- /dev/null
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)tverify.c  8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL        25000
+#define MAXWORDS    25000             /* # of elements in search table */
+
+typedef struct {                      /* info to be stored */
+       int num, siz;
+} info;
+
+char   wp1[8192];
+char   wp2[8192];
+main(argc, argv)
+char **argv;
+{
+       DBT key, res;
+       DB      *dbp;
+       HASHINFO ctl;
+       int     trash;
+       int     stat;
+
+       int i = 0;
+
+       ctl.nelem = INITIAL;
+       ctl.hash = NULL;
+       ctl.bsize = 64;
+       ctl.ffactor = 1;
+       ctl.cachesize = 1024 * 1024;    /* 1 MEG */
+       ctl.lorder = 0;
+       if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, &ctl))) {
+               /* create table */
+               fprintf(stderr, "cannot open: hash table\n" );
+               exit(1);
+       }
+
+       key.data = wp1;
+       while ( fgets(wp1, 8192, stdin) &&
+               fgets(wp2, 8192, stdin) &&
+               i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+               key.size = strlen(wp1);
+
+               stat = (dbp->get)(dbp, &key, &res,0);
+               if (stat < 0) {
+                   fprintf ( stderr, "Error retrieving %s\n", key.data );
+                   exit(1);
+               } else if ( stat > 0 ) {
+                   fprintf ( stderr, "%s not found\n", key.data );
+                   exit(1);
+               }
+               if ( memcmp ( res.data, wp2, res.size ) ) {
+                   fprintf ( stderr, "data for %s is incorrect.  Data was %s.  Should have been %s\n", key.data, res.data, wp2 );
+               }
+       }
+       (dbp->close)(dbp);
+       exit(0);
+}
diff --git a/src/util/berk_db/test/run.test b/src/util/berk_db/test/run.test
new file mode 100644 (file)
index 0000000..81ba71e
--- /dev/null
@@ -0,0 +1,705 @@
+#!/bin/sh -
+#
+#      @(#)run.test    8.10 (Berkeley) 7/26/94
+#
+
+# db regression tests
+main()
+{
+
+       PROG=./dbtest
+       TMP1=t1
+       TMP2=t2
+       TMP3=t3
+
+       if [ -f /usr/share/dict/words ]; then
+               DICT=/usr/share/dict/words
+       elif [ -f /usr/dict/words ]; then
+               DICT=/usr/dict/words
+       else
+               echo 'run.test: no dictionary'
+               exit 1
+       fi
+       
+       if [ $# -eq 0 ]; then
+               for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do
+                       test$t
+               done
+       else
+               while [ $# -gt 0 ]
+                       do case "$1" in
+                       test*)
+                               $1;;
+                       [0-9]*)
+                               test$1;;
+                       btree)
+                               for t in 1 2 3 7 8 9 10 12 13; do
+                                       test$t
+                               done;;
+                       hash)
+                               for t in 1 2 3 8 13 20; do
+                                       test$t
+                               done;;
+                       recno)
+                               for t in 1 2 3 4 5 6 7 10 11; do
+                                       test$t
+                               done;;
+                       *)
+                               echo "run.test: unknown test $1"
+                               echo "usage: run.test test# | type"
+                               exit 1
+                       esac
+                       shift
+               done
+       fi
+       rm -f $TMP1 $TMP2 $TMP3
+       exit 0
+}
+
+# Take the first hundred entries in the dictionary, and make them
+# be key/data pairs.
+test1()
+{
+       echo "Test 1: btree, hash: small key, small data pairs"
+       sed 200q $DICT > $TMP1
+       for type in btree hash; do
+               rm -f $TMP2 $TMP3
+               for i in `sed 200q $DICT`; do
+                       echo p
+                       echo k$i
+                       echo d$i
+                       echo g
+                       echo k$i
+               done > $TMP2
+               $PROG -o $TMP3 $type $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test1: type $type: failed"
+                       exit 1
+               fi
+       done
+       echo "Test 1: recno: small key, small data pairs"
+       rm -f $TMP2 $TMP3
+       sed 200q $DICT |
+       awk '{ 
+               ++i;
+               printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
+       }' > $TMP2
+       $PROG -o $TMP3 recno $TMP2
+       if (cmp -s $TMP1 $TMP3) ; then :
+       else
+               echo "test1: type recno: failed"
+               exit 1
+       fi
+}
+
+# Take the first 200 entries in the dictionary, and give them
+# each a medium size data entry.
+test2()
+{
+       echo "Test 2: btree, hash: small key, medium data pairs"
+       mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
+       echo $mdata |
+       awk '{ for (i = 1; i < 201; ++i) print $0 }' > $TMP1
+       for type in hash btree; do
+               rm -f $TMP2 $TMP3
+               for i in `sed 200q $DICT`; do
+                       echo p
+                       echo k$i
+                       echo d$mdata
+                       echo g
+                       echo k$i
+               done > $TMP2
+               $PROG -o $TMP3 $type $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test2: type $type: failed"
+                       exit 1
+               fi
+       done
+       echo "Test 2: recno: small key, medium data pairs"
+       rm -f $TMP2 $TMP3
+       echo $mdata | 
+       awk '{  for (i = 1; i < 201; ++i)
+               printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
+       }' > $TMP2
+       $PROG -o $TMP3 recno $TMP2
+       if (cmp -s $TMP1 $TMP3) ; then :
+       else
+               echo "test2: type recno: failed"
+               exit 1
+       fi
+}
+
+# Insert the programs in /bin with their paths as their keys.
+test3()
+{
+       echo "Test 3: hash: small key, big data pairs"
+       rm -f $TMP1
+       (find /bin -type f -print | xargs cat) > $TMP1
+       for type in hash; do
+               rm -f $TMP2 $TMP3
+               for i in `find /bin -type f -print`; do
+                       echo p
+                       echo k$i
+                       echo D$i
+                       echo g
+                       echo k$i
+               done > $TMP2
+               $PROG -o $TMP3 $type $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test3: $type: failed"
+                       exit 1
+               fi
+       done
+#      echo "Test 3: btree: small key, big data pairs"
+#      for psize in 512 16384 65536; do
+#              echo "    page size $psize"
+#              for type in btree; do
+#                      rm -f $TMP2 $TMP3
+#                      for i in `find /bin -type f -print`; do
+#                              echo p
+#                              echo k$i
+#                              echo D$i
+#                              echo g
+#                              echo k$i
+#                      done > $TMP2
+#                      $PROG -i psize=$psize -o $TMP3 $type $TMP2
+#                      if (cmp -s $TMP1 $TMP3) ; then :
+#                      else
+#                              echo "test3: $type: page size $psize: failed"
+#                              exit 1
+#                      fi
+#              done
+#      done
+#      echo "Test 3: recno: big data pairs"
+#      rm -f $TMP2 $TMP3
+#      find /bin -type f -print | 
+#      awk '{
+#              ++i;
+#              printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i);
+#      }' > $TMP2
+#      for psize in 512 16384 65536; do
+#              echo "    page size $psize"
+#              $PROG -i psize=$psize -o $TMP3 recno $TMP2
+#              if (cmp -s $TMP1 $TMP3) ; then :
+#              else
+#                      echo "test3: recno: page size $psize: failed"
+#                      exit 1
+#              fi
+#      done
+}
+
+# Do random recno entries.
+test4()
+{
+       echo "Test 4: recno: random entries"
+       echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+       awk '{
+               for (i = 37; i <= 37 + 88 * 17; i += 17) {
+                       if (i % 41)
+                               s = substr($0, 1, i % 41);
+                       else
+                               s = substr($0, 1);
+                       printf("input key %d: %s\n", i, s);
+               }
+               for (i = 1; i <= 15; ++i) {
+                       if (i % 41)
+                               s = substr($0, 1, i % 41);
+                       else
+                               s = substr($0, 1);
+                       printf("input key %d: %s\n", i, s);
+               }
+               for (i = 19234; i <= 19234 + 61 * 27; i += 27) {
+                       if (i % 41)
+                               s = substr($0, 1, i % 41);
+                       else
+                               s = substr($0, 1);
+                       printf("input key %d: %s\n", i, s);
+               }
+               exit
+       }' > $TMP1
+       rm -f $TMP2 $TMP3
+       cat $TMP1 |
+       awk 'BEGIN {
+                       i = 37;
+                       incr = 17;
+               }
+               {
+                       printf("p\nk%d\nd%s\n", i, $0);
+                       if (i == 19234 + 61 * 27)
+                               exit;
+                       if (i == 37 + 88 * 17) {
+                               i = 1;
+                               incr = 1;
+                       } else if (i == 15) {
+                               i = 19234;
+                               incr = 27;
+                       } else
+                               i += incr;
+               }
+               END {
+                       for (i = 37; i <= 37 + 88 * 17; i += 17)
+                               printf("g\nk%d\n", i);
+                       for (i = 1; i <= 15; ++i)
+                               printf("g\nk%d\n", i);
+                       for (i = 19234; i <= 19234 + 61 * 27; i += 27)
+                               printf("g\nk%d\n", i);
+               }' > $TMP2
+       $PROG -o $TMP3 recno $TMP2
+       if (cmp -s $TMP1 $TMP3) ; then :
+       else
+               echo "test4: type recno: failed"
+               exit 1
+       fi
+}
+
+# Do reverse order recno entries.
+test5()
+{
+       echo "Test 5: recno: reverse order entries"
+       echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+       awk ' {
+               for (i = 1500; i; --i) {
+                       if (i % 34)
+                               s = substr($0, 1, i % 34);
+                       else
+                               s = substr($0, 1);
+                       printf("input key %d: %s\n", i, s);
+               }
+               exit;
+       }' > $TMP1
+       rm -f $TMP2 $TMP3
+       cat $TMP1 |
+       awk 'BEGIN {
+                       i = 1500;
+               }
+               {
+                       printf("p\nk%d\nd%s\n", i, $0);
+                       --i;
+               }
+               END {
+                       for (i = 1500; i; --i) 
+                               printf("g\nk%d\n", i);
+               }' > $TMP2
+       $PROG -o $TMP3 recno $TMP2
+       if (cmp -s $TMP1 $TMP3) ; then :
+       else
+               echo "test5: type recno: failed"
+               exit 1
+       fi
+}
+               
+# Do alternating order recno entries.
+test6()
+{
+       echo "Test 6: recno: alternating order entries"
+       echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+       awk ' {
+               for (i = 1; i < 1200; i += 2) {
+                       if (i % 34)
+                               s = substr($0, 1, i % 34);
+                       else
+                               s = substr($0, 1);
+                       printf("input key %d: %s\n", i, s);
+               }
+               for (i = 2; i < 1200; i += 2) {
+                       if (i % 34)
+                               s = substr($0, 1, i % 34);
+                       else
+                               s = substr($0, 1);
+                       printf("input key %d: %s\n", i, s);
+               }
+               exit;
+       }' > $TMP1
+       rm -f $TMP2 $TMP3
+       cat $TMP1 |
+       awk 'BEGIN {
+                       i = 1;
+                       even = 0;
+               }
+               {
+                       printf("p\nk%d\nd%s\n", i, $0);
+                       i += 2;
+                       if (i >= 1200) {
+                               if (even == 1)
+                                       exit;
+                               even = 1;
+                               i = 2;
+                       }
+               }
+               END {
+                       for (i = 1; i < 1200; ++i) 
+                               printf("g\nk%d\n", i);
+               }' > $TMP2
+       $PROG -o $TMP3 recno $TMP2
+       sort -o $TMP1 $TMP1
+       sort -o $TMP3 $TMP3
+       if (cmp -s $TMP1 $TMP3) ; then :
+       else
+               echo "test6: type recno: failed"
+               exit 1
+       fi
+}
+
+# Delete cursor record
+test7()
+{
+       echo "Test 7: btree, recno: delete cursor record"
+       echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+       awk '{
+               for (i = 1; i <= 120; ++i)
+                       printf("%05d: input key %d: %s\n", i, i, $0);
+               printf("%05d: input key %d: %s\n", 120, 120, $0);
+               printf("seq failed, no such key\n");
+               printf("%05d: input key %d: %s\n", 1, 1, $0);
+               printf("%05d: input key %d: %s\n", 2, 2, $0);
+               exit;
+       }' > $TMP1
+       rm -f $TMP2 $TMP3
+
+       for type in btree recno; do
+               cat $TMP1 |
+               awk '{
+                       if (i == 120)
+                               exit;
+                       printf("p\nk%d\nd%s\n", ++i, $0);
+               }
+               END {
+                       printf("fR_NEXT\n");
+                       for (i = 1; i <= 120; ++i)
+                               printf("s\n");
+                       printf("fR_CURSOR\ns\nk120\n");
+                       printf("r\n");
+                       printf("fR_NEXT\ns\n");
+                       printf("fR_CURSOR\ns\nk1\n");
+                       printf("r\n");
+                       printf("fR_FIRST\ns\n");
+               }' > $TMP2
+               $PROG -o $TMP3 recno $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test7: type $type: failed"
+                       exit 1
+               fi
+       done
+}
+
+# Make sure that overflow pages are reused.
+test8()
+{
+       echo "Test 8: btree, hash: repeated small key, big data pairs"
+       rm -f $TMP1
+       echo "" | 
+       awk 'BEGIN {
+               for (i = 1; i <= 10; ++i) {
+                       printf("p\nkkey1\nD/bin/sh\n");
+                       printf("p\nkkey2\nD/bin/csh\n");
+                       if (i % 8 == 0) {
+                               printf("c\nkkey2\nD/bin/csh\n");
+                               printf("c\nkkey1\nD/bin/sh\n");
+                               printf("e\t%d of 10 (comparison)\n", i);
+                       } else
+                               printf("e\t%d of 10             \n", i);
+                       printf("r\nkkey1\nr\nkkey2\n");
+               }
+       }' > $TMP1
+       $PROG btree $TMP1
+#      $PROG hash $TMP1
+       # No explicit test for success.
+}
+
+# Test btree duplicate keys
+test9()
+{
+       echo "Test 9: btree: duplicate keys"
+       echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+       awk '{
+               for (i = 1; i <= 543; ++i)
+                       printf("%05d: input key %d: %s\n", i, i, $0);
+               exit;
+       }' > $TMP1
+       rm -f $TMP2 $TMP3
+
+       for type in btree; do
+               cat $TMP1 | 
+               awk '{
+                       if (i++ % 2)
+                               printf("p\nkduplicatekey\nd%s\n", $0);
+                       else
+                               printf("p\nkunique%dkey\nd%s\n", i, $0);
+               }
+               END {
+                               printf("o\n");
+               }' > $TMP2
+               $PROG -iflags=1 -o $TMP3 $type $TMP2
+               sort -o $TMP3 $TMP3
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test9: type $type: failed"
+                       exit 1
+               fi
+       done
+}
+
+# Test use of cursor flags without initialization
+test10()
+{
+       echo "Test 10: btree, recno: test cursor flag use"
+       echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+       awk '{
+               for (i = 1; i <= 20; ++i)
+                       printf("%05d: input key %d: %s\n", i, i, $0);
+               exit;
+       }' > $TMP1
+       rm -f $TMP2 $TMP3
+
+       # Test that R_CURSOR doesn't succeed before cursor initialized
+       for type in btree recno; do
+               cat $TMP1 |
+               awk '{
+                       if (i == 10)
+                               exit;
+                       printf("p\nk%d\nd%s\n", ++i, $0);
+               }
+               END {
+                       printf("fR_CURSOR\nr\n");
+                       printf("eR_CURSOR SHOULD HAVE FAILED\n");
+               }' > $TMP2
+               $PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
+               if [ -s $TMP3 ] ; then
+                       echo "Test 10: delete: R_CURSOR SHOULD HAVE FAILED"
+                       exit 1
+               fi
+       done
+       for type in btree recno; do
+               cat $TMP1 |
+               awk '{
+                       if (i == 10)
+                               exit;
+                       printf("p\nk%d\nd%s\n", ++i, $0);
+               }
+               END {
+                       printf("fR_CURSOR\np\nk1\ndsome data\n");
+                       printf("eR_CURSOR SHOULD HAVE FAILED\n");
+               }' > $TMP2
+               $PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
+               if [ -s $TMP3 ] ; then
+                       echo "Test 10: put: R_CURSOR SHOULD HAVE FAILED"
+                       exit 1
+               fi
+       done
+}
+
+# Test insert in reverse order.
+test11()
+{
+       echo "Test 11: recno: reverse order insert"
+       echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+       awk '{
+               for (i = 1; i <= 779; ++i)
+                       printf("%05d: input key %d: %s\n", i, i, $0);
+               exit;
+       }' > $TMP1
+       rm -f $TMP2 $TMP3
+
+       for type in recno; do
+               cat $TMP1 |
+               awk '{
+                       if (i == 0) {
+                               i = 1;
+                               printf("p\nk1\nd%s\n", $0);
+                               printf("%s\n", "fR_IBEFORE");
+                       } else
+                               printf("p\nk1\nd%s\n", $0);
+               }
+               END {
+                               printf("or\n");
+               }' > $TMP2
+               $PROG -o $TMP3 $type $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test11: type $type: failed"
+                       exit 1
+               fi
+       done
+}
+
+# Take the first 20000 entries in the dictionary, reverse them, and give
+# them each a small size data entry.  Use a small page size to make sure
+# the btree split code gets hammered.
+test12()
+{
+       echo "Test 12: btree: lots of keys, small page size"
+       mdata=abcdefghijklmnopqrstuvwxy
+       echo $mdata |
+       awk '{ for (i = 1; i < 20001; ++i) print $0 }' > $TMP1
+       for type in btree; do
+               rm -f $TMP2 $TMP3
+               for i in `sed 20000q $DICT | rev`; do
+                       echo p
+                       echo k$i
+                       echo d$mdata
+                       echo g
+                       echo k$i
+               done > $TMP2
+               $PROG -i psize=512 -o $TMP3 $type $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test12: type $type: failed"
+                       exit 1
+               fi
+       done
+}
+
+# Test different byte orders.
+test13()
+{
+       echo "Test 13: btree, hash: differing byte orders"
+       sed 50q $DICT > $TMP1
+       for order in 1234 4321; do
+               for type in btree hash; do
+                       rm -f byte.file $TMP2 $TMP3
+                       for i in `sed 50q $DICT`; do
+                               echo p
+                               echo k$i
+                               echo d$i
+                               echo g
+                               echo k$i
+                       done > $TMP2
+                       $PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+                       if (cmp -s $TMP1 $TMP3) ; then :
+                       else
+                               echo "test13: $type/$order put failed"
+                               exit 1
+                       fi
+                       for i in `sed 50q $DICT`; do
+                               echo g
+                               echo k$i
+                       done > $TMP2
+                       $PROG -s \
+                           -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+                       if (cmp -s $TMP1 $TMP3) ; then :
+                       else
+                               echo "test13: $type/$order get failed"
+                               exit 1
+                       fi
+               done
+       done
+       rm -f byte.file
+}
+
+# Try a variety of bucketsizes and fill factors for hashing
+test20()
+{
+       echo\
+    "Test 20: hash: bucketsize, fill factor; nelem 25000 cachesize 65536"
+       echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+       awk '{
+               for (i = 1; i <= 10000; ++i) {
+                       if (i % 34)
+                               s = substr($0, 1, i % 34);
+                       else
+                               s = substr($0, 1);
+                       printf("%s\n", s);
+               }
+               exit;
+       }' > $TMP1
+       sed 10000q $DICT |
+       awk 'BEGIN {
+               ds="abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg"
+       }
+       {
+               if (++i % 34)
+                       s = substr(ds, 1, i % 34);
+               else
+                       s = substr(ds, 1);
+               printf("p\nk%s\nd%s\n", $0, s);
+       }' > $TMP2
+       sed 10000q $DICT |
+       awk '{
+               ++i;
+               printf("g\nk%s\n", $0);
+       }' >> $TMP2
+       bsize=256
+       for ffactor in 11 14 21; do
+               echo "    bucketsize $bsize, fill factor $ffactor"
+               $PROG -o$TMP3 \
+                   -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+                   hash $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+                       exit 1
+               fi
+       done
+       bsize=512
+       for ffactor in 21 28 43; do
+               echo "    bucketsize $bsize, fill factor $ffactor"
+               $PROG -o$TMP3 \
+                   -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+                   hash $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+                       exit 1
+               fi
+       done
+       bsize=1024
+       for ffactor in 43 57 85; do
+               echo "    bucketsize $bsize, fill factor $ffactor"
+               $PROG -o$TMP3 \
+                   -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+                   hash $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+                       exit 1
+               fi
+       done
+       bsize=2048
+       for ffactor in 85 114 171; do
+               echo "    bucketsize $bsize, fill factor $ffactor"
+               $PROG -o$TMP3 \
+                   -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+                   hash $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+                       exit 1
+               fi
+       done
+       bsize=4096
+       for ffactor in 171 228 341; do
+               echo "    bucketsize $bsize, fill factor $ffactor"
+               $PROG -o$TMP3 \
+                   -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+                   hash $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+                       exit 1
+               fi
+       done
+       bsize=8192
+       for ffactor in 341 455 683; do
+               echo "    bucketsize $bsize, fill factor $ffactor"
+               $PROG -o$TMP3 \
+                   -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+                   hash $TMP2
+               if (cmp -s $TMP1 $TMP3) ; then :
+               else
+                       echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+                       exit 1
+               fi
+       done
+}
+
+main $*