Print this page
5910 libnisdb won't build with modern GCC
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libnisdb/ldap_nisdbquery.c
+++ new/usr/src/lib/libnisdb/ldap_nisdbquery.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 + * Copyright 2015 Gary Mills
22 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 24 * Use is subject to license terms.
24 25 */
25 26
26 27
27 28 #include <strings.h>
28 29 #include <string.h>
29 30 #include <lber.h>
30 31 #include <ldap.h>
31 32
32 33 #include "db_item_c.h"
33 34
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
34 35 #include "nisdb_mt.h"
35 36
36 37 #include "ldap_util.h"
37 38 #include "ldap_structs.h"
38 39 #include "ldap_val.h"
39 40 #include "ldap_ruleval.h"
40 41 #include "ldap_op.h"
41 42 #include "ldap_nisdbquery.h"
42 43 #include "ldap_attr.h"
43 44 #include "ldap_xdr.h"
45 +#include "ldap_ldap.h"
44 46
45 47
46 48 item *
47 49 buildItem(int len, void *value) {
48 50 char *myself = "buildItem";
49 51 item *i = am(myself, sizeof (*i));
50 52 int mlen = len;
51 53
52 54 if (i == 0)
53 55 return (0);
54 56
55 57 /*
56 58 * To this function, a NULL value, or a length less than or equal
57 59 * zero means an item with no value. Hence, buildItem(0, 0) is
58 60 * _not_ the right way to create index_value == 0 to indicate
59 61 * deletion.
60 62 */
61 63 if (value == 0 || len <= 0) {
62 64 i->itemvalue.itemvalue_len = 0;
63 65 i->itemvalue.itemvalue_val = 0;
64 66 return (i);
65 67 }
66 68
67 69 /*
68 70 * NIS+ usually stores the terminating NUL for strings, so we add
69 71 * it here just in case. This means we usually waste a byte for
70 72 * binary column values...
71 73 */
72 74 if (len > 0 && ((char *)value)[len-1] != '\0')
73 75 mlen++;
74 76
75 77 i->itemvalue.itemvalue_len = len;
76 78 i->itemvalue.itemvalue_val = am(myself, mlen);
77 79 if (mlen > 0 && i->itemvalue.itemvalue_val == 0) {
78 80 free(i);
79 81 return (0);
80 82 }
81 83 memcpy(i->itemvalue.itemvalue_val, value, len);
82 84
83 85 return (i);
84 86 }
85 87
86 88 void
87 89 freeItem(item *i) {
88 90 if (i != 0) {
89 91 sfree(i->itemvalue.itemvalue_val);
90 92 free(i);
91 93 }
92 94 }
93 95
94 96 void
95 97 freeQcomp(db_qcomp *qc, int doFree) {
96 98
97 99 if (qc == 0)
98 100 return;
99 101
100 102 freeItem(qc->index_value);
101 103 if (doFree)
102 104 free(qc);
103 105 }
104 106
105 107 db_query *
106 108 buildQuery(int num_components, db_qcomp *components) {
107 109 char *myself = "buildQuery";
108 110 db_query *q = am(myself, sizeof (*q));
109 111
110 112 if (q == 0)
111 113 return (0);
112 114
113 115 q->components.components_len = num_components;
114 116 q->components.components_val = components;
115 117
116 118 return (q);
117 119 }
118 120
119 121 /*
120 122 * Clone a db_query. The 'numComps' parameter can be used to specify
121 123 * the number of db_qcomp's to allocate (in the 'components.components_val'
122 124 * array), if 'components.components_len' hasn't yet reached its expected
123 125 * maximum value.
124 126 */
125 127 db_query *
126 128 cloneQuery(db_query *old, int numComps) {
127 129 db_query *new;
128 130 int i;
129 131 char *myself = "cloneQuery";
130 132
131 133 if (old == 0)
132 134 return (0);
133 135
134 136 new = am(myself, sizeof (*new));
135 137 if (new == 0)
136 138 return (0);
137 139
138 140 if (old->components.components_len > numComps)
139 141 numComps = old->components.components_len;
140 142
141 143 new->components.components_val = am(myself,
142 144 sizeof (new->components.components_val[0]) *
143 145 numComps);
144 146 if (numComps > 0 && new->components.components_val == 0) {
145 147 free(new);
146 148 return (0);
147 149 }
148 150
149 151 for (i = 0; i < old->components.components_len; i++) {
150 152 item *it;
151 153
152 154 if (old->components.components_val[i].index_value == 0) {
153 155 new->components.components_val[i].index_value = 0;
154 156 new->components.components_val[i].which_index =
155 157 old->components.components_val[i].which_index;
156 158 continue;
157 159 }
158 160
159 161 it = buildItem(old->components.components_val[i].index_value->
160 162 itemvalue.itemvalue_len,
161 163 old->components.components_val[i].index_value->
162 164 itemvalue.itemvalue_val);
163 165
164 166 if (it == 0) {
165 167 new->components.components_len = i + 1;
166 168 freeQuery(new);
167 169 return (0);
168 170 }
169 171
170 172 new->components.components_val[i].index_value = it;
171 173 new->components.components_val[i].which_index =
172 174 old->components.components_val[i].which_index;
173 175 }
174 176
175 177 new->components.components_len = old->components.components_len;
176 178
177 179 return (new);
178 180 }
179 181
180 182 void
181 183 freeQuery(db_query *q) {
182 184 int i;
183 185
184 186 if (q == 0)
185 187 return;
186 188
187 189 for (i = 0; i < q->components.components_len; i++) {
188 190 freeItem(q->components.components_val[i].index_value);
189 191 }
190 192
191 193 sfree(q->components.components_val);
192 194 sfree(q);
193 195 }
194 196
195 197 void
196 198 freeQueries(db_query **q, int numQ) {
197 199 int i;
198 200
199 201 if (q == 0)
200 202 return;
201 203
202 204 for (i = 0; i < numQ; i++)
203 205 freeQuery(q[i]);
204 206
205 207 sfree(q);
206 208 }
207 209
208 210 /*
209 211 * Given an array index[0..num-1] of pointers to strings of the form
210 212 * "name=value", create the corresponding db_queries. "name=" indicates
211 213 * deletion, which results in a db_query component where index_value == 0.
212 214 *
213 215 * The __nis_table_mapping_t structure is used to translate column
214 216 * names to indices.
215 217 *
216 218 * If 'rvP' is non-NULL, the searchable columns from the 'index'
↓ open down ↓ |
163 lines elided |
↑ open up ↑ |
217 219 * name/value pairs are used to retrieve copies of the corresponding NIS+
218 220 * entries, and '*rvP' is initialized with the current entry values
219 221 * and object attributes. Names/values supplied in 'index' override
220 222 * those from existing NIS+ entries.
221 223 */
222 224 db_query **
223 225 createQuery(int num, char **index, __nis_table_mapping_t *t,
224 226 __nis_rule_value_t **rvP, int *numVals) {
225 227 db_query **q;
226 228 db_qcomp *qc;
227 - int i, j, n, a, nv, niv, stat, sinum;
229 + int i, j, n, a, nv, niv;
228 230 __nis_rule_value_t *rvq;
229 231 __nis_buffer_t b = {0, 0};
230 232 char *table = 0;
231 233 char *myself = "createQuery";
232 234
233 235 rvq = initRuleValue(1, 0);
234 236 if (rvq == 0)
235 237 return (0);
236 238
237 239 if (numVals == 0)
238 240 numVals = &nv;
239 241 *numVals = 0;
240 242
241 243 if (rvP != 0) {
242 244 /*
243 245 * Try to obtain a copy of the table object, in order to
244 246 * determine the searchable columns. A failure isn't
245 247 * necessarily fatal; we just try to compose the entire
246 248 * LDAP data from the col=val pairs.
247 249 */
248 250 table = fullObjName(F, t->objName);
249 251 if (table == 0) {
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
250 252 logmsg(MSG_NOTIMECHECK, LOG_ERR,
251 253 "%s: Error converting \"%s\" to FQ object name",
252 254 myself, NIL(t->objName));
253 255 freeRuleValue(rvq, 1);
254 256 return (0);
255 257 }
256 258 }
257 259
258 260 /* Create a rule-value from the col=val pairs */
259 261 for (n = 0; n < num; n++) {
260 - char *name;
261 262 char *value;
262 263
263 264 if ((value = strchr(index[n], '=')) == 0) {
264 265 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
265 266 "%s: no '=' in \"%s\"",
266 267 myself, index[n]);
267 268 continue;
268 269 }
269 270
270 271 *value = '\0';
271 272 value++;
272 273
273 274 for (a = 0; a < t->numColumns; a++) {
274 275 if (strcmp(index[n], t->column[a]) == 0) {
275 - int i, len = slen(value)+1;
276 276
277 277 /* Add col=val pair to 'rvq' */
278 278 if (addSCol2RuleValue(index[n], value, rvq)) {
279 279 freeRuleValue(rvq, 1);
280 280 sfree(table);
281 281 return (0);
282 282 }
283 283
284 284 break;
285 285 }
286 286 }
287 287 if (a >= t->numColumns) {
288 288 logmsg(MSG_NOTIMECHECK, LOG_WARNING,
289 289 "%s: Ignoring unknown column \"%s\"",
290 290 myself, NIL(index[n]));
291 291 }
292 292 }
293 293
294 294 /*
295 295 * Find out if any of the columns specified via the 'index'
296 296 * array are multi-valued.
297 297 */
298 298 for (n = 0, niv = 1; n < rvq->numColumns; n++) {
299 299 if (rvq->colVal[n].numVals > 1)
300 300 niv *= rvq->colVal[n].numVals;
301 301 }
302 302
303 303 *numVals = 1;
304 304
305 305 sfree(b.buf);
306 306 sfree(table);
307 307
308 308 if (rvq->numColumns <= 0) {
309 309 freeRuleValue(rvq, *numVals);
310 310 *numVals = 0;
311 311 return (0);
312 312 }
313 313
314 314 /*
315 315 * If any column name was repeated in the col=val pairs (but with
316 316 * different values), 'rvq' will have one or more multi-valued
317 317 * column values. We now convert those into an array of rule-values
318 318 * where every column is single-valued.
319 319 *
320 320 * Since we want all combinations of column values, the number
321 321 * of array elements is the product of all column value counts.
322 322 *
323 323 * There are four possible combinations of 'index' and NIS+ data:
324 324 *
325 325 * (1) Only single-valued 'index' columns, and at most one NIS+
326 326 * entry, so 'rvq' is complete, and '*numVals' == 1.
327 327 *
328 328 * (2) Single-valued 'index' columns, but multiple NIS+ entries.
329 329 * '*numVals' reflects the number of NIS+ entries, and no
330 330 * expansion of 'index' column values to array elements is
331 331 * needed.
332 332 *
333 333 * (3) At least one multi-valued 'index', and multiple NIS+
334 334 * entries. We already rejected the NIS+ data for this case
335 335 * above, so it is in fact equivalent to case (4).
336 336 *
337 337 * (4) At least one multi-valued 'index', but at most one NIS+
338 338 * entry. This is the case where we must expand the multi-valued
339 339 * columns to multiple array elements.
340 340 */
341 341 if (niv > 1 && *numVals == 1) {
342 342 __nis_rule_value_t *rv;
343 343 int repeat;
344 344
345 345 /*
346 346 * By using initRuleValue() to create 'rv', and make each
347 347 * element a clone of 'rvq', we save a lot of code. The
348 348 * down side is that 'rv' only really needs one element
349 349 * for each rv[].colVal[].val array, but we know that at
350 350 * least one rvq->colVal[].val array has more than one
351 351 * element. Hence, making 'rv' a clone of 'rvq' will waste
352 352 * memory.
353 353 *
354 354 * However, we believe this waste is acceptable, because
355 355 * we expect that 'niv' will be small. Also, we are executing
356 356 * in the context of a utility command, not in a daemon.
357 357 */
358 358 rv = initRuleValue(niv, rvq);
359 359 if (rv == 0) {
360 360 freeRuleValue(rvq, 1);
361 361 *numVals = 0;
362 362 return (0);
363 363 }
364 364
365 365 /*
366 366 * For each column value in 'rvq', copy to the appropriate
367 367 * place in 'rv', so that the end result is that all
368 368 * combinations of values are enumerated, and each
369 369 * 'rv[n].colVal[i]' is single-valued.
370 370 *
371 371 * We do this by traversing the rv[] array 'rvq->numColumns'
372 372 * times, where each traversal 'i' works on the values
373 373 * for rvq->colVal[i]. A repeat factor 'repeat' starts out
374 374 * at '1', and is multiplied by 'rvq->colVal[i].numVals'
375 375 * at the end of each traversal. Every value
376 376 * rvq->colVal[i].val[j] is repeated 'repeat' times.
377 377 *
378 378 * This algorithm works by regarding the rv[] array as
379 379 * an I-dimensional array (I = rvq->numColumns), where
380 380 * each dimension 'i' corresponds to the values for
381 381 * rvq->colVal[i]. The I-dimensional array is stored
382 382 * in column-major order.
383 383 *
384 384 * Since the 'rv' elements start out as copies of 'rvq',
385 385 * we achieve the "copy" of the 'rvq' column values by
386 386 * deleting those we don't want from the 'rv' elements.
387 387 */
388 388 for (i = 0, repeat = 1; i < rvq->numColumns; i++) {
389 389 int r, k;
390 390 for (n = 0, j = 0, r = 0; n < niv; n++) {
391 391 /*
392 392 * Free all but element 'j' of the
393 393 * rv[n].colVal[i].val array.
394 394 */
395 395 for (k = 0; k < rv[n].colVal[i].numVals; k++) {
396 396 /* Leave element 'j' in place */
397 397 if (k == j)
398 398 continue;
399 399 sfree(rv[n].colVal[i].val[k].
400 400 value);
401 401 }
402 402 rv[n].colVal[i].numVals = 1;
403 403 /* Move element 'j' to zero */
404 404 if (j != 0)
405 405 rv[n].colVal[i].val[0] =
406 406 rv[n].colVal[i].val[j];
407 407
408 408 /*
409 409 * Increment the repeat index 'r'. If >=
410 410 * 'repeat', reset 'r' and increment the
411 411 * value index 'j'. If 'j' >=
412 412 * rvq->colVal[i].numVals, start over on
413 413 * the column values for column 'i' (i.e.,
414 414 * reset 'j' to zero).
415 415 */
416 416 r += 1;
417 417 if (r >= repeat) {
418 418 r = 0;
419 419 j += 1;
420 420 if (j >= rvq->colVal[i].numVals)
421 421 j = 0;
422 422 }
423 423 }
424 424 repeat *= rvq->colVal[i].numVals;
425 425 }
426 426
427 427 *numVals = niv;
428 428 freeRuleValue(rvq, 1);
429 429 rvq = rv;
430 430 rv = 0;
431 431 }
432 432
433 433 q = am(myself, *numVals * sizeof (q[0]));
434 434 if (q == 0) {
435 435 freeRuleValue(rvq, *numVals);
436 436 return (0);
437 437 }
438 438
439 439 /*
440 440 * Create queries from the rvq[] array.
441 441 */
442 442 for (a = 0; a < *numVals; a++) {
443 443 int nn, err = 0;
444 444
445 445 qc = am(myself, rvq[a].numColumns * sizeof (*qc));
446 446 if (qc != 0) {
447 447 for (nn = 0, i = 0; i < rvq[a].numColumns; i++) {
448 448 for (j = 0; j < t->numColumns; j++) {
449 449 if (strcmp(rvq[a].colName[i],
450 450 t->column[j]) == 0) {
451 451 break;
452 452 }
453 453 }
454 454 if (j >= t->numColumns)
455 455 continue;
456 456 qc[nn].which_index = j;
457 457 if (rvq[a].colVal[i].numVals > 0) {
458 458 qc[nn].index_value = buildItem(
459 459 rvq[a].colVal[i].val[0].length,
460 460 rvq[a].colVal[i].val[0].value);
461 461 if (qc[nn].index_value == 0)
462 462 err++;
463 463 } else {
464 464 logmsg(MSG_NOTIMECHECK, LOG_ERR,
465 465 "%s: No values for [%d]%s",
466 466 myself, a, rvq[a].colName[i]);
467 467 err++;
468 468 }
469 469 nn++;
470 470 }
471 471 if (err == 0)
472 472 q[a] = buildQuery(nn, qc);
473 473 }
474 474 if (err > 0 || q[a] == 0) {
475 475 freeQueries(q, a);
476 476 for (a = 0; a < nn; a++)
477 477 freeQcomp(&qc[a], F);
478 478 sfree(qc);
479 479 freeRuleValue(rvq, *numVals);
480 480 return (0);
481 481 }
482 482 }
483 483
484 484 if (rvP != 0) {
485 485 *rvP = rvq;
486 486 } else {
487 487 freeRuleValue(rvq, 1);
488 488 *numVals = 0;
489 489 }
490 490
491 491 return (q);
492 492 }
493 493
494 494 void
495 495 printQuery(db_query *q, __nis_table_mapping_t *t) {
496 496 int i, mc = -1;
497 497 char *myself = "printQuery";
498 498 char *val[NIS_MAXCOLUMNS];
499 499
500 500 if (q == 0)
501 501 return;
502 502
503 503 (void) memset(val, 0, sizeof (val));
504 504
505 505 /*
506 506 * Collect the values, which may be out of order in 'q'.
507 507 * Remember the largest index.
508 508 */
509 509 for (i = 0; i < q->components.components_len; i++) {
510 510 int ix = q->components.components_val[i].which_index;
511 511
512 512 if (ix >= NIS_MAXCOLUMNS ||
513 513 (t != 0 && ix >= t->numColumns))
514 514 continue;
515 515 if (ix > mc)
516 516 mc = ix;
517 517 val[ix] = q->components.components_val[i].index_value->
518 518 itemvalue.itemvalue_val;
519 519 }
520 520
521 521 /* Print the values we collected */
522 522 for (i = 0; i <= mc; i++) {
523 523 p2buf(myself, "%s%s", (i != 0 ? " " : ""),
524 524 (val[i] != 0 ? val[i] : ""));
525 525 }
526 526 /* If we printed anything, add a newline */
527 527 if (mc >= 0)
528 528 p2buf(myself, "\n");
529 529 }
530 530
531 531 /*
532 532 * Verify that the db_query's 'q' and 'fq' match, in the sense that if
533 533 * they both have a value for a certain index, the values are the same.
534 534 */
535 535 int
536 536 verifyQueryMatch(db_query *q, db_query *fq) {
537 537 int i, j, match;
538 538
539 539 if (fq == 0)
540 540 return (1);
541 541
542 542 if (q == 0)
543 543 return ((fq == 0) ? 1 : 0);
544 544
545 545 for (i = 0, match = 1; match && i < q->components.components_len;
546 546 i++) {
547 547 for (j = 0; j < fq->components.components_len; j++) {
548 548 int len, flen;
549 549
550 550 /* Same index ? */
551 551 if (q->components.components_val[i].which_index !=
552 552 fq->components.components_val[j].
553 553 which_index)
554 554 continue;
555 555 /*
556 556 * If one 'index_value' is NULL, the other one must
557 557 * be NULL as well.
558 558 */
559 559 if (q->components.components_val[i].index_value == 0) {
560 560 if (fq->components.components_val[j].
561 561 index_value == 0)
562 562 continue;
563 563 else {
564 564 match = 0;
565 565 break;
566 566 }
567 567 }
568 568 if (fq->components.components_val[j].index_value ==
569 569 0) {
570 570 match = 0;
571 571 break;
572 572 }
573 573 /* Same value lengths ? */
574 574 len = q->components.components_val[i].index_value->
575 575 itemvalue.itemvalue_len;
576 576 flen = fq->components.components_val[j].index_value->
577 577 itemvalue.itemvalue_len;
578 578 if (len != flen) {
579 579 /*
580 580 * There's a twist here: the input query
581 581 * may well _not_ count a concluding NUL
582 582 * in a string value, while the output
583 583 * usually will. So, if the difference in
584 584 * length is one, and the "extra" byte is
585 585 * a zero-valued one, we accept equality.
586 586 * 'q' is assumed to be the output, and
587 587 * 'fq' the input.
588 588 */
589 589 if (!(len > 0 && len == (flen+1) &&
590 590 q->components.components_val[i].
591 591 index_value->
592 592 itemvalue.itemvalue_val[len-1] == 0)) {
593 593 match = 0;
594 594 break;
595 595 }
596 596 }
597 597 /* Same value ? */
598 598 if (memcmp(q->components.components_val[i].index_value->
599 599 itemvalue.itemvalue_val,
600 600 fq->components.components_val[j].index_value->
601 601 itemvalue.itemvalue_val,
602 602 flen) != 0) {
603 603 match = 0;
604 604 break;
605 605 }
606 606 }
607 607 }
608 608
609 609 return (match);
610 610 }
611 611
612 612 /*
613 613 * Remove those queries in 'q' that don't match t->index.
614 614 * Returns a pointer to the filtered array, which could be
615 615 * a compacted version of the original, or a new copy; in
616 616 * the latter case, the original will have been freed.
617 617 *
618 618 * Filtered/removed db_query's are freed.
619 619 */
620 620 db_query **
621 621 filterQuery(__nis_table_mapping_t *t, db_query **q, db_query *qin,
622 622 __nis_obj_attr_t ***objAttr, int *numQueries) {
623 623 db_query **new;
624 624 __nis_obj_attr_t **attr;
625 625 int i, nq, nn;
626 626 char *myself = "filterQuery";
627 627
628 628 if ((t == 0 && qin == 0) || q == 0 ||
629 629 numQueries == 0 || *numQueries <= 0)
630 630 return (q);
631 631
632 632 nq = *numQueries;
633 633 new = am(myself, nq * sizeof (new[0]));
634 634 if (objAttr != 0)
635 635 attr = am(myself, nq * sizeof (attr[0]));
636 636 else
637 637 attr = 0;
638 638 if (new == 0 || (objAttr != 0 && attr == 0)) {
639 639 sfree(new);
640 640 freeQueries(q, nq);
641 641 sfree(attr);
642 642 if (objAttr != 0) {
643 643 freeObjAttr(*objAttr, nq);
644 644 *objAttr = 0;
645 645 }
646 646 *numQueries = -1;
647 647 return (0);
648 648 }
649 649
650 650 for (i = 0, nn = 0; i < nq; i++) {
651 651 int retain = 1;
652 652
653 653 if (t != 0)
654 654 retain = verifyIndexMatch(t, q[i], 0, 0, 0);
655 655
656 656 if (retain && qin != 0)
657 657 retain = verifyQueryMatch(q[i], qin);
658 658
659 659 if (retain) {
660 660 new[nn] = q[i];
661 661 if (objAttr != 0)
662 662 attr[nn] = (*objAttr)[i];
663 663 nn++;
664 664 } else {
665 665 freeQuery(q[i]);
666 666 q[i] = 0;
667 667 if (objAttr != 0) {
668 668 freeSingleObjAttr((*objAttr)[i]);
669 669 (*objAttr)[i] = 0;
670 670 }
671 671 }
672 672 }
673 673
674 674 /* All q[i]'s are either in 'new', or have been deleted */
675 675 free(q);
676 676 if (objAttr != 0) {
677 677 sfree(*objAttr);
678 678 *objAttr = attr;
679 679 }
680 680
681 681 *numQueries = nn;
682 682
683 683 return (new);
684 684 }
↓ open down ↓ |
399 lines elided |
↑ open up ↑ |
685 685
686 686 db_query **
687 687 createNisPlusEntry(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
688 688 db_query *qin, __nis_obj_attr_t ***objAttr,
689 689 int *numQueries) {
690 690 db_query **query = 0;
691 691 int r, i, j, ir;
692 692 __nis_value_t *rval, *lval;
693 693 __nis_mapping_item_t *litem;
694 694 int numItems;
695 - int nq, iqc;
695 + int nq;
696 696 __nis_obj_attr_t **attr = 0;
697 697 char **dn = 0;
698 698 int numDN = 0;
699 699 char *myself = "createNisPlusEntry";
700 700
701 701 if (t == 0 || t->objectDN == 0 || rv == 0)
702 702 return (0);
703 703
704 704 /* Establish default, per-thread, search base */
705 705 __nisdb_get_tsd()->searchBase = t->objectDN->read.base;
706 706
707 707 for (r = 0, nq = 0; r < t->numRulesFromLDAP; r++) {
708 708 int nrq, ntq, err;
709 709 db_query **newq;
710 710 __nis_obj_attr_t **newattr;
711 711
712 712 rval = buildRvalue(&t->ruleFromLDAP[r]->rhs,
713 713 mit_ldap, rv, NULL);
714 714 if (rval == 0)
715 715 continue;
716 716
717 717 litem = buildLvalue(&t->ruleFromLDAP[r]->lhs, &rval,
718 718 &numItems);
719 719 if (litem == 0) {
720 720 freeValue(rval, 1);
721 721 /* XXX Should this be a fatal error ? */
722 722 continue;
723 723 }
724 724
725 725 lval = 0;
726 726 for (i = 0; i < numItems; i++) {
727 727 __nis_value_t *tmpval, *old;
728 728
729 729 tmpval = getMappingItem(&litem[i],
730 730 mit_nisplus, 0, 0, NULL);
731 731
732 732 /*
733 733 * If the LHS specifies an out-of-context LDAP or
734 734 * NIS+ item, we do the update right here. We
735 735 * don't add any values to 'lval'; instead, we
736 736 * skip to the next item. (However, we still
737 737 * get a string representation of the LHS in case
738 738 * we need to report an error.)
739 739 */
740 740 if (litem[i].type == mit_ldap) {
741 741 int stat;
742 742
743 743 if (dn == 0)
744 744 dn = findDNs(myself, rv, 1,
745 745 t->objectDN->write.base,
746 746 &numDN);
747 747
748 748 stat = storeLDAP(&litem[i], i, numItems, rval,
749 749 t->objectDN, dn, numDN);
750 750 if (stat != LDAP_SUCCESS) {
751 751 char *iname = "<unknown>";
752 752
753 753 if (tmpval != 0 &&
754 754 tmpval->numVals == 1)
755 755 iname = tmpval->val[0].value;
756 756 logmsg(MSG_NOTIMECHECK, LOG_ERR,
757 757 "%s: LDAP store \"%s\": %s",
758 758 myself, iname,
759 759 ldap_err2string(stat));
760 760 }
761 761
762 762 freeValue(tmpval, 1);
763 763 continue;
764 764 }
765 765
766 766 old = lval;
767 767 lval = concatenateValues(old, tmpval);
768 768 freeValue(tmpval, 1);
769 769 freeValue(old, 1);
770 770 }
771 771
772 772 freeMappingItem(litem, numItems);
773 773 if (lval == 0 || lval->numVals <= 0 || rval->numVals <= 0) {
774 774 freeValue(lval, 1);
775 775 freeValue(rval, 1);
776 776 continue;
777 777 }
778 778
779 779 /*
780 780 * We now have a number of possible cases. The notation
781 781 * used in the table is:
782 782 *
783 783 * single A single value (numVals == 1)
784 784 * single/rep A single value with repeat == 1
785 785 * multi[N] N values
786 786 * multi[N]/rep M values with repeat == 1
787 787 * (M) M resulting db_query's
788 788 *
789 789 * lval \ rval single single/rep multi[N] multi[N]/rep
790 790 * single (1) (1) (1) (1)
791 791 * single/rep (1) (1) (N) (N)
792 792 * multi[M] (1) (1) (1) 1+(N-1)/M
793 793 * multi[M]/rep (1) (1) (1) 1+(N-1)/M
794 794 *
795 795 * Of course, we already have 'nq' db_query's from previous
796 796 * rules, so the resulting number of queries is max(1,nq)
797 797 * times the numbers in the table above.
798 798 */
799 799
800 800 /* The number of queries resulting from the current rule */
801 801 if (rval->numVals > 1) {
802 802 if (lval->numVals == 1 && lval->repeat)
803 803 nrq = rval->numVals;
804 804 else if (lval->numVals > 1 && rval->repeat)
805 805 nrq = 1 + ((rval->numVals-1)/lval->numVals);
806 806 else
807 807 nrq = 1;
808 808 } else {
809 809 nrq = 1;
810 810 }
811 811
812 812 /* Total number of queries after adding the current rule */
813 813 if (nq <= 0)
814 814 ntq = nrq;
815 815 else
816 816 ntq = nq * nrq;
817 817
818 818 if (ntq > nq) {
819 819 newq = realloc(query, ntq * sizeof (query[0]));
820 820 newattr = realloc(attr, ntq * sizeof (attr[0]));
821 821 if (newq == 0 || newattr == 0) {
822 822 logmsg(MSG_NOMEM, LOG_ERR,
823 823 "%s: realloc(%d) => NULL",
824 824 myself, ntq * sizeof (query[0]));
825 825 freeValue(lval, 1);
826 826 freeValue(rval, 1);
827 827 freeQueries(query, nq);
828 828 freeObjAttr(attr, nq);
829 829 sfree(newq);
830 830 freeDNs(dn, numDN);
831 831 return (0);
832 832 }
833 833 query = newq;
834 834 attr = newattr;
835 835 }
836 836
837 837 /*
838 838 * Copy/clone the existing queries to the new array,
839 839 * remembering that realloc() has done the first 'nq'
840 840 * ones.
841 841 *
842 842 * If there's an error (probably memory allocation), we
843 843 * still go through the rest of the array, so that it's
844 844 * simple to free the elements when we clean up.
845 845 */
846 846 for (i = 1, err = 0; i < nrq; i++) {
847 847 for (j = 0; j < nq; j++) {
848 848 query[(nq*i)+j] = cloneQuery(query[j],
849 849 t->numColumns);
850 850 if (query[(nq*i)+j] == 0 &&
851 851 query[j] != 0)
852 852 err++;
853 853 attr[(nq*i)+j] = cloneObjAttr(attr[j]);
854 854 if (attr[(nq*i)+j] == 0 &&
855 855 attr[j] != 0)
856 856 err++;
857 857 }
858 858 }
859 859
860 860 if (err > 0) {
861 861 freeValue(lval, 1);
862 862 freeValue(rval, 1);
863 863 freeQueries(query, ntq);
864 864 freeObjAttr(attr, ntq);
865 865 freeDNs(dn, numDN);
866 866 return (0);
867 867 }
868 868
869 869 /*
870 870 * Special case if nq == 0 (i.e., the first time we
871 871 * allocated db_query's). If so, we now allocate empty
872 872 * db_qcomp arrays, which simplifies subsequent
873 873 * copying of values.
874 874 */
875 875 if (nq <= 0) {
876 876 (void) memset(query, 0, ntq * sizeof (query[0]));
877 877 (void) memset(attr, 0, ntq * sizeof (attr[0]));
878 878 for (i = 0, err = 0; i < ntq; i++) {
879 879 query[i] = am(myself, sizeof (*query[i]));
880 880 if (query[i] == 0) {
881 881 err++;
882 882 break;
883 883 }
884 884 query[i]->components.components_val =
885 885 am(myself, t->numColumns *
886 886 sizeof (query[i]->components.components_val[0]));
887 887 if (query[i]->components.components_val == 0) {
888 888 err++;
889 889 break;
890 890 }
891 891 query[i]->components.components_len = 0;
892 892 }
893 893 if (err > 0) {
894 894 freeValue(lval, 1);
895 895 freeValue(rval, 1);
896 896 freeQueries(query, ntq);
897 897 freeObjAttr(attr, ntq);
898 898 freeDNs(dn, numDN);
899 899 return (0);
900 900 }
901 901 }
902 902
903 903 /* Now we're ready to add the new values */
904 904 for (i = 0, ir = 0; i < lval->numVals; i++) {
905 905 char *oaName = 0;
906 906 int index;
907 907
908 908 /* Find column index */
909 909 for (index = 0; index < t->numColumns;
910 910 index++) {
911 911 if (strncmp(t->column[index],
912 912 lval->val[i].value,
913 913 lval->val[i].length) == 0)
914 914 break;
915 915 }
916 916 if (index >= t->numColumns) {
917 917 /*
918 918 * Could be one of the special object
919 919 * attributes.
920 920 */
921 921 oaName = isObjAttr(&lval->val[i]);
922 922 if (oaName == 0)
923 923 continue;
924 924 }
925 925
926 926 for (j = i*nrq; j < (i+1)*nrq; j++) {
927 927 int k;
928 928
929 929 /* If we're out of values, repeat last one */
930 930 ir = (j < rval->numVals) ?
931 931 j : rval->numVals - 1;
932 932
933 933 /*
934 934 * Step through the query array, adding
935 935 * the new value every 'nrq' queries, and
936 936 * starting at 'query[j % nrq]'.
937 937 */
938 938 for (k = j % nrq, err = 0; k < ntq; k += nrq) {
939 939 int ic, c;
940 940
941 941 if (oaName != 0) {
942 942 int fail = setObjAttrField(
943 943 oaName,
944 944 &rval->val[ir],
945 945 &attr[k]);
946 946 if (fail) {
947 947 err++;
948 948 break;
949 949 }
950 950 continue;
951 951 }
952 952
953 953 ic = query[k]->components.
954 954 components_len;
955 955 /*
956 956 * If we've already filled this
957 957 * query, the new value is a dup
958 958 * which we'll ignore.
959 959 */
960 960 if (ic >= t->numColumns)
961 961 continue;
962 962
963 963 /*
964 964 * Do we already have a value for
965 965 * this 'index' ?
966 966 */
967 967 for (c = 0; c < ic; c++) {
968 968 if (query[k]->components.
969 969 components_val[c].
970 970 which_index == index)
971 971 break;
972 972 }
973 973
974 974 /* If no previous value, add it */
975 975 if (c >= ic) {
976 976 int l;
977 977 char *v;
978 978
979 979 query[k]->components.
980 980 components_val[ic].
981 981 which_index = index;
982 982 l = rval->val[ir].length;
983 983 v = rval->val[ir].value;
984 984 if (rval->type == vt_string &&
985 985 l > 0 &&
986 986 v[l-1] != '\0' &&
987 987 v[l] == '\0')
988 988 l++;
989 989 query[k]->components.
990 990 components_val[ic].
991 991 index_value =
992 992 buildItem(l, v);
993 993 if (query[k]->
994 994 components.
995 995 components_val[ic].
996 996 index_value == 0) {
997 997 err++;
998 998 break;
999 999 }
1000 1000 query[k]->components.
1001 1001 components_len++;
1002 1002 }
1003 1003 }
1004 1004 if (err > 0) {
1005 1005 freeValue(lval, 1);
1006 1006 freeValue(rval, 1);
1007 1007 freeQueries(query, ntq);
1008 1008 freeObjAttr(attr, ntq);
1009 1009 freeDNs(dn, numDN);
1010 1010 return (0);
1011 1011 }
1012 1012 }
1013 1013 }
1014 1014 freeValue(lval, 1);
1015 1015 freeValue(rval, 1);
1016 1016
1017 1017 nq = ntq;
1018 1018 }
1019 1019
1020 1020 freeDNs(dn, numDN);
1021 1021
1022 1022 if (nq <= 0) {
1023 1023 sfree(query);
1024 1024 query = 0;
1025 1025 }
1026 1026
1027 1027 /* Should we filter on index or input query ? */
1028 1028 if (query != 0) {
1029 1029 if (t->index.numIndexes > 0)
1030 1030 query = filterQuery(t, query, qin, &attr, &nq);
1031 1031 else if (qin != 0)
1032 1032 query = filterQuery(0, query, qin, &attr, &nq);
1033 1033 }
1034 1034
1035 1035 if (query != 0 && numQueries != 0)
1036 1036 *numQueries = nq;
1037 1037
1038 1038 if (objAttr != 0)
1039 1039 *objAttr = attr;
1040 1040 else
1041 1041 freeObjAttr(attr, nq);
1042 1042
1043 1043 return (query);
1044 1044 }
1045 1045 /*
1046 1046 * Given a table mapping and a rule-value, convert to an array of
1047 1047 * (db_query *), using the fromLDAP ruleset.
1048 1048 *
1049 1049 * On entry, '*numQueries' holds the number of elements in the 'rv'
1050 1050 * array. On exit, it holds the number of (db_query *)'s in the return
1051 1051 * value array.
1052 1052 */
1053 1053 db_query **
1054 1054 ruleValue2Query(__nis_table_mapping_t *t, __nis_rule_value_t *rv,
1055 1055 db_query *qin, __nis_obj_attr_t ***objAttr, int *numQueries) {
1056 1056 db_query **q = 0, ***qp = 0;
1057 1057 int i, nqp, nq, *nnp = 0, nv;
1058 1058 __nis_obj_attr_t **attr = 0, ***atp = 0;
1059 1059 char *myself = "ruleValue2Query";
1060 1060
1061 1061
1062 1062 if (t == 0 || rv == 0 || numQueries == 0)
1063 1063 return (0);
1064 1064
1065 1065 nv = *numQueries;
1066 1066 if (nv <= 0)
1067 1067 return (0);
1068 1068
1069 1069 /*
1070 1070 * 'qp' is an array of (db_query **), and we get one element for
1071 1071 * each call to createNisPlusEntry(); i.e., one for each rule-value.
1072 1072 *
1073 1073 * 'nnp[i]' is the count of (db_query *) in each 'qp[i]'.
1074 1074 */
1075 1075 qp = am(myself, nv * sizeof (*qp));
1076 1076 nnp = am(myself, nv * sizeof (*nnp));
1077 1077 atp = am(myself, nv * sizeof (*atp));
1078 1078 if (qp == 0 || nnp == 0 || atp == 0) {
1079 1079 sfree(qp);
1080 1080 sfree(nnp);
1081 1081 sfree(atp);
1082 1082 return (0);
1083 1083 }
1084 1084
1085 1085 for (i = 0, nq = 0, nqp = 0; i < nv; i++) {
1086 1086 qp[nqp] = createNisPlusEntry(t, &rv[i], qin, &atp[nqp],
1087 1087 &nnp[nqp]);
1088 1088 /* If we fail, abort (XXX??? or continue ???) */
1089 1089 if (qp[nqp] == 0)
1090 1090 goto cleanup;
1091 1091 nq += nnp[nqp];
1092 1092 nqp++;
1093 1093 }
1094 1094
1095 1095 /* If we didn't get any (db_query **)'s, return failure */
1096 1096 if (nqp == 0 || nq <= 0)
1097 1097 goto cleanup;
1098 1098
1099 1099 q = am(myself, nq * sizeof (q[0]));
1100 1100 attr = am(myself, nq * sizeof (attr[0]));
1101 1101 if (q == 0 || attr == 0) {
1102 1102 nq = 0;
1103 1103 goto cleanup;
1104 1104 }
1105 1105
1106 1106 /* Convert 'qp' to an array of (db_query *)'s */
1107 1107 for (i = 0, nq = 0; i < nqp; i++) {
1108 1108 (void) memcpy(&q[nq], qp[i], nnp[i] * sizeof (qp[i][0]));
1109 1109 (void) memcpy(&attr[nq], atp[i], nnp[i] * sizeof (atp[i][0]));
1110 1110 nq += nnp[i];
1111 1111 free(qp[i]);
1112 1112 free(atp[i]);
1113 1113 }
1114 1114
1115 1115 *numQueries = nq;
1116 1116 if (objAttr != 0)
1117 1117 *objAttr = attr;
1118 1118 else
1119 1119 freeObjAttr(attr, nq);
1120 1120
1121 1121 /* Make sure 'cleanup' doesn't free the db_query pointers */
1122 1122 nqp = 0;
1123 1123
1124 1124 cleanup:
1125 1125 for (i = 0; i < nqp; i++) {
1126 1126 freeQueries(qp[i], nnp[i]);
1127 1127 sfree(atp[i]);
1128 1128 }
1129 1129 sfree(qp);
1130 1130 sfree(nnp);
1131 1131 sfree(atp);
1132 1132
1133 1133 return (q);
1134 1134 }
1135 1135
1136 1136 db_query *
1137 1137 pseudoEntryObj2Query(entry_obj *e, nis_object *tobj, __nis_rule_value_t *rv) {
1138 1138 db_query *qbuf;
1139 1139 db_qcomp *qcbuf;
1140 1140 int nc, i;
1141 1141 __nis_rule_value_t *rvt = 0;
1142 1142 char *myself = "pseudoEntryObj2Query";
1143 1143
1144 1144 nc = e->en_cols.en_cols_len - 1;
1145 1145
1146 1146 if (e == 0 || nc < 0 || nc > NIS_MAXCOLUMNS)
1147 1147 return (0);
1148 1148
1149 1149 /*
1150 1150 * If 'rvP' is non-NULL, build a rule value from the pseudo-
1151 1151 * nis_object in e->en_cols.en_cols_val[0].
1152 1152 */
1153 1153 if (rv != 0) {
1154 1154 nis_object *o;
1155 1155
1156 1156 o = unmakePseudoEntryObj(e, tobj);
1157 1157 if (o == 0)
1158 1158 return (0);
1159 1159 rvt = addObjAttr2RuleValue(o, 0);
1160 1160 nis_destroy_object(o);
1161 1161 if (rvt == 0)
1162 1162 return (0);
1163 1163 }
1164 1164
1165 1165 qbuf = am(myself, sizeof (*qbuf));
1166 1166 /*
1167 1167 * If there are no columns (other than the pseudo-entry object),
1168 1168 * we're done.
1169 1169 */
1170 1170 if (nc == 0)
1171 1171 return (qbuf);
1172 1172
1173 1173 qcbuf = am(myself, nc * sizeof (*qcbuf));
1174 1174 if (qcbuf == 0) {
1175 1175 sfree(qcbuf);
1176 1176 if (rvt != 0)
1177 1177 freeRuleValue(rvt, 1);
1178 1178 return (0);
1179 1179 }
1180 1180
1181 1181 /*
1182 1182 * Build the db_query, remembering that e->en_cols.en_cols_val[0]
1183 1183 * is the pseudo-nis_object.
1184 1184 */
1185 1185 qbuf->components.components_val = qcbuf;
1186 1186 qbuf->components.components_len = nc;
1187 1187 for (i = 0; i < nc; i++) {
1188 1188 qcbuf[i].which_index = i;
1189 1189 qcbuf[i].index_value = buildItem(
1190 1190 e->en_cols.en_cols_val[i+1].ec_value.ec_value_len,
1191 1191 e->en_cols.en_cols_val[i+1].ec_value.ec_value_val);
1192 1192 if (qcbuf[i].index_value == 0) {
1193 1193 freeQuery(qbuf);
1194 1194 if (rvt != 0)
1195 1195 freeRuleValue(rvt, 1);
1196 1196 return (0);
1197 1197 }
1198 1198 }
1199 1199
1200 1200 if (rvt != 0) {
1201 1201 *rv = *rvt;
1202 1202 sfree(rvt);
1203 1203 }
1204 1204
1205 1205 return (qbuf);
1206 1206 }
1207 1207
1208 1208 /*
1209 1209 * Given an input query 'q', and a db_query work buffer 'qbuf', return
1210 1210 * a pointer to a query with one component corresponding to component
1211 1211 * 'index' in 'q'.
1212 1212 *
1213 1213 * Note that no memory is allocated, and that the returned query has
1214 1214 * pointers into 'q'.
1215 1215 */
1216 1216 db_query *
1217 1217 queryFromComponent(db_query *q, int index, db_query *qbuf) {
1218 1218
1219 1219 if (q == 0 || index < 0 || index >= q->components.components_len ||
1220 1220 qbuf == 0)
1221 1221 return (0);
1222 1222
1223 1223 qbuf->components.components_len = 1;
1224 1224 qbuf->components.components_val = &q->components.components_val[index];
1225 1225
1226 1226 return (qbuf);
1227 1227 }
↓ open down ↓ |
522 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX