/*
* 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
*/
/*
*/
#include <strings.h>
#include <string.h>
#include <lber.h>
#include <ldap.h>
#include "db_item_c.h"
#include "nisdb_mt.h"
#include "ldap_util.h"
#include "ldap_structs.h"
#include "ldap_val.h"
#include "ldap_ruleval.h"
#include "ldap_op.h"
#include "ldap_nisdbquery.h"
#include "ldap_attr.h"
#include "ldap_xdr.h"
item *
if (i == 0)
return (0);
/*
* To this function, a NULL value, or a length less than or equal
* zero means an item with no value. Hence, buildItem(0, 0) is
* _not_ the right way to create index_value == 0 to indicate
* deletion.
*/
i->itemvalue.itemvalue_len = 0;
i->itemvalue.itemvalue_val = 0;
return (i);
}
/*
* NIS+ usually stores the terminating NUL for strings, so we add
* it here just in case. This means we usually waste a byte for
* binary column values...
*/
mlen++;
free(i);
return (0);
}
return (i);
}
void
if (i != 0) {
free(i);
}
}
void
if (qc == 0)
return;
if (doFree)
}
/*
* Clone a db_query. The 'numComps' parameter can be used to specify
* the number of db_qcomp's to allocate (in the 'components.components_val'
* array), if 'components.components_len' hasn't yet reached its expected
* maximum value.
*/
db_query *
int i;
if (old == 0)
return (0);
if (new == 0)
return (0);
numComps);
return (0);
}
continue;
}
if (it == 0) {
return (0);
}
}
return (new);
}
void
int i;
if (q == 0)
return;
for (i = 0; i < q->components.components_len; i++) {
}
sfree(q);
}
void
int i;
if (q == 0)
return;
for (i = 0; i < numQ; i++)
freeQuery(q[i]);
sfree(q);
}
void
if (q == 0)
return;
/*
* Collect the values, which may be out of order in 'q'.
* Remember the largest index.
*/
for (i = 0; i < q->components.components_len; i++) {
if (ix >= NIS_MAXCOLUMNS ||
(t != 0 && ix >= t->numColumns))
continue;
}
/* Print the values we collected */
for (i = 0; i <= mc; i++) {
}
/* If we printed anything, add a newline */
if (mc >= 0)
}
/*
* Verify that the db_query's 'q' and 'fq' match, in the sense that if
* they both have a value for a certain index, the values are the same.
*/
int
int i, j, match;
if (fq == 0)
return (1);
if (q == 0)
return ((fq == 0) ? 1 : 0);
i++) {
/* Same index ? */
continue;
/*
* If one 'index_value' is NULL, the other one must
* be NULL as well.
*/
index_value == 0)
continue;
else {
match = 0;
break;
}
}
0) {
match = 0;
break;
}
/* Same value lengths ? */
/*
* There's a twist here: the input query
* may well _not_ count a concluding NUL
* in a string value, while the output
* usually will. So, if the difference in
* length is one, and the "extra" byte is
* a zero-valued one, we accept equality.
* 'q' is assumed to be the output, and
* 'fq' the input.
*/
q->components.components_val[i].
match = 0;
break;
}
}
/* Same value ? */
flen) != 0) {
match = 0;
break;
}
}
}
return (match);
}
/*
* Remove those queries in 'q' that don't match t->index.
* Returns a pointer to the filtered array, which could be
* a compacted version of the original, or a new copy; in
* the latter case, the original will have been freed.
*
*/
db_query **
if ((t == 0 && qin == 0) || q == 0 ||
numQueries == 0 || *numQueries <= 0)
return (q);
nq = *numQueries;
if (objAttr != 0)
else
attr = 0;
freeQueries(q, nq);
if (objAttr != 0) {
*objAttr = 0;
}
*numQueries = -1;
return (0);
}
if (t != 0)
retain = verifyIndexMatch(t, q[i], 0, 0, 0);
if (retain) {
if (objAttr != 0)
nn++;
} else {
freeQuery(q[i]);
q[i] = 0;
if (objAttr != 0) {
freeSingleObjAttr((*objAttr)[i]);
(*objAttr)[i] = 0;
}
}
}
/* All q[i]'s are either in 'new', or have been deleted */
free(q);
if (objAttr != 0) {
}
*numQueries = nn;
return (new);
}
db_query **
int *numQueries) {
int r, i, j, ir;
int numItems;
char **dn = 0;
int numDN = 0;
return (0);
/* Establish default, per-thread, search base */
for (r = 0, nq = 0; r < t->numRulesFromLDAP; r++) {
if (rval == 0)
continue;
&numItems);
if (litem == 0) {
/* XXX Should this be a fatal error ? */
continue;
}
lval = 0;
for (i = 0; i < numItems; i++) {
/*
* If the LHS specifies an out-of-context LDAP or
* NIS+ item, we do the update right here. We
* don't add any values to 'lval'; instead, we
* skip to the next item. (However, we still
* get a string representation of the LHS in case
* we need to report an error.)
*/
int stat;
if (dn == 0)
&numDN);
if (stat != LDAP_SUCCESS) {
if (tmpval != 0 &&
"%s: LDAP store \"%s\": %s",
}
continue;
}
}
continue;
}
/*
* We now have a number of possible cases. The notation
* used in the table is:
*
* single A single value (numVals == 1)
* multi[N] N values
* multi[N]/rep M values with repeat == 1
* (M) M resulting db_query's
*
* single (1) (1) (1) (1)
* multi[M] (1) (1) (1) 1+(N-1)/M
* multi[M]/rep (1) (1) (1) 1+(N-1)/M
*
* Of course, we already have 'nq' db_query's from previous
* rules, so the resulting number of queries is max(1,nq)
* times the numbers in the table above.
*/
/* The number of queries resulting from the current rule */
else
nrq = 1;
} else {
nrq = 1;
}
/* Total number of queries after adding the current rule */
if (nq <= 0)
else
"%s: realloc(%d) => NULL",
return (0);
}
}
/*
* remembering that realloc() has done the first 'nq'
* ones.
*
* If there's an error (probably memory allocation), we
* still go through the rest of the array, so that it's
* simple to free the elements when we clean up.
*/
for (j = 0; j < nq; j++) {
t->numColumns);
query[j] != 0)
err++;
attr[j] != 0)
err++;
}
}
if (err > 0) {
return (0);
}
/*
* Special case if nq == 0 (i.e., the first time we
* allocated db_query's). If so, we now allocate empty
* db_qcomp arrays, which simplifies subsequent
* copying of values.
*/
if (nq <= 0) {
if (query[i] == 0) {
err++;
break;
}
err++;
break;
}
}
if (err > 0) {
return (0);
}
}
/* Now we're ready to add the new values */
char *oaName = 0;
int index;
/* Find column index */
index++) {
break;
}
if (index >= t->numColumns) {
/*
* Could be one of the special object
* attributes.
*/
if (oaName == 0)
continue;
}
int k;
/* If we're out of values, repeat last one */
/*
* Step through the query array, adding
* the new value every 'nrq' queries, and
* starting at 'query[j % nrq]'.
*/
int ic, c;
if (oaName != 0) {
&attr[k]);
if (fail) {
err++;
break;
}
continue;
}
/*
* If we've already filled this
* query, the new value is a dup
* which we'll ignore.
*/
if (ic >= t->numColumns)
continue;
/*
* Do we already have a value for
* this 'index' ?
*/
for (c = 0; c < ic; c++) {
if (query[k]->components.
components_val[c].
which_index == index)
break;
}
/* If no previous value, add it */
if (c >= ic) {
int l;
char *v;
query[k]->components.
which_index = index;
l > 0 &&
v[l-1] != '\0' &&
v[l] == '\0')
l++;
query[k]->components.
buildItem(l, v);
if (query[k]->
index_value == 0) {
err++;
break;
}
query[k]->components.
}
}
if (err > 0) {
return (0);
}
}
}
}
if (nq <= 0) {
query = 0;
}
/* Should we filter on index or input query ? */
if (query != 0) {
if (t->index.numIndexes > 0)
else if (qin != 0)
}
if (query != 0 && numQueries != 0)
*numQueries = nq;
if (objAttr != 0)
else
return (query);
}
/*
* Given a table mapping and a rule-value, convert to an array of
* (db_query *), using the fromLDAP ruleset.
*
* On entry, '*numQueries' holds the number of elements in the 'rv'
* array. On exit, it holds the number of (db_query *)'s in the return
* value array.
*/
db_query **
if (t == 0 || rv == 0 || numQueries == 0)
return (0);
nv = *numQueries;
if (nv <= 0)
return (0);
/*
* 'qp' is an array of (db_query **), and we get one element for
* each call to createNisPlusEntry(); i.e., one for each rule-value.
*
* 'nnp[i]' is the count of (db_query *) in each 'qp[i]'.
*/
return (0);
}
/* If we fail, abort (XXX??? or continue ???) */
goto cleanup;
nqp++;
}
/* If we didn't get any (db_query **)'s, return failure */
goto cleanup;
if (q == 0 || attr == 0) {
nq = 0;
goto cleanup;
}
/* Convert 'qp' to an array of (db_query *)'s */
}
*numQueries = nq;
if (objAttr != 0)
else
/* Make sure 'cleanup' doesn't free the db_query pointers */
nqp = 0;
for (i = 0; i < nqp; i++) {
}
return (q);
}
db_query *
int nc, i;
return (0);
/*
* If 'rvP' is non-NULL, build a rule value from the pseudo-
* nis_object in e->en_cols.en_cols_val[0].
*/
if (rv != 0) {
nis_object *o;
o = unmakePseudoEntryObj(e, tobj);
if (o == 0)
return (0);
rvt = addObjAttr2RuleValue(o, 0);
if (rvt == 0)
return (0);
}
/*
* If there are no columns (other than the pseudo-entry object),
* we're done.
*/
if (nc == 0)
return (qbuf);
if (qcbuf == 0) {
if (rvt != 0)
return (0);
}
/*
* Build the db_query, remembering that e->en_cols.en_cols_val[0]
* is the pseudo-nis_object.
*/
for (i = 0; i < nc; i++) {
qcbuf[i].which_index = i;
if (qcbuf[i].index_value == 0) {
if (rvt != 0)
return (0);
}
}
if (rvt != 0) {
}
return (qbuf);
}
/*
* Given an input query 'q', and a db_query work buffer 'qbuf', return
* a pointer to a query with one component corresponding to component
* 'index' in 'q'.
*
* Note that no memory is allocated, and that the returned query has
* pointers into 'q'.
*/
db_query *
qbuf == 0)
return (0);
return (qbuf);
}