1004388ebScasper /*
254925bf6Swillf * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3004388ebScasper * Use is subject to license terms.
4004388ebScasper */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate /*
7*55fea89dSDan Cross * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * Openvision retains the copyright to derivative works of
107c478bd9Sstevel@tonic-gate * this source code. Do *NOT* create a derivative of this
117c478bd9Sstevel@tonic-gate * source code before consulting with your legal department.
127c478bd9Sstevel@tonic-gate * Do *NOT* integrate *ANY* of this source code into another
137c478bd9Sstevel@tonic-gate * product before consulting with your legal department.
147c478bd9Sstevel@tonic-gate *
157c478bd9Sstevel@tonic-gate * For further information, read the top-level Openvision
167c478bd9Sstevel@tonic-gate * copyright which is contained in the top-level MIT Kerberos
177c478bd9Sstevel@tonic-gate * copyright.
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
207c478bd9Sstevel@tonic-gate *
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate
237c478bd9Sstevel@tonic-gate
247c478bd9Sstevel@tonic-gate /*
257c478bd9Sstevel@tonic-gate * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <sys/file.h>
297c478bd9Sstevel@tonic-gate #include <fcntl.h>
307c478bd9Sstevel@tonic-gate #include <unistd.h>
3154925bf6Swillf #include <k5-int.h>
3254925bf6Swillf #include "policy_db.h"
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
3454925bf6Swillf #include <db.h>
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate #define MAX_LOCK_TRIES 5
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate struct _locklist {
397c478bd9Sstevel@tonic-gate osa_adb_lock_ent lockinfo;
407c478bd9Sstevel@tonic-gate struct _locklist *next;
417c478bd9Sstevel@tonic-gate };
427c478bd9Sstevel@tonic-gate
osa_adb_create_db(char * filename,char * lockfilename,int magic)4354925bf6Swillf krb5_error_code osa_adb_create_db(char *filename, char *lockfilename,
4454925bf6Swillf int magic)
457c478bd9Sstevel@tonic-gate {
467c478bd9Sstevel@tonic-gate int lf;
477c478bd9Sstevel@tonic-gate DB *db;
4856a424ccSmp BTREEINFO btinfo;
49*55fea89dSDan Cross
5056a424ccSmp memset(&btinfo, 0, sizeof(btinfo));
5156a424ccSmp btinfo.flags = 0;
5256a424ccSmp btinfo.cachesize = 0;
5356a424ccSmp btinfo.psize = 4096;
5456a424ccSmp btinfo.lorder = 0;
5556a424ccSmp btinfo.minkeypage = 0;
5656a424ccSmp btinfo.compare = NULL;
5756a424ccSmp btinfo.prefix = NULL;
5856a424ccSmp db = dbopen(filename, O_RDWR | O_CREAT | O_EXCL, 0600, DB_BTREE, &btinfo);
597c478bd9Sstevel@tonic-gate if (db == NULL)
607c478bd9Sstevel@tonic-gate return errno;
617c478bd9Sstevel@tonic-gate if (db->close(db) < 0)
627c478bd9Sstevel@tonic-gate return errno;
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate /* only create the lock file if we successfully created the db */
657c478bd9Sstevel@tonic-gate lf = THREEPARAMOPEN(lockfilename, O_RDWR | O_CREAT | O_EXCL, 0600);
667c478bd9Sstevel@tonic-gate if (lf == -1)
677c478bd9Sstevel@tonic-gate return errno;
687c478bd9Sstevel@tonic-gate (void) close(lf);
69*55fea89dSDan Cross
707c478bd9Sstevel@tonic-gate return OSA_ADB_OK;
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate
osa_adb_destroy_db(char * filename,char * lockfilename,int magic)7354925bf6Swillf krb5_error_code osa_adb_destroy_db(char *filename, char *lockfilename,
747c478bd9Sstevel@tonic-gate int magic)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate /* the admin databases do not contain security-critical data */
777c478bd9Sstevel@tonic-gate if (unlink(filename) < 0 ||
787c478bd9Sstevel@tonic-gate unlink(lockfilename) < 0)
797c478bd9Sstevel@tonic-gate return errno;
807c478bd9Sstevel@tonic-gate return OSA_ADB_OK;
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate
osa_adb_rename_db(char * filefrom,char * lockfrom,char * fileto,char * lockto,int magic)8354925bf6Swillf krb5_error_code osa_adb_rename_db(char *filefrom, char *lockfrom,
847c478bd9Sstevel@tonic-gate char *fileto, char *lockto, int magic)
857c478bd9Sstevel@tonic-gate {
867c478bd9Sstevel@tonic-gate osa_adb_db_t fromdb, todb;
8754925bf6Swillf krb5_error_code ret;
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate /* make sure todb exists */
9054925bf6Swillf /*LINTED*/
917c478bd9Sstevel@tonic-gate if ((ret = osa_adb_create_db(fileto, lockto, magic)) &&
927c478bd9Sstevel@tonic-gate ret != EEXIST)
937c478bd9Sstevel@tonic-gate return ret;
947c478bd9Sstevel@tonic-gate
9556a424ccSmp if ((ret = osa_adb_init_db(&fromdb, filefrom, lockfrom, magic)))
967c478bd9Sstevel@tonic-gate return ret;
9756a424ccSmp if ((ret = osa_adb_init_db(&todb, fileto, lockto, magic))) {
987c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(fromdb, magic);
997c478bd9Sstevel@tonic-gate return ret;
1007c478bd9Sstevel@tonic-gate }
10154925bf6Swillf if ((ret = osa_adb_get_lock(fromdb, KRB5_DB_LOCKMODE_PERMANENT))) {
1027c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(fromdb, magic);
1037c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(todb, magic);
1047c478bd9Sstevel@tonic-gate return ret;
1057c478bd9Sstevel@tonic-gate }
10654925bf6Swillf if ((ret = osa_adb_get_lock(todb, KRB5_DB_LOCKMODE_PERMANENT))) {
1077c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(fromdb, magic);
1087c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(todb, magic);
1097c478bd9Sstevel@tonic-gate return ret;
1107c478bd9Sstevel@tonic-gate }
11156a424ccSmp if ((rename(filefrom, fileto) < 0)) {
1127c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(fromdb, magic);
1137c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(todb, magic);
1147c478bd9Sstevel@tonic-gate return errno;
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate * Do not release the lock on fromdb because it is being renamed
1187c478bd9Sstevel@tonic-gate * out of existence; no one can ever use it again.
1197c478bd9Sstevel@tonic-gate */
12056a424ccSmp if ((ret = osa_adb_release_lock(todb))) {
1217c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(fromdb, magic);
1227c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(todb, magic);
1237c478bd9Sstevel@tonic-gate return ret;
1247c478bd9Sstevel@tonic-gate }
125*55fea89dSDan Cross
1267c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(fromdb, magic);
1277c478bd9Sstevel@tonic-gate (void) osa_adb_fini_db(todb, magic);
1287c478bd9Sstevel@tonic-gate return 0;
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate
osa_adb_init_db(osa_adb_db_t * dbp,char * filename,char * lockfilename,int magic)13154925bf6Swillf krb5_error_code osa_adb_init_db(osa_adb_db_t *dbp, char *filename,
1327c478bd9Sstevel@tonic-gate char *lockfilename, int magic)
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate osa_adb_db_t db;
1357c478bd9Sstevel@tonic-gate static struct _locklist *locklist = NULL;
1367c478bd9Sstevel@tonic-gate struct _locklist *lockp;
1377c478bd9Sstevel@tonic-gate krb5_error_code code;
138*55fea89dSDan Cross
1397c478bd9Sstevel@tonic-gate if (dbp == NULL || filename == NULL)
1407c478bd9Sstevel@tonic-gate return EINVAL;
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate db = (osa_adb_princ_t) malloc(sizeof(osa_adb_db_ent));
1437c478bd9Sstevel@tonic-gate if (db == NULL)
1447c478bd9Sstevel@tonic-gate return ENOMEM;
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate memset(db, 0, sizeof(*db));
1477c478bd9Sstevel@tonic-gate db->info.hash = NULL;
1487c478bd9Sstevel@tonic-gate db->info.bsize = 256;
1497c478bd9Sstevel@tonic-gate db->info.ffactor = 8;
1507c478bd9Sstevel@tonic-gate db->info.nelem = 25000;
1517c478bd9Sstevel@tonic-gate db->info.lorder = 0;
1527c478bd9Sstevel@tonic-gate
15356a424ccSmp db->btinfo.flags = 0;
15456a424ccSmp db->btinfo.cachesize = 0;
15556a424ccSmp db->btinfo.psize = 4096;
15656a424ccSmp db->btinfo.lorder = 0;
15756a424ccSmp db->btinfo.minkeypage = 0;
15856a424ccSmp db->btinfo.compare = NULL;
15956a424ccSmp db->btinfo.prefix = NULL;
1607c478bd9Sstevel@tonic-gate /*
1617c478bd9Sstevel@tonic-gate * A process is allowed to open the same database multiple times
1627c478bd9Sstevel@tonic-gate * and access it via different handles. If the handles use
1637c478bd9Sstevel@tonic-gate * distinct lockinfo structures, things get confused: lock(A),
1647c478bd9Sstevel@tonic-gate * lock(B), release(B) will result in the kernel unlocking the
1657c478bd9Sstevel@tonic-gate * lock file but handle A will still think the file is locked.
1667c478bd9Sstevel@tonic-gate * Therefore, all handles using the same lock file must share a
1677c478bd9Sstevel@tonic-gate * single lockinfo structure.
1687c478bd9Sstevel@tonic-gate *
1697c478bd9Sstevel@tonic-gate * It is not sufficient to have a single lockinfo structure,
1707c478bd9Sstevel@tonic-gate * however, because a single process may also wish to open
1717c478bd9Sstevel@tonic-gate * multiple different databases simultaneously, with different
1727c478bd9Sstevel@tonic-gate * lock files. This code used to use a single static lockinfo
1737c478bd9Sstevel@tonic-gate * structure, which means that the second database opened used
1747c478bd9Sstevel@tonic-gate * the first database's lock file. This was Bad.
1757c478bd9Sstevel@tonic-gate *
1767c478bd9Sstevel@tonic-gate * We now maintain a linked list of lockinfo structures, keyed by
1777c478bd9Sstevel@tonic-gate * lockfilename. An entry is added when this function is called
1787c478bd9Sstevel@tonic-gate * with a new lockfilename, and all subsequent calls with that
1797c478bd9Sstevel@tonic-gate * lockfilename use the existing entry, updating the refcnt.
1807c478bd9Sstevel@tonic-gate * When the database is closed with fini_db(), the refcnt is
1817c478bd9Sstevel@tonic-gate * decremented, and when it is zero the lockinfo structure is
1827c478bd9Sstevel@tonic-gate * freed and reset. The entry in the linked list, however, is
1837c478bd9Sstevel@tonic-gate * never removed; it will just be reinitialized the next time
1847c478bd9Sstevel@tonic-gate * init_db is called with the right lockfilename.
1857c478bd9Sstevel@tonic-gate */
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate /* find or create the lockinfo structure for lockfilename */
1887c478bd9Sstevel@tonic-gate lockp = locklist;
1897c478bd9Sstevel@tonic-gate while (lockp) {
1907c478bd9Sstevel@tonic-gate if (strcmp(lockp->lockinfo.filename, lockfilename) == 0)
1917c478bd9Sstevel@tonic-gate break;
1927c478bd9Sstevel@tonic-gate else
1937c478bd9Sstevel@tonic-gate lockp = lockp->next;
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate if (lockp == NULL) {
1967c478bd9Sstevel@tonic-gate /* doesn't exist, create it, add to list */
1977c478bd9Sstevel@tonic-gate lockp = (struct _locklist *) malloc(sizeof(*lockp));
1987c478bd9Sstevel@tonic-gate if (lockp == NULL) {
1997c478bd9Sstevel@tonic-gate free(db);
2007c478bd9Sstevel@tonic-gate return ENOMEM;
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate memset(lockp, 0, sizeof(*lockp));
2037c478bd9Sstevel@tonic-gate lockp->next = locklist;
2047c478bd9Sstevel@tonic-gate locklist = lockp;
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate /* now initialize lockp->lockinfo if necessary */
2087c478bd9Sstevel@tonic-gate if (lockp->lockinfo.lockfile == NULL) {
20954925bf6Swillf if ((code = krb5int_init_context_kdc(&lockp->lockinfo.context))) {
2107c478bd9Sstevel@tonic-gate free(db);
21154925bf6Swillf return((krb5_error_code) code);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate * needs be open read/write so that write locking can work with
2167c478bd9Sstevel@tonic-gate * POSIX systems
2177c478bd9Sstevel@tonic-gate */
2187c478bd9Sstevel@tonic-gate lockp->lockinfo.filename = strdup(lockfilename);
219004388ebScasper if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+F")) == NULL) {
2207c478bd9Sstevel@tonic-gate /*
2217c478bd9Sstevel@tonic-gate * maybe someone took away write permission so we could only
2227c478bd9Sstevel@tonic-gate * get shared locks?
2237c478bd9Sstevel@tonic-gate */
224004388ebScasper if ((lockp->lockinfo.lockfile = fopen(lockfilename, "rF"))
2257c478bd9Sstevel@tonic-gate == NULL) {
2267c478bd9Sstevel@tonic-gate free(db);
2277c478bd9Sstevel@tonic-gate return OSA_ADB_NOLOCKFILE;
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate lockp->lockinfo.lockmode = lockp->lockinfo.lockcnt = 0;
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate /* lockp is set, lockinfo is initialized, update the reference count */
2347c478bd9Sstevel@tonic-gate db->lock = &lockp->lockinfo;
2357c478bd9Sstevel@tonic-gate db->lock->refcnt++;
2367c478bd9Sstevel@tonic-gate
23756a424ccSmp db->opencnt = 0;
2387c478bd9Sstevel@tonic-gate db->filename = strdup(filename);
2397c478bd9Sstevel@tonic-gate db->magic = magic;
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate *dbp = db;
242*55fea89dSDan Cross
2437c478bd9Sstevel@tonic-gate return OSA_ADB_OK;
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate
osa_adb_fini_db(osa_adb_db_t db,int magic)24654925bf6Swillf krb5_error_code osa_adb_fini_db(osa_adb_db_t db, int magic)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate if (db->magic != magic)
2497c478bd9Sstevel@tonic-gate return EINVAL;
2507c478bd9Sstevel@tonic-gate if (db->lock->refcnt == 0) {
2517c478bd9Sstevel@tonic-gate /* barry says this can't happen */
2527c478bd9Sstevel@tonic-gate return OSA_ADB_FAILURE;
2537c478bd9Sstevel@tonic-gate } else {
2547c478bd9Sstevel@tonic-gate db->lock->refcnt--;
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate if (db->lock->refcnt == 0) {
2587c478bd9Sstevel@tonic-gate /*
2597c478bd9Sstevel@tonic-gate * Don't free db->lock->filename, it is used as a key to
2607c478bd9Sstevel@tonic-gate * find the lockinfo entry in the linked list. If the
2617c478bd9Sstevel@tonic-gate * lockfile doesn't exist, we must be closing the database
2627c478bd9Sstevel@tonic-gate * after trashing it. This has to be allowed, so don't
2637c478bd9Sstevel@tonic-gate * generate an error.
2647c478bd9Sstevel@tonic-gate */
26554925bf6Swillf if (db->lock->lockmode != KRB5_DB_LOCKMODE_PERMANENT)
2667c478bd9Sstevel@tonic-gate (void) fclose(db->lock->lockfile);
2677c478bd9Sstevel@tonic-gate db->lock->lockfile = NULL;
2687c478bd9Sstevel@tonic-gate krb5_free_context(db->lock->context);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate db->magic = 0;
2727c478bd9Sstevel@tonic-gate free(db->filename);
2737c478bd9Sstevel@tonic-gate free(db);
2747c478bd9Sstevel@tonic-gate return OSA_ADB_OK;
275*55fea89dSDan Cross }
276*55fea89dSDan Cross
osa_adb_get_lock(osa_adb_db_t db,int mode)27754925bf6Swillf krb5_error_code osa_adb_get_lock(osa_adb_db_t db, int mode)
2787c478bd9Sstevel@tonic-gate {
27954925bf6Swillf int tries, gotlock, perm, krb5_mode, ret = 0;
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate if (db->lock->lockmode >= mode) {
2827c478bd9Sstevel@tonic-gate /* No need to upgrade lock, just incr refcnt and return */
2837c478bd9Sstevel@tonic-gate db->lock->lockcnt++;
2847c478bd9Sstevel@tonic-gate return(OSA_ADB_OK);
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate perm = 0;
2887c478bd9Sstevel@tonic-gate switch (mode) {
28954925bf6Swillf case KRB5_DB_LOCKMODE_PERMANENT:
2907c478bd9Sstevel@tonic-gate perm = 1;
2910b16192fSToomas Soome /* FALLTHROUGH */
29254925bf6Swillf case KRB5_DB_LOCKMODE_EXCLUSIVE:
2937c478bd9Sstevel@tonic-gate krb5_mode = KRB5_LOCKMODE_EXCLUSIVE;
2947c478bd9Sstevel@tonic-gate break;
29554925bf6Swillf case KRB5_DB_LOCKMODE_SHARED:
2967c478bd9Sstevel@tonic-gate krb5_mode = KRB5_LOCKMODE_SHARED;
2977c478bd9Sstevel@tonic-gate break;
2987c478bd9Sstevel@tonic-gate default:
2997c478bd9Sstevel@tonic-gate return(EINVAL);
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate for (gotlock = tries = 0; tries < MAX_LOCK_TRIES; tries++) {
3037c478bd9Sstevel@tonic-gate if ((ret = krb5_lock_file(db->lock->context,
3047c478bd9Sstevel@tonic-gate fileno(db->lock->lockfile),
3057c478bd9Sstevel@tonic-gate krb5_mode|KRB5_LOCKMODE_DONTBLOCK)) == 0) {
3067c478bd9Sstevel@tonic-gate gotlock++;
3077c478bd9Sstevel@tonic-gate break;
30854925bf6Swillf } else if (ret == EBADF && mode == KRB5_DB_LOCKMODE_EXCLUSIVE)
3097c478bd9Sstevel@tonic-gate /* tried to exclusive-lock something we don't have */
3107c478bd9Sstevel@tonic-gate /* write access to */
3117c478bd9Sstevel@tonic-gate return OSA_ADB_NOEXCL_PERM;
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate sleep(1);
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate /* test for all the likely "can't get lock" error codes */
3177c478bd9Sstevel@tonic-gate if (ret == EACCES || ret == EAGAIN || ret == EWOULDBLOCK)
3187c478bd9Sstevel@tonic-gate return OSA_ADB_CANTLOCK_DB;
3197c478bd9Sstevel@tonic-gate else if (ret != 0)
3207c478bd9Sstevel@tonic-gate return ret;
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate /*
3237c478bd9Sstevel@tonic-gate * If the file no longer exists, someone acquired a permanent
3247c478bd9Sstevel@tonic-gate * lock. If that process terminates its exclusive lock is lost,
3257c478bd9Sstevel@tonic-gate * but if we already had the file open we can (probably) lock it
3267c478bd9Sstevel@tonic-gate * even though it has been unlinked. So we need to insist that
3277c478bd9Sstevel@tonic-gate * it exist.
3287c478bd9Sstevel@tonic-gate */
3297c478bd9Sstevel@tonic-gate if (access(db->lock->filename, F_OK) < 0) {
3307c478bd9Sstevel@tonic-gate (void) krb5_lock_file(db->lock->context,
3317c478bd9Sstevel@tonic-gate fileno(db->lock->lockfile),
3327c478bd9Sstevel@tonic-gate KRB5_LOCKMODE_UNLOCK);
3337c478bd9Sstevel@tonic-gate return OSA_ADB_NOLOCKFILE;
3347c478bd9Sstevel@tonic-gate }
335*55fea89dSDan Cross
3367c478bd9Sstevel@tonic-gate /* we have the shared/exclusive lock */
337*55fea89dSDan Cross
3387c478bd9Sstevel@tonic-gate if (perm) {
3397c478bd9Sstevel@tonic-gate if (unlink(db->lock->filename) < 0) {
3407c478bd9Sstevel@tonic-gate /* somehow we can't delete the file, but we already */
3417c478bd9Sstevel@tonic-gate /* have the lock, so release it and return */
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate ret = errno;
3447c478bd9Sstevel@tonic-gate (void) krb5_lock_file(db->lock->context,
3457c478bd9Sstevel@tonic-gate fileno(db->lock->lockfile),
3467c478bd9Sstevel@tonic-gate KRB5_LOCKMODE_UNLOCK);
347*55fea89dSDan Cross
3487c478bd9Sstevel@tonic-gate /* maybe we should return CANTLOCK_DB.. but that would */
3497c478bd9Sstevel@tonic-gate /* look just like the db was already locked */
3507c478bd9Sstevel@tonic-gate return ret;
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate /* this releases our exclusive lock.. which is okay because */
3547c478bd9Sstevel@tonic-gate /* now no one else can get one either */
3557c478bd9Sstevel@tonic-gate (void) fclose(db->lock->lockfile);
3567c478bd9Sstevel@tonic-gate }
357*55fea89dSDan Cross
3587c478bd9Sstevel@tonic-gate db->lock->lockmode = mode;
3597c478bd9Sstevel@tonic-gate db->lock->lockcnt++;
3607c478bd9Sstevel@tonic-gate return OSA_ADB_OK;
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate
osa_adb_release_lock(osa_adb_db_t db)36354925bf6Swillf krb5_error_code osa_adb_release_lock(osa_adb_db_t db)
3647c478bd9Sstevel@tonic-gate {
3657c478bd9Sstevel@tonic-gate int ret, fd;
366*55fea89dSDan Cross
3677c478bd9Sstevel@tonic-gate if (!db->lock->lockcnt) /* lock already unlocked */
3687c478bd9Sstevel@tonic-gate return OSA_ADB_NOTLOCKED;
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate if (--db->lock->lockcnt == 0) {
37154925bf6Swillf if (db->lock->lockmode == KRB5_DB_LOCKMODE_PERMANENT) {
3727c478bd9Sstevel@tonic-gate /* now we need to create the file since it does not exist */
3737c478bd9Sstevel@tonic-gate fd = THREEPARAMOPEN(db->lock->filename,O_RDWR | O_CREAT | O_EXCL,
3747c478bd9Sstevel@tonic-gate 0600);
375004388ebScasper if ((db->lock->lockfile = fdopen(fd, "w+F")) == NULL)
3767c478bd9Sstevel@tonic-gate return OSA_ADB_NOLOCKFILE;
37756a424ccSmp } else if ((ret = krb5_lock_file(db->lock->context,
3787c478bd9Sstevel@tonic-gate fileno(db->lock->lockfile),
37956a424ccSmp KRB5_LOCKMODE_UNLOCK)))
3807c478bd9Sstevel@tonic-gate return ret;
381*55fea89dSDan Cross
3827c478bd9Sstevel@tonic-gate db->lock->lockmode = 0;
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate return OSA_ADB_OK;
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate
osa_adb_open_and_lock(osa_adb_princ_t db,int locktype)38754925bf6Swillf krb5_error_code osa_adb_open_and_lock(osa_adb_princ_t db, int locktype)
3887c478bd9Sstevel@tonic-gate {
3897c478bd9Sstevel@tonic-gate int ret;
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate ret = osa_adb_get_lock(db, locktype);
3927c478bd9Sstevel@tonic-gate if (ret != OSA_ADB_OK)
3937c478bd9Sstevel@tonic-gate return ret;
39456a424ccSmp if (db->opencnt)
39556a424ccSmp goto open_ok;
39656a424ccSmp
39756a424ccSmp db->db = dbopen(db->filename, O_RDWR, 0600, DB_BTREE, &db->btinfo);
39856a424ccSmp if (db->db != NULL)
39956a424ccSmp goto open_ok;
40056a424ccSmp switch (errno) {
40156a424ccSmp #ifdef EFTYPE
40256a424ccSmp case EFTYPE:
40356a424ccSmp #endif
40456a424ccSmp case EINVAL:
40556a424ccSmp db->db = dbopen(db->filename, O_RDWR, 0600, DB_HASH, &db->info);
40656a424ccSmp if (db->db != NULL)
40756a424ccSmp goto open_ok;
4080b16192fSToomas Soome /* FALLTHROUGH */
40956a424ccSmp default:
4107c478bd9Sstevel@tonic-gate (void) osa_adb_release_lock(db);
41156a424ccSmp if (errno == EINVAL)
4127c478bd9Sstevel@tonic-gate return OSA_ADB_BAD_DB;
4137c478bd9Sstevel@tonic-gate return errno;
4147c478bd9Sstevel@tonic-gate }
41556a424ccSmp open_ok:
41656a424ccSmp db->opencnt++;
4177c478bd9Sstevel@tonic-gate return OSA_ADB_OK;
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate
osa_adb_close_and_unlock(osa_adb_princ_t db)42054925bf6Swillf krb5_error_code osa_adb_close_and_unlock(osa_adb_princ_t db)
4217c478bd9Sstevel@tonic-gate {
42256a424ccSmp if (--db->opencnt)
42356a424ccSmp return osa_adb_release_lock(db);
42456a424ccSmp if(db->db != NULL && db->db->close(db->db) == -1) {
4257c478bd9Sstevel@tonic-gate (void) osa_adb_release_lock(db);
4267c478bd9Sstevel@tonic-gate return OSA_ADB_FAILURE;
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate
4297c478bd9Sstevel@tonic-gate db->db = NULL;
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate return(osa_adb_release_lock(db));
4327c478bd9Sstevel@tonic-gate }
433