xref: /freebsd/crypto/krb5/src/plugins/kdb/db2/adb_openclose.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert  * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
4*7f2fe78bSCy Schubert  *
5*7f2fe78bSCy Schubert  * $Header$
6*7f2fe78bSCy Schubert  */
7*7f2fe78bSCy Schubert 
8*7f2fe78bSCy Schubert #include        <k5-int.h>
9*7f2fe78bSCy Schubert #include        <sys/file.h>
10*7f2fe78bSCy Schubert #include        <fcntl.h>
11*7f2fe78bSCy Schubert #include        <unistd.h>
12*7f2fe78bSCy Schubert #include        "policy_db.h"
13*7f2fe78bSCy Schubert #include        <stdlib.h>
14*7f2fe78bSCy Schubert #include        <db.h>
15*7f2fe78bSCy Schubert 
16*7f2fe78bSCy Schubert struct _locklist {
17*7f2fe78bSCy Schubert     osa_adb_lock_ent lockinfo;
18*7f2fe78bSCy Schubert     struct _locklist *next;
19*7f2fe78bSCy Schubert };
20*7f2fe78bSCy Schubert 
21*7f2fe78bSCy Schubert krb5_error_code
osa_adb_create_db(char * filename,char * lockfilename,int magic)22*7f2fe78bSCy Schubert osa_adb_create_db(char *filename, char *lockfilename, int magic)
23*7f2fe78bSCy Schubert {
24*7f2fe78bSCy Schubert     int lf;
25*7f2fe78bSCy Schubert     DB *db;
26*7f2fe78bSCy Schubert     BTREEINFO btinfo;
27*7f2fe78bSCy Schubert 
28*7f2fe78bSCy Schubert     memset(&btinfo, 0, sizeof(btinfo));
29*7f2fe78bSCy Schubert     btinfo.flags = 0;
30*7f2fe78bSCy Schubert     btinfo.cachesize = 0;
31*7f2fe78bSCy Schubert     btinfo.psize = 4096;
32*7f2fe78bSCy Schubert     btinfo.lorder = 0;
33*7f2fe78bSCy Schubert     btinfo.minkeypage = 0;
34*7f2fe78bSCy Schubert     btinfo.compare = NULL;
35*7f2fe78bSCy Schubert     btinfo.prefix = NULL;
36*7f2fe78bSCy Schubert     db = dbopen(filename, O_RDWR | O_CREAT | O_EXCL, 0600, DB_BTREE, &btinfo);
37*7f2fe78bSCy Schubert     if (db == NULL)
38*7f2fe78bSCy Schubert         return errno;
39*7f2fe78bSCy Schubert     if (db->close(db) < 0)
40*7f2fe78bSCy Schubert         return errno;
41*7f2fe78bSCy Schubert 
42*7f2fe78bSCy Schubert     /* only create the lock file if we successfully created the db */
43*7f2fe78bSCy Schubert     lf = THREEPARAMOPEN(lockfilename, O_RDWR | O_CREAT | O_EXCL, 0600);
44*7f2fe78bSCy Schubert     if (lf == -1)
45*7f2fe78bSCy Schubert         return errno;
46*7f2fe78bSCy Schubert     (void) close(lf);
47*7f2fe78bSCy Schubert 
48*7f2fe78bSCy Schubert     return OSA_ADB_OK;
49*7f2fe78bSCy Schubert }
50*7f2fe78bSCy Schubert 
51*7f2fe78bSCy Schubert krb5_error_code
osa_adb_destroy_db(char * filename,char * lockfilename,int magic)52*7f2fe78bSCy Schubert osa_adb_destroy_db(char *filename, char *lockfilename, int magic)
53*7f2fe78bSCy Schubert {
54*7f2fe78bSCy Schubert     /* the admin databases do not contain security-critical data */
55*7f2fe78bSCy Schubert     if (unlink(filename) < 0 ||
56*7f2fe78bSCy Schubert         unlink(lockfilename) < 0)
57*7f2fe78bSCy Schubert         return errno;
58*7f2fe78bSCy Schubert     return OSA_ADB_OK;
59*7f2fe78bSCy Schubert }
60*7f2fe78bSCy Schubert 
61*7f2fe78bSCy Schubert krb5_error_code
osa_adb_init_db(osa_adb_db_t * dbp,char * filename,char * lockfilename,int magic)62*7f2fe78bSCy Schubert osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename,
63*7f2fe78bSCy Schubert                 int magic)
64*7f2fe78bSCy Schubert {
65*7f2fe78bSCy Schubert     osa_adb_db_t db;
66*7f2fe78bSCy Schubert     static struct _locklist *locklist = NULL;
67*7f2fe78bSCy Schubert     struct _locklist *lockp;
68*7f2fe78bSCy Schubert     krb5_error_code code;
69*7f2fe78bSCy Schubert 
70*7f2fe78bSCy Schubert     if (dbp == NULL || filename == NULL)
71*7f2fe78bSCy Schubert         return EINVAL;
72*7f2fe78bSCy Schubert 
73*7f2fe78bSCy Schubert     db = (osa_adb_princ_t) malloc(sizeof(osa_adb_db_ent));
74*7f2fe78bSCy Schubert     if (db == NULL)
75*7f2fe78bSCy Schubert         return ENOMEM;
76*7f2fe78bSCy Schubert 
77*7f2fe78bSCy Schubert     memset(db, 0, sizeof(*db));
78*7f2fe78bSCy Schubert     db->info.hash = NULL;
79*7f2fe78bSCy Schubert     db->info.bsize = 256;
80*7f2fe78bSCy Schubert     db->info.ffactor = 8;
81*7f2fe78bSCy Schubert     db->info.nelem = 25000;
82*7f2fe78bSCy Schubert     db->info.lorder = 0;
83*7f2fe78bSCy Schubert 
84*7f2fe78bSCy Schubert     db->btinfo.flags = 0;
85*7f2fe78bSCy Schubert     db->btinfo.cachesize = 0;
86*7f2fe78bSCy Schubert     db->btinfo.psize = 4096;
87*7f2fe78bSCy Schubert     db->btinfo.lorder = 0;
88*7f2fe78bSCy Schubert     db->btinfo.minkeypage = 0;
89*7f2fe78bSCy Schubert     db->btinfo.compare = NULL;
90*7f2fe78bSCy Schubert     db->btinfo.prefix = NULL;
91*7f2fe78bSCy Schubert     /*
92*7f2fe78bSCy Schubert      * A process is allowed to open the same database multiple times
93*7f2fe78bSCy Schubert      * and access it via different handles.  If the handles use
94*7f2fe78bSCy Schubert      * distinct lockinfo structures, things get confused: lock(A),
95*7f2fe78bSCy Schubert      * lock(B), release(B) will result in the kernel unlocking the
96*7f2fe78bSCy Schubert      * lock file but handle A will still think the file is locked.
97*7f2fe78bSCy Schubert      * Therefore, all handles using the same lock file must share a
98*7f2fe78bSCy Schubert      * single lockinfo structure.
99*7f2fe78bSCy Schubert      *
100*7f2fe78bSCy Schubert      * It is not sufficient to have a single lockinfo structure,
101*7f2fe78bSCy Schubert      * however, because a single process may also wish to open
102*7f2fe78bSCy Schubert      * multiple different databases simultaneously, with different
103*7f2fe78bSCy Schubert      * lock files.  This code used to use a single static lockinfo
104*7f2fe78bSCy Schubert      * structure, which means that the second database opened used
105*7f2fe78bSCy Schubert      * the first database's lock file.  This was Bad.
106*7f2fe78bSCy Schubert      *
107*7f2fe78bSCy Schubert      * We now maintain a linked list of lockinfo structures, keyed by
108*7f2fe78bSCy Schubert      * lockfilename.  An entry is added when this function is called
109*7f2fe78bSCy Schubert      * with a new lockfilename, and all subsequent calls with that
110*7f2fe78bSCy Schubert      * lockfilename use the existing entry, updating the refcnt.
111*7f2fe78bSCy Schubert      * When the database is closed with fini_db(), the refcnt is
112*7f2fe78bSCy Schubert      * decremented, and when it is zero the lockinfo structure is
113*7f2fe78bSCy Schubert      * freed and reset.  The entry in the linked list, however, is
114*7f2fe78bSCy Schubert      * never removed; it will just be reinitialized the next time
115*7f2fe78bSCy Schubert      * init_db is called with the right lockfilename.
116*7f2fe78bSCy Schubert      */
117*7f2fe78bSCy Schubert 
118*7f2fe78bSCy Schubert     /* find or create the lockinfo structure for lockfilename */
119*7f2fe78bSCy Schubert     lockp = locklist;
120*7f2fe78bSCy Schubert     while (lockp) {
121*7f2fe78bSCy Schubert         if (strcmp(lockp->lockinfo.filename, lockfilename) == 0)
122*7f2fe78bSCy Schubert             break;
123*7f2fe78bSCy Schubert         else
124*7f2fe78bSCy Schubert             lockp = lockp->next;
125*7f2fe78bSCy Schubert     }
126*7f2fe78bSCy Schubert     if (lockp == NULL) {
127*7f2fe78bSCy Schubert         /* doesn't exist, create it, add to list */
128*7f2fe78bSCy Schubert         lockp = (struct _locklist *) malloc(sizeof(*lockp));
129*7f2fe78bSCy Schubert         if (lockp == NULL) {
130*7f2fe78bSCy Schubert             free(db);
131*7f2fe78bSCy Schubert             return ENOMEM;
132*7f2fe78bSCy Schubert         }
133*7f2fe78bSCy Schubert         memset(lockp, 0, sizeof(*lockp));
134*7f2fe78bSCy Schubert         lockp->lockinfo.filename = strdup(lockfilename);
135*7f2fe78bSCy Schubert         if (lockp->lockinfo.filename == NULL) {
136*7f2fe78bSCy Schubert             free(lockp);
137*7f2fe78bSCy Schubert             free(db);
138*7f2fe78bSCy Schubert             return ENOMEM;
139*7f2fe78bSCy Schubert         }
140*7f2fe78bSCy Schubert         lockp->next = locklist;
141*7f2fe78bSCy Schubert         locklist = lockp;
142*7f2fe78bSCy Schubert     }
143*7f2fe78bSCy Schubert 
144*7f2fe78bSCy Schubert     /* now initialize lockp->lockinfo if necessary */
145*7f2fe78bSCy Schubert     if (lockp->lockinfo.lockfile == NULL) {
146*7f2fe78bSCy Schubert         if ((code = krb5int_init_context_kdc(&lockp->lockinfo.context))) {
147*7f2fe78bSCy Schubert             free(db);
148*7f2fe78bSCy Schubert             return((krb5_error_code) code);
149*7f2fe78bSCy Schubert         }
150*7f2fe78bSCy Schubert 
151*7f2fe78bSCy Schubert         /*
152*7f2fe78bSCy Schubert          * needs be open read/write so that write locking can work with
153*7f2fe78bSCy Schubert          * POSIX systems
154*7f2fe78bSCy Schubert          */
155*7f2fe78bSCy Schubert         if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) {
156*7f2fe78bSCy Schubert             /*
157*7f2fe78bSCy Schubert              * maybe someone took away write permission so we could only
158*7f2fe78bSCy Schubert              * get shared locks?
159*7f2fe78bSCy Schubert              */
160*7f2fe78bSCy Schubert             if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r"))
161*7f2fe78bSCy Schubert                 == NULL) {
162*7f2fe78bSCy Schubert                 free(db);
163*7f2fe78bSCy Schubert                 return OSA_ADB_NOLOCKFILE;
164*7f2fe78bSCy Schubert             }
165*7f2fe78bSCy Schubert         }
166*7f2fe78bSCy Schubert         set_cloexec_file(lockp->lockinfo.lockfile);
167*7f2fe78bSCy Schubert         lockp->lockinfo.lockmode = lockp->lockinfo.lockcnt = 0;
168*7f2fe78bSCy Schubert     }
169*7f2fe78bSCy Schubert 
170*7f2fe78bSCy Schubert     /* lockp is set, lockinfo is initialized, update the reference count */
171*7f2fe78bSCy Schubert     db->lock = &lockp->lockinfo;
172*7f2fe78bSCy Schubert     db->lock->refcnt++;
173*7f2fe78bSCy Schubert 
174*7f2fe78bSCy Schubert     db->opencnt = 0;
175*7f2fe78bSCy Schubert     db->filename = strdup(filename);
176*7f2fe78bSCy Schubert     db->magic = magic;
177*7f2fe78bSCy Schubert 
178*7f2fe78bSCy Schubert     *dbp = db;
179*7f2fe78bSCy Schubert 
180*7f2fe78bSCy Schubert     return OSA_ADB_OK;
181*7f2fe78bSCy Schubert }
182*7f2fe78bSCy Schubert 
183*7f2fe78bSCy Schubert krb5_error_code
osa_adb_fini_db(osa_adb_db_t db,int magic)184*7f2fe78bSCy Schubert osa_adb_fini_db(osa_adb_db_t db, int magic)
185*7f2fe78bSCy Schubert {
186*7f2fe78bSCy Schubert     if (db->magic != magic)
187*7f2fe78bSCy Schubert         return EINVAL;
188*7f2fe78bSCy Schubert     if (db->lock->refcnt == 0) {
189*7f2fe78bSCy Schubert         /* barry says this can't happen */
190*7f2fe78bSCy Schubert         return OSA_ADB_FAILURE;
191*7f2fe78bSCy Schubert     } else {
192*7f2fe78bSCy Schubert         db->lock->refcnt--;
193*7f2fe78bSCy Schubert     }
194*7f2fe78bSCy Schubert 
195*7f2fe78bSCy Schubert     if (db->lock->refcnt == 0) {
196*7f2fe78bSCy Schubert         /*
197*7f2fe78bSCy Schubert          * Don't free db->lock->filename, it is used as a key to
198*7f2fe78bSCy Schubert          * find the lockinfo entry in the linked list.  If the
199*7f2fe78bSCy Schubert          * lockfile doesn't exist, we must be closing the database
200*7f2fe78bSCy Schubert          * after trashing it.  This has to be allowed, so don't
201*7f2fe78bSCy Schubert          * generate an error.
202*7f2fe78bSCy Schubert          */
203*7f2fe78bSCy Schubert         if (db->lock->lockmode != KRB5_DB_LOCKMODE_PERMANENT)
204*7f2fe78bSCy Schubert             (void) fclose(db->lock->lockfile);
205*7f2fe78bSCy Schubert         db->lock->lockfile = NULL;
206*7f2fe78bSCy Schubert         krb5_free_context(db->lock->context);
207*7f2fe78bSCy Schubert     }
208*7f2fe78bSCy Schubert 
209*7f2fe78bSCy Schubert     db->magic = 0;
210*7f2fe78bSCy Schubert     free(db->filename);
211*7f2fe78bSCy Schubert     free(db);
212*7f2fe78bSCy Schubert     return OSA_ADB_OK;
213*7f2fe78bSCy Schubert }
214*7f2fe78bSCy Schubert 
215*7f2fe78bSCy Schubert krb5_error_code
osa_adb_get_lock(osa_adb_db_t db,int mode)216*7f2fe78bSCy Schubert osa_adb_get_lock(osa_adb_db_t db, int mode)
217*7f2fe78bSCy Schubert {
218*7f2fe78bSCy Schubert     int perm, krb5_mode, ret = 0;
219*7f2fe78bSCy Schubert 
220*7f2fe78bSCy Schubert     if (db->lock->lockmode >= mode) {
221*7f2fe78bSCy Schubert         /* No need to upgrade lock, just incr refcnt and return */
222*7f2fe78bSCy Schubert         db->lock->lockcnt++;
223*7f2fe78bSCy Schubert         return(OSA_ADB_OK);
224*7f2fe78bSCy Schubert     }
225*7f2fe78bSCy Schubert 
226*7f2fe78bSCy Schubert     perm = 0;
227*7f2fe78bSCy Schubert     switch (mode) {
228*7f2fe78bSCy Schubert     case KRB5_DB_LOCKMODE_PERMANENT:
229*7f2fe78bSCy Schubert         perm = 1;
230*7f2fe78bSCy Schubert     case KRB5_DB_LOCKMODE_EXCLUSIVE:
231*7f2fe78bSCy Schubert         krb5_mode = KRB5_LOCKMODE_EXCLUSIVE;
232*7f2fe78bSCy Schubert         break;
233*7f2fe78bSCy Schubert     case KRB5_DB_LOCKMODE_SHARED:
234*7f2fe78bSCy Schubert         krb5_mode = KRB5_LOCKMODE_SHARED;
235*7f2fe78bSCy Schubert         break;
236*7f2fe78bSCy Schubert     default:
237*7f2fe78bSCy Schubert         return(EINVAL);
238*7f2fe78bSCy Schubert     }
239*7f2fe78bSCy Schubert 
240*7f2fe78bSCy Schubert     ret = krb5_lock_file(db->lock->context, fileno(db->lock->lockfile),
241*7f2fe78bSCy Schubert                          krb5_mode);
242*7f2fe78bSCy Schubert     if (ret == EBADF && mode == KRB5_DB_LOCKMODE_EXCLUSIVE)
243*7f2fe78bSCy Schubert         return OSA_ADB_NOEXCL_PERM;
244*7f2fe78bSCy Schubert     else if (ret == EACCES || ret == EAGAIN || ret == EWOULDBLOCK)
245*7f2fe78bSCy Schubert         return OSA_ADB_CANTLOCK_DB;
246*7f2fe78bSCy Schubert     else if (ret != 0)
247*7f2fe78bSCy Schubert         return ret;
248*7f2fe78bSCy Schubert 
249*7f2fe78bSCy Schubert     /*
250*7f2fe78bSCy Schubert      * If the file no longer exists, someone acquired a permanent
251*7f2fe78bSCy Schubert      * lock.  If that process terminates its exclusive lock is lost,
252*7f2fe78bSCy Schubert      * but if we already had the file open we can (probably) lock it
253*7f2fe78bSCy Schubert      * even though it has been unlinked.  So we need to insist that
254*7f2fe78bSCy Schubert      * it exist.
255*7f2fe78bSCy Schubert      */
256*7f2fe78bSCy Schubert     if (access(db->lock->filename, F_OK) < 0) {
257*7f2fe78bSCy Schubert         (void) krb5_lock_file(db->lock->context,
258*7f2fe78bSCy Schubert                               fileno(db->lock->lockfile),
259*7f2fe78bSCy Schubert                               KRB5_LOCKMODE_UNLOCK);
260*7f2fe78bSCy Schubert         return OSA_ADB_NOLOCKFILE;
261*7f2fe78bSCy Schubert     }
262*7f2fe78bSCy Schubert 
263*7f2fe78bSCy Schubert     /* we have the shared/exclusive lock */
264*7f2fe78bSCy Schubert 
265*7f2fe78bSCy Schubert     if (perm) {
266*7f2fe78bSCy Schubert         if (unlink(db->lock->filename) < 0) {
267*7f2fe78bSCy Schubert             /* somehow we can't delete the file, but we already */
268*7f2fe78bSCy Schubert             /* have the lock, so release it and return */
269*7f2fe78bSCy Schubert 
270*7f2fe78bSCy Schubert             ret = errno;
271*7f2fe78bSCy Schubert             (void) krb5_lock_file(db->lock->context,
272*7f2fe78bSCy Schubert                                   fileno(db->lock->lockfile),
273*7f2fe78bSCy Schubert                                   KRB5_LOCKMODE_UNLOCK);
274*7f2fe78bSCy Schubert 
275*7f2fe78bSCy Schubert             /* maybe we should return CANTLOCK_DB.. but that would */
276*7f2fe78bSCy Schubert             /* look just like the db was already locked */
277*7f2fe78bSCy Schubert             return ret;
278*7f2fe78bSCy Schubert         }
279*7f2fe78bSCy Schubert 
280*7f2fe78bSCy Schubert         /* this releases our exclusive lock.. which is okay because */
281*7f2fe78bSCy Schubert         /* now no one else can get one either */
282*7f2fe78bSCy Schubert         (void) fclose(db->lock->lockfile);
283*7f2fe78bSCy Schubert     }
284*7f2fe78bSCy Schubert 
285*7f2fe78bSCy Schubert     db->lock->lockmode = mode;
286*7f2fe78bSCy Schubert     db->lock->lockcnt++;
287*7f2fe78bSCy Schubert     return OSA_ADB_OK;
288*7f2fe78bSCy Schubert }
289*7f2fe78bSCy Schubert 
290*7f2fe78bSCy Schubert krb5_error_code
osa_adb_release_lock(osa_adb_db_t db)291*7f2fe78bSCy Schubert osa_adb_release_lock(osa_adb_db_t db)
292*7f2fe78bSCy Schubert {
293*7f2fe78bSCy Schubert     int ret, fd;
294*7f2fe78bSCy Schubert 
295*7f2fe78bSCy Schubert     if (!db->lock->lockcnt)            /* lock already unlocked */
296*7f2fe78bSCy Schubert         return OSA_ADB_NOTLOCKED;
297*7f2fe78bSCy Schubert 
298*7f2fe78bSCy Schubert     if (--db->lock->lockcnt == 0) {
299*7f2fe78bSCy Schubert         if (db->lock->lockmode == KRB5_DB_LOCKMODE_PERMANENT) {
300*7f2fe78bSCy Schubert             /* now we need to create the file since it does not exist */
301*7f2fe78bSCy Schubert             fd = THREEPARAMOPEN(db->lock->filename,O_RDWR | O_CREAT | O_EXCL,
302*7f2fe78bSCy Schubert                                 0600);
303*7f2fe78bSCy Schubert             if (fd < 0)
304*7f2fe78bSCy Schubert                 return OSA_ADB_NOLOCKFILE;
305*7f2fe78bSCy Schubert             set_cloexec_fd(fd);
306*7f2fe78bSCy Schubert             if ((db->lock->lockfile = fdopen(fd, "w+")) == NULL)
307*7f2fe78bSCy Schubert                 return OSA_ADB_NOLOCKFILE;
308*7f2fe78bSCy Schubert         } else if ((ret = krb5_lock_file(db->lock->context,
309*7f2fe78bSCy Schubert                                          fileno(db->lock->lockfile),
310*7f2fe78bSCy Schubert                                          KRB5_LOCKMODE_UNLOCK)))
311*7f2fe78bSCy Schubert             return ret;
312*7f2fe78bSCy Schubert 
313*7f2fe78bSCy Schubert         db->lock->lockmode = 0;
314*7f2fe78bSCy Schubert     }
315*7f2fe78bSCy Schubert     return OSA_ADB_OK;
316*7f2fe78bSCy Schubert }
317*7f2fe78bSCy Schubert 
318*7f2fe78bSCy Schubert krb5_error_code
osa_adb_open_and_lock(osa_adb_princ_t db,int locktype)319*7f2fe78bSCy Schubert osa_adb_open_and_lock(osa_adb_princ_t db, int locktype)
320*7f2fe78bSCy Schubert {
321*7f2fe78bSCy Schubert     int ret;
322*7f2fe78bSCy Schubert 
323*7f2fe78bSCy Schubert     ret = osa_adb_get_lock(db, locktype);
324*7f2fe78bSCy Schubert     if (ret != OSA_ADB_OK)
325*7f2fe78bSCy Schubert         return ret;
326*7f2fe78bSCy Schubert     if (db->opencnt)
327*7f2fe78bSCy Schubert         goto open_ok;
328*7f2fe78bSCy Schubert 
329*7f2fe78bSCy Schubert     db->db = dbopen(db->filename, O_RDWR, 0600, DB_BTREE, &db->btinfo);
330*7f2fe78bSCy Schubert     if (db->db == NULL && IS_EFTYPE(errno))
331*7f2fe78bSCy Schubert         db->db = dbopen(db->filename, O_RDWR, 0600, DB_HASH, &db->info);
332*7f2fe78bSCy Schubert     if (db->db == NULL) {
333*7f2fe78bSCy Schubert         (void)osa_adb_release_lock(db);
334*7f2fe78bSCy Schubert         return (errno == EINVAL) ? OSA_ADB_BAD_DB : errno;
335*7f2fe78bSCy Schubert     }
336*7f2fe78bSCy Schubert 
337*7f2fe78bSCy Schubert open_ok:
338*7f2fe78bSCy Schubert     db->opencnt++;
339*7f2fe78bSCy Schubert     return OSA_ADB_OK;
340*7f2fe78bSCy Schubert }
341*7f2fe78bSCy Schubert 
342*7f2fe78bSCy Schubert krb5_error_code
osa_adb_close_and_unlock(osa_adb_princ_t db)343*7f2fe78bSCy Schubert osa_adb_close_and_unlock(osa_adb_princ_t db)
344*7f2fe78bSCy Schubert {
345*7f2fe78bSCy Schubert     if (--db->opencnt)
346*7f2fe78bSCy Schubert         return osa_adb_release_lock(db);
347*7f2fe78bSCy Schubert     if(db->db != NULL && db->db->close(db->db) == -1) {
348*7f2fe78bSCy Schubert         (void) osa_adb_release_lock(db);
349*7f2fe78bSCy Schubert         return OSA_ADB_FAILURE;
350*7f2fe78bSCy Schubert     }
351*7f2fe78bSCy Schubert 
352*7f2fe78bSCy Schubert     db->db = NULL;
353*7f2fe78bSCy Schubert 
354*7f2fe78bSCy Schubert     return(osa_adb_release_lock(db));
355*7f2fe78bSCy Schubert }
356