libnvpair.c revision 1.1.1.2.6.1 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, " %lld", (longlong_t)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%llx", (u_longlong_t)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, " %lld", (longlong_t)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%llx",
220 (u_longlong_t)val[i]);
221 break;
222 }
223 case DATA_TYPE_STRING_ARRAY: {
224 char **val;
225 (void) nvpair_value_string_array(nvp, &val, &nelem);
226 for (i = 0; i < nelem; i++)
227 (void) fprintf(fp, " %s", val[i]);
228 break;
229 }
230 case DATA_TYPE_HRTIME: {
231 hrtime_t val;
232 (void) nvpair_value_hrtime(nvp, &val);
233 (void) fprintf(fp, " 0x%llx", val);
234 break;
235 }
236 case DATA_TYPE_NVLIST: {
237 nvlist_t *val;
238 (void) nvpair_value_nvlist(nvp, &val);
239 (void) fprintf(fp, " (embedded nvlist)\n");
240 nvlist_print_with_indent(fp, val, depth + 1);
241 indent(fp, depth + 1);
242 (void) fprintf(fp, "(end %s)\n", name);
243 break;
244 }
245 case DATA_TYPE_NVLIST_ARRAY: {
246 nvlist_t **val;
247 (void) nvpair_value_nvlist_array(nvp, &val, &nelem);
248 (void) fprintf(fp, " (array of embedded nvlists)\n");
249 for (i = 0; i < nelem; i++) {
250 indent(fp, depth + 1);
251 (void) fprintf(fp,
252 "(start %s[%d])\n", name, i);
253 nvlist_print_with_indent(fp, val[i], depth + 1);
254 indent(fp, depth + 1);
255 (void) fprintf(fp, "(end %s[%d])\n", name, i);
256 }
257 break;
258 }
259 default:
260 (void) fprintf(fp, " unknown data type (%d)", type);
261 break;
262 }
263 (void) fprintf(fp, "\n");
264 nvp = nvlist_next_nvpair(nvl, nvp);
265 }
266 }
267
268 void
269 nvlist_print(FILE *fp, nvlist_t *nvl)
270 {
271 nvlist_print_with_indent(fp, nvl, 0);
272 }
273
274
275 #define NVP(elem, type, vtype, ptype, format) { \
276 vtype value; \
277 \
278 (void) nvpair_value_##type(elem, &value); \
279 (void) printf("%*s%s: " format "\n", indent, "", \
280 nvpair_name(elem), (ptype)value); \
281 }
282
283 #define NVPA(elem, type, vtype, ptype, format) { \
284 uint_t i, count; \
285 vtype *value; \
286 \
287 (void) nvpair_value_##type(elem, &value, &count); \
288 for (i = 0; i < count; i++) { \
289 (void) printf("%*s%s[%d]: " format "\n", indent, "", \
290 nvpair_name(elem), i, (ptype)value[i]); \
291 } \
292 }
293
294 /*
295 * Similar to nvlist_print() but handles arrays slightly differently.
296 */
297 void
298 dump_nvlist(nvlist_t *list, int indent)
299 {
300 nvpair_t *elem = NULL;
301 boolean_t bool_value;
302 nvlist_t *nvlist_value;
303 nvlist_t **nvlist_array_value;
304 uint_t i, count;
305
306 if (list == NULL) {
307 return;
308 }
309
310 while ((elem = nvlist_next_nvpair(list, elem)) != NULL) {
311 switch (nvpair_type(elem)) {
312 case DATA_TYPE_BOOLEAN_VALUE:
313 (void) nvpair_value_boolean_value(elem, &bool_value);
314 (void) printf("%*s%s: %s\n", indent, "",
315 nvpair_name(elem), bool_value ? "true" : "false");
316 break;
317
318 case DATA_TYPE_BYTE:
319 NVP(elem, byte, uchar_t, int, "%u");
320 break;
321
322 case DATA_TYPE_INT8:
323 NVP(elem, int8, int8_t, int, "%d");
324 break;
325
326 case DATA_TYPE_UINT8:
327 NVP(elem, uint8, uint8_t, int, "%u");
328 break;
329
330 case DATA_TYPE_INT16:
331 NVP(elem, int16, int16_t, int, "%d");
332 break;
333
334 case DATA_TYPE_UINT16:
335 NVP(elem, uint16, uint16_t, int, "%u");
336 break;
337
338 case DATA_TYPE_INT32:
339 NVP(elem, int32, int32_t, long, "%ld");
340 break;
341
342 case DATA_TYPE_UINT32:
343 NVP(elem, uint32, uint32_t, ulong_t, "%lu");
344 break;
345
346 case DATA_TYPE_INT64:
347 NVP(elem, int64, int64_t, longlong_t, "%lld");
348 break;
349
350 case DATA_TYPE_UINT64:
351 NVP(elem, uint64, uint64_t, u_longlong_t, "%llu");
352 break;
353
354 case DATA_TYPE_STRING:
355 NVP(elem, string, char *, char *, "'%s'");
356 break;
357
358 case DATA_TYPE_BYTE_ARRAY:
359 NVPA(elem, byte_array, uchar_t, int, "%u");
360 break;
361
362 case DATA_TYPE_INT8_ARRAY:
363 NVPA(elem, int8_array, int8_t, int, "%d");
364 break;
365
366 case DATA_TYPE_UINT8_ARRAY:
367 NVPA(elem, uint8_array, uint8_t, int, "%u");
368 break;
369
370 case DATA_TYPE_INT16_ARRAY:
371 NVPA(elem, int16_array, int16_t, int, "%d");
372 break;
373
374 case DATA_TYPE_UINT16_ARRAY:
375 NVPA(elem, uint16_array, uint16_t, int, "%u");
376 break;
377
378 case DATA_TYPE_INT32_ARRAY:
379 NVPA(elem, int32_array, int32_t, long, "%ld");
380 break;
381
382 case DATA_TYPE_UINT32_ARRAY:
383 NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu");
384 break;
385
386 case DATA_TYPE_INT64_ARRAY:
387 NVPA(elem, int64_array, int64_t, longlong_t, "%lld");
388 break;
389
390 case DATA_TYPE_UINT64_ARRAY:
391 NVPA(elem, uint64_array, uint64_t, u_longlong_t,
392 "%llu");
393 break;
394
395 case DATA_TYPE_STRING_ARRAY:
396 NVPA(elem, string_array, char *, char *, "'%s'");
397 break;
398
399 case DATA_TYPE_NVLIST:
400 (void) nvpair_value_nvlist(elem, &nvlist_value);
401 (void) printf("%*s%s:\n", indent, "",
402 nvpair_name(elem));
403 dump_nvlist(nvlist_value, indent + 4);
404 break;
405
406 case DATA_TYPE_NVLIST_ARRAY:
407 (void) nvpair_value_nvlist_array(elem,
408 &nvlist_array_value, &count);
409 for (i = 0; i < count; i++) {
410 (void) printf("%*s%s[%u]:\n", indent, "",
411 nvpair_name(elem), i);
412 dump_nvlist(nvlist_array_value[i], indent + 4);
413 }
414 break;
415
416 default:
417 (void) printf(dgettext(TEXT_DOMAIN, "bad config type "
418 "%d for %s\n"), nvpair_type(elem),
419 nvpair_name(elem));
420 }
421 }
422 }
423
424 /*
425 * Determine if string 'value' matches 'nvp' value. The 'value' string is
426 * converted, depending on the type of 'nvp', prior to match. For numeric
427 * types, a radix independent sscanf conversion of 'value' is used. If 'nvp'
428 * is an array type, 'ai' is the index into the array against which we are
429 * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass
430 * in a regex_t compilation of value in 'value_regex' to trigger regular
431 * expression string match instead of simple strcmp().
432 *
433 * Return 1 on match, 0 on no-match, and -1 on error. If the error is
434 * related to value syntax error and 'ep' is non-NULL, *ep will point into
435 * the 'value' string at the location where the error exists.
436 *
437 * NOTE: It may be possible to move the non-regex_t version of this into
438 * common code used by library/kernel/boot.
439 */
440 int
441 nvpair_value_match_regex(nvpair_t *nvp, int ai,
442 char *value, regex_t *value_regex, char **ep)
443 {
444 char *evalue;
445 uint_t a_len;
446 int sr;
447
448 if (ep)
449 *ep = NULL;
450
451 if ((nvp == NULL) || (value == NULL))
452 return (-1); /* error fail match - invalid args */
453
454 /* make sure array and index combination make sense */
455 if ((nvpair_type_is_array(nvp) && (ai < 0)) ||
456 (!nvpair_type_is_array(nvp) && (ai >= 0)))
457 return (-1); /* error fail match - bad index */
458
459 /* non-string values should be single 'chunk' */
460 if ((nvpair_type(nvp) != DATA_TYPE_STRING) &&
461 (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) {
462 value += strspn(value, " \t");
463 evalue = value + strcspn(value, " \t");
464 if (*evalue) {
465 if (ep)
466 *ep = evalue;
467 return (-1); /* error fail match - syntax */
468 }
469 }
470
471 sr = EOF;
472 switch (nvpair_type(nvp)) {
473 case DATA_TYPE_STRING: {
474 char *val;
475
476 /* check string value for match */
477 if (nvpair_value_string(nvp, &val) == 0) {
478 if (value_regex) {
479 if (regexec(value_regex, val,
480 (size_t)0, NULL, 0) == 0)
481 return (1); /* match */
482 } else {
483 if (strcmp(value, val) == 0)
484 return (1); /* match */
485 }
486 }
487 break;
488 }
489 case DATA_TYPE_STRING_ARRAY: {
490 char **val_array;
491
492 /* check indexed string value of array for match */
493 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
494 (ai < a_len)) {
495 if (value_regex) {
496 if (regexec(value_regex, val_array[ai],
497 (size_t)0, NULL, 0) == 0)
498 return (1);
499 } else {
500 if (strcmp(value, val_array[ai]) == 0)
501 return (1);
502 }
503 }
504 break;
505 }
506 case DATA_TYPE_BYTE: {
507 uchar_t val, val_arg;
508
509 /* scanf uchar_t from value and check for match */
510 sr = sscanf(value, "%c", &val_arg);
511 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) &&
512 (val == val_arg))
513 return (1);
514 break;
515 }
516 case DATA_TYPE_BYTE_ARRAY: {
517 uchar_t *val_array, val_arg;
518
519
520 /* check indexed value of array for match */
521 sr = sscanf(value, "%c", &val_arg);
522 if ((sr == 1) &&
523 (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
524 (ai < a_len) &&
525 (val_array[ai] == val_arg))
526 return (1);
527 break;
528 }
529 case DATA_TYPE_INT8: {
530 int8_t val, val_arg;
531
532 /* scanf int8_t from value and check for match */
533 sr = sscanf(value, "%"SCNi8, &val_arg);
534 if ((sr == 1) &&
535 (nvpair_value_int8(nvp, &val) == 0) &&
536 (val == val_arg))
537 return (1);
538 break;
539 }
540 case DATA_TYPE_INT8_ARRAY: {
541 int8_t *val_array, val_arg;
542
543 /* check indexed value of array for match */
544 sr = sscanf(value, "%"SCNi8, &val_arg);
545 if ((sr == 1) &&
546 (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
547 (ai < a_len) &&
548 (val_array[ai] == val_arg))
549 return (1);
550 break;
551 }
552 case DATA_TYPE_UINT8: {
553 uint8_t val, val_arg;
554
555 /* scanf uint8_t from value and check for match */
556 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
557 if ((sr == 1) &&
558 (nvpair_value_uint8(nvp, &val) == 0) &&
559 (val == val_arg))
560 return (1);
561 break;
562 }
563 case DATA_TYPE_UINT8_ARRAY: {
564 uint8_t *val_array, val_arg;
565
566 /* check indexed value of array for match */
567 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
568 if ((sr == 1) &&
569 (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
570 (ai < a_len) &&
571 (val_array[ai] == val_arg))
572 return (1);
573 break;
574 }
575 case DATA_TYPE_INT16: {
576 int16_t val, val_arg;
577
578 /* scanf int16_t from value and check for match */
579 sr = sscanf(value, "%"SCNi16, &val_arg);
580 if ((sr == 1) &&
581 (nvpair_value_int16(nvp, &val) == 0) &&
582 (val == val_arg))
583 return (1);
584 break;
585 }
586 case DATA_TYPE_INT16_ARRAY: {
587 int16_t *val_array, val_arg;
588
589 /* check indexed value of array for match */
590 sr = sscanf(value, "%"SCNi16, &val_arg);
591 if ((sr == 1) &&
592 (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
593 (ai < a_len) &&
594 (val_array[ai] == val_arg))
595 return (1);
596 break;
597 }
598 case DATA_TYPE_UINT16: {
599 uint16_t val, val_arg;
600
601 /* scanf uint16_t from value and check for match */
602 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
603 if ((sr == 1) &&
604 (nvpair_value_uint16(nvp, &val) == 0) &&
605 (val == val_arg))
606 return (1);
607 break;
608 }
609 case DATA_TYPE_UINT16_ARRAY: {
610 uint16_t *val_array, val_arg;
611
612 /* check indexed value of array for match */
613 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
614 if ((sr == 1) &&
615 (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
616 (ai < a_len) &&
617 (val_array[ai] == val_arg))
618 return (1);
619 break;
620 }
621 case DATA_TYPE_INT32: {
622 int32_t val, val_arg;
623
624 /* scanf int32_t from value and check for match */
625 sr = sscanf(value, "%"SCNi32, &val_arg);
626 if ((sr == 1) &&
627 (nvpair_value_int32(nvp, &val) == 0) &&
628 (val == val_arg))
629 return (1);
630 break;
631 }
632 case DATA_TYPE_INT32_ARRAY: {
633 int32_t *val_array, val_arg;
634
635 /* check indexed value of array for match */
636 sr = sscanf(value, "%"SCNi32, &val_arg);
637 if ((sr == 1) &&
638 (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
639 (ai < a_len) &&
640 (val_array[ai] == val_arg))
641 return (1);
642 break;
643 }
644 case DATA_TYPE_UINT32: {
645 uint32_t val, val_arg;
646
647 /* scanf uint32_t from value and check for match */
648 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
649 if ((sr == 1) &&
650 (nvpair_value_uint32(nvp, &val) == 0) &&
651 (val == val_arg))
652 return (1);
653 break;
654 }
655 case DATA_TYPE_UINT32_ARRAY: {
656 uint32_t *val_array, val_arg;
657
658 /* check indexed value of array for match */
659 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
660 if ((sr == 1) &&
661 (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
662 (ai < a_len) &&
663 (val_array[ai] == val_arg))
664 return (1);
665 break;
666 }
667 case DATA_TYPE_INT64: {
668 int64_t val, val_arg;
669
670 /* scanf int64_t from value and check for match */
671 sr = sscanf(value, "%"SCNi64, &val_arg);
672 if ((sr == 1) &&
673 (nvpair_value_int64(nvp, &val) == 0) &&
674 (val == val_arg))
675 return (1);
676 break;
677 }
678 case DATA_TYPE_INT64_ARRAY: {
679 int64_t *val_array, val_arg;
680
681 /* check indexed value of array for match */
682 sr = sscanf(value, "%"SCNi64, &val_arg);
683 if ((sr == 1) &&
684 (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
685 (ai < a_len) &&
686 (val_array[ai] == val_arg))
687 return (1);
688 break;
689 }
690 case DATA_TYPE_UINT64: {
691 uint64_t val_arg, val;
692
693 /* scanf uint64_t from value and check for match */
694 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
695 if ((sr == 1) &&
696 (nvpair_value_uint64(nvp, &val) == 0) &&
697 (val == val_arg))
698 return (1);
699 break;
700 }
701 case DATA_TYPE_UINT64_ARRAY: {
702 uint64_t *val_array, val_arg;
703
704 /* check indexed value of array for match */
705 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
706 if ((sr == 1) &&
707 (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
708 (ai < a_len) &&
709 (val_array[ai] == val_arg))
710 return (1);
711 break;
712 }
713 case DATA_TYPE_BOOLEAN_VALUE: {
714 boolean_t val, val_arg;
715
716 /* scanf boolean_t from value and check for match */
717 sr = sscanf(value, "%"SCNi32, &val_arg);
718 if ((sr == 1) &&
719 (nvpair_value_boolean_value(nvp, &val) == 0) &&
720 (val == val_arg))
721 return (1);
722 break;
723 }
724 case DATA_TYPE_BOOLEAN_ARRAY: {
725 boolean_t *val_array, val_arg;
726
727 /* check indexed value of array for match */
728 sr = sscanf(value, "%"SCNi32, &val_arg);
729 if ((sr == 1) &&
730 (nvpair_value_boolean_array(nvp,
731 &val_array, &a_len) == 0) &&
732 (ai < a_len) &&
733 (val_array[ai] == val_arg))
734 return (1);
735 break;
736 }
737 case DATA_TYPE_HRTIME:
738 case DATA_TYPE_NVLIST:
739 case DATA_TYPE_NVLIST_ARRAY:
740 case DATA_TYPE_BOOLEAN:
741 case DATA_TYPE_DOUBLE:
742 case DATA_TYPE_UNKNOWN:
743 default:
744 /*
745 * unknown/unsupported data type
746 */
747 return (-1); /* error fail match */
748 }
749
750 /*
751 * check to see if sscanf failed conversion, return approximate
752 * pointer to problem
753 */
754 if (sr != 1) {
755 if (ep)
756 *ep = value;
757 return (-1); /* error fail match - syntax */
758 }
759
760 return (0); /* fail match */
761 }
762
763 int
764 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
765 {
766 return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
767 }
768