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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <sys/types.h>
31 #include <sys/inttypes.h>
32 #include "libnvpair.h"
35 * libnvpair - A tools library for manipulating <name, value> pairs.
37 * This library provides routines packing an unpacking nv pairs
38 * for transporting data across process boundaries, transporting
39 * between kernel and userland, and possibly saving onto disk files.
43 indent(FILE *fp, int depth)
46 (void) fprintf(fp, "\t");
50 * nvlist_print - Prints elements in an event buffer
54 nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth)
65 (void) fprintf(fp, "nvlist version: %d\n", NVL_VERSION(nvl));
67 nvp = nvlist_next_nvpair(nvl, NULL);
70 data_type_t type = nvpair_type(nvp);
73 name = nvpair_name(nvp);
74 (void) fprintf(fp, "\t%s =", name);
77 case DATA_TYPE_BOOLEAN: {
78 (void) fprintf(fp, " 1");
81 case DATA_TYPE_BOOLEAN_VALUE: {
83 (void) nvpair_value_boolean_value(nvp, &val);
84 (void) fprintf(fp, " %d", val);
87 case DATA_TYPE_BYTE: {
89 (void) nvpair_value_byte(nvp, &val);
90 (void) fprintf(fp, " 0x%2.2x", val);
93 case DATA_TYPE_INT8: {
95 (void) nvpair_value_int8(nvp, &val);
96 (void) fprintf(fp, " %d", val);
99 case DATA_TYPE_UINT8: {
101 (void) nvpair_value_uint8(nvp, &val);
102 (void) fprintf(fp, " 0x%x", val);
105 case DATA_TYPE_INT16: {
107 (void) nvpair_value_int16(nvp, &val);
108 (void) fprintf(fp, " %d", val);
111 case DATA_TYPE_UINT16: {
113 (void) nvpair_value_uint16(nvp, &val);
114 (void) fprintf(fp, " 0x%x", val);
117 case DATA_TYPE_INT32: {
119 (void) nvpair_value_int32(nvp, &val);
120 (void) fprintf(fp, " %d", val);
123 case DATA_TYPE_UINT32: {
125 (void) nvpair_value_uint32(nvp, &val);
126 (void) fprintf(fp, " 0x%x", val);
129 case DATA_TYPE_INT64: {
131 (void) nvpair_value_int64(nvp, &val);
132 (void) fprintf(fp, " %lld", (longlong_t)val);
135 case DATA_TYPE_UINT64: {
137 (void) nvpair_value_uint64(nvp, &val);
138 (void) fprintf(fp, " 0x%llx", (u_longlong_t)val);
141 case DATA_TYPE_DOUBLE: {
143 (void) nvpair_value_double(nvp, &val);
144 (void) fprintf(fp, " 0x%llf", val);
147 case DATA_TYPE_STRING: {
149 (void) nvpair_value_string(nvp, &val);
150 (void) fprintf(fp, " %s", val);
153 case DATA_TYPE_BOOLEAN_ARRAY: {
155 (void) nvpair_value_boolean_array(nvp, &val, &nelem);
156 for (i = 0; i < nelem; i++)
157 (void) fprintf(fp, " %d", val[i]);
160 case DATA_TYPE_BYTE_ARRAY: {
162 (void) nvpair_value_byte_array(nvp, &val, &nelem);
163 for (i = 0; i < nelem; i++)
164 (void) fprintf(fp, " 0x%2.2x", val[i]);
167 case DATA_TYPE_INT8_ARRAY: {
169 (void) nvpair_value_int8_array(nvp, &val, &nelem);
170 for (i = 0; i < nelem; i++)
171 (void) fprintf(fp, " %d", val[i]);
174 case DATA_TYPE_UINT8_ARRAY: {
176 (void) nvpair_value_uint8_array(nvp, &val, &nelem);
177 for (i = 0; i < nelem; i++)
178 (void) fprintf(fp, " 0x%x", val[i]);
181 case DATA_TYPE_INT16_ARRAY: {
183 (void) nvpair_value_int16_array(nvp, &val, &nelem);
184 for (i = 0; i < nelem; i++)
185 (void) fprintf(fp, " %d", val[i]);
188 case DATA_TYPE_UINT16_ARRAY: {
190 (void) nvpair_value_uint16_array(nvp, &val, &nelem);
191 for (i = 0; i < nelem; i++)
192 (void) fprintf(fp, " 0x%x", val[i]);
195 case DATA_TYPE_INT32_ARRAY: {
197 (void) nvpair_value_int32_array(nvp, &val, &nelem);
198 for (i = 0; i < nelem; i++)
199 (void) fprintf(fp, " %d", val[i]);
202 case DATA_TYPE_UINT32_ARRAY: {
204 (void) nvpair_value_uint32_array(nvp, &val, &nelem);
205 for (i = 0; i < nelem; i++)
206 (void) fprintf(fp, " 0x%x", val[i]);
209 case DATA_TYPE_INT64_ARRAY: {
211 (void) nvpair_value_int64_array(nvp, &val, &nelem);
212 for (i = 0; i < nelem; i++)
213 (void) fprintf(fp, " %lld", (longlong_t)val[i]);
216 case DATA_TYPE_UINT64_ARRAY: {
218 (void) nvpair_value_uint64_array(nvp, &val, &nelem);
219 for (i = 0; i < nelem; i++)
220 (void) fprintf(fp, " 0x%llx",
221 (u_longlong_t)val[i]);
224 case DATA_TYPE_STRING_ARRAY: {
226 (void) nvpair_value_string_array(nvp, &val, &nelem);
227 for (i = 0; i < nelem; i++)
228 (void) fprintf(fp, " %s", val[i]);
231 case DATA_TYPE_HRTIME: {
233 (void) nvpair_value_hrtime(nvp, &val);
234 (void) fprintf(fp, " 0x%llx", val);
237 case DATA_TYPE_NVLIST: {
239 (void) nvpair_value_nvlist(nvp, &val);
240 (void) fprintf(fp, " (embedded nvlist)\n");
241 nvlist_print_with_indent(fp, val, depth + 1);
242 indent(fp, depth + 1);
243 (void) fprintf(fp, "(end %s)\n", name);
246 case DATA_TYPE_NVLIST_ARRAY: {
248 (void) nvpair_value_nvlist_array(nvp, &val, &nelem);
249 (void) fprintf(fp, " (array of embedded nvlists)\n");
250 for (i = 0; i < nelem; i++) {
251 indent(fp, depth + 1);
253 "(start %s[%d])\n", name, i);
254 nvlist_print_with_indent(fp, val[i], depth + 1);
255 indent(fp, depth + 1);
256 (void) fprintf(fp, "(end %s[%d])\n", name, i);
261 (void) fprintf(fp, " unknown data type (%d)", type);
264 (void) fprintf(fp, "\n");
265 nvp = nvlist_next_nvpair(nvl, nvp);
270 nvlist_print(FILE *fp, nvlist_t *nvl)
272 nvlist_print_with_indent(fp, nvl, 0);
276 * Determine if string 'value' matches 'nvp' value. The 'value' string is
277 * converted, depending on the type of 'nvp', prior to match. For numeric
278 * types, a radix independent sscanf conversion of 'value' is used. If 'nvp'
279 * is an array type, 'ai' is the index into the array against which we are
280 * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass
281 * in a regex_t compilation of value in 'value_regex' to trigger regular
282 * expression string match instead of simple strcmp().
284 * Return 1 on match, 0 on no-match, and -1 on error. If the error is
285 * related to value syntax error and 'ep' is non-NULL, *ep will point into
286 * the 'value' string at the location where the error exists.
288 * NOTE: It may be possible to move the non-regex_t version of this into
289 * common code used by library/kernel/boot.
292 nvpair_value_match_regex(nvpair_t *nvp, int ai,
293 char *value, regex_t *value_regex, char **ep)
302 if ((nvp == NULL) || (value == NULL))
303 return (-1); /* error fail match - invalid args */
305 /* make sure array and index combination make sense */
306 if ((nvpair_type_is_array(nvp) && (ai < 0)) ||
307 (!nvpair_type_is_array(nvp) && (ai >= 0)))
308 return (-1); /* error fail match - bad index */
310 /* non-string values should be single 'chunk' */
311 if ((nvpair_type(nvp) != DATA_TYPE_STRING) &&
312 (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) {
313 value += strspn(value, " \t");
314 evalue = value + strcspn(value, " \t");
318 return (-1); /* error fail match - syntax */
323 switch (nvpair_type(nvp)) {
324 case DATA_TYPE_STRING: {
327 /* check string value for match */
328 if (nvpair_value_string(nvp, &val) == 0) {
330 if (regexec(value_regex, val,
331 (size_t)0, NULL, 0) == 0)
332 return (1); /* match */
334 if (strcmp(value, val) == 0)
335 return (1); /* match */
340 case DATA_TYPE_STRING_ARRAY: {
343 /* check indexed string value of array for match */
344 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
347 if (regexec(value_regex, val_array[ai],
348 (size_t)0, NULL, 0) == 0)
351 if (strcmp(value, val_array[ai]) == 0)
357 case DATA_TYPE_BYTE: {
358 uchar_t val, val_arg;
360 /* scanf uchar_t from value and check for match */
361 sr = sscanf(value, "%c", &val_arg);
362 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) &&
367 case DATA_TYPE_BYTE_ARRAY: {
368 uchar_t *val_array, val_arg;
371 /* check indexed value of array for match */
372 sr = sscanf(value, "%c", &val_arg);
374 (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
376 (val_array[ai] == val_arg))
380 case DATA_TYPE_INT8: {
383 /* scanf int8_t from value and check for match */
384 sr = sscanf(value, "%"SCNi8, &val_arg);
386 (nvpair_value_int8(nvp, &val) == 0) &&
391 case DATA_TYPE_INT8_ARRAY: {
392 int8_t *val_array, val_arg;
394 /* check indexed value of array for match */
395 sr = sscanf(value, "%"SCNi8, &val_arg);
397 (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
399 (val_array[ai] == val_arg))
403 case DATA_TYPE_UINT8: {
404 uint8_t val, val_arg;
406 /* scanf uint8_t from value and check for match */
407 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
409 (nvpair_value_uint8(nvp, &val) == 0) &&
414 case DATA_TYPE_UINT8_ARRAY: {
415 uint8_t *val_array, val_arg;
417 /* check indexed value of array for match */
418 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
420 (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
422 (val_array[ai] == val_arg))
426 case DATA_TYPE_INT16: {
427 int16_t val, val_arg;
429 /* scanf int16_t from value and check for match */
430 sr = sscanf(value, "%"SCNi16, &val_arg);
432 (nvpair_value_int16(nvp, &val) == 0) &&
437 case DATA_TYPE_INT16_ARRAY: {
438 int16_t *val_array, val_arg;
440 /* check indexed value of array for match */
441 sr = sscanf(value, "%"SCNi16, &val_arg);
443 (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
445 (val_array[ai] == val_arg))
449 case DATA_TYPE_UINT16: {
450 uint16_t val, val_arg;
452 /* scanf uint16_t from value and check for match */
453 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
455 (nvpair_value_uint16(nvp, &val) == 0) &&
460 case DATA_TYPE_UINT16_ARRAY: {
461 uint16_t *val_array, val_arg;
463 /* check indexed value of array for match */
464 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
466 (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
468 (val_array[ai] == val_arg))
472 case DATA_TYPE_INT32: {
473 int32_t val, val_arg;
475 /* scanf int32_t from value and check for match */
476 sr = sscanf(value, "%"SCNi32, &val_arg);
478 (nvpair_value_int32(nvp, &val) == 0) &&
483 case DATA_TYPE_INT32_ARRAY: {
484 int32_t *val_array, val_arg;
486 /* check indexed value of array for match */
487 sr = sscanf(value, "%"SCNi32, &val_arg);
489 (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
491 (val_array[ai] == val_arg))
495 case DATA_TYPE_UINT32: {
496 uint32_t val, val_arg;
498 /* scanf uint32_t from value and check for match */
499 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
501 (nvpair_value_uint32(nvp, &val) == 0) &&
506 case DATA_TYPE_UINT32_ARRAY: {
507 uint32_t *val_array, val_arg;
509 /* check indexed value of array for match */
510 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
512 (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
514 (val_array[ai] == val_arg))
518 case DATA_TYPE_INT64: {
519 int64_t val, val_arg;
521 /* scanf int64_t from value and check for match */
522 sr = sscanf(value, "%"SCNi64, &val_arg);
524 (nvpair_value_int64(nvp, &val) == 0) &&
529 case DATA_TYPE_INT64_ARRAY: {
530 int64_t *val_array, val_arg;
532 /* check indexed value of array for match */
533 sr = sscanf(value, "%"SCNi64, &val_arg);
535 (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
537 (val_array[ai] == val_arg))
541 case DATA_TYPE_UINT64: {
542 uint64_t val_arg, val;
544 /* scanf uint64_t from value and check for match */
545 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
547 (nvpair_value_uint64(nvp, &val) == 0) &&
552 case DATA_TYPE_UINT64_ARRAY: {
553 uint64_t *val_array, val_arg;
555 /* check indexed value of array for match */
556 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
558 (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
560 (val_array[ai] == val_arg))
564 case DATA_TYPE_BOOLEAN_VALUE: {
565 boolean_t val, val_arg;
567 /* scanf boolean_t from value and check for match */
568 sr = sscanf(value, "%"SCNi32, &val_arg);
570 (nvpair_value_boolean_value(nvp, &val) == 0) &&
575 case DATA_TYPE_BOOLEAN_ARRAY: {
576 boolean_t *val_array, val_arg;
578 /* check indexed value of array for match */
579 sr = sscanf(value, "%"SCNi32, &val_arg);
581 (nvpair_value_boolean_array(nvp,
582 &val_array, &a_len) == 0) &&
584 (val_array[ai] == val_arg))
588 case DATA_TYPE_HRTIME:
589 case DATA_TYPE_NVLIST:
590 case DATA_TYPE_NVLIST_ARRAY:
591 case DATA_TYPE_BOOLEAN:
592 case DATA_TYPE_DOUBLE:
593 case DATA_TYPE_UNKNOWN:
596 * unknown/unsupported data type
598 return (-1); /* error fail match */
602 * check to see if sscanf failed conversion, return approximate
608 return (-1); /* error fail match - syntax */
611 return (0); /* fail match */
615 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
617 return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));