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
));