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"
31 #include "libnvpair.h"
34 * libnvpair - A tools library for manipulating <name, value> pairs.
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.
42 indent(FILE *fp, int depth)
45 (void) fprintf(fp, "\t");
49 * nvlist_print - Prints elements in an event buffer
53 nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth)
64 (void) fprintf(fp, "nvlist version: %d\n", NVL_VERSION(nvl));
66 nvp = nvlist_next_nvpair(nvl, NULL);
69 data_type_t type = nvpair_type(nvp);
72 name = nvpair_name(nvp);
73 (void) fprintf(fp, "\t%s =", name);
76 case DATA_TYPE_BOOLEAN: {
77 (void) fprintf(fp, " 1");
80 case DATA_TYPE_BOOLEAN_VALUE: {
82 (void) nvpair_value_boolean_value(nvp, &val);
83 (void) fprintf(fp, " %d", val);
86 case DATA_TYPE_BYTE: {
88 (void) nvpair_value_byte(nvp, &val);
89 (void) fprintf(fp, " 0x%2.2x", val);
92 case DATA_TYPE_INT8: {
94 (void) nvpair_value_int8(nvp, &val);
95 (void) fprintf(fp, " %d", val);
98 case DATA_TYPE_UINT8: {
100 (void) nvpair_value_uint8(nvp, &val);
101 (void) fprintf(fp, " 0x%x", val);
104 case DATA_TYPE_INT16: {
106 (void) nvpair_value_int16(nvp, &val);
107 (void) fprintf(fp, " %d", val);
110 case DATA_TYPE_UINT16: {
112 (void) nvpair_value_uint16(nvp, &val);
113 (void) fprintf(fp, " 0x%x", val);
116 case DATA_TYPE_INT32: {
118 (void) nvpair_value_int32(nvp, &val);
119 (void) fprintf(fp, " %d", val);
122 case DATA_TYPE_UINT32: {
124 (void) nvpair_value_uint32(nvp, &val);
125 (void) fprintf(fp, " 0x%x", val);
128 case DATA_TYPE_INT64: {
130 (void) nvpair_value_int64(nvp, &val);
131 (void) fprintf(fp, " %lld", (longlong_t)val);
134 case DATA_TYPE_UINT64: {
136 (void) nvpair_value_uint64(nvp, &val);
137 (void) fprintf(fp, " 0x%llx", (u_longlong_t)val);
140 case DATA_TYPE_DOUBLE: {
142 (void) nvpair_value_double(nvp, &val);
143 (void) fprintf(fp, " 0x%llf", val);
146 case DATA_TYPE_STRING: {
148 (void) nvpair_value_string(nvp, &val);
149 (void) fprintf(fp, " %s", val);
152 case DATA_TYPE_BOOLEAN_ARRAY: {
154 (void) nvpair_value_boolean_array(nvp, &val, &nelem);
155 for (i = 0; i < nelem; i++)
156 (void) fprintf(fp, " %d", val[i]);
159 case DATA_TYPE_BYTE_ARRAY: {
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]);
166 case DATA_TYPE_INT8_ARRAY: {
168 (void) nvpair_value_int8_array(nvp, &val, &nelem);
169 for (i = 0; i < nelem; i++)
170 (void) fprintf(fp, " %d", val[i]);
173 case DATA_TYPE_UINT8_ARRAY: {
175 (void) nvpair_value_uint8_array(nvp, &val, &nelem);
176 for (i = 0; i < nelem; i++)
177 (void) fprintf(fp, " 0x%x", val[i]);
180 case DATA_TYPE_INT16_ARRAY: {
182 (void) nvpair_value_int16_array(nvp, &val, &nelem);
183 for (i = 0; i < nelem; i++)
184 (void) fprintf(fp, " %d", val[i]);
187 case DATA_TYPE_UINT16_ARRAY: {
189 (void) nvpair_value_uint16_array(nvp, &val, &nelem);
190 for (i = 0; i < nelem; i++)
191 (void) fprintf(fp, " 0x%x", val[i]);
194 case DATA_TYPE_INT32_ARRAY: {
196 (void) nvpair_value_int32_array(nvp, &val, &nelem);
197 for (i = 0; i < nelem; i++)
198 (void) fprintf(fp, " %d", val[i]);
201 case DATA_TYPE_UINT32_ARRAY: {
203 (void) nvpair_value_uint32_array(nvp, &val, &nelem);
204 for (i = 0; i < nelem; i++)
205 (void) fprintf(fp, " 0x%x", val[i]);
208 case DATA_TYPE_INT64_ARRAY: {
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]);
215 case DATA_TYPE_UINT64_ARRAY: {
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]);
223 case DATA_TYPE_STRING_ARRAY: {
225 (void) nvpair_value_string_array(nvp, &val, &nelem);
226 for (i = 0; i < nelem; i++)
227 (void) fprintf(fp, " %s", val[i]);
230 case DATA_TYPE_HRTIME: {
232 (void) nvpair_value_hrtime(nvp, &val);
233 (void) fprintf(fp, " 0x%llx", val);
236 case DATA_TYPE_NVLIST: {
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);
245 case DATA_TYPE_NVLIST_ARRAY: {
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);
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);
260 (void) fprintf(fp, " unknown data type (%d)", type);
263 (void) fprintf(fp, "\n");
264 nvp = nvlist_next_nvpair(nvl, nvp);
269 nvlist_print(FILE *fp, nvlist_t *nvl)
271 nvlist_print_with_indent(fp, nvl, 0);
275 * Determine if string 'value' matches 'nvp' value. The 'value' string is
276 * converted, depending on the type of 'nvp', prior to match. For numeric
277 * types, a radix independent sscanf conversion of 'value' is used. If 'nvp'
278 * is an array type, 'ai' is the index into the array against which we are
279 * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass
280 * in a regex_t compilation of value in 'value_regex' to trigger regular
281 * expression string match instead of simple strcmp().
283 * Return 1 on match, 0 on no-match, and -1 on error. If the error is
284 * related to value syntax error and 'ep' is non-NULL, *ep will point into
285 * the 'value' string at the location where the error exists.
287 * NOTE: It may be possible to move the non-regex_t version of this into
288 * common code used by library/kernel/boot.
291 nvpair_value_match_regex(nvpair_t *nvp, int ai,
292 char *value, regex_t *value_regex, char **ep)
301 if ((nvp == NULL) || (value == NULL))
302 return (-1); /* error fail match - invalid args */
304 /* make sure array and index combination make sense */
305 if ((nvpair_type_is_array(nvp) && (ai < 0)) ||
306 (!nvpair_type_is_array(nvp) && (ai >= 0)))
307 return (-1); /* error fail match - bad index */
309 /* non-string values should be single 'chunk' */
310 if ((nvpair_type(nvp) != DATA_TYPE_STRING) &&
311 (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) {
312 value += strspn(value, " \t");
313 evalue = value + strcspn(value, " \t");
317 return (-1); /* error fail match - syntax */
322 switch (nvpair_type(nvp)) {
323 case DATA_TYPE_STRING: {
326 /* check string value for match */
327 if (nvpair_value_string(nvp, &val) == 0) {
329 if (regexec(value_regex, val,
330 (size_t)0, NULL, 0) == 0)
331 return (1); /* match */
333 if (strcmp(value, val) == 0)
334 return (1); /* match */
339 case DATA_TYPE_STRING_ARRAY: {
342 /* check indexed string value of array for match */
343 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
346 if (regexec(value_regex, val_array[ai],
347 (size_t)0, NULL, 0) == 0)
350 if (strcmp(value, val_array[ai]) == 0)
356 case DATA_TYPE_BYTE: {
357 uchar_t val, val_arg;
359 /* scanf uchar_t from value and check for match */
360 sr = sscanf(value, "%c", &val_arg);
361 if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) &&
366 case DATA_TYPE_BYTE_ARRAY: {
367 uchar_t *val_array, val_arg;
370 /* check indexed value of array for match */
371 sr = sscanf(value, "%c", &val_arg);
373 (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
375 (val_array[ai] == val_arg))
379 case DATA_TYPE_INT8: {
382 /* scanf int8_t from value and check for match */
383 sr = sscanf(value, "%"SCNi8, &val_arg);
385 (nvpair_value_int8(nvp, &val) == 0) &&
390 case DATA_TYPE_INT8_ARRAY: {
391 int8_t *val_array, val_arg;
393 /* check indexed value of array for match */
394 sr = sscanf(value, "%"SCNi8, &val_arg);
396 (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
398 (val_array[ai] == val_arg))
402 case DATA_TYPE_UINT8: {
403 uint8_t val, val_arg;
405 /* scanf uint8_t from value and check for match */
406 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
408 (nvpair_value_uint8(nvp, &val) == 0) &&
413 case DATA_TYPE_UINT8_ARRAY: {
414 uint8_t *val_array, val_arg;
416 /* check indexed value of array for match */
417 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
419 (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
421 (val_array[ai] == val_arg))
425 case DATA_TYPE_INT16: {
426 int16_t val, val_arg;
428 /* scanf int16_t from value and check for match */
429 sr = sscanf(value, "%"SCNi16, &val_arg);
431 (nvpair_value_int16(nvp, &val) == 0) &&
436 case DATA_TYPE_INT16_ARRAY: {
437 int16_t *val_array, val_arg;
439 /* check indexed value of array for match */
440 sr = sscanf(value, "%"SCNi16, &val_arg);
442 (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
444 (val_array[ai] == val_arg))
448 case DATA_TYPE_UINT16: {
449 uint16_t val, val_arg;
451 /* scanf uint16_t from value and check for match */
452 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
454 (nvpair_value_uint16(nvp, &val) == 0) &&
459 case DATA_TYPE_UINT16_ARRAY: {
460 uint16_t *val_array, val_arg;
462 /* check indexed value of array for match */
463 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
465 (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
467 (val_array[ai] == val_arg))
471 case DATA_TYPE_INT32: {
472 int32_t val, val_arg;
474 /* scanf int32_t from value and check for match */
475 sr = sscanf(value, "%"SCNi32, &val_arg);
477 (nvpair_value_int32(nvp, &val) == 0) &&
482 case DATA_TYPE_INT32_ARRAY: {
483 int32_t *val_array, val_arg;
485 /* check indexed value of array for match */
486 sr = sscanf(value, "%"SCNi32, &val_arg);
488 (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
490 (val_array[ai] == val_arg))
494 case DATA_TYPE_UINT32: {
495 uint32_t val, val_arg;
497 /* scanf uint32_t from value and check for match */
498 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
500 (nvpair_value_uint32(nvp, &val) == 0) &&
505 case DATA_TYPE_UINT32_ARRAY: {
506 uint32_t *val_array, val_arg;
508 /* check indexed value of array for match */
509 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
511 (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
513 (val_array[ai] == val_arg))
517 case DATA_TYPE_INT64: {
518 int64_t val, val_arg;
520 /* scanf int64_t from value and check for match */
521 sr = sscanf(value, "%"SCNi64, &val_arg);
523 (nvpair_value_int64(nvp, &val) == 0) &&
528 case DATA_TYPE_INT64_ARRAY: {
529 int64_t *val_array, val_arg;
531 /* check indexed value of array for match */
532 sr = sscanf(value, "%"SCNi64, &val_arg);
534 (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
536 (val_array[ai] == val_arg))
540 case DATA_TYPE_UINT64: {
541 uint64_t val_arg, val;
543 /* scanf uint64_t from value and check for match */
544 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
546 (nvpair_value_uint64(nvp, &val) == 0) &&
551 case DATA_TYPE_UINT64_ARRAY: {
552 uint64_t *val_array, val_arg;
554 /* check indexed value of array for match */
555 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
557 (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
559 (val_array[ai] == val_arg))
563 case DATA_TYPE_BOOLEAN_VALUE: {
564 boolean_t val, val_arg;
566 /* scanf boolean_t from value and check for match */
567 sr = sscanf(value, "%"SCNi32, &val_arg);
569 (nvpair_value_boolean_value(nvp, &val) == 0) &&
574 case DATA_TYPE_BOOLEAN_ARRAY: {
575 boolean_t *val_array, val_arg;
577 /* check indexed value of array for match */
578 sr = sscanf(value, "%"SCNi32, &val_arg);
580 (nvpair_value_boolean_array(nvp,
581 &val_array, &a_len) == 0) &&
583 (val_array[ai] == val_arg))
587 case DATA_TYPE_HRTIME:
588 case DATA_TYPE_NVLIST:
589 case DATA_TYPE_NVLIST_ARRAY:
590 case DATA_TYPE_BOOLEAN:
591 case DATA_TYPE_DOUBLE:
592 case DATA_TYPE_UNKNOWN:
595 * unknown/unsupported data type
597 return (-1); /* error fail match */
601 * check to see if sscanf failed conversion, return approximate
607 return (-1); /* error fail match - syntax */
610 return (0); /* fail match */
614 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
616 return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));