xref: /titanic_53/usr/src/lib/libnisdb/db_mindex2.cc (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 (c) 2001 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  *	All Rights Reserved.
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 <stdio.h>
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #include <malloc.h>
32*7c478bd9Sstevel@tonic-gate #include <strings.h>
33*7c478bd9Sstevel@tonic-gate #include <string.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
36*7c478bd9Sstevel@tonic-gate #include <time.h>
37*7c478bd9Sstevel@tonic-gate #include "db_headers.h"
38*7c478bd9Sstevel@tonic-gate #include "db.h"
39*7c478bd9Sstevel@tonic-gate #include "db_mindex.h"
40*7c478bd9Sstevel@tonic-gate #include "db_pickle.h"
41*7c478bd9Sstevel@tonic-gate #include "nisdb_mt.h"
42*7c478bd9Sstevel@tonic-gate #include "nisdb_ldap.h"
43*7c478bd9Sstevel@tonic-gate #include "ldap_nisdbquery.h"
44*7c478bd9Sstevel@tonic-gate #include "ldap_map.h"
45*7c478bd9Sstevel@tonic-gate #include "ldap_ruleval.h"
46*7c478bd9Sstevel@tonic-gate #include "ldap_scheme.h"
47*7c478bd9Sstevel@tonic-gate #include "ldap_parse.h"
48*7c478bd9Sstevel@tonic-gate #include "nis_hashitem.h"
49*7c478bd9Sstevel@tonic-gate #include "nis_servlist.h"
50*7c478bd9Sstevel@tonic-gate #include "ldap_nisplus.h"
51*7c478bd9Sstevel@tonic-gate #include "nis_db.h"
52*7c478bd9Sstevel@tonic-gate #include "ldap_glob.h"
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /* Pass through configuration information to the table */
55*7c478bd9Sstevel@tonic-gate bool_t
56*7c478bd9Sstevel@tonic-gate db_mindex::configure(char *tablePath) {
57*7c478bd9Sstevel@tonic-gate 	if (tablePath == NULL)
58*7c478bd9Sstevel@tonic-gate 		return (FALSE);
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate 	if (objPath.ptr != 0)
61*7c478bd9Sstevel@tonic-gate 		free(objPath.ptr);
62*7c478bd9Sstevel@tonic-gate 	objPath.ptr = strdup(tablePath);
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate 	if (table != NULL) {
65*7c478bd9Sstevel@tonic-gate 		return (table->configure(tablePath));
66*7c478bd9Sstevel@tonic-gate 	} else {
67*7c478bd9Sstevel@tonic-gate 		/* Defer table config until we have a table instance */
68*7c478bd9Sstevel@tonic-gate 		return (objPath.ptr != NULL);
69*7c478bd9Sstevel@tonic-gate 	}
70*7c478bd9Sstevel@tonic-gate }
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate /*
73*7c478bd9Sstevel@tonic-gate  * The noWriteThrough flag is used to prevent modifies/updates to LDAP
74*7c478bd9Sstevel@tonic-gate  * while we're incorporating log data into the in-memory tables.
75*7c478bd9Sstevel@tonic-gate  */
76*7c478bd9Sstevel@tonic-gate void
77*7c478bd9Sstevel@tonic-gate db_mindex::setNoWriteThrough(void) {
78*7c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
79*7c478bd9Sstevel@tonic-gate 	noWriteThrough.flag++;
80*7c478bd9Sstevel@tonic-gate }
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate void
83*7c478bd9Sstevel@tonic-gate db_mindex::clearNoWriteThrough(void) {
84*7c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
85*7c478bd9Sstevel@tonic-gate 	if (noWriteThrough.flag > 0)
86*7c478bd9Sstevel@tonic-gate 		noWriteThrough.flag--;
87*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
88*7c478bd9Sstevel@tonic-gate 	else
89*7c478bd9Sstevel@tonic-gate 		abort();
90*7c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
91*7c478bd9Sstevel@tonic-gate }
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate /*
94*7c478bd9Sstevel@tonic-gate  * The noLDAPquery flag is used to prevent recursive LDAP queries when
95*7c478bd9Sstevel@tonic-gate  * satisfy_query() is re-entered as we add an entry from queryLDAP().
96*7c478bd9Sstevel@tonic-gate  */
97*7c478bd9Sstevel@tonic-gate void
98*7c478bd9Sstevel@tonic-gate db_mindex::setNoLDAPquery(void) {
99*7c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
100*7c478bd9Sstevel@tonic-gate 	noLDAPquery.flag++;
101*7c478bd9Sstevel@tonic-gate }
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate void
104*7c478bd9Sstevel@tonic-gate db_mindex::clearNoLDAPquery(void) {
105*7c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
106*7c478bd9Sstevel@tonic-gate 	if (noLDAPquery.flag > 0)
107*7c478bd9Sstevel@tonic-gate 		noLDAPquery.flag--;
108*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
109*7c478bd9Sstevel@tonic-gate 	else
110*7c478bd9Sstevel@tonic-gate 		abort();
111*7c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
112*7c478bd9Sstevel@tonic-gate }
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate /*
115*7c478bd9Sstevel@tonic-gate  * The initialLoad flag tells us if an add or remove is done as part of
116*7c478bd9Sstevel@tonic-gate  * the initial load of data, in which case we should use the initial TTLs.
117*7c478bd9Sstevel@tonic-gate  */
118*7c478bd9Sstevel@tonic-gate void
119*7c478bd9Sstevel@tonic-gate db_mindex::setInitialLoad(void) {
120*7c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
121*7c478bd9Sstevel@tonic-gate 	initialLoad.flag++;
122*7c478bd9Sstevel@tonic-gate }
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate void
125*7c478bd9Sstevel@tonic-gate db_mindex::clearInitialLoad(void) {
126*7c478bd9Sstevel@tonic-gate 	ASSERTWHELD(this->mindex);
127*7c478bd9Sstevel@tonic-gate 	if (initialLoad.flag > 0)
128*7c478bd9Sstevel@tonic-gate 		initialLoad.flag--;
129*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
130*7c478bd9Sstevel@tonic-gate 	else
131*7c478bd9Sstevel@tonic-gate 		abort();
132*7c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
133*7c478bd9Sstevel@tonic-gate }
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate void
136*7c478bd9Sstevel@tonic-gate db_mindex::setDbPtr(void *ptr) {
137*7c478bd9Sstevel@tonic-gate 	dbptr.ptr = ptr;
138*7c478bd9Sstevel@tonic-gate }
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate void *
141*7c478bd9Sstevel@tonic-gate db_mindex::getDbPtr(void) {
142*7c478bd9Sstevel@tonic-gate 	return (dbptr.ptr);
143*7c478bd9Sstevel@tonic-gate }
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate db_table *
146*7c478bd9Sstevel@tonic-gate db_mindex::getTable(void) {
147*7c478bd9Sstevel@tonic-gate 	return (table);
148*7c478bd9Sstevel@tonic-gate }
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate extern void	db_free_result(db_result *);
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate zotypes
153*7c478bd9Sstevel@tonic-gate updateMappingObj(__nis_table_mapping_t *t, char **objNameP,
154*7c478bd9Sstevel@tonic-gate 		bool_t *isMasterP) {
155*7c478bd9Sstevel@tonic-gate 	zotypes	type = NIS_BOGUS_OBJ;
156*7c478bd9Sstevel@tonic-gate 	char	*objName = 0;
157*7c478bd9Sstevel@tonic-gate 	char	*myself = "updateMappingObj";
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	if (t != 0)
160*7c478bd9Sstevel@tonic-gate 		objName = t->objName;
161*7c478bd9Sstevel@tonic-gate 	else if (objNameP != 0)
162*7c478bd9Sstevel@tonic-gate 		objName = *objNameP;
163*7c478bd9Sstevel@tonic-gate 	else
164*7c478bd9Sstevel@tonic-gate 		return (NIS_BOGUS_OBJ);
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	if (objName != 0) {
167*7c478bd9Sstevel@tonic-gate 		db_status	stat;
168*7c478bd9Sstevel@tonic-gate 		int		lstat = LDAP_SUCCESS;
169*7c478bd9Sstevel@tonic-gate 		nis_object	*o = dbFindObject(objName, &stat);
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 		/* If not found in the local DB, try LDAP */
172*7c478bd9Sstevel@tonic-gate 		if (o == 0) {
173*7c478bd9Sstevel@tonic-gate 			if (stat != DB_NOTFOUND) {
174*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_INFO,
175*7c478bd9Sstevel@tonic-gate 					"%s: DB err %d for \"%s\"",
176*7c478bd9Sstevel@tonic-gate 					myself, stat, NIL(objName));
177*7c478bd9Sstevel@tonic-gate 			}
178*7c478bd9Sstevel@tonic-gate 			o = ldapFindObj(t, objName, &lstat);
179*7c478bd9Sstevel@tonic-gate 			/* If found, refresh/create the local copy */
180*7c478bd9Sstevel@tonic-gate 			if (o != 0) {
181*7c478bd9Sstevel@tonic-gate 				db_status	rstat;
182*7c478bd9Sstevel@tonic-gate 				rstat = dbRefreshObj(objName, o);
183*7c478bd9Sstevel@tonic-gate 				if (rstat != DB_SUCCESS)
184*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
185*7c478bd9Sstevel@tonic-gate 					"%s: DB error %d refreshing \"%s\"",
186*7c478bd9Sstevel@tonic-gate 					myself, rstat, NIL(objName));
187*7c478bd9Sstevel@tonic-gate 			}
188*7c478bd9Sstevel@tonic-gate 		}
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 		if (o != 0) {
191*7c478bd9Sstevel@tonic-gate 			type = o->zo_data.zo_type;
192*7c478bd9Sstevel@tonic-gate 			if (objNameP != 0) {
193*7c478bd9Sstevel@tonic-gate 				*objNameP = sdup(myself, T, objName);
194*7c478bd9Sstevel@tonic-gate 				if (*objNameP == 0) {
195*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
196*7c478bd9Sstevel@tonic-gate 				"%s: Unable to copy object name (\"%s\")",
197*7c478bd9Sstevel@tonic-gate 						myself, NIL(objName));
198*7c478bd9Sstevel@tonic-gate 				}
199*7c478bd9Sstevel@tonic-gate 			}
200*7c478bd9Sstevel@tonic-gate 			if (t != 0) {
201*7c478bd9Sstevel@tonic-gate 				if (!setMappingObjTypeEtc(t, o))
202*7c478bd9Sstevel@tonic-gate 					nis_destroy_object(o);
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 				if (isMasterP != 0)
205*7c478bd9Sstevel@tonic-gate 					*isMasterP = t->isMaster;
206*7c478bd9Sstevel@tonic-gate 			} else {
207*7c478bd9Sstevel@tonic-gate 				if (isMasterP != 0)
208*7c478bd9Sstevel@tonic-gate 					*isMasterP = isMaster(o);
209*7c478bd9Sstevel@tonic-gate 				nis_destroy_object(o);
210*7c478bd9Sstevel@tonic-gate 			}
211*7c478bd9Sstevel@tonic-gate 		} else if (lstat != LDAP_SUCCESS) {
212*7c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_INFO,
213*7c478bd9Sstevel@tonic-gate 				"%s: LDAP err %d for \"%s\"",
214*7c478bd9Sstevel@tonic-gate 				myself, lstat, NIL(objName));
215*7c478bd9Sstevel@tonic-gate 		}
216*7c478bd9Sstevel@tonic-gate 	}
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate 	return (type);
219*7c478bd9Sstevel@tonic-gate }
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate static __nis_table_mapping_t *
222*7c478bd9Sstevel@tonic-gate mappingFromObj(nis_object *obj, int *statP) {
223*7c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
224*7c478bd9Sstevel@tonic-gate 	__nis_buffer_t		b = {0, 0};
225*7c478bd9Sstevel@tonic-gate 	char			*objPath;
226*7c478bd9Sstevel@tonic-gate 	char			*myself = "mappingFromObj";
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 	if (obj == 0 || obj->zo_data.zo_type == NIS_ENTRY_OBJ)
229*7c478bd9Sstevel@tonic-gate 		return (0);
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	/*
232*7c478bd9Sstevel@tonic-gate 	 * Convert full object name to the db table path used as
233*7c478bd9Sstevel@tonic-gate 	 * key for the mapping hash list.
234*7c478bd9Sstevel@tonic-gate 	 */
235*7c478bd9Sstevel@tonic-gate 	bp2buf(myself, &b, "%s.%s",
236*7c478bd9Sstevel@tonic-gate 		NIL(obj->zo_name), NIL(obj->zo_domain));
237*7c478bd9Sstevel@tonic-gate 	objPath = internalTableName(b.buf);
238*7c478bd9Sstevel@tonic-gate 	sfree(b.buf);
239*7c478bd9Sstevel@tonic-gate 	if (slen(objPath) <= 0) {
240*7c478bd9Sstevel@tonic-gate 		if (statP != 0)
241*7c478bd9Sstevel@tonic-gate 			*statP = LDAP_OPERATIONS_ERROR;
242*7c478bd9Sstevel@tonic-gate 		sfree(objPath);
243*7c478bd9Sstevel@tonic-gate 		return (0);
244*7c478bd9Sstevel@tonic-gate 	}
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate 	t = (__nis_table_mapping_t *)__nis_find_item_mt(objPath,
247*7c478bd9Sstevel@tonic-gate 						&ldapMappingList, 0, 0);
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate 	sfree(objPath);
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	return (t);
252*7c478bd9Sstevel@tonic-gate }
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate static __nis_table_mapping_t *
255*7c478bd9Sstevel@tonic-gate selectMapping(db_table *table, nis_object *obj, db_query *qin,
256*7c478bd9Sstevel@tonic-gate 		bool_t wantWrite, bool_t *asObjP, int *statP) {
257*7c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
258*7c478bd9Sstevel@tonic-gate 	__nis_buffer_t		b = {0, 0};
259*7c478bd9Sstevel@tonic-gate 	bool_t			doLDAP, asObj;
260*7c478bd9Sstevel@tonic-gate 	int			stat = LDAP_SUCCESS;
261*7c478bd9Sstevel@tonic-gate 	char			*objPath = 0, buf[MAXPATHLEN+NIS_MAXNAMELEN+1];
262*7c478bd9Sstevel@tonic-gate 	char			*myself = "db_mindex::selectMapping";
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 	/*
265*7c478bd9Sstevel@tonic-gate 	 * If 'table' is NULL, we try to find a mapping for 'obj'.
266*7c478bd9Sstevel@tonic-gate 	 * We expect this to happen when our caller wants to write
267*7c478bd9Sstevel@tonic-gate 	 * the object from a directory entry to LDAP.
268*7c478bd9Sstevel@tonic-gate 	 */
269*7c478bd9Sstevel@tonic-gate 	if (table == 0) {
270*7c478bd9Sstevel@tonic-gate 		if (asObjP != 0)
271*7c478bd9Sstevel@tonic-gate 			*asObjP = TRUE;
272*7c478bd9Sstevel@tonic-gate 		if (statP != 0)
273*7c478bd9Sstevel@tonic-gate 			*statP = LDAP_SUCCESS;
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 		t = mappingFromObj(obj, statP);
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 		if (t == 0)
278*7c478bd9Sstevel@tonic-gate 			return (0);
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 		/*
281*7c478bd9Sstevel@tonic-gate 		 * Should the object type in the mapping be NIS_BOGUS_OBJ,
282*7c478bd9Sstevel@tonic-gate 		 * we need to determine what kind of object this is.
283*7c478bd9Sstevel@tonic-gate 		 */
284*7c478bd9Sstevel@tonic-gate 		if (t->objType == NIS_BOGUS_OBJ) {
285*7c478bd9Sstevel@tonic-gate 			t->objType = updateMappingObj(t, 0, 0);
286*7c478bd9Sstevel@tonic-gate 			if (t->objType == NIS_BOGUS_OBJ) {
287*7c478bd9Sstevel@tonic-gate 				if (statP != 0)
288*7c478bd9Sstevel@tonic-gate 					*statP = LDAP_OPERATIONS_ERROR;
289*7c478bd9Sstevel@tonic-gate 				return (0);
290*7c478bd9Sstevel@tonic-gate 			}
291*7c478bd9Sstevel@tonic-gate 		}
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 		/*
294*7c478bd9Sstevel@tonic-gate 		 * If caller wants a mapping suitable for writing,
295*7c478bd9Sstevel@tonic-gate 		 * check that we're the master for this object.
296*7c478bd9Sstevel@tonic-gate 		 */
297*7c478bd9Sstevel@tonic-gate 		if (wantWrite && !t->isMaster)
298*7c478bd9Sstevel@tonic-gate 			return (0);
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 		return (t);
301*7c478bd9Sstevel@tonic-gate 	}
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 	/*
304*7c478bd9Sstevel@tonic-gate 	 * If the object type for the mapping is NIS_BOGUS_OBJ, then
305*7c478bd9Sstevel@tonic-gate 	 * we haven't yet been able to determine what kind of object this
306*7c478bd9Sstevel@tonic-gate 	 * is. Try to fix that now.
307*7c478bd9Sstevel@tonic-gate 	 */
308*7c478bd9Sstevel@tonic-gate 	if (table->mapping.objType == NIS_BOGUS_OBJ) {
309*7c478bd9Sstevel@tonic-gate 		table->mapping.objType = updateMappingObj(table->mapping.tm,
310*7c478bd9Sstevel@tonic-gate 						&table->mapping.objName,
311*7c478bd9Sstevel@tonic-gate 						&table->mapping.isMaster);
312*7c478bd9Sstevel@tonic-gate 		table->mapping.expireType = table->mapping.objType;
313*7c478bd9Sstevel@tonic-gate 	}
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 	/*
316*7c478bd9Sstevel@tonic-gate 	 * Depending on the object type (table->mapping.objType):
317*7c478bd9Sstevel@tonic-gate 	 *
318*7c478bd9Sstevel@tonic-gate 	 *	table		Use table->mapping.tm to query LDAP
319*7c478bd9Sstevel@tonic-gate 	 *			for entries per 'qin'.
320*7c478bd9Sstevel@tonic-gate 	 *
321*7c478bd9Sstevel@tonic-gate 	 *	directory	Use 'qin' and table->mapping.objName
322*7c478bd9Sstevel@tonic-gate 	 *			to retrieve a mapping entry, and then
323*7c478bd9Sstevel@tonic-gate 	 *			query LDAP for the corresponding object.
324*7c478bd9Sstevel@tonic-gate 	 *			'qin' == NULL means reading/writing the
325*7c478bd9Sstevel@tonic-gate 	 *			entire directory object, plus the names
326*7c478bd9Sstevel@tonic-gate 	 *			of the directory entries.
327*7c478bd9Sstevel@tonic-gate 	 *
328*7c478bd9Sstevel@tonic-gate 	 *	bogus		Not mapping this object. However, we may
329*7c478bd9Sstevel@tonic-gate 	 *			still be mapping the object 'obj'.
330*7c478bd9Sstevel@tonic-gate 	 *
331*7c478bd9Sstevel@tonic-gate 	 *	other		Shouldn't happen; illegal.
332*7c478bd9Sstevel@tonic-gate 	 */
333*7c478bd9Sstevel@tonic-gate 	switch (table->mapping.objType) {
334*7c478bd9Sstevel@tonic-gate 	case NIS_TABLE_OBJ:
335*7c478bd9Sstevel@tonic-gate 		t = table->mapping.tm;
336*7c478bd9Sstevel@tonic-gate 		if (wantWrite)
337*7c478bd9Sstevel@tonic-gate 			doLDAP = table->mapping.isMaster &&
338*7c478bd9Sstevel@tonic-gate 					table->mapping.toLDAP;
339*7c478bd9Sstevel@tonic-gate 		else
340*7c478bd9Sstevel@tonic-gate 			doLDAP = table->mapping.fromLDAP;
341*7c478bd9Sstevel@tonic-gate 		asObj = FALSE;
342*7c478bd9Sstevel@tonic-gate 		break;
343*7c478bd9Sstevel@tonic-gate 	case NIS_DIRECTORY_OBJ: {
344*7c478bd9Sstevel@tonic-gate 		char		*sub = 0;
345*7c478bd9Sstevel@tonic-gate 		int		nqc, len = 0;
346*7c478bd9Sstevel@tonic-gate 		db_qcomp	*qc;
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 		t = 0;
349*7c478bd9Sstevel@tonic-gate 		doLDAP = FALSE;
350*7c478bd9Sstevel@tonic-gate 		asObj = TRUE;
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 		/*
353*7c478bd9Sstevel@tonic-gate 		 * We expect the query to have one component, containing
354*7c478bd9Sstevel@tonic-gate 		 * the directory entry name. If there's no query, we want
355*7c478bd9Sstevel@tonic-gate 		 * an enumeration of the entries in the directory. They're
356*7c478bd9Sstevel@tonic-gate 		 * stored with the XDR:ed directory object in LDAP, so
357*7c478bd9Sstevel@tonic-gate 		 * asObj should be TRUE.
358*7c478bd9Sstevel@tonic-gate 		 */
359*7c478bd9Sstevel@tonic-gate 		if (qin == 0) {
360*7c478bd9Sstevel@tonic-gate 			t = table->mapping.tm;
361*7c478bd9Sstevel@tonic-gate 			if (wantWrite)
362*7c478bd9Sstevel@tonic-gate 				doLDAP = table->mapping.isMaster &&
363*7c478bd9Sstevel@tonic-gate 					table->mapping.toLDAP;
364*7c478bd9Sstevel@tonic-gate 			else
365*7c478bd9Sstevel@tonic-gate 				doLDAP = table->mapping.fromLDAP;
366*7c478bd9Sstevel@tonic-gate 			asObj = TRUE;
367*7c478bd9Sstevel@tonic-gate 			break;
368*7c478bd9Sstevel@tonic-gate 		}
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 		nqc = qin->size();
371*7c478bd9Sstevel@tonic-gate 		if (nqc != 1 || (qc = qin->queryloc()) == 0 ||
372*7c478bd9Sstevel@tonic-gate 				qc[0].index_value == 0) {
373*7c478bd9Sstevel@tonic-gate 			stat = LDAP_PARAM_ERROR;
374*7c478bd9Sstevel@tonic-gate 			break;
375*7c478bd9Sstevel@tonic-gate 		}
376*7c478bd9Sstevel@tonic-gate 		qc[0].index_value->get_value(&sub, &len);
377*7c478bd9Sstevel@tonic-gate 		if (sub == 0 || len <= 0) {
378*7c478bd9Sstevel@tonic-gate 			stat = LDAP_PARAM_ERROR;
379*7c478bd9Sstevel@tonic-gate 			break;
380*7c478bd9Sstevel@tonic-gate 		}
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 		/* Append directory name to dir entry name */
383*7c478bd9Sstevel@tonic-gate 		sbc2buf(myself, sub, len, &b);
384*7c478bd9Sstevel@tonic-gate 		bp2buf(myself, &b, ".%s", table->mapping.objName);
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 		/* Convert to the DB internal name */
387*7c478bd9Sstevel@tonic-gate 		objPath = internal_table_name(b.buf, buf);
388*7c478bd9Sstevel@tonic-gate 		sfree(b.buf);
389*7c478bd9Sstevel@tonic-gate 		if (slen(objPath) <= 0) {
390*7c478bd9Sstevel@tonic-gate 			stat = LDAP_OPERATIONS_ERROR;
391*7c478bd9Sstevel@tonic-gate 			break;
392*7c478bd9Sstevel@tonic-gate 		}
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 		/* Look for the corresponding table mapping */
395*7c478bd9Sstevel@tonic-gate 		t = (__nis_table_mapping_t *)__nis_find_item_mt(
396*7c478bd9Sstevel@tonic-gate 					objPath, &ldapMappingList, 0, 0);
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate 		if (t == 0)
399*7c478bd9Sstevel@tonic-gate 			break;
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate 		/* Update object mapping information */
402*7c478bd9Sstevel@tonic-gate 		if (t->objType == NIS_BOGUS_OBJ)
403*7c478bd9Sstevel@tonic-gate 			(void) updateMappingObj(t, 0, 0);
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 		/*
406*7c478bd9Sstevel@tonic-gate 		 * Should check the objectDN's in 't', but leave that to
407*7c478bd9Sstevel@tonic-gate 		 * underlying functions.
408*7c478bd9Sstevel@tonic-gate 		 */
409*7c478bd9Sstevel@tonic-gate 		if (wantWrite)
410*7c478bd9Sstevel@tonic-gate 			doLDAP = t->isMaster;
411*7c478bd9Sstevel@tonic-gate 		else
412*7c478bd9Sstevel@tonic-gate 			doLDAP = TRUE;
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 		break;
415*7c478bd9Sstevel@tonic-gate 	}
416*7c478bd9Sstevel@tonic-gate 	case NIS_BOGUS_OBJ:
417*7c478bd9Sstevel@tonic-gate 		t = mappingFromObj(obj, statP);
418*7c478bd9Sstevel@tonic-gate 		doLDAP = TRUE;
419*7c478bd9Sstevel@tonic-gate 		asObj = TRUE;
420*7c478bd9Sstevel@tonic-gate 		break;
421*7c478bd9Sstevel@tonic-gate 	default:
422*7c478bd9Sstevel@tonic-gate 		t = 0;
423*7c478bd9Sstevel@tonic-gate 		doLDAP = FALSE;
424*7c478bd9Sstevel@tonic-gate 		asObj = TRUE;
425*7c478bd9Sstevel@tonic-gate 		break;
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate 	if (!doLDAP)
429*7c478bd9Sstevel@tonic-gate 		t = 0;
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	if (asObjP != 0)
432*7c478bd9Sstevel@tonic-gate 		*asObjP = asObj;
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 	if (statP != 0)
435*7c478bd9Sstevel@tonic-gate 		*statP = stat;
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 	return (t);
438*7c478bd9Sstevel@tonic-gate }
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate /*
441*7c478bd9Sstevel@tonic-gate  * Replace or remove the table entry identified by 'e'. 'tableName' is
442*7c478bd9Sstevel@tonic-gate  * the name of the table (which could be a directory) in which the entry
443*7c478bd9Sstevel@tonic-gate  * resides. 'obj' is an un-XDR:ed copy of the object in 'e', optionally
444*7c478bd9Sstevel@tonic-gate  * supplied to save re-doing unpacking of the entry object. 'tobj' is
445*7c478bd9Sstevel@tonic-gate  * a pointer to the table object; needed for table entries, but not
446*7c478bd9Sstevel@tonic-gate  * for directory entries.
447*7c478bd9Sstevel@tonic-gate  *
448*7c478bd9Sstevel@tonic-gate  * 'ttime' contains the current time, to be supplied for the trans log
449*7c478bd9Sstevel@tonic-gate  * entry.
450*7c478bd9Sstevel@tonic-gate  *
451*7c478bd9Sstevel@tonic-gate  * Returns LDAP_SUCCESS when entry successfully added/modified/deleted,
452*7c478bd9Sstevel@tonic-gate  * LDAP_COMPARE_TRUE if an entry to be added/modified was the same as
453*7c478bd9Sstevel@tonic-gate  * an already existing one, and a suitable error otherwise.
454*7c478bd9Sstevel@tonic-gate  */
455*7c478bd9Sstevel@tonic-gate int
456*7c478bd9Sstevel@tonic-gate db_mindex::updateTableEntry(entry_object *e, int replace, char *tableName,
457*7c478bd9Sstevel@tonic-gate 		nis_object *obj, nis_object *tobj, uint32_t ttime,
458*7c478bd9Sstevel@tonic-gate 		int *xid) {
459*7c478bd9Sstevel@tonic-gate 	int			stat, freeObj = 0;
460*7c478bd9Sstevel@tonic-gate 	db_index_entry		*dbie;
461*7c478bd9Sstevel@tonic-gate 	long			count = 0;
462*7c478bd9Sstevel@tonic-gate 	bool_t			valid = TRUE;
463*7c478bd9Sstevel@tonic-gate 	db_result		*dbres;
464*7c478bd9Sstevel@tonic-gate 	db_query		*qi;
465*7c478bd9Sstevel@tonic-gate 	nis_object		*oldObj = 0;
466*7c478bd9Sstevel@tonic-gate 	char			*myself = "db_mindex::updateTableEntry";
467*7c478bd9Sstevel@tonic-gate 
468*7c478bd9Sstevel@tonic-gate 	if (table == 0 || e == 0)
469*7c478bd9Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 	qi = extract_index_values_from_object(e);
472*7c478bd9Sstevel@tonic-gate 	if (qi == 0) {
473*7c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOMEM, LOG_ERR,
474*7c478bd9Sstevel@tonic-gate 				"%s: Out of memory for query index",
475*7c478bd9Sstevel@tonic-gate 				myself);
476*7c478bd9Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
477*7c478bd9Sstevel@tonic-gate 	}
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 	dbie = satisfy_query(qi, &count, &valid, FALSE);
480*7c478bd9Sstevel@tonic-gate 	if (dbie != 0 && (count != 1 || !valid)) {
481*7c478bd9Sstevel@tonic-gate 		logmsg(MSG_NOTIMECHECK, LOG_INFO,
482*7c478bd9Sstevel@tonic-gate 			"%s: count=%d, valid=%s",
483*7c478bd9Sstevel@tonic-gate 			myself, count, valid ? "TRUE" : "FALSE");
484*7c478bd9Sstevel@tonic-gate 		delete qi;
485*7c478bd9Sstevel@tonic-gate 		return (LDAP_OPERATIONS_ERROR);
486*7c478bd9Sstevel@tonic-gate 	}
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 	/*
489*7c478bd9Sstevel@tonic-gate 	 * Need a copy of the old object in order to log a removal
490*7c478bd9Sstevel@tonic-gate 	 * (this is true even if we're modifying an existing entry).
491*7c478bd9Sstevel@tonic-gate 	 */
492*7c478bd9Sstevel@tonic-gate 	if (dbie != 0) {
493*7c478bd9Sstevel@tonic-gate 		oldObj = unmakePseudoEntryObj(
494*7c478bd9Sstevel@tonic-gate 				table->get_entry(dbie->getlocation()), tobj);
495*7c478bd9Sstevel@tonic-gate 		if (oldObj == 0) {
496*7c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
497*7c478bd9Sstevel@tonic-gate 	"%s: Error getting object from old pseudo-entry for \"%s\" in \"%s\"",
498*7c478bd9Sstevel@tonic-gate 					myself, NIL(obj->zo_name),
499*7c478bd9Sstevel@tonic-gate 					NIL(tableName));
500*7c478bd9Sstevel@tonic-gate 			delete qi;
501*7c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
502*7c478bd9Sstevel@tonic-gate 		}
503*7c478bd9Sstevel@tonic-gate 	}
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	if (replace) {
506*7c478bd9Sstevel@tonic-gate 		/* Need the object from the entry */
507*7c478bd9Sstevel@tonic-gate 		if (dbie != 0 && obj == 0) {
508*7c478bd9Sstevel@tonic-gate 			obj = unmakePseudoEntryObj(e, tobj);
509*7c478bd9Sstevel@tonic-gate 			if (obj == 0) {
510*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
511*7c478bd9Sstevel@tonic-gate 	"%s: Error getting object from pseudo-entry for \"%s\" in \"%s\"",
512*7c478bd9Sstevel@tonic-gate 					myself, NIL(obj->zo_name),
513*7c478bd9Sstevel@tonic-gate 					NIL(tableName));
514*7c478bd9Sstevel@tonic-gate 				delete qi;
515*7c478bd9Sstevel@tonic-gate 				nis_destroy_object(oldObj);
516*7c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
517*7c478bd9Sstevel@tonic-gate 			}
518*7c478bd9Sstevel@tonic-gate 			freeObj = 1;
519*7c478bd9Sstevel@tonic-gate 		}
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate 		/* Is the new object a dup of the old ? */
522*7c478bd9Sstevel@tonic-gate 		if (dbie != 0 && sameNisPlusObj(oldObj, obj)) {
523*7c478bd9Sstevel@tonic-gate 			/* Yes, it's a dup, so just update the timestamp */
524*7c478bd9Sstevel@tonic-gate 			table->touchEntry(dbie->getlocation());
525*7c478bd9Sstevel@tonic-gate 			delete qi;
526*7c478bd9Sstevel@tonic-gate 			if (freeObj)
527*7c478bd9Sstevel@tonic-gate 				nis_destroy_object(obj);
528*7c478bd9Sstevel@tonic-gate 			nis_destroy_object(oldObj);
529*7c478bd9Sstevel@tonic-gate 			return (LDAP_COMPARE_TRUE);
530*7c478bd9Sstevel@tonic-gate 		} else {
531*7c478bd9Sstevel@tonic-gate 			/*
532*7c478bd9Sstevel@tonic-gate 			 * Not a dup, so go ahead and add it. Provided
533*7c478bd9Sstevel@tonic-gate 			 * that 'qi' isn't NULL (which we've already
534*7c478bd9Sstevel@tonic-gate 			 * checked), DB_ADD(_NOSYNC) does the right
535*7c478bd9Sstevel@tonic-gate 			 * thing even if matching entries already
536*7c478bd9Sstevel@tonic-gate 			 * exist.
537*7c478bd9Sstevel@tonic-gate 			 */
538*7c478bd9Sstevel@tonic-gate 			dbres = ((db *)dbptr.ptr)->log_action(DB_ADD_NOSYNC,
539*7c478bd9Sstevel@tonic-gate 								qi, e);
540*7c478bd9Sstevel@tonic-gate 			if (dbres == 0)
541*7c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
542*7c478bd9Sstevel@tonic-gate 			else if (dbres->status == DB_SUCCESS)
543*7c478bd9Sstevel@tonic-gate 				stat = LDAP_SUCCESS;
544*7c478bd9Sstevel@tonic-gate 			else
545*7c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
546*7c478bd9Sstevel@tonic-gate 			db_free_result(dbres);
547*7c478bd9Sstevel@tonic-gate 		}
548*7c478bd9Sstevel@tonic-gate 	} else {	/* Removing */
549*7c478bd9Sstevel@tonic-gate 		/* If the object doesn't exist, we're done */
550*7c478bd9Sstevel@tonic-gate 		if (dbie == 0) {
551*7c478bd9Sstevel@tonic-gate 			delete qi;
552*7c478bd9Sstevel@tonic-gate 			return (LDAP_SUCCESS);
553*7c478bd9Sstevel@tonic-gate 		}
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 		dbres = ((db *)dbptr.ptr)->log_action(DB_REMOVE_NOSYNC, qi, 0);
556*7c478bd9Sstevel@tonic-gate 		if (dbres == 0)
557*7c478bd9Sstevel@tonic-gate 			stat = LDAP_OPERATIONS_ERROR;
558*7c478bd9Sstevel@tonic-gate 		else if (dbres->status == DB_SUCCESS)
559*7c478bd9Sstevel@tonic-gate 			stat = LDAP_SUCCESS;
560*7c478bd9Sstevel@tonic-gate 		else
561*7c478bd9Sstevel@tonic-gate 			stat = LDAP_OPERATIONS_ERROR;
562*7c478bd9Sstevel@tonic-gate 		db_free_result(dbres);
563*7c478bd9Sstevel@tonic-gate 	}
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 	/* Log the operation */
566*7c478bd9Sstevel@tonic-gate 	if (stat == LDAP_SUCCESS) {
567*7c478bd9Sstevel@tonic-gate 		int		ret, numAttrs;
568*7c478bd9Sstevel@tonic-gate 		nis_attr	*attr, attrbuf[NIS_MAXCOLUMNS];
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 		/* If we haven't begun the transaction yet, do so now */
571*7c478bd9Sstevel@tonic-gate 		if (*xid == 0) {
572*7c478bd9Sstevel@tonic-gate 			*xid = beginTransaction();
573*7c478bd9Sstevel@tonic-gate 			if (*xid == 0) {
574*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
575*7c478bd9Sstevel@tonic-gate 				"%s: Error starting transaction for \"%s\"",
576*7c478bd9Sstevel@tonic-gate 					myself, NIL(tableName));
577*7c478bd9Sstevel@tonic-gate 				delete qi;
578*7c478bd9Sstevel@tonic-gate 				if (oldObj != 0)
579*7c478bd9Sstevel@tonic-gate 					nis_destroy_object(oldObj);
580*7c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
581*7c478bd9Sstevel@tonic-gate 			}
582*7c478bd9Sstevel@tonic-gate 		}
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate 		if (replace && obj == 0) {
585*7c478bd9Sstevel@tonic-gate 			obj = unmakePseudoEntryObj(e, tobj);
586*7c478bd9Sstevel@tonic-gate 			if (obj == 0) {
587*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
588*7c478bd9Sstevel@tonic-gate 	"%s: Error getting object from pseudo-entry for \"%s\" in \"%s\"",
589*7c478bd9Sstevel@tonic-gate 					myself, NIL(obj->zo_name),
590*7c478bd9Sstevel@tonic-gate 					NIL(tableName));
591*7c478bd9Sstevel@tonic-gate 				delete qi;
592*7c478bd9Sstevel@tonic-gate 				if (oldObj != 0)
593*7c478bd9Sstevel@tonic-gate 					nis_destroy_object(oldObj);
594*7c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
595*7c478bd9Sstevel@tonic-gate 			}
596*7c478bd9Sstevel@tonic-gate 			freeObj = 1;
597*7c478bd9Sstevel@tonic-gate 		}
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate 		/*
600*7c478bd9Sstevel@tonic-gate 		 * The log stores nis_attr information, so we need to
601*7c478bd9Sstevel@tonic-gate 		 * convert the scheme-query to a nis_attr array.
602*7c478bd9Sstevel@tonic-gate 		 */
603*7c478bd9Sstevel@tonic-gate 		attr = schemeQuery2nisAttr(qi, attrbuf, scheme,
604*7c478bd9Sstevel@tonic-gate 				table->mapping.tm, &numAttrs);
605*7c478bd9Sstevel@tonic-gate 		if (attr == 0) {
606*7c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
607*7c478bd9Sstevel@tonic-gate 	"%s: Error converting index query to nis_attr for \"%s\" in \"%s\"",
608*7c478bd9Sstevel@tonic-gate 				myself, NIL(obj->zo_name), NIL(tableName));
609*7c478bd9Sstevel@tonic-gate 			if (freeObj)
610*7c478bd9Sstevel@tonic-gate 				nis_destroy_object(obj);
611*7c478bd9Sstevel@tonic-gate 			if (oldObj != 0)
612*7c478bd9Sstevel@tonic-gate 				nis_destroy_object(oldObj);
613*7c478bd9Sstevel@tonic-gate 			delete qi;
614*7c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
615*7c478bd9Sstevel@tonic-gate 		}
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 		if (replace) {
618*7c478bd9Sstevel@tonic-gate 			/*
619*7c478bd9Sstevel@tonic-gate 			 * While the DB can handle a modify (replace)
620*7c478bd9Sstevel@tonic-gate 			 * operation, the trans log stores this as a
621*7c478bd9Sstevel@tonic-gate 			 * remove followed by an add (which allows
622*7c478bd9Sstevel@tonic-gate 			 * backing out the change by removing the new
623*7c478bd9Sstevel@tonic-gate 			 * object incarnation, and adding the old one).
624*7c478bd9Sstevel@tonic-gate 			 */
625*7c478bd9Sstevel@tonic-gate 			if (oldObj != 0)
626*7c478bd9Sstevel@tonic-gate 				ret = addUpdate(REM_IBASE, tableName,
627*7c478bd9Sstevel@tonic-gate 					numAttrs, attr, oldObj, 0, ttime);
628*7c478bd9Sstevel@tonic-gate 			else
629*7c478bd9Sstevel@tonic-gate 				ret = 0;
630*7c478bd9Sstevel@tonic-gate 			if (ret == 0)
631*7c478bd9Sstevel@tonic-gate 				ret = addUpdate(ADD_IBASE, tableName,
632*7c478bd9Sstevel@tonic-gate 					numAttrs, attr, obj, 0, ttime);
633*7c478bd9Sstevel@tonic-gate 		} else {	/* Removal */
634*7c478bd9Sstevel@tonic-gate 			ret = addUpdate(REM_IBASE, tableName, numAttrs, attr,
635*7c478bd9Sstevel@tonic-gate 					oldObj, 0, ttime);
636*7c478bd9Sstevel@tonic-gate 		}
637*7c478bd9Sstevel@tonic-gate 		if (ret != 0) {
638*7c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
639*7c478bd9Sstevel@tonic-gate 		"%s: Error adding trans log entry for \"%s\" in \"%s\"",
640*7c478bd9Sstevel@tonic-gate 				myself, NIL(obj->zo_name), NIL(tableName));
641*7c478bd9Sstevel@tonic-gate 			stat = LDAP_OPERATIONS_ERROR;
642*7c478bd9Sstevel@tonic-gate 		}
643*7c478bd9Sstevel@tonic-gate 	}
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate 	delete qi;
646*7c478bd9Sstevel@tonic-gate 
647*7c478bd9Sstevel@tonic-gate 	if (oldObj != 0)
648*7c478bd9Sstevel@tonic-gate 		nis_destroy_object(oldObj);
649*7c478bd9Sstevel@tonic-gate 	if (freeObj)
650*7c478bd9Sstevel@tonic-gate 		nis_destroy_object(obj);
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	return (stat);
653*7c478bd9Sstevel@tonic-gate }
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate bool_t
656*7c478bd9Sstevel@tonic-gate db_mindex::touchEntry(entry_object *e) {
657*7c478bd9Sstevel@tonic-gate 	db_query		*qi;
658*7c478bd9Sstevel@tonic-gate 	bool_t			ret;
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate 	if (table == 0 || e == 0)
661*7c478bd9Sstevel@tonic-gate 		return (FALSE);
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 	qi = extract_index_values_from_object(e);
664*7c478bd9Sstevel@tonic-gate 	if (qi == 0)
665*7c478bd9Sstevel@tonic-gate 		return (FALSE);
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	ret = touchEntry(qi);
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate 	delete qi;
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	return (ret);
672*7c478bd9Sstevel@tonic-gate }
673*7c478bd9Sstevel@tonic-gate 
674*7c478bd9Sstevel@tonic-gate bool_t
675*7c478bd9Sstevel@tonic-gate db_mindex::touchEntry(db_query *q) {
676*7c478bd9Sstevel@tonic-gate 	db_index_entry		*dbie;
677*7c478bd9Sstevel@tonic-gate 	long			count;
678*7c478bd9Sstevel@tonic-gate 	bool_t			valid;
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate 	dbie = satisfy_query(q, &count, &valid, FALSE);
681*7c478bd9Sstevel@tonic-gate 	if (dbie != 0 && count == 1 && valid)
682*7c478bd9Sstevel@tonic-gate 		table->touchEntry(dbie->getlocation());
683*7c478bd9Sstevel@tonic-gate 	else
684*7c478bd9Sstevel@tonic-gate 		return (FALSE);
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 	return (TRUE);
687*7c478bd9Sstevel@tonic-gate }
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate /*
690*7c478bd9Sstevel@tonic-gate  * Compose an object name from column zero of 'e' and 't->objName',
691*7c478bd9Sstevel@tonic-gate  * and return the mapping for that object, if any. Also set '*name'
692*7c478bd9Sstevel@tonic-gate  * to point to the dir entry name in 'e'. Note that this is a pointer
693*7c478bd9Sstevel@tonic-gate  * to existing data, and shouldn't be freed other than as part of
694*7c478bd9Sstevel@tonic-gate  * freeing 'e'.
695*7c478bd9Sstevel@tonic-gate  */
696*7c478bd9Sstevel@tonic-gate static __nis_table_mapping_t *
697*7c478bd9Sstevel@tonic-gate findDirEntryMapping(__nis_table_mapping_t *t, entry_object *e, char **name) {
698*7c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*x;
699*7c478bd9Sstevel@tonic-gate 	char			*entryName;
700*7c478bd9Sstevel@tonic-gate 	char			*myself = "findDirEntryMapping";
701*7c478bd9Sstevel@tonic-gate 	__nis_buffer_t		b = {0, 0};
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate 	if (e == 0 || e->en_cols.en_cols_len != 2 ||
704*7c478bd9Sstevel@tonic-gate 			e->en_cols.en_cols_val == 0)
705*7c478bd9Sstevel@tonic-gate 		return (0);
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate 	entryName = e->en_cols.en_cols_val[1].ec_value.ec_value_val;
708*7c478bd9Sstevel@tonic-gate 	if (name != 0)
709*7c478bd9Sstevel@tonic-gate 		*name = entryName;
710*7c478bd9Sstevel@tonic-gate 
711*7c478bd9Sstevel@tonic-gate 	if (t == 0 || entryName == 0 || t->objName == 0)
712*7c478bd9Sstevel@tonic-gate 		return (0);
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate 	bp2buf(myself, &b, "%s.%s", entryName, t->objName);
715*7c478bd9Sstevel@tonic-gate 	if (b.len == 0 || b.buf == 0)
716*7c478bd9Sstevel@tonic-gate 		return (0);
717*7c478bd9Sstevel@tonic-gate 
718*7c478bd9Sstevel@tonic-gate 	x = (__nis_table_mapping_t *)__nis_find_item_mt(b.buf,
719*7c478bd9Sstevel@tonic-gate 						&ldapMappingList, 0, 0);
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 	sfree(b.buf);
722*7c478bd9Sstevel@tonic-gate 
723*7c478bd9Sstevel@tonic-gate 	return (x);
724*7c478bd9Sstevel@tonic-gate }
725*7c478bd9Sstevel@tonic-gate 
726*7c478bd9Sstevel@tonic-gate /*
727*7c478bd9Sstevel@tonic-gate  * Query LDAP per the supplied (scheme-) query 'qin'. If 'doAsynch' is
728*7c478bd9Sstevel@tonic-gate  * set, and the query is an enumeration (qin == 0), the query will be
729*7c478bd9Sstevel@tonic-gate  * performed in a detached thread, and complete asynchronously. In this
730*7c478bd9Sstevel@tonic-gate  * case, the return status reflects the setup and launch of the
731*7c478bd9Sstevel@tonic-gate  * detached thread; the query will complete asynchronously.
732*7c478bd9Sstevel@tonic-gate  *
733*7c478bd9Sstevel@tonic-gate  * Returns an appropriate LDAP status code.
734*7c478bd9Sstevel@tonic-gate  */
735*7c478bd9Sstevel@tonic-gate int
736*7c478bd9Sstevel@tonic-gate db_mindex::queryLDAP(db_query *qin, char *dbId, int doAsynch) {
737*7c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
738*7c478bd9Sstevel@tonic-gate 	int			i, na, nq = 0, stat, stat2, numAttrs, ret;
739*7c478bd9Sstevel@tonic-gate 	int			xid = 0;
740*7c478bd9Sstevel@tonic-gate 	long			numEa;
741*7c478bd9Sstevel@tonic-gate 	bool_t			asObj, doEnum;
742*7c478bd9Sstevel@tonic-gate 	db_query		*q;
743*7c478bd9Sstevel@tonic-gate 	entry_object		**ea;
744*7c478bd9Sstevel@tonic-gate 	nis_attr		attr;
745*7c478bd9Sstevel@tonic-gate 	nis_object		*dirObj;
746*7c478bd9Sstevel@tonic-gate 	db_status		dstat;
747*7c478bd9Sstevel@tonic-gate 	char			*myself = "db_mindex::queryLDAP";
748*7c478bd9Sstevel@tonic-gate 
749*7c478bd9Sstevel@tonic-gate 	if (!useLDAPrespository || table == 0)
750*7c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
751*7c478bd9Sstevel@tonic-gate 
752*7c478bd9Sstevel@tonic-gate 	/*
753*7c478bd9Sstevel@tonic-gate 	 * Instances from the deferred dictionary shouldn't change,
754*7c478bd9Sstevel@tonic-gate 	 * there's no point in querying LDAP.
755*7c478bd9Sstevel@tonic-gate 	 */
756*7c478bd9Sstevel@tonic-gate 	if (table->mapping.isDeferredTable)
757*7c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
758*7c478bd9Sstevel@tonic-gate 
759*7c478bd9Sstevel@tonic-gate 	t = selectMapping(table, 0, qin, FALSE, &asObj, &stat);
760*7c478bd9Sstevel@tonic-gate 
761*7c478bd9Sstevel@tonic-gate 	if (t == 0)
762*7c478bd9Sstevel@tonic-gate 		return (stat);
763*7c478bd9Sstevel@tonic-gate 
764*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
765*7c478bd9Sstevel@tonic-gate 	printf("%s: %s (%s)\n",
766*7c478bd9Sstevel@tonic-gate 		myself, NIL(t->objName), (asObj ? "object" : "entry"));
767*7c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate 	if (qin != NULL) {
770*7c478bd9Sstevel@tonic-gate 		q = schemeQuery2Query(qin, scheme);
771*7c478bd9Sstevel@tonic-gate 		if (q == 0)
772*7c478bd9Sstevel@tonic-gate 			return (LDAP_PARAM_ERROR);
773*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
774*7c478bd9Sstevel@tonic-gate 		q->print();
775*7c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
776*7c478bd9Sstevel@tonic-gate 	} else {
777*7c478bd9Sstevel@tonic-gate 		q = 0;
778*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
779*7c478bd9Sstevel@tonic-gate 		printf("\tenumerating %s%s%s\n",
780*7c478bd9Sstevel@tonic-gate 			dbId ? dbId : "", dbId ? ":" : "", NIL(t->objName));
781*7c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
782*7c478bd9Sstevel@tonic-gate 	}
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate 	/*
785*7c478bd9Sstevel@tonic-gate 	 * Do we have any active mappings for this particular query and
786*7c478bd9Sstevel@tonic-gate 	 * dbId ?  If not, we're done.
787*7c478bd9Sstevel@tonic-gate 	 *
788*7c478bd9Sstevel@tonic-gate 	 * Note that we don't care about the return value from
789*7c478bd9Sstevel@tonic-gate 	 * selectTableMapping(), just wheter or not there are
790*7c478bd9Sstevel@tonic-gate 	 * any valid mappings.
791*7c478bd9Sstevel@tonic-gate 	 */
792*7c478bd9Sstevel@tonic-gate 	i = 0;
793*7c478bd9Sstevel@tonic-gate 	sfree(selectTableMapping(t, q, 0, asObj, dbId, &i));
794*7c478bd9Sstevel@tonic-gate 	if (i <= 0) {
795*7c478bd9Sstevel@tonic-gate 		freeQuery(q);
796*7c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
797*7c478bd9Sstevel@tonic-gate 	}
798*7c478bd9Sstevel@tonic-gate 
799*7c478bd9Sstevel@tonic-gate 	/* Is the object a directory ? */
800*7c478bd9Sstevel@tonic-gate 	if (asObj) {
801*7c478bd9Sstevel@tonic-gate 		nis_object	*o;
802*7c478bd9Sstevel@tonic-gate 		entry_object	*e, eo;
803*7c478bd9Sstevel@tonic-gate 		entry_col	ec[2];
804*7c478bd9Sstevel@tonic-gate 		int		nea;
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate 		stat = objFromLDAP(t, &o, &ea, &nea);
807*7c478bd9Sstevel@tonic-gate 		numEa = nea;
808*7c478bd9Sstevel@tonic-gate 
809*7c478bd9Sstevel@tonic-gate 		if (stat == LDAP_NO_SUCH_OBJECT) {
810*7c478bd9Sstevel@tonic-gate 			/* Positive failure; remove the object */
811*7c478bd9Sstevel@tonic-gate 			dstat = dbDeleteObj(t->objName);
812*7c478bd9Sstevel@tonic-gate 			if (dstat == DB_SUCCESS || dstat == DB_NOTFOUND) {
813*7c478bd9Sstevel@tonic-gate 				stat = LDAP_SUCCESS;
814*7c478bd9Sstevel@tonic-gate 			} else {
815*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
816*7c478bd9Sstevel@tonic-gate 					"%s: DB error %d deleting \"%s\"",
817*7c478bd9Sstevel@tonic-gate 					myself, dstat, NIL(t->objName));
818*7c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
819*7c478bd9Sstevel@tonic-gate 			}
820*7c478bd9Sstevel@tonic-gate 
821*7c478bd9Sstevel@tonic-gate 			freeQuery(q);
822*7c478bd9Sstevel@tonic-gate 
823*7c478bd9Sstevel@tonic-gate 			return (stat);
824*7c478bd9Sstevel@tonic-gate 		} else if (stat != LDAP_SUCCESS) {
825*7c478bd9Sstevel@tonic-gate 			freeQuery(q);
826*7c478bd9Sstevel@tonic-gate 			return (stat);
827*7c478bd9Sstevel@tonic-gate 		} else if (o == 0) {
828*7c478bd9Sstevel@tonic-gate 			/* OK; this entry just isn't mapped */
829*7c478bd9Sstevel@tonic-gate 			freeQuery(q);
830*7c478bd9Sstevel@tonic-gate 			return (LDAP_SUCCESS);
831*7c478bd9Sstevel@tonic-gate 		}
832*7c478bd9Sstevel@tonic-gate 
833*7c478bd9Sstevel@tonic-gate 		if (q != 0) {
834*7c478bd9Sstevel@tonic-gate 			/*
835*7c478bd9Sstevel@tonic-gate 			 * We're updating one particular entry (described
836*7c478bd9Sstevel@tonic-gate 			 * by 't') in the directory 'table->mapping.tm'.
837*7c478bd9Sstevel@tonic-gate 			 */
838*7c478bd9Sstevel@tonic-gate 
839*7c478bd9Sstevel@tonic-gate 			setOid(o);
840*7c478bd9Sstevel@tonic-gate 			dstat = dbRefreshObj(t->objName, o);
841*7c478bd9Sstevel@tonic-gate 			if (dstat == DB_SUCCESS) {
842*7c478bd9Sstevel@tonic-gate 				stat = LDAP_SUCCESS;
843*7c478bd9Sstevel@tonic-gate 			} else {
844*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
845*7c478bd9Sstevel@tonic-gate 			"%s: DB error %d updating \"%s\" in \"%s\"",
846*7c478bd9Sstevel@tonic-gate 					myself, NIL(t->objName),
847*7c478bd9Sstevel@tonic-gate 					NIL(table->mapping.tm->objName));
848*7c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
849*7c478bd9Sstevel@tonic-gate 			}
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate 			freeEntryObjArray(ea, numEa);
852*7c478bd9Sstevel@tonic-gate 			freeQuery(q);
853*7c478bd9Sstevel@tonic-gate 			nis_destroy_object(o);
854*7c478bd9Sstevel@tonic-gate 
855*7c478bd9Sstevel@tonic-gate 			return (stat);
856*7c478bd9Sstevel@tonic-gate 		}
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate 		dirObj = o;
859*7c478bd9Sstevel@tonic-gate 
860*7c478bd9Sstevel@tonic-gate 		/*
861*7c478bd9Sstevel@tonic-gate 		 * q == 0, so we're enumerating. Update the list of
862*7c478bd9Sstevel@tonic-gate 		 * directory entries.
863*7c478bd9Sstevel@tonic-gate 		 */
864*7c478bd9Sstevel@tonic-gate 
865*7c478bd9Sstevel@tonic-gate 		/*
866*7c478bd9Sstevel@tonic-gate 		 * Need to disable write-through to LDAP, for which we need
867*7c478bd9Sstevel@tonic-gate 		 * a lock on our db_mindex ('this'); we're also updating the
868*7c478bd9Sstevel@tonic-gate 		 * table, so we need a write lock on that as well.
869*7c478bd9Sstevel@tonic-gate 		 */
870*7c478bd9Sstevel@tonic-gate 		WRITELOCKNR(this, stat, "w db_mindex::queryLDAP");
871*7c478bd9Sstevel@tonic-gate 		if (stat == 0) {
872*7c478bd9Sstevel@tonic-gate 			WRITELOCKNR(table, stat2,
873*7c478bd9Sstevel@tonic-gate 				"table w db_mindex::queryLDAP");
874*7c478bd9Sstevel@tonic-gate 		}
875*7c478bd9Sstevel@tonic-gate 		if (stat != 0 || stat2 != 0) {
876*7c478bd9Sstevel@tonic-gate 			nis_destroy_object(dirObj);
877*7c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
878*7c478bd9Sstevel@tonic-gate 				"%s: lock error %d", myself,
879*7c478bd9Sstevel@tonic-gate 				stat != 0 ? stat : stat2);
880*7c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
881*7c478bd9Sstevel@tonic-gate 		}
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate 		setNoWriteThrough();
884*7c478bd9Sstevel@tonic-gate 		setNoLDAPquery();
885*7c478bd9Sstevel@tonic-gate 		table->setEnumMode(0);
886*7c478bd9Sstevel@tonic-gate 
887*7c478bd9Sstevel@tonic-gate 		for (i = 0, na = 0; i < numEa; i++) {
888*7c478bd9Sstevel@tonic-gate 			int			st;
889*7c478bd9Sstevel@tonic-gate 			__nis_table_mapping_t	*x;
890*7c478bd9Sstevel@tonic-gate 			char			*name = 0;
891*7c478bd9Sstevel@tonic-gate 			entry_obj		*e;
892*7c478bd9Sstevel@tonic-gate 
893*7c478bd9Sstevel@tonic-gate 			if (ea[i] == 0)
894*7c478bd9Sstevel@tonic-gate 				continue;
895*7c478bd9Sstevel@tonic-gate 
896*7c478bd9Sstevel@tonic-gate 			/*
897*7c478bd9Sstevel@tonic-gate 			 * We've got a list of dir entries. In the general,
898*7c478bd9Sstevel@tonic-gate 			 * case, some are new, and some already exist.
899*7c478bd9Sstevel@tonic-gate 			 * We definitely want to add the new ones, and to
900*7c478bd9Sstevel@tonic-gate 			 * that end, we need a copy of the object for the
901*7c478bd9Sstevel@tonic-gate 			 * entry. By definition, if an entry is new, we
902*7c478bd9Sstevel@tonic-gate 			 * don't yet have a copy of the object for it, so
903*7c478bd9Sstevel@tonic-gate 			 * it's LDAP or nothing.
904*7c478bd9Sstevel@tonic-gate 			 *
905*7c478bd9Sstevel@tonic-gate 			 * If the entry already exists, try to update the
906*7c478bd9Sstevel@tonic-gate 			 * entry object. In this case, we again only need
907*7c478bd9Sstevel@tonic-gate 			 * to look in LDAP for the object; if there already
908*7c478bd9Sstevel@tonic-gate 			 * is one in the DB, it's in the dir entry which we
909*7c478bd9Sstevel@tonic-gate 			 * want to update.
910*7c478bd9Sstevel@tonic-gate 			 *
911*7c478bd9Sstevel@tonic-gate 			 * So, whether adding or replacing, try to get the
912*7c478bd9Sstevel@tonic-gate 			 * object from LDAP.
913*7c478bd9Sstevel@tonic-gate 			 *
914*7c478bd9Sstevel@tonic-gate 			 * If we can't get a copy of the object, there's not
915*7c478bd9Sstevel@tonic-gate 			 * much point in adding or updating (since a dir
916*7c478bd9Sstevel@tonic-gate 			 * entry just consists of the entry object and name),
917*7c478bd9Sstevel@tonic-gate 			 * so we continue to the next entry.
918*7c478bd9Sstevel@tonic-gate 			 *
919*7c478bd9Sstevel@tonic-gate 			 * However, in that case, we do need to touch the
920*7c478bd9Sstevel@tonic-gate 			 * dir entry; otherwise, it will be removed later
921*7c478bd9Sstevel@tonic-gate 			 * on.
922*7c478bd9Sstevel@tonic-gate 			 */
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate 			x = findDirEntryMapping(t, ea[i], &name);
925*7c478bd9Sstevel@tonic-gate 			o = 0;
926*7c478bd9Sstevel@tonic-gate 			if (x == 0 || (st = objFromLDAP(x, &o, 0, 0)) !=
927*7c478bd9Sstevel@tonic-gate 					LDAP_SUCCESS) {
928*7c478bd9Sstevel@tonic-gate 				if (x != 0)
929*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
930*7c478bd9Sstevel@tonic-gate 			"%s: Unable to obtain object for \"%s\" in \"%s\": %s",
931*7c478bd9Sstevel@tonic-gate 					myself, NIL(name), NIL(t->objName),
932*7c478bd9Sstevel@tonic-gate 						ldap_err2string(st));
933*7c478bd9Sstevel@tonic-gate 				if (o != 0)
934*7c478bd9Sstevel@tonic-gate 					nis_destroy_object(o);
935*7c478bd9Sstevel@tonic-gate 				if (!touchEntry(ea[i])) {
936*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
937*7c478bd9Sstevel@tonic-gate 			"%s: Inconsistency: LDAP-derived directory \"%s\" "
938*7c478bd9Sstevel@tonic-gate 			"contains entry \"%s\", which is unknown locally, "
939*7c478bd9Sstevel@tonic-gate 			"and has no LDAP mapping",
940*7c478bd9Sstevel@tonic-gate 						myself, NIL(t->objName),
941*7c478bd9Sstevel@tonic-gate 						NIL(name));
942*7c478bd9Sstevel@tonic-gate 				}
943*7c478bd9Sstevel@tonic-gate 				continue;
944*7c478bd9Sstevel@tonic-gate 			}
945*7c478bd9Sstevel@tonic-gate 
946*7c478bd9Sstevel@tonic-gate 			if (ea[i]->en_cols.en_cols_len != 2 ||
947*7c478bd9Sstevel@tonic-gate 				ea[i]->en_cols.en_cols_val == 0 ||
948*7c478bd9Sstevel@tonic-gate 				ea[i]->en_cols.en_cols_val[0].
949*7c478bd9Sstevel@tonic-gate 					ec_value.ec_value_val != 0 ||
950*7c478bd9Sstevel@tonic-gate 				ea[i]->en_cols.en_cols_val[0].
951*7c478bd9Sstevel@tonic-gate 					ec_value.ec_value_len != 0) {
952*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
953*7c478bd9Sstevel@tonic-gate 			"%s: Illegal entry_obj col 0 for \"%s\" in \"%s\"",
954*7c478bd9Sstevel@tonic-gate 					myself, NIL(name), NIL(t->objName));
955*7c478bd9Sstevel@tonic-gate 				nis_destroy_object(o);
956*7c478bd9Sstevel@tonic-gate 				touchEntry(ea[i]);
957*7c478bd9Sstevel@tonic-gate 				continue;
958*7c478bd9Sstevel@tonic-gate 			}
959*7c478bd9Sstevel@tonic-gate 
960*7c478bd9Sstevel@tonic-gate 			setOid(o);
961*7c478bd9Sstevel@tonic-gate 			e = makePseudoEntryObj(o, ea[i], 0);
962*7c478bd9Sstevel@tonic-gate 			if (e == 0) {
963*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
964*7c478bd9Sstevel@tonic-gate 	"%s: Unable to create pseudo entry object for \"%s\" in \"%s\"",
965*7c478bd9Sstevel@tonic-gate 					myself, NIL(name), NIL(t->objName));
966*7c478bd9Sstevel@tonic-gate 				nis_destroy_object(o);
967*7c478bd9Sstevel@tonic-gate 				touchEntry(ea[i]);
968*7c478bd9Sstevel@tonic-gate 				continue;
969*7c478bd9Sstevel@tonic-gate 			}
970*7c478bd9Sstevel@tonic-gate 
971*7c478bd9Sstevel@tonic-gate 			st = updateTableEntry(e, 1, t->objName, o, 0,
972*7c478bd9Sstevel@tonic-gate 						o->zo_oid.mtime, &xid);
973*7c478bd9Sstevel@tonic-gate 			if (st == LDAP_SUCCESS) {
974*7c478bd9Sstevel@tonic-gate 				na++;
975*7c478bd9Sstevel@tonic-gate 			} else if (st == LDAP_COMPARE_TRUE) {
976*7c478bd9Sstevel@tonic-gate 				/* OK, same as existing entry */
977*7c478bd9Sstevel@tonic-gate 				st = LDAP_SUCCESS;
978*7c478bd9Sstevel@tonic-gate 			} else {
979*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
980*7c478bd9Sstevel@tonic-gate 		"%s: Error updating directory entry for \"%s\" in \"%s\": %s",
981*7c478bd9Sstevel@tonic-gate 					myself, NIL(name), NIL(t->objName),
982*7c478bd9Sstevel@tonic-gate 					ldap_err2string(st));
983*7c478bd9Sstevel@tonic-gate 				if (stat == LDAP_SUCCESS)
984*7c478bd9Sstevel@tonic-gate 					stat = st;
985*7c478bd9Sstevel@tonic-gate 			}
986*7c478bd9Sstevel@tonic-gate 
987*7c478bd9Sstevel@tonic-gate 			/* Free the XDR buffer */
988*7c478bd9Sstevel@tonic-gate 			sfree(e->en_cols.en_cols_val[0].
989*7c478bd9Sstevel@tonic-gate 					ec_value.ec_value_val);
990*7c478bd9Sstevel@tonic-gate 			/* Restore ea[i] */
991*7c478bd9Sstevel@tonic-gate 			ea[i]->en_cols.en_cols_val[0].
992*7c478bd9Sstevel@tonic-gate 					ec_value.ec_value_val = 0;
993*7c478bd9Sstevel@tonic-gate 			ea[i]->en_cols.en_cols_val[0].
994*7c478bd9Sstevel@tonic-gate 					ec_value.ec_value_len = 0;
995*7c478bd9Sstevel@tonic-gate 			nis_destroy_object(o);
996*7c478bd9Sstevel@tonic-gate 		}
997*7c478bd9Sstevel@tonic-gate 
998*7c478bd9Sstevel@tonic-gate 		freeEntryObjArray(ea, numEa);
999*7c478bd9Sstevel@tonic-gate 
1000*7c478bd9Sstevel@tonic-gate 		/* Get list of entries to remove */
1001*7c478bd9Sstevel@tonic-gate 		ea = table->endEnumMode(&numEa);
1002*7c478bd9Sstevel@tonic-gate 		if (ea != 0) {
1003*7c478bd9Sstevel@tonic-gate 			uint32_t	nowt = time(0);
1004*7c478bd9Sstevel@tonic-gate 
1005*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < numEa; i++) {
1006*7c478bd9Sstevel@tonic-gate 				int	st;
1007*7c478bd9Sstevel@tonic-gate 
1008*7c478bd9Sstevel@tonic-gate 				if (ea[i] == 0)
1009*7c478bd9Sstevel@tonic-gate 					continue;
1010*7c478bd9Sstevel@tonic-gate 
1011*7c478bd9Sstevel@tonic-gate 				st = updateTableEntry(ea[i], 0, t->objName, 0,
1012*7c478bd9Sstevel@tonic-gate 							0, nowt, &xid);
1013*7c478bd9Sstevel@tonic-gate 				if (st == LDAP_SUCCESS) {
1014*7c478bd9Sstevel@tonic-gate 					na++;
1015*7c478bd9Sstevel@tonic-gate 				} else {
1016*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1017*7c478bd9Sstevel@tonic-gate 			"%s: Error removing directory entry for \"%s\": %s",
1018*7c478bd9Sstevel@tonic-gate 						myself, NIL(t->objName),
1019*7c478bd9Sstevel@tonic-gate 						ldap_err2string(st));
1020*7c478bd9Sstevel@tonic-gate 					if (stat == LDAP_SUCCESS)
1021*7c478bd9Sstevel@tonic-gate 						stat = st;
1022*7c478bd9Sstevel@tonic-gate 				}
1023*7c478bd9Sstevel@tonic-gate 			}
1024*7c478bd9Sstevel@tonic-gate 		}
1025*7c478bd9Sstevel@tonic-gate 
1026*7c478bd9Sstevel@tonic-gate 		if (stat == LDAP_SUCCESS) {
1027*7c478bd9Sstevel@tonic-gate 			struct timeval	now;
1028*7c478bd9Sstevel@tonic-gate 			(void) gettimeofday(&now, 0);
1029*7c478bd9Sstevel@tonic-gate 			table->mapping.enumExpire = now.tv_sec +
1030*7c478bd9Sstevel@tonic-gate 				table->mapping.ttl;
1031*7c478bd9Sstevel@tonic-gate 		}
1032*7c478bd9Sstevel@tonic-gate 
1033*7c478bd9Sstevel@tonic-gate 		if (na > 0)
1034*7c478bd9Sstevel@tonic-gate 			(void) ((db *)dbptr.ptr)->sync_log();
1035*7c478bd9Sstevel@tonic-gate 
1036*7c478bd9Sstevel@tonic-gate 		if (xid != 0 && na > 0 && stat == LDAP_SUCCESS) {
1037*7c478bd9Sstevel@tonic-gate 			ret = endTransaction(xid, dirObj);
1038*7c478bd9Sstevel@tonic-gate 			if (ret != 0) {
1039*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
1040*7c478bd9Sstevel@tonic-gate 				"%s: Error ending transaction for \"%s\"",
1041*7c478bd9Sstevel@tonic-gate 					myself, NIL(t->objName));
1042*7c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
1043*7c478bd9Sstevel@tonic-gate 			}
1044*7c478bd9Sstevel@tonic-gate 		} else if (xid != 0) {
1045*7c478bd9Sstevel@tonic-gate 			ret = abort_transaction(xid);
1046*7c478bd9Sstevel@tonic-gate 			if (ret != 0) {
1047*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
1048*7c478bd9Sstevel@tonic-gate 				"%s: Error aborting transaction for \"%s\"",
1049*7c478bd9Sstevel@tonic-gate 					myself, NIL(t->objName));
1050*7c478bd9Sstevel@tonic-gate 			}
1051*7c478bd9Sstevel@tonic-gate 		}
1052*7c478bd9Sstevel@tonic-gate 		nis_destroy_object(dirObj);
1053*7c478bd9Sstevel@tonic-gate 
1054*7c478bd9Sstevel@tonic-gate 		sfree(ea);
1055*7c478bd9Sstevel@tonic-gate 
1056*7c478bd9Sstevel@tonic-gate 		clearNoLDAPquery();
1057*7c478bd9Sstevel@tonic-gate 		clearNoWriteThrough();
1058*7c478bd9Sstevel@tonic-gate 
1059*7c478bd9Sstevel@tonic-gate 		WRITEUNLOCK2(table, this,
1060*7c478bd9Sstevel@tonic-gate 			stat, stat,
1061*7c478bd9Sstevel@tonic-gate 			"table wu db_mindex::queryLDAP",
1062*7c478bd9Sstevel@tonic-gate 			"wu db_mindex::queryLDAP");
1063*7c478bd9Sstevel@tonic-gate 
1064*7c478bd9Sstevel@tonic-gate 		return (stat);
1065*7c478bd9Sstevel@tonic-gate 	}
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate 	/*
1068*7c478bd9Sstevel@tonic-gate 	 * In order to ping replicas, if any, we need to find the
1069*7c478bd9Sstevel@tonic-gate 	 * directory containing the table to be updated. If we
1070*7c478bd9Sstevel@tonic-gate 	 * can't find the directory object, we're sunk, so let's
1071*7c478bd9Sstevel@tonic-gate 	 * start with that.
1072*7c478bd9Sstevel@tonic-gate 	 */
1073*7c478bd9Sstevel@tonic-gate 	if (t->isMaster) {
1074*7c478bd9Sstevel@tonic-gate 		dirObj = findObj(t->obj->zo_domain, &dstat, &stat);
1075*7c478bd9Sstevel@tonic-gate 		if (dirObj == 0) {
1076*7c478bd9Sstevel@tonic-gate 			if (stat == LDAP_SUCCESS)
1077*7c478bd9Sstevel@tonic-gate 				stat = LDAP_OPERATIONS_ERROR;
1078*7c478bd9Sstevel@tonic-gate 			return (stat);
1079*7c478bd9Sstevel@tonic-gate 		}
1080*7c478bd9Sstevel@tonic-gate 	} else {
1081*7c478bd9Sstevel@tonic-gate 		dirObj = 0;
1082*7c478bd9Sstevel@tonic-gate 	}
1083*7c478bd9Sstevel@tonic-gate 
1084*7c478bd9Sstevel@tonic-gate 	stat = entriesFromLDAP(t, qin, q, dbId, dirObj, doAsynch);
1085*7c478bd9Sstevel@tonic-gate 
1086*7c478bd9Sstevel@tonic-gate 	return (stat);
1087*7c478bd9Sstevel@tonic-gate }
1088*7c478bd9Sstevel@tonic-gate 
1089*7c478bd9Sstevel@tonic-gate extern db	*tableDB(char *);
1090*7c478bd9Sstevel@tonic-gate 
1091*7c478bd9Sstevel@tonic-gate /*
1092*7c478bd9Sstevel@tonic-gate  * Remove the LDAP entry/entries corresponding to 'qin'/'obj'.
1093*7c478bd9Sstevel@tonic-gate  */
1094*7c478bd9Sstevel@tonic-gate int
1095*7c478bd9Sstevel@tonic-gate db_mindex::removeLDAP(db_query *qin, nis_object *obj) {
1096*7c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
1097*7c478bd9Sstevel@tonic-gate 	db_query		*q;
1098*7c478bd9Sstevel@tonic-gate 	bool_t			asObj;
1099*7c478bd9Sstevel@tonic-gate 	int			stat;
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate 	if (!useLDAPrespository || table == 0)
1102*7c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
1103*7c478bd9Sstevel@tonic-gate 
1104*7c478bd9Sstevel@tonic-gate 	/* Instances from the deferred dictionary should not update LDAP */
1105*7c478bd9Sstevel@tonic-gate 	if (table->mapping.isDeferredTable)
1106*7c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
1107*7c478bd9Sstevel@tonic-gate 
1108*7c478bd9Sstevel@tonic-gate 	t = selectMapping(table, 0, qin, TRUE, &asObj, &stat);
1109*7c478bd9Sstevel@tonic-gate 	if (t == 0 && stat != LDAP_SUCCESS)
1110*7c478bd9Sstevel@tonic-gate 		return (stat);
1111*7c478bd9Sstevel@tonic-gate 
1112*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
1113*7c478bd9Sstevel@tonic-gate 	if (t != 0)
1114*7c478bd9Sstevel@tonic-gate 		printf("removeLDAP: %s\n", NIL(t->objName));
1115*7c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
1116*7c478bd9Sstevel@tonic-gate 
1117*7c478bd9Sstevel@tonic-gate 	if (qin != NULL) {
1118*7c478bd9Sstevel@tonic-gate 		if (asObj) {
1119*7c478bd9Sstevel@tonic-gate 			/*
1120*7c478bd9Sstevel@tonic-gate 			 * selectMapping() gave us the mapping for the
1121*7c478bd9Sstevel@tonic-gate 			 * directory entry. However, if 't' is NULL, this
1122*7c478bd9Sstevel@tonic-gate 			 * could be due to the directory itself not being
1123*7c478bd9Sstevel@tonic-gate 			 * mapped, in which case we must obtain the mapping
1124*7c478bd9Sstevel@tonic-gate 			 * info from 'obj'.
1125*7c478bd9Sstevel@tonic-gate 			 */
1126*7c478bd9Sstevel@tonic-gate 			if (t == 0) {
1127*7c478bd9Sstevel@tonic-gate 				t = selectMapping(0, obj, 0, TRUE, &asObj,
1128*7c478bd9Sstevel@tonic-gate 						&stat);
1129*7c478bd9Sstevel@tonic-gate 				if (t == 0 && stat != LDAP_SUCCESS)
1130*7c478bd9Sstevel@tonic-gate 					return (stat);
1131*7c478bd9Sstevel@tonic-gate 			}
1132*7c478bd9Sstevel@tonic-gate 
1133*7c478bd9Sstevel@tonic-gate 			if (t != 0) {
1134*7c478bd9Sstevel@tonic-gate 				stat = deleteLDAPobj(t);
1135*7c478bd9Sstevel@tonic-gate 				/*
1136*7c478bd9Sstevel@tonic-gate 				 * If we were successful, update the object
1137*7c478bd9Sstevel@tonic-gate 				 * stored with the mapping.
1138*7c478bd9Sstevel@tonic-gate 				 */
1139*7c478bd9Sstevel@tonic-gate 				if (stat == LDAP_SUCCESS)
1140*7c478bd9Sstevel@tonic-gate 					(void) replaceMappingObj(t, 0);
1141*7c478bd9Sstevel@tonic-gate 				else
1142*7c478bd9Sstevel@tonic-gate 					return (stat);
1143*7c478bd9Sstevel@tonic-gate 			}
1144*7c478bd9Sstevel@tonic-gate 
1145*7c478bd9Sstevel@tonic-gate 			/*
1146*7c478bd9Sstevel@tonic-gate 			 * Since it's a directory entry we've removed, we also
1147*7c478bd9Sstevel@tonic-gate 			 * need to update the directory object itself.
1148*7c478bd9Sstevel@tonic-gate 			 */
1149*7c478bd9Sstevel@tonic-gate 			stat = storeLDAP(0, 0, 0, 0, 0);
1150*7c478bd9Sstevel@tonic-gate 		} else {
1151*7c478bd9Sstevel@tonic-gate 			q = schemeQuery2Query(qin, scheme);
1152*7c478bd9Sstevel@tonic-gate 			if (q == 0)
1153*7c478bd9Sstevel@tonic-gate 				return (LDAP_PARAM_ERROR);
1154*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
1155*7c478bd9Sstevel@tonic-gate 			q->print();
1156*7c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
1157*7c478bd9Sstevel@tonic-gate 			stat = mapToLDAP(t, 1, &q, 0, 0, 0, 0);
1158*7c478bd9Sstevel@tonic-gate 			freeQuery(q);
1159*7c478bd9Sstevel@tonic-gate 		}
1160*7c478bd9Sstevel@tonic-gate 	} else {
1161*7c478bd9Sstevel@tonic-gate 		/*
1162*7c478bd9Sstevel@tonic-gate 		 * This isn't the way to remove the LDAP entries
1163*7c478bd9Sstevel@tonic-gate 		 * corresponding to the entire table.
1164*7c478bd9Sstevel@tonic-gate 		 */
1165*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
1166*7c478bd9Sstevel@tonic-gate 		abort();
1167*7c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
1168*7c478bd9Sstevel@tonic-gate 		stat = LDAP_PARAM_ERROR;
1169*7c478bd9Sstevel@tonic-gate 	}
1170*7c478bd9Sstevel@tonic-gate 
1171*7c478bd9Sstevel@tonic-gate 	return (stat);
1172*7c478bd9Sstevel@tonic-gate }
1173*7c478bd9Sstevel@tonic-gate 
1174*7c478bd9Sstevel@tonic-gate /*
1175*7c478bd9Sstevel@tonic-gate  * Helper function for storeLDAP() which handles updates for objects
1176*7c478bd9Sstevel@tonic-gate  * other than table entries.
1177*7c478bd9Sstevel@tonic-gate  */
1178*7c478bd9Sstevel@tonic-gate int
1179*7c478bd9Sstevel@tonic-gate db_mindex::storeObjLDAP(__nis_table_mapping_t *t, nis_object *o) {
1180*7c478bd9Sstevel@tonic-gate 	int		stat, assigned = 0;
1181*7c478bd9Sstevel@tonic-gate 	entry_object	**ea;
1182*7c478bd9Sstevel@tonic-gate 	int		numEa, doUnlock = 0;
1183*7c478bd9Sstevel@tonic-gate 	db		*dbase = 0;
1184*7c478bd9Sstevel@tonic-gate 	db_mindex	*dbm = 0;
1185*7c478bd9Sstevel@tonic-gate 	char		*myself = "db_mindex::storeObjLDAP";
1186*7c478bd9Sstevel@tonic-gate 
1187*7c478bd9Sstevel@tonic-gate 	if (t == 0 || o == 0)
1188*7c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
1189*7c478bd9Sstevel@tonic-gate 
1190*7c478bd9Sstevel@tonic-gate 	/*
1191*7c478bd9Sstevel@tonic-gate 	 * If the object to be stored is anything other than a
1192*7c478bd9Sstevel@tonic-gate 	 * directory, we can just go ahead and write it to LDAP.
1193*7c478bd9Sstevel@tonic-gate 	 * A directory object, however, also needs a directory
1194*7c478bd9Sstevel@tonic-gate 	 * entry list, so we should to get hold of the db_table
1195*7c478bd9Sstevel@tonic-gate 	 * that goes with the directory.
1196*7c478bd9Sstevel@tonic-gate 	 */
1197*7c478bd9Sstevel@tonic-gate 	if (o->zo_data.zo_type == NIS_DIRECTORY_OBJ) {
1198*7c478bd9Sstevel@tonic-gate 		dbase = tableDB(t->objName);
1199*7c478bd9Sstevel@tonic-gate 		if (dbase != 0)
1200*7c478bd9Sstevel@tonic-gate 			dbm = dbase->mindex();
1201*7c478bd9Sstevel@tonic-gate 		if (dbase == 0 || dbm == 0 || dbm->table == 0) {
1202*7c478bd9Sstevel@tonic-gate 			/* By definition, no dir entries */
1203*7c478bd9Sstevel@tonic-gate 			ea = 0;
1204*7c478bd9Sstevel@tonic-gate 			numEa = 0;
1205*7c478bd9Sstevel@tonic-gate 			dbase = 0;
1206*7c478bd9Sstevel@tonic-gate 		} else {
1207*7c478bd9Sstevel@tonic-gate 			entry_object	**tea;
1208*7c478bd9Sstevel@tonic-gate 			long		i, ntea;
1209*7c478bd9Sstevel@tonic-gate 
1210*7c478bd9Sstevel@tonic-gate 			/*
1211*7c478bd9Sstevel@tonic-gate 			 * Read-lock the table so that 'tab'
1212*7c478bd9Sstevel@tonic-gate 			 * doesn't change while we're using it.
1213*7c478bd9Sstevel@tonic-gate 			 */
1214*7c478bd9Sstevel@tonic-gate 			READLOCK(dbm->table, LDAP_OPERATIONS_ERROR,
1215*7c478bd9Sstevel@tonic-gate 					"r table db_mindex::storeLDAP");
1216*7c478bd9Sstevel@tonic-gate 			doUnlock = 1;
1217*7c478bd9Sstevel@tonic-gate 
1218*7c478bd9Sstevel@tonic-gate 			tea = dbm->table->gettab();
1219*7c478bd9Sstevel@tonic-gate 			ntea = dbm->table->getsize();
1220*7c478bd9Sstevel@tonic-gate 
1221*7c478bd9Sstevel@tonic-gate 			/*
1222*7c478bd9Sstevel@tonic-gate 			 * There may be empty slots in the table 'tab'
1223*7c478bd9Sstevel@tonic-gate 			 * array, so get rid of those.
1224*7c478bd9Sstevel@tonic-gate 			 */
1225*7c478bd9Sstevel@tonic-gate 			if (tea != 0 && ntea > 0) {
1226*7c478bd9Sstevel@tonic-gate 				ea = (entry_object **)am(myself,
1227*7c478bd9Sstevel@tonic-gate 						ntea * sizeof (ea[0]));
1228*7c478bd9Sstevel@tonic-gate 				if (ea == 0) {
1229*7c478bd9Sstevel@tonic-gate 					READUNLOCK(dbm->table, LDAP_NO_MEMORY,
1230*7c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
1231*7c478bd9Sstevel@tonic-gate 					return (LDAP_NO_MEMORY);
1232*7c478bd9Sstevel@tonic-gate 				}
1233*7c478bd9Sstevel@tonic-gate 				for (i = 0, numEa = 0; i < ntea; i++) {
1234*7c478bd9Sstevel@tonic-gate 					if (tea[i] != 0) {
1235*7c478bd9Sstevel@tonic-gate 						ea[numEa] = tea[i];
1236*7c478bd9Sstevel@tonic-gate 						numEa++;
1237*7c478bd9Sstevel@tonic-gate 					}
1238*7c478bd9Sstevel@tonic-gate 				}
1239*7c478bd9Sstevel@tonic-gate 				if (numEa == 0) {
1240*7c478bd9Sstevel@tonic-gate 					/* No non-empty slots */
1241*7c478bd9Sstevel@tonic-gate 					sfree(ea);
1242*7c478bd9Sstevel@tonic-gate 					ea = 0;
1243*7c478bd9Sstevel@tonic-gate 					READUNLOCK(dbm->table,
1244*7c478bd9Sstevel@tonic-gate 						LDAP_OPERATIONS_ERROR,
1245*7c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
1246*7c478bd9Sstevel@tonic-gate 					doUnlock = 0;
1247*7c478bd9Sstevel@tonic-gate 				}
1248*7c478bd9Sstevel@tonic-gate 			} else {
1249*7c478bd9Sstevel@tonic-gate 				ea = 0;
1250*7c478bd9Sstevel@tonic-gate 				numEa = 0;
1251*7c478bd9Sstevel@tonic-gate 				READUNLOCK(dbm->table,
1252*7c478bd9Sstevel@tonic-gate 					LDAP_OPERATIONS_ERROR,
1253*7c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
1254*7c478bd9Sstevel@tonic-gate 				doUnlock = 0;
1255*7c478bd9Sstevel@tonic-gate 			}
1256*7c478bd9Sstevel@tonic-gate 		}
1257*7c478bd9Sstevel@tonic-gate 	} else {
1258*7c478bd9Sstevel@tonic-gate 		ea = 0;
1259*7c478bd9Sstevel@tonic-gate 		numEa = 0;
1260*7c478bd9Sstevel@tonic-gate 	}
1261*7c478bd9Sstevel@tonic-gate 
1262*7c478bd9Sstevel@tonic-gate 	stat = objToLDAP(t, o, ea, numEa);
1263*7c478bd9Sstevel@tonic-gate 
1264*7c478bd9Sstevel@tonic-gate 	if (ea != 0)
1265*7c478bd9Sstevel@tonic-gate 		sfree(ea);
1266*7c478bd9Sstevel@tonic-gate 	if (doUnlock) {
1267*7c478bd9Sstevel@tonic-gate 		READUNLOCK(dbm->table, stat,
1268*7c478bd9Sstevel@tonic-gate 				"ru table db_mindex::storeLDAP");
1269*7c478bd9Sstevel@tonic-gate 	}
1270*7c478bd9Sstevel@tonic-gate 
1271*7c478bd9Sstevel@tonic-gate 	return (stat);
1272*7c478bd9Sstevel@tonic-gate }
1273*7c478bd9Sstevel@tonic-gate 
1274*7c478bd9Sstevel@tonic-gate 
1275*7c478bd9Sstevel@tonic-gate /*
1276*7c478bd9Sstevel@tonic-gate  * Store data specified by the index-query 'qin' to LDAP. If 'obj' is
1277*7c478bd9Sstevel@tonic-gate  * non-null, it's a pointer to the pseudo-entry object corresponding to
1278*7c478bd9Sstevel@tonic-gate  * 'qin'. As a short-cut/convenience, the caller can instead supply
1279*7c478bd9Sstevel@tonic-gate  * the actual nis_object 'o'; if 'o' is NULL, it's derived from 'obj'.
1280*7c478bd9Sstevel@tonic-gate  *
1281*7c478bd9Sstevel@tonic-gate  * 'oldObj' is used for table entries if the store operation is
1282*7c478bd9Sstevel@tonic-gate  * an update, and the corresponding NIS+ operation was a delete followed
1283*7c478bd9Sstevel@tonic-gate  * by an add. In this case, oldObj contains the pre-delete incarnation of
1284*7c478bd9Sstevel@tonic-gate  * the entry object to be modified.
1285*7c478bd9Sstevel@tonic-gate  *
1286*7c478bd9Sstevel@tonic-gate  * The 'dbId' string is used to select one dbId for mapping chains
1287*7c478bd9Sstevel@tonic-gate  * that contain more than one.
1288*7c478bd9Sstevel@tonic-gate  *
1289*7c478bd9Sstevel@tonic-gate  * Returns an LDAP status code.
1290*7c478bd9Sstevel@tonic-gate  */
1291*7c478bd9Sstevel@tonic-gate int
1292*7c478bd9Sstevel@tonic-gate db_mindex::storeLDAP(db_query *qin, entry_object *obj, nis_object *o,
1293*7c478bd9Sstevel@tonic-gate 			entry_obj *oldObj, char *dbId) {
1294*7c478bd9Sstevel@tonic-gate 	__nis_table_mapping_t	*t;
1295*7c478bd9Sstevel@tonic-gate 	bool_t			asObj;
1296*7c478bd9Sstevel@tonic-gate 	db_query		*q, *qo, **qa;
1297*7c478bd9Sstevel@tonic-gate 	__nis_rule_value_t	*rv = 0;
1298*7c478bd9Sstevel@tonic-gate 	int			stat;
1299*7c478bd9Sstevel@tonic-gate 	char			*myself = "db_mindex::storeLDAP";
1300*7c478bd9Sstevel@tonic-gate 
1301*7c478bd9Sstevel@tonic-gate 	if (!useLDAPrespository || table == 0)
1302*7c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
1303*7c478bd9Sstevel@tonic-gate 
1304*7c478bd9Sstevel@tonic-gate 	/* Instances from the deferred dictionary should not update LDAP */
1305*7c478bd9Sstevel@tonic-gate 	if (table->mapping.isDeferredTable)
1306*7c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
1307*7c478bd9Sstevel@tonic-gate 
1308*7c478bd9Sstevel@tonic-gate 	t = selectMapping(table, 0, qin, TRUE, &asObj, &stat);
1309*7c478bd9Sstevel@tonic-gate 	if (t == 0 && stat != LDAP_SUCCESS)
1310*7c478bd9Sstevel@tonic-gate 		return (stat);
1311*7c478bd9Sstevel@tonic-gate 
1312*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
1313*7c478bd9Sstevel@tonic-gate 	if (t != 0)
1314*7c478bd9Sstevel@tonic-gate 		printf("storeLDAP: %s%s%s\n",
1315*7c478bd9Sstevel@tonic-gate 			dbId ? dbId : "", dbId ? ":" : "", NIL(t->objName));
1316*7c478bd9Sstevel@tonic-gate #endif	/* NISDB_LDAP_DEBUG */
1317*7c478bd9Sstevel@tonic-gate 
1318*7c478bd9Sstevel@tonic-gate 	/*
1319*7c478bd9Sstevel@tonic-gate 	 * selectMapping() didn't have the object to look at, so we
1320*7c478bd9Sstevel@tonic-gate 	 * must check if this is a directory entry or not.
1321*7c478bd9Sstevel@tonic-gate 	 */
1322*7c478bd9Sstevel@tonic-gate 	if (asObj) {
1323*7c478bd9Sstevel@tonic-gate 		if (o != 0) {
1324*7c478bd9Sstevel@tonic-gate 			if (o->zo_data.zo_type == NIS_ENTRY_OBJ)
1325*7c478bd9Sstevel@tonic-gate 				asObj = FALSE;
1326*7c478bd9Sstevel@tonic-gate 		} else if (obj != 0) {
1327*7c478bd9Sstevel@tonic-gate 			if (obj->en_type == 0 ||
1328*7c478bd9Sstevel@tonic-gate 				strcmp(obj->en_type, "IN_DIRECTORY") != 0)
1329*7c478bd9Sstevel@tonic-gate 				asObj = FALSE;
1330*7c478bd9Sstevel@tonic-gate 		}
1331*7c478bd9Sstevel@tonic-gate 	}
1332*7c478bd9Sstevel@tonic-gate 
1333*7c478bd9Sstevel@tonic-gate 	if (asObj) {
1334*7c478bd9Sstevel@tonic-gate 		bool_t		freeO = FALSE;
1335*7c478bd9Sstevel@tonic-gate 
1336*7c478bd9Sstevel@tonic-gate 		/*
1337*7c478bd9Sstevel@tonic-gate 		 * If we don't have a mapping, that's probably because
1338*7c478bd9Sstevel@tonic-gate 		 * the directory (represented by 'this') isn't mapped.
1339*7c478bd9Sstevel@tonic-gate 		 * Try to get a mapping from 'o' or 'obj'.
1340*7c478bd9Sstevel@tonic-gate 		 */
1341*7c478bd9Sstevel@tonic-gate 		if (t == 0) {
1342*7c478bd9Sstevel@tonic-gate 			if (o == 0 && obj != 0) {
1343*7c478bd9Sstevel@tonic-gate 				o = unmakePseudoEntryObj(obj, 0);
1344*7c478bd9Sstevel@tonic-gate 				if (o == 0)
1345*7c478bd9Sstevel@tonic-gate 					return (LDAP_OPERATIONS_ERROR);
1346*7c478bd9Sstevel@tonic-gate 				freeO = TRUE;
1347*7c478bd9Sstevel@tonic-gate 			}
1348*7c478bd9Sstevel@tonic-gate 			if (o != 0) {
1349*7c478bd9Sstevel@tonic-gate 				t = selectMapping(0, o, 0, TRUE, &asObj, &stat);
1350*7c478bd9Sstevel@tonic-gate 				if (t == 0) {
1351*7c478bd9Sstevel@tonic-gate 					if (freeO)
1352*7c478bd9Sstevel@tonic-gate 						nis_destroy_object(o);
1353*7c478bd9Sstevel@tonic-gate 					return (stat);
1354*7c478bd9Sstevel@tonic-gate 				}
1355*7c478bd9Sstevel@tonic-gate 			}
1356*7c478bd9Sstevel@tonic-gate 		}
1357*7c478bd9Sstevel@tonic-gate 
1358*7c478bd9Sstevel@tonic-gate 		/*
1359*7c478bd9Sstevel@tonic-gate 		 * If we found a mapping for the 'table' in this db_mindex,
1360*7c478bd9Sstevel@tonic-gate 		 * store the object.
1361*7c478bd9Sstevel@tonic-gate 		 */
1362*7c478bd9Sstevel@tonic-gate 		if (t != 0) {
1363*7c478bd9Sstevel@tonic-gate 			if (o == 0) {
1364*7c478bd9Sstevel@tonic-gate 				if (obj != 0) {
1365*7c478bd9Sstevel@tonic-gate 					o = unmakePseudoEntryObj(obj, 0);
1366*7c478bd9Sstevel@tonic-gate 					freeO = TRUE;
1367*7c478bd9Sstevel@tonic-gate 				} else {
1368*7c478bd9Sstevel@tonic-gate 					db_status	dstat;
1369*7c478bd9Sstevel@tonic-gate 
1370*7c478bd9Sstevel@tonic-gate 					o = dbFindObject(t->objName, &dstat);
1371*7c478bd9Sstevel@tonic-gate 					if (o == 0)
1372*7c478bd9Sstevel@tonic-gate 						logmsg(MSG_NOTIMECHECK, LOG_ERR,
1373*7c478bd9Sstevel@tonic-gate 					"%s: DB error %d finding \"%s\"",
1374*7c478bd9Sstevel@tonic-gate 							myself,
1375*7c478bd9Sstevel@tonic-gate 							NIL(t->objName));
1376*7c478bd9Sstevel@tonic-gate 					freeO = TRUE;
1377*7c478bd9Sstevel@tonic-gate 				}
1378*7c478bd9Sstevel@tonic-gate 			}
1379*7c478bd9Sstevel@tonic-gate 			if (o == 0)
1380*7c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
1381*7c478bd9Sstevel@tonic-gate 
1382*7c478bd9Sstevel@tonic-gate 			stat = storeObjLDAP(t, o);
1383*7c478bd9Sstevel@tonic-gate 
1384*7c478bd9Sstevel@tonic-gate 			/*
1385*7c478bd9Sstevel@tonic-gate 			 * Store the object with the mapping. If 'o' was
1386*7c478bd9Sstevel@tonic-gate 			 * supplied by the caller, we first need to make
1387*7c478bd9Sstevel@tonic-gate 			 * a copy.
1388*7c478bd9Sstevel@tonic-gate 			 */
1389*7c478bd9Sstevel@tonic-gate 			if (!freeO) {
1390*7c478bd9Sstevel@tonic-gate 				o = nis_clone_object(o, 0);
1391*7c478bd9Sstevel@tonic-gate 				if (o == 0)
1392*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1393*7c478bd9Sstevel@tonic-gate 			"%s: Unable to refresh mapping object for \"%s\"",
1394*7c478bd9Sstevel@tonic-gate 						myself, NIL(t->objName));
1395*7c478bd9Sstevel@tonic-gate 			}
1396*7c478bd9Sstevel@tonic-gate 			if (o != 0) {
1397*7c478bd9Sstevel@tonic-gate 				if (!replaceMappingObj(t, o))
1398*7c478bd9Sstevel@tonic-gate 					nis_destroy_object(o);
1399*7c478bd9Sstevel@tonic-gate 			}
1400*7c478bd9Sstevel@tonic-gate 
1401*7c478bd9Sstevel@tonic-gate 			/*
1402*7c478bd9Sstevel@tonic-gate 			 * Object now either destroyed or stored in 't'.
1403*7c478bd9Sstevel@tonic-gate 			 * Set pointer to NULL in order to avoid freeing
1404*7c478bd9Sstevel@tonic-gate 			 * it below.
1405*7c478bd9Sstevel@tonic-gate 			 */
1406*7c478bd9Sstevel@tonic-gate 			o = 0;
1407*7c478bd9Sstevel@tonic-gate 
1408*7c478bd9Sstevel@tonic-gate 			if (stat != LDAP_SUCCESS)
1409*7c478bd9Sstevel@tonic-gate 				return (stat);
1410*7c478bd9Sstevel@tonic-gate 		}
1411*7c478bd9Sstevel@tonic-gate 
1412*7c478bd9Sstevel@tonic-gate 		if (freeO && o != 0) {
1413*7c478bd9Sstevel@tonic-gate 			nis_destroy_object(o);
1414*7c478bd9Sstevel@tonic-gate 			o = 0;
1415*7c478bd9Sstevel@tonic-gate 		}
1416*7c478bd9Sstevel@tonic-gate 
1417*7c478bd9Sstevel@tonic-gate 		/*
1418*7c478bd9Sstevel@tonic-gate 		 * If the entry object 'obj' has the type "IN_DIRECTORY",
1419*7c478bd9Sstevel@tonic-gate 		 * then it's a directory entry, and we should check if
1420*7c478bd9Sstevel@tonic-gate 		 * the directory is mapped to LDAP, and update the dir
1421*7c478bd9Sstevel@tonic-gate 		 * entry list accordingly.
1422*7c478bd9Sstevel@tonic-gate 		 */
1423*7c478bd9Sstevel@tonic-gate 		if (obj == 0 || obj->en_type == 0 ||
1424*7c478bd9Sstevel@tonic-gate 				strcmp(obj->en_type, "IN_DIRECTORY") != 0)
1425*7c478bd9Sstevel@tonic-gate 			return (LDAP_SUCCESS);
1426*7c478bd9Sstevel@tonic-gate 
1427*7c478bd9Sstevel@tonic-gate 		/* Does it have a mapping  ? */
1428*7c478bd9Sstevel@tonic-gate 		t = selectMapping(table, 0, 0, TRUE, &asObj, &stat);
1429*7c478bd9Sstevel@tonic-gate 		if (t == 0)
1430*7c478bd9Sstevel@tonic-gate 			return (stat);
1431*7c478bd9Sstevel@tonic-gate 
1432*7c478bd9Sstevel@tonic-gate 		stat = storeObjLDAP(t, t->obj);
1433*7c478bd9Sstevel@tonic-gate 
1434*7c478bd9Sstevel@tonic-gate 		return (stat);
1435*7c478bd9Sstevel@tonic-gate 	}
1436*7c478bd9Sstevel@tonic-gate 
1437*7c478bd9Sstevel@tonic-gate 	/* Store table entries. If we don't have a mapping, we're done. */
1438*7c478bd9Sstevel@tonic-gate 	if (t == 0)
1439*7c478bd9Sstevel@tonic-gate 		return (LDAP_SUCCESS);
1440*7c478bd9Sstevel@tonic-gate 
1441*7c478bd9Sstevel@tonic-gate 	if (qin != NULL && obj != NULL) {
1442*7c478bd9Sstevel@tonic-gate 		db_index_entry	*dbie;
1443*7c478bd9Sstevel@tonic-gate 		int		i, size, nq = 0;
1444*7c478bd9Sstevel@tonic-gate 		long		l, count;
1445*7c478bd9Sstevel@tonic-gate 		bool_t		valid;
1446*7c478bd9Sstevel@tonic-gate 		db_query	qbuf, **qold;
1447*7c478bd9Sstevel@tonic-gate 
1448*7c478bd9Sstevel@tonic-gate 		rv = (__nis_rule_value_t *)am(myself, sizeof (*rv));
1449*7c478bd9Sstevel@tonic-gate 		qa = (db_query **)am(myself, sizeof (qa[0]));
1450*7c478bd9Sstevel@tonic-gate 		if (oldObj != 0) {
1451*7c478bd9Sstevel@tonic-gate 			/*
1452*7c478bd9Sstevel@tonic-gate 			 * Note that only qold[0] is a unique query pointer.
1453*7c478bd9Sstevel@tonic-gate 			 * All the other qold[i]'s are copies of qa[i].
1454*7c478bd9Sstevel@tonic-gate 			 * Hence, we only free qold[0], as well as qold
1455*7c478bd9Sstevel@tonic-gate 			 * itself.
1456*7c478bd9Sstevel@tonic-gate 			 */
1457*7c478bd9Sstevel@tonic-gate 			qold = (db_query **)am(myself, sizeof (qold[0]));
1458*7c478bd9Sstevel@tonic-gate 		} else {
1459*7c478bd9Sstevel@tonic-gate 			qold = 0;
1460*7c478bd9Sstevel@tonic-gate 		}
1461*7c478bd9Sstevel@tonic-gate 		if (rv == 0 || qa == 0 || (oldObj != 0 && qold == 0)) {
1462*7c478bd9Sstevel@tonic-gate 			sfree(rv);
1463*7c478bd9Sstevel@tonic-gate 			sfree(qa);
1464*7c478bd9Sstevel@tonic-gate 			sfree(qold);
1465*7c478bd9Sstevel@tonic-gate 			return (LDAP_NO_MEMORY);
1466*7c478bd9Sstevel@tonic-gate 		}
1467*7c478bd9Sstevel@tonic-gate 
1468*7c478bd9Sstevel@tonic-gate 		q = schemeQuery2Query(qin, scheme);
1469*7c478bd9Sstevel@tonic-gate 		if (q == 0) {
1470*7c478bd9Sstevel@tonic-gate 			sfree(rv);
1471*7c478bd9Sstevel@tonic-gate 			sfree(qa);
1472*7c478bd9Sstevel@tonic-gate 			return (LDAP_PARAM_ERROR);
1473*7c478bd9Sstevel@tonic-gate 		}
1474*7c478bd9Sstevel@tonic-gate 
1475*7c478bd9Sstevel@tonic-gate 		qa[0] = pseudoEntryObj2Query(obj, t->obj, &rv[0]);
1476*7c478bd9Sstevel@tonic-gate 		if (qa[0] == 0) {
1477*7c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOTIMECHECK, LOG_ERR,
1478*7c478bd9Sstevel@tonic-gate "%s: Unable to obtain query representation of new entry object for \"%s\"",
1479*7c478bd9Sstevel@tonic-gate 				myself, NIL(t->dbId));
1480*7c478bd9Sstevel@tonic-gate 			freeQuery(q);
1481*7c478bd9Sstevel@tonic-gate 			sfree(rv);
1482*7c478bd9Sstevel@tonic-gate 			sfree(qa);
1483*7c478bd9Sstevel@tonic-gate 			sfree(qold);
1484*7c478bd9Sstevel@tonic-gate 			return (LDAP_OPERATIONS_ERROR);
1485*7c478bd9Sstevel@tonic-gate 		}
1486*7c478bd9Sstevel@tonic-gate 		if (oldObj != 0) {
1487*7c478bd9Sstevel@tonic-gate 			qold[0] = pseudoEntryObj2Query(oldObj, t->obj, 0);
1488*7c478bd9Sstevel@tonic-gate 			if (qold[0] == 0) {
1489*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_ERR,
1490*7c478bd9Sstevel@tonic-gate "%s: Unable to obtain query representation of old entry object for \"%s\"",
1491*7c478bd9Sstevel@tonic-gate 					myself, NIL(t->dbId));
1492*7c478bd9Sstevel@tonic-gate 				freeQueries(qa, 1);
1493*7c478bd9Sstevel@tonic-gate 				freeQuery(q);
1494*7c478bd9Sstevel@tonic-gate 				sfree(rv);
1495*7c478bd9Sstevel@tonic-gate 				sfree(qa);
1496*7c478bd9Sstevel@tonic-gate 				sfree(qold);
1497*7c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
1498*7c478bd9Sstevel@tonic-gate 			}
1499*7c478bd9Sstevel@tonic-gate 		}
1500*7c478bd9Sstevel@tonic-gate 
1501*7c478bd9Sstevel@tonic-gate 		nq++;
1502*7c478bd9Sstevel@tonic-gate 
1503*7c478bd9Sstevel@tonic-gate 		/*
1504*7c478bd9Sstevel@tonic-gate 		 * In order to support many-to-one NIS+ to LDAP mapping,
1505*7c478bd9Sstevel@tonic-gate 		 * we need to find all possible matches in the NIS+ DB,
1506*7c478bd9Sstevel@tonic-gate 		 * and then merge to produce a single update. mapToLDAP()
1507*7c478bd9Sstevel@tonic-gate 		 * takes care of the merging, so our job is to collect
1508*7c478bd9Sstevel@tonic-gate 		 * the matches. Worst case is that we need to search
1509*7c478bd9Sstevel@tonic-gate 		 * individually for each component in 'qin', so that's
1510*7c478bd9Sstevel@tonic-gate 		 * what we'll do.
1511*7c478bd9Sstevel@tonic-gate 		 *
1512*7c478bd9Sstevel@tonic-gate 		 * mapToLDAP() has a mode that only performs an update
1513*7c478bd9Sstevel@tonic-gate 		 * for the first DN, and that's what we want. In order
1514*7c478bd9Sstevel@tonic-gate 		 * to make sure that it's the correct DN, we leave the
1515*7c478bd9Sstevel@tonic-gate 		 * original query as the first one passed to mapToLDAP().
1516*7c478bd9Sstevel@tonic-gate 		 */
1517*7c478bd9Sstevel@tonic-gate 
1518*7c478bd9Sstevel@tonic-gate 		size = qin->size();
1519*7c478bd9Sstevel@tonic-gate 
1520*7c478bd9Sstevel@tonic-gate 		/* For each component of 'qin' */
1521*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < size; i++) {
1522*7c478bd9Sstevel@tonic-gate 			db_query		*qc, **qat, **qoldt;
1523*7c478bd9Sstevel@tonic-gate 			long			j;
1524*7c478bd9Sstevel@tonic-gate 			__nis_rule_value_t	*rvt;
1525*7c478bd9Sstevel@tonic-gate 
1526*7c478bd9Sstevel@tonic-gate 			qc = queryFromComponent(qin, i, &qbuf);
1527*7c478bd9Sstevel@tonic-gate 			if (qc == 0)
1528*7c478bd9Sstevel@tonic-gate 				continue;
1529*7c478bd9Sstevel@tonic-gate 
1530*7c478bd9Sstevel@tonic-gate 			dbie = satisfy_query_dbonly(qc, &count, FALSE, &valid);
1531*7c478bd9Sstevel@tonic-gate 			if (dbie == 0 || !valid || count <= 0)
1532*7c478bd9Sstevel@tonic-gate 				continue;
1533*7c478bd9Sstevel@tonic-gate 
1534*7c478bd9Sstevel@tonic-gate 			rvt = (__nis_rule_value_t *)realloc(rv,
1535*7c478bd9Sstevel@tonic-gate 						(nq+count) * sizeof (rv[0]));
1536*7c478bd9Sstevel@tonic-gate 			qat = (db_query **)realloc(qa,
1537*7c478bd9Sstevel@tonic-gate 						(nq+count) * sizeof (qa[0]));
1538*7c478bd9Sstevel@tonic-gate 			if (qold != 0)
1539*7c478bd9Sstevel@tonic-gate 				qoldt = (db_query **)realloc(qold,
1540*7c478bd9Sstevel@tonic-gate 						(nq+count) * sizeof (qold[0]));
1541*7c478bd9Sstevel@tonic-gate 			if (rvt == 0 || qat == 0 || (qold != 0 && qoldt == 0)) {
1542*7c478bd9Sstevel@tonic-gate 				if (qat == 0)
1543*7c478bd9Sstevel@tonic-gate 					freeQueries(qa, nq);
1544*7c478bd9Sstevel@tonic-gate 				else
1545*7c478bd9Sstevel@tonic-gate 					freeQueries(qat, nq);
1546*7c478bd9Sstevel@tonic-gate 				if (rvt == 0)
1547*7c478bd9Sstevel@tonic-gate 					freeRuleValue(rv, nq);
1548*7c478bd9Sstevel@tonic-gate 				else
1549*7c478bd9Sstevel@tonic-gate 					freeRuleValue(rvt, nq);
1550*7c478bd9Sstevel@tonic-gate 				if (qold != 0) {
1551*7c478bd9Sstevel@tonic-gate 					if (qoldt == 0)
1552*7c478bd9Sstevel@tonic-gate 						freeQueries(qold, 1);
1553*7c478bd9Sstevel@tonic-gate 					else
1554*7c478bd9Sstevel@tonic-gate 						freeQueries(qoldt, 1);
1555*7c478bd9Sstevel@tonic-gate 				}
1556*7c478bd9Sstevel@tonic-gate 				freeQuery(q);
1557*7c478bd9Sstevel@tonic-gate 				(void) memset(&qbuf, 0, sizeof (qbuf));
1558*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOMEM, LOG_ERR,
1559*7c478bd9Sstevel@tonic-gate 					"%s: realloc(%d) failed",
1560*7c478bd9Sstevel@tonic-gate 					myself, (nq+count) * sizeof (void *));
1561*7c478bd9Sstevel@tonic-gate 				return (LDAP_NO_MEMORY);
1562*7c478bd9Sstevel@tonic-gate 			}
1563*7c478bd9Sstevel@tonic-gate 
1564*7c478bd9Sstevel@tonic-gate 			rv = rvt;
1565*7c478bd9Sstevel@tonic-gate 			qa = qat;
1566*7c478bd9Sstevel@tonic-gate 
1567*7c478bd9Sstevel@tonic-gate 			(void) memset(&rv[nq], 0, count * sizeof (rv[0]));
1568*7c478bd9Sstevel@tonic-gate 			(void) memset(&qa[nq], 0, count * sizeof (qa[0]));
1569*7c478bd9Sstevel@tonic-gate 			if (qold != 0) {
1570*7c478bd9Sstevel@tonic-gate 				qold = qoldt;
1571*7c478bd9Sstevel@tonic-gate 				(void) memset(&qold[nq], 0,
1572*7c478bd9Sstevel@tonic-gate 						count * sizeof (qold[0]));
1573*7c478bd9Sstevel@tonic-gate 			}
1574*7c478bd9Sstevel@tonic-gate 
1575*7c478bd9Sstevel@tonic-gate 			for (j = 0; j < count; j++) {
1576*7c478bd9Sstevel@tonic-gate 				qa[nq] = pseudoEntryObj2Query(
1577*7c478bd9Sstevel@tonic-gate 					table->get_entry(dbie->getlocation()),
1578*7c478bd9Sstevel@tonic-gate 							t->obj, &rv[nq]);
1579*7c478bd9Sstevel@tonic-gate 				if (qa[nq] == 0) {
1580*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1581*7c478bd9Sstevel@tonic-gate 			"%s: Could not create query from entry obj for \"%s\"",
1582*7c478bd9Sstevel@tonic-gate 						myself, NIL(t->objName));
1583*7c478bd9Sstevel@tonic-gate 					freeQueries(qa, nq);
1584*7c478bd9Sstevel@tonic-gate 					freeQueries(qold, 1);
1585*7c478bd9Sstevel@tonic-gate 					freeRuleValue(rv, nq);
1586*7c478bd9Sstevel@tonic-gate 					freeQuery(q);
1587*7c478bd9Sstevel@tonic-gate 					(void) memset(&qbuf, 0, sizeof (qbuf));
1588*7c478bd9Sstevel@tonic-gate 					return (LDAP_PARAM_ERROR);
1589*7c478bd9Sstevel@tonic-gate 				}
1590*7c478bd9Sstevel@tonic-gate 				if (qold != 0)
1591*7c478bd9Sstevel@tonic-gate 					qold[nq] = qa[nq];
1592*7c478bd9Sstevel@tonic-gate 				nq++;
1593*7c478bd9Sstevel@tonic-gate 				dbie = dbie->getnextresult();
1594*7c478bd9Sstevel@tonic-gate 				if (dbie == 0)
1595*7c478bd9Sstevel@tonic-gate 					break;
1596*7c478bd9Sstevel@tonic-gate 			}
1597*7c478bd9Sstevel@tonic-gate 		}
1598*7c478bd9Sstevel@tonic-gate 
1599*7c478bd9Sstevel@tonic-gate 		stat = mapToLDAP(t, nq, (qold != 0 ? qold : qa), qa, rv, 1,
1600*7c478bd9Sstevel@tonic-gate 				dbId);
1601*7c478bd9Sstevel@tonic-gate 
1602*7c478bd9Sstevel@tonic-gate 		freeQueries(qa, nq);
1603*7c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, nq);
1604*7c478bd9Sstevel@tonic-gate 		freeQuery(q);
1605*7c478bd9Sstevel@tonic-gate 		freeQueries(qold, 1);
1606*7c478bd9Sstevel@tonic-gate 		(void) memset(&qbuf, 0, sizeof (qbuf));
1607*7c478bd9Sstevel@tonic-gate 
1608*7c478bd9Sstevel@tonic-gate 	} else if (qin == 0 && obj == 0 && t->objType == NIS_TABLE_OBJ) {
1609*7c478bd9Sstevel@tonic-gate 		long			i, j, ntab;
1610*7c478bd9Sstevel@tonic-gate 		entry_object		**tab;
1611*7c478bd9Sstevel@tonic-gate 
1612*7c478bd9Sstevel@tonic-gate 		READLOCK(table, LDAP_OPERATIONS_ERROR,
1613*7c478bd9Sstevel@tonic-gate 				"r table db_mindex::storeLDAP");
1614*7c478bd9Sstevel@tonic-gate 
1615*7c478bd9Sstevel@tonic-gate 		tab = table->gettab();
1616*7c478bd9Sstevel@tonic-gate 		ntab = table->getsize();
1617*7c478bd9Sstevel@tonic-gate 		if (tab == 0 || ntab <= 0) {
1618*7c478bd9Sstevel@tonic-gate 			READUNLOCK(table, LDAP_OPERATIONS_ERROR,
1619*7c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
1620*7c478bd9Sstevel@tonic-gate 			return (LDAP_SUCCESS);
1621*7c478bd9Sstevel@tonic-gate 		}
1622*7c478bd9Sstevel@tonic-gate 
1623*7c478bd9Sstevel@tonic-gate 		qa = (db_query **)am(myself, ntab * sizeof (qa[0]));
1624*7c478bd9Sstevel@tonic-gate 		rv = (__nis_rule_value_t *)am(myself, ntab * sizeof (rv[0]));
1625*7c478bd9Sstevel@tonic-gate 		if (qa == 0 || rv == 0) {
1626*7c478bd9Sstevel@tonic-gate 			sfree(qa);
1627*7c478bd9Sstevel@tonic-gate 			sfree(rv);
1628*7c478bd9Sstevel@tonic-gate 			READUNLOCK(table, LDAP_OPERATIONS_ERROR,
1629*7c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
1630*7c478bd9Sstevel@tonic-gate 			return (LDAP_NO_MEMORY);
1631*7c478bd9Sstevel@tonic-gate 		}
1632*7c478bd9Sstevel@tonic-gate 
1633*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < ntab; i++) {
1634*7c478bd9Sstevel@tonic-gate 			if (tab[i] == 0)
1635*7c478bd9Sstevel@tonic-gate 				continue;
1636*7c478bd9Sstevel@tonic-gate 
1637*7c478bd9Sstevel@tonic-gate 			qa[i] = pseudoEntryObj2Query(tab[i], t->obj, &rv[i]);
1638*7c478bd9Sstevel@tonic-gate 			if (qa[i] == 0) {
1639*7c478bd9Sstevel@tonic-gate 				freeQueries(qa, i);
1640*7c478bd9Sstevel@tonic-gate 				freeRuleValue(rv, i);
1641*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1642*7c478bd9Sstevel@tonic-gate 			"%s: Could not create query from entry for \"%s\"",
1643*7c478bd9Sstevel@tonic-gate 					myself, NIL(t->objName));
1644*7c478bd9Sstevel@tonic-gate 				READUNLOCK(table, LDAP_OPERATIONS_ERROR,
1645*7c478bd9Sstevel@tonic-gate 					"ru table db_mindex::storeLDAP");
1646*7c478bd9Sstevel@tonic-gate 				return (LDAP_OPERATIONS_ERROR);
1647*7c478bd9Sstevel@tonic-gate 			}
1648*7c478bd9Sstevel@tonic-gate 		}
1649*7c478bd9Sstevel@tonic-gate 
1650*7c478bd9Sstevel@tonic-gate 		stat = mapToLDAP(t, ntab, qa, qa, rv, 0, dbId);
1651*7c478bd9Sstevel@tonic-gate 
1652*7c478bd9Sstevel@tonic-gate 		freeQueries(qa, ntab);
1653*7c478bd9Sstevel@tonic-gate 		freeRuleValue(rv, ntab);
1654*7c478bd9Sstevel@tonic-gate 
1655*7c478bd9Sstevel@tonic-gate 		if (stat == LDAP_SUCCESS) {
1656*7c478bd9Sstevel@tonic-gate 			struct timeval  now;
1657*7c478bd9Sstevel@tonic-gate 			int		lstat, lck = 1;
1658*7c478bd9Sstevel@tonic-gate 			/*
1659*7c478bd9Sstevel@tonic-gate 			 * Since we've just successfully uploaded everthing
1660*7c478bd9Sstevel@tonic-gate 			 * in this table, we now consider our local copy
1661*7c478bd9Sstevel@tonic-gate 			 * up-to-date as well.
1662*7c478bd9Sstevel@tonic-gate 			 */
1663*7c478bd9Sstevel@tonic-gate 
1664*7c478bd9Sstevel@tonic-gate 			(void) gettimeofday(&now, 0);
1665*7c478bd9Sstevel@tonic-gate 			WRITELOCKNR(table, lstat,
1666*7c478bd9Sstevel@tonic-gate 				"w table db_mindex::storeLDAP");
1667*7c478bd9Sstevel@tonic-gate 			if (lstat == 0) {
1668*7c478bd9Sstevel@tonic-gate 				table->mapping.enumExpire = now.tv_sec +
1669*7c478bd9Sstevel@tonic-gate 					table->mapping.ttl;
1670*7c478bd9Sstevel@tonic-gate 				lck = 0;
1671*7c478bd9Sstevel@tonic-gate 				WRITEUNLOCKNR(table, lstat,
1672*7c478bd9Sstevel@tonic-gate 					"wu table db_mindex::storeLDAP");
1673*7c478bd9Sstevel@tonic-gate 			}
1674*7c478bd9Sstevel@tonic-gate 			if (lstat != 0) {
1675*7c478bd9Sstevel@tonic-gate 				logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1676*7c478bd9Sstevel@tonic-gate 					"%s: %sock error %d for \"%s\"%s",
1677*7c478bd9Sstevel@tonic-gate 					myself, lck?"L":"Unl", lstat,
1678*7c478bd9Sstevel@tonic-gate 					NIL(t->objName),
1679*7c478bd9Sstevel@tonic-gate 					lck ?
1680*7c478bd9Sstevel@tonic-gate 				"; unable to update enumeration expiration":
1681*7c478bd9Sstevel@tonic-gate 				"");
1682*7c478bd9Sstevel@tonic-gate 			}
1683*7c478bd9Sstevel@tonic-gate 		}
1684*7c478bd9Sstevel@tonic-gate 
1685*7c478bd9Sstevel@tonic-gate 		READUNLOCK(table, stat,
1686*7c478bd9Sstevel@tonic-gate 				"ru table db_mindex::storeLDAP");
1687*7c478bd9Sstevel@tonic-gate 	}
1688*7c478bd9Sstevel@tonic-gate 
1689*7c478bd9Sstevel@tonic-gate 	return (stat);
1690*7c478bd9Sstevel@tonic-gate }
1691