Libinfo-78.2.tar.gz
[apple/libinfo.git] / netinfo.subproj / ni_util.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Utility routines for netinfo data structures
26 * Copyright (C) 1989 by NeXT, Inc.
27 */
28 #include <netinfo/ni.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <strings.h>
32 #include <regex.h>
33 #include "mm.h"
34
35 void
36 ni_idlist_insert(
37 ni_idlist *cl,
38 ni_index id,
39 ni_index where
40 )
41 {
42 ni_index i;
43
44 MM_GROW_ARRAY(cl->niil_val, cl->niil_len);
45 for (i = cl->niil_len; i > where; i--) {
46 cl->niil_val[i] = cl->niil_val[i - 1];
47 }
48 cl->niil_val[i] = id;
49 cl->niil_len++;
50 }
51
52 int
53 ni_idlist_delete(
54 ni_idlist *idlist,
55 ni_index id
56 )
57 {
58 ni_index j;
59 ni_index i;
60
61 for (i = 0; i < idlist->niil_len; i++) {
62 if (idlist->niil_val[i] == id) {
63 for (j = i + 1; j < idlist->niil_len; j++) {
64 idlist->niil_val[j - 1] = idlist->niil_val[j];
65 }
66 MM_SHRINK_ARRAY(idlist->niil_val, idlist->niil_len--);
67 return(1);
68 }
69 }
70 return (0);
71 }
72
73
74 void
75 ni_idlist_free(
76 ni_idlist *idlist
77 )
78 {
79 if (idlist->niil_val != NULL) {
80 MM_FREE_ARRAY(idlist->niil_val, idlist->niil_len);
81 }
82 NI_INIT(idlist);
83 }
84
85 ni_idlist
86 ni_idlist_dup(
87 const ni_idlist idlist
88 )
89 {
90 ni_idlist newlist;
91 ni_index i;
92
93 newlist.niil_len = idlist.niil_len;
94 MM_ALLOC_ARRAY(newlist.niil_val, idlist.niil_len);
95 for (i = 0; i < idlist.niil_len; i++) {
96 newlist.niil_val[i] = idlist.niil_val[i];
97 }
98 return (newlist);
99 }
100
101 void
102 ni_proplist_insert(
103 ni_proplist *pl,
104 const ni_property prop,
105 ni_index where
106 )
107 {
108 ni_index i;
109
110 MM_GROW_ARRAY(pl->nipl_val, pl->nipl_len);
111 for (i = pl->nipl_len; i > where; i--) {
112 pl->nipl_val[i] = pl->nipl_val[i - 1];
113 }
114 pl->nipl_val[i] = ni_prop_dup(prop);
115 pl->nipl_len++;
116 }
117
118 void
119 ni_proplist_delete(
120 ni_proplist *pl,
121 ni_index which
122 )
123 {
124 int i;
125
126 ni_prop_free(&pl->nipl_val[which]);
127 for (i = which + 1; i < pl->nipl_len; i++) {
128 pl->nipl_val[i - 1] = pl->nipl_val[i];
129 }
130 MM_SHRINK_ARRAY(pl->nipl_val, pl->nipl_len--);
131 }
132
133 void
134 ni_proplist_free(
135 ni_proplist *pl
136 )
137 {
138 ni_index i;
139
140 if (pl->nipl_val == NULL) {
141 return;
142 }
143 for (i = 0; i < pl->nipl_len; i++) {
144 ni_prop_free(&pl->nipl_val[i]);
145 }
146 MM_FREE_ARRAY(pl->nipl_val, pl->nipl_len);
147 NI_INIT(pl);
148 }
149
150 void
151 ni_proplist_list_free(
152 ni_proplist_list *pll
153 )
154 {
155 ni_index i;
156
157 if (pll->nipll_val == NULL) {
158 return;
159 }
160 for (i = 0; i < pll->nipll_len; i++) {
161 ni_proplist_free(&pll->nipll_val[i]);
162 }
163 MM_FREE_ARRAY(pll->nipll_val, pll->nipll_len);
164 NI_INIT(pll);
165 }
166
167 ni_proplist
168 ni_proplist_dup(
169 const ni_proplist pl
170 )
171 {
172 ni_proplist newlist;
173 ni_index i;
174
175 newlist.nipl_len = pl.nipl_len;
176 MM_ALLOC_ARRAY(newlist.nipl_val, pl.nipl_len);
177 for (i = 0; i < pl.nipl_len; i++) {
178 newlist.nipl_val[i].nip_name = ni_name_dup(pl.nipl_val[i].nip_name);
179 newlist.nipl_val[i].nip_val = ni_namelist_dup(pl.nipl_val[i].nip_val);
180 }
181 return (newlist);
182 }
183
184 ni_index
185 ni_proplist_match(
186 const ni_proplist pl,
187 ni_name_const pname,
188 ni_name_const pval
189 )
190 {
191 ni_index i;
192 ni_index j;
193 ni_namelist nl;
194
195 for (i = 0; i < pl.nipl_len; i++) {
196 if (ni_name_match(pname, pl.nipl_val[i].nip_name)) {
197 if (pval == NULL) {
198 return (i);
199 }
200 nl = pl.nipl_val[i].nip_val;
201 for (j = 0; j < nl.ninl_len; j++) {
202 if (ni_name_match(pval, nl.ninl_val[j])) {
203 return (i);
204 }
205 }
206 break;
207 }
208 }
209 return (NI_INDEX_NULL);
210 }
211
212
213 ni_property
214 ni_prop_dup(
215 const ni_property prop
216 )
217 {
218 ni_property newprop;
219
220 newprop.nip_name = ni_name_dup(prop.nip_name);
221 newprop.nip_val = ni_namelist_dup(prop.nip_val);
222 return (newprop);
223 }
224
225 void
226 ni_prop_free(
227 ni_property *prop
228 )
229 {
230 ni_name_free(&prop->nip_name);
231 ni_namelist_free(&prop->nip_val);
232 }
233
234 int
235 ni_name_match(
236 ni_name_const nm1,
237 ni_name_const nm2
238 )
239 {
240 return (strcmp(nm1, nm2) == 0);
241 }
242
243 ni_name
244 ni_name_dup(
245 ni_name_const nm
246 )
247 {
248 return (strcpy(malloc(strlen(nm) + 1), nm));
249 }
250
251
252 void
253 ni_name_free(
254 ni_name *nm
255 )
256 {
257 if (*nm != NULL) {
258 free(*nm);
259 *nm = NULL;
260 }
261 }
262
263 ni_namelist
264 ni_namelist_dup(
265 const ni_namelist nl
266 )
267 {
268 ni_namelist newlist;
269 ni_index i;
270
271 newlist.ninl_len = nl.ninl_len;
272 MM_ALLOC_ARRAY(newlist.ninl_val, newlist.ninl_len);
273 for (i = 0; i < nl.ninl_len; i++) {
274 newlist.ninl_val[i] = ni_name_dup(nl.ninl_val[i]);
275 }
276 return (newlist);
277 }
278
279 void
280 ni_namelist_free(
281 ni_namelist *nl
282 )
283 {
284 ni_index i;
285
286 if (nl->ninl_val == NULL) {
287 return;
288 }
289 for (i = 0; i < nl->ninl_len; i++) {
290 ni_name_free(&nl->ninl_val[i]);
291 }
292 MM_FREE_ARRAY(nl->ninl_val, nl->ninl_len);
293 NI_INIT(nl);
294 }
295
296 void
297 ni_namelist_insert(
298 ni_namelist *nl,
299 ni_name_const nm,
300 ni_index where
301 )
302 {
303 ni_index i;
304
305 MM_GROW_ARRAY(nl->ninl_val, nl->ninl_len);
306 for (i = nl->ninl_len; i > where; i--) {
307 nl->ninl_val[i] = nl->ninl_val[i - 1];
308 }
309 nl->ninl_val[i] = ni_name_dup(nm);
310 nl->ninl_len++;
311 }
312
313 void
314 ni_namelist_delete(
315 ni_namelist *nl,
316 ni_index which
317 )
318 {
319 int i;
320
321 ni_name_free(&nl->ninl_val[which]);
322 for (i = which + 1; i < nl-> ninl_len; i++) {
323 nl->ninl_val[i - 1] = nl->ninl_val[i];
324 }
325 MM_SHRINK_ARRAY(nl->ninl_val, nl->ninl_len--);
326 }
327
328 ni_index
329 ni_namelist_match(
330 const ni_namelist nl,
331 ni_name_const nm
332 )
333 {
334 ni_index i;
335
336 for (i = 0; i < nl.ninl_len; i++) {
337 if (ni_name_match(nl.ninl_val[i], nm)) {
338 return (i);
339 }
340 }
341 return (NI_INDEX_NULL);
342 }
343
344 void
345 ni_entrylist_insert(
346 ni_entrylist *el,
347 const ni_entry en
348 )
349 {
350 ni_entry entry;
351
352 MM_GROW_ARRAY(el->niel_val, el->niel_len);
353 entry.id = en.id;
354 if (en.names != NULL) {
355 MM_ALLOC(entry.names);
356 *entry.names = ni_namelist_dup(*en.names);
357 } else {
358 entry.names = NULL;
359 }
360 el->niel_val[el->niel_len++] = entry;
361 }
362
363 void
364 ni_entrylist_delete(
365 ni_entrylist *el,
366 ni_index which
367 )
368 {
369 int i;
370
371 if (el->niel_val[which].names != NULL) {
372 ni_namelist_free(el->niel_val[which].names);
373 }
374 for (i = which + 1; i < el-> niel_len; i++) {
375 el->niel_val[i - 1] = el->niel_val[i];
376 }
377 MM_SHRINK_ARRAY(el->niel_val, el->niel_len--);
378 }
379
380 void
381 ni_entrylist_free(
382 ni_entrylist *el
383 )
384 {
385 ni_index i;
386
387 if (el->niel_val == NULL) {
388 return;
389 }
390 for (i = 0; i < el->niel_len; i++) {
391 if (el->niel_val[i].names != NULL) {
392 ni_namelist_free(el->niel_val[i].names);
393 MM_FREE(el->niel_val[i].names);
394 }
395 }
396 MM_FREE_ARRAY(el->niel_val, el->niel_len);
397 NI_INIT(el);
398 }
399
400
401
402 /*
403 * We can do this without an addition to the protocol
404 */
405 ni_status
406 ni_lookupprop(
407 void *ni,
408 ni_id *id,
409 ni_name_const pname,
410 ni_namelist *nl
411 )
412 {
413 ni_status status;
414 ni_namelist list;
415 ni_index which;
416
417 NI_INIT(&list);
418 status = ni_listprops(ni, id, &list);
419 if (status != NI_OK) {
420 return (status);
421 }
422 which = ni_namelist_match(list, pname);
423 ni_namelist_free(&list);
424 if (which == NI_INDEX_NULL) {
425 return (NI_NOPROP);
426 }
427 return (ni_readprop(ni, id, which, nl));
428 }
429
430 /*
431 * Search from local domain to root domain to locate a path.
432 */
433 ni_status
434 ni_find(void **dom, ni_id *nid, ni_name dirname, unsigned int timeout)
435 {
436 void *d, *p;
437 ni_id n;
438 ni_status status;
439
440 *dom = NULL;
441 nid->nii_object = NI_INDEX_NULL;
442 nid->nii_instance = NI_INDEX_NULL;
443
444 status = ni_open(NULL, ".", &d);
445 if (status != NI_OK) return status;
446
447 if (timeout > 0)
448 {
449 ni_setreadtimeout(d, timeout);
450 ni_setabort(d, 1);
451 }
452
453 while (d != NULL)
454 {
455 status = ni_pathsearch(d, &n, dirname);
456 if (status == NI_OK)
457 {
458 *dom = d;
459 *nid = n;
460 return NI_OK;
461 }
462
463 status = ni_open(d, "..", &p);
464 ni_free(d);
465 d = NULL;
466 if (status == NI_OK) d = p;
467 }
468
469 return NI_NODIR;
470 }
471
472 ni_status
473 ni_search(void *handle, ni_id *dir, ni_name name, ni_name expr, int flags, ni_entrylist *entries)
474 {
475 regex_t *cexp;
476 int i, j, found;
477 ni_entrylist el;
478 ni_namelist *nl;
479 ni_status status;
480
481 /* get subdirectory list */
482 NI_INIT(&el);
483 status = ni_list(handle, dir, name, &el);
484 if (status != NI_OK) return status;
485
486 cexp = (regex_t *)malloc(sizeof(regex_t));
487 memset(cexp, 0, sizeof(regex_t));
488 i = regcomp(cexp, expr, flags);
489 if (i != 0)
490 {
491 free(cexp);
492 return NI_FAILED;
493 }
494
495 for (i = 0; i < el.ni_entrylist_len; i++)
496 {
497 if (el.ni_entrylist_val[i].names == NULL) continue;
498
499 nl = el.ni_entrylist_val[i].names;
500
501 for (j = 0; j < nl->ni_namelist_len; j++)
502 {
503 found = 0;
504 if (regexec(cexp, nl->ni_namelist_val[j], 0, NULL, 0) != 0) continue;
505
506 found = 1;
507 break;
508 }
509
510 if (found == 0) continue;
511
512 if (entries->ni_entrylist_len == 0)
513 {
514 entries->ni_entrylist_val = malloc(sizeof(ni_entry));
515 }
516 else
517 {
518 entries->ni_entrylist_val = (ni_entry *)realloc(entries->ni_entrylist_val, (entries->ni_entrylist_len + 1) * sizeof(ni_entry));
519 }
520
521 entries->ni_entrylist_val[entries->ni_entrylist_len].id = el.ni_entrylist_val[i].id;
522 entries->ni_entrylist_val[entries->ni_entrylist_len].names = el.ni_entrylist_val[i].names;
523 el.ni_entrylist_val[i].names = NULL;
524 entries->ni_entrylist_len++;
525 }
526
527 ni_entrylist_free(&el);
528 regfree(cexp);
529 free(cexp);
530
531 return NI_OK;
532 }