1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <time.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 32*7c478bd9Sstevel@tonic-gate #include <lber.h> 33*7c478bd9Sstevel@tonic-gate #include <ldap.h> 34*7c478bd9Sstevel@tonic-gate #include <signal.h> 35*7c478bd9Sstevel@tonic-gate #include <pthread.h> 36*7c478bd9Sstevel@tonic-gate #include "db_headers.h" 37*7c478bd9Sstevel@tonic-gate #include "db.h" 38*7c478bd9Sstevel@tonic-gate #include "db_mindex.h" 39*7c478bd9Sstevel@tonic-gate #include "db_dictionary.h" 40*7c478bd9Sstevel@tonic-gate #include "nisdb_mt.h" 41*7c478bd9Sstevel@tonic-gate #include "ldap_map.h" 42*7c478bd9Sstevel@tonic-gate #include "ldap_glob.h" 43*7c478bd9Sstevel@tonic-gate #include "ldap_nisplus.h" 44*7c478bd9Sstevel@tonic-gate #include "ldap_util.h" 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate extern db_dictionary *InUseDictionary; 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate extern "C" { 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate typedef struct { 53*7c478bd9Sstevel@tonic-gate db_mindex *mindex; 54*7c478bd9Sstevel@tonic-gate __nis_table_mapping_t *t; 55*7c478bd9Sstevel@tonic-gate db_query *qin; 56*7c478bd9Sstevel@tonic-gate db_query *q; 57*7c478bd9Sstevel@tonic-gate char *dbId; 58*7c478bd9Sstevel@tonic-gate nis_object *dirObj; 59*7c478bd9Sstevel@tonic-gate int isDeferred; 60*7c478bd9Sstevel@tonic-gate char *tableName; 61*7c478bd9Sstevel@tonic-gate } __entries_from_ldap_arg_t; 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate static void *entriesFromLDAPthread(void *); 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate } 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate int entriesFromLDAPreal(__entries_from_ldap_arg_t *); 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #ifdef SET_ENTRY_FLAGS 70*7c478bd9Sstevel@tonic-gate static uint_t 71*7c478bd9Sstevel@tonic-gate entryFlagsFromTable(uint_t tf) { 72*7c478bd9Sstevel@tonic-gate uint_t ef = 0; 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate if ((tf & TA_BINARY) != 0) 75*7c478bd9Sstevel@tonic-gate ef |= EN_BINARY; 76*7c478bd9Sstevel@tonic-gate if ((tf & TA_CRYPT) != 0) 77*7c478bd9Sstevel@tonic-gate ef |= EN_CRYPT; 78*7c478bd9Sstevel@tonic-gate if ((tf & TA_XDR) != 0) 79*7c478bd9Sstevel@tonic-gate ef |= EN_XDR; 80*7c478bd9Sstevel@tonic-gate if ((tf & TA_ASN1) != 0) 81*7c478bd9Sstevel@tonic-gate ef |= EN_ASN1; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate return (ef); 84*7c478bd9Sstevel@tonic-gate } 85*7c478bd9Sstevel@tonic-gate #endif /* SET_ENTRY_FLAGS */ 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * Retrieve container entries from LDAP per 't' and 'qin'/'q'. 89*7c478bd9Sstevel@tonic-gate * This is a helper function for db_mindex::queryLDAP(); see 90*7c478bd9Sstevel@tonic-gate * that function for details of the parameters (except doAsynch). 91*7c478bd9Sstevel@tonic-gate * 92*7c478bd9Sstevel@tonic-gate * If 'doAsynch' is set, and the retrieval is an enumeration 93*7c478bd9Sstevel@tonic-gate * (qin == NULL), the retrieval is performed in a detached 94*7c478bd9Sstevel@tonic-gate * thread. In this case, the return code just reflects the 95*7c478bd9Sstevel@tonic-gate * setup and launch of the detached thread. Retrieval will 96*7c478bd9Sstevel@tonic-gate * complete asynchronously. 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate int 99*7c478bd9Sstevel@tonic-gate db_mindex::entriesFromLDAP(__nis_table_mapping_t *t, db_query *qin, db_query *q, 100*7c478bd9Sstevel@tonic-gate char *dbId, nis_object *dirObj, int doAsynch) { 101*7c478bd9Sstevel@tonic-gate __entries_from_ldap_arg_t *arg; 102*7c478bd9Sstevel@tonic-gate int stat; 103*7c478bd9Sstevel@tonic-gate db_status dstat; 104*7c478bd9Sstevel@tonic-gate char *myself = "db_mindex::entriesFromLDAP"; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate arg = (__entries_from_ldap_arg_t *)am(myself, sizeof (*arg)); 107*7c478bd9Sstevel@tonic-gate if (arg == 0) { 108*7c478bd9Sstevel@tonic-gate freeQuery(q); 109*7c478bd9Sstevel@tonic-gate if (dirObj != 0) 110*7c478bd9Sstevel@tonic-gate nis_destroy_object(dirObj); 111*7c478bd9Sstevel@tonic-gate return (LDAP_NO_MEMORY); 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate arg->mindex = this; 115*7c478bd9Sstevel@tonic-gate arg->t = t; 116*7c478bd9Sstevel@tonic-gate arg->qin = qin; 117*7c478bd9Sstevel@tonic-gate arg->q = q; 118*7c478bd9Sstevel@tonic-gate arg->dbId = dbId; 119*7c478bd9Sstevel@tonic-gate arg->dirObj = dirObj; 120*7c478bd9Sstevel@tonic-gate arg->tableName = t->objName; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* 123*7c478bd9Sstevel@tonic-gate * Check if an enumeration thread is running; if so, then regardless 124*7c478bd9Sstevel@tonic-gate * of whether or not the current operation is an enumeration, we 125*7c478bd9Sstevel@tonic-gate * just return success, and let our caller get the data from the 126*7c478bd9Sstevel@tonic-gate * existing (deferred) DB. 127*7c478bd9Sstevel@tonic-gate */ 128*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 129*7c478bd9Sstevel@tonic-gate if (table->mapping.enumTid != 0) { 130*7c478bd9Sstevel@tonic-gate int doReturn = 0; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate stat = pthread_kill(table->mapping.enumTid, 0); 133*7c478bd9Sstevel@tonic-gate if (stat == ESRCH) { 134*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 135*7c478bd9Sstevel@tonic-gate "%s: Enumeration thread %d not found for \"%s\"; exit status = %d (%s)", 136*7c478bd9Sstevel@tonic-gate myself, table->mapping.enumTid, 137*7c478bd9Sstevel@tonic-gate NIL(t->objName), table->mapping.enumStat, 138*7c478bd9Sstevel@tonic-gate ldap_err2string(table->mapping.enumStat)); 139*7c478bd9Sstevel@tonic-gate /* Reflect the fact that no enum thread is running */ 140*7c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 141*7c478bd9Sstevel@tonic-gate table->mapping.enumStat = -1; 142*7c478bd9Sstevel@tonic-gate /* Cleanup deferred mode */ 143*7c478bd9Sstevel@tonic-gate if (table->mapping.enumDeferred) { 144*7c478bd9Sstevel@tonic-gate dstat = InUseDictionary->commit(t->objPath); 145*7c478bd9Sstevel@tonic-gate if (dstat == DB_SUCCESS) { 146*7c478bd9Sstevel@tonic-gate table->mapping.enumDeferred = 0; 147*7c478bd9Sstevel@tonic-gate } else { 148*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 149*7c478bd9Sstevel@tonic-gate "%s: DB error %d committing \"%s\"", 150*7c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate } else if (stat == 0) { 154*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 155*7c478bd9Sstevel@tonic-gate "%s: Enumeration thread %d already running for \"%s\"", 156*7c478bd9Sstevel@tonic-gate myself, table->mapping.enumTid, 157*7c478bd9Sstevel@tonic-gate NIL(t->objName)); 158*7c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 159*7c478bd9Sstevel@tonic-gate doReturn = 1; 160*7c478bd9Sstevel@tonic-gate } else { 161*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 162*7c478bd9Sstevel@tonic-gate "%s: Error %d looking for enumeration thread %d for \"%s\"", 163*7c478bd9Sstevel@tonic-gate myself, stat, table->mapping.enumTid, 164*7c478bd9Sstevel@tonic-gate NIL(t->objName)); 165*7c478bd9Sstevel@tonic-gate doReturn = 1; 166*7c478bd9Sstevel@tonic-gate stat = LDAP_OPERATIONS_ERROR; 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate if (doReturn) { 169*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 170*7c478bd9Sstevel@tonic-gate sfree(arg); 171*7c478bd9Sstevel@tonic-gate freeQuery(q); 172*7c478bd9Sstevel@tonic-gate if (dirObj != 0) 173*7c478bd9Sstevel@tonic-gate nis_destroy_object(dirObj); 174*7c478bd9Sstevel@tonic-gate return (stat); 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate /* 179*7c478bd9Sstevel@tonic-gate * If we're enumerating (and hence expect that retrieving all data, 180*7c478bd9Sstevel@tonic-gate * and updating the local DB, might take a while), create a deferred- 181*7c478bd9Sstevel@tonic-gate * update table that clients can use while we are updating the real 182*7c478bd9Sstevel@tonic-gate * one. 183*7c478bd9Sstevel@tonic-gate */ 184*7c478bd9Sstevel@tonic-gate if (doAsynch && qin == 0) { 185*7c478bd9Sstevel@tonic-gate if ((dstat = InUseDictionary->defer(t->objPath)) == 186*7c478bd9Sstevel@tonic-gate DB_SUCCESS) { 187*7c478bd9Sstevel@tonic-gate arg->isDeferred = 1; 188*7c478bd9Sstevel@tonic-gate table->mapping.enumDeferred = 1; 189*7c478bd9Sstevel@tonic-gate } else { 190*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 191*7c478bd9Sstevel@tonic-gate "%s: Unable to defer updates for \"%s\" (status=%d);" 192*7c478bd9Sstevel@tonic-gate " updating in place", 193*7c478bd9Sstevel@tonic-gate myself, NIL(t->objName), dstat); 194*7c478bd9Sstevel@tonic-gate arg->isDeferred = 0; 195*7c478bd9Sstevel@tonic-gate table->mapping.enumDeferred = 0; 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate } else { 198*7c478bd9Sstevel@tonic-gate arg->isDeferred = 0; 199*7c478bd9Sstevel@tonic-gate table->mapping.enumDeferred = 0; 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate /* If enumerating, perform the operation in a separate thread */ 203*7c478bd9Sstevel@tonic-gate if (doAsynch && qin == 0) { 204*7c478bd9Sstevel@tonic-gate pthread_t tid; 205*7c478bd9Sstevel@tonic-gate pthread_attr_t attr; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate (void) pthread_attr_init(&attr); 208*7c478bd9Sstevel@tonic-gate #ifdef FORCE_SYNCHRONOUS 209*7c478bd9Sstevel@tonic-gate #else 210*7c478bd9Sstevel@tonic-gate (void) pthread_attr_setdetachstate(&attr, 211*7c478bd9Sstevel@tonic-gate PTHREAD_CREATE_DETACHED); 212*7c478bd9Sstevel@tonic-gate #endif /* FORCE_SYNCHRONOUS */ 213*7c478bd9Sstevel@tonic-gate stat = pthread_create(&tid, &attr, entriesFromLDAPthread, arg); 214*7c478bd9Sstevel@tonic-gate if (stat != 0) { 215*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 216*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 217*7c478bd9Sstevel@tonic-gate "%s: Error %d creating new thread; using current one", 218*7c478bd9Sstevel@tonic-gate myself, stat); 219*7c478bd9Sstevel@tonic-gate stat = (int)entriesFromLDAPthread(arg); 220*7c478bd9Sstevel@tonic-gate return (stat); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate table->mapping.enumTid = tid; 224*7c478bd9Sstevel@tonic-gate table->mapping.enumStat = -1; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate /* 227*7c478bd9Sstevel@tonic-gate * We're now returning to the caller, who will get data 228*7c478bd9Sstevel@tonic-gate * from: 229*7c478bd9Sstevel@tonic-gate * 230*7c478bd9Sstevel@tonic-gate * The deferred DB, if an enumeration thread already 231*7c478bd9Sstevel@tonic-gate * was running, and deferred mode was on, or 232*7c478bd9Sstevel@tonic-gate * 233*7c478bd9Sstevel@tonic-gate * The original DB, if we just started an enumeration 234*7c478bd9Sstevel@tonic-gate * thread. In this case, our caller (several levels up) 235*7c478bd9Sstevel@tonic-gate * is holding a lock on the db_mindex/db_table, which 236*7c478bd9Sstevel@tonic-gate * means that the enum thread will have to wait for 237*7c478bd9Sstevel@tonic-gate * our caller once it's done the LDAP retrieval, and 238*7c478bd9Sstevel@tonic-gate * wants to update the DB. 239*7c478bd9Sstevel@tonic-gate */ 240*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 241*7c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 242*7c478bd9Sstevel@tonic-gate #ifdef FORCE_SYNCHRONOUS 243*7c478bd9Sstevel@tonic-gate { 244*7c478bd9Sstevel@tonic-gate int tstat; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate stat = pthread_join(tid, (void **)&tstat); 247*7c478bd9Sstevel@tonic-gate if (stat == 0) { 248*7c478bd9Sstevel@tonic-gate stat = tstat; 249*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 250*7c478bd9Sstevel@tonic-gate "%s: thread %d => %d", 251*7c478bd9Sstevel@tonic-gate myself, tid, tstat); 252*7c478bd9Sstevel@tonic-gate } else { 253*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 254*7c478bd9Sstevel@tonic-gate "%s: pthread_join(%d) => %d", 255*7c478bd9Sstevel@tonic-gate myself, tid, stat); 256*7c478bd9Sstevel@tonic-gate stat = LDAP_OPERATIONS_ERROR; 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate #endif /* FORCE_SYNCHRONOUS */ 260*7c478bd9Sstevel@tonic-gate } else { 261*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 262*7c478bd9Sstevel@tonic-gate stat = (int)entriesFromLDAPthread(arg); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate return (stat); 266*7c478bd9Sstevel@tonic-gate } 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate extern "C" { 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate /* 271*7c478bd9Sstevel@tonic-gate * We use this 'extern "C"' function in order to make sure that 272*7c478bd9Sstevel@tonic-gate * pthread_create() doesn't have any problems trying to invoke a 273*7c478bd9Sstevel@tonic-gate * C++ function. 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate static void * 276*7c478bd9Sstevel@tonic-gate entriesFromLDAPthread(void *voidarg) { 277*7c478bd9Sstevel@tonic-gate __entries_from_ldap_arg_t *arg; 278*7c478bd9Sstevel@tonic-gate int stat; 279*7c478bd9Sstevel@tonic-gate db *dbase; 280*7c478bd9Sstevel@tonic-gate db_table_desc *tbl = 0; 281*7c478bd9Sstevel@tonic-gate char *tableName; 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate arg = (__entries_from_ldap_arg_t *)voidarg; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate /* Lock to prevent removal */ 286*7c478bd9Sstevel@tonic-gate (void) __nis_lock_db_table(arg->tableName, 1, 0, 287*7c478bd9Sstevel@tonic-gate "entriesFromLDAPthread"); 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * It's possible that the db_mindex for the table has changed, 291*7c478bd9Sstevel@tonic-gate * or disappeared, between now and the time when our parent 292*7c478bd9Sstevel@tonic-gate * thread released its lock on the table. Hence, we search the 293*7c478bd9Sstevel@tonic-gate * dictionary to re-acquire the 'db', and the db_mindex. 294*7c478bd9Sstevel@tonic-gate */ 295*7c478bd9Sstevel@tonic-gate tableName = internalTableName(arg->tableName); 296*7c478bd9Sstevel@tonic-gate if (tableName != 0) { 297*7c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 298*7c478bd9Sstevel@tonic-gate db_mindex *oldMindex = arg->mindex; 299*7c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate dbase = InUseDictionary->find_table(tableName, &tbl, FALSE); 302*7c478bd9Sstevel@tonic-gate if (dbase != 0) 303*7c478bd9Sstevel@tonic-gate arg->mindex = dbase->mindex(); 304*7c478bd9Sstevel@tonic-gate else 305*7c478bd9Sstevel@tonic-gate arg->mindex = 0; 306*7c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 307*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 308*7c478bd9Sstevel@tonic-gate "entriesFromLDAPthread: %s -> %s -> 0x%x (0x%x)", 309*7c478bd9Sstevel@tonic-gate NIL(arg->tableName), NIL(tableName), 310*7c478bd9Sstevel@tonic-gate arg->mindex, oldMindex); 311*7c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 312*7c478bd9Sstevel@tonic-gate sfree(tableName); 313*7c478bd9Sstevel@tonic-gate tableName = 0; 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate stat = entriesFromLDAPreal(arg); 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate (void) __nis_ulock_db_table(arg->tableName, 1, 0, 319*7c478bd9Sstevel@tonic-gate "entriesFromLDAPthread"); 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate freeQuery(arg->q); 322*7c478bd9Sstevel@tonic-gate if (arg->dirObj != 0) 323*7c478bd9Sstevel@tonic-gate nis_destroy_object(arg->dirObj); 324*7c478bd9Sstevel@tonic-gate sfree(arg); 325*7c478bd9Sstevel@tonic-gate return ((void *)stat); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate int 331*7c478bd9Sstevel@tonic-gate entriesFromLDAPreal(__entries_from_ldap_arg_t *arg) { 332*7c478bd9Sstevel@tonic-gate db_mindex *mindex; 333*7c478bd9Sstevel@tonic-gate db_table *table; 334*7c478bd9Sstevel@tonic-gate __nis_table_mapping_t *t; 335*7c478bd9Sstevel@tonic-gate db_query *q, *qin; 336*7c478bd9Sstevel@tonic-gate char *dbId; 337*7c478bd9Sstevel@tonic-gate nis_object *dirObj; 338*7c478bd9Sstevel@tonic-gate int i, na, nau, nq = 0, xid = 0; 339*7c478bd9Sstevel@tonic-gate int ret, stat = LDAP_SUCCESS, stat2, stat3; 340*7c478bd9Sstevel@tonic-gate int lstat; 341*7c478bd9Sstevel@tonic-gate __nis_obj_attr_t **oa = 0; 342*7c478bd9Sstevel@tonic-gate db_query **res; 343*7c478bd9Sstevel@tonic-gate entry_object **ea; 344*7c478bd9Sstevel@tonic-gate long numEa; 345*7c478bd9Sstevel@tonic-gate bool_t doEnum; 346*7c478bd9Sstevel@tonic-gate db_status dstat; 347*7c478bd9Sstevel@tonic-gate struct timeval start; 348*7c478bd9Sstevel@tonic-gate char *myself = 349*7c478bd9Sstevel@tonic-gate "db_mindex::entriesFromLDAPreal"; 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate if (arg == 0) 352*7c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 353*7c478bd9Sstevel@tonic-gate mindex = arg->mindex; 354*7c478bd9Sstevel@tonic-gate t = arg->t; 355*7c478bd9Sstevel@tonic-gate q = arg->q; 356*7c478bd9Sstevel@tonic-gate qin = arg->qin; 357*7c478bd9Sstevel@tonic-gate dbId = arg->dbId; 358*7c478bd9Sstevel@tonic-gate dirObj = arg->dirObj; 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate table = (mindex != 0) ? mindex->getTable() : 0; 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate if (mindex == 0 || t == 0 || table == 0) { 363*7c478bd9Sstevel@tonic-gate /* We haven't done anything, so rollback should be OK */ 364*7c478bd9Sstevel@tonic-gate if (arg->isDeferred && t != 0) { 365*7c478bd9Sstevel@tonic-gate dstat = InUseDictionary->rollback(t->objPath); 366*7c478bd9Sstevel@tonic-gate if (dstat != DB_SUCCESS) { 367*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 368*7c478bd9Sstevel@tonic-gate "%s: DB error %d rolling back \"%s\"", 369*7c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 370*7c478bd9Sstevel@tonic-gate /* 371*7c478bd9Sstevel@tonic-gate * Had rollback succeeded, the 'table' 372*7c478bd9Sstevel@tonic-gate * would have disappeared. However, since 373*7c478bd9Sstevel@tonic-gate * rollback failed, we need to update the 374*7c478bd9Sstevel@tonic-gate * table->mapping.enum* fields. 375*7c478bd9Sstevel@tonic-gate */ 376*7c478bd9Sstevel@tonic-gate if (table != 0) { 377*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&table-> 378*7c478bd9Sstevel@tonic-gate mapping.enumLock); 379*7c478bd9Sstevel@tonic-gate table->mapping.enumStat = 380*7c478bd9Sstevel@tonic-gate LDAP_PARAM_ERROR; 381*7c478bd9Sstevel@tonic-gate table->mapping.enumTime = 0; 382*7c478bd9Sstevel@tonic-gate table->mapping.enumEntries = 0; 383*7c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 384*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table-> 385*7c478bd9Sstevel@tonic-gate mapping.enumLock); 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate return (LDAP_PARAM_ERROR); 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate if (qin == 0) 393*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, "%s: enumerating \"%s%s%s\"", 394*7c478bd9Sstevel@tonic-gate myself, dbId ? dbId : "", dbId ? ":" : "", 395*7c478bd9Sstevel@tonic-gate NIL(t->objName)); 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&start, 0); 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate /* Getting table entries */ 400*7c478bd9Sstevel@tonic-gate res = mapFromLDAP(t, q, &nq, dbId, &stat, &oa); 401*7c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 402*7c478bd9Sstevel@tonic-gate logmsg(MSG_ALWAYS, LOG_INFO, 403*7c478bd9Sstevel@tonic-gate "%s: mapFromLDAP() => 0x%x, status=%d %s; nq = %d", 404*7c478bd9Sstevel@tonic-gate myself, res, stat, stat == LDAP_SUCCESS ? "" : 405*7c478bd9Sstevel@tonic-gate ldap_err2string(stat), nq); 406*7c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate /* 409*7c478bd9Sstevel@tonic-gate * Keep track of the number of NIS+ entries we got back; 410*7c478bd9Sstevel@tonic-gate * note that the number of LDAP entries may have been 411*7c478bd9Sstevel@tonic-gate * smaller or larger. 412*7c478bd9Sstevel@tonic-gate */ 413*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 414*7c478bd9Sstevel@tonic-gate table->mapping.enumEntries = nq; 415*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate /* 418*7c478bd9Sstevel@tonic-gate * If we get LDAP_NO_SUCH_OBJECT, we need to delete the entries 419*7c478bd9Sstevel@tonic-gate * in the table, so we can't just return. 420*7c478bd9Sstevel@tonic-gate */ 421*7c478bd9Sstevel@tonic-gate if (res == 0 && stat != LDAP_NO_SUCH_OBJECT) { 422*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 423*7c478bd9Sstevel@tonic-gate "%s: mapFromLDAP() => 0x0, status=%d (%s)", 424*7c478bd9Sstevel@tonic-gate myself, stat, ldap_err2string(stat)); 425*7c478bd9Sstevel@tonic-gate if (arg->isDeferred) { 426*7c478bd9Sstevel@tonic-gate dstat = InUseDictionary->rollback(t->objPath); 427*7c478bd9Sstevel@tonic-gate if (dstat != DB_SUCCESS) { 428*7c478bd9Sstevel@tonic-gate struct timeval end; 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 431*7c478bd9Sstevel@tonic-gate "%s: DB error %d rolling back \"%s\"", 432*7c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 433*7c478bd9Sstevel@tonic-gate /* 434*7c478bd9Sstevel@tonic-gate * Had rollback succeeded, the 'table' 435*7c478bd9Sstevel@tonic-gate * would have disappeared. However, since 436*7c478bd9Sstevel@tonic-gate * rollback failed, we need to update the 437*7c478bd9Sstevel@tonic-gate * table->mapping.enum* fields. 438*7c478bd9Sstevel@tonic-gate */ 439*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 440*7c478bd9Sstevel@tonic-gate table->mapping.enumStat = stat; 441*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&end, 0); 442*7c478bd9Sstevel@tonic-gate end.tv_sec -= start.tv_sec; 443*7c478bd9Sstevel@tonic-gate end.tv_usec -= start.tv_usec; 444*7c478bd9Sstevel@tonic-gate if (end.tv_usec < 0) { 445*7c478bd9Sstevel@tonic-gate end.tv_usec += 1000000; 446*7c478bd9Sstevel@tonic-gate end.tv_sec -= 1; 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate table->mapping.enumTime = 449*7c478bd9Sstevel@tonic-gate 1000000*end.tv_sec + end.tv_usec; 450*7c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 451*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate return (stat); 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate /* 458*7c478bd9Sstevel@tonic-gate * Need to disable write-through to LDAP, for which we need a lock 459*7c478bd9Sstevel@tonic-gate * on our db_mindex ('mindex'); we're also updating the table, so 460*7c478bd9Sstevel@tonic-gate * we need a write lock on that as well. However, before locking the 461*7c478bd9Sstevel@tonic-gate * mindex, we need to maintain lock integrity by acquiring the 462*7c478bd9Sstevel@tonic-gate * trans log lock. Note that actually beginning a transaction is 463*7c478bd9Sstevel@tonic-gate * expensive, so we defer that until we know that we really need 464*7c478bd9Sstevel@tonic-gate * to update. 465*7c478bd9Sstevel@tonic-gate */ 466*7c478bd9Sstevel@tonic-gate lstat = lockTransLog(myself, 1, 1); 467*7c478bd9Sstevel@tonic-gate if (lstat != 0) { 468*7c478bd9Sstevel@tonic-gate if (lstat == EBUSY) 469*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 470*7c478bd9Sstevel@tonic-gate "%s: transaction log busy; no LDAP update for \"%s\"", 471*7c478bd9Sstevel@tonic-gate myself, NIL(t->objName)); 472*7c478bd9Sstevel@tonic-gate else 473*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 474*7c478bd9Sstevel@tonic-gate "%s: Error %d locking transaction log; no LDAP update for \"%s\"", 475*7c478bd9Sstevel@tonic-gate myself, lstat, NIL(t->objName)); 476*7c478bd9Sstevel@tonic-gate if (arg->isDeferred) { 477*7c478bd9Sstevel@tonic-gate dstat = InUseDictionary->rollback(t->objPath); 478*7c478bd9Sstevel@tonic-gate if (dstat != DB_SUCCESS) { 479*7c478bd9Sstevel@tonic-gate struct timeval end; 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 482*7c478bd9Sstevel@tonic-gate "%s: DB error %d rolling back \"%s\"", 483*7c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 484*7c478bd9Sstevel@tonic-gate /* 485*7c478bd9Sstevel@tonic-gate * Had rollback succeeded, the 'table' 486*7c478bd9Sstevel@tonic-gate * would have disappeared. However, since 487*7c478bd9Sstevel@tonic-gate * rollback failed, we need to update the 488*7c478bd9Sstevel@tonic-gate * table->mapping.enum* fields. 489*7c478bd9Sstevel@tonic-gate */ 490*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 491*7c478bd9Sstevel@tonic-gate table->mapping.enumStat = LDAP_OPERATIONS_ERROR; 492*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&end, 0); 493*7c478bd9Sstevel@tonic-gate end.tv_sec -= start.tv_sec; 494*7c478bd9Sstevel@tonic-gate end.tv_usec -= start.tv_usec; 495*7c478bd9Sstevel@tonic-gate if (end.tv_usec < 0) { 496*7c478bd9Sstevel@tonic-gate end.tv_usec += 1000000; 497*7c478bd9Sstevel@tonic-gate end.tv_sec -= 1; 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate table->mapping.enumTime = 1000000*end.tv_sec + 500*7c478bd9Sstevel@tonic-gate end.tv_usec; 501*7c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 502*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate return (LDAP_OPERATIONS_ERROR); 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate /* 509*7c478bd9Sstevel@tonic-gate * If we have any updates, we'll call db::sync_log, which write- 510*7c478bd9Sstevel@tonic-gate * locks the 'db' instance. In order to avoid a dead-lock with 511*7c478bd9Sstevel@tonic-gate * threads performing a DB lookup (which will lock the 'db' and 512*7c478bd9Sstevel@tonic-gate * then the 'db_mindex'), we need hence need to lock in the 513*7c478bd9Sstevel@tonic-gate * following order: 514*7c478bd9Sstevel@tonic-gate * 515*7c478bd9Sstevel@tonic-gate * trans.log (already holding that one) 516*7c478bd9Sstevel@tonic-gate * db 517*7c478bd9Sstevel@tonic-gate * db_mindex 518*7c478bd9Sstevel@tonic-gate * db_table 519*7c478bd9Sstevel@tonic-gate */ 520*7c478bd9Sstevel@tonic-gate TRYWRITELOCK(((db *)mindex->getDbPtr()), stat, 521*7c478bd9Sstevel@tonic-gate "w db db_mindex::entriesFromLDAPreal"); 522*7c478bd9Sstevel@tonic-gate if (stat == 0) { 523*7c478bd9Sstevel@tonic-gate TRYWRITELOCK(mindex, stat2, "w db_mindex::entriesFromLDAPreal"); 524*7c478bd9Sstevel@tonic-gate if (stat2 == 0) { 525*7c478bd9Sstevel@tonic-gate TRYWRITELOCK(table, stat3, 526*7c478bd9Sstevel@tonic-gate "table w db_mindex::entriesFromLDAPreal"); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate if (stat != 0 || stat2 != 0 || stat3 != 0) { 531*7c478bd9Sstevel@tonic-gate if (stat != 0) { 532*7c478bd9Sstevel@tonic-gate if (stat == EBUSY) 533*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 534*7c478bd9Sstevel@tonic-gate "%s: 'db' busy; no LDAP update for \"%s\"", 535*7c478bd9Sstevel@tonic-gate myself, NIL(t->objName)); 536*7c478bd9Sstevel@tonic-gate else 537*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 538*7c478bd9Sstevel@tonic-gate "%s: 'db' lock error %d; no LDAP update for \"%s\"", 539*7c478bd9Sstevel@tonic-gate myself, stat, NIL(t->objName)); 540*7c478bd9Sstevel@tonic-gate } else if (stat2 != 0) { 541*7c478bd9Sstevel@tonic-gate if (stat2 == EBUSY) 542*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 543*7c478bd9Sstevel@tonic-gate "%s: 'db_mindex' busy; no LDAP update for \"%s\"", 544*7c478bd9Sstevel@tonic-gate myself, NIL(t->objName)); 545*7c478bd9Sstevel@tonic-gate else 546*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 547*7c478bd9Sstevel@tonic-gate "%s: 'db_mindex' lock error %d; no LDAP update for \"%s\"", 548*7c478bd9Sstevel@tonic-gate myself, stat2, NIL(t->objName)); 549*7c478bd9Sstevel@tonic-gate } else { 550*7c478bd9Sstevel@tonic-gate if (stat3 == EBUSY) 551*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 552*7c478bd9Sstevel@tonic-gate "%s: 'db_table' busy; no LDAP update for \"%s\"", 553*7c478bd9Sstevel@tonic-gate myself, NIL(t->objName)); 554*7c478bd9Sstevel@tonic-gate else 555*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 556*7c478bd9Sstevel@tonic-gate "%s: 'db_table' lock error %d; no LDAP update for \"%s\"", 557*7c478bd9Sstevel@tonic-gate myself, stat3, NIL(t->objName)); 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate freeQueries(res, nq); 560*7c478bd9Sstevel@tonic-gate if (arg->isDeferred) { 561*7c478bd9Sstevel@tonic-gate dstat = InUseDictionary->rollback(t->objPath); 562*7c478bd9Sstevel@tonic-gate if (dstat != DB_SUCCESS) { 563*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 564*7c478bd9Sstevel@tonic-gate "%s: DB error %d rolling back \"%s\"", 565*7c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 566*7c478bd9Sstevel@tonic-gate /* 567*7c478bd9Sstevel@tonic-gate * Had rollback succeeded, the 'table' 568*7c478bd9Sstevel@tonic-gate * would have disappeared. However, since 569*7c478bd9Sstevel@tonic-gate * rollback failed, we need to update the 570*7c478bd9Sstevel@tonic-gate * table->mapping.enum* fields. 571*7c478bd9Sstevel@tonic-gate */ 572*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 573*7c478bd9Sstevel@tonic-gate table->mapping.enumStat = LDAP_OPERATIONS_ERROR; 574*7c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 575*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate if (stat == 0) { 579*7c478bd9Sstevel@tonic-gate if (stat2 == 0) { 580*7c478bd9Sstevel@tonic-gate WRITEUNLOCK2(mindex, ((db *)mindex->getDbPtr()), 581*7c478bd9Sstevel@tonic-gate LDAP_OPERATIONS_ERROR, 582*7c478bd9Sstevel@tonic-gate LDAP_OPERATIONS_ERROR, 583*7c478bd9Sstevel@tonic-gate "db_mindex::entriesFromLDAPreal wu", 584*7c478bd9Sstevel@tonic-gate "db_mindex::entriesFromLDAPreal wu db"); 585*7c478bd9Sstevel@tonic-gate } else { 586*7c478bd9Sstevel@tonic-gate WRITEUNLOCK(((db *)mindex->getDbPtr()), 587*7c478bd9Sstevel@tonic-gate LDAP_OPERATIONS_ERROR, 588*7c478bd9Sstevel@tonic-gate "db_mindex::entriesFromLDAPreal wu db"); 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate unlockTransLog(myself, 1); 592*7c478bd9Sstevel@tonic-gate return (LDAP_OPERATIONS_ERROR); 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 596*7c478bd9Sstevel@tonic-gate mindex->setNoWriteThrough(); 597*7c478bd9Sstevel@tonic-gate mindex->setNoLDAPquery(); 598*7c478bd9Sstevel@tonic-gate if (qin == 0) { 599*7c478bd9Sstevel@tonic-gate table->setEnumMode(0); 600*7c478bd9Sstevel@tonic-gate doEnum = TRUE; 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate /* 603*7c478bd9Sstevel@tonic-gate * If there is no non-indexed table mapping, we must filter 604*7c478bd9Sstevel@tonic-gate * the enum mode (i.e., deletion candidates) array to only 605*7c478bd9Sstevel@tonic-gate * contain those entries that match the indexes. 606*7c478bd9Sstevel@tonic-gate */ 607*7c478bd9Sstevel@tonic-gate if (haveIndexedMapping(t)) { 608*7c478bd9Sstevel@tonic-gate entry_object **tea = table->gettab(); 609*7c478bd9Sstevel@tonic-gate long i, ntea = table->getsize(); 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate /* 613*7c478bd9Sstevel@tonic-gate * Walk through the entry array, and remove any enum 614*7c478bd9Sstevel@tonic-gate * array entry that _doesn't_ match the index(es). 615*7c478bd9Sstevel@tonic-gate */ 616*7c478bd9Sstevel@tonic-gate for (i = 0; i < ntea; i++) { 617*7c478bd9Sstevel@tonic-gate db_query *q; 618*7c478bd9Sstevel@tonic-gate __nis_table_mapping_t **tp; 619*7c478bd9Sstevel@tonic-gate int numMatches; 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate if (tea[i] == 0) 622*7c478bd9Sstevel@tonic-gate continue; 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate q = pseudoEntryObj2Query(tea[i], 0, 0); 625*7c478bd9Sstevel@tonic-gate if (q == 0) 626*7c478bd9Sstevel@tonic-gate continue; 627*7c478bd9Sstevel@tonic-gate 628*7c478bd9Sstevel@tonic-gate tp = selectTableMapping(t, q, 0, 0, dbId, 629*7c478bd9Sstevel@tonic-gate &numMatches); 630*7c478bd9Sstevel@tonic-gate if (tp == 0 || numMatches <= 0) 631*7c478bd9Sstevel@tonic-gate table->enumTouch(i); 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate sfree(tp); 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate freeQuery(q); 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, "%s: %d entries from LDAP", 640*7c478bd9Sstevel@tonic-gate myself, nq); 641*7c478bd9Sstevel@tonic-gate } else { 642*7c478bd9Sstevel@tonic-gate db_index_entry *dbie; 643*7c478bd9Sstevel@tonic-gate long i, count; 644*7c478bd9Sstevel@tonic-gate bool_t valid; 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate /* 647*7c478bd9Sstevel@tonic-gate * Find the entries in the DB that currently match the 648*7c478bd9Sstevel@tonic-gate * query, and add them to the enum array. Those that 649*7c478bd9Sstevel@tonic-gate * remain untouched when we've processed the LDAP data 650*7c478bd9Sstevel@tonic-gate * don't currently exist in LDAP, and should be deleted 651*7c478bd9Sstevel@tonic-gate * from the DB. 652*7c478bd9Sstevel@tonic-gate */ 653*7c478bd9Sstevel@tonic-gate dbie = mindex->satisfy_query_dbonly(qin, &count, FALSE, &valid); 654*7c478bd9Sstevel@tonic-gate if (dbie != 0 && valid && count > 0) { 655*7c478bd9Sstevel@tonic-gate table->setEnumMode(count); 656*7c478bd9Sstevel@tonic-gate doEnum = TRUE; 657*7c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) { 658*7c478bd9Sstevel@tonic-gate table->enumSetup(dbie->getlocation(), i); 659*7c478bd9Sstevel@tonic-gate dbie = dbie->getnextresult(); 660*7c478bd9Sstevel@tonic-gate if (dbie == 0) 661*7c478bd9Sstevel@tonic-gate break; 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate } else { 664*7c478bd9Sstevel@tonic-gate doEnum = FALSE; 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate entry_col ec[NIS_MAXCOLUMNS+1]; 669*7c478bd9Sstevel@tonic-gate for (i = 0, na = 0; i < nq; i++) { 670*7c478bd9Sstevel@tonic-gate entry_object eo, *e; 671*7c478bd9Sstevel@tonic-gate table_col *tc; 672*7c478bd9Sstevel@tonic-gate nis_object o, *to; 673*7c478bd9Sstevel@tonic-gate int j, nc; 674*7c478bd9Sstevel@tonic-gate db_qcomp *qc; 675*7c478bd9Sstevel@tonic-gate 676*7c478bd9Sstevel@tonic-gate if (res[i] == 0) 677*7c478bd9Sstevel@tonic-gate continue; 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 680*7c478bd9Sstevel@tonic-gate printQuery(res[i], t); 681*7c478bd9Sstevel@tonic-gate printObjAttr(oa[i]); 682*7c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate /* Assemble an object from the query and attributes */ 685*7c478bd9Sstevel@tonic-gate (void) memset(&o, 0, sizeof (o)); 686*7c478bd9Sstevel@tonic-gate if (oa[i] != 0) { 687*7c478bd9Sstevel@tonic-gate o.zo_owner = oa[i]->zo_owner; 688*7c478bd9Sstevel@tonic-gate o.zo_group = oa[i]->zo_group; 689*7c478bd9Sstevel@tonic-gate o.zo_domain = oa[i]->zo_domain; 690*7c478bd9Sstevel@tonic-gate o.zo_access = oa[i]->zo_access; 691*7c478bd9Sstevel@tonic-gate o.zo_ttl = oa[i]->zo_ttl; 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate if ((to = t->obj) != 0) { 694*7c478bd9Sstevel@tonic-gate o.zo_name = to->zo_name; 695*7c478bd9Sstevel@tonic-gate o.zo_data.objdata_u.en_data.en_type = 696*7c478bd9Sstevel@tonic-gate to->zo_data.objdata_u.ta_data.ta_type; 697*7c478bd9Sstevel@tonic-gate tc = to->zo_data.objdata_u.ta_data.ta_cols.ta_cols_val; 698*7c478bd9Sstevel@tonic-gate if (to->zo_data.objdata_u.ta_data.ta_cols.ta_cols_len 699*7c478bd9Sstevel@tonic-gate != t->numColumns) 700*7c478bd9Sstevel@tonic-gate tc = 0; 701*7c478bd9Sstevel@tonic-gate if (o.zo_owner == 0) 702*7c478bd9Sstevel@tonic-gate o.zo_owner = to->zo_owner; 703*7c478bd9Sstevel@tonic-gate if (o.zo_group == 0) 704*7c478bd9Sstevel@tonic-gate o.zo_group = to->zo_group; 705*7c478bd9Sstevel@tonic-gate if (o.zo_domain == 0) 706*7c478bd9Sstevel@tonic-gate o.zo_domain = to->zo_domain; 707*7c478bd9Sstevel@tonic-gate if (o.zo_access == 0) 708*7c478bd9Sstevel@tonic-gate o.zo_access = to->zo_access; 709*7c478bd9Sstevel@tonic-gate if (o.zo_ttl == 0) 710*7c478bd9Sstevel@tonic-gate o.zo_ttl = to->zo_ttl; 711*7c478bd9Sstevel@tonic-gate } else { 712*7c478bd9Sstevel@tonic-gate tc = 0; 713*7c478bd9Sstevel@tonic-gate o.zo_owner = ""; 714*7c478bd9Sstevel@tonic-gate o.zo_group = ""; 715*7c478bd9Sstevel@tonic-gate o.zo_domain = ""; 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate o.zo_data.zo_type = NIS_ENTRY_OBJ; 719*7c478bd9Sstevel@tonic-gate o.zo_data.objdata_u.en_data.en_cols.en_cols_len = 720*7c478bd9Sstevel@tonic-gate t->numColumns + 1; 721*7c478bd9Sstevel@tonic-gate o.zo_data.objdata_u.en_data.en_cols.en_cols_val = ec; 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate (void) memset(&ec, 0, sizeof (ec)); 724*7c478bd9Sstevel@tonic-gate nc = res[i]->size(); 725*7c478bd9Sstevel@tonic-gate qc = res[i]->queryloc(); 726*7c478bd9Sstevel@tonic-gate if (qc == 0) { 727*7c478bd9Sstevel@tonic-gate freeQuery(res[i]); 728*7c478bd9Sstevel@tonic-gate continue; 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate for (j = 0; j < nc; j++) { 731*7c478bd9Sstevel@tonic-gate int ic = 1+ qc[j].which_index; 732*7c478bd9Sstevel@tonic-gate if (ic < 1 || ic > t->numColumns) 733*7c478bd9Sstevel@tonic-gate continue; 734*7c478bd9Sstevel@tonic-gate #ifdef SET_ENTRY_FLAGS 735*7c478bd9Sstevel@tonic-gate if (tc != 0) 736*7c478bd9Sstevel@tonic-gate ec[ic].ec_flags = 737*7c478bd9Sstevel@tonic-gate entryFlagsFromTable(tc[ic-1].tc_flags); 738*7c478bd9Sstevel@tonic-gate #else 739*7c478bd9Sstevel@tonic-gate /* 740*7c478bd9Sstevel@tonic-gate * In theory, the entry flags should be derived 741*7c478bd9Sstevel@tonic-gate * from the table flags. However, that doesn't 742*7c478bd9Sstevel@tonic-gate * seem to be the way that the DB code has done 743*7c478bd9Sstevel@tonic-gate * things so far, so leave the entry flags unset. 744*7c478bd9Sstevel@tonic-gate */ 745*7c478bd9Sstevel@tonic-gate #endif /* SET_ENTRY_FLAGS */ 746*7c478bd9Sstevel@tonic-gate qc[j].index_value->get_value( 747*7c478bd9Sstevel@tonic-gate &ec[ic].ec_value.ec_value_val, 748*7c478bd9Sstevel@tonic-gate (int *)&ec[ic].ec_value.ec_value_len); 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate setOid(&o); 752*7c478bd9Sstevel@tonic-gate e = makePseudoEntryObj(&o, &eo, t->obj); 753*7c478bd9Sstevel@tonic-gate if (e == 0) { 754*7c478bd9Sstevel@tonic-gate freeQuery(res[i]); 755*7c478bd9Sstevel@tonic-gate continue; 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate /* 759*7c478bd9Sstevel@tonic-gate * 'o' is currently a pseudo-object of type entry, with 760*7c478bd9Sstevel@tonic-gate * column zero used for an XDR:ed version of the entry_obj, 761*7c478bd9Sstevel@tonic-gate * column one the real column zero of the entry, etc. 762*7c478bd9Sstevel@tonic-gate * We now need a real NIS_ENTRY_OBJ object, so move the 763*7c478bd9Sstevel@tonic-gate * entry_col array one step left. 764*7c478bd9Sstevel@tonic-gate */ 765*7c478bd9Sstevel@tonic-gate o.zo_data.objdata_u.en_data.en_cols.en_cols_len = t->numColumns; 766*7c478bd9Sstevel@tonic-gate o.zo_data.objdata_u.en_data.en_cols.en_cols_val = &ec[1]; 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate stat = mindex->updateTableEntry(e, 1, t->objName, &o, t->obj, 769*7c478bd9Sstevel@tonic-gate o.zo_oid.mtime, &xid); 770*7c478bd9Sstevel@tonic-gate /* 771*7c478bd9Sstevel@tonic-gate * LDAP_SUCCESS => Entry added or modified 772*7c478bd9Sstevel@tonic-gate * LDAP_COMPARE_TRUE => Entry same as existing one 773*7c478bd9Sstevel@tonic-gate * other => Error 774*7c478bd9Sstevel@tonic-gate */ 775*7c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) { 776*7c478bd9Sstevel@tonic-gate na++; 777*7c478bd9Sstevel@tonic-gate } else if (stat == LDAP_COMPARE_TRUE) { 778*7c478bd9Sstevel@tonic-gate stat = LDAP_SUCCESS; 779*7c478bd9Sstevel@tonic-gate } else { 780*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 781*7c478bd9Sstevel@tonic-gate "%s: Error adding entry to \"%s\": %s", 782*7c478bd9Sstevel@tonic-gate myself, NIL(t->objName), 783*7c478bd9Sstevel@tonic-gate ldap_err2string(stat)); 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate if (e->en_cols.en_cols_val != 0) 787*7c478bd9Sstevel@tonic-gate sfree(e->en_cols.en_cols_val[0].ec_value.ec_value_val); 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate freeQuery(res[i]); 790*7c478bd9Sstevel@tonic-gate } 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate sfree(res); 793*7c478bd9Sstevel@tonic-gate 794*7c478bd9Sstevel@tonic-gate /* Take care of deletes if we enumerated the table */ 795*7c478bd9Sstevel@tonic-gate if (doEnum) { 796*7c478bd9Sstevel@tonic-gate ea = table->endEnumMode(&numEa); 797*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 798*7c478bd9Sstevel@tonic-gate "%s: %d entries added/updated", myself, na); 799*7c478bd9Sstevel@tonic-gate nau = na; 800*7c478bd9Sstevel@tonic-gate } else 801*7c478bd9Sstevel@tonic-gate ea = 0; 802*7c478bd9Sstevel@tonic-gate if (ea != 0) { 803*7c478bd9Sstevel@tonic-gate uint32_t nowt = time(0); 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate for (i = 0; i < numEa; i++) { 806*7c478bd9Sstevel@tonic-gate int st; 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate if (ea[i] == 0) 809*7c478bd9Sstevel@tonic-gate continue; 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate st = mindex->updateTableEntry(ea[i], 0, t->objName, 0, 812*7c478bd9Sstevel@tonic-gate t->obj, nowt, &xid); 813*7c478bd9Sstevel@tonic-gate if (st == LDAP_SUCCESS) { 814*7c478bd9Sstevel@tonic-gate na++; 815*7c478bd9Sstevel@tonic-gate } else { 816*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 817*7c478bd9Sstevel@tonic-gate "%s: Error removing directory entry for \"%s\": %s", 818*7c478bd9Sstevel@tonic-gate myself, NIL(t->objName), 819*7c478bd9Sstevel@tonic-gate ldap_err2string(st)); 820*7c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) 821*7c478bd9Sstevel@tonic-gate stat = st; 822*7c478bd9Sstevel@tonic-gate } 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate if (stat == LDAP_SUCCESS) { 825*7c478bd9Sstevel@tonic-gate struct timeval now; 826*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, 0); 827*7c478bd9Sstevel@tonic-gate table->mapping.enumExpire = now.tv_sec + 828*7c478bd9Sstevel@tonic-gate table->mapping.ttl; 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate if (doEnum) 831*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 832*7c478bd9Sstevel@tonic-gate "%s: %d entries deleted", myself, na-nau); 833*7c478bd9Sstevel@tonic-gate } 834*7c478bd9Sstevel@tonic-gate 835*7c478bd9Sstevel@tonic-gate sfree(ea); 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate /* If we called log_action() successfully, we need to sync the log */ 838*7c478bd9Sstevel@tonic-gate if (na > 0) 839*7c478bd9Sstevel@tonic-gate (void) ((db *)mindex->getDbPtr())->sync_log(); 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate if (xid != 0 && na > 0 && stat == LDAP_SUCCESS) 842*7c478bd9Sstevel@tonic-gate ret = endTransaction(xid, dirObj); 843*7c478bd9Sstevel@tonic-gate else if (xid != 0) 844*7c478bd9Sstevel@tonic-gate ret = abort_transaction(xid); 845*7c478bd9Sstevel@tonic-gate else 846*7c478bd9Sstevel@tonic-gate ret = 0; 847*7c478bd9Sstevel@tonic-gate if (ret != 0) { 848*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_ERR, 849*7c478bd9Sstevel@tonic-gate "%s: Error %s transaction for \"%s\"", 850*7c478bd9Sstevel@tonic-gate myself, (na > 0 && stat == LDAP_SUCCESS) ? 851*7c478bd9Sstevel@tonic-gate "ending" : "aborting", 852*7c478bd9Sstevel@tonic-gate NIL(t->objName)); 853*7c478bd9Sstevel@tonic-gate stat = LDAP_OPERATIONS_ERROR; 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate mindex->clearNoLDAPquery(); 857*7c478bd9Sstevel@tonic-gate mindex->clearNoWriteThrough(); 858*7c478bd9Sstevel@tonic-gate freeObjAttr(oa, nq); 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 861*7c478bd9Sstevel@tonic-gate printbuf(); 862*7c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate if (doEnum) 865*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_INFO, 866*7c478bd9Sstevel@tonic-gate "%s: enumeration \"%s\" done", myself, NIL(t->objName)); 867*7c478bd9Sstevel@tonic-gate 868*7c478bd9Sstevel@tonic-gate if (arg->isDeferred) { 869*7c478bd9Sstevel@tonic-gate /* 870*7c478bd9Sstevel@tonic-gate * Rollback doesn't recover data written to disk, so 871*7c478bd9Sstevel@tonic-gate * we should commit even if we're returning failure. 872*7c478bd9Sstevel@tonic-gate */ 873*7c478bd9Sstevel@tonic-gate dstat = InUseDictionary->commit(t->objPath); 874*7c478bd9Sstevel@tonic-gate if (dstat != DB_SUCCESS) { 875*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 876*7c478bd9Sstevel@tonic-gate "%s: DB error %d committing \"%s\"", 877*7c478bd9Sstevel@tonic-gate myself, dstat, NIL(t->objName)); 878*7c478bd9Sstevel@tonic-gate } 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&table->mapping.enumLock); 881*7c478bd9Sstevel@tonic-gate if (arg->isDeferred && dstat == DB_SUCCESS) 882*7c478bd9Sstevel@tonic-gate table->mapping.enumDeferred = 0; 883*7c478bd9Sstevel@tonic-gate table->mapping.enumStat = stat; 884*7c478bd9Sstevel@tonic-gate { 885*7c478bd9Sstevel@tonic-gate struct timeval end; 886*7c478bd9Sstevel@tonic-gate 887*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&end, 0); 888*7c478bd9Sstevel@tonic-gate end.tv_sec -= start.tv_sec; 889*7c478bd9Sstevel@tonic-gate end.tv_usec -= start.tv_usec; 890*7c478bd9Sstevel@tonic-gate if (end.tv_usec < 0) { 891*7c478bd9Sstevel@tonic-gate end.tv_usec += 1000000; 892*7c478bd9Sstevel@tonic-gate end.tv_sec -= 1; 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate table->mapping.enumTime = 1000000*end.tv_sec + end.tv_usec; 895*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, 896*7c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 897*7c478bd9Sstevel@tonic-gate LOG_WARNING, 898*7c478bd9Sstevel@tonic-gate #else 899*7c478bd9Sstevel@tonic-gate LOG_INFO, 900*7c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 901*7c478bd9Sstevel@tonic-gate "%s: %d entries in %ld usec => %ld usec/entry", 902*7c478bd9Sstevel@tonic-gate NIL(t->objName), table->mapping.enumEntries, 903*7c478bd9Sstevel@tonic-gate table->mapping.enumTime, 904*7c478bd9Sstevel@tonic-gate table->mapping.enumTime/ 905*7c478bd9Sstevel@tonic-gate (table->mapping.enumEntries != 0 ? 906*7c478bd9Sstevel@tonic-gate table->mapping.enumEntries : 1)); 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate table->mapping.enumTid = 0; 909*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&table->mapping.enumLock); 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate WRITEUNLOCKNR(table, stat3, "table wu db_mindex::entriesFromLDAPreal"); 912*7c478bd9Sstevel@tonic-gate WRITEUNLOCKNR(mindex, stat2, "db_mindex::entriesFromLDAPreal wu"); 913*7c478bd9Sstevel@tonic-gate WRITEUNLOCKNR(((db *)mindex->getDbPtr()), lstat, 914*7c478bd9Sstevel@tonic-gate "db db_mindex::entriesFromLDAPreal wu"); 915*7c478bd9Sstevel@tonic-gate unlockTransLog(myself, 1); 916*7c478bd9Sstevel@tonic-gate if (stat3 != 0) 917*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 918*7c478bd9Sstevel@tonic-gate "%s: Error %d unlocking db_table", myself, stat3); 919*7c478bd9Sstevel@tonic-gate if (stat2 != 0) 920*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 921*7c478bd9Sstevel@tonic-gate "%s: Error %d unlocking db_mindex", myself, stat2); 922*7c478bd9Sstevel@tonic-gate if (lstat != 0) 923*7c478bd9Sstevel@tonic-gate logmsg(MSG_NOTIMECHECK, LOG_WARNING, 924*7c478bd9Sstevel@tonic-gate "%s: Error %d unlocking db", myself, lstat); 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate return (stat); 927*7c478bd9Sstevel@tonic-gate } 928