BSD 4_4 release
[unix-history] / usr / src / old / libndbm / ndbm.c
index 5a8ca60..1734fe4 100644 (file)
@@ -1,32 +1,36 @@
-#ifndef lint
-static char sccsid[] = "@(#)ndbm.c     4.1 (Berkeley) %G%";
-#endif
+/*-
+ * Copyright (c) 1983 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This module is believed to contain source code proprietary to AT&T.
+ * Use and redistribution is subject to the Berkeley Software License
+ * Agreement and your Software Agreement with AT&T (Western Electric).
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ndbm.c     5.7 (Berkeley) 4/22/91";
+#endif /* LIBC_SCCS and not lint */
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/file.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/file.h>
+#include <stdio.h>
 #include <errno.h>
 #include <errno.h>
-#include <ndbm.h>
+#include "ndbm.h"
 
 
-#define NULL    (char *)0
 #define BYTESIZ 8
 #define BYTESIZ 8
+#undef setbit
 
 
-static  datum firsthash();
-static  dbm_access();
-static  getbit();
-static  setbit();
-static  datum makdatum();
-static  cmpdatum();
-static  long hashinc();
-static  long dcalchash();
-static  delitem();
-static  additem();
-static  chkblk();
-extern  int errno;
+static datum makdatum();
+static long hashinc();
+static long dcalchash();
+static int additem(), delitem(), finddatum(), getbit();
+static void dbm_access(), setbit();
+extern int errno;
 
 DBM *
 
 DBM *
-ndbmopen(file, flags, mode)
-       char *file;
+dbm_open(file, flags, mode)
+       const char *file;
        int flags, mode;
 {
        struct stat statb;
        int flags, mode;
 {
        struct stat statb;
@@ -36,263 +40,253 @@ ndbmopen(file, flags, mode)
                errno = ENOMEM;
                return ((DBM *)0);
        }
                errno = ENOMEM;
                return ((DBM *)0);
        }
+       db->dbm_flags = (flags & 03) == O_RDONLY ? _DBM_RDONLY : 0;
        if ((flags & 03) == O_WRONLY)
                flags = (flags & ~03) | O_RDWR;
        if ((flags & 03) == O_WRONLY)
                flags = (flags & ~03) | O_RDWR;
-       db->db_flags = 0;
-       strcpy(db->db_pagbuf, file);
-       strcat(db->db_pagbuf, ".pag");
-       db->db_pagf = open(db->db_pagbuf, flags, mode);
-       if (db->db_pagf < 0)
+       strcpy(db->dbm_pagbuf, file);
+       strcat(db->dbm_pagbuf, ".pag");
+       db->dbm_pagf = open(db->dbm_pagbuf, flags, mode);
+       if (db->dbm_pagf < 0)
                goto bad;
                goto bad;
-       strcpy(db->db_pagbuf, file);
-       strcat(db->db_pagbuf, ".dir");
-       db->db_dirf = open(db->db_pagbuf, flags, mode);
-       if (db->db_dirf < 0)
+       strcpy(db->dbm_pagbuf, file);
+       strcat(db->dbm_pagbuf, ".dir");
+       db->dbm_dirf = open(db->dbm_pagbuf, flags, mode);
+       if (db->dbm_dirf < 0)
                goto bad1;
                goto bad1;
-       fstat(db->db_dirf, &statb);
-       db->db_maxbno = statb.st_size*BYTESIZ-1;
-       db->db_pagbno = db->db_dirbno = -1;
+       fstat(db->dbm_dirf, &statb);
+       db->dbm_maxbno = statb.st_size*BYTESIZ-1;
+       db->dbm_pagbno = db->dbm_dirbno = -1;
        return (db);
 bad1:
        return (db);
 bad1:
-       (void) close(db->db_pagf);
+       (void) close(db->dbm_pagf);
 bad:
        free((char *)db);
        return ((DBM *)0);
 }
 
 void
 bad:
        free((char *)db);
        return ((DBM *)0);
 }
 
 void
-ndbmclose(db)
+dbm_close(db)
        DBM *db;
 {
 
        DBM *db;
 {
 
-       (void) close(db->db_dirf);
-       (void) close(db->db_pagf);
+       (void) close(db->dbm_dirf);
+       (void) close(db->dbm_pagf);
        free((char *)db);
 }
 
 long
        free((char *)db);
 }
 
 long
-dbmforder(db, key)
+dbm_forder(db, key)
        register DBM *db;
        datum key;
 {
        long hash;
 
        hash = dcalchash(key);
        register DBM *db;
        datum key;
 {
        long hash;
 
        hash = dcalchash(key);
-       for (db->db_hmask=0;; db->db_hmask=(db->db_hmask<<1)+1) {
-               db->db_blkno = hash & db->db_hmask;
-               db->db_bitno = db->db_blkno + db->db_hmask;
+       for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) {
+               db->dbm_blkno = hash & db->dbm_hmask;
+               db->dbm_bitno = db->dbm_blkno + db->dbm_hmask;
                if (getbit(db) == 0)
                        break;
        }
                if (getbit(db) == 0)
                        break;
        }
-       return (db->db_blkno);
+       return (db->dbm_blkno);
 }
 
 datum
 }
 
 datum
-dbmfetch(db, key)
+dbm_fetch(db, key)
        register DBM *db;
        datum key;
 {
        register i;
        datum item;
 
        register DBM *db;
        datum key;
 {
        register i;
        datum item;
 
+       if (dbm_error(db))
+               goto err;
        dbm_access(db, dcalchash(key));
        dbm_access(db, dcalchash(key));
-       for (i=0;; i+=2) {
-               item = makdatum(db->db_pagbuf, i);
-               if (item.dptr == NULL)
+       if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {
+               item = makdatum(db->dbm_pagbuf, i+1);
+               if (item.dptr != NULL)
                        return (item);
                        return (item);
-               if (cmpdatum(key, item) == 0) {
-                       item = makdatum(db->db_pagbuf, i+1);
-                       if (item.dptr == NULL)
-                               printf("items not in pairs\n");
-                       return (item);
-               }
        }
        }
+err:
+       item.dptr = NULL;
+       item.dsize = 0;
+       return (item);
 }
 
 }
 
-dbmdelete(db, key)
+dbm_delete(db, key)
        register DBM *db;
        datum key;
 {
        register i;
        datum item;
 
        register DBM *db;
        datum key;
 {
        register i;
        datum item;
 
-       if (dbrdonly(db)) {
+       if (dbm_error(db))
+               return (-1);
+       if (dbm_rdonly(db)) {
                errno = EPERM;
                return (-1);
        }
        dbm_access(db, dcalchash(key));
                errno = EPERM;
                return (-1);
        }
        dbm_access(db, dcalchash(key));
-       for (i=0;; i+=2) {
-               item = makdatum(db->db_pagbuf, i);
-               if (item.dptr == NULL)
-                       return (-1);
-               if (cmpdatum(key, item) == 0) {
-                       delitem(db->db_pagbuf, i);
-                       delitem(db->db_pagbuf, i);
-                       break;
-               }
+       if ((i = finddatum(db->dbm_pagbuf, key)) < 0)
+               return (-1);
+       if (!delitem(db->dbm_pagbuf, i))
+               goto err;
+       db->dbm_pagbno = db->dbm_blkno;
+       (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET);
+       if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
+       err:
+               db->dbm_flags |= _DBM_IOERR;
+               return (-1);
        }
        }
-       (void) lseek(db->db_pagf, db->db_blkno*PBLKSIZ, L_SET);
-       (void) write(db->db_pagf, db->db_pagbuf, PBLKSIZ);
-       db->db_pagbno = db->db_blkno;
        return (0);
 }
 
        return (0);
 }
 
-dbmstore(db, key, dat)
+dbm_store(db, key, dat, replace)
        register DBM *db;
        datum key, dat;
        register DBM *db;
        datum key, dat;
+       int replace;
 {
        register i;
 {
        register i;
-       datum item;
+       datum item, item1;
        char ovfbuf[PBLKSIZ];
 
        char ovfbuf[PBLKSIZ];
 
-       if (dbrdonly(db)) {
+       if (dbm_error(db))
+               return (-1);
+       if (dbm_rdonly(db)) {
                errno = EPERM;
                return (-1);
        }
 loop:
        dbm_access(db, dcalchash(key));
                errno = EPERM;
                return (-1);
        }
 loop:
        dbm_access(db, dcalchash(key));
-       for (i=0;; i+=2) {
-               item = makdatum(db->db_pagbuf, i);
-               if (item.dptr == NULL)
-                       break;
-               if (cmpdatum(key, item) == 0) {
-                       return(0);
-/*
-                       delitem(db->db_pagbuf, i);
-                       delitem(db->db_pagbuf, i);
-                       break;
-*/
+       if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) {
+               if (!replace)
+                       return (1);
+               if (!delitem(db->dbm_pagbuf, i)) {
+                       db->dbm_flags |= _DBM_IOERR;
+                       return (-1);
                }
        }
                }
        }
-       i = additem(db->db_pagbuf, key);
-       if (i < 0)
-               goto split;
-       if (additem(db->db_pagbuf, dat) < 0) {
-               delitem(db->db_pagbuf, i);
+       if (!additem(db->dbm_pagbuf, key, dat))
                goto split;
                goto split;
+       db->dbm_pagbno = db->dbm_blkno;
+       (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET);
+       if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
+               db->dbm_flags |= _DBM_IOERR;
+               return (-1);
        }
        }
-       (void) lseek(db->db_pagf, db->db_blkno*PBLKSIZ, L_SET);
-       (void) write(db->db_pagf, db->db_pagbuf, PBLKSIZ);
-       db->db_pagbno = db->db_blkno;
        return (0);
 
 split:
        return (0);
 
 split:
-       if (key.dsize+dat.dsize+2*sizeof(short) >= PBLKSIZ) {
+       if (key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ) {
+               db->dbm_flags |= _DBM_IOERR;
                errno = ENOSPC;
                return (-1);
        }
        bzero(ovfbuf, PBLKSIZ);
        for (i=0;;) {
                errno = ENOSPC;
                return (-1);
        }
        bzero(ovfbuf, PBLKSIZ);
        for (i=0;;) {
-               item = makdatum(db->db_pagbuf, i);
+               item = makdatum(db->dbm_pagbuf, i);
                if (item.dptr == NULL)
                        break;
                if (item.dptr == NULL)
                        break;
-               if (dcalchash(item) & (db->db_hmask+1)) {
-                       additem(ovfbuf, item);
-                       delitem(db->db_pagbuf, i);
-                       item = makdatum(db->db_pagbuf, i);
-                       if (item.dptr == NULL) {
-                               printf("ndbm: split not paired\n");
+               if (dcalchash(item) & (db->dbm_hmask+1)) {
+                       item1 = makdatum(db->dbm_pagbuf, i+1);
+                       if (item1.dptr == NULL) {
+                               fprintf(stderr, "ndbm: split not paired\n");
+                               db->dbm_flags |= _DBM_IOERR;
                                break;
                        }
                                break;
                        }
-                       additem(ovfbuf, item);
-                       delitem(db->db_pagbuf, i);
+                       if (!additem(ovfbuf, item, item1) ||
+                           !delitem(db->dbm_pagbuf, i)) {
+                               db->dbm_flags |= _DBM_IOERR;
+                               return (-1);
+                       }
                        continue;
                }
                i += 2;
        }
                        continue;
                }
                i += 2;
        }
-       (void) lseek(db->db_pagf, db->db_blkno*PBLKSIZ, L_SET);
-       (void) write(db->db_pagf, db->db_pagbuf, PBLKSIZ);
-       db->db_pagbno = db->db_blkno;
-       (void) lseek(db->db_pagf, (db->db_blkno+db->db_hmask+1)*PBLKSIZ, L_SET);
-       (void) write(db->db_pagf, ovfbuf, PBLKSIZ);
+       db->dbm_pagbno = db->dbm_blkno;
+       (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET);
+       if (write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) {
+               db->dbm_flags |= _DBM_IOERR;
+               return (-1);
+       }
+       (void) lseek(db->dbm_pagf, (db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ, L_SET);
+       if (write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ) {
+               db->dbm_flags |= _DBM_IOERR;
+               return (-1);
+       }
        setbit(db);
        goto loop;
 }
 
 datum
        setbit(db);
        goto loop;
 }
 
 datum
-dbmfirstkey(db)
+dbm_firstkey(db)
        DBM *db;
 {
 
        DBM *db;
 {
 
-       return (firsthash(db, 0L));
+       db->dbm_blkptr = 0L;
+       db->dbm_keyptr = 0;
+       return (dbm_nextkey(db));
 }
 
 datum
 }
 
 datum
-dbmnextkey(db, key)
+dbm_nextkey(db)
        register DBM *db;
        register DBM *db;
-       datum key;
 {
 {
-       register i;
-       datum item, bitem;
-       long hash;
-       int f;
+       struct stat statb;
+       datum item;
 
 
-       hash = dcalchash(key);
-       dbm_access(db, hash);
-       f = 1;
-       for (i=0;; i+=2) {
-               item = makdatum(db->db_pagbuf, i);
-               if (item.dptr == NULL)
-                       break;
-               if (cmpdatum(key, item) <= 0)
-                       continue;
-               if (f || cmpdatum(bitem, item) < 0) {
-                       bitem = item;
-                       f = 0;
+       if (dbm_error(db) || fstat(db->dbm_pagf, &statb) < 0)
+               goto err;
+       statb.st_size /= PBLKSIZ;
+       for (;;) {
+               if (db->dbm_blkptr != db->dbm_pagbno) {
+                       db->dbm_pagbno = db->dbm_blkptr;
+                       (void) lseek(db->dbm_pagf, db->dbm_blkptr*PBLKSIZ, L_SET);
+                       if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)
+                               bzero(db->dbm_pagbuf, PBLKSIZ);
+#ifdef DEBUG
+                       else if (chkblk(db->dbm_pagbuf) < 0)
+                               db->dbm_flags |= _DBM_IOERR;
+#endif
                }
                }
-       }
-       if (f == 0)
-               return (bitem);
-       hash = hashinc(db, hash);
-       if (hash == 0)
-               return (item);
-       return (firsthash(db, hash));
-}
-
-static datum
-firsthash(db, hash)
-       register DBM *db;
-       long hash;
-{
-       register i;
-       datum item, bitem;
-
-loop:
-       dbm_access(db, hash);
-       bitem = makdatum(db->db_pagbuf, 0);
-       for (i=2;; i+=2) {
-               item = makdatum(db->db_pagbuf, i);
-               if (item.dptr == NULL)
+               if (((short *)db->dbm_pagbuf)[0] != 0) {
+                       item = makdatum(db->dbm_pagbuf, db->dbm_keyptr);
+                       if (item.dptr != NULL) {
+                               db->dbm_keyptr += 2;
+                               return (item);
+                       }
+                       db->dbm_keyptr = 0;
+               }
+               if (++db->dbm_blkptr >= statb.st_size)
                        break;
                        break;
-               if (cmpdatum(bitem, item) < 0)
-                       bitem = item;
        }
        }
-       if (bitem.dptr != NULL)
-               return (bitem);
-       hash = hashinc(db, hash);
-       if (hash == 0)
-               return (item);
-       goto loop;
+err:
+       item.dptr = NULL;
+       item.dsize = 0;
+       return (item);
 }
 
 }
 
-static
+static void
 dbm_access(db, hash)
        register DBM *db;
        long hash;
 {
 dbm_access(db, hash)
        register DBM *db;
        long hash;
 {
-       
-       for (db->db_hmask=0;; db->db_hmask=(db->db_hmask<<1)+1) {
-               db->db_blkno = hash & db->db_hmask;
-               db->db_bitno = db->db_blkno + db->db_hmask;
+
+       for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) {
+               db->dbm_blkno = hash & db->dbm_hmask;
+               db->dbm_bitno = db->dbm_blkno + db->dbm_hmask;
                if (getbit(db) == 0)
                        break;
        }
                if (getbit(db) == 0)
                        break;
        }
-       if (db->db_blkno != db->db_pagbno) {
-               bzero(db->db_pagbuf, PBLKSIZ);
-               (void) lseek(db->db_pagf, db->db_blkno*PBLKSIZ, L_SET);
-               (void) read(db->db_pagf, db->db_pagbuf, PBLKSIZ);
-               chkblk(db->db_pagbuf);
-               db->db_pagbno = db->db_blkno;
+       if (db->dbm_blkno != db->dbm_pagbno) {
+               db->dbm_pagbno = db->dbm_blkno;
+               (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET);
+               if (read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ)
+                       bzero(db->dbm_pagbuf, PBLKSIZ);
+#ifdef DEBUG
+               else if (chkblk(db->dbm_pagbuf) < 0)
+                       db->dbm_flags |= _DBM_IOERR;
+#endif
        }
 }
 
        }
 }
 
@@ -304,46 +298,45 @@ getbit(db)
        register b, i, n;
        
 
        register b, i, n;
        
 
-       if (db->db_bitno > db->db_maxbno)
+       if (db->dbm_bitno > db->dbm_maxbno)
                return (0);
                return (0);
-       n = db->db_bitno % BYTESIZ;
-       bn = db->db_bitno / BYTESIZ;
+       n = db->dbm_bitno % BYTESIZ;
+       bn = db->dbm_bitno / BYTESIZ;
        i = bn % DBLKSIZ;
        b = bn / DBLKSIZ;
        i = bn % DBLKSIZ;
        b = bn / DBLKSIZ;
-       if (b != db->db_dirbno) {
-               bzero(db->db_dirbuf, DBLKSIZ);
-               (void) lseek(db->db_dirf, (long)b*DBLKSIZ, L_SET);
-               (void) read(db->db_dirf, db->db_dirbuf, DBLKSIZ);
-               db->db_dirbno = b;
+       if (b != db->dbm_dirbno) {
+               db->dbm_dirbno = b;
+               (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET);
+               if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
+                       bzero(db->dbm_dirbuf, DBLKSIZ);
        }
        }
-       if (db->db_dirbuf[i] & (1<<n))
-               return (1);
-       return (0);
+       return (db->dbm_dirbuf[i] & (1<<n));
 }
 
 }
 
-static
+static void
 setbit(db)
        register DBM *db;
 {
        long bn;
        register i, n, b;
 
 setbit(db)
        register DBM *db;
 {
        long bn;
        register i, n, b;
 
-       if (dbrdonly(db)) {
-               errno = EPERM;
-               return (-1);
-       }
-       if (db->db_bitno > db->db_maxbno) {
-               db->db_maxbno = db->db_bitno;
-               getbit(db);
-       }
-       n = db->db_bitno % BYTESIZ;
-       bn = db->db_bitno / BYTESIZ;
+       if (db->dbm_bitno > db->dbm_maxbno)
+               db->dbm_maxbno = db->dbm_bitno;
+       n = db->dbm_bitno % BYTESIZ;
+       bn = db->dbm_bitno / BYTESIZ;
        i = bn % DBLKSIZ;
        b = bn / DBLKSIZ;
        i = bn % DBLKSIZ;
        b = bn / DBLKSIZ;
-       db->db_dirbuf[i] |= 1<<n;
-       (void) lseek(db->db_dirf, (long)b*DBLKSIZ, L_SET);
-       (void) write(db->db_dirf, db->db_dirbuf, DBLKSIZ);
-       db->db_dirbno = b;
+       if (b != db->dbm_dirbno) {
+               db->dbm_dirbno = b;
+               (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET);
+               if (read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
+                       bzero(db->dbm_dirbuf, DBLKSIZ);
+       }
+       db->dbm_dirbuf[i] |= 1<<n;
+       db->dbm_dirbno = b;
+       (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET);
+       if (write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ)
+               db->dbm_flags |= _DBM_IOERR;
 }
 
 static datum
 }
 
 static datum
@@ -355,40 +348,37 @@ makdatum(buf, n)
        datum item;
 
        sp = (short *)buf;
        datum item;
 
        sp = (short *)buf;
-       if (n < 0 || n >= sp[0])
-               goto null;
+       if ((unsigned)n >= sp[0]) {
+               item.dptr = NULL;
+               item.dsize = 0;
+               return (item);
+       }
        t = PBLKSIZ;
        if (n > 0)
        t = PBLKSIZ;
        if (n > 0)
-               t = sp[n+1-1];
+               t = sp[n];
        item.dptr = buf+sp[n+1];
        item.dsize = t - sp[n+1];
        return (item);
        item.dptr = buf+sp[n+1];
        item.dsize = t - sp[n+1];
        return (item);
-
-null:
-       item.dptr = NULL;
-       item.dsize = 0;
-       return (item);
 }
 
 static
 }
 
 static
-cmpdatum(d1, d2)
-       datum d1, d2;
+finddatum(buf, item)
+       char buf[PBLKSIZ];
+       datum item;
 {
 {
-       register n;
-       register char *p1, *p2;
+       register short *sp;
+       register int i, n, j;
 
 
-       n = d1.dsize;
-       if (n != d2.dsize)
-               return (n - d2.dsize);
-       if (n == 0)
-               return (0);
-       p1 = d1.dptr;
-       p2 = d2.dptr;
-       do
-               if (*p1++ != *p2++)
-                       return (*--p1 - *--p2);
-       while (--n);
-       return (0);
+       sp = (short *)buf;
+       n = PBLKSIZ;
+       for (i=0, j=sp[0]; i<j; i+=2, n = sp[i]) {
+               n -= sp[i+1];
+               if (n != item.dsize)
+                       continue;
+               if (n == 0 || bcmp(&buf[sp[i+1]], item.dptr, n) == 0)
+                       return (i);
+       }
+       return (-1);
 }
 
 static  int hitab[16]
 }
 
 static  int hitab[16]
@@ -428,14 +418,14 @@ hashinc(db, hash)
 {
        long bit;
 
 {
        long bit;
 
-       hash &= db->db_hmask;
-       bit = db->db_hmask+1;
+       hash &= db->dbm_hmask;
+       bit = db->dbm_hmask+1;
        for (;;) {
                bit >>= 1;
                if (bit == 0)
                        return (0L);
        for (;;) {
                bit >>= 1;
                if (bit == 0)
                        return (0L);
-               if ((hash&bit) == 0)
-                       return (hash|bit);
+               if ((hash & bit) == 0)
+                       return (hash | bit);
                hash &= ~bit;
        }
 }
                hash &= ~bit;
        }
 }
@@ -444,82 +434,84 @@ static long
 dcalchash(item)
        datum item;
 {
 dcalchash(item)
        datum item;
 {
-       register i, j, f;
-       long hashl;
-       int hashi;
+       register int s, c, j;
+       register char *cp;
+       register long hashl;
+       register int hashi;
 
        hashl = 0;
        hashi = 0;
 
        hashl = 0;
        hashi = 0;
-       for (i=0; i<item.dsize; i++) {
-               f = item.dptr[i];
+       for (cp = item.dptr, s=item.dsize; --s >= 0; ) {
+               c = *cp++;
                for (j=0; j<BYTESIZ; j+=4) {
                for (j=0; j<BYTESIZ; j+=4) {
-                       hashi += hitab[f&017];
+                       hashi += hitab[c&017];
                        hashl += hltab[hashi&63];
                        hashl += hltab[hashi&63];
-                       f >>= 4;
+                       c >>= 4;
                }
        }
        return (hashl);
 }
 
                }
        }
        return (hashl);
 }
 
+/*
+ * Delete pairs of items (n & n+1).
+ */
 static
 delitem(buf, n)
        char buf[PBLKSIZ];
 {
 static
 delitem(buf, n)
        char buf[PBLKSIZ];
 {
-       register short *sp;
-       register i1, i2, i3;
+       register short *sp, *sp1;
+       register i1, i2;
 
        sp = (short *)buf;
 
        sp = (short *)buf;
-       if (n < 0 || n >= sp[0])
-               goto bad;
-       i1 = sp[n+1];
-       i2 = PBLKSIZ;
+       i2 = sp[0];
+       if ((unsigned)n >= i2 || (n & 1))
+               return (0);
+       if (n == i2-2) {
+               sp[0] -= 2;
+               return (1);
+       }
+       i1 = PBLKSIZ;
        if (n > 0)
        if (n > 0)
-               i2 = sp[n+1-1];
-       i3 = sp[sp[0]+1-1];
-       if (i2 > i1)
-       while (i1 > i3) {
-               i1--;
-               i2--;
-               buf[i2] = buf[i1];
-               buf[i1] = 0;
+               i1 = sp[n];
+       i1 -= sp[n+2];
+       if (i1 > 0) {
+               i2 = sp[i2];
+               bcopy(&buf[i2], &buf[i2 + i1], sp[n+2] - i2);
        }
        }
-       i2 -= i1;
-       for (i1=n+1; i1<sp[0]; i1++)
-               sp[i1+1-1] = sp[i1+1] + i2;
-       sp[0]--;
-       sp[sp[0]+1] = 0;
-       return;
-
-bad:
-       printf("ndbm: bad delitem\n");
-       abort();
+       sp[0] -= 2;
+       for (sp1 = sp + sp[0], sp += n+1; sp <= sp1; sp++)
+               sp[0] = sp[2] + i1;
+       return (1);
 }
 
 }
 
+/*
+ * Add pairs of items (item & item1).
+ */
 static
 static
-additem(buf, item)
+additem(buf, item, item1)
        char buf[PBLKSIZ];
        char buf[PBLKSIZ];
-       datum item;
+       datum item, item1;
 {
        register short *sp;
        register i1, i2;
 
        sp = (short *)buf;
        i1 = PBLKSIZ;
 {
        register short *sp;
        register i1, i2;
 
        sp = (short *)buf;
        i1 = PBLKSIZ;
-       if (sp[0] > 0)
-               i1 = sp[sp[0]+1-1];
-       i1 -= item.dsize;
-       i2 = (sp[0]+2) * sizeof(short);
-       if (i1 <= i2)
-               return (-1);
-       sp[sp[0]+1] = i1;
-       for (i2=0; i2<item.dsize; i2++) {
-               buf[i1] = item.dptr[i2];
-               i1++;
-       }
-       sp[0]++;
-       return (sp[0]-1);
+       i2 = sp[0];
+       if (i2 > 0)
+               i1 = sp[i2];
+       i1 -= item.dsize + item1.dsize;
+       if (i1 <= (i2+3) * (int)sizeof(short))
+               return (0);
+       sp[0] += 2;
+       sp[++i2] = i1 + item1.dsize;
+       bcopy(item.dptr, &buf[i1 + item1.dsize], item.dsize);
+       sp[++i2] = i1;
+       bcopy(item1.dptr, &buf[i1], item1.dsize);
+       return (1);
 }
 
 }
 
+#ifdef DEBUG
 static
 chkblk(buf)
        char buf[PBLKSIZ];
 static
 chkblk(buf)
        char buf[PBLKSIZ];
@@ -531,15 +523,11 @@ chkblk(buf)
        t = PBLKSIZ;
        for (i=0; i<sp[0]; i++) {
                if (sp[i+1] > t)
        t = PBLKSIZ;
        for (i=0; i<sp[0]; i++) {
                if (sp[i+1] > t)
-                       goto bad;
+                       return (-1);
                t = sp[i+1];
        }
        if (t < (sp[0]+1)*sizeof(short))
                t = sp[i+1];
        }
        if (t < (sp[0]+1)*sizeof(short))
-               goto bad;
-       return;
-
-bad:
-       printf("ndbm: bad block\n");
-       abort();
-       bzero(buf, PBLKSIZ);
+               return (-1);
+       return (0);
 }
 }
+#endif