⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 krb_dbm.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Source: /usr/src/kerberosIV/kdb/RCS/krb_dbm.c,v $ * $Author: sklower $  * * Copyright 1988 by the Massachusetts Institute of Technology.  * * For copying and distribution information, please see the file * <mit-copyright.h>.  */#ifndef	lintstatic char rcsid_krb_dbm_c[] ="$Header: /usr/src/kerberosIV/kdb/RCS/krb_dbm.c,v 4.12 92/12/01 11:52:19 sklower Exp $";#endif	lint#include <sys/types.h>#include <sys/uio.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/resource.h>#include <sys/errno.h>#include <sys/file.h>#include <netinet/in.h>#include <mit-copyright.h>#include <stdio.h>#include <string.h>#include <des.h>#include <krb.h>#include <krb_db.h>#include <ndbm.h>#define KERB_DB_MAX_RETRY 5#ifdef DEBUGextern int debug;extern long kerb_debug;extern char *progname;#endifextern char *malloc();extern int errno;static  init = 0;static char default_db_name[] = DBM_FILE;static char *current_db_name = default_db_name;static void encode_princ_key(), decode_princ_key();static void encode_princ_contents(), decode_princ_contents();static void kerb_dbl_fini();static int kerb_dbl_lock();static void kerb_dbl_unlock();static struct timeval timestamp;/* current time of request */static int non_blocking = 0;/* * This module contains all of the code which directly interfaces to * the underlying representation of the Kerberos database; this * implementation uses a DBM or NDBM indexed "file" (actually * implemented as two separate files) to store the relations, plus a * third file as a semaphore to allow the database to be replaced out * from underneath the KDC server. *//* * 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 (kdb_util, kpropd) 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 * KERB_DB_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. *//* Macros to convert ndbm names to dbm names. * Note that dbm_nextkey() cannot be simply converted using a macro, since * it is invoked giving the database, and nextkey() needs the previous key. * * Instead, all routines call "dbm_next" instead. */#define dbm_next(db,key) dbm_nextkey(db)/* * Utility routine: generate name of database file. */static char *gen_dbsuffix(db_name, sfx)    char *db_name;    char *sfx;{    char *dbsuffix;        if (sfx == NULL)	sfx = ".ok";    dbsuffix = malloc (strlen(db_name) + strlen(sfx) + 1);    strcpy(dbsuffix, db_name);    strcat(dbsuffix, sfx);    return dbsuffix;}/* * initialization for data base routines. */kerb_db_init(){    init = 1;    return (0);}/* * gracefully shut down database--must be called by ANY program that does * a kerb_db_init  */kerb_db_fini(){}/* * 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. */kerb_db_set_name(name)	char *name;{    DBM *db;    if (name == NULL)	name = default_db_name;    db = dbm_open(name, 0, 0);    if (db == NULL)	return errno;    dbm_close(db);    kerb_dbl_fini();    current_db_name = name;    return 0;}/* * Return the last modification time of the database. */long kerb_get_db_age(){    struct stat st;    char *okname;    long age;        okname = gen_dbsuffix(current_db_name, ".ok");    if (stat (okname, &st) < 0)	age = 0;    else	age = st.st_mtime;    free (okname);    return age;}/* * 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 long kerb_start_update(db_name)    char *db_name;{    char *okname = gen_dbsuffix(db_name, ".ok");    long age = kerb_get_db_age();        if (unlink(okname) < 0	&& errno != ENOENT) {	    age = -1;    }    free (okname);    return age;}static long kerb_end_update(db_name, age)    char *db_name;    long age;{    int fd;    int retval = 0;    char *new_okname = gen_dbsuffix(db_name, ".ok#");    char *okname = gen_dbsuffix(db_name, ".ok");        fd = open (new_okname, O_CREAT|O_RDWR|O_TRUNC, 0600);    if (fd < 0)	retval = errno;    else {	struct stat st;	struct timeval tv[2];	/* make sure that semaphore is "after" previous value. */	if (fstat (fd, &st) == 0	    && st.st_mtime <= age) {	    tv[0].tv_sec = st.st_atime;	    tv[0].tv_usec = 0;	    tv[1].tv_sec = age;	    tv[1].tv_usec = 0;	    /* set times.. */	    utimes (new_okname, tv);	    fsync(fd);	}	close(fd);	if (rename (new_okname, okname) < 0)	    retval = errno;    }    free (new_okname);    free (okname);    return retval;}static long kerb_start_read(){    return kerb_get_db_age();}static long kerb_end_read(age)    u_long age;{    if (kerb_get_db_age() != age || age == -1) {	return -1;    }    return 0;}/* * Create the database, assuming it's not there. */kerb_db_create(db_name)    char *db_name;{    char *okname = gen_dbsuffix(db_name, ".ok");    int fd;    register int ret = 0;    DBM *db;    db = dbm_open(db_name, O_RDWR|O_CREAT|O_EXCL, 0600);    if (db == NULL)	ret = errno;    else	dbm_close(db);    if (ret == 0) {	fd = open (okname, O_CREAT|O_RDWR|O_TRUNC, 0600);	if (fd < 0)	    ret = errno;	close(fd);    }    return ret;}/* * "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... */kerb_db_rename(from, to)    char *from;    char *to;{    char *fromdir = gen_dbsuffix (from, ".db");    char *todir = gen_dbsuffix (to, ".db");    char *fromok = gen_dbsuffix(from, ".ok");    long trans = kerb_start_update(to);    int ok = 0;        if (rename (fromdir, todir) == 0) {	(void) unlink (fromok);	ok = 1;    }    free (fromok);    free (fromdir);    free (todir);    if (ok)	return kerb_end_update(to, trans);    else	return -1;}/* * look up a principal in the data base returns number of principals * found , and whether there were more than requested.  */kerb_db_get_principal(name, inst, principal, max, more)    char   *name;		/* could have wild card */    char   *inst;		/* could have wild card */    Principal *principal;    unsigned int max;		/* max number of name structs to return */    int    *more;		/* where there more than 'max' tuples? */{    int     found = 0, code;    extern int errorproc();    int     wildp, wildi;    datum   key, contents;    char    testname[ANAME_SZ], testinst[INST_SZ];    u_long trans;    int try;    DBM    *db;    if (!init)	kerb_db_init();		/* initialize database routines */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -