* kdb_dbm.c: Unused file deleted
authorKen Raeburn <raeburn@mit.edu>
Fri, 10 Jun 2005 02:48:13 +0000 (02:48 +0000)
committerKen Raeburn <raeburn@mit.edu>
Fri, 10 Jun 2005 02:48:13 +0000 (02:48 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@17235 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/kdb/ChangeLog
src/lib/kdb/kdb_dbm.c [deleted file]

index e69af02a233a5fe1a20ba995410995612bcbdf7c..99e6b58ca74579302a2ababb01a8477961ca826e 100644 (file)
@@ -1,3 +1,7 @@
+2005-06-09  Ken Raeburn  <raeburn@mit.edu>
+
+       * kdb_dbm.c: Unused file deleted.
+
 2004-07-09  Ken Raeburn  <raeburn@mit.edu>
 
        * kdb_db2.c (krb5_db2_db_get_principal): Rename local variable
diff --git a/src/lib/kdb/kdb_dbm.c b/src/lib/kdb/kdb_dbm.c
deleted file mode 100644 (file)
index 4769ba9..0000000
+++ /dev/null
@@ -1,1409 +0,0 @@
-/*
- * lib/kdb/kdb_dbm.c
- *
- * Copyright 1988,1989,1990,1991 by the Massachusetts Institute of Technology. 
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- *   require a specific license from the United States Government.
- *   It is the responsibility of any person or organization contemplating
- *   export to obtain such a license before exporting.
- * 
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission.  Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose.  It is provided "as is" without express
- * or implied warranty.
- * 
- */
-
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-/* Obtain dispatch table definitions from kdb.h */
-#define        KDB5_DISPATCH
-#include "k5-int.h"
-#include "kdb_dbc.h"
-#include <stdio.h>
-#include <errno.h>
-#include <utime.h>
-
-#define OLD_COMPAT_VERSION_1
-
-#ifdef OLD_COMPAT_VERSION_1
-#include "kdb_compat.h"
-#endif
-
-#define KRB5_DBM_MAX_RETRY 5
-
-#ifdef DEBUG
-extern int debug;
-extern long krb5_dbm_db_debug;
-extern char *progname;
-#endif
-
-static char default_db_name[] = DEFAULT_KDB_FILE;
-
-static char *gen_dbsuffix 
-       (char *, char * );
-static krb5_error_code krb5_dbm_db_start_update 
-       (krb5_context);
-static krb5_error_code krb5_dbm_db_end_update 
-       (krb5_context);
-
-/*
- * This module contains all of the code which directly interfaces to
- * the underlying representation of the Kerberos database; this
- * implementation uses the Berkeley hash db to store the relations, plus a
- * second file as a semaphore to allow the database to be replaced out
- * from underneath the KDC server.
- */
-static kdb5_dispatch_table kdb5_default_dispatch = {
-    "Berkeley Hashed Database w/ DBM interface",
-    ".db",                     /* Index file name ext  */
-    (char *) NULL,             /* Data file name ext   */
-    ".ok",                     /* Lock file name ext   */
-    dbm_open,                  /* Open Database        */
-    dbm_close,                 /* Close Database       */
-    dbm_fetch,                 /* Fetch Key            */
-    dbm_firstkey,              /* Fetch First Key      */
-    dbm_nextkey,               /* Fetch Next Key       */
-    dbm_delete,                        /* Delete Key           */
-    dbm_store,                 /* Store Key            */
-    /*
-     * The following are #ifdef'd because they have the potential to be
-     * macros rather than functions.
-     */
-    (int (*)()) NULL,          /* Get DB index FD num  */
-    (int (*)()) NULL,          /* Get DB data FD num   */
-};
-
-/*
- * These macros dispatch via the dispatch table.
- */
-#define        KDBM_OPEN(dbc, db, fl, mo)      ((*(((krb5_db_context *)dbc)->  \
-                                           db_dispatch->kdb5_dbm_open)) \
-                                        (db, fl, mo))
-#define        KDBM_CLOSE(dbc, db)             ((*(((krb5_db_context *)dbc)->  \
-                                           db_dispatch->kdb5_dbm_close))(db))
-#define        KDBM_FETCH(dbc, db, key)        ((*(((krb5_db_context *)dbc)->  \
-                                           db_dispatch->kdb5_dbm_fetch)) \
-                                        (db, key))
-#define        KDBM_FIRSTKEY(dbc, db)          ((*(((krb5_db_context *)dbc)->  \
-                                           db_dispatch->kdb5_dbm_firstkey)) \
-                                        (db))
-#define        KDBM_NEXTKEY(dbc, db)           ((*(((krb5_db_context *)dbc)->  \
-                                           db_dispatch->kdb5_dbm_nextkey)) \
-                                        (db))
-#define        KDBM_DELETE(dbc, db, key)       ((*(((krb5_db_context *)dbc)->  \
-                                           db_dispatch->kdb5_dbm_delete)) \
-                                        (db, key))
-#define        KDBM_STORE(dbc, db, key, c, f)  ((*(((krb5_db_context *)dbc)->  \
-                                           db_dispatch->kdb5_dbm_store)) \
-                                        (db, key, c, f))
-#define        KDBM_INDEX_EXT(dbc)             (((krb5_db_context *)dbc)->      \
-                                         db_dispatch->kdb5_db_index_ext)
-#define        KDBM_DATA_EXT(dbc)              (((krb5_db_context *)dbc)->      \
-                                         db_dispatch->kdb5_db_data_ext)
-#define        KDBM_LOCK_EXT(dbc)              (((krb5_db_context *)dbc)->      \
-                                         db_dispatch->kdb5_db_lock_ext)
-
-/*
- * Locking:
- * 
- * There are two distinct locking protocols used.  One is designed to
- * lock against processes (the admin_server, for one) which make
- * incremental changes to the database; the other is designed to lock
- * against utilities (kdb5_edit, kpropd, kdb5_convert) which replace the
- * entire database in one fell swoop.
- *
- * The first locking protocol is implemented using flock() in the 
- * krb_dbl_lock() and krb_dbl_unlock routines.
- *
- * The second locking protocol is necessary because DBM "files" are
- * actually implemented as two separate files, and it is impossible to
- * atomically rename two files simultaneously.  It assumes that the
- * database is replaced only very infrequently in comparison to the time
- * needed to do a database read operation.
- *
- * A third file is used as a "version" semaphore; the modification
- * time of this file is the "version number" of the database.
- * At the start of a read operation, the reader checks the version
- * number; at the end of the read operation, it checks again.  If the
- * version number changed, or if the semaphore was nonexistant at
- * either time, the reader sleeps for a second to let things
- * stabilize, and then tries again; if it does not succeed after
- * KRB5_DBM_MAX_RETRY attempts, it gives up.
- * 
- * On update, the semaphore file is deleted (if it exists) before any
- * update takes place; at the end of the update, it is replaced, with
- * a version number strictly greater than the version number which
- * existed at the start of the update.
- * 
- * If the system crashes in the middle of an update, the semaphore
- * file is not automatically created on reboot; this is a feature, not
- * a bug, since the database may be inconsistant.  Note that the
- * absence of a semaphore file does not prevent another _update_ from
- * taking place later.  Database replacements take place automatically
- * only on slave servers; a crash in the middle of an update will be
- * fixed by the next slave propagation.  A crash in the middle of an
- * update on the master would be somewhat more serious, but this would
- * likely be noticed by an administrator, who could fix the problem and
- * retry the operation.
- */
-
-#define free_dbsuffix(name) free(name)
-
-/*
- * Routines to deal with context.
- */
-#define        k5dbm_inited(c) (c && c->db_context &&  \
-                        ((krb5_db_context *) c->db_context)->db_inited)
-
-/*
- * Restore the default context.
- */
-static void
-k5dbm_clear_context(dbctx)
-    krb5_db_context *  dbctx;
-{
-    /*
-     * Free any dynamically allocated memory.  File descriptors and locks
-     * are the caller's problem.
-     */
-    if (dbctx->db_lf_name)
-       free(dbctx->db_lf_name);
-    if (dbctx->db_name && (dbctx->db_name != default_db_name))
-       free(dbctx->db_name);
-    /*
-     * Clear the structure and reset the defaults.
-     */
-    memset((char *) dbctx, 0, sizeof(krb5_db_context));
-    dbctx->db_name = default_db_name;
-    dbctx->db_nb_locks = FALSE;
-    dbctx->db_dispatch = &kdb5_default_dispatch;
-}
-
-static krb5_error_code
-k5dbm_init_context(context)
-    krb5_context       context;
-{
-    krb5_db_context *  db_ctx;
-
-    if (context->db_context == NULL) {
-       if ((db_ctx = (krb5_db_context *) malloc(sizeof(krb5_db_context)))) {
-           memset((char *) db_ctx, 0, sizeof(krb5_db_context));
-           k5dbm_clear_context((krb5_db_context *)db_ctx);
-           context->db_context = (void *) db_ctx;
-       } else 
-           return(ENOMEM);
-    }
-    return(0);
-}
-
-/*
- * Utility routine: generate name of database file.
- */
-
-static char *
-gen_dbsuffix(db_name, sfx)
-char *db_name;
-char *sfx;
-{
-    char *dbsuffix;
-    
-    if (sfx == NULL)
-       return((char *) NULL);
-
-    dbsuffix = malloc (strlen(db_name) + strlen(sfx) + 1);
-    if (!dbsuffix)
-       return(0);
-    (void) strcpy(dbsuffix, db_name);
-    (void) strcat(dbsuffix, sfx);
-    return dbsuffix;
-}
-
-/*
- * initialization for data base routines.
- */
-
-krb5_error_code
-krb5_dbm_db_init(context)
-    krb5_context         context;
-{
-    char               * filename = NULL;
-    krb5_db_context    * db_ctx;
-    krb5_error_code      retval;
-
-    if (k5dbm_inited(context))
-       return 0;
-
-    /* Check for presence of our context, if not present, allocate one. */
-    if ((retval = k5dbm_init_context(context)))
-       return(retval);
-
-    db_ctx = context->db_context;
-    db_ctx->db_dbm_ctx = NULL;
-
-    if (!(filename = gen_dbsuffix (db_ctx->db_name, KDBM_LOCK_EXT(db_ctx))))
-       return ENOMEM;
-
-    /*
-     * should be opened read/write so that write locking can work with
-     * POSIX systems
-     */
-    if ((db_ctx->db_lf_file = open(filename, O_RDWR, 0666)) < 0) {
-       if ((db_ctx->db_lf_file = open(filename, O_RDONLY, 0666)) < 0) {
-           retval = errno;
-           goto err_out;
-       }
-    }
-    db_ctx->db_lf_name = filename;
-    db_ctx->db_inited++;
-
-    if ((retval = krb5_dbm_db_get_age(context, NULL, &db_ctx->db_lf_time))) 
-       goto err_out;
-
-    return 0;
-    
-err_out:
-    db_ctx->db_dbm_ctx = (DBM *) NULL;
-    k5dbm_clear_context(db_ctx);
-    return (retval);
-}
-
-/*
- * gracefully shut down database--must be called by ANY program that does
- * a krb5_dbm_db_init 
- */
-krb5_error_code
-krb5_dbm_db_fini(context)
-    krb5_context context;
-{
-    krb5_error_code retval = 0;
-    krb5_db_context    *db_ctx;
-
-    db_ctx = (krb5_db_context *) context->db_context;
-
-    if (k5dbm_inited(context)) {
-       if (close(db_ctx->db_lf_file))
-           retval = errno;
-       else
-           retval = 0;
-    }
-    if (db_ctx) {
-       k5dbm_clear_context(db_ctx);
-       free (context->db_context);
-       context->db_context = NULL;
-    }
-    return retval;
-}
-
-krb5_error_code
-krb5_dbm_db_open_database(context)
-    krb5_context context;
-{
-    if (!k5dbm_inited(context))
-       return KRB5_KDB_DBNOTINITED;
-    return 0;
-}
-
-krb5_error_code
-krb5_dbm_db_close_database(context)
-    krb5_context context;
-{
-    if (!k5dbm_inited(context))
-       return KRB5_KDB_DBNOTINITED;
-    return 0;
-}
-
-/*
- * Set/Get the master key associated with the database
- *
- * These only exist because the db_context is part of the kcontext
- * The should really reference the db_context
- */
-krb5_error_code
-krb5_dbm_db_set_mkey(context, db_context, key)
-    krb5_context         context;
-    krb5_db_context    * db_context;
-    krb5_keyblock  * key;
-{
-    krb5_db_context *db_ctx;
-
-    if (!k5dbm_inited(context))
-       return(KRB5_KDB_DBNOTINITED);
-
-    db_ctx = context->db_context;
-    db_ctx->db_master_key = key;
-    return 0;
-}
-
-krb5_error_code
-krb5_dbm_db_get_mkey(context, db_context, key)
-    krb5_context         context;
-    krb5_db_context    * db_context;
-    krb5_keyblock  **key;
-{
-    krb5_db_context *db_ctx;
-
-    if (!k5dbm_inited(context))
-       return(KRB5_KDB_DBNOTINITED);
-
-    db_ctx = context->db_context;
-    *key = db_ctx->db_master_key;
-    return 0;
-
-}
-
-/*
- * Set the "name" of the current database to some alternate value.
- *
- * Passing a null pointer as "name" will set back to the default.
- * If the alternate database doesn't exist, nothing is changed.
- *
- * XXX rethink this
- */
-
-krb5_error_code
-krb5_dbm_db_set_name(context, name)
-    krb5_context context;
-    char *name;
-{
-    DBM *db;
-    krb5_db_context *db_ctx;
-    krb5_error_code kret;
-
-    if (k5dbm_inited(context))
-       return KRB5_KDB_DBINITED;
-
-    /* Check for presence of our context, if not present, allocate one. */
-    if ((kret = k5dbm_init_context(context)))
-       return(kret);
-
-    if (name == NULL)
-       name = default_db_name;
-
-    db_ctx = context->db_context;
-    if ((db = KDBM_OPEN(db_ctx, name, O_RDONLY, 0)) == NULL)
-       return errno;
-
-    db_ctx->db_name = strdup(name);
-    KDBM_CLOSE(db_ctx, db);
-    return 0;
-}
-
-/*
- * Return the last modification time of the database.
- *
- * Think about using fstat.
- */
-
-krb5_error_code
-krb5_dbm_db_get_age(context, db_name, age)
-    krb5_context context;
-    char *db_name;
-    time_t *age;
-{
-    krb5_db_context *db_ctx;
-    struct stat st;
-    
-    if (!k5dbm_inited(context))
-       return(KRB5_KDB_DBNOTINITED);
-    db_ctx = (krb5_db_context *) context->db_context;
-    if (fstat (db_ctx->db_lf_file, &st) < 0)
-       *age = -1;
-    else
-       *age = st.st_mtime;
-    return 0;
-}
-
-/*
- * Remove the semaphore file; indicates that database is currently
- * under renovation.
- *
- * This is only for use when moving the database out from underneath
- * the server (for example, during slave updates).
- */
-
-static krb5_error_code
-krb5_dbm_db_start_update(context)
-    krb5_context context;
-{
-    return 0;
-}
-
-static krb5_error_code
-krb5_dbm_db_end_update(context)
-    krb5_context context;
-{
-    krb5_error_code retval;
-    krb5_db_context *db_ctx = context->db_context;
-    struct stat st;
-    time_t now;
-    struct utimbuf utbuf;
-
-    if (!k5dbm_inited(context))
-       return(KRB5_KDB_DBNOTINITED);
-
-    retval = 0;
-    now = time((time_t *) NULL);
-    if (fstat(db_ctx->db_lf_file, &st) == 0) {
-       if (st.st_mtime >= now) {
-           utbuf.actime = st.st_mtime+1;
-           utbuf.modtime = st.st_mtime+1;
-           if (utime(db_ctx->db_lf_name, &utbuf))
-               retval = errno;
-       }
-       else {
-           if (utime(db_ctx->db_lf_name, (struct utimbuf *) NULL))
-               retval = errno;
-       }
-    }
-    else
-       retval = errno;
-    if (!retval) {
-       if (fstat(db_ctx->db_lf_file, &st) == 0)
-           db_ctx->db_lf_time = st.st_mtime;
-       else
-           retval = errno;
-    }
-    return(retval);
-}
-
-krb5_error_code
-krb5_dbm_db_lock(context, mode)
-    krb5_context         context;
-    int                  mode;
-{
-    int                  krb5_lock_mode;
-    krb5_error_code      retval;
-    time_t               mod_time;
-    krb5_db_context    * db_ctx;
-    DBM                * db;
-
-    if (!k5dbm_inited(context))
-       return KRB5_KDB_DBNOTINITED;
-
-    db_ctx = (krb5_db_context *) context->db_context;
-    if (db_ctx->db_locks_held && (db_ctx->db_lock_mode >= mode)) {
-       /* No need to upgrade lock, just return */
-       db_ctx->db_locks_held++;
-       return(0);
-    }
-
-    if ((mode != KRB5_LOCKMODE_SHARED) && (mode != KRB5_LOCKMODE_EXCLUSIVE)) 
-       return KRB5_KDB_BADLOCKMODE;
-
-    if (db_ctx->db_nb_locks)
-       krb5_lock_mode = mode | KRB5_LOCKMODE_DONTBLOCK;
-    else
-       krb5_lock_mode = mode;
-
-    switch (retval = krb5_lock_file(context,db_ctx->db_lf_file,krb5_lock_mode)){
-    case EBADF:
-       if (mode == KRB5_LOCKMODE_EXCLUSIVE)
-           return KRB5_KDB_CANTLOCK_DB;
-    default:
-       return retval;
-    case 0:
-       break;
-    }
-
-    if ((retval = krb5_dbm_db_get_age(context, NULL, &mod_time)))
-       goto lock_error;
-
-    if ((db = KDBM_OPEN(db_ctx, db_ctx->db_name,
-                       mode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR,
-                       0600))) {
-        db_ctx->db_lf_time = mod_time;
-        db_ctx->db_dbm_ctx = db;
-    } else {
-        retval = errno;
-        goto lock_error;
-    }
-
-    db_ctx->db_lock_mode = mode;
-    db_ctx->db_locks_held++;
-    return 0;
-
-lock_error:;
-    db_ctx->db_lock_mode = 0;
-    db_ctx->db_locks_held = 0;
-    (void) krb5_dbm_db_unlock(context);
-    return retval;
-}
-
-krb5_error_code
-krb5_dbm_db_unlock(context)
-    krb5_context context;
-{
-    krb5_db_context    * db_ctx;
-    krb5_error_code      retval;
-
-    if (!k5dbm_inited(context))
-       return KRB5_KDB_DBNOTINITED;
-
-    db_ctx = (krb5_db_context *) context->db_context;
-    if (!db_ctx->db_locks_held)                /* lock already unlocked */
-       return KRB5_KDB_NOTLOCKED;
-
-    if (--(db_ctx->db_locks_held) == 0) {
-    KDBM_CLOSE(db_ctx, db_ctx->db_dbm_ctx);
-       db_ctx->db_dbm_ctx = NULL;
-
-       retval = krb5_lock_file(context, db_ctx->db_lf_file,
-                               KRB5_LOCKMODE_UNLOCK);
-       db_ctx->db_lock_mode = 0;
-       return(retval);
-    }
-    return 0;
-}
-
-/*
- * Create the database, assuming it's not there.
- */
-krb5_error_code
-krb5_dbm_db_create(context, db_name)
-    krb5_context context;
-    char *db_name;
-{
-    char *okname;
-    int fd;
-    register krb5_error_code retval = 0;
-    DBM *db;
-
-    if ((retval = k5dbm_init_context(context)))
-       return(retval);
-    
-    db = KDBM_OPEN(context->db_context, db_name, O_RDWR|O_CREAT|O_EXCL, 0600);
-    if (db == NULL)
-       retval = errno;
-    else
-       KDBM_CLOSE(context->db_context, db);
-    if (retval == 0) {
-       okname = gen_dbsuffix(db_name, KDBM_LOCK_EXT(context->db_context));
-       if (!okname)
-           retval = ENOMEM;
-       else {
-           fd = open (okname, O_CREAT|O_RDWR|O_TRUNC, 0600);
-           if (fd < 0)
-               retval = errno;
-           else
-               close(fd);
-           free_dbsuffix(okname);
-       }
-    }
-    return retval;
-}
-
-/*
- * Destroy the database.  Zero's out all of the files, just to be sure.
- */
-static krb5_error_code
-destroy_file_suffix(dbname, suffix)
-       char    *dbname;
-       char    *suffix;
-{
-       char    *filename;
-       struct stat     statb;
-       int             nb,fd,i,j;
-       char            buf[BUFSIZ];
-       char            zbuf[BUFSIZ];
-       int             dowrite;
-
-       filename = gen_dbsuffix(dbname, suffix);
-       if (filename == 0)
-               return ENOMEM;
-       if ((fd = open(filename, O_RDWR, 0)) < 0) {
-               free(filename);
-               return errno;
-       }
-       /* fstat() will probably not fail unless using a remote filesystem
-          (which is inappropriate for the kerberos database) so this check
-          is mostly paranoia.  */
-       if (fstat(fd, &statb) == -1) {
-               int retval = errno;
-               free(filename);
-               return retval;
-       }
-       /*
-        * Stroll through the file, reading in BUFSIZ chunks.  If everything
-        * is zero, then we're done for that block, otherwise, zero the block.
-        * We would like to just blast through everything, but some DB
-        * implementations make holey files and writing data to the holes
-        * causes actual blocks to be allocated which is no good, since
-        * we're just about to unlink it anyways.
-        */
-       memset(zbuf, 0, BUFSIZ);
-       i = 0;
-       while (i < statb.st_size) {
-               dowrite = 0;
-               nb = read(fd, buf, BUFSIZ);
-               if (nb < 0) {
-                       int retval = errno;
-                       free(filename);
-                       return retval;
-               }
-               for (j=0; j<nb; j++) {
-                   if (buf[j] != '\0') {
-                       dowrite = 1;
-                       break;
-                   }
-               }
-               if (dowrite) {
-                       lseek(fd, i, SEEK_SET);
-                       nb = write(fd, zbuf, nb);
-                       if (nb < 0) {
-                               int retval = errno;
-                               free(filename);
-                               return retval;
-                       }
-               }
-               i += nb;
-       }
-       /* ??? Is fsync really needed?  I don't know of any non-networked
-          filesystem which will discard queued writes to disk if a file
-          is deleted after it is closed.  --jfc */
-#ifndef NOFSYNC
-       fsync(fd);
-#endif
-       close(fd);
-
-       if (unlink(filename)) {
-               free(filename);
-               return(errno);
-       }
-       free(filename);
-       return(0);
-}
-
-/*
- * Since the destroy operation happens outside the init/fini bracket, we
- * have some tomfoolery to undergo here.  If we're operating under no
- * database context, then we initialize with the default.  If the caller
- * wishes a different context (e.g. different dispatch table), it's their
- * responsibility to call kdb5_db_set_dbops() before this call.  That will
- * set up the right dispatch table values (e.g. name extensions).
- */
-krb5_error_code
-krb5_dbm_db_destroy(context, dbname)
-    krb5_context context;
-       char    *dbname;
-{
-       krb5_error_code retval1, retval2, retval3;
-       krb5_boolean tmpcontext;
-
-       tmpcontext = 0;
-       if (!context->db_context) {
-           tmpcontext = 1;
-           if ((retval1 = k5dbm_init_context(context)))
-               return(retval1);
-       }
-       retval1 = retval2 = retval3 = 0;
-       if (KDBM_DATA_EXT(context->db_context))
-            retval1 = destroy_file_suffix(dbname, 
-                                          KDBM_DATA_EXT(context->db_context));
-       if (KDBM_INDEX_EXT(context->db_context))
-            retval2 = destroy_file_suffix(dbname, 
-                                         KDBM_INDEX_EXT(context->db_context));
-       retval3 = destroy_file_suffix(dbname,
-                                     KDBM_LOCK_EXT(context->db_context));
-       /*
-        * This kludgery is needed because it is possible to link
-        * against BSD DB but use the ndbm interface.  The result is
-        * that the dispatch table thinks the file extensions are
-        * .dir and .pag, but the database layer uses .db.
-        */
-       if (retval1 == ENOENT && retval2 == ENOENT &&
-           KDBM_INDEX_EXT(context->db_context) &&
-           strcmp(KDBM_INDEX_EXT(context->db_context), ".dir") == 0 &&
-           KDBM_DATA_EXT(context->db_context) &&
-           strcmp(KDBM_DATA_EXT(context->db_context), ".pag") == 0) {
-            retval1 = retval2 = destroy_file_suffix(dbname, ".db");
-       }
-       if (retval1 || retval2 || retval3)
-            return (retval1 ? retval1 : (retval2 ? retval2 : retval3));
-
-       if (tmpcontext) {
-           k5dbm_clear_context((krb5_db_context *) context->db_context);
-           free(context->db_context);
-           context->db_context = (void *) NULL;
-       }
-       return(0);
-}
-
-/*
- * "Atomically" rename the database in a way that locks out read
- * access in the middle of the rename.
- *
- * Not perfect; if we crash in the middle of an update, we don't
- * necessarily know to complete the transaction the rename, but...
- */
-/*
- * Since the rename operation happens outside the init/fini bracket, we
- * have to go through the same stuff that we went through up in db_destroy.
- */
-krb5_error_code
-krb5_dbm_db_rename(context, from, to)
-    krb5_context context;
-    char *from;
-    char *to;
-{
-    DBM *db;
-    char *fromdir = 0;
-    char *todir = 0;
-    char *frompag = 0;
-    char *topag = 0;
-    char *fromok = 0;
-    char *took = 0;
-    krb5_error_code retval;
-    krb5_db_context *s_context, *db_ctx;
-
-    s_context = context->db_context;
-    context->db_context = (void *) NULL;
-    if (!(retval = k5dbm_init_context(context))) {
-       db_ctx = (krb5_db_context *) context->db_context;
-
-       /*
-        * Create the database if it does not already exist; the
-        * files must exist because krb5_dbm_db_lock, called below,
-        * will fail otherwise.
-        */
-       db = KDBM_OPEN(db_ctx, to, O_RDWR|O_CREAT, 0600); 
-       if (db == NULL) {
-            retval = errno;
-            goto errout;
-       }
-       else
-            KDBM_CLOSE(db_ctx, db);
-       
-       /*
-        * Set the database to the target, so that other processes sharing
-        * the target will stop their activity, and notice the new database.
-        */
-       retval = krb5_dbm_db_set_name(context, to);
-       if (retval)
-               goto errout;
-       
-       db_ctx->db_lf_name = gen_dbsuffix(db_ctx->db_name,
-                                         KDBM_LOCK_EXT(db_ctx));
-       if (db_ctx->db_lf_name == (char *)NULL) {
-           retval = ENOMEM;
-           goto errout;
-       }
-
-       db_ctx->db_lf_file = open(db_ctx->db_lf_name, O_RDWR|O_CREAT, 0600);
-       if (db_ctx->db_lf_file < 0) {
-           retval = errno;
-           goto errout;
-       }
-
-       db_ctx->db_inited = 1;
-
-       retval = krb5_dbm_db_get_age(context, NULL, &db_ctx->db_lf_time);
-       if (retval)
-           goto errout;
-    }
-    else
-       return(retval);
-
-    if (KDBM_INDEX_EXT(context->db_context)) {
-       fromdir = gen_dbsuffix (from, KDBM_INDEX_EXT(context->db_context));
-       todir = gen_dbsuffix (to, KDBM_INDEX_EXT(context->db_context));
-       if (!fromdir || !todir) {
-           retval = ENOMEM;
-           goto errout;
-       }
-    }
-
-    if (KDBM_DATA_EXT(context->db_context)) {
-       frompag = gen_dbsuffix (from, KDBM_DATA_EXT(context->db_context));
-       topag = gen_dbsuffix (to, KDBM_DATA_EXT(context->db_context));
-       if (!frompag || !topag) {
-           retval = ENOMEM;
-           goto errout;
-       }
-    }
-
-    if (KDBM_LOCK_EXT(context->db_context)) {
-       fromok = gen_dbsuffix (from, KDBM_LOCK_EXT(context->db_context));
-       took = gen_dbsuffix (to, KDBM_LOCK_EXT(context->db_context));
-       if (!fromok || !took) {
-           retval = ENOMEM;
-           goto errout;
-       }
-    }
-
-    if ((retval = krb5_dbm_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
-       goto errout;
-
-    if ((retval = krb5_dbm_db_start_update(context)))
-       goto errout;
-    
-    if (((!fromdir && !todir) ||
-        (fromdir && todir && (rename (fromdir, todir) == 0))) &&
-       ((!frompag && !topag) ||
-        (frompag && topag && (rename (frompag, topag) == 0)))) {
-           /* We only need to unlink the source lock file */
-           if (fromok)
-               (void) unlink(fromok);
-           retval = krb5_dbm_db_end_update(context);
-    } else {
-        /*
-         * This kludgery is needed because it is possible to link
-         * against BSD DB but use the ndbm interface.  The result is
-         * that the dispatch table thinks the file extensions are
-         * .dir and .pag, but the database layer uses .db.
-         */
-        if (errno == ENOENT &&
-            KDBM_INDEX_EXT(context->db_context) &&
-            strcmp(KDBM_INDEX_EXT(context->db_context), ".dir") == 0 &&
-            KDBM_DATA_EXT(context->db_context) &&
-            strcmp(KDBM_DATA_EXT(context->db_context), ".pag") == 0) {
-             free(fromdir); free(todir); free(frompag); free(topag);
-
-             fromdir = todir = NULL;
-             frompag = gen_dbsuffix (from, ".db");
-             topag = gen_dbsuffix (to, ".db");
-             if (!frompag || !topag) {
-                  retval = ENOMEM;
-                  goto errout;
-             }
-             if (rename(frompag, topag) == 0) {
-                  /* We only need to unlink the source lock file */
-                  if (fromok)
-                       (void) unlink(fromok);
-                  retval = krb5_dbm_db_end_update(context);
-             } else {
-                  retval = errno;
-                  (void) krb5_dbm_db_end_update(context);
-             }
-        } else {
-             retval = errno;
-             (void) krb5_dbm_db_end_update(context);
-        }
-    }
-    
-    
-errout:
-    if (fromok)
-       free_dbsuffix (fromok);
-    if (took)
-       free_dbsuffix (took);
-    if (topag)
-       free_dbsuffix (topag);
-    if (frompag)
-       free_dbsuffix (frompag);
-    if (todir)
-       free_dbsuffix (todir);
-    if (fromdir)
-       free_dbsuffix (fromdir);
-
-    if (context->db_context) {
-       if (db_ctx->db_lf_file >= 0) {
-           krb5_dbm_db_unlock(context);
-           close(db_ctx->db_lf_file);
-       }
-       k5dbm_clear_context((krb5_db_context *) context->db_context);
-       free (context->db_context);
-    }
-
-    context->db_context = s_context;
-    (void) krb5_dbm_db_unlock(context);                /* unlock saved context db */
-
-    return retval;
-}
-
-/*
- * look up a principal in the data base.
- * returns number of entries found, and whether there were
- * more than requested. 
- */
-
-krb5_error_code
-krb5_dbm_db_get_principal(context, searchfor, entries, nentries, more)
-    krb5_context context;
-krb5_const_principal searchfor;
-krb5_db_entry *entries;                /* filled in */
-int *nentries;                         /* how much room/how many found */
-krb5_boolean *more;                    /* are there more? */
-{
-    krb5_error_code retval;
-    datum   key, contents;
-    krb5_db_context *db_ctx;
-    int try;
-
-    *more = FALSE;
-    *nentries = 0;
-
-    if (!k5dbm_inited(context))
-       return KRB5_KDB_DBNOTINITED;
-
-    db_ctx = (krb5_db_context *) context->db_context;
-    for (try = 0; try < KRB5_DBM_MAX_RETRY; try++) {
-       if ((retval = krb5_dbm_db_lock(context, KRB5_LOCKMODE_SHARED))) {
-           if (db_ctx->db_nb_locks) 
-               return(retval);
-           sleep(1);
-           continue;
-       }
-       break;
-    }
-    if (try == KRB5_DBM_MAX_RETRY) 
-       return KRB5_KDB_DB_INUSE;
-
-    /* XXX deal with wildcard lookups */
-    if ((retval = krb5_encode_princ_dbmkey(context, &key, searchfor)))
-        goto cleanup;
-
-    contents = KDBM_FETCH(db_ctx, db_ctx->db_dbm_ctx, key);
-    krb5_free_princ_dbmkey(context, &key);
-
-    if (contents.dptr) 
-       if (!(retval = krb5_decode_princ_contents(context, &contents,entries)))
-           *nentries = 1;
-
-cleanup:
-    (void) krb5_dbm_db_unlock(context);                /* unlock read lock */
-    return retval;
-}
-
-/*
-  Free stuff returned by krb5_dbm_db_get_principal.
- */
-void
-krb5_dbm_db_free_principal(context, entries, nentries)
-    krb5_context context;
-    krb5_db_entry *entries;
-    int nentries;
-{
-    register int i;
-    for (i = 0; i < nentries; i++)
-       krb5_dbe_free_contents(context, &entries[i]);
-    return;
-}
-
-/*
-  Stores the *"nentries" entry structures pointed to by "entries" in the
-  database.
-
-  *"nentries" is updated upon return to reflect the number of records
-  acutally stored; the first *"nstored" records will have been stored in the
-  database (even if an error occurs).
-
- */
-
-krb5_error_code
-krb5_dbm_db_put_principal(context, entries, nentries)
-    krb5_context context;
-    krb5_db_entry *entries;
-    register int *nentries;            /* number of entry structs to update */
-{
-    int i, n;
-    datum   key, contents;
-    krb5_error_code retval;
-    krb5_db_context *db_ctx;
-
-    n = *nentries;
-    *nentries = 0;
-    if (!k5dbm_inited(context))
-       return KRB5_KDB_DBNOTINITED;
-
-    db_ctx = (krb5_db_context *) context->db_context;
-    if ((retval = krb5_dbm_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
-       return retval;
-
-    if ((retval = krb5_dbm_db_start_update(context))) {
-        (void)krb5_dbm_db_unlock(context);             
-       return retval;
-    }
-
-    /* for each one, stuff temps, and do replace/append */
-    for (i = 0; i < n; i++) {
-       if ((retval = krb5_encode_princ_contents(context, &contents,
-                                                entries)))
-           break;
-
-       if ((retval = krb5_encode_princ_dbmkey(context, &key,
-                                              entries->princ))) {
-           krb5_free_princ_contents(context, &contents);
-           break;
-       }
-       if (KDBM_STORE(db_ctx, db_ctx->db_dbm_ctx, key, contents, DBM_REPLACE))
-           retval = errno?errno:KRB5_KDB_DB_CORRUPT;
-
-       krb5_free_princ_contents(context, &contents);
-       krb5_free_princ_dbmkey(context, &key);
-       if (retval)
-           break;
-       entries++;                      /* bump to next struct */
-    }
-
-    (void)krb5_dbm_db_end_update(context);
-    (void)krb5_dbm_db_unlock(context);         /* unlock database */
-    *nentries = i;
-    return(retval);
-}
-
-/*
- * delete a principal from the data base.
- * returns number of entries removed
- */
-
-krb5_error_code
-krb5_dbm_db_delete_principal(context, searchfor, nentries)
-    krb5_context         context;
-    krb5_const_principal  searchfor;
-    int                * nentries;     /* how many found & deleted */
-{
-    krb5_error_code      retval;
-    krb5_db_entry        entry;
-    krb5_db_context    * db_ctx;
-    datum                key, contents, contents2;
-    DBM                * db;
-    int                          i;
-
-    if (!k5dbm_inited(context))
-       return KRB5_KDB_DBNOTINITED;
-
-    db_ctx = (krb5_db_context *) context->db_context;
-    if ((retval = krb5_dbm_db_lock(context, KRB5_LOCKMODE_EXCLUSIVE)))
-       return(retval);
-
-    if ((retval = krb5_dbm_db_start_update(context))) {
-        (void) krb5_dbm_db_unlock(context);    /* unlock write lock */
-       return(retval);
-    }
-
-    if ((retval = krb5_encode_princ_dbmkey(context, &key, searchfor)))
-       goto cleanup;
-
-    db = db_ctx->db_dbm_ctx;
-    contents = KDBM_FETCH(db_ctx, db, key);
-    if (contents.dptr == NULL) {
-       retval = KRB5_KDB_NOENTRY;
-       *nentries = 0;
-    } else {
-       memset((char *)&entry, 0, sizeof(entry));
-       if ((retval = krb5_decode_princ_contents(context, &contents,
-                                                &entry)))
-           goto cleankey;
-       *nentries = 1;
-       /* Clear encrypted key contents */
-       for (i = 0; i < entry.n_key_data; i++) {
-           if (entry.key_data[i].key_data_length[0]) {
-               memset((char *)entry.key_data[i].key_data_contents[0], 0, 
-                      entry.key_data[i].key_data_length[0]); 
-           }
-       }
-       if ((retval = krb5_encode_princ_contents(context, &contents2,
-                                                &entry)))
-           goto cleancontents;
-
-       if (KDBM_STORE(db_ctx, db, key, contents2, DBM_REPLACE))
-           retval = errno?errno:KRB5_KDB_DB_CORRUPT;
-       else {
-           if (KDBM_DELETE(db_ctx, db, key))
-               retval = errno?errno:KRB5_KDB_DB_CORRUPT;
-       }
-       krb5_free_princ_contents(context, &contents2);
-    cleancontents:
-       krb5_dbe_free_contents(context, &entry);
-    cleankey:
-       krb5_free_princ_dbmkey(context, &key);
-    }
-
-cleanup:
-    (void)krb5_dbm_db_end_update(context);
-    (void) krb5_dbm_db_unlock(context);        /* unlock write lock */
-    return retval;
-}
-
-krb5_error_code
-krb5_dbm_db_iterate (context, func, func_arg)
-    krb5_context context;
-    krb5_error_code (*func) (krb5_pointer, krb5_db_entry *);
-    krb5_pointer func_arg;
-{
-    datum key, contents;
-    krb5_db_entry entries;
-    krb5_error_code retval;
-    DBM *db;
-    krb5_db_context *db_ctx;
-    
-    if (!k5dbm_inited(context))
-       return KRB5_KDB_DBNOTINITED;
-
-    db_ctx = (krb5_db_context *) context->db_context;
-    if ((retval = krb5_dbm_db_lock(context, KRB5_LOCKMODE_SHARED)))
-       return retval;
-
-    db = db_ctx->db_dbm_ctx;
-    for (key = KDBM_FIRSTKEY (db_ctx, db);
-        key.dptr != NULL; key = KDBM_NEXTKEY(db_ctx, db)) {
-       contents = KDBM_FETCH (db_ctx, db, key);
-       if ((retval = krb5_decode_princ_contents(context, &contents,
-                                                &entries)))
-           break;
-       retval = (*func)(func_arg, &entries);
-       krb5_dbe_free_contents(context, &entries);
-       if (retval)
-           break;
-    }
-    (void) krb5_dbm_db_unlock(context);
-    return retval;
-}
-
-krb5_boolean
-krb5_dbm_db_set_lockmode(context, mode)
-    krb5_context context;
-    krb5_boolean mode;
-{
-    krb5_boolean old;
-    krb5_db_context *db_ctx;
-
-    old = mode;
-    if ((db_ctx = (krb5_db_context *) context->db_context)) {
-       old = db_ctx->db_nb_locks;
-       db_ctx->db_nb_locks = mode;
-    }
-    return old;
-}
-
-/*
- * Set dispatch table.
- */
-krb5_error_code
-kdb5_db_set_dbops(context, new)
-    krb5_context       context;
-    kdb5_dispatch_table        *new;
-{
-    krb5_error_code    kret;
-    krb5_db_context    *db_ctx;
-
-    kret = KRB5_KDB_DBINITED;
-    if (!k5dbm_inited(context)) {
-       if (!(kret = k5dbm_init_context(context))) {
-           db_ctx = (krb5_db_context *) context->db_context;
-           db_ctx->db_dispatch = (new) ? new : &kdb5_default_dispatch;
-       }
-    }
-    return(kret);
-}
-
-/*
- * Context serialization operations.
- */
-
-/*
- * kdb5_context_size() - Determine size required to serialize.
- */
-static krb5_error_code
-kdb5_context_size(kcontext, arg, sizep)
-    krb5_context       kcontext;
-    krb5_pointer       arg;
-    size_t             *sizep;
-{
-    krb5_error_code    kret;
-    size_t             required;
-    krb5_db_context    *dbctx;
-
-    /*
-     * The database context requires at minimum:
-     * krb5_int32      for KV5M_DB_CONTEXT
-     * krb5_int32      for db_inited
-     * krb5_int32      for database lockfile non-blocking flag
-     * krb5_int32      for database lockfile lock count
-     * krb5_int32      for database lockfile lock mode
-     * krb5_int32      for length of database name.
-     * krb5_int32      for KV5M_DB_CONTEXT
-     */
-    kret = EINVAL;
-    if ((dbctx = (krb5_db_context *) arg)) {
-       required = (sizeof(krb5_int32) * 7);
-       if (dbctx->db_inited && dbctx->db_dispatch && dbctx->db_name)
-           required += strlen(dbctx->db_name);
-       kret = 0;
-       *sizep += required;
-    }
-    return(kret);
-}
-\f
-/*
- * kdb5_context_externalize()  - Externalize the database context.
- */
-static krb5_error_code
-kdb5_context_externalize(kcontext, arg, buffer, lenremain)
-    krb5_context       kcontext;
-    krb5_pointer       arg;
-    krb5_octet         **buffer;
-    size_t             *lenremain;
-{
-    krb5_error_code    kret;
-    krb5_db_context    *dbctx;
-    size_t             required;
-    krb5_octet         *bp;
-    size_t             remain;
-
-    required = 0;
-    bp = *buffer;
-    remain = *lenremain;
-    kret = EINVAL;
-    if ((dbctx = (krb5_db_context *) arg)) {
-       kret = ENOMEM;
-       if (!kdb5_context_size(kcontext, arg, &required) &&
-           (required <= remain)) {
-           /* Write magic number */
-           (void) krb5_ser_pack_int32(KV5M_DB_CONTEXT, &bp, &remain);
-
-           /* Write inited flag */
-           (void) krb5_ser_pack_int32((krb5_int32) dbctx->db_inited,
-                                      &bp, &remain);
-
-           /* Write blocking lock lockmode */
-           (void) krb5_ser_pack_int32((krb5_int32) dbctx->db_nb_locks,
-                                      &bp, &remain);
-
-           /* Write lock count */
-           (void) krb5_ser_pack_int32((krb5_int32)
-                                      (dbctx->db_inited) ?
-                                      dbctx->db_locks_held : 0,
-                                      &bp, &remain);
-
-           /* Write lock mode */
-           (void) krb5_ser_pack_int32((krb5_int32)
-                                      (dbctx->db_inited) ?
-                                      dbctx->db_lock_mode : 0,
-                                      &bp, &remain);
-
-           /* Write length of database name */
-           (void) krb5_ser_pack_int32((dbctx->db_inited && dbctx->db_name) ?
-                                      (krb5_int32) strlen(dbctx->db_name) : 0,
-                                      &bp, &remain);
-           if (dbctx->db_inited && dbctx->db_name)
-               (void) krb5_ser_pack_bytes((krb5_octet *) dbctx->db_name,
-                                          strlen(dbctx->db_name),
-                                          &bp, &remain);
-
-           /* Write trailer */
-           (void) krb5_ser_pack_int32(KV5M_DB_CONTEXT, &bp, &remain);
-           kret = 0;
-           *buffer = bp;
-           *lenremain = remain;
-       }
-    }
-    return(kret);
-}
-\f
-/*
- * kdb5_context_internalize()  - Internalize the database context.
- */
-static krb5_error_code
-kdb5_context_internalize(kcontext, argp, buffer, lenremain)
-    krb5_context       kcontext;
-    krb5_pointer       *argp;
-    krb5_octet         **buffer;
-    size_t             *lenremain;
-{
-    krb5_error_code    kret;
-    krb5_context       tmpctx;
-    krb5_db_context    *dbctx;
-    krb5_int32         ibuf;
-    krb5_octet         *bp;
-    size_t             remain;
-    krb5_int32         iflag;
-    krb5_int32         nb_lockmode;
-    krb5_int32         lockcount;
-    krb5_int32         lockmode;
-    krb5_int32         dbnamelen;
-    char               *dbname;
-
-    bp = *buffer;
-    remain = *lenremain;
-    kret = EINVAL;
-    dbctx = (krb5_db_context *) NULL;
-    /* Read our magic number */
-    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
-       ibuf = 0;
-    if (ibuf == KV5M_DB_CONTEXT) {
-       kret = ENOMEM;
-
-       if (!(kret = krb5_ser_unpack_int32(&iflag, &bp, &remain)) &&
-           !(kret = krb5_ser_unpack_int32(&nb_lockmode, &bp, &remain)) &&
-           !(kret = krb5_ser_unpack_int32(&lockcount, &bp, &remain)) &&
-           !(kret = krb5_ser_unpack_int32(&lockmode, &bp, &remain)) &&
-           !(kret = krb5_ser_unpack_int32(&dbnamelen, &bp, &remain)) &&
-           !(kret = krb5_init_context(&tmpctx))) {
-           if (iflag) {
-               dbname = (char *) NULL;
-               if (dbnamelen &&
-                   (dbname = (char *) malloc((size_t) (dbnamelen+1)))) {
-                   kret = krb5_ser_unpack_bytes((krb5_octet *) dbname,
-                                                (size_t) dbnamelen,
-                                                &bp, &remain);
-                   if (!kret)
-                       dbname[dbnamelen] = '\0';
-               }
-               if (!kret &&
-                   (!dbname || !(kret = krb5_db_set_name(tmpctx, dbname))) &&
-                   !(kret = krb5_db_init(tmpctx))) {
-                   dbctx = (krb5_db_context *) tmpctx->db_context;
-                   (void) krb5_dbm_db_set_lockmode(tmpctx, 0);
-                   if (lockmode)
-                       kret = krb5_db_lock(tmpctx, lockmode);
-                   if (!kret && lockmode)
-                       dbctx->db_locks_held = lockcount;
-                   (void) krb5_dbm_db_set_lockmode(tmpctx, nb_lockmode);
-               }
-               if (dbname)
-                   krb5_xfree(dbname);
-           }
-           if (!kret)
-               kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
-           if (kret || (ibuf != KV5M_DB_CONTEXT))
-               kret = EINVAL;
-
-           if (kret) {
-               if (dbctx)
-                   krb5_db_fini(tmpctx);
-           }
-           else
-               tmpctx->db_context = (void *) NULL;
-           krb5_free_context(tmpctx);
-       }
-    }
-    if (!kret) {
-       *buffer = bp;
-       *lenremain = remain;
-       *argp = (krb5_pointer) dbctx;
-    }
-    return(kret);
-}
-
-/* Dispatch entry */
-static const krb5_ser_entry kdb5_context_ser_entry = {
-    KV5M_DB_CONTEXT,                   /* Type                 */
-    kdb5_context_size,                 /* Sizer routine        */
-    kdb5_context_externalize,          /* Externalize routine  */
-    kdb5_context_internalize           /* Externalize routine  */
-};
-
-/*
- * Register serializer.
- */
-krb5_error_code
-krb5_ser_db_context_init(kcontext)
-    krb5_context       kcontext;
-{
-    return(krb5_register_serializer(kcontext, &kdb5_context_ser_entry));
-}