You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@locus.apache.org on 2000/09/21 15:06:16 UTC

cvs commit: apache-1.3/src/lib/sdbm .cvsignore sdbm.c sdbm.dsp sdbm.h sdbm.mak sdbm.ncb sdbm.opt sdbm_hash.c sdbm_lock.c sdbm_pair.c sdbm_pair.h sdbm_tune.h

wrowe       00/09/21 06:06:15

  Added:       src/lib/sdbm .cvsignore sdbm.c sdbm.dsp sdbm.h sdbm.mak
                        sdbm.ncb sdbm.opt sdbm_hash.c sdbm_lock.c
                        sdbm_pair.c sdbm_pair.h sdbm_tune.h
  Log:
    sdbm from mod_dav 1.0 added to accomodate Win32 and other DBM-less
    platforms.  Required by mod_auth_dbm in the core distro for Win32.
  
  Revision  Changes    Path
  1.1                  apache-1.3/src/lib/sdbm/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  Makefile
  Debug
  Release
  
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm.c
  
  Index: sdbm.c
  ===================================================================
  /*
   * sdbm - ndbm work-alike hashed database library
   * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
   * author: oz@nexus.yorku.ca
   * status: public domain.
   *
   * core routines
   */
  
  #include "sdbm.h"
  #include "sdbm_tune.h"
  #include "sdbm_pair.h"
  
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  #include <errno.h>
  #include <string.h>
  #include <stdlib.h>
  #ifdef WIN32
  #include <io.h>
  #include <stdio.h>
  #else
  #include <unistd.h>	/* for lseek() */
  #endif
  
  
  /*
   * forward
   */
  static int getdbit proto((DBM *, long));
  static int setdbit proto((DBM *, long));
  static int getpage proto((DBM *, long));
  static datum getnext proto((DBM *));
  static int makroom proto((DBM *, long, int));
  
  /*
   * useful macros
   */
  #define bad(x)		((x).dptr == NULL || (x).dsize <= 0)
  #define exhash(item)	sdbm_hash((item).dptr, (item).dsize)
  #define ioerr(db)	((db)->flags |= DBM_IOERR)
  
  #define OFF_PAG(off)	(long) (off) * PBLKSIZ
  #define OFF_DIR(off)	(long) (off) * DBLKSIZ
  
  static long masks[] = {
  	000000000000, 000000000001, 000000000003, 000000000007,
  	000000000017, 000000000037, 000000000077, 000000000177,
  	000000000377, 000000000777, 000000001777, 000000003777,
  	000000007777, 000000017777, 000000037777, 000000077777,
  	000000177777, 000000377777, 000000777777, 000001777777,
  	000003777777, 000007777777, 000017777777, 000037777777,
  	000077777777, 000177777777, 000377777777, 000777777777,
  	001777777777, 003777777777, 007777777777, 017777777777
  };
  
  datum nullitem = {NULL, 0};
  
  DBM *
  sdbm_open(file, flags, mode)
  register char *file;
  register int flags;
  register int mode;
  {
  	register DBM *db;
  	register char *dirname;
  	register char *pagname;
  	register int n;
  
  	if (file == NULL || !*file)
  		return errno = EINVAL, (DBM *) NULL;
  /*
   * need space for two seperate filenames
   */
  	n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
  
  	if ((dirname = malloc((unsigned) n)) == NULL)
  		return errno = ENOMEM, (DBM *) NULL;
  /*
   * build the file names
   */
  	dirname = strcat(strcpy(dirname, file), DIRFEXT);
  	pagname = strcpy(dirname + strlen(dirname) + 1, file);
  	pagname = strcat(pagname, PAGFEXT);
  
  	db = sdbm_prep(dirname, pagname, flags, mode);
  	free((char *) dirname);
  	return db;
  }
  
  DBM *
  sdbm_prep(dirname, pagname, flags, mode)
  char *dirname;
  char *pagname;
  int flags;
  int mode;
  {
  	register DBM *db;
  	struct stat dstat;
  
  	if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
  		return errno = ENOMEM, (DBM *) NULL;
  
          db->flags = 0;
          db->hmask = 0;
          db->blkptr = 0;
          db->keyptr = 0;
  /*
   * adjust user flags so that WRONLY becomes RDWR, 
   * as required by this package. Also set our internal
   * flag for RDONLY if needed.
   */
  	if (flags & O_WRONLY)
  		flags = (flags & ~O_WRONLY) | O_RDWR;
  
  	else if ((flags & 03) == O_RDONLY)
  		db->flags = DBM_RDONLY;
  /*
   * open the files in sequence, and stat the dirfile.
   * If we fail anywhere, undo everything, return NULL.
   */
  #if defined(OS2) || defined(MSDOS) || defined(WIN32)
  	flags |= O_BINARY;
  #endif
  	if ((db->pagf = open(pagname, flags, mode)) > -1) {
  	    if ( sdbm_fd_lock(db->pagf, sdbm_rdonly(db)) > -1 ) {
  		if ((db->dirf = open(dirname, flags, mode)) > -1) {
  /*
   * need the dirfile size to establish max bit number.
   */
  			if (fstat(db->dirf, &dstat) == 0) {
  /*
   * zero size: either a fresh database, or one with a single,
   * unsplit data page: dirpage is all zeros.
   */
  				db->dirbno = (!dstat.st_size) ? 0 : -1;
  				db->pagbno = -1;
  				db->maxbno = dstat.st_size * BYTESIZ;
  
  				(void) memset(db->pagbuf, 0, PBLKSIZ);
  				(void) memset(db->dirbuf, 0, DBLKSIZ);
  			/*
  			 * success
  			 */
  				return db;
  			}
  			(void) close(db->dirf);
  		}
  		(void) sdbm_fd_unlock(db->pagf);
  	    }
  	    (void) close(db->pagf);
  	}
  	free((char *) db);
  	return (DBM *) NULL;
  }
  
  void
  sdbm_close(db)
  register DBM *db;
  {
  	if (db == NULL)
  		errno = EINVAL;
  	else {
  		(void) close(db->dirf);
  		(void) sdbm_fd_unlock(db->pagf);
  		(void) close(db->pagf);
  		free((char *) db);
  	}
  }
  
  datum
  sdbm_fetch(db, key)
  register DBM *db;
  datum key;
  {
  	if (db == NULL || bad(key))
  		return errno = EINVAL, nullitem;
  
  	if (getpage(db, exhash(key)))
  		return getpair(db->pagbuf, key);
  
  	return ioerr(db), nullitem;
  }
  
  int
  sdbm_delete(db, key)
  register DBM *db;
  datum key;
  {
  	if (db == NULL || bad(key))
  		return errno = EINVAL, -1;
  	if (sdbm_rdonly(db))
  		return errno = EPERM, -1;
  
  	if (getpage(db, exhash(key))) {
  		if (!delpair(db->pagbuf, key))
  			return -1;
  /*
   * update the page file
   */
  		if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
  		    || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
  			return ioerr(db), -1;
  
  		return 0;
  	}
  
  	return ioerr(db), -1;
  }
  
  int
  sdbm_store(db, key, val, flags)
  register DBM *db;
  datum key;
  datum val;
  int flags;
  {
  	int need;
  	register long hash;
  
  	if (db == NULL || bad(key))
  		return errno = EINVAL, -1;
  	if (sdbm_rdonly(db))
  		return errno = EPERM, -1;
  
  	need = key.dsize + val.dsize;
  /*
   * is the pair too big (or too small) for this database ??
   */
  	if (need < 0 || need > PAIRMAX)
  		return errno = EINVAL, -1;
  
  	if (getpage(db, (hash = exhash(key)))) {
  /*
   * if we need to replace, delete the key/data pair
   * first. If it is not there, ignore.
   */
  		if (flags == DBM_REPLACE)
  			(void) delpair(db->pagbuf, key);
  #ifdef SEEDUPS
  		else if (duppair(db->pagbuf, key))
  			return 1;
  #endif
  /*
   * if we do not have enough room, we have to split.
   */
  		if (!fitpair(db->pagbuf, need))
  			if (!makroom(db, hash, need))
  				return ioerr(db), -1;
  /*
   * we have enough room or split is successful. insert the key,
   * and update the page file.
   */
  		(void) putpair(db->pagbuf, key, val);
  
  		if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
  		    || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
  			return ioerr(db), -1;
  	/*
  	 * success
  	 */
  		return 0;
  	}
  
  	return ioerr(db), -1;
  }
  
  /*
   * makroom - make room by splitting the overfull page
   * this routine will attempt to make room for SPLTMAX times before
   * giving up.
   */
  static int
  makroom(db, hash, need)
  register DBM *db;
  long hash;
  int need;
  {
  	long newp;
  	char twin[PBLKSIZ];
  	char *pag = db->pagbuf;
  	char *new = twin;
  	register int smax = SPLTMAX;
  
  	do {
  /*
   * split the current page
   */
  		(void) splpage(pag, new, db->hmask + 1);
  /*
   * address of the new page
   */
  		newp = (hash & db->hmask) | (db->hmask + 1);
  
  /*
   * write delay, read avoidence/cache shuffle:
   * select the page for incoming pair: if key is to go to the new page,
   * write out the previous one, and copy the new one over, thus making
   * it the current page. If not, simply write the new page, and we are
   * still looking at the page of interest. current page is not updated
   * here, as sdbm_store will do so, after it inserts the incoming pair.
   */
  		if (hash & (db->hmask + 1)) {
  			if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
  			    || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
  				return 0;
  			db->pagbno = newp;
  			(void) memcpy(pag, new, PBLKSIZ);
  		}
  		else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
  			 || write(db->pagf, new, PBLKSIZ) < 0)
  			return 0;
  
  		if (!setdbit(db, db->curbit))
  			return 0;
  /*
   * see if we have enough room now
   */
  		if (fitpair(pag, need))
  			return 1;
  /*
   * try again... update curbit and hmask as getpage would have
   * done. because of our update of the current page, we do not
   * need to read in anything. BUT we have to write the current
   * [deferred] page out, as the window of failure is too great.
   */
  		db->curbit = 2 * db->curbit +
  			((hash & (db->hmask + 1)) ? 2 : 1);
  		db->hmask |= db->hmask + 1;
  
  		if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
  		    || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
  			return 0;
  
  	} while (--smax);
  /*
   * if we are here, this is real bad news. After SPLTMAX splits,
   * we still cannot fit the key. say goodnight.
   */
  #ifdef BADMESS
  	(void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
  #endif
  	return 0;
  
  }
  
  /*
   * the following two routines will break if
   * deletions aren't taken into account. (ndbm bug)
   */
  datum
  sdbm_firstkey(db)
  register DBM *db;
  {
  	if (db == NULL)
  		return errno = EINVAL, nullitem;
  /*
   * start at page 0
   */
  	if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0
  	    || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
  		return ioerr(db), nullitem;
  	db->pagbno = 0;
  	db->blkptr = 0;
  	db->keyptr = 0;
  
  	return getnext(db);
  }
  
  datum
  sdbm_nextkey(db)
  register DBM *db;
  {
  	if (db == NULL)
  		return errno = EINVAL, nullitem;
  	return getnext(db);
  }
  
  /*
   * all important binary trie traversal
   */
  static int
  getpage(db, hash)
  register DBM *db;
  register long hash;
  {
  	register int hbit;
  	register long dbit;
  	register long pagb;
  
  	dbit = 0;
  	hbit = 0;
  	while (dbit < db->maxbno && getdbit(db, dbit))
  		dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
  
  	debug(("dbit: %d...", dbit));
  
  	db->curbit = dbit;
  	db->hmask = masks[hbit];
  
  	pagb = hash & db->hmask;
  /*
   * see if the block we need is already in memory.
   * note: this lookaside cache has about 10% hit rate.
   */
  	if (pagb != db->pagbno) { 
  /*
   * note: here, we assume a "hole" is read as 0s.
   * if not, must zero pagbuf first.
   */
  		if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
  		    || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
  			return 0;
  		if (!chkpage(db->pagbuf))
  			return 0;
  		db->pagbno = pagb;
  
  		debug(("pag read: %d\n", pagb));
  	}
  	return 1;
  }
  
  static int
  getdbit(db, dbit)
  register DBM *db;
  register long dbit;
  {
  	register long c;
  	register long dirb;
  
  	c = dbit / BYTESIZ;
  	dirb = c / DBLKSIZ;
  
  	if (dirb != db->dirbno) {
  		if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
  		    || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
  			return 0;
  		db->dirbno = dirb;
  
  		debug(("dir read: %d\n", dirb));
  	}
  
  	return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
  }
  
  static int
  setdbit(db, dbit)
  register DBM *db;
  register long dbit;
  {
  	register long c;
  	register long dirb;
  
  	c = dbit / BYTESIZ;
  	dirb = c / DBLKSIZ;
  
  	if (dirb != db->dirbno) {
  		if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
  		    || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
  			return 0;
  		db->dirbno = dirb;
  
  		debug(("dir read: %d\n", dirb));
  	}
  
  	db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
  
  	if (dbit >= db->maxbno)
  		db->maxbno += DBLKSIZ * BYTESIZ;
  
  	if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
  	    || write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
  		return 0;
  
  	return 1;
  }
  
  /*
   * getnext - get the next key in the page, and if done with
   * the page, try the next page in sequence
   */
  static datum
  getnext(db)
  register DBM *db;
  {
  	datum key;
  
  	for (;;) {
  		db->keyptr++;
  		key = getnkey(db->pagbuf, db->keyptr);
  		if (key.dptr != NULL)
  			return key;
  /*
   * we either run out, or there is nothing on this page..
   * try the next one... If we lost our position on the
   * file, we will have to seek.
   */
  		db->keyptr = 0;
  		if (db->pagbno != db->blkptr++)
  			if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
  				break;
  		db->pagbno = db->blkptr;
  		if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
  			break;
  		if (!chkpage(db->pagbuf))
  			break;
  	}
  
  	return ioerr(db), nullitem;
  }
  
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm.dsp
  
  Index: sdbm.dsp
  ===================================================================
  # Microsoft Developer Studio Project File - Name="sdbm" - Package Owner=<4>
  # Microsoft Developer Studio Generated Build File, Format Version 5.00
  # ** DO NOT EDIT **
  
  # TARGTYPE "Win32 (x86) Static Library" 0x0104
  
  CFG=sdbm - Win32 Debug
  !MESSAGE This is not a valid makefile. To build this project using NMAKE,
  !MESSAGE use the Export Makefile command and run
  !MESSAGE 
  !MESSAGE NMAKE /f "sdbm.mak".
  !MESSAGE 
  !MESSAGE You can specify a configuration when running NMAKE
  !MESSAGE by defining the macro CFG on the command line. For example:
  !MESSAGE 
  !MESSAGE NMAKE /f "sdbm.mak" CFG="sdbm - Win32 Debug"
  !MESSAGE 
  !MESSAGE Possible choices for configuration are:
  !MESSAGE 
  !MESSAGE "sdbm - Win32 Release" (based on "Win32 (x86) Static Library")
  !MESSAGE "sdbm - Win32 Debug" (based on "Win32 (x86) Static Library")
  !MESSAGE 
  
  # Begin Project
  # PROP Scc_ProjName ""
  # PROP Scc_LocalPath ""
  CPP=cl.exe
  
  !IF  "$(CFG)" == "sdbm - Win32 Release"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 0
  # PROP BASE Output_Dir "Release"
  # PROP BASE Intermediate_Dir "Release"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 0
  # PROP Output_Dir "Release"
  # PROP Intermediate_Dir "Release"
  # PROP Target_Dir ""
  RSC=rc.exe
  # ADD BASE RSC /l 0x409
  # ADD RSC /l 0x409
  # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
  # ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /I "..\..\os\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LIB32=link.exe -lib
  # ADD BASE LIB32 /nologo
  # ADD LIB32 /nologo
  
  !ELSEIF  "$(CFG)" == "sdbm - Win32 Debug"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 1
  # PROP BASE Output_Dir "Debug"
  # PROP BASE Intermediate_Dir "Debug"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 1
  # PROP Output_Dir "Debug"
  # PROP Intermediate_Dir "Debug"
  # PROP Target_Dir ""
  RSC=rc.exe
  # ADD BASE RSC /l 0x409
  # ADD RSC /l 0x409
  # ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
  # ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "SHARED_MODULE" /FD /c
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LIB32=link.exe -lib
  # ADD BASE LIB32 /nologo
  # ADD LIB32 /nologo
  
  !ENDIF 
  
  # Begin Target
  
  # Name "sdbm - Win32 Release"
  # Name "sdbm - Win32 Debug"
  # Begin Source File
  
  SOURCE=.\sdbm.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\sdbm.h
  # End Source File
  # Begin Source File
  
  SOURCE=.\sdbm_hash.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\sdbm_lock.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\sdbm_pair.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\sdbm_pair.h
  # End Source File
  # Begin Source File
  
  SOURCE=.\sdbm_tune.h
  # End Source File
  # End Target
  # End Project
  
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm.h
  
  Index: sdbm.h
  ===================================================================
  /*
   * sdbm - ndbm work-alike hashed database library
   * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
   * author: oz@nexus.yorku.ca
   * status: public domain. 
   */
  /* increase the block/page size and what can be inserted */
  #if 1
  #define DBLKSIZ 16384
  #define PBLKSIZ 8192
  #define PAIRMAX 8008			/* arbitrary on PBLKSIZ-N */
  #else
  #define DBLKSIZ 4096
  #define PBLKSIZ 1024
  #define PAIRMAX 1008			/* arbitrary on PBLKSIZ-N */
  #endif
  #define SPLTMAX	10			/* maximum allowed splits */
  					/* for a single insertion */
  #define DIRFEXT	".dir"
  #define PAGFEXT	".pag"
  
  typedef struct {
  	int dirf;		       /* directory file descriptor */
  	int pagf;		       /* page file descriptor */
  	int flags;		       /* status/error flags, see below */
  	long maxbno;		       /* size of dirfile in bits */
  	long curbit;		       /* current bit number */
  	long hmask;		       /* current hash mask */
  	long blkptr;		       /* current block for nextkey */
  	int keyptr;		       /* current key for nextkey */
  	long blkno;		       /* current page to read/write */
  	long pagbno;		       /* current page in pagbuf */
  	char pagbuf[PBLKSIZ];	       /* page file block buffer */
  	long dirbno;		       /* current block in dirbuf */
  	char dirbuf[DBLKSIZ];	       /* directory file block buffer */
  } DBM;
  
  #define DBM_RDONLY	0x1	       /* data base open read-only */
  #define DBM_IOERR	0x2	       /* data base I/O error */
  
  /*
   * utility macros
   */
  #define sdbm_rdonly(db)		((db)->flags & DBM_RDONLY)
  #define sdbm_error(db)		((db)->flags & DBM_IOERR)
  
  #define sdbm_clearerr(db)	((db)->flags &= ~DBM_IOERR)  /* ouch */
  
  #define sdbm_dirfno(db)	((db)->dirf)
  #define sdbm_pagfno(db)	((db)->pagf)
  
  typedef struct {
  	char *dptr;
  	int dsize;
  } datum;
  
  extern datum nullitem;
  
  #ifdef __STDC__
  #define proto(p) p
  #else
  #define proto(p) ()
  #endif
  
  /*
   * flags to sdbm_store
   */
  #define DBM_INSERT	0
  #define DBM_REPLACE	1
  
  /*
   * ndbm interface
   */
  extern DBM *sdbm_open proto((char *, int, int));
  extern void sdbm_close proto((DBM *));
  extern datum sdbm_fetch proto((DBM *, datum));
  extern int sdbm_delete proto((DBM *, datum));
  extern int sdbm_store proto((DBM *, datum, datum, int));
  extern datum sdbm_firstkey proto((DBM *));
  extern datum sdbm_nextkey proto((DBM *));
  
  /*
   * other
   */
  extern DBM *sdbm_prep proto((char *, char *, int, int));
  extern long sdbm_hash proto((char *, int));
  
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm.mak
  
  Index: sdbm.mak
  ===================================================================
  # Microsoft Developer Studio Generated NMAKE File, Based on sdbm.dsp
  !IF "$(CFG)" == ""
  CFG=sdbm - Win32 Release
  !MESSAGE No configuration specified. Defaulting to sdbm - Win32 Release.
  !ENDIF 
  
  !IF "$(CFG)" != "sdbm - Win32 Release" && "$(CFG)" != "sdbm - Win32 Debug"
  !MESSAGE Invalid configuration "$(CFG)" specified.
  !MESSAGE You can specify a configuration when running NMAKE
  !MESSAGE by defining the macro CFG on the command line. For example:
  !MESSAGE 
  !MESSAGE NMAKE /f "sdbm.mak" CFG="sdbm - Win32 Debug"
  !MESSAGE 
  !MESSAGE Possible choices for configuration are:
  !MESSAGE 
  !MESSAGE "sdbm - Win32 Release" (based on "Win32 (x86) Static Library")
  !MESSAGE "sdbm - Win32 Debug" (based on "Win32 (x86) Static Library")
  !MESSAGE 
  !ERROR An invalid configuration is specified.
  !ENDIF 
  
  !IF "$(OS)" == "Windows_NT"
  NULL=
  !ELSE 
  NULL=nul
  !ENDIF 
  
  !IF  "$(CFG)" == "sdbm - Win32 Release"
  
  OUTDIR=.\Release
  INTDIR=.\Release
  # Begin Custom Macros
  OutDir=.\Release
  # End Custom Macros
  
  ALL : "$(OUTDIR)\sdbm.lib"
  
  
  CLEAN :
  	-@erase "$(INTDIR)\sdbm.obj"
  	-@erase "$(INTDIR)\sdbm_hash.obj"
  	-@erase "$(INTDIR)\sdbm_lock.obj"
  	-@erase "$(INTDIR)\sdbm_pair.obj"
  	-@erase "$(INTDIR)\vc60.idb"
  	-@erase "$(OUTDIR)\sdbm.lib"
  
  "$(OUTDIR)" :
      if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
  
  CPP=cl.exe
  CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "\apache-1.3\src\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fp"$(INTDIR)\sdbm.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
  
  .c{$(INTDIR)}.obj::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  .cpp{$(INTDIR)}.obj::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  .cxx{$(INTDIR)}.obj::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  .c{$(INTDIR)}.sbr::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  .cpp{$(INTDIR)}.sbr::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  .cxx{$(INTDIR)}.sbr::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  RSC=rc.exe
  BSC32=bscmake.exe
  BSC32_FLAGS=/nologo /o"$(OUTDIR)\sdbm.bsc" 
  BSC32_SBRS= \
  	
  LIB32=link.exe -lib
  LIB32_FLAGS=/nologo /out:"$(OUTDIR)\sdbm.lib" 
  LIB32_OBJS= \
  	"$(INTDIR)\sdbm.obj" \
  	"$(INTDIR)\sdbm_hash.obj" \
  	"$(INTDIR)\sdbm_lock.obj" \
  	"$(INTDIR)\sdbm_pair.obj"
  
  "$(OUTDIR)\sdbm.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
      $(LIB32) @<<
    $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
  <<
  
  !ELSEIF  "$(CFG)" == "sdbm - Win32 Debug"
  
  OUTDIR=.\Debug
  INTDIR=.\Debug
  # Begin Custom Macros
  OutDir=.\Debug
  # End Custom Macros
  
  ALL : "$(OUTDIR)\sdbm.lib"
  
  
  CLEAN :
  	-@erase "$(INTDIR)\sdbm.obj"
  	-@erase "$(INTDIR)\sdbm_hash.obj"
  	-@erase "$(INTDIR)\sdbm_lock.obj"
  	-@erase "$(INTDIR)\sdbm_pair.obj"
  	-@erase "$(INTDIR)\vc60.idb"
  	-@erase "$(OUTDIR)\sdbm.lib"
  
  "$(OUTDIR)" :
      if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
  
  CPP=cl.exe
  CPP_PROJ=/nologo /MDd /W3 /GX /Z7 /Od /I "\apache-1.3\src\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\sdbm.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
  
  .c{$(INTDIR)}.obj::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  .cpp{$(INTDIR)}.obj::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  .cxx{$(INTDIR)}.obj::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  .c{$(INTDIR)}.sbr::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  .cpp{$(INTDIR)}.sbr::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  .cxx{$(INTDIR)}.sbr::
     $(CPP) @<<
     $(CPP_PROJ) $< 
  <<
  
  RSC=rc.exe
  BSC32=bscmake.exe
  BSC32_FLAGS=/nologo /o"$(OUTDIR)\sdbm.bsc" 
  BSC32_SBRS= \
  	
  LIB32=link.exe -lib
  LIB32_FLAGS=/nologo /out:"$(OUTDIR)\sdbm.lib" /nodefaultlib 
  LIB32_OBJS= \
  	"$(INTDIR)\sdbm.obj" \
  	"$(INTDIR)\sdbm_hash.obj" \
  	"$(INTDIR)\sdbm_lock.obj" \
  	"$(INTDIR)\sdbm_pair.obj"
  
  "$(OUTDIR)\sdbm.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
      $(LIB32) @<<
    $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
  <<
  
  !ENDIF 
  
  
  !IF "$(CFG)" == "sdbm - Win32 Release" || "$(CFG)" == "sdbm - Win32 Debug"
  SOURCE=.\sdbm.c
  
  "$(INTDIR)\sdbm.obj" : $(SOURCE) "$(INTDIR)"
  
  
  SOURCE=.\sdbm_hash.c
  
  "$(INTDIR)\sdbm_hash.obj" : $(SOURCE) "$(INTDIR)"
  
  
  SOURCE=.\sdbm_lock.c
  
  "$(INTDIR)\sdbm_lock.obj" : $(SOURCE) "$(INTDIR)"
  
  
  SOURCE=.\sdbm_pair.c
  
  "$(INTDIR)\sdbm_pair.obj" : $(SOURCE) "$(INTDIR)"
  
  
  
  !ENDIF 
  
  
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm.ncb
  
  Index: sdbm.ncb
  ===================================================================
  Microsoft C/C++ program database 2.00
  
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm.opt
  
  	<<Binary file>>
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm_hash.c
  
  Index: sdbm_hash.c
  ===================================================================
  /*
   * sdbm - ndbm work-alike hashed database library
   * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
   * author: oz@nexus.yorku.ca
   * status: public domain. keep it that way.
   *
   * hashing routine
   */
  
  #include "sdbm.h"
  /*
   * polynomial conversion ignoring overflows
   * [this seems to work remarkably well, in fact better
   * then the ndbm hash function. Replace at your own risk]
   * use: 65599	nice.
   *      65587   even better. 
   */
  long
  sdbm_hash(str, len)
  register char *str;
  register int len;
  {
  	register unsigned long n = 0;
  
  #define DUFF	/* go ahead and use the loop-unrolled version */
  #ifdef DUFF
  
  #define HASHC	n = *str++ + 65599 * n
  
  	if (len > 0) {
  		register int loop = (len + 8 - 1) >> 3;
  
  		switch(len & (8 - 1)) {
  		case 0:	do {
  			HASHC;	case 7:	HASHC;
  		case 6:	HASHC;	case 5:	HASHC;
  		case 4:	HASHC;	case 3:	HASHC;
  		case 2:	HASHC;	case 1:	HASHC;
  			} while (--loop);
  		}
  
  	}
  #else
  	while (len--)
  		n = *str++ + 65599 * n;
  #endif
  	return n;
  }
  
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm_lock.c
  
  Index: sdbm_lock.c
  ===================================================================
  /*
  ** File locking
  **
  ** Snarfed from mod_rewrite.c. Munged up for our use.
  */
  
  #include "ap_config.h"
  
      /* The locking support:
       * Try to determine whether we should use fcntl() or flock().
       * Would be better ap_config.h could provide this... :-(
       */
  #if defined(USE_FCNTL_SERIALIZED_ACCEPT)
  #define USE_FCNTL 1
  #include <fcntl.h>
  #endif
  #if defined(USE_FLOCK_SERIALIZED_ACCEPT)
  #define USE_FLOCK 1
  #include <sys/file.h>
  #endif
  #if !defined(USE_FCNTL) && !defined(USE_FLOCK)
  #define USE_FLOCK 1
  #if !defined(MPE) && !defined(WIN32)
  #include <sys/file.h>
  #endif
  #ifndef LOCK_UN
  #undef USE_FLOCK
  #define USE_FCNTL 1
  #include <fcntl.h>
  #endif
  #endif
  #ifdef AIX
  #undef USE_FLOCK
  #define USE_FCNTL 1
  #include <fcntl.h>
  #endif
  #ifdef WIN32
  #undef USE_FCNTL
  #define USE_LOCKING
  #include <sys/locking.h>
  #endif
  
  
  #ifdef USE_FCNTL
  /* ugly interface requires this structure to be "live" for a while */
  static struct flock   lock_it;
  static struct flock unlock_it;
  #endif
  
  /* NOTE: this function blocks until it acquires the lock */
  int sdbm_fd_lock(int fd, int readonly)
  {
      int rc;
  
  #ifdef USE_FCNTL
      lock_it.l_whence = SEEK_SET; /* from current point */
      lock_it.l_start  = 0;        /* -"- */
      lock_it.l_len    = 0;        /* until end of file */
      lock_it.l_type   = readonly ? F_RDLCK : F_WRLCK;  /* set lock type */
      lock_it.l_pid    = 0;        /* pid not actually interesting */
  
      while (   ((rc = fcntl(fd, F_SETLKW, &lock_it)) < 0)
                && (errno == EINTR)                               ) {
          continue;
      }
  #endif
  #ifdef USE_FLOCK
      while (   ((rc = flock(fd, readonly ? LOCK_SH : LOCK_EX)) < 0)
                && (errno == EINTR)               ) {
          continue;
      }
  #endif
  #ifdef USE_LOCKING
      /* ### this doesn't allow simultaneous reads! */
      /* ### this doesn't block forever */
      /* Lock the first byte */
      lseek(fd, 0, SEEK_SET);
      rc = _locking(fd, _LK_LOCK, 1);
  #endif
  
      return rc;
  }
  
  int sdbm_fd_unlock(int fd)
  {
      int rc;
  
  #ifdef USE_FCNTL
      unlock_it.l_whence = SEEK_SET; /* from current point */
      unlock_it.l_start  = 0;        /* -"- */
      unlock_it.l_len    = 0;        /* until end of file */
      unlock_it.l_type   = F_UNLCK;  /* unlock */
      unlock_it.l_pid    = 0;        /* pid not actually interesting */
  
      rc = fcntl(fd, F_SETLKW, &unlock_it);
  #endif
  #ifdef USE_FLOCK
      rc = flock(fd, LOCK_UN);
  #endif
  #ifdef USE_LOCKING
      lseek(fd, 0, SEEK_SET);
      rc = _locking(fd, _LK_UNLCK, 1);
  #endif
  
      return rc;
  }
  
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm_pair.c
  
  Index: sdbm_pair.c
  ===================================================================
  /*
   * sdbm - ndbm work-alike hashed database library
   * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
   * author: oz@nexus.yorku.ca
   * status: public domain.
   *
   * page-level routines
   */
  
  #include "sdbm.h"
  #include "sdbm_tune.h"
  #include "sdbm_pair.h"
  
  #include <string.h>	/* for memset() */
  
  
  #define exhash(item)	sdbm_hash((item).dptr, (item).dsize)
  
  /* 
   * forward 
   */
  static int seepair proto((char *, int, char *, int));
  
  /*
   * page format:
   *	+------------------------------+
   * ino	| n | keyoff | datoff | keyoff |
   * 	+------------+--------+--------+
   *	| datoff | - - - ---->	       |
   *	+--------+---------------------+
   *	|	 F R E E A R E A       |
   *	+--------------+---------------+
   *	|  <---- - - - | data          |
   *	+--------+-----+----+----------+
   *	|  key   | data     | key      |
   *	+--------+----------+----------+
   *
   * calculating the offsets for free area:  if the number
   * of entries (ino[0]) is zero, the offset to the END of
   * the free area is the block size. Otherwise, it is the
   * nth (ino[ino[0]]) entry's offset.
   */
  
  int
  fitpair(pag, need)
  char *pag;
  int need;
  {
  	register int n;
  	register int off;
  	register int avail;
  	register short *ino = (short *) pag;
  
  	off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
  	avail = off - (n + 1) * sizeof(short);
  	need += 2 * sizeof(short);
  
  	debug(("avail %d need %d\n", avail, need));
  
  	return need <= avail;
  }
  
  void
  putpair(pag, key, val)
  char *pag;
  datum key;
  datum val;
  {
  	register int n;
  	register int off;
  	register short *ino = (short *) pag;
  
  	off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
  /*
   * enter the key first
   */
  	off -= key.dsize;
  	(void) memcpy(pag + off, key.dptr, key.dsize);
  	ino[n + 1] = off;
  /*
   * now the data
   */
  	off -= val.dsize;
  	(void) memcpy(pag + off, val.dptr, val.dsize);
  	ino[n + 2] = off;
  /*
   * adjust item count
   */
  	ino[0] += 2;
  }
  
  datum
  getpair(pag, key)
  char *pag;
  datum key;
  {
  	register int i;
  	register int n;
  	datum val;
  	register short *ino = (short *) pag;
  
  	if ((n = ino[0]) == 0)
  		return nullitem;
  
  	if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
  		return nullitem;
  
  	val.dptr = pag + ino[i + 1];
  	val.dsize = ino[i] - ino[i + 1];
  	return val;
  }
  
  #ifdef SEEDUPS
  int
  duppair(pag, key)
  char *pag;
  datum key;
  {
  	register short *ino = (short *) pag;
  	return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
  }
  #endif
  
  datum
  getnkey(pag, num)
  char *pag;
  int num;
  {
  	datum key;
  	register int off;
  	register short *ino = (short *) pag;
  
  	num = num * 2 - 1;
  	if (ino[0] == 0 || num > ino[0])
  		return nullitem;
  
  	off = (num > 1) ? ino[num - 1] : PBLKSIZ;
  
  	key.dptr = pag + ino[num];
  	key.dsize = off - ino[num];
  
  	return key;
  }
  
  int
  delpair(pag, key)
  char *pag;
  datum key;
  {
  	register int n;
  	register int i;
  	register short *ino = (short *) pag;
  
  	if ((n = ino[0]) == 0)
  		return 0;
  
  	if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
  		return 0;
  /*
   * found the key. if it is the last entry
   * [i.e. i == n - 1] we just adjust the entry count.
   * hard case: move all data down onto the deleted pair,
   * shift offsets onto deleted offsets, and adjust them.
   * [note: 0 < i < n]
   */
  	if (i < n - 1) {
  		register int m;
  		register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
  		register char *src = pag + ino[i + 1];
  		register int   zoo = dst - src;
  
  		debug(("free-up %d ", zoo));
  /*
   * shift data/keys down
   */
  		m = ino[i + 1] - ino[n];
  
  #undef DUFF	/* just use memmove. it should be plenty fast. */
  #ifdef DUFF
  #define MOVB 	*--dst = *--src
  
  		if (m > 0) {
  			register int loop = (m + 8 - 1) >> 3;
  
  			switch (m & (8 - 1)) {
  			case 0:	do {
  				MOVB;	case 7:	MOVB;
  			case 6:	MOVB;	case 5:	MOVB;
  			case 4:	MOVB;	case 3:	MOVB;
  			case 2:	MOVB;	case 1:	MOVB;
  				} while (--loop);
  			}
  		}
  #else
  		dst -= m;
  		src -= m;
  		memmove(dst, src, m);
  #endif
  
  /*
   * adjust offset index up
   */
  		while (i < n - 1) {
  			ino[i] = ino[i + 2] + zoo;
  			i++;
  		}
  	}
  	ino[0] -= 2;
  	return 1;
  }
  
  /*
   * search for the key in the page.
   * return offset index in the range 0 < i < n.
   * return 0 if not found.
   */
  static int
  seepair(pag, n, key, siz)
  char *pag;
  register int n;
  register char *key;
  register int siz;
  {
  	register int i;
  	register int off = PBLKSIZ;
  	register short *ino = (short *) pag;
  
  	for (i = 1; i < n; i += 2) {
  		if (siz == off - ino[i] &&
  		    memcmp(key, pag + ino[i], siz) == 0)
  			return i;
  		off = ino[i + 1];
  	}
  	return 0;
  }
  
  void
  splpage(pag, new, sbit)
  char *pag;
  char *new;
  long sbit;
  {
  	datum key;
  	datum val;
  
  	register int n;
  	register int off = PBLKSIZ;
  	char cur[PBLKSIZ];
  	register short *ino = (short *) cur;
  
  	(void) memcpy(cur, pag, PBLKSIZ);
  	(void) memset(pag, 0, PBLKSIZ);
  	(void) memset(new, 0, PBLKSIZ);
  
  	n = ino[0];
  	for (ino++; n > 0; ino += 2) {
  		key.dptr = cur + ino[0]; 
  		key.dsize = off - ino[0];
  		val.dptr = cur + ino[1];
  		val.dsize = ino[0] - ino[1];
  /*
   * select the page pointer (by looking at sbit) and insert
   */
  		(void) putpair((exhash(key) & sbit) ? new : pag, key, val);
  
  		off = ino[1];
  		n -= 2;
  	}
  
  	debug(("%d split %d/%d\n", ((short *) cur)[0] / 2, 
  	       ((short *) new)[0] / 2,
  	       ((short *) pag)[0] / 2));
  }
  
  /*
   * check page sanity: 
   * number of entries should be something
   * reasonable, and all offsets in the index should be in order.
   * this could be made more rigorous.
   */
  int
  chkpage(pag)
  char *pag;
  {
  	register int n;
  	register int off;
  	register short *ino = (short *) pag;
  
  	if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
  		return 0;
  
  	if (n > 0) {
  		off = PBLKSIZ;
  		for (ino++; n > 0; ino += 2) {
  			if (ino[0] > off || ino[1] > off ||
  			    ino[1] > ino[0])
  				return 0;
  			off = ino[1];
  			n -= 2;
  		}
  	}
  	return 1;
  }
  
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm_pair.h
  
  Index: sdbm_pair.h
  ===================================================================
  /* Mini EMBED (pair.c) */
  #define chkpage sdbm__chkpage
  #define delpair sdbm__delpair
  #define duppair sdbm__duppair
  #define fitpair sdbm__fitpair
  #define getnkey sdbm__getnkey
  #define getpair sdbm__getpair
  #define putpair sdbm__putpair
  #define splpage sdbm__splpage
  
  extern int fitpair proto((char *, int));
  extern void  putpair proto((char *, datum, datum));
  extern datum	getpair proto((char *, datum));
  extern int  delpair proto((char *, datum));
  extern int  chkpage proto((char *));
  extern datum getnkey proto((char *, int));
  extern void splpage proto((char *, char *, long));
  #ifdef SEEDUPS
  extern int duppair proto((char *, datum));
  #endif
  
  
  
  1.1                  apache-1.3/src/lib/sdbm/sdbm_tune.h
  
  Index: sdbm_tune.h
  ===================================================================
  /*
   * sdbm - ndbm work-alike hashed database library
   * tuning and portability constructs [not nearly enough]
   * author: oz@nexus.yorku.ca
   */
  
  #define BYTESIZ		8
  
  /*
   * important tuning parms (hah)
   */
  
  #define SEEDUPS			/* always detect duplicates */
  #define BADMESS			/* generate a message for worst case:
  				   cannot make room after SPLTMAX splits */
  /*
   * misc
   */
  #ifdef DEBUG
  #define debug(x)	printf x
  #else
  #define debug(x)
  #endif
  
  int sdbm_fd_lock(int fd, int readonly);
  int sdbm_fd_unlock(int fd);