#include <stdio.h>
#include <malloc.h>
#include <strings.h>
#include <string.h>
#include <sys/param.h>
#include <sys/types.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"
bool_t
db_mindex::configure(char *tablePath) {
if (tablePath == NULL)
return (FALSE);
if (objPath.ptr != 0)
free(objPath.ptr);
objPath.ptr = strdup(tablePath);
if (table != NULL) {
return (table->configure(tablePath));
} else {
return (objPath.ptr != NULL);
}
}
void
db_mindex::setNoWriteThrough(void) {
ASSERTWHELD(this->mindex);
noWriteThrough.flag++;
}
void
db_mindex::clearNoWriteThrough(void) {
ASSERTWHELD(this->mindex);
if (noWriteThrough.flag > 0)
noWriteThrough.flag--;
#ifdef NISDB_LDAP_DEBUG
else
abort();
#endif
}
void
db_mindex::setNoLDAPquery(void) {
ASSERTWHELD(this->mindex);
noLDAPquery.flag++;
}
void
db_mindex::clearNoLDAPquery(void) {
ASSERTWHELD(this->mindex);
if (noLDAPquery.flag > 0)
noLDAPquery.flag--;
#ifdef NISDB_LDAP_DEBUG
else
abort();
#endif
}
void
db_mindex::setInitialLoad(void) {
ASSERTWHELD(this->mindex);
initialLoad.flag++;
}
void
db_mindex::clearInitialLoad(void) {
ASSERTWHELD(this->mindex);
if (initialLoad.flag > 0)
initialLoad.flag--;
#ifdef NISDB_LDAP_DEBUG
else
abort();
#endif
}
void
db_mindex::setDbPtr(void *ptr) {
dbptr.ptr = ptr;
}
void *
db_mindex::getDbPtr(void) {
return (dbptr.ptr);
}
db_table *
db_mindex::getTable(void) {
return (table);
}
static void setOid(nis_object *obj);
extern void db_free_result(db_result *);
zotypes
updateMappingObj(__nis_table_mapping_t *t, char **objNameP,
bool_t *isMasterP) {
zotypes type = NIS_BOGUS_OBJ;
char *objName = 0;
const char *myself = "updateMappingObj";
if (t != 0)
objName = t->objName;
else if (objNameP != 0)
objName = *objNameP;
else
return (NIS_BOGUS_OBJ);
if (objName != 0) {
db_status stat;
int lstat = LDAP_SUCCESS;
nis_object *o = dbFindObject(objName, &stat);
if (o == 0) {
if (stat != DB_NOTFOUND) {
logmsg(MSG_NOTIMECHECK, LOG_INFO,
"%s: DB err %d for \"%s\"",
myself, stat, NIL(objName));
}
o = ldapFindObj(t, objName, &lstat);
if (o != 0) {
db_status rstat;
rstat = dbRefreshObj(objName, o);
if (rstat != DB_SUCCESS)
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: DB error %d refreshing \"%s\"",
myself, rstat, NIL(objName));
}
}
if (o != 0) {
type = o->zo_data.zo_type;
if (objNameP != 0) {
*objNameP = sdup(myself, T, objName);
if (*objNameP == 0) {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Unable to copy object name (\"%s\")",
myself, NIL(objName));
}
}
if (t != 0) {
if (!setMappingObjTypeEtc(t, o))
nis_destroy_object(o);
} else {
nis_destroy_object(o);
}
} else if (lstat != LDAP_SUCCESS) {
logmsg(MSG_NOTIMECHECK, LOG_INFO,
"%s: LDAP err %d for \"%s\"",
myself, lstat, NIL(objName));
}
}
return (type);
}
static __nis_table_mapping_t *
mappingFromObj(nis_object *obj, int *statP) {
__nis_table_mapping_t *t;
__nis_buffer_t b = {0, 0};
char *objPath;
const char *myself = "mappingFromObj";
if (obj == 0 || obj->zo_data.zo_type == NIS_ENTRY_OBJ)
return (0);
bp2buf(myself, &b, "%s.%s",
NIL(obj->zo_name), NIL(obj->zo_domain));
objPath = internalTableName(b.buf);
sfree(b.buf);
if (slen(objPath) <= 0) {
if (statP != 0)
*statP = LDAP_OPERATIONS_ERROR;
sfree(objPath);
return (0);
}
t = (__nis_table_mapping_t *)__nis_find_item_mt(objPath,
&ldapMappingList, 0, 0);
sfree(objPath);
return (t);
}
static __nis_table_mapping_t *
selectMapping(db_table *table, nis_object *obj, db_query *qin,
bool_t wantWrite, bool_t *asObjP, int *statP) {
__nis_table_mapping_t *t;
__nis_buffer_t b = {0, 0};
bool_t doLDAP, asObj;
int stat = LDAP_SUCCESS;
char *objPath = 0, buf[MAXPATHLEN+NIS_MAXNAMELEN+1];
const char *myself = "db_mindex::selectMapping";
if (table == 0) {
if (asObjP != 0)
*asObjP = TRUE;
if (statP != 0)
*statP = LDAP_SUCCESS;
t = mappingFromObj(obj, statP);
if (t == 0)
return (0);
if (t->objType == NIS_BOGUS_OBJ) {
t->objType = updateMappingObj(t, 0, 0);
if (t->objType == NIS_BOGUS_OBJ) {
if (statP != 0)
*statP = LDAP_OPERATIONS_ERROR;
return (0);
}
}
return (t);
}
if (table->mapping.objType == NIS_BOGUS_OBJ) {
table->mapping.objType = updateMappingObj(table->mapping.tm,
&table->mapping.objName,
&table->mapping.isMaster);
table->mapping.expireType = table->mapping.objType;
}
switch (table->mapping.objType) {
case NIS_TABLE_OBJ:
t = table->mapping.tm;
if (wantWrite)
doLDAP = table->mapping.isMaster &&
table->mapping.toLDAP;
else
doLDAP = table->mapping.fromLDAP;
asObj = FALSE;
break;
case NIS_DIRECTORY_OBJ: {
char *sub = 0;
int nqc, len = 0;
db_qcomp *qc;
t = 0;
doLDAP = FALSE;
asObj = TRUE;
if (qin == 0) {
t = table->mapping.tm;
if (wantWrite)
doLDAP = table->mapping.isMaster &&
table->mapping.toLDAP;
else
doLDAP = table->mapping.fromLDAP;
asObj = TRUE;
break;
}
nqc = qin->size();
if (nqc != 1 || (qc = qin->queryloc()) == 0 ||
qc[0].index_value == 0) {
stat = LDAP_PARAM_ERROR;
break;
}
qc[0].index_value->get_value(&sub, &len);
if (sub == 0 || len <= 0) {
stat = LDAP_PARAM_ERROR;
break;
}
sbc2buf(myself, sub, len, &b);
bp2buf(myself, &b, ".%s", table->mapping.objName);
objPath = internal_table_name(b.buf, buf);
sfree(b.buf);
if (slen(objPath) <= 0) {
stat = LDAP_OPERATIONS_ERROR;
break;
}
t = (__nis_table_mapping_t *)__nis_find_item_mt(
objPath, &ldapMappingList, 0, 0);
if (t == 0)
break;
if (t->objType == NIS_BOGUS_OBJ)
(void) updateMappingObj(t, 0, 0);
if (wantWrite)
doLDAP = t->isMaster;
else
doLDAP = TRUE;
break;
}
case NIS_BOGUS_OBJ:
t = mappingFromObj(obj, statP);
doLDAP = TRUE;
asObj = TRUE;
break;
default:
t = 0;
doLDAP = FALSE;
asObj = TRUE;
break;
}
if (!doLDAP)
t = 0;
if (asObjP != 0)
*asObjP = asObj;
if (statP != 0)
*statP = stat;
return (t);
}
int
db_mindex::updateTableEntry(entry_object *e, int replace, char *tableName,
nis_object *obj, nis_object *tobj, uint32_t ttime,
int *xid) {
int stat, freeObj = 0;
db_index_entry *dbie;
long count = 0;
bool_t valid = TRUE;
db_result *dbres;
db_query *qi;
nis_object *oldObj = 0;
const char *myself = "db_mindex::updateTableEntry";
if (table == 0 || e == 0)
return (LDAP_PARAM_ERROR);
qi = extract_index_values_from_object(e);
if (qi == 0) {
logmsg(MSG_NOMEM, LOG_ERR,
"%s: Out of memory for query index",
myself);
return (LDAP_NO_MEMORY);
}
dbie = satisfy_query(qi, &count, &valid, FALSE);
if (dbie != 0 && (count != 1 || !valid)) {
logmsg(MSG_NOTIMECHECK, LOG_INFO,
"%s: count=%d, valid=%s",
myself, count, valid ? "TRUE" : "FALSE");
delete qi;
return (LDAP_OPERATIONS_ERROR);
}
if (dbie != 0) {
oldObj = unmakePseudoEntryObj(
table->get_entry(dbie->getlocation()), tobj);
if (oldObj == 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Error getting object from old pseudo-entry for \"%s\" in \"%s\"",
myself, NIL(obj->zo_name),
NIL(tableName));
delete qi;
return (LDAP_OPERATIONS_ERROR);
}
}
if (replace) {
if (dbie != 0 && obj == 0) {
obj = unmakePseudoEntryObj(e, tobj);
if (obj == 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Error getting object from pseudo-entry for \"%s\" in \"%s\"",
myself, NIL(obj->zo_name),
NIL(tableName));
delete qi;
nis_destroy_object(oldObj);
return (LDAP_OPERATIONS_ERROR);
}
freeObj = 1;
}
if (dbie != 0 && sameNisPlusObj(oldObj, obj)) {
table->touchEntry(dbie->getlocation());
delete qi;
if (freeObj)
nis_destroy_object(obj);
nis_destroy_object(oldObj);
return (LDAP_COMPARE_TRUE);
} else {
dbres = ((db *)dbptr.ptr)->log_action(DB_ADD_NOSYNC,
qi, e);
if (dbres == 0)
stat = LDAP_OPERATIONS_ERROR;
else if (dbres->status == DB_SUCCESS)
stat = LDAP_SUCCESS;
else
stat = LDAP_OPERATIONS_ERROR;
db_free_result(dbres);
}
} else {
if (dbie == 0) {
delete qi;
return (LDAP_SUCCESS);
}
dbres = ((db *)dbptr.ptr)->log_action(DB_REMOVE_NOSYNC, qi, 0);
if (dbres == 0)
stat = LDAP_OPERATIONS_ERROR;
else if (dbres->status == DB_SUCCESS)
stat = LDAP_SUCCESS;
else
stat = LDAP_OPERATIONS_ERROR;
db_free_result(dbres);
}
if (stat == LDAP_SUCCESS) {
int ret, numAttrs;
nis_attr *attr, attrbuf[NIS_MAXCOLUMNS];
if (*xid == 0) {
*xid = beginTransaction();
if (*xid == 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Error starting transaction for \"%s\"",
myself, NIL(tableName));
delete qi;
if (oldObj != 0)
nis_destroy_object(oldObj);
return (LDAP_OPERATIONS_ERROR);
}
}
if (replace && obj == 0) {
obj = unmakePseudoEntryObj(e, tobj);
if (obj == 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Error getting object from pseudo-entry for \"%s\" in \"%s\"",
myself, NIL(obj->zo_name),
NIL(tableName));
delete qi;
if (oldObj != 0)
nis_destroy_object(oldObj);
return (LDAP_OPERATIONS_ERROR);
}
freeObj = 1;
}
attr = schemeQuery2nisAttr(qi, attrbuf, scheme,
table->mapping.tm, &numAttrs);
if (attr == 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Error converting index query to nis_attr for \"%s\" in \"%s\"",
myself, NIL(obj->zo_name), NIL(tableName));
if (freeObj)
nis_destroy_object(obj);
if (oldObj != 0)
nis_destroy_object(oldObj);
delete qi;
return (LDAP_OPERATIONS_ERROR);
}
if (replace) {
if (oldObj != 0)
ret = addUpdate(REM_IBASE, tableName,
numAttrs, attr, oldObj, 0, ttime);
else
ret = 0;
if (ret == 0)
ret = addUpdate(ADD_IBASE, tableName,
numAttrs, attr, obj, 0, ttime);
} else {
ret = addUpdate(REM_IBASE, tableName, numAttrs, attr,
oldObj, 0, ttime);
}
if (ret != 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Error adding trans log entry for \"%s\" in \"%s\"",
myself, NIL(obj->zo_name), NIL(tableName));
stat = LDAP_OPERATIONS_ERROR;
}
}
delete qi;
if (oldObj != 0)
nis_destroy_object(oldObj);
if (freeObj)
nis_destroy_object(obj);
return (stat);
}
bool_t
db_mindex::touchEntry(entry_object *e) {
db_query *qi;
bool_t ret;
if (table == 0 || e == 0)
return (FALSE);
qi = extract_index_values_from_object(e);
if (qi == 0)
return (FALSE);
ret = touchEntry(qi);
delete qi;
return (ret);
}
bool_t
db_mindex::touchEntry(db_query *q) {
db_index_entry *dbie;
long count;
bool_t valid;
dbie = satisfy_query(q, &count, &valid, FALSE);
if (dbie != 0 && count == 1 && valid)
table->touchEntry(dbie->getlocation());
else
return (FALSE);
return (TRUE);
}
static __nis_table_mapping_t *
findDirEntryMapping(__nis_table_mapping_t *t, entry_object *e, char **name) {
__nis_table_mapping_t *x;
char *entryName;
const char *myself = "findDirEntryMapping";
__nis_buffer_t b = {0, 0};
if (e == 0 || e->en_cols.en_cols_len != 2 ||
e->en_cols.en_cols_val == 0)
return (0);
entryName = e->en_cols.en_cols_val[1].ec_value.ec_value_val;
if (name != 0)
*name = entryName;
if (t == 0 || entryName == 0 || t->objName == 0)
return (0);
bp2buf(myself, &b, "%s.%s", entryName, t->objName);
if (b.len == 0 || b.buf == 0)
return (0);
x = (__nis_table_mapping_t *)__nis_find_item_mt(b.buf,
&ldapMappingList, 0, 0);
sfree(b.buf);
return (x);
}
int
db_mindex::queryLDAP(db_query *qin, char *dbId, int doAsynch) {
__nis_table_mapping_t *t;
int i, na, nq = 0, stat, stat2, numAttrs, ret;
int xid = 0;
long numEa;
bool_t asObj, doEnum;
db_query *q;
entry_object **ea;
nis_attr attr;
nis_object *dirObj;
db_status dstat;
const char *myself = "db_mindex::queryLDAP";
if (!useLDAPrespository || table == 0)
return (LDAP_SUCCESS);
if (table->mapping.isDeferredTable)
return (LDAP_SUCCESS);
t = selectMapping(table, 0, qin, FALSE, &asObj, &stat);
if (t == 0)
return (stat);
#ifdef NISDB_LDAP_DEBUG
printf("%s: %s (%s)\n",
myself, NIL(t->objName), (asObj ? "object" : "entry"));
#endif
if (qin != NULL) {
q = schemeQuery2Query(qin, scheme);
if (q == 0)
return (LDAP_PARAM_ERROR);
#ifdef NISDB_LDAP_DEBUG
q->print();
#endif
} else {
q = 0;
#ifdef NISDB_LDAP_DEBUG
printf("\tenumerating %s%s%s\n",
dbId ? dbId : "", dbId ? ":" : "", NIL(t->objName));
#endif
}
i = 0;
sfree(selectTableMapping(t, q, 0, asObj, dbId, &i));
if (i <= 0) {
freeQuery(q);
return (LDAP_SUCCESS);
}
if (asObj) {
nis_object *o;
entry_object *e, eo;
entry_col ec[2];
int nea;
stat = objFromLDAP(t, &o, &ea, &nea);
numEa = nea;
if (stat == LDAP_NO_SUCH_OBJECT) {
dstat = dbDeleteObj(t->objName);
if (dstat == DB_SUCCESS || dstat == DB_NOTFOUND) {
stat = LDAP_SUCCESS;
} else {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: DB error %d deleting \"%s\"",
myself, dstat, NIL(t->objName));
stat = LDAP_OPERATIONS_ERROR;
}
freeQuery(q);
return (stat);
} else if (stat != LDAP_SUCCESS) {
freeQuery(q);
return (stat);
} else if (o == 0) {
freeQuery(q);
return (LDAP_SUCCESS);
}
if (q != 0) {
setOid(o);
dstat = dbRefreshObj(t->objName, o);
if (dstat == DB_SUCCESS) {
stat = LDAP_SUCCESS;
} else {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: DB error %d updating \"%s\" in \"%s\"",
myself, NIL(t->objName),
NIL(table->mapping.tm->objName));
stat = LDAP_OPERATIONS_ERROR;
}
freeEntryObjArray(ea, numEa);
freeQuery(q);
nis_destroy_object(o);
return (stat);
}
dirObj = o;
WRITELOCKNR(this, stat, "w db_mindex::queryLDAP");
if (stat == 0) {
WRITELOCKNR(table, stat2,
"table w db_mindex::queryLDAP");
}
if (stat != 0 || stat2 != 0) {
nis_destroy_object(dirObj);
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: lock error %d", myself,
stat != 0 ? stat : stat2);
return (LDAP_OPERATIONS_ERROR);
}
setNoWriteThrough();
setNoLDAPquery();
table->setEnumMode(0);
for (i = 0, na = 0; i < numEa; i++) {
int st;
__nis_table_mapping_t *x;
char *name = 0;
entry_obj *e;
if (ea[i] == 0)
continue;
x = findDirEntryMapping(t, ea[i], &name);
o = 0;
if (x == 0 || (st = objFromLDAP(x, &o, 0, 0)) !=
LDAP_SUCCESS) {
if (x != 0)
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Unable to obtain object for \"%s\" in \"%s\": %s",
myself, NIL(name), NIL(t->objName),
ldap_err2string(st));
if (o != 0)
nis_destroy_object(o);
if (!touchEntry(ea[i])) {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Inconsistency: LDAP-derived directory \"%s\" "
"contains entry \"%s\", which is unknown locally, "
"and has no LDAP mapping",
myself, NIL(t->objName),
NIL(name));
}
continue;
}
if (ea[i]->en_cols.en_cols_len != 2 ||
ea[i]->en_cols.en_cols_val == 0 ||
ea[i]->en_cols.en_cols_val[0].
ec_value.ec_value_val != 0 ||
ea[i]->en_cols.en_cols_val[0].
ec_value.ec_value_len != 0) {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Illegal entry_obj col 0 for \"%s\" in \"%s\"",
myself, NIL(name), NIL(t->objName));
nis_destroy_object(o);
touchEntry(ea[i]);
continue;
}
setOid(o);
e = makePseudoEntryObj(o, ea[i], 0);
if (e == 0) {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Unable to create pseudo entry object for \"%s\" in \"%s\"",
myself, NIL(name), NIL(t->objName));
nis_destroy_object(o);
touchEntry(ea[i]);
continue;
}
st = updateTableEntry(e, 1, t->objName, o, 0,
o->zo_oid.mtime, &xid);
if (st == LDAP_SUCCESS) {
na++;
} else if (st == LDAP_COMPARE_TRUE) {
st = LDAP_SUCCESS;
} else {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Error updating directory entry for \"%s\" in \"%s\": %s",
myself, NIL(name), NIL(t->objName),
ldap_err2string(st));
if (stat == LDAP_SUCCESS)
stat = st;
}
sfree(e->en_cols.en_cols_val[0].
ec_value.ec_value_val);
ea[i]->en_cols.en_cols_val[0].
ec_value.ec_value_val = 0;
ea[i]->en_cols.en_cols_val[0].
ec_value.ec_value_len = 0;
nis_destroy_object(o);
}
freeEntryObjArray(ea, numEa);
ea = table->endEnumMode(&numEa);
if (ea != 0) {
uint32_t nowt = time(0);
for (i = 0; i < numEa; i++) {
int st;
if (ea[i] == 0)
continue;
st = updateTableEntry(ea[i], 0, t->objName, 0,
0, nowt, &xid);
if (st == LDAP_SUCCESS) {
na++;
} else {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Error removing directory entry for \"%s\": %s",
myself, NIL(t->objName),
ldap_err2string(st));
if (stat == LDAP_SUCCESS)
stat = st;
}
}
}
if (stat == LDAP_SUCCESS) {
struct timeval now;
(void) gettimeofday(&now, 0);
table->mapping.enumExpire = now.tv_sec +
table->mapping.ttl;
}
if (na > 0)
(void) ((db *)dbptr.ptr)->sync_log();
if (xid != 0 && na > 0 && stat == LDAP_SUCCESS) {
ret = endTransaction(xid, dirObj);
if (ret != 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Error ending transaction for \"%s\"",
myself, NIL(t->objName));
stat = LDAP_OPERATIONS_ERROR;
}
} else if (xid != 0) {
ret = abort_transaction(xid);
if (ret != 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Error aborting transaction for \"%s\"",
myself, NIL(t->objName));
}
}
nis_destroy_object(dirObj);
sfree(ea);
clearNoLDAPquery();
clearNoWriteThrough();
WRITEUNLOCK2(table, this,
stat, stat,
"table wu db_mindex::queryLDAP",
"wu db_mindex::queryLDAP");
return (stat);
}
if (t->isMaster) {
dirObj = findObj(t->obj->zo_domain, &dstat, &stat);
if (dirObj == 0) {
if (stat == LDAP_SUCCESS)
stat = LDAP_OPERATIONS_ERROR;
return (stat);
}
} else {
dirObj = 0;
}
stat = entriesFromLDAP(t, qin, q, dbId, dirObj, doAsynch);
return (stat);
}
extern db *tableDB(char *);
int
db_mindex::removeLDAP(db_query *qin, nis_object *obj) {
__nis_table_mapping_t *t;
db_query *q;
bool_t asObj;
int stat;
if (!useLDAPrespository || table == 0)
return (LDAP_SUCCESS);
if (table->mapping.isDeferredTable)
return (LDAP_SUCCESS);
t = selectMapping(table, 0, qin, TRUE, &asObj, &stat);
if (t == 0 && stat != LDAP_SUCCESS)
return (stat);
#ifdef NISDB_LDAP_DEBUG
if (t != 0)
printf("removeLDAP: %s\n", NIL(t->objName));
#endif
if (qin != NULL) {
if (asObj) {
if (t == 0) {
t = selectMapping(0, obj, 0, TRUE, &asObj,
&stat);
if (t == 0 && stat != LDAP_SUCCESS)
return (stat);
}
if (t != 0) {
stat = deleteLDAPobj(t);
if (stat == LDAP_SUCCESS)
(void) replaceMappingObj(t, 0);
else
return (stat);
}
stat = storeLDAP(0, 0, 0, 0, 0);
} else {
q = schemeQuery2Query(qin, scheme);
if (q == 0)
return (LDAP_PARAM_ERROR);
#ifdef NISDB_LDAP_DEBUG
q->print();
#endif
stat = mapToLDAP(t, 1, &q, 0, 0, 0, 0);
freeQuery(q);
}
} else {
#ifdef NISDB_LDAP_DEBUG
abort();
#endif
stat = LDAP_PARAM_ERROR;
}
return (stat);
}
int
db_mindex::storeObjLDAP(__nis_table_mapping_t *t, nis_object *o) {
int stat, assigned = 0;
entry_object **ea;
int numEa, doUnlock = 0;
db *dbase = 0;
db_mindex *dbm = 0;
const char *myself = "db_mindex::storeObjLDAP";
if (t == 0 || o == 0)
return (LDAP_SUCCESS);
if (o->zo_data.zo_type == NIS_DIRECTORY_OBJ) {
dbase = tableDB(t->objName);
if (dbase != 0)
dbm = dbase->mindex();
if (dbase == 0 || dbm == 0 || dbm->table == 0) {
ea = 0;
numEa = 0;
dbase = 0;
} else {
entry_object **tea;
long i, ntea;
READLOCK(dbm->table, LDAP_OPERATIONS_ERROR,
"r table db_mindex::storeLDAP");
doUnlock = 1;
tea = dbm->table->gettab();
ntea = dbm->table->getsize();
if (tea != 0 && ntea > 0) {
ea = (entry_object **)am(myself,
ntea * sizeof (ea[0]));
if (ea == 0) {
READUNLOCK(dbm->table, LDAP_NO_MEMORY,
"ru table db_mindex::storeLDAP");
return (LDAP_NO_MEMORY);
}
for (i = 0, numEa = 0; i < ntea; i++) {
if (tea[i] != 0) {
ea[numEa] = tea[i];
numEa++;
}
}
if (numEa == 0) {
sfree(ea);
ea = 0;
READUNLOCK(dbm->table,
LDAP_OPERATIONS_ERROR,
"ru table db_mindex::storeLDAP");
doUnlock = 0;
}
} else {
ea = 0;
numEa = 0;
READUNLOCK(dbm->table,
LDAP_OPERATIONS_ERROR,
"ru table db_mindex::storeLDAP");
doUnlock = 0;
}
}
} else {
ea = 0;
numEa = 0;
}
stat = objToLDAP(t, o, ea, numEa);
if (ea != 0)
sfree(ea);
if (doUnlock) {
READUNLOCK(dbm->table, stat,
"ru table db_mindex::storeLDAP");
}
return (stat);
}
int
db_mindex::storeLDAP(db_query *qin, entry_object *obj, nis_object *o,
entry_obj *oldObj, char *dbId) {
__nis_table_mapping_t *t;
bool_t asObj;
db_query *q, *qo, **qa;
__nis_rule_value_t *rv = 0;
int stat;
const char *myself = "db_mindex::storeLDAP";
if (!useLDAPrespository || table == 0)
return (LDAP_SUCCESS);
if (table->mapping.isDeferredTable)
return (LDAP_SUCCESS);
t = selectMapping(table, 0, qin, TRUE, &asObj, &stat);
if (t == 0 && stat != LDAP_SUCCESS)
return (stat);
#ifdef NISDB_LDAP_DEBUG
if (t != 0)
printf("storeLDAP: %s%s%s\n",
dbId ? dbId : "", dbId ? ":" : "", NIL(t->objName));
#endif
if (asObj) {
if (o != 0) {
if (o->zo_data.zo_type == NIS_ENTRY_OBJ)
asObj = FALSE;
} else if (obj != 0) {
if (obj->en_type == 0 ||
strcmp(obj->en_type, "IN_DIRECTORY") != 0)
asObj = FALSE;
}
}
if (asObj) {
bool_t freeO = FALSE;
if (t == 0) {
if (o == 0 && obj != 0) {
o = unmakePseudoEntryObj(obj, 0);
if (o == 0)
return (LDAP_OPERATIONS_ERROR);
freeO = TRUE;
}
if (o != 0) {
t = selectMapping(0, o, 0, TRUE, &asObj, &stat);
if (t == 0) {
if (freeO)
nis_destroy_object(o);
return (stat);
}
}
}
if (t != 0) {
if (o == 0) {
if (obj != 0) {
o = unmakePseudoEntryObj(obj, 0);
freeO = TRUE;
} else {
db_status dstat;
o = dbFindObject(t->objName, &dstat);
if (o == 0)
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: DB error %d finding \"%s\"",
myself,
NIL(t->objName));
freeO = TRUE;
}
}
if (o == 0)
return (LDAP_OPERATIONS_ERROR);
stat = storeObjLDAP(t, o);
if (!freeO) {
o = nis_clone_object(o, 0);
if (o == 0)
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Unable to refresh mapping object for \"%s\"",
myself, NIL(t->objName));
}
if (o != 0) {
if (!replaceMappingObj(t, o))
nis_destroy_object(o);
}
o = 0;
if (stat != LDAP_SUCCESS)
return (stat);
}
if (freeO && o != 0) {
nis_destroy_object(o);
o = 0;
}
if (obj == 0 || obj->en_type == 0 ||
strcmp(obj->en_type, "IN_DIRECTORY") != 0)
return (LDAP_SUCCESS);
t = selectMapping(table, 0, 0, TRUE, &asObj, &stat);
if (t == 0)
return (stat);
stat = storeObjLDAP(t, t->obj);
return (stat);
}
if (t == 0)
return (LDAP_SUCCESS);
if (qin != NULL && obj != NULL) {
db_index_entry *dbie;
int i, size, nq = 0;
long l, count;
bool_t valid;
db_query qbuf, **qold;
rv = (__nis_rule_value_t *)am(myself, sizeof (*rv));
qa = (db_query **)am(myself, sizeof (qa[0]));
if (oldObj != 0) {
qold = (db_query **)am(myself, sizeof (qold[0]));
} else {
qold = 0;
}
if (rv == 0 || qa == 0 || (oldObj != 0 && qold == 0)) {
sfree(rv);
sfree(qa);
sfree(qold);
return (LDAP_NO_MEMORY);
}
q = schemeQuery2Query(qin, scheme);
if (q == 0) {
sfree(rv);
sfree(qa);
return (LDAP_PARAM_ERROR);
}
qa[0] = pseudoEntryObj2Query(obj, t->obj, &rv[0]);
if (qa[0] == 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Unable to obtain query representation of new entry object for \"%s\"",
myself, NIL(t->dbId));
freeQuery(q);
sfree(rv);
sfree(qa);
sfree(qold);
return (LDAP_OPERATIONS_ERROR);
}
if (oldObj != 0) {
qold[0] = pseudoEntryObj2Query(oldObj, t->obj, 0);
if (qold[0] == 0) {
logmsg(MSG_NOTIMECHECK, LOG_ERR,
"%s: Unable to obtain query representation of old entry object for \"%s\"",
myself, NIL(t->dbId));
freeQueries(qa, 1);
freeQuery(q);
sfree(rv);
sfree(qa);
sfree(qold);
return (LDAP_OPERATIONS_ERROR);
}
}
nq++;
size = qin->size();
for (i = 0; i < size; i++) {
db_query *qc, **qat, **qoldt;
long j;
__nis_rule_value_t *rvt;
qc = queryFromComponent(qin, i, &qbuf);
if (qc == 0)
continue;
dbie = satisfy_query_dbonly(qc, &count, FALSE, &valid);
if (dbie == 0 || !valid || count <= 0)
continue;
rvt = (__nis_rule_value_t *)realloc(rv,
(nq+count) * sizeof (rv[0]));
qat = (db_query **)realloc(qa,
(nq+count) * sizeof (qa[0]));
if (qold != 0)
qoldt = (db_query **)realloc(qold,
(nq+count) * sizeof (qold[0]));
if (rvt == 0 || qat == 0 || (qold != 0 && qoldt == 0)) {
if (qat == 0)
freeQueries(qa, nq);
else
freeQueries(qat, nq);
if (rvt == 0)
freeRuleValue(rv, nq);
else
freeRuleValue(rvt, nq);
if (qold != 0) {
if (qoldt == 0)
freeQueries(qold, 1);
else
freeQueries(qoldt, 1);
}
freeQuery(q);
(void) memset(&qbuf, 0, sizeof (qbuf));
logmsg(MSG_NOMEM, LOG_ERR,
"%s: realloc(%d) failed",
myself, (nq+count) * sizeof (void *));
return (LDAP_NO_MEMORY);
}
rv = rvt;
qa = qat;
(void) memset(&rv[nq], 0, count * sizeof (rv[0]));
(void) memset(&qa[nq], 0, count * sizeof (qa[0]));
if (qold != 0) {
qold = qoldt;
(void) memset(&qold[nq], 0,
count * sizeof (qold[0]));
}
for (j = 0; j < count; j++) {
qa[nq] = pseudoEntryObj2Query(
table->get_entry(dbie->getlocation()),
t->obj, &rv[nq]);
if (qa[nq] == 0) {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Could not create query from entry obj for \"%s\"",
myself, NIL(t->objName));
freeQueries(qa, nq);
freeQueries(qold, 1);
freeRuleValue(rv, nq);
freeQuery(q);
(void) memset(&qbuf, 0, sizeof (qbuf));
return (LDAP_PARAM_ERROR);
}
if (qold != 0)
qold[nq] = qa[nq];
nq++;
dbie = dbie->getnextresult();
if (dbie == 0)
break;
}
}
stat = mapToLDAP(t, nq, (qold != 0 ? qold : qa), qa, rv, 1,
dbId);
freeQueries(qa, nq);
freeRuleValue(rv, nq);
freeQuery(q);
freeQueries(qold, 1);
(void) memset(&qbuf, 0, sizeof (qbuf));
} else if (qin == 0 && obj == 0 && t->objType == NIS_TABLE_OBJ) {
long i, j, ntab;
entry_object **tab;
READLOCK(table, LDAP_OPERATIONS_ERROR,
"r table db_mindex::storeLDAP");
tab = table->gettab();
ntab = table->getsize();
if (tab == 0 || ntab <= 0) {
READUNLOCK(table, LDAP_OPERATIONS_ERROR,
"ru table db_mindex::storeLDAP");
return (LDAP_SUCCESS);
}
qa = (db_query **)am(myself, ntab * sizeof (qa[0]));
rv = (__nis_rule_value_t *)am(myself, ntab * sizeof (rv[0]));
if (qa == 0 || rv == 0) {
sfree(qa);
sfree(rv);
READUNLOCK(table, LDAP_OPERATIONS_ERROR,
"ru table db_mindex::storeLDAP");
return (LDAP_NO_MEMORY);
}
for (i = 0; i < ntab; i++) {
if (tab[i] == 0)
continue;
qa[i] = pseudoEntryObj2Query(tab[i], t->obj, &rv[i]);
if (qa[i] == 0) {
freeQueries(qa, i);
freeRuleValue(rv, i);
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: Could not create query from entry for \"%s\"",
myself, NIL(t->objName));
READUNLOCK(table, LDAP_OPERATIONS_ERROR,
"ru table db_mindex::storeLDAP");
return (LDAP_OPERATIONS_ERROR);
}
}
stat = mapToLDAP(t, ntab, qa, qa, rv, 0, dbId);
freeQueries(qa, ntab);
freeRuleValue(rv, ntab);
if (stat == LDAP_SUCCESS) {
struct timeval now;
int lstat, lck = 1;
(void) gettimeofday(&now, 0);
WRITELOCKNR(table, lstat,
"w table db_mindex::storeLDAP");
if (lstat == 0) {
table->mapping.enumExpire = now.tv_sec +
table->mapping.ttl;
lck = 0;
WRITEUNLOCKNR(table, lstat,
"wu table db_mindex::storeLDAP");
}
if (lstat != 0) {
logmsg(MSG_NOTIMECHECK, LOG_WARNING,
"%s: %sock error %d for \"%s\"%s",
myself, lck?"L":"Unl", lstat,
NIL(t->objName),
lck ?
"; unable to update enumeration expiration":
"");
}
}
READUNLOCK(table, stat,
"ru table db_mindex::storeLDAP");
}
return (stat);
}
static void
setOid(nis_object *obj) {
if (obj != 0) {
obj->zo_oid.ctime = obj->zo_oid.mtime = time(0);
}
}