Update core ZFS code from build 121 to build 141.
[zfs.git] / lib / libnvpair / libnvpair.c
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 }