xref: /netbsd-src/external/cddl/osnet/dist/lib/libnvpair/libnvpair.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
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