]> git.proxmox.com Git - mirror_zfs-debian.git/blob - lib/libnvpair/libnvpair.c
Script updates
[mirror_zfs-debian.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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <unistd.h>
29 #include <strings.h>
30 #include <sys/types.h>
31 #include <sys/inttypes.h>
32 #include "libnvpair.h"
33
34 /*
35 * libnvpair - A tools library for manipulating <name, value> pairs.
36 *
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.
40 */
41
42 static void
43 indent(FILE *fp, int depth)
44 {
45 while (depth-- > 0)
46 (void) fprintf(fp, "\t");
47 }
48
49 /*
50 * nvlist_print - Prints elements in an event buffer
51 */
52 static
53 void
54 nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth)
55 {
56 int i;
57 char *name;
58 uint_t nelem;
59 nvpair_t *nvp;
60
61 if (nvl == NULL)
62 return;
63
64 indent(fp, depth);
65 (void) fprintf(fp, "nvlist version: %d\n", NVL_VERSION(nvl));
66
67 nvp = nvlist_next_nvpair(nvl, NULL);
68
69 while (nvp) {
70 data_type_t type = nvpair_type(nvp);
71
72 indent(fp, depth);
73 name = nvpair_name(nvp);
74 (void) fprintf(fp, "\t%s =", name);
75 nelem = 0;
76 switch (type) {
77 case DATA_TYPE_BOOLEAN: {
78 (void) fprintf(fp, " 1");
79 break;
80 }
81 case DATA_TYPE_BOOLEAN_VALUE: {
82 boolean_t val;
83 (void) nvpair_value_boolean_value(nvp, &val);
84 (void) fprintf(fp, " %d", val);
85 break;
86 }
87 case DATA_TYPE_BYTE: {
88 uchar_t val;
89 (void) nvpair_value_byte(nvp, &val);
90 (void) fprintf(fp, " 0x%2.2x", val);
91 break;
92 }
93 case DATA_TYPE_INT8: {
94 int8_t val;
95 (void) nvpair_value_int8(nvp, &val);
96 (void) fprintf(fp, " %d", val);
97 break;
98 }
99 case DATA_TYPE_UINT8: {
100 uint8_t val;
101 (void) nvpair_value_uint8(nvp, &val);
102 (void) fprintf(fp, " 0x%x", val);
103 break;
104 }
105 case DATA_TYPE_INT16: {
106 int16_t val;
107 (void) nvpair_value_int16(nvp, &val);
108 (void) fprintf(fp, " %d", val);
109 break;
110 }
111 case DATA_TYPE_UINT16: {
112 uint16_t val;
113 (void) nvpair_value_uint16(nvp, &val);
114 (void) fprintf(fp, " 0x%x", val);
115 break;
116 }
117 case DATA_TYPE_INT32: {
118 int32_t val;
119 (void) nvpair_value_int32(nvp, &val);
120 (void) fprintf(fp, " %d", val);
121 break;
122 }
123 case DATA_TYPE_UINT32: {
124 uint32_t val;
125 (void) nvpair_value_uint32(nvp, &val);
126 (void) fprintf(fp, " 0x%x", val);
127 break;
128 }
129 case DATA_TYPE_INT64: {
130 int64_t val;
131 (void) nvpair_value_int64(nvp, &val);
132 (void) fprintf(fp, " %lld", (longlong_t)val);
133 break;
134 }
135 case DATA_TYPE_UINT64: {
136 uint64_t val;
137 (void) nvpair_value_uint64(nvp, &val);
138 (void) fprintf(fp, " 0x%llx", (u_longlong_t)val);
139 break;
140 }
141 case DATA_TYPE_DOUBLE: {
142 double val;
143 (void) nvpair_value_double(nvp, &val);
144 (void) fprintf(fp, " 0x%llf", val);
145 break;
146 }
147 case DATA_TYPE_STRING: {
148 char *val;
149 (void) nvpair_value_string(nvp, &val);
150 (void) fprintf(fp, " %s", val);
151 break;
152 }
153 case DATA_TYPE_BOOLEAN_ARRAY: {
154 boolean_t *val;
155 (void) nvpair_value_boolean_array(nvp, &val, &nelem);
156 for (i = 0; i < nelem; i++)
157 (void) fprintf(fp, " %d", val[i]);
158 break;
159 }
160 case DATA_TYPE_BYTE_ARRAY: {
161 uchar_t *val;
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]);
165 break;
166 }
167 case DATA_TYPE_INT8_ARRAY: {
168 int8_t *val;
169 (void) nvpair_value_int8_array(nvp, &val, &nelem);
170 for (i = 0; i < nelem; i++)
171 (void) fprintf(fp, " %d", val[i]);
172 break;
173 }
174 case DATA_TYPE_UINT8_ARRAY: {
175 uint8_t *val;
176 (void) nvpair_value_uint8_array(nvp, &val, &nelem);
177 for (i = 0; i < nelem; i++)
178 (void) fprintf(fp, " 0x%x", val[i]);
179 break;
180 }
181 case DATA_TYPE_INT16_ARRAY: {
182 int16_t *val;
183 (void) nvpair_value_int16_array(nvp, &val, &nelem);
184 for (i = 0; i < nelem; i++)
185 (void) fprintf(fp, " %d", val[i]);
186 break;
187 }
188 case DATA_TYPE_UINT16_ARRAY: {
189 uint16_t *val;
190 (void) nvpair_value_uint16_array(nvp, &val, &nelem);
191 for (i = 0; i < nelem; i++)
192 (void) fprintf(fp, " 0x%x", val[i]);
193 break;
194 }
195 case DATA_TYPE_INT32_ARRAY: {
196 int32_t *val;
197 (void) nvpair_value_int32_array(nvp, &val, &nelem);
198 for (i = 0; i < nelem; i++)
199 (void) fprintf(fp, " %d", val[i]);
200 break;
201 }
202 case DATA_TYPE_UINT32_ARRAY: {
203 uint32_t *val;
204 (void) nvpair_value_uint32_array(nvp, &val, &nelem);
205 for (i = 0; i < nelem; i++)
206 (void) fprintf(fp, " 0x%x", val[i]);
207 break;
208 }
209 case DATA_TYPE_INT64_ARRAY: {
210 int64_t *val;
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]);
214 break;
215 }
216 case DATA_TYPE_UINT64_ARRAY: {
217 uint64_t *val;
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]);
222 break;
223 }
224 case DATA_TYPE_STRING_ARRAY: {
225 char **val;
226 (void) nvpair_value_string_array(nvp, &val, &nelem);
227 for (i = 0; i < nelem; i++)
228 (void) fprintf(fp, " %s", val[i]);
229 break;
230 }
231 case DATA_TYPE_HRTIME: {
232 hrtime_t val;
233 (void) nvpair_value_hrtime(nvp, &val);
234 (void) fprintf(fp, " 0x%llx", val);
235 break;
236 }
237 case DATA_TYPE_NVLIST: {
238 nvlist_t *val;
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);
244 break;
245 }
246 case DATA_TYPE_NVLIST_ARRAY: {
247 nvlist_t **val;
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);
252 (void) fprintf(fp,
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);
257 }
258 break;
259 }
260 default:
261 (void) fprintf(fp, " unknown data type (%d)", type);
262 break;
263 }
264 (void) fprintf(fp, "\n");
265 nvp = nvlist_next_nvpair(nvl, nvp);
266 }
267 }
268
269 void
270 nvlist_print(FILE *fp, nvlist_t *nvl)
271 {
272 nvlist_print_with_indent(fp, nvl, 0);
273 }
274
275 /*
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().
283 *
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.
287 *
288 * NOTE: It may be possible to move the non-regex_t version of this into
289 * common code used by library/kernel/boot.
290 */
291 int
292 nvpair_value_match_regex(nvpair_t *nvp, int ai,
293 char *value, regex_t *value_regex, char **ep)
294 {
295 char *evalue;
296 uint_t a_len;
297 int sr;
298
299 if (ep)
300 *ep = NULL;
301
302 if ((nvp == NULL) || (value == NULL))
303 return (-1); /* error fail match - invalid args */
304
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 */
309
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");
315 if (*evalue) {
316 if (ep)
317 *ep = evalue;
318 return (-1); /* error fail match - syntax */
319 }
320 }
321
322 sr = EOF;
323 switch (nvpair_type(nvp)) {
324 case DATA_TYPE_STRING: {
325 char *val;
326
327 /* check string value for match */
328 if (nvpair_value_string(nvp, &val) == 0) {
329 if (value_regex) {
330 if (regexec(value_regex, val,
331 (size_t)0, NULL, 0) == 0)
332 return (1); /* match */
333 } else {
334 if (strcmp(value, val) == 0)
335 return (1); /* match */
336 }
337 }
338 break;
339 }
340 case DATA_TYPE_STRING_ARRAY: {
341 char **val_array;
342
343 /* check indexed string value of array for match */
344 if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
345 (ai < a_len)) {
346 if (value_regex) {
347 if (regexec(value_regex, val_array[ai],
348 (size_t)0, NULL, 0) == 0)
349 return (1);
350 } else {
351 if (strcmp(value, val_array[ai]) == 0)
352 return (1);
353 }
354 }
355 break;
356 }
357 case DATA_TYPE_BYTE: {
358 uchar_t val, val_arg;
359
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) &&
363 (val == val_arg))
364 return (1);
365 break;
366 }
367 case DATA_TYPE_BYTE_ARRAY: {
368 uchar_t *val_array, val_arg;
369
370
371 /* check indexed value of array for match */
372 sr = sscanf(value, "%c", &val_arg);
373 if ((sr == 1) &&
374 (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
375 (ai < a_len) &&
376 (val_array[ai] == val_arg))
377 return (1);
378 break;
379 }
380 case DATA_TYPE_INT8: {
381 int8_t val, val_arg;
382
383 /* scanf int8_t from value and check for match */
384 sr = sscanf(value, "%"SCNi8, &val_arg);
385 if ((sr == 1) &&
386 (nvpair_value_int8(nvp, &val) == 0) &&
387 (val == val_arg))
388 return (1);
389 break;
390 }
391 case DATA_TYPE_INT8_ARRAY: {
392 int8_t *val_array, val_arg;
393
394 /* check indexed value of array for match */
395 sr = sscanf(value, "%"SCNi8, &val_arg);
396 if ((sr == 1) &&
397 (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
398 (ai < a_len) &&
399 (val_array[ai] == val_arg))
400 return (1);
401 break;
402 }
403 case DATA_TYPE_UINT8: {
404 uint8_t val, val_arg;
405
406 /* scanf uint8_t from value and check for match */
407 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
408 if ((sr == 1) &&
409 (nvpair_value_uint8(nvp, &val) == 0) &&
410 (val == val_arg))
411 return (1);
412 break;
413 }
414 case DATA_TYPE_UINT8_ARRAY: {
415 uint8_t *val_array, val_arg;
416
417 /* check indexed value of array for match */
418 sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
419 if ((sr == 1) &&
420 (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
421 (ai < a_len) &&
422 (val_array[ai] == val_arg))
423 return (1);
424 break;
425 }
426 case DATA_TYPE_INT16: {
427 int16_t val, val_arg;
428
429 /* scanf int16_t from value and check for match */
430 sr = sscanf(value, "%"SCNi16, &val_arg);
431 if ((sr == 1) &&
432 (nvpair_value_int16(nvp, &val) == 0) &&
433 (val == val_arg))
434 return (1);
435 break;
436 }
437 case DATA_TYPE_INT16_ARRAY: {
438 int16_t *val_array, val_arg;
439
440 /* check indexed value of array for match */
441 sr = sscanf(value, "%"SCNi16, &val_arg);
442 if ((sr == 1) &&
443 (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
444 (ai < a_len) &&
445 (val_array[ai] == val_arg))
446 return (1);
447 break;
448 }
449 case DATA_TYPE_UINT16: {
450 uint16_t val, val_arg;
451
452 /* scanf uint16_t from value and check for match */
453 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
454 if ((sr == 1) &&
455 (nvpair_value_uint16(nvp, &val) == 0) &&
456 (val == val_arg))
457 return (1);
458 break;
459 }
460 case DATA_TYPE_UINT16_ARRAY: {
461 uint16_t *val_array, val_arg;
462
463 /* check indexed value of array for match */
464 sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
465 if ((sr == 1) &&
466 (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
467 (ai < a_len) &&
468 (val_array[ai] == val_arg))
469 return (1);
470 break;
471 }
472 case DATA_TYPE_INT32: {
473 int32_t val, val_arg;
474
475 /* scanf int32_t from value and check for match */
476 sr = sscanf(value, "%"SCNi32, &val_arg);
477 if ((sr == 1) &&
478 (nvpair_value_int32(nvp, &val) == 0) &&
479 (val == val_arg))
480 return (1);
481 break;
482 }
483 case DATA_TYPE_INT32_ARRAY: {
484 int32_t *val_array, val_arg;
485
486 /* check indexed value of array for match */
487 sr = sscanf(value, "%"SCNi32, &val_arg);
488 if ((sr == 1) &&
489 (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
490 (ai < a_len) &&
491 (val_array[ai] == val_arg))
492 return (1);
493 break;
494 }
495 case DATA_TYPE_UINT32: {
496 uint32_t val, val_arg;
497
498 /* scanf uint32_t from value and check for match */
499 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
500 if ((sr == 1) &&
501 (nvpair_value_uint32(nvp, &val) == 0) &&
502 (val == val_arg))
503 return (1);
504 break;
505 }
506 case DATA_TYPE_UINT32_ARRAY: {
507 uint32_t *val_array, val_arg;
508
509 /* check indexed value of array for match */
510 sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
511 if ((sr == 1) &&
512 (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
513 (ai < a_len) &&
514 (val_array[ai] == val_arg))
515 return (1);
516 break;
517 }
518 case DATA_TYPE_INT64: {
519 int64_t val, val_arg;
520
521 /* scanf int64_t from value and check for match */
522 sr = sscanf(value, "%"SCNi64, &val_arg);
523 if ((sr == 1) &&
524 (nvpair_value_int64(nvp, &val) == 0) &&
525 (val == val_arg))
526 return (1);
527 break;
528 }
529 case DATA_TYPE_INT64_ARRAY: {
530 int64_t *val_array, val_arg;
531
532 /* check indexed value of array for match */
533 sr = sscanf(value, "%"SCNi64, &val_arg);
534 if ((sr == 1) &&
535 (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
536 (ai < a_len) &&
537 (val_array[ai] == val_arg))
538 return (1);
539 break;
540 }
541 case DATA_TYPE_UINT64: {
542 uint64_t val_arg, val;
543
544 /* scanf uint64_t from value and check for match */
545 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
546 if ((sr == 1) &&
547 (nvpair_value_uint64(nvp, &val) == 0) &&
548 (val == val_arg))
549 return (1);
550 break;
551 }
552 case DATA_TYPE_UINT64_ARRAY: {
553 uint64_t *val_array, val_arg;
554
555 /* check indexed value of array for match */
556 sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
557 if ((sr == 1) &&
558 (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
559 (ai < a_len) &&
560 (val_array[ai] == val_arg))
561 return (1);
562 break;
563 }
564 case DATA_TYPE_BOOLEAN_VALUE: {
565 boolean_t val, val_arg;
566
567 /* scanf boolean_t from value and check for match */
568 sr = sscanf(value, "%"SCNi32, &val_arg);
569 if ((sr == 1) &&
570 (nvpair_value_boolean_value(nvp, &val) == 0) &&
571 (val == val_arg))
572 return (1);
573 break;
574 }
575 case DATA_TYPE_BOOLEAN_ARRAY: {
576 boolean_t *val_array, val_arg;
577
578 /* check indexed value of array for match */
579 sr = sscanf(value, "%"SCNi32, &val_arg);
580 if ((sr == 1) &&
581 (nvpair_value_boolean_array(nvp,
582 &val_array, &a_len) == 0) &&
583 (ai < a_len) &&
584 (val_array[ai] == val_arg))
585 return (1);
586 break;
587 }
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:
594 default:
595 /*
596 * unknown/unsupported data type
597 */
598 return (-1); /* error fail match */
599 }
600
601 /*
602 * check to see if sscanf failed conversion, return approximate
603 * pointer to problem
604 */
605 if (sr != 1) {
606 if (ep)
607 *ep = value;
608 return (-1); /* error fail match - syntax */
609 }
610
611 return (0); /* fail match */
612 }
613
614 int
615 nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
616 {
617 return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
618 }