1*54925bf6Swillf /* 2*54925bf6Swillf * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3*54925bf6Swillf * Use is subject to license terms. 4*54925bf6Swillf */ 5*54925bf6Swillf #pragma ident "%Z%%M% %I% %E% SMI" 6*54925bf6Swillf 7*54925bf6Swillf /* 8*54925bf6Swillf * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 9*54925bf6Swillf * 10*54925bf6Swillf * Openvision retains the copyright to derivative works of 11*54925bf6Swillf * this source code. Do *NOT* create a derivative of this 12*54925bf6Swillf * source code before consulting with your legal department. 13*54925bf6Swillf * Do *NOT* integrate *ANY* of this source code into another 14*54925bf6Swillf * product before consulting with your legal department. 15*54925bf6Swillf * 16*54925bf6Swillf * For further information, read the top-level Openvision 17*54925bf6Swillf * copyright which is contained in the top-level MIT Kerberos 18*54925bf6Swillf * copyright. 19*54925bf6Swillf * 20*54925bf6Swillf * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING 21*54925bf6Swillf * 22*54925bf6Swillf */ 23*54925bf6Swillf 24*54925bf6Swillf 25*54925bf6Swillf /* 26*54925bf6Swillf * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved 27*54925bf6Swillf * 28*54925bf6Swillf * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/adb_openclose.c,v 1.8 2002/10/08 20:20:29 tlyu Exp $ 29*54925bf6Swillf */ 30*54925bf6Swillf 31*54925bf6Swillf #if !defined(lint) && !defined(__CODECENTER__) 32*54925bf6Swillf static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/adb_openclose.c,v 1.8 2002/10/08 20:20:29 tlyu Exp $"; 33*54925bf6Swillf #endif 34*54925bf6Swillf 35*54925bf6Swillf #include <sys/file.h> 36*54925bf6Swillf #include <fcntl.h> 37*54925bf6Swillf #include <unistd.h> 38*54925bf6Swillf #include <k5-int.h> 39*54925bf6Swillf #include "policy_db.h" 40*54925bf6Swillf #include <stdlib.h> 41*54925bf6Swillf #include <db.h> 42*54925bf6Swillf 43*54925bf6Swillf #define MAX_LOCK_TRIES 5 44*54925bf6Swillf 45*54925bf6Swillf struct _locklist { 46*54925bf6Swillf osa_adb_lock_ent lockinfo; 47*54925bf6Swillf struct _locklist *next; 48*54925bf6Swillf }; 49*54925bf6Swillf 50*54925bf6Swillf krb5_error_code osa_adb_create_db(char *filename, char *lockfilename, 51*54925bf6Swillf int magic) 52*54925bf6Swillf { 53*54925bf6Swillf int lf; 54*54925bf6Swillf DB *db; 55*54925bf6Swillf BTREEINFO btinfo; 56*54925bf6Swillf 57*54925bf6Swillf memset(&btinfo, 0, sizeof(btinfo)); 58*54925bf6Swillf btinfo.flags = 0; 59*54925bf6Swillf btinfo.cachesize = 0; 60*54925bf6Swillf btinfo.psize = 4096; 61*54925bf6Swillf btinfo.lorder = 0; 62*54925bf6Swillf btinfo.minkeypage = 0; 63*54925bf6Swillf btinfo.compare = NULL; 64*54925bf6Swillf btinfo.prefix = NULL; 65*54925bf6Swillf db = dbopen(filename, O_RDWR | O_CREAT | O_EXCL, 0600, DB_BTREE, &btinfo); 66*54925bf6Swillf if (db == NULL) 67*54925bf6Swillf return errno; 68*54925bf6Swillf if (db->close(db) < 0) 69*54925bf6Swillf return errno; 70*54925bf6Swillf 71*54925bf6Swillf /* only create the lock file if we successfully created the db */ 72*54925bf6Swillf lf = THREEPARAMOPEN(lockfilename, O_RDWR | O_CREAT | O_EXCL, 0600); 73*54925bf6Swillf if (lf == -1) 74*54925bf6Swillf return errno; 75*54925bf6Swillf (void) close(lf); 76*54925bf6Swillf 77*54925bf6Swillf return OSA_ADB_OK; 78*54925bf6Swillf } 79*54925bf6Swillf 80*54925bf6Swillf krb5_error_code osa_adb_destroy_db(char *filename, char *lockfilename, 81*54925bf6Swillf int magic) 82*54925bf6Swillf { 83*54925bf6Swillf /* the admin databases do not contain security-critical data */ 84*54925bf6Swillf if (unlink(filename) < 0 || 85*54925bf6Swillf unlink(lockfilename) < 0) 86*54925bf6Swillf return errno; 87*54925bf6Swillf return OSA_ADB_OK; 88*54925bf6Swillf } 89*54925bf6Swillf 90*54925bf6Swillf krb5_error_code osa_adb_rename_db(char *filefrom, char *lockfrom, 91*54925bf6Swillf char *fileto, char *lockto, int magic) 92*54925bf6Swillf { 93*54925bf6Swillf osa_adb_db_t fromdb, todb; 94*54925bf6Swillf krb5_error_code ret; 95*54925bf6Swillf 96*54925bf6Swillf /* make sure todb exists */ 97*54925bf6Swillf /*LINTED*/ 98*54925bf6Swillf if ((ret = osa_adb_create_db(fileto, lockto, magic)) && 99*54925bf6Swillf ret != EEXIST) 100*54925bf6Swillf return ret; 101*54925bf6Swillf 102*54925bf6Swillf if ((ret = osa_adb_init_db(&fromdb, filefrom, lockfrom, magic))) 103*54925bf6Swillf return ret; 104*54925bf6Swillf if ((ret = osa_adb_init_db(&todb, fileto, lockto, magic))) { 105*54925bf6Swillf (void) osa_adb_fini_db(fromdb, magic); 106*54925bf6Swillf return ret; 107*54925bf6Swillf } 108*54925bf6Swillf if ((ret = osa_adb_get_lock(fromdb, KRB5_DB_LOCKMODE_PERMANENT))) { 109*54925bf6Swillf (void) osa_adb_fini_db(fromdb, magic); 110*54925bf6Swillf (void) osa_adb_fini_db(todb, magic); 111*54925bf6Swillf return ret; 112*54925bf6Swillf } 113*54925bf6Swillf if ((ret = osa_adb_get_lock(todb, KRB5_DB_LOCKMODE_PERMANENT))) { 114*54925bf6Swillf (void) osa_adb_fini_db(fromdb, magic); 115*54925bf6Swillf (void) osa_adb_fini_db(todb, magic); 116*54925bf6Swillf return ret; 117*54925bf6Swillf } 118*54925bf6Swillf if ((rename(filefrom, fileto) < 0)) { 119*54925bf6Swillf (void) osa_adb_fini_db(fromdb, magic); 120*54925bf6Swillf (void) osa_adb_fini_db(todb, magic); 121*54925bf6Swillf return errno; 122*54925bf6Swillf } 123*54925bf6Swillf /* 124*54925bf6Swillf * Do not release the lock on fromdb because it is being renamed 125*54925bf6Swillf * out of existence; no one can ever use it again. 126*54925bf6Swillf */ 127*54925bf6Swillf if ((ret = osa_adb_release_lock(todb))) { 128*54925bf6Swillf (void) osa_adb_fini_db(fromdb, magic); 129*54925bf6Swillf (void) osa_adb_fini_db(todb, magic); 130*54925bf6Swillf return ret; 131*54925bf6Swillf } 132*54925bf6Swillf 133*54925bf6Swillf (void) osa_adb_fini_db(fromdb, magic); 134*54925bf6Swillf (void) osa_adb_fini_db(todb, magic); 135*54925bf6Swillf return 0; 136*54925bf6Swillf } 137*54925bf6Swillf 138*54925bf6Swillf krb5_error_code osa_adb_init_db(osa_adb_db_t *dbp, char *filename, 139*54925bf6Swillf char *lockfilename, int magic) 140*54925bf6Swillf { 141*54925bf6Swillf osa_adb_db_t db; 142*54925bf6Swillf static struct _locklist *locklist = NULL; 143*54925bf6Swillf struct _locklist *lockp; 144*54925bf6Swillf krb5_error_code code; 145*54925bf6Swillf 146*54925bf6Swillf if (dbp == NULL || filename == NULL) 147*54925bf6Swillf return EINVAL; 148*54925bf6Swillf 149*54925bf6Swillf db = (osa_adb_princ_t) malloc(sizeof(osa_adb_db_ent)); 150*54925bf6Swillf if (db == NULL) 151*54925bf6Swillf return ENOMEM; 152*54925bf6Swillf 153*54925bf6Swillf memset(db, 0, sizeof(*db)); 154*54925bf6Swillf db->info.hash = NULL; 155*54925bf6Swillf db->info.bsize = 256; 156*54925bf6Swillf db->info.ffactor = 8; 157*54925bf6Swillf db->info.nelem = 25000; 158*54925bf6Swillf db->info.lorder = 0; 159*54925bf6Swillf 160*54925bf6Swillf db->btinfo.flags = 0; 161*54925bf6Swillf db->btinfo.cachesize = 0; 162*54925bf6Swillf db->btinfo.psize = 4096; 163*54925bf6Swillf db->btinfo.lorder = 0; 164*54925bf6Swillf db->btinfo.minkeypage = 0; 165*54925bf6Swillf db->btinfo.compare = NULL; 166*54925bf6Swillf db->btinfo.prefix = NULL; 167*54925bf6Swillf /* 168*54925bf6Swillf * A process is allowed to open the same database multiple times 169*54925bf6Swillf * and access it via different handles. If the handles use 170*54925bf6Swillf * distinct lockinfo structures, things get confused: lock(A), 171*54925bf6Swillf * lock(B), release(B) will result in the kernel unlocking the 172*54925bf6Swillf * lock file but handle A will still think the file is locked. 173*54925bf6Swillf * Therefore, all handles using the same lock file must share a 174*54925bf6Swillf * single lockinfo structure. 175*54925bf6Swillf * 176*54925bf6Swillf * It is not sufficient to have a single lockinfo structure, 177*54925bf6Swillf * however, because a single process may also wish to open 178*54925bf6Swillf * multiple different databases simultaneously, with different 179*54925bf6Swillf * lock files. This code used to use a single static lockinfo 180*54925bf6Swillf * structure, which means that the second database opened used 181*54925bf6Swillf * the first database's lock file. This was Bad. 182*54925bf6Swillf * 183*54925bf6Swillf * We now maintain a linked list of lockinfo structures, keyed by 184*54925bf6Swillf * lockfilename. An entry is added when this function is called 185*54925bf6Swillf * with a new lockfilename, and all subsequent calls with that 186*54925bf6Swillf * lockfilename use the existing entry, updating the refcnt. 187*54925bf6Swillf * When the database is closed with fini_db(), the refcnt is 188*54925bf6Swillf * decremented, and when it is zero the lockinfo structure is 189*54925bf6Swillf * freed and reset. The entry in the linked list, however, is 190*54925bf6Swillf * never removed; it will just be reinitialized the next time 191*54925bf6Swillf * init_db is called with the right lockfilename. 192*54925bf6Swillf */ 193*54925bf6Swillf 194*54925bf6Swillf /* find or create the lockinfo structure for lockfilename */ 195*54925bf6Swillf lockp = locklist; 196*54925bf6Swillf while (lockp) { 197*54925bf6Swillf if (strcmp(lockp->lockinfo.filename, lockfilename) == 0) 198*54925bf6Swillf break; 199*54925bf6Swillf else 200*54925bf6Swillf lockp = lockp->next; 201*54925bf6Swillf } 202*54925bf6Swillf if (lockp == NULL) { 203*54925bf6Swillf /* doesn't exist, create it, add to list */ 204*54925bf6Swillf lockp = (struct _locklist *) malloc(sizeof(*lockp)); 205*54925bf6Swillf if (lockp == NULL) { 206*54925bf6Swillf free(db); 207*54925bf6Swillf return ENOMEM; 208*54925bf6Swillf } 209*54925bf6Swillf memset(lockp, 0, sizeof(*lockp)); 210*54925bf6Swillf lockp->next = locklist; 211*54925bf6Swillf locklist = lockp; 212*54925bf6Swillf } 213*54925bf6Swillf 214*54925bf6Swillf /* now initialize lockp->lockinfo if necessary */ 215*54925bf6Swillf if (lockp->lockinfo.lockfile == NULL) { 216*54925bf6Swillf if ((code = krb5int_init_context_kdc(&lockp->lockinfo.context))) { 217*54925bf6Swillf free(db); 218*54925bf6Swillf return((krb5_error_code) code); 219*54925bf6Swillf } 220*54925bf6Swillf 221*54925bf6Swillf /* 222*54925bf6Swillf * needs be open read/write so that write locking can work with 223*54925bf6Swillf * POSIX systems 224*54925bf6Swillf */ 225*54925bf6Swillf lockp->lockinfo.filename = strdup(lockfilename); 226*54925bf6Swillf if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+F")) == NULL) { 227*54925bf6Swillf /* 228*54925bf6Swillf * maybe someone took away write permission so we could only 229*54925bf6Swillf * get shared locks? 230*54925bf6Swillf */ 231*54925bf6Swillf if ((lockp->lockinfo.lockfile = fopen(lockfilename, "rF")) 232*54925bf6Swillf == NULL) { 233*54925bf6Swillf free(db); 234*54925bf6Swillf return OSA_ADB_NOLOCKFILE; 235*54925bf6Swillf } 236*54925bf6Swillf } 237*54925bf6Swillf lockp->lockinfo.lockmode = lockp->lockinfo.lockcnt = 0; 238*54925bf6Swillf } 239*54925bf6Swillf 240*54925bf6Swillf /* lockp is set, lockinfo is initialized, update the reference count */ 241*54925bf6Swillf db->lock = &lockp->lockinfo; 242*54925bf6Swillf db->lock->refcnt++; 243*54925bf6Swillf 244*54925bf6Swillf db->opencnt = 0; 245*54925bf6Swillf db->filename = strdup(filename); 246*54925bf6Swillf db->magic = magic; 247*54925bf6Swillf 248*54925bf6Swillf *dbp = db; 249*54925bf6Swillf 250*54925bf6Swillf return OSA_ADB_OK; 251*54925bf6Swillf } 252*54925bf6Swillf 253*54925bf6Swillf krb5_error_code osa_adb_fini_db(osa_adb_db_t db, int magic) 254*54925bf6Swillf { 255*54925bf6Swillf if (db->magic != magic) 256*54925bf6Swillf return EINVAL; 257*54925bf6Swillf if (db->lock->refcnt == 0) { 258*54925bf6Swillf /* barry says this can't happen */ 259*54925bf6Swillf return OSA_ADB_FAILURE; 260*54925bf6Swillf } else { 261*54925bf6Swillf db->lock->refcnt--; 262*54925bf6Swillf } 263*54925bf6Swillf 264*54925bf6Swillf if (db->lock->refcnt == 0) { 265*54925bf6Swillf /* 266*54925bf6Swillf * Don't free db->lock->filename, it is used as a key to 267*54925bf6Swillf * find the lockinfo entry in the linked list. If the 268*54925bf6Swillf * lockfile doesn't exist, we must be closing the database 269*54925bf6Swillf * after trashing it. This has to be allowed, so don't 270*54925bf6Swillf * generate an error. 271*54925bf6Swillf */ 272*54925bf6Swillf if (db->lock->lockmode != KRB5_DB_LOCKMODE_PERMANENT) 273*54925bf6Swillf (void) fclose(db->lock->lockfile); 274*54925bf6Swillf db->lock->lockfile = NULL; 275*54925bf6Swillf krb5_free_context(db->lock->context); 276*54925bf6Swillf } 277*54925bf6Swillf 278*54925bf6Swillf db->magic = 0; 279*54925bf6Swillf free(db->filename); 280*54925bf6Swillf free(db); 281*54925bf6Swillf return OSA_ADB_OK; 282*54925bf6Swillf } 283*54925bf6Swillf 284*54925bf6Swillf krb5_error_code osa_adb_get_lock(osa_adb_db_t db, int mode) 285*54925bf6Swillf { 286*54925bf6Swillf int tries, gotlock, perm, krb5_mode, ret = 0; 287*54925bf6Swillf 288*54925bf6Swillf if (db->lock->lockmode >= mode) { 289*54925bf6Swillf /* No need to upgrade lock, just incr refcnt and return */ 290*54925bf6Swillf db->lock->lockcnt++; 291*54925bf6Swillf return(OSA_ADB_OK); 292*54925bf6Swillf } 293*54925bf6Swillf 294*54925bf6Swillf perm = 0; 295*54925bf6Swillf switch (mode) { 296*54925bf6Swillf case KRB5_DB_LOCKMODE_PERMANENT: 297*54925bf6Swillf perm = 1; 298*54925bf6Swillf /*LINTED*/ 299*54925bf6Swillf case KRB5_DB_LOCKMODE_EXCLUSIVE: 300*54925bf6Swillf krb5_mode = KRB5_LOCKMODE_EXCLUSIVE; 301*54925bf6Swillf break; 302*54925bf6Swillf case KRB5_DB_LOCKMODE_SHARED: 303*54925bf6Swillf krb5_mode = KRB5_LOCKMODE_SHARED; 304*54925bf6Swillf break; 305*54925bf6Swillf default: 306*54925bf6Swillf return(EINVAL); 307*54925bf6Swillf } 308*54925bf6Swillf 309*54925bf6Swillf for (gotlock = tries = 0; tries < MAX_LOCK_TRIES; tries++) { 310*54925bf6Swillf if ((ret = krb5_lock_file(db->lock->context, 311*54925bf6Swillf fileno(db->lock->lockfile), 312*54925bf6Swillf krb5_mode|KRB5_LOCKMODE_DONTBLOCK)) == 0) { 313*54925bf6Swillf gotlock++; 314*54925bf6Swillf break; 315*54925bf6Swillf } else if (ret == EBADF && mode == KRB5_DB_LOCKMODE_EXCLUSIVE) 316*54925bf6Swillf /* tried to exclusive-lock something we don't have */ 317*54925bf6Swillf /* write access to */ 318*54925bf6Swillf return OSA_ADB_NOEXCL_PERM; 319*54925bf6Swillf 320*54925bf6Swillf sleep(1); 321*54925bf6Swillf } 322*54925bf6Swillf 323*54925bf6Swillf /* test for all the likely "can't get lock" error codes */ 324*54925bf6Swillf if (ret == EACCES || ret == EAGAIN || ret == EWOULDBLOCK) 325*54925bf6Swillf return OSA_ADB_CANTLOCK_DB; 326*54925bf6Swillf else if (ret != 0) 327*54925bf6Swillf return ret; 328*54925bf6Swillf 329*54925bf6Swillf /* 330*54925bf6Swillf * If the file no longer exists, someone acquired a permanent 331*54925bf6Swillf * lock. If that process terminates its exclusive lock is lost, 332*54925bf6Swillf * but if we already had the file open we can (probably) lock it 333*54925bf6Swillf * even though it has been unlinked. So we need to insist that 334*54925bf6Swillf * it exist. 335*54925bf6Swillf */ 336*54925bf6Swillf if (access(db->lock->filename, F_OK) < 0) { 337*54925bf6Swillf (void) krb5_lock_file(db->lock->context, 338*54925bf6Swillf fileno(db->lock->lockfile), 339*54925bf6Swillf KRB5_LOCKMODE_UNLOCK); 340*54925bf6Swillf return OSA_ADB_NOLOCKFILE; 341*54925bf6Swillf } 342*54925bf6Swillf 343*54925bf6Swillf /* we have the shared/exclusive lock */ 344*54925bf6Swillf 345*54925bf6Swillf if (perm) { 346*54925bf6Swillf if (unlink(db->lock->filename) < 0) { 347*54925bf6Swillf /* somehow we can't delete the file, but we already */ 348*54925bf6Swillf /* have the lock, so release it and return */ 349*54925bf6Swillf 350*54925bf6Swillf ret = errno; 351*54925bf6Swillf (void) krb5_lock_file(db->lock->context, 352*54925bf6Swillf fileno(db->lock->lockfile), 353*54925bf6Swillf KRB5_LOCKMODE_UNLOCK); 354*54925bf6Swillf 355*54925bf6Swillf /* maybe we should return CANTLOCK_DB.. but that would */ 356*54925bf6Swillf /* look just like the db was already locked */ 357*54925bf6Swillf return ret; 358*54925bf6Swillf } 359*54925bf6Swillf 360*54925bf6Swillf /* this releases our exclusive lock.. which is okay because */ 361*54925bf6Swillf /* now no one else can get one either */ 362*54925bf6Swillf (void) fclose(db->lock->lockfile); 363*54925bf6Swillf } 364*54925bf6Swillf 365*54925bf6Swillf db->lock->lockmode = mode; 366*54925bf6Swillf db->lock->lockcnt++; 367*54925bf6Swillf return OSA_ADB_OK; 368*54925bf6Swillf } 369*54925bf6Swillf 370*54925bf6Swillf krb5_error_code osa_adb_release_lock(osa_adb_db_t db) 371*54925bf6Swillf { 372*54925bf6Swillf int ret, fd; 373*54925bf6Swillf 374*54925bf6Swillf if (!db->lock->lockcnt) /* lock already unlocked */ 375*54925bf6Swillf return OSA_ADB_NOTLOCKED; 376*54925bf6Swillf 377*54925bf6Swillf if (--db->lock->lockcnt == 0) { 378*54925bf6Swillf if (db->lock->lockmode == KRB5_DB_LOCKMODE_PERMANENT) { 379*54925bf6Swillf /* now we need to create the file since it does not exist */ 380*54925bf6Swillf fd = THREEPARAMOPEN(db->lock->filename,O_RDWR | O_CREAT | O_EXCL, 381*54925bf6Swillf 0600); 382*54925bf6Swillf if ((db->lock->lockfile = fdopen(fd, "w+F")) == NULL) 383*54925bf6Swillf return OSA_ADB_NOLOCKFILE; 384*54925bf6Swillf } else if ((ret = krb5_lock_file(db->lock->context, 385*54925bf6Swillf fileno(db->lock->lockfile), 386*54925bf6Swillf KRB5_LOCKMODE_UNLOCK))) 387*54925bf6Swillf return ret; 388*54925bf6Swillf 389*54925bf6Swillf db->lock->lockmode = 0; 390*54925bf6Swillf } 391*54925bf6Swillf return OSA_ADB_OK; 392*54925bf6Swillf } 393*54925bf6Swillf 394*54925bf6Swillf krb5_error_code osa_adb_open_and_lock(osa_adb_princ_t db, int locktype) 395*54925bf6Swillf { 396*54925bf6Swillf int ret; 397*54925bf6Swillf 398*54925bf6Swillf ret = osa_adb_get_lock(db, locktype); 399*54925bf6Swillf if (ret != OSA_ADB_OK) 400*54925bf6Swillf return ret; 401*54925bf6Swillf if (db->opencnt) 402*54925bf6Swillf goto open_ok; 403*54925bf6Swillf 404*54925bf6Swillf db->db = dbopen(db->filename, O_RDWR, 0600, DB_BTREE, &db->btinfo); 405*54925bf6Swillf if (db->db != NULL) 406*54925bf6Swillf goto open_ok; 407*54925bf6Swillf switch (errno) { 408*54925bf6Swillf #ifdef EFTYPE 409*54925bf6Swillf case EFTYPE: 410*54925bf6Swillf #endif 411*54925bf6Swillf case EINVAL: 412*54925bf6Swillf db->db = dbopen(db->filename, O_RDWR, 0600, DB_HASH, &db->info); 413*54925bf6Swillf if (db->db != NULL) 414*54925bf6Swillf goto open_ok; 415*54925bf6Swillf default: 416*54925bf6Swillf (void) osa_adb_release_lock(db); 417*54925bf6Swillf if (errno == EINVAL) 418*54925bf6Swillf return OSA_ADB_BAD_DB; 419*54925bf6Swillf return errno; 420*54925bf6Swillf } 421*54925bf6Swillf open_ok: 422*54925bf6Swillf db->opencnt++; 423*54925bf6Swillf return OSA_ADB_OK; 424*54925bf6Swillf } 425*54925bf6Swillf 426*54925bf6Swillf krb5_error_code osa_adb_close_and_unlock(osa_adb_princ_t db) 427*54925bf6Swillf { 428*54925bf6Swillf if (--db->opencnt) 429*54925bf6Swillf return osa_adb_release_lock(db); 430*54925bf6Swillf if(db->db != NULL && db->db->close(db->db) == -1) { 431*54925bf6Swillf (void) osa_adb_release_lock(db); 432*54925bf6Swillf return OSA_ADB_FAILURE; 433*54925bf6Swillf } 434*54925bf6Swillf 435*54925bf6Swillf db->db = NULL; 436*54925bf6Swillf 437*54925bf6Swillf return(osa_adb_release_lock(db)); 438*54925bf6Swillf } 439