xref: /illumos-gate/usr/src/lib/libnvpair/libnvpair.c (revision 269e59f9a28bf47e0f463e64fc5af4a408b73b21)
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%llf", 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