libnvpair.c revision 1.1.1.2.12.2 1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <unistd.h>
27 #include <strings.h>
28 #include <libintl.h>
29 #include <sys/types.h>
30 #include <sys/inttypes.h>
31 #include "libnvpair.h"
32
33 /*
34 * libnvpair - A tools library for manipulating <name, value> pairs.
35 *
36 * This library provides routines packing an unpacking nv pairs
37 * for transporting data across process boundaries, transporting
38 * between kernel and userland, and possibly saving onto disk files.
39 */
40
41 static void
42 indent(FILE *fp, int depth)
43 {
44 while (depth-- > 0)
45 (void) fprintf(fp, "\t");
46 }
47
48 /*
49 * nvlist_print - Prints elements in an event buffer
50 */
51 static
52 void
53 nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth)
54 {
55 int i;
56 char *name;
57 uint_t nelem;
58 nvpair_t *nvp;
59
60 if (nvl == NULL)
61 return;
62
63 indent(fp, depth);
64 (void) fprintf(fp, "nvlist version: %d\n", NVL_VERSION(nvl));
65
66 nvp = nvlist_next_nvpair(nvl, NULL);
67
68 while (nvp) {
69 data_type_t type = nvpair_type(nvp);
70
71 indent(fp, depth);
72 name = nvpair_name(nvp);
73 (void) fprintf(fp, "\t%s =", name);
74 nelem = 0;
75 switch (type) {
76 case DATA_TYPE_BOOLEAN: {
77 (void) fprintf(fp, " 1");
78 break;
79 }
80 case DATA_TYPE_BOOLEAN_VALUE: {
81 boolean_t val;
82 (void) nvpair_value_boolean_value(nvp, &val);
83 (void) fprintf(fp, " %d", val);
84 break;
85 }
86 case DATA_TYPE_BYTE: {
87 uchar_t val;
88 (void) nvpair_value_byte(nvp, &val);
89 (void) fprintf(fp, " 0x%2.2x", val);
90 break;
91 }
92 case DATA_TYPE_INT8: {
93 int8_t val;
94 (void) nvpair_value_int8(nvp, &val);
95 (void) fprintf(fp, " %d", val);
96 break;
97 }
98 case DATA_TYPE_UINT8: {
99 uint8_t val;
100 (void) nvpair_value_uint8(nvp, &val);
101 (void) fprintf(fp, " 0x%x", val);
102 break;
103 }
104 case DATA_TYPE_INT16: {
105 int16_t val;
106 (void) nvpair_value_int16(nvp, &val);
107 (void) fprintf(fp, " %d", val);
108 break;
109 }
110 case DATA_TYPE_UINT16: {
111 uint16_t val;
112 (void) nvpair_value_uint16(nvp, &val);
113 (void) fprintf(fp, " 0x%x", val);
114 break;
115 }
116 case DATA_TYPE_INT32: {
117 int32_t val;
118 (void) nvpair_value_int32(nvp, &val);
119 (void) fprintf(fp, " %d", val);
120 break;
121 }
122 case DATA_TYPE_UINT32: {
123 uint32_t val;
124 (void) nvpair_value_uint32(nvp, &val);
125 (void) fprintf(fp, " 0x%x", val);
126 break;
127 }
128 case DATA_TYPE_INT64: {
129 int64_t val;
130 (void) nvpair_value_int64(nvp, &val);
131 (void) fprintf(fp, " %" PRId64 , val);
132 break;
133 }
134 case DATA_TYPE_UINT64: {
135 uint64_t val;
136 (void) nvpair_value_uint64(nvp, &val);
137 (void) fprintf(fp, " 0x%" PRIx64, val);
138 break;
139 }
140 case DATA_TYPE_DOUBLE: {
141 double val;
142 (void) nvpair_value_double(nvp, &val);
143 (void) fprintf(fp, " 0x%f", val);
144 break;
145 }
146 case DATA_TYPE_STRING: {
147 char *val;
148 (void) nvpair_value_string(nvp, &val);
149 (void) fprintf(fp, " %s", val);
150 break;
151 }
152 case DATA_TYPE_BOOLEAN_ARRAY: {
153 boolean_t *val;
154 (void) nvpair_value_boolean_array(nvp, &val, &nelem);
155 for (i = 0; i < nelem; i++)
156 (void) fprintf(fp, " %d", val[i]);
157 break;
158 }
159 case DATA_TYPE_BYTE_ARRAY: {
160 uchar_t *val;
161 (void) nvpair_value_byte_array(nvp, &val, &nelem);
162 for (i = 0; i < nelem; i++)
163 (void) fprintf(fp, " 0x%2.2x", val[i]);
164 break;
165 }
166 case DATA_TYPE_INT8_ARRAY: {
167 int8_t *val;
168 (void) nvpair_value_int8_array(nvp, &val, &nelem);
169 for (i = 0; i < nelem; i++)
170 (void) fprintf(fp, " %d", val[i]);
171 break;
172 }
173 case DATA_TYPE_UINT8_ARRAY: {
174 uint8_t *val;
175 (void) nvpair_value_uint8_array(nvp, &val, &nelem);
176 for (i = 0; i < nelem; i++)
177 (void) fprintf(fp, " 0x%x", val[i]);
178 break;
179 }
180 case DATA_TYPE_INT16_ARRAY: {
181 int16_t *val;
182 (void) nvpair_value_int16_array(nvp, &val, &nelem);
183 for (i = 0; i < nelem; i++)
184 (void) fprintf(fp, " %d", val[i]);
185 break;
186 }
187 case DATA_TYPE_UINT16_ARRAY: {
188 uint16_t *val;
189 (void) nvpair_value_uint16_array(nvp, &val, &nelem);
190 for (i = 0; i < nelem; i++)
191 (void) fprintf(fp, " 0x%x", val[i]);
192 break;
193 }
194 case DATA_TYPE_INT32_ARRAY: {
195 int32_t *val;
196 (void) nvpair_value_int32_array(nvp, &val, &nelem);
197 for (i = 0; i < nelem; i++)
198 (void) fprintf(fp, " %d", val[i]);
199 break;
200 }
201 case DATA_TYPE_UINT32_ARRAY: {
202 uint32_t *val;
203 (void) nvpair_value_uint32_array(nvp, &val, &nelem);
204 for (i = 0; i < nelem; i++)
205 (void) fprintf(fp, " 0x%x", val[i]);
206 break;
207 }
208 case DATA_TYPE_INT64_ARRAY: {
209 int64_t *val;
210 (void) nvpair_value_int64_array(nvp, &val, &nelem);
211 for (i = 0; i < nelem; i++)
212 (void) fprintf(fp, " %" PRId64, val[i]);
213 break;
214 }
215 case DATA_TYPE_UINT64_ARRAY: {
216 uint64_t *val;
217 (void) nvpair_value_uint64_array(nvp, &val, &nelem);
218 for (i = 0; i < nelem; i++)
219 (void) fprintf(fp, " 0x%" PRIx64, val[i]);
220 break;
221 }
222 case DATA_TYPE_STRING_ARRAY: {
223 char **val;
224 (void) nvpair_value_string_array(nvp, &val, &nelem);
225 for (i = 0; i < nelem; i++)
226 (void) fprintf(fp, " %s", val[i]);
227 break;
228 }
229 case DATA_TYPE_HRTIME: {
230 hrtime_t val;
231 (void) nvpair_value_hrtime(nvp, &val);
232 (void) fprintf(fp, " 0x%jx", (intmax_t)val);
233 break;
234 }
235 case DATA_TYPE_NVLIST: {
236 nvlist_t *val;
237 (void) nvpair_value_nvlist(nvp, &val);
238 (void) fprintf(fp, " (embedded nvlist)\n");
239 nvlist_print_with_indent(fp, val, depth + 1);
240 indent(fp, depth + 1);
241 (void) fprintf(fp, "(end %s)\n", name);
242 break;
243 }
244 case DATA_TYPE_NVLIST_ARRAY: {
245 nvlist_t **val;
246 (void) nvpair_value_nvlist_array(nvp, &val, &nelem);
247 (void) fprintf(fp, " (array of embedded nvlists)\n");
248 for (i = 0; i < nelem; i++) {
249 indent(fp, depth + 1);
250 (void) fprintf(fp,
251 "(start %s[%d])\n", name, i);
252 nvlist_print_with_indent(fp, val[i], depth + 1);
253 indent(fp, depth + 1);
254 (void) fprintf(fp, "(end %s[%d])\n", name, i);
255 }
256 break;
257 }
258 default:
259 (void) fprintf(fp, " unknown data type (%d)", type);
260 break;
261 }
262 (void) fprintf(fp, "\n");
263 nvp = nvlist_next_nvpair(nvl, nvp);
264 }
265 }
266
267 void
268 nvlist_print(FILE *fp, nvlist_t *nvl)
269 {
270 nvlist_print_with_indent(fp, nvl, 0);
271 }
272
273
274 #define NVP(elem, type, vtype, ptype, format) { \
275 vtype value; \
276 \
277 (void) nvpair_value_##type(elem, &value); \
278 (void) printf("%*s%s: " format "\n", indent, "", \
279 nvpair_name(elem), (ptype)value); \
280 }
281
282 #define NVPA(elem, type, vtype, ptype, format) { \
283 uint_t i, count; \
284 vtype *value; \
285 \
286 (void) nvpair_value_##type(elem, &value, &count); \
287 for (i = 0; i < count; i++) { \
288 (void) printf("%*s%s[%d]: " format "\n", indent, "", \
289 nvpair_name(elem), i, (ptype)value[i]); \
290 } \
291 }
292
293 /*
294 * Similar to nvlist_print() but handles arrays slightly differently.
295 */
296 void
297 dump_nvlist(nvlist_t *list, int indent)
298 {
299 nvpair_t *elem = NULL;
300 boolean_t bool_value;
301 nvlist_t *nvlist_value;
302 nvlist_t **nvlist_array_value;
303 uint_t i, count;
304
305 if (list == NULL) {
306 return;
307 }
308
309 while ((elem = nvlist_next_nvpair(list, elem)) != NULL) {
310 switch (nvpair_type(elem)) {
311 case DATA_TYPE_BOOLEAN_VALUE:
312 (void) nvpair_value_boolean_value(elem, &bool_value);
313 (void) printf("%*s%s: %s\n", indent, "",
314 nvpair_name(elem), bool_value ? "true" : "false");
315 break;
316
317 case DATA_TYPE_BYTE:
318 NVP(elem, byte, uchar_t, int, "%u");
319 break;
320
321 case DATA_TYPE_INT8:
322 NVP(elem, int8, int8_t, int, "%d");
323 break;
324
325 case DATA_TYPE_UINT8:
326 NVP(elem, uint8, uint8_t, int, "%u");
327 break;
328
329 case DATA_TYPE_INT16:
330 NVP(elem, int16, int16_t, int, "%d");
331 break;
332
333 case DATA_TYPE_UINT16:
334 NVP(elem, uint16, uint16_t, int, "%u");
335 break;
336
337 case DATA_TYPE_INT32:
338 NVP(elem, int32, int32_t, long, "%ld");
339 break;
340
341 case DATA_TYPE_UINT32:
342 NVP(elem, uint32, uint32_t, ulong_t, "%lu");
343 break;
344
345 case DATA_TYPE_INT64:
346 NVP(elem, int64, int64_t, int64_t, "%" PRIx64);
347 break;
348
349 case DATA_TYPE_UINT64:
350 NVP(elem, uint64, uint64_t, uint64_t, "%" PRIu64);
351 break;
352
353 case DATA_TYPE_STRING:
354 NVP(elem, string, char *, char *, "'%s'");
355 break;
356
357 case DATA_TYPE_BYTE_ARRAY:
358 NVPA(elem, byte_array, uchar_t, int, "%u");
359 break;
360
361 case DATA_TYPE_INT8_ARRAY:
362 NVPA(elem, int8_array, int8_t, int, "%d");
363 break;
364
365 case DATA_TYPE_UINT8_ARRAY:
366 NVPA(elem, uint8_array, uint8_t, int, "%u");
367 break;
368
369 case DATA_TYPE_INT16_ARRAY:
370 NVPA(elem, int16_array, int16_t, int, "%d");
371 break;
372
373 case DATA_TYPE_UINT16_ARRAY:
374 NVPA(elem, uint16_array, uint16_t, int, "%u");
375 break;
376
377 case DATA_TYPE_INT32_ARRAY:
378 NVPA(elem, int32_array, int32_t, long, "%ld");
379 break;
380
381 case DATA_TYPE_UINT32_ARRAY:
382 NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu");
383 break;
384
385 case DATA_TYPE_INT64_ARRAY:
386 NVPA(elem, int64_array, int64_t, int64_t, "%" PRId64);
387 break;
388
389 case DATA_TYPE_UINT64_ARRAY:
390 NVPA(elem, uint64_array, uint64_t, uint64_t,
391 "%" PRIu64);
392 break;
393
394 case DATA_TYPE_STRING_ARRAY:
395 NVPA(elem, string_array, char *, char *, "'%s'");
396 break;
397
398 case DATA_TYPE_NVLIST:
399 (void) nvpair_value_nvlist(elem, &nvlist_value);
400 (void) printf("%*s%s:\n", indent, "",
401 nvpair_name(elem));
402 dump_nvlist(nvlist_value, indent + 4);
403 break;
404
405 case DATA_TYPE_NVLIST_ARRAY:
406 (void) nvpair_value_nvlist_array(elem,
407 &nvlist_array_value, &count);
408 for (i = 0; i < count; i++) {
409 (void) printf("%*s%s[%u]:\n", indent, "",
410 nvpair_name(elem), i);
411 dump_nvlist(nvlist_array_value[i], indent + 4);
412 }
413 break;
414
415 default:
416 (void) printf(dgettext(TEXT_DOMAIN, "bad config type "
417 "%d for %s\n"), nvpair_type(elem),
418 nvpair_name(elem));
419 }
420 }
421 }
422
423 /*
424 * Determine if string 'value' matches 'nvp' value. The 'value' string is
425 * converted, depending on the type of 'nvp', prior to match. For numeric
426 * types, a radix independent sscanf conversion of 'value' is used. If 'nvp'
427 * is an array type, 'ai' is the index into the array against which we are
428 * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass
429 * in a regex_t compilation of value in 'value_regex' to trigger regular
430 * expression string match instead of simple strcmp().
431 *
432 * Return 1 on match, 0 on no-match, and -1 on error. If the error is
433 * related to value syntax error and 'ep' is non-NULL, *ep will point into
434 * the 'value' string at the location where the error exists.
435 *
436 * NOTE: It may be possible to move the non-regex_t version of this into
437 * common code used by library/kernel/boot.
438 */
439 int
440 nvpair_value_match_regex(nvpair_t *nvp, int ai,
441 char *value, regex_t *value_regex, char **ep)
442 {
443 char *evalue;
444 uint_t a_len;
445 int sr;
446
447 if (ep)
448 *ep = NULL;
449
450 if ((nvp == NULL) || (value == NULL))
451 return (-1); /* error fail match - invalid args */
452
453 /* make sure array and index combination make sense */
454 if ((nvpair_type_is_array(nvp) && (ai < 0)) ||
455 (!nvpair_type_is_array(nvp) && (ai >= 0)))
456 return (-1); /* error fail match - bad index */
457
458 /* non-string values should be single 'chunk' */
459 if ((nvpair_type(nvp) != DATA_TYPE_STRING) &&
460 (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) {
461 value += strspn(value, " \t");
462 evalue = value + strcspn(value, " \t");
463 if (*evalue) {
464 if (ep)
465 *ep = evalue;
466 return (-1); /* error fail match - syntax */
467 }
468 }
469
470 sr = EOF;
471 switch (nvpair_type(nvp)) {
472 case DATA_TYPE_STRING: {
473 char *val;
474
475 /* check string value for match */
476 if (nvpair_value_string(nvp, &val) == 0) {
477 if (value_regex) {
478 if (regexec(value_regex, val,
479 (size_t)0, NULL, 0) == 0)
480 return (1); /* match */
481 } else {
482 if (strcmp(value, val) == 0)
483 return (1); /* match */
484 }
485 }
486 break;
487 }
488 case DATA_TYPE_STRING_ARRAY: {
489 char **val_array;
490
491 /* check indexed string value of array for match */
492 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
493 (ai < a_len)) {
494 if (value_regex) {
495 if (regexec(value_regex, val_array[ai],
496 (size_t)0, NULL, 0) == 0)
497 return (1);
498 } else {
499 if (strcmp(value, val_array[ai]) == 0)
500 return (1);
501 }
502 }
503 break;
504 }
505 case DATA_TYPE_BYTE: {
506 uchar_t val, val_arg;
507
508 /* scanf uchar_t from value and check for match */
509 sr = sscanf(value, "%c", &val_arg);
510 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) &&
511 (val == val_arg))
512 return (1);
513 break;
514 }
515 case DATA_TYPE_BYTE_ARRAY: {
516 uchar_t *val_array, val_arg;
517
518
519 /* check indexed value of array for match */
520 sr = sscanf(value, "%c", &val_arg);
521 if ((sr == 1) &&
522 (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
523 (ai < a_len) &&
524 (val_array[ai] == val_arg))
525 return (1);
526 break;
527 }
528 case DATA_TYPE_INT8: {
529 int8_t val, val_arg;
530
531 /* scanf int8_t from value and check for match */
532 sr = sscanf(value, "%"SCNi8, &val_arg);
533 if ((sr == 1) &&
534 (nvpair_value_int8(nvp, &val) == 0) &&
535 (val == val_arg))
536 return (1);
537 break;
538 }
539 case DATA_TYPE_INT8_ARRAY: {
540 int8_t *val_array, val_arg;
541
542 /* check indexed value of array for match */
543 sr = sscanf(value, "%"SCNi8, &val_arg);
544 if ((sr == 1) &&
545 (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
546 (ai < a_len) &&
547 (val_array[ai] == val_arg))
548 return (1);
549 break;
550 }
551 case DATA_TYPE_UINT8: {
552 uint8_t val, val_arg;
553
554 /* scanf uint8_t from value and check for match */
555 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
556 if ((sr == 1) &&
557 (nvpair_value_uint8(nvp, &val) == 0) &&
558 (val == val_arg))
559 return (1);
560 break;
561 }
562 case DATA_TYPE_UINT8_ARRAY: {
563 uint8_t *val_array, val_arg;
564
565 /* check indexed value of array for match */
566 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
567 if ((sr == 1) &&
568 (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
569 (ai < a_len) &&
570 (val_array[ai] == val_arg))
571 return (1);
572 break;
573 }
574 case DATA_TYPE_INT16: {
575 int16_t val, val_arg;
576
577 /* scanf int16_t from value and check for match */
578 sr = sscanf(value, "%"SCNi16, &val_arg);
579 if ((sr == 1) &&
580 (nvpair_value_int16(nvp, &val) == 0) &&
581 (val == val_arg))
582 return (1);
583 break;
584 }
585 case DATA_TYPE_INT16_ARRAY: {
586 int16_t *val_array, val_arg;
587
588 /* check indexed value of array for match */
589 sr = sscanf(value, "%"SCNi16, &val_arg);
590 if ((sr == 1) &&
591 (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
592 (ai < a_len) &&
593 (val_array[ai] == val_arg))
594 return (1);
595 break;
596 }
597 case DATA_TYPE_UINT16: {
598 uint16_t val, val_arg;
599
600 /* scanf uint16_t from value and check for match */
601 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
602 if ((sr == 1) &&
603 (nvpair_value_uint16(nvp, &val) == 0) &&
604 (val == val_arg))
605 return (1);
606 break;
607 }
608 case DATA_TYPE_UINT16_ARRAY: {
609 uint16_t *val_array, val_arg;
610
611 /* check indexed value of array for match */
612 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
613 if ((sr == 1) &&
614 (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
615 (ai < a_len) &&
616 (val_array[ai] == val_arg))
617 return (1);
618 break;
619 }
620 case DATA_TYPE_INT32: {
621 int32_t val, val_arg;
622
623 /* scanf int32_t from value and check for match */
624 sr = sscanf(value, "%"SCNi32, &val_arg);
625 if ((sr == 1) &&
626 (nvpair_value_int32(nvp, &val) == 0) &&
627 (val == val_arg))
628 return (1);
629 break;
630 }
631 case DATA_TYPE_INT32_ARRAY: {
632 int32_t *val_array, val_arg;
633
634 /* check indexed value of array for match */
635 sr = sscanf(value, "%"SCNi32, &val_arg);
636 if ((sr == 1) &&
637 (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
638 (ai < a_len) &&
639 (val_array[ai] == val_arg))
640 return (1);
641 break;
642 }
643 case DATA_TYPE_UINT32: {
644 uint32_t val, val_arg;
645
646 /* scanf uint32_t from value and check for match */
647 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
648 if ((sr == 1) &&
649 (nvpair_value_uint32(nvp, &val) == 0) &&
650 (val == val_arg))
651 return (1);
652 break;
653 }
654 case DATA_TYPE_UINT32_ARRAY: {
655 uint32_t *val_array, val_arg;
656
657 /* check indexed value of array for match */
658 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
659 if ((sr == 1) &&
660 (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
661 (ai < a_len) &&
662 (val_array[ai] == val_arg))
663 return (1);
664 break;
665 }
666 case DATA_TYPE_INT64: {
667 int64_t val, val_arg;
668
669 /* scanf int64_t from value and check for match */
670 sr = sscanf(value, "%"SCNi64, &val_arg);
671 if ((sr == 1) &&
672 (nvpair_value_int64(nvp, &val) == 0) &&
673 (val == val_arg))
674 return (1);
675 break;
676 }
677 case DATA_TYPE_INT64_ARRAY: {
678 int64_t *val_array, val_arg;
679
680 /* check indexed value of array for match */
681 sr = sscanf(value, "%"SCNi64, &val_arg);
682 if ((sr == 1) &&
683 (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
684 (ai < a_len) &&
685 (val_array[ai] == val_arg))
686 return (1);
687 break;
688 }
689 case DATA_TYPE_UINT64: {
690 uint64_t val_arg, val;
691
692 /* scanf uint64_t from value and check for match */
693 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
694 if ((sr == 1) &&
695 (nvpair_value_uint64(nvp, &val) == 0) &&
696 (val == val_arg))
697 return (1);
698 break;
699 }
700 case DATA_TYPE_UINT64_ARRAY: {
701 uint64_t *val_array, val_arg;
702
703 /* check indexed value of array for match */
704 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
705 if ((sr == 1) &&
706 (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
707 (ai < a_len) &&
708 (val_array[ai] == val_arg))
709 return (1);
710 break;
711 }
712 case DATA_TYPE_BOOLEAN_VALUE: {
713 boolean_t val, val_arg;
714
715 /* scanf boolean_t from value and check for match */
716 sr = sscanf(value, "%"SCNi32, &val_arg);
717 if ((sr == 1) &&
718 (nvpair_value_boolean_value(nvp, &val) == 0) &&
719 (val == val_arg))
720 return (1);
721 break;
722 }
723 case DATA_TYPE_BOOLEAN_ARRAY: {
724 boolean_t *val_array, val_arg;
725
726 /* check indexed value of array for match */
727 sr = sscanf(value, "%"SCNi32, &val_arg);
728 if ((sr == 1) &&
729 (nvpair_value_boolean_array(nvp,
730 &val_array, &a_len) == 0) &&
731 (ai < a_len) &&
732 (val_array[ai] == val_arg))
733 return (1);
734 break;
735 }
736 case DATA_TYPE_HRTIME:
737 case DATA_TYPE_NVLIST:
738 case DATA_TYPE_NVLIST_ARRAY:
739 case DATA_TYPE_BOOLEAN:
740 case DATA_TYPE_DOUBLE:
741 case DATA_TYPE_UNKNOWN:
742 default:
743 /*
744 * unknown/unsupported data type
745 */
746 return (-1); /* error fail match */
747 }
748
749 /*
750 * check to see if sscanf failed conversion, return approximate
751 * pointer to problem
752 */
753 if (sr != 1) {
754 if (ep)
755 *ep = value;
756 return (-1); /* error fail match - syntax */
757 }
758
759 return (0); /* fail match */
760 }
761
762 int
763 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
764 {
765 return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
766 }
767