Xref: utzoo unix-pc.general:818 comp.sys.att:3485 Path: utzoo!attcan!uunet!lll-winken!lll-tis!ames!ucsd!rutgers!mtunx!att!ihnp4!chinet!randy From: randy@chinet.UUCP (Randy Suess) Newsgroups: unix-pc.general,comp.sys.att Subject: Re: BSD stuff --> libndir and libdbm Message-ID: <5827@chinet.UUCP> Date: 14 Jun 88 12:58:37 GMT Reply-To: randy@chinet.UUCP (Randy Suess) Organization: Chinet - Public Access Unix Lines: 2195 I have been swamped with requests, so figure a posting is in order. This posting and the following contain the mdbm source as posted a while ago and the mods made by Dave Ihnat (ignatz@chinet) to make it look like a 99.9% clone of V7 dbm. Made spacewar and news 2.11 work fine on a 3b2/310 running SysVr3.1. Good luck. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh ./addons/READ.ME <<'END_OF_./addons/READ.ME' XFrom ihnp4!zehntel!hplabs!hao!seismo!umcp-cs!eneevax!chris Sat Aug 18 03:31:41 1984 XRelay-Version: version B 2.10.1 exptools 1/30/84; site ihnp3.UUCP XPosting-Version: version B 2.10.1 6/24/83; site eneevax.UUCP XPath: ihnp3!ihnp4!zehntel!hplabs!hao!seismo!umcp-cs!eneevax!chris XFrom: chris@eneevax.UUCP (Chris Torek) XNewsgroups: net.sources XSubject: bcopy, bcmp, bzero for 4.1BSD XMessage-ID: <153@eneevax.UUCP> XDate: Sat, 18-Aug-84 03:31:41 CDT XArticle-I.D.: eneevax.153 XPosted: Sat Aug 18 03:31:41 1984 XDate-Received: Sun, 19-Aug-84 11:19:10 EDT XOrganization: Univ. of Maryland, EE Dept. XLines: 156 X XI've received (justified) complaints for not explaining bcmp(), Xbcopy(), and bzero() in my mdbm source posting. This is one of those X4.2 dependencies I warned about. Anyway, here are implementations of Xbcopy, bcmp, and bzero in Vax assembly and in C. WARNING: I haven't Xtested the Vax assembly version of bcmp (nor any of the C routines but Xwho needs to test those?). Also, the assembly routines won't work Xunder VMS, which (I believe) needs r2-r11 saved; you'd have to change Xthe entry masks. X XIf you're running 4.2 you should already have these in your C library, Xso in that case, ignore this posting. (Otherwise, why not rewrite Xthese for your particular machine and *install* it in your C library?) X X--Chris Torek, U of MD CS/EE, seismo!umcp-cs!chris, chris@maryland.ARPA, X chris@umcp-cs.CSNet (I don't have my regular .signature installed on X this machine) X------------------------------------------- END_OF_./addons/READ.ME if test 1514 -ne `wc -c <./addons/READ.ME`; then echo shar: \"./addons/READ.ME\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./addons/bcmp.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./addons/bcmp.c\" else echo shar: Extracting \"./addons/bcmp.c\" \(383 characters\) sed "s/^X//" >./addons/bcmp.c <<'END_OF_./addons/bcmp.c' X/* X * bcmp X * X * compare count bytes at s1 and s2; return 0 iff equal X * X * N.B.: Beware large counts (>32767) on machines with 16 bit `int's. X * (This routine should really be rewritten for those.) X */ Xbcmp (s1, s2, count) Xregister char *s1, *s2; Xregister int count; X{ X while (--count >= 0) X if (*s1++ != *s2++) X return 1; /* or ``return *--s1 - *--s2;'' */ X return 0; X} END_OF_./addons/bcmp.c if test 383 -ne `wc -c <./addons/bcmp.c`; then echo shar: \"./addons/bcmp.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./addons/bcmp.s -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./addons/bcmp.s\" else echo shar: Extracting \"./addons/bcmp.s\" \(518 characters\) sed "s/^X//" >./addons/bcmp.s <<'END_OF_./addons/bcmp.s' X# bcmp (s1, s2, count) char *s1, *s2; int count; X# X# Compare "count" bytes at "s1" with those at "s2"; return 0 iff equal X X .align 2 X .globl _bcopy X_bcopy: X .word 0 X movl 4(ap),r1 # r1 = s1 X movl 8(ap),r3 # r3 = s2 X brb 2f X1: X subl2 r0,12(ap) # count-=65535 (bytes compared) X cmpc3 r0,(r1),(r3) # r1, r3 magically point to next 65K X bneq 3f X2: X movzwl $65535,r0 X cmpl 12(ap),r0 # <= 65535 bytes to compare? X jgtr 1b # brif not, do 65535 and try again X cmpc3 12(ap),(r1),(r3) # compare up to 65535 bytes X3: X ret END_OF_./addons/bcmp.s if test 518 -ne `wc -c <./addons/bcmp.s`; then echo shar: \"./addons/bcmp.s\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./addons/bcopy.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./addons/bcopy.c\" else echo shar: Extracting \"./addons/bcopy.c\" \(356 characters\) sed "s/^X//" >./addons/bcopy.c <<'END_OF_./addons/bcopy.c' X/* X * bcopy - copy count bytes from "from" to "to" - not guaranteed to work X * if "from" and "to" overlap X * X * N.B.: Beware large counts (>32767) on machines with 16 bit `int's. X * (This routine should really be rewritten for those.) X */ Xbcopy (from, to, count) Xregister char *from, *to; Xregister int count; X{ X while (--count >= 0) X *to++ = *from++; X} END_OF_./addons/bcopy.c if test 356 -ne `wc -c <./addons/bcopy.c`; then echo shar: \"./addons/bcopy.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./addons/bcopy.s -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./addons/bcopy.s\" else echo shar: Extracting \"./addons/bcopy.s\" \(540 characters\) sed "s/^X//" >./addons/bcopy.s <<'END_OF_./addons/bcopy.s' X# bcopy (from, to, count) char *from, *to; int count; X# X# Copy "count" bytes from "from" to "to"; not guaranteed to X# work if "from" and "to" overlap. X X .align 2 X .globl _bcopy X_bcopy: X .word 0 X movl 4(ap),r1 # r1 = from X movl 8(ap),r3 # r3 = to X brb 2f X1: X subl2 r0,12(ap) # count-=65535 (bytes moved this time) X movc3 r0,(r1),(r3) # r1, r3 magically point to next 65K X2: X movzwl $65535,r0 X cmpl 12(ap),r0 # <= 65535 bytes to move? X jgtr 1b # brif not, move 65535 and try again X movc3 12(ap),(r1),(r3) # move up to 65535 bytes X ret END_OF_./addons/bcopy.s if test 540 -ne `wc -c <./addons/bcopy.s`; then echo shar: \"./addons/bcopy.s\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./addons/bzero.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./addons/bzero.c\" else echo shar: Extracting \"./addons/bzero.c\" \(284 characters\) sed "s/^X//" >./addons/bzero.c <<'END_OF_./addons/bzero.c' X/* X * bzero - zero count bytes at address addr X * X * N.B.: Beware large counts (>32767) on machines with 16 bit `int's. X * (This routine should really be rewritten for those.) X */ Xbzero (addr, count) Xregister char *addr; Xregister int count; X{ X while (--count >= 0) X *addr++ = 0; X} END_OF_./addons/bzero.c if test 284 -ne `wc -c <./addons/bzero.c`; then echo shar: \"./addons/bzero.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./addons/bzero.s -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./addons/bzero.s\" else echo shar: Extracting \"./addons/bzero.s\" \(455 characters\) sed "s/^X//" >./addons/bzero.s <<'END_OF_./addons/bzero.s' X# bzero (addr, count) char *addr; int count; X# X# Zero "count" bytes at address "addr" X X .align 2 X .globl _bzero X_bzero: X .word 0 X movl 4(ap),r3 # r3 = addr X brb 2f X1: X subl2 r0,8(ap) # count-=65535 (bytes zeroed this time) X movc5 $0,(sp),$0,r0,(r3) # r3 magically points to next 65K X2: X movzwl $65535,r0 X cmpl 8(ap),r0 # <= 65535 bytes to zero? X jgtr 1b # brif not, zero 65535 and try again X movc5 $0,(sp),$0,8(ap),(r3) # zero up to 65535 bytes X ret END_OF_./addons/bzero.s if test 455 -ne `wc -c <./addons/bzero.s`; then echo shar: \"./addons/bzero.s\" unpacked with wrong size! fi # end of overwriting check fi if test ! -d ./mdbm ; then echo shar: Creating directory \"./mdbm\" mkdir ./mdbm fi if test ! -d ./mdbm/.archinfo ; then echo shar: Creating directory \"./mdbm/.archinfo\" mkdir ./mdbm/.archinfo fi if test -f ./mdbm/Makefile -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/Makefile\" else echo shar: Extracting \"./mdbm/Makefile\" \(1830 characters\) sed "s/^X//" >./mdbm/Makefile <<'END_OF_./mdbm/Makefile' X# $Header$ X# X# The -R flag compiles initialized data into the text area. Not really X# necessary, but nice. X# (DMI-AiC): Unfortunately, also not on BTL-derived compilers. X# (DMI-AiC): Added dbm compatibility module XCC = ccsh # 3b1 Only! X#CC = cc X X#CFLAGS= -O -R XCFLAGS= -O X XOBJS= access.o checkblock.o close.o compare.o delete.o delitem.o\ X fetch.o firsthash.o firstkey.o hash.o hashinc.o nextkey.o\ X open.o search.o store.o sync.o dbmcompat.o X XSRCS= access.c checkblock.c close.c compare.c delete.c delitem.c\ X fetch.c firsthash.c firstkey.c hash.c hashinc.c nextkey.c\ X open.c search.c store.c sync.c dbmcompat.c X XHDRS= mdbm.h mdbm_local.h X X.c.o: X $(CC) -c $(CFLAGS) $< X @ld -r -x $@ X @mv a.out $@ X Xall: libmdbm.a testdbm dumpdbm X Xlibmdbm.a: $(OBJS) X ar cr libmdbm.a `lorder $(OBJS) | tsort` X# ranlib libmdbm.a X Xinstall: X install -m 444 -o bin -g bin -c libmdbm.a $(DESTDIR)/usr/lib X ln $(DESTDIR)/usr/lib/libmdbm.a $(DESTDIR)/usr/lib/libdbm.a X# ranlib $(DESTDIR)/usr/lib/libmdbm.a X install -m 444 -o bin -g bin -c mdbm.h $(DESTDIR)/include X install -c mdbm.3x $(DESTDIR)/usr/man/man3 X Xtestdbm: testdbm.o libmdbm.a X cc $(CFLAGS) -o testdbm testdbm.o libmdbm.a X Xdumpdbm: dumpdbm.o libmdbm.a X cc $(CFLAGS) -o dumpdbm dumpdbm.o libmdbm.a X Xclean: X rm -f libmdbm.a *.o a.out testdbm dumpdbm core X Xlint: $(SRCS) $(HDRS) X lint -h $(SRCS) | egrep -v 'possible pointer alignment problem' X Xaccess.o: mdbm.h mdbm_local.h Xadditem.o: mdbm.h mdbm_local.h Xcheckblock.o: mdbm.h mdbm_local.h Xclose.o: mdbm.h mdbm_local.h Xdelete.o: mdbm.h mdbm_local.h Xdelitem.o: mdbm.h mdbm_local.h Xfetch.o: mdbm.h mdbm_local.h Xfirsthash.o: mdbm.h mdbm_local.h Xfirstkey.o: mdbm.h mdbm_local.h Xhash.o: mdbm.h mdbm_local.h Xnextkey.o: mdbm.h mdbm_local.h Xopen.o: mdbm.h mdbm_local.h Xsearch.o: mdbm_local.h Xstore.o: mdbm.h mdbm_local.h Xsync.o: mdbm.h mdbm_local.h X X END_OF_./mdbm/Makefile if test 1830 -ne `wc -c <./mdbm/Makefile`; then echo shar: \"./mdbm/Makefile\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/access.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/access.c\" else echo shar: Extracting \"./mdbm/access.c\" \(1210 characters\) sed "s/^X//" >./mdbm/access.c <<'END_OF_./mdbm/access.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/access.c,v 1.1 84/08/12 09:54:48 chris Rel $"; X#endif X X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Read in the appropriate data block for an item whose hash index is X * hash. The hash index specifies the data block in an indirect way: X * if the bit in the map is set then more bits of the hash value should X * be considered. If it is not set then we have the right hash bits X * and the block number is just the low bits of the hash value. X * X * Return the hash mask that gets the right block number. X */ Xint mdbm_access (d, hash) Xregister struct mdbm *d; Xregister long hash; X{ X register long hmask, X b; X X for (hmask = 0;; hmask = (hmask << 1) + 1) { X b = (hash & hmask) + hmask;/* map bit number */ X if (b < d -> mdbm_maxbit) { X register int i, X n; X X n = b % BYTESIZ; /* bit index */ X b /= BYTESIZ; /* byte index */ X i = b % d -> mdbm_msize;/* byte offset in map */ X b /= d -> mdbm_msize;/* map block number */ X MDBM_MREAD (d, b); X if (d -> mdbm_m[i] & (1 << n)) X continue; X } X b = hash & hmask; X MDBM_DREAD (d, b); X return hmask; X } X} END_OF_./mdbm/access.c if test 1210 -ne `wc -c <./mdbm/access.c`; then echo shar: \"./mdbm/access.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/bcmp.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/bcmp.c\" else echo shar: Extracting \"./mdbm/bcmp.c\" \(383 characters\) sed "s/^X//" >./mdbm/bcmp.c <<'END_OF_./mdbm/bcmp.c' X/* X * bcmp X * X * compare count bytes at s1 and s2; return 0 iff equal X * X * N.B.: Beware large counts (>32767) on machines with 16 bit `int's. X * (This routine should really be rewritten for those.) X */ Xbcmp (s1, s2, count) Xregister char *s1, *s2; Xregister int count; X{ X while (--count >= 0) X if (*s1++ != *s2++) X return 1; /* or ``return *--s1 - *--s2;'' */ X return 0; X} END_OF_./mdbm/bcmp.c if test 383 -ne `wc -c <./mdbm/bcmp.c`; then echo shar: \"./mdbm/bcmp.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/bcopy.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/bcopy.c\" else echo shar: Extracting \"./mdbm/bcopy.c\" \(356 characters\) sed "s/^X//" >./mdbm/bcopy.c <<'END_OF_./mdbm/bcopy.c' X/* X * bcopy - copy count bytes from "from" to "to" - not guaranteed to work X * if "from" and "to" overlap X * X * N.B.: Beware large counts (>32767) on machines with 16 bit `int's. X * (This routine should really be rewritten for those.) X */ Xbcopy (from, to, count) Xregister char *from, *to; Xregister int count; X{ X while (--count >= 0) X *to++ = *from++; X} END_OF_./mdbm/bcopy.c if test 356 -ne `wc -c <./mdbm/bcopy.c`; then echo shar: \"./mdbm/bcopy.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/bzero.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/bzero.c\" else echo shar: Extracting \"./mdbm/bzero.c\" \(284 characters\) sed "s/^X//" >./mdbm/bzero.c <<'END_OF_./mdbm/bzero.c' X/* X * bzero - zero count bytes at address addr X * X * N.B.: Beware large counts (>32767) on machines with 16 bit `int's. X * (This routine should really be rewritten for those.) X */ Xbzero (addr, count) Xregister char *addr; Xregister int count; X{ X while (--count >= 0) X *addr++ = 0; X} END_OF_./mdbm/bzero.c if test 284 -ne `wc -c <./mdbm/bzero.c`; then echo shar: \"./mdbm/bzero.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/checkblock.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/checkblock.c\" else echo shar: Extracting \"./mdbm/checkblock.c\" \(724 characters\) sed "s/^X//" >./mdbm/checkblock.c <<'END_OF_./mdbm/checkblock.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/checkblock.c,v 1.1 84/08/12 09:56:16 chris Rel $"; X#endif X X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Perform some sanity checks on a data block X */ Xmdbm_checkblock (buf, size) Xchar *buf; Xint size; X{ X register struct mdbm_dblock *db = (struct mdbm_dblock *) buf; X register struct mdbm_dentry *de; X register int i, X t = size; X X de = &db -> db_e[1]; X for (i = 1; i < db -> db_n; i++) { X if (de -> de_off > t) X goto bad; X t = de -> de_off; X de++; X } X if (&buf[t] < (char *) de) X goto bad; X return; X Xbad: X printf ("mdbm: bad block\n"); X fflush(stdout); X abort (); X bzero (buf, size); X} END_OF_./mdbm/checkblock.c if test 724 -ne `wc -c <./mdbm/checkblock.c`; then echo shar: \"./mdbm/checkblock.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/close.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/close.c\" else echo shar: Extracting \"./mdbm/close.c\" \(454 characters\) sed "s/^X//" >./mdbm/close.c <<'END_OF_./mdbm/close.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/close.c,v 1.1 84/08/12 09:57:45 chris Rel $"; X#endif X X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Close a database X */ Xmdbm_close (d) Xregister struct mdbm *d; X{ X MDBM_SYNC (d); X (void) close (d -> mdbm_datafd); X (void) close (d -> mdbm_mapfd); X free (d -> mdbm_d); X free (d -> mdbm_s); X free (d -> mdbm_m); X free ((char *) d); X return 0; X} END_OF_./mdbm/close.c if test 454 -ne `wc -c <./mdbm/close.c`; then echo shar: \"./mdbm/close.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/compare.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/compare.c\" else echo shar: Extracting \"./mdbm/compare.c\" \(492 characters\) sed "s/^X//" >./mdbm/compare.c <<'END_OF_./mdbm/compare.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/compare.c,v 1.1 84/08/12 09:57:59 chris Rel $"; X#endif X X/* X * Compare strings s1 and s2 for len bytes; return the difference X * between the first differing characters. Could probably use strncmp X * but I don't trust it to work the same way when encountering \0s. X */ Xmdbm_compare (s1, s2, len) Xregister char *s1, *s2; Xregister int len; X{ X while (--len >= 0) X if (*s1++ != *s2++) X return *--s1 - *--s2; X return 0; X} END_OF_./mdbm/compare.c if test 492 -ne `wc -c <./mdbm/compare.c`; then echo shar: \"./mdbm/compare.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/dbm.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/dbm.h\" else echo shar: Extracting \"./mdbm/dbm.h\" \(319 characters\) sed "s/^X//" >./mdbm/dbm.h <<'END_OF_./mdbm/dbm.h' X/* X * Multiple key database library compatibility include file X * David M. Ihnat, 1988 X */ X X#include X Xextern datum fetch (); Xextern datum firstkey (); Xextern datum nextkey (); Xextern long forder (); Xextern int delete (); Xextern int store (); Xextern struct mdbm *open (); Xextern int close (); X END_OF_./mdbm/dbm.h if test 319 -ne `wc -c <./mdbm/dbm.h`; then echo shar: \"./mdbm/dbm.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/dbmcompat.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/dbmcompat.c\" else echo shar: Extracting \"./mdbm/dbmcompat.c\" \(4647 characters\) sed "s/^X//" >./mdbm/dbmcompat.c <<'END_OF_./mdbm/dbmcompat.c' X/* X * Compat - provides mdbm <--> dbm compatibility X * X * Author: David M. Ihnat, 2/9/87 X * X * This is a work in the Public Domain. X */ X#include X#include X#include X#include X#include X#include "mdbm.h" X Xstatic struct mdbm *compat_dat = (struct mdbm *)NULL; X/* */ Xdbminit(file) Xchar *file; X{ X /* X * This is interesting; 'dbm' uses two files, '.dir' and X * '.pag'; 'mdbm' uses '.map' and '.dat'. There X * also exists the possibility that calling programs may need to know X * about the original files' existence and/or size, while all the mdbm X * routines insist on the new file names. Solution? The following: X * X * 1) If called, and the old files don't exist, error--in X * the old 'dbm' scheme, they had to create the old files. X * X * 2) If called and the 'old' name files exist, AND they're of zero X * then LINK them to the new name files, since they're just creating X * the database. This will satisfy both the old and new routines. X * X * 3) If called, and the 'old' name files exist and are NOT of zero X * length, then they MUST be already linked to the corresponding X * new-name file, else they could be trying to feed us an old-format X * 'dbm' database. X */ X X /* Only one database may be open at any one time under 'dbm' */ X if(compat_dat != (struct mdbm *)NULL) X (void)mdbm_close(compat_dat); X X /* X * Ok, do the files exist (and, of course, if so, are they accessible?) X */ X if(dbm_fcheck(file,".dir",".map")) X return(-1); X X if(dbm_fcheck(file,".pag",".dat")) X return(-1); X X /* OK, all files either newly set up or already exist! Continue... */ X compat_dat = X mdbm_open(file,O_RDWR,0,(int *)NULL,(int *)NULL,(char *)NULL); X X if(compat_dat == (struct mdbm *)NULL) X return(-1); X X (void)mdbm_setflags(compat_dat,MDBM_ISAUTOW); X X return(0); X} X/* */ Xdatum Xfetch(key) Xdatum key; X{ X return(mdbm_fetch(compat_dat,key)); X} X/* */ Xstore(key,content) Xdatum key,content; X{ X return(mdbm_store(compat_dat,key,content,MDBM_REPLACE)); X} X/* */ Xdelete(key) Xdatum key; X{ X return(mdbm_delete(compat_dat,key)); X} X/* */ Xdatum Xfirstkey() X{ X return(mdbm_firstkey(compat_dat)); X} X/* */ Xdatum Xnextkey(key) Xdatum key; X{ X return(mdbm_nextkey(compat_dat,key)); X} X/* */ Xstatic int Xdbm_fcheck(file,old,new) Xchar *file, *old, *new; X{ X register char *old_file, *new_file; X register int retval1, retval2; X struct stat old_statbuf, new_statbuf; X X char *malloc(); X X /* X * This routine performs all the validity checks. Note that, on error X * returns, the 'malloc'd space isn't released. This isn't too evil an X * action, since failure here should mean further processing can't normally X * continue. X */ X X /* Allocate enough space for '.[map|dat]' and '.[dir|pag]'*/ X old_file = malloc((unsigned)(strlen(file) + 5)); X new_file = malloc((unsigned)(strlen(file) + 5)); X X if(old_file == (char *)NULL || new_file == (char *)NULL) X { X fprintf(stderr,"dbmcompat: Couldn't allocate memory (1)\n"); X return(-1); X } X X /* Setup for test of the old/new file set */ X strcpy(old_file,file); X strcat(old_file,old); X X strcpy(new_file,file); X strcat(new_file,new); X X retval1= stat(old_file,&old_statbuf); X if(retval1) X retval1 = errno; X X retval2= stat(new_file,&new_statbuf); X if(retval2) X retval2 = errno; X X if(retval1) X { X /* Something's fatally wrong */ X if(retval1 == ENOENT) /* Ok...not there... */ X { X fprintf(stderr,"dbmcompat: No file %s\n",old_file); X }else X { /* Couldn't get to it for some reason! */ X fprintf(stderr, X "dbmcompat: Can't get to file %s: %d\n", X old_file,retval1); X } X return(-1); X } X X /* X * Got here; file exists & we can get to it. Does the corresponding X * 'new' file? X */ X if(retval2) X { X if(retval2 == ENOENT) /* Ok, not there... */ X { X if(old_statbuf.st_size != (off_t)0) X { X fprintf(stderr,"dbmcompat: No %s and %s is non-zero size.", X new_file,old_file); X fprintf(stderr,"Possibly old 'dbm' database?\n"); X return(-1); X }else X { X /* Interesting--could be initializing new database. */ X if(link(old_file,new_file)) X { X /* Ouch! */ X perror("dbmcompat"); X return(-1); X } X } X }else X { X fprintf(stderr,"dbmcompat: %s inacessible: %d\n", X new_file,retval2); X return(-1); X } X }else X { X /* It exists; had better be linked to the old file! */ X if((old_statbuf.st_dev != new_statbuf.st_dev) || X (old_statbuf.st_ino != new_statbuf.st_ino)) X { X fprintf(stderr,"dbmcompat: %s and %s are not linked!\n", X old_file,new_file); X return(-1); X } X } X X /* Wow--it's all OK! */ X (void)free(old_file); X (void)free(new_file); X X return(0); X} END_OF_./mdbm/dbmcompat.c if test 4647 -ne `wc -c <./mdbm/dbmcompat.c`; then echo shar: \"./mdbm/dbmcompat.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/delete.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/delete.c\" else echo shar: Extracting \"./mdbm/delete.c\" \(1007 characters\) sed "s/^X//" >./mdbm/delete.c <<'END_OF_./mdbm/delete.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/delete.c,v 1.1 84/08/12 09:58:22 chris Rel $"; X#endif X X#include X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Delete datum under key in dbm d X */ Xmdbm_delete (d, key) Xregister struct mdbm *d; Xdatum key; X{ X#define db ((struct mdbm_dblock *) d -> mdbm_d) X register struct mdbm_dentry *de; X long keyblock; X int keyindex; X extern int errno; X X de = mdbm_search (d, key.dptr, key.dsize, &keyblock, &keyindex, 0); X if (de == 0) { X errno = ENOENT; X return (-1); X } X if (d -> mdbm_flags & MDBM_ISRONLY) { X errno = EPERM; X return (-1); X } X X /* delete the datum */ X mdbm_delitem (d, de - db -> db_e); X X /* delete the key */ X de = mdbm_search (d, key.dptr, key.dsize, &keyblock, &keyindex, 1); X MDBM_DREAD (d, keyblock); X de = &db -> db_e[keyindex]; X de -> de_outx = 0; /* not in use as a key anymore */ X mdbm_delitem (d, keyindex); X MDBM_AUTO (d); X return 0; X} END_OF_./mdbm/delete.c if test 1007 -ne `wc -c <./mdbm/delete.c`; then echo shar: \"./mdbm/delete.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/delitem.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/delitem.c\" else echo shar: Extracting \"./mdbm/delitem.c\" \(1356 characters\) sed "s/^X//" >./mdbm/delitem.c <<'END_OF_./mdbm/delitem.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/delitem.c,v 1.1 84/08/12 09:58:37 chris Rel $"; X#endif lint X X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Delete item 'n' from current data buffer of dbm d X */ Xmdbm_delitem (d, n) Xregister struct mdbm *d; Xregister int n; X{ X register int i; X#define db ((struct mdbm_dblock *) d -> mdbm_d) X register struct mdbm_dentry *de; X X if (n < 0 || n >= db -> db_n) X goto bad; X de = &db -> db_e[n]; X if (de -> de_links > 1) { X de -> de_links--; X goto done; X } X db -> db_n--; X i = (n ? de[-1].de_off : d -> mdbm_dsize) - de -> de_off; X if (i) { /* delete i bytes of text */ X if (n < db -> db_n) { X register char *to, X *from; X register int bytes; X X to = d -> mdbm_d + (n ? de[-1].de_off : d -> mdbm_dsize); X from = to - i; X bytes = de -> de_off - db -> db_e[db -> db_n].de_off; X while (--bytes >= 0) X *--to = *--from; X } X bzero (d -> mdbm_d + db -> db_e[db -> db_n].de_off, i); X } X { X register struct mdbm_dentry *e; X X e = &db -> db_e[db -> db_n]; X while (de < e) { X *de = de[1]; X de -> de_off += i; X de++; X } X bzero ((char *) e, sizeof e); X } Xdone: X d -> mdbm_flags |= MDBM_DDIRTY; X return; X Xbad: X printf ("mdbm bug: bad delitem\n"); X fflush(stdout); X abort (); X} END_OF_./mdbm/delitem.c if test 1356 -ne `wc -c <./mdbm/delitem.c`; then echo shar: \"./mdbm/delitem.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/dumpdbm.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/dumpdbm.c\" else echo shar: Extracting \"./mdbm/dumpdbm.c\" \(1830 characters\) sed "s/^X//" >./mdbm/dumpdbm.c <<'END_OF_./mdbm/dumpdbm.c' X#include "mdbm.h" X#include "mdbm_local.h" X#include X#include X#ifdef SYSV X#include X#else X#include X#endif X#include X#include X Xabort () { kill (getpid (), SIGILL); } X Xmain (argc, argv) Xint argc; Xchar **argv; X{ X register struct mdbm *mp; X register struct mdbm_dblock *db; X register struct mdbm_dentry *de; X int dsize, msize, blocks; X register int i, j, len; X struct stat sb; X X if (argc < 2) { X fprintf (stderr, "Usage: dumpdbm dbname\n"); X exit (1); X } X if (argc > 2) X signal (SIGILL, SIG_IGN); X dsize = msize = 0; X mp = mdbm_open (argv[1], O_RDONLY, 0, &dsize, &msize, (char *) 0); X if (!mp) { X perror (argv[1]); X exit (1); X } X printf ("dbm %s: dsize = %d, msize = %d\n", argv[1], dsize, msize); X (void) fstat (mp -> mdbm_datafd, &sb); X blocks = sb.st_size / dsize; X printf ("(%d data blocks)\n", blocks); X db = (struct mdbm_dblock *) mp -> mdbm_d; X for (i = 0; i < blocks; i++) { X MDBM_DREAD (mp, i); X printf ("block %d: %d entries\n", i, db -> db_n); X for (j = 0, de = db -> db_e; j < db -> db_n; j++, de++) { X printf ("\t%2d: @%4d links=%2d inx=%4d outx=%4d outh=%08x ", X j, de -> de_off, de -> de_links, de -> de_inx, X de -> de_outx, de -> de_outh); X len = (j ? de[-1].de_off : dsize) - de -> de_off; X pr_entry (mp -> mdbm_d + de -> de_off, len); X } X } X (void) mdbm_close (mp); X exit (0); X} X Xpr_entry (s, len) Xregister char *s; Xregister int len; X{ X register int c; X X putchar ('"'); X while (--len >= 0) { X c = *s++ & 0377; X if (c & 0200) X putchar ('M'), putchar ('-'), c &= 0177; X if (c == 0177) X putchar ('^'), putchar ('?'); X else if (c < ' ') X putchar ('^'), putchar (c + '@'); X else X putchar (c); X } X putchar ('"'); X putchar ('\n'); X} END_OF_./mdbm/dumpdbm.c if test 1830 -ne `wc -c <./mdbm/dumpdbm.c`; then echo shar: \"./mdbm/dumpdbm.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/fetch.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/fetch.c\" else echo shar: Extracting \"./mdbm/fetch.c\" \(670 characters\) sed "s/^X//" >./mdbm/fetch.c <<'END_OF_./mdbm/fetch.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/fetch.c,v 1.1 84/08/12 09:59:20 chris Rel $"; X#endif X X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Find datum in dbm d, given key X */ Xdatum mdbm_fetch (d, key) Xregister struct mdbm *d; Xdatum key; X{ X#define db ((struct mdbm_dblock *) d -> mdbm_d) X register struct mdbm_dentry *de; X datum item; X X de = mdbm_search (d, key.dptr, key.dsize, (long *) 0, (int *) 0, 0); X if (de) { X item.dptr = d -> mdbm_d + de -> de_off; X item.dsize = (de > db -> db_e ? de[-1].de_off : d -> mdbm_dsize) - X de -> de_off; X } X else X item.dptr = 0, item.dsize = 0; X return item; X} END_OF_./mdbm/fetch.c if test 670 -ne `wc -c <./mdbm/fetch.c`; then echo shar: \"./mdbm/fetch.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/firsthash.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/firsthash.c\" else echo shar: Extracting \"./mdbm/firsthash.c\" \(1440 characters\) sed "s/^X//" >./mdbm/firsthash.c <<'END_OF_./mdbm/firsthash.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/firsthash.c,v 1.1 84/08/12 09:59:59 chris Rel $"; X#endif X X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Return the first datum in dbm d with hash value hash X */ Xdatum mdbm_firsthash (d, hash) Xregister struct mdbm *d; Xlong hash; X{ X#define db ((struct mdbm_dblock *) d -> mdbm_d) X register struct mdbm_dentry *de; X register int i; X char *bp; X int bl; X char *ip; X int il, X found; X long hmask; X datum rval; X Xloop: X /* Suck in the block for the given hash, then find the "first" key. */ X hmask = mdbm_access (d, hash); X found = 0; X#ifdef lint /* lint doesn't realize that 'found' X overrides the tests on bl and bp */ X bl = 0; X bp = 0; X#endif lint X for (i = 0, de = db -> db_e; i < db -> db_n; i++, de++) { X if (de -> de_outx == 0) /* not a key */ X continue; X il = (i ? de[-1].de_off : d -> mdbm_dsize) - de -> de_off; X ip = d -> mdbm_d + de -> de_off; X if (!found || il < bl || (il == bl && mdbm_compare (ip, bp, il) < 0)) { X bl = il; X bp = ip; X found++; X } X } X if (found) { X bcopy (bp, rval.dptr = d -> mdbm_s, rval.dsize = bl); X return rval; X } X X /* No item with this hash, so get next hash and try again */ X hash = mdbm_hashinc (hash, hmask); X if (hash == 0) { /* no more */ X rval.dsize = 0; X rval.dptr = 0; X return rval; X } X goto loop; X} END_OF_./mdbm/firsthash.c if test 1440 -ne `wc -c <./mdbm/firsthash.c`; then echo shar: \"./mdbm/firsthash.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/firstkey.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/firstkey.c\" else echo shar: Extracting \"./mdbm/firstkey.c\" \(306 characters\) sed "s/^X//" >./mdbm/firstkey.c <<'END_OF_./mdbm/firstkey.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/firstkey.c,v 1.1 84/08/12 10:00:27 chris Rel $"; X#endif X X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Return the "first" key in dbm d X */ Xdatum mdbm_firstkey (d) Xstruct mdbm *d; X{ X return mdbm_firsthash (d, 0L); X} END_OF_./mdbm/firstkey.c if test 306 -ne `wc -c <./mdbm/firstkey.c`; then echo shar: \"./mdbm/firstkey.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/hash.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/hash.c\" else echo shar: Extracting \"./mdbm/hash.c\" \(1708 characters\) sed "s/^X//" >./mdbm/hash.c <<'END_OF_./mdbm/hash.c' X#include X#include "mdbm.h" X#include "mdbm_local.h" X Xint hitab[16] = { X/* ken's X 055,043,036,054,063,014,004,005, X 010,064,077,000,035,027,025,071, */ X X 61, 57, 53, 49, 45, 41, 37, 33, X 29, 25, 21, 17, 13, 9, 5, 1, X}; X Xlong hltab[64] = { X 06100151277L,06106161736L,06452611562L,05001724107L, X 02614772546L,04120731531L,04665262210L,07347467531L, X 06735253126L,06042345173L,03072226605L,01464164730L, X 03247435524L,07652510057L,01546775256L,05714532133L, X 06173260402L,07517101630L,02431460343L,01743245566L, X 00261675137L,02433103631L,03421772437L,04447707466L, X 04435620103L,03757017115L,03641531772L,06767633246L, X 02673230344L,00260612216L,04133454451L,00615531516L, X 06137717526L,02574116560L,02304023373L,07061702261L, X 05153031405L,05322056705L,07401116734L,06552375715L, X 06165233473L,05311063631L,01212221723L,01052267235L, X 06000615237L,01075222665L,06330216006L,04402355630L, X 01451177262L,02000133436L,06025467062L,07121076461L, X 03123433522L,01010635225L,01716177066L,05161746527L, X 01736635071L,06243505026L,03637211610L,01756474365L, X 04723077174L,03642763134L,05750130273L,03655541561L, X}; X X/* X * Calculate the hash val for the given item. X */ Xlong mdbm_calchash (s, len) Xregister char *s; Xregister int len; X{ X register int hashi = 0; X register long hashl = 0L; X X while (--len >= 0) { X register int f = *s++; X X#if BYTESIZ > 4 && BYTESIZ <= 8 /* an easy optimization */ X hashi += hitab[f & 15]; X hashl += hltab[hashi & 63]; X f >>= 4; X hashi += hitab[f & 15]; X hashl += hltab[hashi & 63]; X#else X register int j; X X for (j = 0; j < BYTESIZ; j += 4) { X hashi += hitab[f & 15]; X hashl += hltab[hashi & 63]; X f >>= 4; X } X#endif X } X return hashl; X} END_OF_./mdbm/hash.c if test 1708 -ne `wc -c <./mdbm/hash.c`; then echo shar: \"./mdbm/hash.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/hashinc.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/hashinc.c\" else echo shar: Extracting \"./mdbm/hashinc.c\" \(447 characters\) sed "s/^X//" >./mdbm/hashinc.c <<'END_OF_./mdbm/hashinc.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/hashinc.c,v 1.1 84/08/12 10:01:19 chris Rel $"; X#endif X X/* X * Return the next hash number for this dbm, or 0 for no more X */ Xlong mdbm_hashinc (hash, hmask) Xregister long hash, hmask; X{ X register long bit; X X hash &= hmask; X bit = hmask + 1; X for (;;) { X bit >>= 1; X if (bit == 0) X return 0L; X if ((hash & bit) == 0) X return hash | bit; X hash &= ~bit; X } X} END_OF_./mdbm/hashinc.c if test 447 -ne `wc -c <./mdbm/hashinc.c`; then echo shar: \"./mdbm/hashinc.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/mdbm.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/mdbm.h\" else echo shar: Extracting \"./mdbm/mdbm.h\" \(2312 characters\) sed "s/^X//" >./mdbm/mdbm.h <<'END_OF_./mdbm/mdbm.h' X/* $Header: /ful/chris/dist/mdbm/mdbm.h,v 1.1 84/08/12 10:05:08 chris Rel $ */ X X/* X * Multiple key database library (-lmdbm) X */ X X/* structure describing an open mdbm file */ Xstruct mdbm { X int mdbm_flags; /* flags (see below) */ X int mdbm_datafd; /* data area file descriptor */ X int mdbm_mapfd; /* bitmap file descriptor */ X int mdbm_dsize; /* data buffer size */ X int mdbm_msize; /* bitmap buffer size */ X long mdbm_maxbit; /* max possible set bit in map + 1 */ X long mdbm_dblock; /* index of current data block */ X long mdbm_mblock; /* index of current map block */ X char *mdbm_d; /* current data block */ X char *mdbm_s; /* secondary data block */ X char *mdbm_m; /* current map block */ X}; X X/* structure giving (external) description of data and keys */ Xtypedef struct { X char *dptr; X int dsize; X} datum; X X/* X * mdbm_flags X */ X#define MDBM_ISRONLY 0x01 /* true => db is readonly */ X#define MDBM_ISAUTOW 0x02 /* true => do all writes immediately */ X#define MDBM_DDIRTY 0x04 /* true => data buffer out of sync */ X#define MDBM_MDIRTY 0x08 /* true => map buffer out of sync */ X X#define MDBM_UF 0x02 /* user allowed to modify only these flags */ X X/* X * flags to mdbm_store() X */ X#define MDBM_INSERT 0 /* insert only; abort if key found */ X#define MDBM_REPLACE 1 /* replace (or insert if not found) */ X Xdatum mdbm_fetch (); Xdatum mdbm_firstkey (); Xdatum mdbm_nextkey (); Xlong mdbm_forder (); Xint mdbm_delete (); Xint mdbm_store (); Xstruct mdbm *mdbm_open (); Xint mdbm_close (); X X/* X * open flags the same as those for the open() system call X * with the exception that we force O_RDWR for O_WRONLY opens. X */ X X/* X * mdbm files contain a descriptive comment whose length is not X * longer than this, and is (supposed to be) null terminated. X */ X#define MDBM_CSIZ 248 X X/* X * ``routines'' to examine and alter flags X */ X#define mdbm_getflags(m) \ X ((m) -> mdbm_flags) X#define mdbm_setflags(m,f) \ X ((m) -> mdbm_flags &= ~MDBM_UF, (m) -> mdbm_flags |= (f) & MDBM_UF) X#define mdbm_bisflags(m,f) \ X ((m) -> mdbm_flags |= (f) & MDBM_UF) X#define mdbm_bicflags(m,f) \ X ((m) -> mdbm_flags &= ~((f) & MDBM_UF)) X X/* X * BSD-isms X */ X#define SYSV X X#ifdef SYSV X#define bcmp(s1, s2, cnt) memcmp(s1,s2,cnt) X#define bcopy(fr, to, cnt) memcpy(to,fr,cnt) X#define bzero(addr,cnt) memset(addr,'\0',cnt) X#endif END_OF_./mdbm/mdbm.h if test 2312 -ne `wc -c <./mdbm/mdbm.h`; then echo shar: \"./mdbm/mdbm.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/mdbm_local.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/mdbm_local.h\" else echo shar: Extracting \"./mdbm/mdbm_local.h\" \(4198 characters\) sed "s/^X//" >./mdbm/mdbm_local.h <<'END_OF_./mdbm/mdbm_local.h' X/* $Header: /ful/chris/dist/mdbm/mdbm_local.h,v 1.1 84/08/12 10:05:28 chris Rel $ */ X X/* X * Definitions local to the various mdbm source files X */ X X#define BYTESIZ 8 /* size of a byte */ X#define MAXUSHORT 65535 /* largest legal value for unsigned short */ X X/* Default database sizes for new databases */ X#define MDBM_DefaultDataSize 1024 /* data buffer block size */ X#define MDBM_DefaultMapSize 4096 /* bitmap buffer block size */ X X/* Minimum sizes. Requests for anything smaller will be brought up X to these values. */ X#define MDBM_MinDataSize 128 /* minimum data buffer size */ X#define MDBM_MinMapSize 128 /* minimum map buffer size */ X X/* X * This structure goes in at the front of the map file. It describes X * the per-database info. Typically the "comment" field contains the X * name of the database. X */ Xstruct mdbm_h { X int mh_dsize; /* size of data file blocks */ X int mh_msize; /* size of map file blocks */ X char mh_comment[MDBM_CSIZ];/* whatever you like */ X}; X X/* X * Within the map file, we simply have bits set whenever a data block X * was split. The data file is more complex. It contains the following X * info in each block: X * # entries in block X * entries X * free space X * text X * X * where the format of an entry is (as given by struct mdbm_dentry) X * X * X * off is the offset within the block of the text (and thus also specifies X * the size of the text string); links is the number of links to this item; X * inx is the ``in index'' number of this item; outx is the ``out index'' X * number of this item; and outh is the out hash. X * X * If an item is in use as a key, its outx will contain a nonzero X * number which is repeated in the inx field of its datum. The hash value X * in outh will (by the usual extensible hashing rules) determine a block X * number, and the item with the matching inx field in that block is the X * datum under the key in question. X * X * An item's inx field will always contain a nonzero number that is unique X * to the block in which the item resides. X */ Xstruct mdbm_dblock { X int db_n; /* number of entries */ X struct mdbm_dentry { X unsigned short de_off; /* offset to beginning of text */ X unsigned short de_links;/* number of links */ X unsigned short de_inx; /* in index */ X unsigned short de_outx; /* out index */ X unsigned long de_outh; /* out hash */ X } db_e[1]; /* actually db_e[db_n], but can't say that */ X}; X X/* Some macros to simplify(?) things a bit */ X X/* Read block blk (size sz offset off) from file f into buffer buf */ X#define MDBM_RBLK(f,blk,buf,sz,off) \ X ((void) lseek (f, (blk)*(sz)+(off), 0), (void) read (f, buf, sz)) X X/* Write block blk (size sz offset off) to file f from buffer buf */ X#define MDBM_WBLK(f,blk,buf,sz,off) \ X ((void) lseek (f, (blk)*(sz)+(off), 0), (void) write (f, buf, sz)) X X/* Write (if needed) */ X#define MDBM_DSYNC(d) \ X if ((d) -> mdbm_flags & MDBM_DDIRTY) { \ X MDBM_WBLK ((d) -> mdbm_datafd, (d) -> mdbm_dblock, (d) -> mdbm_d, \ X (d) -> mdbm_dsize, 0); \ X (d) -> mdbm_flags &= ~MDBM_DDIRTY; \ X } X X#define MDBM_MSYNC(d) \ X if ((d) -> mdbm_flags & MDBM_MDIRTY) { \ X MDBM_WBLK ((d) -> mdbm_mapfd, (d) -> mdbm_mblock, (d) -> mdbm_m, \ X (d) -> mdbm_msize, sizeof (struct mdbm_h)); \ X (d) -> mdbm_flags &= ~MDBM_MDIRTY; \ X } X X#define MDBM_SYNC(d) { MDBM_DSYNC(d); MDBM_MSYNC(d); } X X/* Do autowrites */ X#define MDBM_AUTO(d) if ((d) -> mdbm_flags & MDBM_ISAUTOW) MDBM_SYNC (d) X X/* Read data block b */ X#define MDBM_DREAD(d,b) \ X if ((d) -> mdbm_dblock != (b)) { \ X MDBM_DSYNC (d); \ X bzero ((d) -> mdbm_d, (d) -> mdbm_dsize); \ X MDBM_RBLK ((d) -> mdbm_datafd, (d) -> mdbm_dblock = (b), \ X (d) -> mdbm_d, (d) -> mdbm_dsize, 0); \ X mdbm_checkblock ((d) -> mdbm_d, (d) -> mdbm_dsize); \ X } X X/* Read map block b */ X#define MDBM_MREAD(d,b) \ X if ((d) -> mdbm_mblock != (b)) { \ X MDBM_MSYNC (d); \ X bzero ((d) -> mdbm_m, (d) -> mdbm_msize); \ X MDBM_RBLK ((d) -> mdbm_mapfd, (d) -> mdbm_mblock = (b), \ X (d) -> mdbm_m, (d) -> mdbm_msize, sizeof (struct mdbm_h)); \ X } X X/* X * function types X */ Xlong mdbm_calchash (); Xlong mdbm_hashinc (); Xstruct mdbm_dentry *mdbm_search (); Xdatum mdbm_firsthash (); Xlong lseek (); Xchar *malloc (); END_OF_./mdbm/mdbm_local.h if test 4198 -ne `wc -c <./mdbm/mdbm_local.h`; then echo shar: \"./mdbm/mdbm_local.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/nextkey.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/nextkey.c\" else echo shar: Extracting \"./mdbm/nextkey.c\" \(1627 characters\) sed "s/^X//" >./mdbm/nextkey.c <<'END_OF_./mdbm/nextkey.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/nextkey.c,v 1.1 84/08/12 10:01:55 chris Rel $"; X#endif X X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Return the "next" key in dbm d X */ Xdatum mdbm_nextkey (d, key) Xregister struct mdbm *d; Xdatum key; X{ X#define db ((struct mdbm_dblock *) d -> mdbm_d) X register struct mdbm_dentry *de; X register int i; X char *bp; X int bl; X char *ip; X int il, X found; X long hash, X hmask; X datum rval; X X /* Suck in the block for the given hash, then find the key that follows X the one given */ X hash = mdbm_calchash (key.dptr, key.dsize); X hmask = mdbm_access (d, hash); X found = 0; X#ifdef lint /* lint doesn't realize that 'found' X overrides the tests on bl and bp */ X bl = 0; X bp = 0; X#endif lint X for (i = 0, de = db -> db_e; i < db -> db_n; i++, de++) { X if (de -> de_outx == 0) /* not a key */ X continue; X il = (i ? de[-1].de_off : d -> mdbm_dsize) - de -> de_off; X ip = d -> mdbm_d + de -> de_off; X if (il < key.dsize || X (il == key.dsize && mdbm_compare (ip, key.dptr, il) <= 0)) X continue; X if (!found || il < bl || (il == bl && mdbm_compare (ip, bp, il) < 0)) { X bl = il; X bp = ip; X found++; X } X } X if (found) { X bcopy (bp, rval.dptr = d -> mdbm_s, rval.dsize = bl); X return rval; X } X X /* No item with this hash, so get next hash and return its first item */ X hash = mdbm_hashinc (hash, hmask); X if (hash == 0) { /* no more */ X rval.dsize = 0; X rval.dptr = 0; X return rval; X } X return mdbm_firsthash (d, hash); X} END_OF_./mdbm/nextkey.c if test 1627 -ne `wc -c <./mdbm/nextkey.c`; then echo shar: \"./mdbm/nextkey.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/open.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/open.c\" else echo shar: Extracting \"./mdbm/open.c\" \(3310 characters\) sed "s/^X//" >./mdbm/open.c <<'END_OF_./mdbm/open.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/open.c,v 1.1 84/08/12 10:02:40 chris Rel $"; X#endif X X#include "mdbm.h" X#include "mdbm_local.h" X#include X#include X#include X#ifdef SYSV X#include X#else X#include X#endif X#include X X/* X * Open or create a database X */ Xstruct mdbm *mdbm_open (file, flags, mode, adsize, amsize, comment) Xchar *file; Xint flags, mode; Xint *adsize, *amsize; Xchar *comment; X{ X register struct mdbm *d; X struct stat stat; X struct mdbm_h mdbm_h; X int dsize, X msize, X l; X char *namebuf, X *p; X char *strcpy (); X char *strncpy (); X extern int errno; X X /* get a descriptor */ X if ((d = (struct mdbm *) malloc (sizeof *d)) == 0) { X errno = ENOMEM; X return 0; X } X /* get enough room for the file names */ X l = strlen (file); X if ((namebuf = malloc ((unsigned) (l + 5))) == 0) { X l = ENOMEM; X goto out; X } X X /* find out how big the buffers should be, if this is a new db */ X dsize = adsize == 0 || *adsize == 0 ? MDBM_DefaultDataSize : *adsize; X msize = amsize == 0 || *amsize == 0 ? MDBM_DefaultMapSize : *amsize; X if (dsize < MDBM_MinDataSize) X dsize = MDBM_MinDataSize; X if (msize < MDBM_MinMapSize) X msize = MDBM_MinMapSize; X X /* fix up the mode, then open them files */ X if ((flags & 3) == O_WRONLY) X flags = (flags & ~3) | O_RDWR; X (void) strcpy (namebuf, file); X p = &namebuf[l]; X (void) strcpy (p, ".dat"); X if ((d -> mdbm_datafd = open (namebuf, flags, mode)) < 0) { X l = errno; X goto out; X } X (void) strcpy (p, ".map"); X if ((d -> mdbm_mapfd = open (namebuf, flags, mode)) < 0) { X l = errno; X goto out1; X } X free (namebuf); X X /* initialize the dbm descriptor */ X d -> mdbm_flags = (flags & 3) == O_RDONLY ? MDBM_ISRONLY : 0; X X (void) fstat (d -> mdbm_mapfd, &stat); X if (stat.st_size == 0) { X mdbm_h.mh_dsize = dsize; X mdbm_h.mh_msize = msize; X bzero (mdbm_h.mh_comment, MDBM_CSIZ); X (void) strncpy (mdbm_h.mh_comment, X comment && *comment ? comment : file, MDBM_CSIZ); X mdbm_h.mh_comment[MDBM_CSIZ - 1] = 0; X if ((d -> mdbm_flags & MDBM_ISRONLY) == 0) X if (write (d -> mdbm_mapfd, (char *) & mdbm_h, sizeof mdbm_h) != X sizeof mdbm_h) X goto out2; X } X else { X if (read (d -> mdbm_mapfd, (char *) & mdbm_h, sizeof mdbm_h) != X sizeof mdbm_h) { X l = EINVAL; X goto out2; X } X dsize = mdbm_h.mh_dsize; X msize = mdbm_h.mh_msize; X } X if (adsize) X *adsize = dsize; X if (amsize) X *amsize = msize; X if (comment) X (void) strncpy (comment, mdbm_h.mh_comment, MDBM_CSIZ); X if ((d -> mdbm_d = malloc ((unsigned) dsize)) == 0) { X l = ENOMEM; X goto out2; X } X if ((d -> mdbm_s = malloc ((unsigned) dsize)) == 0) { X free (d -> mdbm_d); X l = ENOMEM; X goto out2; X } X if ((d -> mdbm_m = malloc ((unsigned) msize)) == 0) { X free (d -> mdbm_s); X free (d -> mdbm_d); X l = ENOMEM; X goto out2; X } X d -> mdbm_dsize = dsize; X d -> mdbm_msize = msize; X d -> mdbm_maxbit = (stat.st_size - sizeof mdbm_h) * BYTESIZ; X d -> mdbm_dblock = -1; X d -> mdbm_mblock = -1; X X return d; X Xout2: X (void) close (d -> mdbm_datafd); Xout1: X (void) close (d -> mdbm_mapfd); Xout: X free ((char *) d); X errno = l; X return 0; X} END_OF_./mdbm/open.c if test 3310 -ne `wc -c <./mdbm/open.c`; then echo shar: \"./mdbm/open.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/search.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/search.c\" else echo shar: Extracting \"./mdbm/search.c\" \(1528 characters\) sed "s/^X//" >./mdbm/search.c <<'END_OF_./mdbm/search.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/search.c,v 1.1 84/08/12 10:03:12 chris Rel $"; X#endif X X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Search for the given key, and if found, return a pointer to the X * datum under the key. If ablock and aindex are nonzero, fill in X * the block and index numbers of the key. If justkey is true, X * forget about the datum and stop when the key is found. X * X * (Workhorse for fetch, also used by delete & store.) X */ Xstruct mdbm_dentry *mdbm_search (d, s, len, ablock, aindex, justkey) Xregister struct mdbm *d; Xchar *s; Xregister int len; Xlong *ablock; Xint *aindex; Xint justkey; X{ X#define db ((struct mdbm_dblock *) d -> mdbm_d) X register struct mdbm_dentry *de; X register int i; X register unsigned short outx; X long outh; X X (void) mdbm_access (d, mdbm_calchash (s, len)); X for (i = 0, de = db -> db_e; i < db -> db_n; i++, de++) { X if (de -> de_outx == 0) /* not a key */ X continue; X if (len == (i ? de[-1].de_off : d -> mdbm_dsize) - de -> de_off) X if (bcmp (s, d -> mdbm_d + de -> de_off, len) == 0) X goto found; X } X return 0; Xfound: X if (ablock) X *ablock = d -> mdbm_dblock; X if (aindex) X *aindex = i; X if (justkey) X return de; X outx = de -> de_outx; X (void) mdbm_access (d, outh = de -> de_outh); X for (i = 0, de = db -> db_e; i < db -> db_n; i++, de++) X if (de -> de_inx == outx) X return de; X printf ("mdbm bug: no datum for key (%d, %d)\n", outh, outx); X return 0; X} END_OF_./mdbm/search.c if test 1528 -ne `wc -c <./mdbm/search.c`; then echo shar: \"./mdbm/search.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/sync.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/sync.c\" else echo shar: Extracting \"./mdbm/sync.c\" \(423 characters\) sed "s/^X//" >./mdbm/sync.c <<'END_OF_./mdbm/sync.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/sync.c,v 1.1 84/08/12 10:04:03 chris Rel $"; X#endif X X#include X#include "mdbm.h" X#include "mdbm_local.h" X X/* X * Sync the file attached to dbm d X */ Xmdbm_sync (d) Xregister struct mdbm *d; X{ X MDBM_SYNC (d); X#ifdef SYSV X (void) sync (); X (void) sync (); X#else X (void) fsync (d -> mdbm_datafd); X (void) fsync (d -> mdbm_mapfd); X#endif X} END_OF_./mdbm/sync.c if test 423 -ne `wc -c <./mdbm/sync.c`; then echo shar: \"./mdbm/sync.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f ./mdbm/testdbm.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"./mdbm/testdbm.c\" else echo shar: Extracting \"./mdbm/testdbm.c\" \(5554 characters\) sed "s/^X//" >./mdbm/testdbm.c <<'END_OF_./mdbm/testdbm.c' X#ifndef lint Xstatic char rcsid[] = "$Header: /ful/chris/dist/mdbm/testdbm.c,v 1.1 84/08/12 10:04:23 chris Rel $"; X#endif lint X X/* X * testdbm - test the new multiple key database library X */ X X#include "mdbm.h" X#include X#include X#ifdef SYSV X#include X#else X#include X#endif X#include X Xstruct mdbm *mp; X#define NAV 10 Xstruct stringarg { X int s_len; X char *s_str; X} av[NAV]; X Xint c_open (), c_close (), c_fetch (), c_insert (), c_replace (); Xint c_delete (), c_list (), c_quit (), c_sync (); X Xstruct cmd { X char *c_name; X int (*c_func)(); X int c_args; X} cmds[] = { X "open", c_open, 2, X "open", c_open, 4, X "open", c_open, 5, X "close", c_close, 1, X "fetch", c_fetch, 2, X "get", c_fetch, 2, X "insert", c_insert, 3, X "store", c_insert, 3, X "replace", c_replace, 3, X "delete", c_delete, 2, X "list", c_list, 1, X "quit", c_quit, 1, X "sync", c_sync, 1, X 0, 0, 0 X}; Xchar serrbuf[BUFSIZ]; X X#define checkdb() \ X if (!mp) { \ X fprintf (stderr, "no database active\n"); \ X return; \ X } \ X else X Xmain () { X char cmdbuf[BUFSIZ]; X X setbuf (stderr, serrbuf); X for (;;) { X fflush (stderr); X printf ("testdbm> "); X fflush (stdout); X if (fgets (cmdbuf, sizeof cmdbuf, stdin) == NULL) { X putchar ('\n'); X c_quit (0); X } X if (doit (cmdbuf)) X printf ("Eh?\n"); X } X} X Xdoit (s) Xchar *s; X{ X register int argc = parse (s); X register struct cmd *cp; X X if (argc < 1) X return 0; X if (av[0].s_len < 1) X return 1; X for (cp = cmds; cp -> c_name; cp++) { X if (cp -> c_args != argc) X continue; X if (strncmp (cp -> c_name, av[0].s_str, av[0].s_len) == 0) { X (*cp -> c_func) (argc); X return 0; X } X } X return 1; X} X Xc_open (argc) { X int dsize, msize; X static char comment[MDBM_CSIZ]; X X if (mp) X (void) mdbm_close (mp); X if (argc == 5) X strncpy (comment, av[4].s_str, sizeof comment); X else X *comment = 0; X if (argc >= 4) { X dsize = atoi (av[2].s_str); X msize = atoi (av[3].s_str); X } X else X dsize = msize = 0; X mp = mdbm_open (av[1].s_str, O_RDWR|O_CREAT, 0666, &dsize, &msize, comment); X if (mp == 0) { X fprintf (stderr, "can't open "); X perror (av[1].s_str); X return; X } X comment[sizeof comment - 1] = 0; X printf ("opened %s - dsize %d, msize %d, comment %s\n", X av[1].s_str, dsize, msize, comment); X} X Xc_close (argc) { X if (mp) X (void) mdbm_close (mp); X mp = 0; X} X Xc_fetch (argc) { X datum key, dat; X X checkdb (); X key.dptr = av[1].s_str; X key.dsize = av[1].s_len; X dat = mdbm_fetch (mp, key); X prdatum (key); X printf (": "); X if (dat.dptr == 0) X printf ("not found"); X else X prdatum (dat); X putchar ('\n'); X} X Xprdatum (d) Xdatum d; X{ X register char *p; X register int c; X register int i; X X i = d.dsize; X p = d.dptr; X while (--i >= 0) { X c = *p++ & 0377; X if (c & 0200) { X putchar ('M'), putchar ('-'); X c &= 0177; X } X if (c == 0177 || c < ' ') { X putchar ('^'); X if (c == 0177) X putchar ('?'); X else X putchar (c + '@'); X } X else X putchar (c); X } X} X Xc_insert (argc) { X datum key, dat; X int e; X X checkdb (); X key.dptr = av[1].s_str; X key.dsize = av[1].s_len; X dat.dptr = av[2].s_str; X dat.dsize = av[2].s_len; X e = mdbm_store (mp, key, dat, MDBM_INSERT); X if (e == 0) X return; X if (e < 0) X perror ("store failed"); X else X fprintf (stderr, "insert failed, key in use\n"); X} X Xc_replace (argc) { X datum key, dat; X int e; X X checkdb (); X key.dptr = av[1].s_str; X key.dsize = av[1].s_len; X dat.dptr = av[2].s_str; X dat.dsize = av[2].s_len; X if (mdbm_store (mp, key, dat, MDBM_REPLACE)) X perror ("store failed"); X} X Xc_delete (argc) { X datum key; X X checkdb (); X key.dptr = av[1].s_str; X key.dsize = av[1].s_len; X if (mdbm_delete (mp, key)) X perror ("delete failed"); X} X Xc_list () { X datum key, dat; X X checkdb (); X for (key = mdbm_firstkey (mp); key.dptr; key = mdbm_nextkey (mp, key)) { X dat = mdbm_fetch (mp, key); X prdatum (key); X printf (": "); X if (dat.dptr == 0) X printf ("datum not found!"); X else X prdatum (dat); X putchar ('\n'); X } X} X Xc_quit () { X if (mp) X (void) mdbm_close (mp); X exit (0); X} X Xc_sync () { X checkdb (); X mdbm_sync (mp); X} X Xparse (s) Xregister char *s; X{ X register struct stringarg *ap; X register int aleft; X register int qu = 0; X register char *cp; X register int c; X static char xbuf[BUFSIZ]; X char *malloc (); X X for (ap = av, aleft = NAV; --aleft >= 0; ap++) X if (ap -> s_str) { X free (ap -> s_str); X ap -> s_str = 0; X } X X ap = av; X aleft = NAV; X while (*s) { X while (isspace (*s)) X s++; X if (!*s) X break; X qu = 0; X cp = xbuf; X while (((c = *s) != 0) && (qu || !isspace (c))) { X s++; X if (qu == '\\') { X switch (c) { X case 'n': X c = '\n'; X break; X case 'r': X c = '\r'; X break; X case 't': X c = '\t'; X break; X case 'b': X c = '\b'; X break; X case 'f': X c = '\f'; X break; X case '0': X case '1': X case '2': X case '3': X case '4': X case '5': X case '6': X case '7': X c -= '0'; X if (*s >= '0' && *s <= '7') { X c = (c << 3) + *s++ - '0'; X if (*s >= '0' && *s <= '7') X c = (c << 3) + *s++ - '0'; X } X break; X } X *cp++ = c; X qu = 0; X } X else if (c == qu) X qu = 0; X else if (qu == 0 && (c == '\'' || c == '"' || c == '\\')) X qu = c; X else X *cp++ = c; X } X *cp++ = 0; X if (--aleft < 0) { X fprintf (stderr, "too many argv's\n"); X return 0; X } X ap -> s_str = malloc (cp - xbuf); X ap -> s_len = cp - xbuf; X bcopy (xbuf, ap -> s_str, ap -> s_len); X ap -> s_len--; /* stop counting trailing \0 */ X ap++; X } X return NAV - aleft; X} END_OF_./mdbm/testdbm.c if test 5554 -ne `wc -c <./mdbm/testdbm.c`; then echo shar: \"./mdbm/testdbm.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 1 \(of 2\). cp /dev/null ark1isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 --- But don't underestimate raw, frothing, manic hardware. (barry shein) Randy Suess ..!att!chinet!randy -- But don't underestimate raw, frothing, manic hardware. (barry shein) Randy Suess ..!att!chinet!randy