/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <malloc.h>
#include <strings.h>
#include <string.h>
#include <time.h>
#include "db_headers.h"
#include "db.h"
#include "db_mindex.h"
#include "db_pickle.h"
#include "nisdb_mt.h"
#include "nisdb_ldap.h"
#include "ldap_nisdbquery.h"
#include "ldap_map.h"
#include "ldap_ruleval.h"
#include "ldap_scheme.h"
#include "ldap_parse.h"
#include "nis_hashitem.h"
#include "nis_db.h"
#include "ldap_glob.h"
/* Pass through configuration information to the table */
return (FALSE);
} else {
/* Defer table config until we have a table instance */
}
}
/*
* while we're incorporating log data into the in-memory tables.
*/
void
ASSERTWHELD(this->mindex);
}
void
ASSERTWHELD(this->mindex);
if (noWriteThrough.flag > 0)
#ifdef NISDB_LDAP_DEBUG
else
abort();
#endif /* NISDB_LDAP_DEBUG */
}
/*
* The noLDAPquery flag is used to prevent recursive LDAP queries when
* satisfy_query() is re-entered as we add an entry from queryLDAP().
*/
void
ASSERTWHELD(this->mindex);
noLDAPquery.flag++;
}
void
ASSERTWHELD(this->mindex);
if (noLDAPquery.flag > 0)
noLDAPquery.flag--;
#ifdef NISDB_LDAP_DEBUG
else
abort();
#endif /* NISDB_LDAP_DEBUG */
}
/*
* The initialLoad flag tells us if an add or remove is done as part of
* the initial load of data, in which case we should use the initial TTLs.
*/
void
ASSERTWHELD(this->mindex);
initialLoad.flag++;
}
void
ASSERTWHELD(this->mindex);
if (initialLoad.flag > 0)
initialLoad.flag--;
#ifdef NISDB_LDAP_DEBUG
else
abort();
#endif /* NISDB_LDAP_DEBUG */
}
void
}
void *
}
db_table *
return (table);
}
extern void db_free_result(db_result *);
char *objName = 0;
if (t != 0)
else if (objNameP != 0)
else
return (NIS_BOGUS_OBJ);
if (objName != 0) {
/* If not found in the local DB, try LDAP */
if (o == 0) {
if (stat != DB_NOTFOUND) {
"%s: DB err %d for \"%s\"",
}
if (o != 0) {
if (rstat != DB_SUCCESS)
"%s: DB error %d refreshing \"%s\"",
}
}
if (o != 0) {
if (objNameP != 0) {
if (*objNameP == 0) {
"%s: Unable to copy object name (\"%s\")",
}
}
if (t != 0) {
if (!setMappingObjTypeEtc(t, o))
} else {
}
} else if (lstat != LDAP_SUCCESS) {
"%s: LDAP err %d for \"%s\"",
}
}
return (type);
}
static __nis_table_mapping_t *
__nis_buffer_t b = {0, 0};
char *objPath;
return (0);
/*
* Convert full object name to the db table path used as
* key for the mapping hash list.
*/
if (statP != 0)
return (0);
}
&ldapMappingList, 0, 0);
return (t);
}
static __nis_table_mapping_t *
__nis_buffer_t b = {0, 0};
/*
* If 'table' is NULL, we try to find a mapping for 'obj'.
* We expect this to happen when our caller wants to write
* the object from a directory entry to LDAP.
*/
if (table == 0) {
if (asObjP != 0)
if (statP != 0)
*statP = LDAP_SUCCESS;
if (t == 0)
return (0);
/*
* Should the object type in the mapping be NIS_BOGUS_OBJ,
* we need to determine what kind of object this is.
*/
if (t->objType == NIS_BOGUS_OBJ) {
t->objType = updateMappingObj(t, 0, 0);
if (t->objType == NIS_BOGUS_OBJ) {
if (statP != 0)
return (0);
}
}
/*
* If caller wants a mapping suitable for writing,
* check that we're the master for this object.
*/
return (t);
}
/*
* If the object type for the mapping is NIS_BOGUS_OBJ, then
* we haven't yet been able to determine what kind of object this
* is. Try to fix that now.
*/
}
/*
* Depending on the object type (table->mapping.objType):
*
* table Use table->mapping.tm to query LDAP
* for entries per 'qin'.
*
* directory Use 'qin' and table->mapping.objName
* to retrieve a mapping entry, and then
* query LDAP for the corresponding object.
* entire directory object, plus the names
* of the directory entries.
*
* bogus Not mapping this object. However, we may
* still be mapping the object 'obj'.
*
* other Shouldn't happen; illegal.
*/
case NIS_TABLE_OBJ:
if (wantWrite)
else
break;
case NIS_DIRECTORY_OBJ: {
char *sub = 0;
t = 0;
/*
* We expect the query to have one component, containing
* the directory entry name. If there's no query, we want
* an enumeration of the entries in the directory. They're
* stored with the XDR:ed directory object in LDAP, so
* asObj should be TRUE.
*/
if (qin == 0) {
if (wantWrite)
else
break;
}
qc[0].index_value == 0) {
break;
}
break;
}
/* Append directory name to dir entry name */
/* Convert to the DB internal name */
break;
}
/* Look for the corresponding table mapping */
objPath, &ldapMappingList, 0, 0);
if (t == 0)
break;
/* Update object mapping information */
if (t->objType == NIS_BOGUS_OBJ)
(void) updateMappingObj(t, 0, 0);
/*
* Should check the objectDN's in 't', but leave that to
* underlying functions.
*/
if (wantWrite)
else
break;
}
case NIS_BOGUS_OBJ:
break;
default:
t = 0;
break;
}
if (!doLDAP)
t = 0;
if (asObjP != 0)
if (statP != 0)
return (t);
}
/*
* Replace or remove the table entry identified by 'e'. 'tableName' is
* the name of the table (which could be a directory) in which the entry
* resides. 'obj' is an un-XDR:ed copy of the object in 'e', optionally
* supplied to save re-doing unpacking of the entry object. 'tobj' is
* a pointer to the table object; needed for table entries, but not
* for directory entries.
*
* 'ttime' contains the current time, to be supplied for the trans log
* entry.
*
* an already existing one, and a suitable error otherwise.
*/
int
int *xid) {
long count = 0;
if (table == 0 || e == 0)
return (LDAP_PARAM_ERROR);
if (qi == 0) {
"%s: Out of memory for query index",
myself);
return (LDAP_NO_MEMORY);
}
"%s: count=%d, valid=%s",
delete qi;
return (LDAP_OPERATIONS_ERROR);
}
/*
* Need a copy of the old object in order to log a removal
* (this is true even if we're modifying an existing entry).
*/
if (dbie != 0) {
if (oldObj == 0) {
"%s: Error getting object from old pseudo-entry for \"%s\" in \"%s\"",
delete qi;
return (LDAP_OPERATIONS_ERROR);
}
}
if (replace) {
/* Need the object from the entry */
if (obj == 0) {
"%s: Error getting object from pseudo-entry for \"%s\" in \"%s\"",
delete qi;
return (LDAP_OPERATIONS_ERROR);
}
freeObj = 1;
}
/* Is the new object a dup of the old ? */
/* Yes, it's a dup, so just update the timestamp */
delete qi;
if (freeObj)
return (LDAP_COMPARE_TRUE);
} else {
/*
* Not a dup, so go ahead and add it. Provided
* that 'qi' isn't NULL (which we've already
* checked), DB_ADD(_NOSYNC) does the right
* thing even if matching entries already
* exist.
*/
qi, e);
if (dbres == 0)
stat = LDAP_SUCCESS;
else
}
} else { /* Removing */
/* If the object doesn't exist, we're done */
if (dbie == 0) {
delete qi;
return (LDAP_SUCCESS);
}
if (dbres == 0)
stat = LDAP_SUCCESS;
else
}
/* Log the operation */
if (stat == LDAP_SUCCESS) {
/* If we haven't begun the transaction yet, do so now */
if (*xid == 0) {
*xid = beginTransaction();
if (*xid == 0) {
"%s: Error starting transaction for \"%s\"",
delete qi;
if (oldObj != 0)
return (LDAP_OPERATIONS_ERROR);
}
}
if (obj == 0) {
"%s: Error getting object from pseudo-entry for \"%s\" in \"%s\"",
delete qi;
if (oldObj != 0)
return (LDAP_OPERATIONS_ERROR);
}
freeObj = 1;
}
/*
* The log stores nis_attr information, so we need to
* convert the scheme-query to a nis_attr array.
*/
if (attr == 0) {
"%s: Error converting index query to nis_attr for \"%s\" in \"%s\"",
if (freeObj)
if (oldObj != 0)
delete qi;
return (LDAP_OPERATIONS_ERROR);
}
if (replace) {
/*
* While the DB can handle a modify (replace)
* operation, the trans log stores this as a
* remove followed by an add (which allows
* backing out the change by removing the new
* object incarnation, and adding the old one).
*/
if (oldObj != 0)
else
ret = 0;
if (ret == 0)
} else { /* Removal */
}
if (ret != 0) {
"%s: Error adding trans log entry for \"%s\" in \"%s\"",
}
}
delete qi;
if (oldObj != 0)
if (freeObj)
return (stat);
}
if (table == 0 || e == 0)
return (FALSE);
if (qi == 0)
return (FALSE);
delete qi;
return (ret);
}
long count;
else
return (FALSE);
return (TRUE);
}
/*
* Compose an object name from column zero of 'e' and 't->objName',
* and return the mapping for that object, if any. Also set '*name'
* to point to the dir entry name in 'e'. Note that this is a pointer
* to existing data, and shouldn't be freed other than as part of
* freeing 'e'.
*/
static __nis_table_mapping_t *
char *entryName;
__nis_buffer_t b = {0, 0};
e->en_cols.en_cols_val == 0)
return (0);
if (name != 0)
return (0);
return (0);
&ldapMappingList, 0, 0);
return (x);
}
/*
* Query LDAP per the supplied (scheme-) query 'qin'. If 'doAsynch' is
* set, and the query is an enumeration (qin == 0), the query will be
* performed in a detached thread, and complete asynchronously. In this
* case, the return status reflects the setup and launch of the
* detached thread; the query will complete asynchronously.
*
* Returns an appropriate LDAP status code.
*/
int
int xid = 0;
long numEa;
db_query *q;
if (!useLDAPrespository || table == 0)
return (LDAP_SUCCESS);
/*
* Instances from the deferred dictionary shouldn't change,
* there's no point in querying LDAP.
*/
return (LDAP_SUCCESS);
if (t == 0)
return (stat);
#ifdef NISDB_LDAP_DEBUG
printf("%s: %s (%s)\n",
#endif /* NISDB_LDAP_DEBUG */
if (q == 0)
return (LDAP_PARAM_ERROR);
#ifdef NISDB_LDAP_DEBUG
q->print();
#endif /* NISDB_LDAP_DEBUG */
} else {
q = 0;
#ifdef NISDB_LDAP_DEBUG
printf("\tenumerating %s%s%s\n",
#endif /* NISDB_LDAP_DEBUG */
}
/*
* Do we have any active mappings for this particular query and
* dbId ? If not, we're done.
*
* Note that we don't care about the return value from
* selectTableMapping(), just wheter or not there are
* any valid mappings.
*/
i = 0;
if (i <= 0) {
freeQuery(q);
return (LDAP_SUCCESS);
}
/* Is the object a directory ? */
if (asObj) {
nis_object *o;
int nea;
if (stat == LDAP_NO_SUCH_OBJECT) {
/* Positive failure; remove the object */
stat = LDAP_SUCCESS;
} else {
"%s: DB error %d deleting \"%s\"",
}
freeQuery(q);
return (stat);
} else if (stat != LDAP_SUCCESS) {
freeQuery(q);
return (stat);
} else if (o == 0) {
/* OK; this entry just isn't mapped */
freeQuery(q);
return (LDAP_SUCCESS);
}
if (q != 0) {
/*
* We're updating one particular entry (described
* by 't') in the directory 'table->mapping.tm'.
*/
setOid(o);
if (dstat == DB_SUCCESS) {
stat = LDAP_SUCCESS;
} else {
"%s: DB error %d updating \"%s\" in \"%s\"",
}
freeQuery(q);
return (stat);
}
dirObj = o;
/*
* q == 0, so we're enumerating. Update the list of
* directory entries.
*/
/*
* Need to disable write-through to LDAP, for which we need
* a lock on our db_mindex ('this'); we're also updating the
* table, so we need a write lock on that as well.
*/
if (stat == 0) {
"table w db_mindex::queryLDAP");
}
"%s: lock error %d", myself,
return (LDAP_OPERATIONS_ERROR);
}
table->setEnumMode(0);
int st;
char *name = 0;
entry_obj *e;
if (ea[i] == 0)
continue;
/*
* We've got a list of dir entries. In the general,
* case, some are new, and some already exist.
* We definitely want to add the new ones, and to
* that end, we need a copy of the object for the
* entry. By definition, if an entry is new, we
* don't yet have a copy of the object for it, so
* it's LDAP or nothing.
*
* If the entry already exists, try to update the
* entry object. In this case, we again only need
* to look in LDAP for the object; if there already
* is one in the DB, it's in the dir entry which we
* want to update.
*
* So, whether adding or replacing, try to get the
* object from LDAP.
*
* If we can't get a copy of the object, there's not
* much point in adding or updating (since a dir
* entry just consists of the entry object and name),
* so we continue to the next entry.
*
* However, in that case, we do need to touch the
* dir entry; otherwise, it will be removed later
* on.
*/
o = 0;
if (x == 0 || (st = objFromLDAP(x, &o, 0, 0)) !=
LDAP_SUCCESS) {
if (x != 0)
"%s: Unable to obtain object for \"%s\" in \"%s\": %s",
if (o != 0)
if (!touchEntry(ea[i])) {
"%s: Inconsistency: LDAP-derived directory \"%s\" "
"contains entry \"%s\", which is unknown locally, "
"and has no LDAP mapping",
}
continue;
}
ec_value.ec_value_val != 0 ||
ec_value.ec_value_len != 0) {
"%s: Illegal entry_obj col 0 for \"%s\" in \"%s\"",
touchEntry(ea[i]);
continue;
}
setOid(o);
e = makePseudoEntryObj(o, ea[i], 0);
if (e == 0) {
"%s: Unable to create pseudo entry object for \"%s\" in \"%s\"",
touchEntry(ea[i]);
continue;
}
if (st == LDAP_SUCCESS) {
na++;
} else if (st == LDAP_COMPARE_TRUE) {
/* OK, same as existing entry */
st = LDAP_SUCCESS;
} else {
"%s: Error updating directory entry for \"%s\" in \"%s\": %s",
if (stat == LDAP_SUCCESS)
}
/* Free the XDR buffer */
/* Restore ea[i] */
ec_value.ec_value_val = 0;
ec_value.ec_value_len = 0;
}
/* Get list of entries to remove */
if (ea != 0) {
for (i = 0; i < numEa; i++) {
int st;
if (ea[i] == 0)
continue;
if (st == LDAP_SUCCESS) {
na++;
} else {
"%s: Error removing directory entry for \"%s\": %s",
if (stat == LDAP_SUCCESS)
}
}
}
if (stat == LDAP_SUCCESS) {
(void) gettimeofday(&now, 0);
}
if (na > 0)
if (ret != 0) {
"%s: Error ending transaction for \"%s\"",
}
} else if (xid != 0) {
if (ret != 0) {
"%s: Error aborting transaction for \"%s\"",
}
}
WRITEUNLOCK2(table, this,
"table wu db_mindex::queryLDAP",
"wu db_mindex::queryLDAP");
return (stat);
}
/*
* In order to ping replicas, if any, we need to find the
* directory containing the table to be updated. If we
* can't find the directory object, we're sunk, so let's
* start with that.
*/
if (t->isMaster) {
if (dirObj == 0) {
if (stat == LDAP_SUCCESS)
return (stat);
}
} else {
dirObj = 0;
}
return (stat);
}
/*
*/
int
db_query *q;
int stat;
if (!useLDAPrespository || table == 0)
return (LDAP_SUCCESS);
/* Instances from the deferred dictionary should not update LDAP */
return (LDAP_SUCCESS);
if (t == 0 && stat != LDAP_SUCCESS)
return (stat);
#ifdef NISDB_LDAP_DEBUG
if (t != 0)
#endif /* NISDB_LDAP_DEBUG */
if (asObj) {
/*
* selectMapping() gave us the mapping for the
* directory entry. However, if 't' is NULL, this
* could be due to the directory itself not being
* mapped, in which case we must obtain the mapping
* info from 'obj'.
*/
if (t == 0) {
&stat);
if (t == 0 && stat != LDAP_SUCCESS)
return (stat);
}
if (t != 0) {
stat = deleteLDAPobj(t);
/*
* If we were successful, update the object
* stored with the mapping.
*/
if (stat == LDAP_SUCCESS)
(void) replaceMappingObj(t, 0);
else
return (stat);
}
/*
* Since it's a directory entry we've removed, we also
* need to update the directory object itself.
*/
} else {
if (q == 0)
return (LDAP_PARAM_ERROR);
#ifdef NISDB_LDAP_DEBUG
q->print();
#endif /* NISDB_LDAP_DEBUG */
freeQuery(q);
}
} else {
/*
* This isn't the way to remove the LDAP entries
* corresponding to the entire table.
*/
#ifdef NISDB_LDAP_DEBUG
abort();
#endif /* NISDB_LDAP_DEBUG */
}
return (stat);
}
/*
* Helper function for storeLDAP() which handles updates for objects
* other than table entries.
*/
int
if (t == 0 || o == 0)
return (LDAP_SUCCESS);
/*
* If the object to be stored is anything other than a
* directory, we can just go ahead and write it to LDAP.
* A directory object, however, also needs a directory
* entry list, so we should to get hold of the db_table
* that goes with the directory.
*/
if (dbase != 0)
/* By definition, no dir entries */
ea = 0;
numEa = 0;
dbase = 0;
} else {
long i, ntea;
/*
* Read-lock the table so that 'tab'
* doesn't change while we're using it.
*/
"r table db_mindex::storeLDAP");
doUnlock = 1;
/*
* There may be empty slots in the table 'tab'
* array, so get rid of those.
*/
if (ea == 0) {
"ru table db_mindex::storeLDAP");
return (LDAP_NO_MEMORY);
}
if (tea[i] != 0) {
numEa++;
}
}
if (numEa == 0) {
/* No non-empty slots */
ea = 0;
"ru table db_mindex::storeLDAP");
doUnlock = 0;
}
} else {
ea = 0;
numEa = 0;
"ru table db_mindex::storeLDAP");
doUnlock = 0;
}
}
} else {
ea = 0;
numEa = 0;
}
if (ea != 0)
if (doUnlock) {
"ru table db_mindex::storeLDAP");
}
return (stat);
}
/*
* Store data specified by the index-query 'qin' to LDAP. If 'obj' is
* non-null, it's a pointer to the pseudo-entry object corresponding to
* 'qin'. As a short-cut/convenience, the caller can instead supply
* the actual nis_object 'o'; if 'o' is NULL, it's derived from 'obj'.
*
* 'oldObj' is used for table entries if the store operation is
* an update, and the corresponding NIS+ operation was a delete followed
* by an add. In this case, oldObj contains the pre-delete incarnation of
* the entry object to be modified.
*
* The 'dbId' string is used to select one dbId for mapping chains
* that contain more than one.
*
* Returns an LDAP status code.
*/
int
int stat;
if (!useLDAPrespository || table == 0)
return (LDAP_SUCCESS);
/* Instances from the deferred dictionary should not update LDAP */
return (LDAP_SUCCESS);
if (t == 0 && stat != LDAP_SUCCESS)
return (stat);
#ifdef NISDB_LDAP_DEBUG
if (t != 0)
printf("storeLDAP: %s%s%s\n",
#endif /* NISDB_LDAP_DEBUG */
/*
* selectMapping() didn't have the object to look at, so we
* must check if this is a directory entry or not.
*/
if (asObj) {
if (o != 0) {
} else if (obj != 0) {
}
}
if (asObj) {
/*
* If we don't have a mapping, that's probably because
* the directory (represented by 'this') isn't mapped.
* Try to get a mapping from 'o' or 'obj'.
*/
if (t == 0) {
if (o == 0 && obj != 0) {
o = unmakePseudoEntryObj(obj, 0);
if (o == 0)
return (LDAP_OPERATIONS_ERROR);
}
if (o != 0) {
if (t == 0) {
if (freeO)
return (stat);
}
}
}
/*
* If we found a mapping for the 'table' in this db_mindex,
* store the object.
*/
if (t != 0) {
if (o == 0) {
if (obj != 0) {
o = unmakePseudoEntryObj(obj, 0);
} else {
if (o == 0)
"%s: DB error %d finding \"%s\"",
}
}
if (o == 0)
return (LDAP_OPERATIONS_ERROR);
stat = storeObjLDAP(t, o);
/*
* Store the object with the mapping. If 'o' was
* supplied by the caller, we first need to make
* a copy.
*/
if (!freeO) {
o = nis_clone_object(o, 0);
if (o == 0)
"%s: Unable to refresh mapping object for \"%s\"",
}
if (o != 0) {
if (!replaceMappingObj(t, o))
}
/*
* Object now either destroyed or stored in 't'.
* Set pointer to NULL in order to avoid freeing
* it below.
*/
o = 0;
if (stat != LDAP_SUCCESS)
return (stat);
}
if (freeO && o != 0) {
o = 0;
}
/*
* If the entry object 'obj' has the type "IN_DIRECTORY",
* then it's a directory entry, and we should check if
* the directory is mapped to LDAP, and update the dir
* entry list accordingly.
*/
return (LDAP_SUCCESS);
/* Does it have a mapping ? */
if (t == 0)
return (stat);
return (stat);
}
/* Store table entries. If we don't have a mapping, we're done. */
if (t == 0)
return (LDAP_SUCCESS);
long l, count;
if (oldObj != 0) {
/*
* Note that only qold[0] is a unique query pointer.
* All the other qold[i]'s are copies of qa[i].
* Hence, we only free qold[0], as well as qold
* itself.
*/
} else {
qold = 0;
}
return (LDAP_NO_MEMORY);
}
if (q == 0) {
return (LDAP_PARAM_ERROR);
}
if (qa[0] == 0) {
"%s: Unable to obtain query representation of new entry object for \"%s\"",
freeQuery(q);
return (LDAP_OPERATIONS_ERROR);
}
if (oldObj != 0) {
if (qold[0] == 0) {
"%s: Unable to obtain query representation of old entry object for \"%s\"",
freeQuery(q);
return (LDAP_OPERATIONS_ERROR);
}
}
nq++;
/*
* In order to support many-to-one NIS+ to LDAP mapping,
* we need to find all possible matches in the NIS+ DB,
* and then merge to produce a single update. mapToLDAP()
* takes care of the merging, so our job is to collect
* the matches. Worst case is that we need to search
* individually for each component in 'qin', so that's
* what we'll do.
*
* mapToLDAP() has a mode that only performs an update
* for the first DN, and that's what we want. In order
* to make sure that it's the correct DN, we leave the
* original query as the first one passed to mapToLDAP().
*/
/* For each component of 'qin' */
for (i = 0; i < size; i++) {
long j;
if (qc == 0)
continue;
continue;
if (qold != 0)
if (qat == 0)
else
if (rvt == 0)
else
if (qold != 0) {
if (qoldt == 0)
else
}
freeQuery(q);
"%s: realloc(%d) failed",
return (LDAP_NO_MEMORY);
}
if (qold != 0) {
}
for (j = 0; j < count; j++) {
"%s: Could not create query from entry obj for \"%s\"",
freeQuery(q);
return (LDAP_PARAM_ERROR);
}
if (qold != 0)
nq++;
if (dbie == 0)
break;
}
}
dbId);
freeQuery(q);
long i, j, ntab;
"r table db_mindex::storeLDAP");
"ru table db_mindex::storeLDAP");
return (LDAP_SUCCESS);
}
"ru table db_mindex::storeLDAP");
return (LDAP_NO_MEMORY);
}
for (i = 0; i < ntab; i++) {
if (tab[i] == 0)
continue;
if (qa[i] == 0) {
freeQueries(qa, i);
freeRuleValue(rv, i);
"%s: Could not create query from entry for \"%s\"",
"ru table db_mindex::storeLDAP");
return (LDAP_OPERATIONS_ERROR);
}
}
if (stat == LDAP_SUCCESS) {
/*
* Since we've just successfully uploaded everthing
* in this table, we now consider our local copy
* up-to-date as well.
*/
(void) gettimeofday(&now, 0);
"w table db_mindex::storeLDAP");
if (lstat == 0) {
lck = 0;
"wu table db_mindex::storeLDAP");
}
if (lstat != 0) {
"%s: %sock error %d for \"%s\"%s",
lck ?
"; unable to update enumeration expiration":
"");
}
}
"ru table db_mindex::storeLDAP");
}
return (stat);
}
/*
* Sets the oid (i.e., the creation and modification times) for the
* specified object. In order to avoid retrieving the old incarnation
* (if any) from the DB first, we're punting and setting both mtime
* and ctime to the current time.
*/
static void
if (obj != 0) {
}
}