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 (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. |
23 | * Copyright (c) 2012 by Delphix. All rights reserved. |
24 | */ |
25 | |
26 | #include <solaris.h> |
27 | #include <inttypes.h> |
28 | #include <unistd.h> |
29 | #include <string.h> |
30 | #include <libintl.h> |
31 | #include <stdarg.h> |
32 | #include <note.h> |
33 | #include "libnvpair.h" |
34 | |
35 | /* |
36 | * libnvpair - A tools library for manipulating <name, value> pairs. |
37 | * |
38 | * This library provides routines packing an unpacking nv pairs |
39 | * for transporting data across process boundaries, transporting |
40 | * between kernel and userland, and possibly saving onto disk files. |
41 | */ |
42 | |
43 | /* |
44 | * Print control structure. |
45 | */ |
46 | |
47 | #define DEFINEOP(opname, vtype) \ |
48 | struct { \ |
49 | int (*op)(struct nvlist_prtctl *, void *, nvlist_t *, \ |
50 | const char *, vtype); \ |
51 | void *arg; \ |
52 | } opname |
53 | |
54 | #define DEFINEARROP(opname, vtype) \ |
55 | struct { \ |
56 | int (*op)(struct nvlist_prtctl *, void *, nvlist_t *, \ |
57 | const char *, vtype, uint_t); \ |
58 | void *arg; \ |
59 | } opname |
60 | |
61 | struct nvlist_printops { |
62 | DEFINEOP(print_boolean, int); |
63 | DEFINEOP(print_boolean_value, boolean_t); |
64 | DEFINEOP(print_byte, uchar_t); |
65 | DEFINEOP(print_int8, int8_t); |
66 | DEFINEOP(print_uint8, uint8_t); |
67 | DEFINEOP(print_int16, int16_t); |
68 | DEFINEOP(print_uint16, uint16_t); |
69 | DEFINEOP(print_int32, int32_t); |
70 | DEFINEOP(print_uint32, uint32_t); |
71 | DEFINEOP(print_int64, int64_t); |
72 | DEFINEOP(print_uint64, uint64_t); |
73 | DEFINEOP(print_double, double); |
74 | DEFINEOP(print_string, char *); |
75 | DEFINEOP(print_hrtime, hrtime_t); |
76 | DEFINEOP(print_nvlist, nvlist_t *); |
77 | DEFINEARROP(print_boolean_array, boolean_t *); |
78 | DEFINEARROP(print_byte_array, uchar_t *); |
79 | DEFINEARROP(print_int8_array, int8_t *); |
80 | DEFINEARROP(print_uint8_array, uint8_t *); |
81 | DEFINEARROP(print_int16_array, int16_t *); |
82 | DEFINEARROP(print_uint16_array, uint16_t *); |
83 | DEFINEARROP(print_int32_array, int32_t *); |
84 | DEFINEARROP(print_uint32_array, uint32_t *); |
85 | DEFINEARROP(print_int64_array, int64_t *); |
86 | DEFINEARROP(print_uint64_array, uint64_t *); |
87 | DEFINEARROP(print_string_array, char **); |
88 | DEFINEARROP(print_nvlist_array, nvlist_t **); |
89 | }; |
90 | |
91 | struct nvlist_prtctl { |
92 | FILE *nvprt_fp; /* output destination */ |
93 | enum nvlist_indent_mode nvprt_indent_mode; /* see above */ |
94 | int nvprt_indent; /* absolute indent, or tab depth */ |
95 | int nvprt_indentinc; /* indent or tab increment */ |
96 | const char *nvprt_nmfmt; /* member name format, max one %s */ |
97 | const char *nvprt_eomfmt; /* after member format, e.g. "\n" */ |
98 | const char *nvprt_btwnarrfmt; /* between array members */ |
99 | int nvprt_btwnarrfmt_nl; /* nvprt_eoamfmt includes newline? */ |
100 | struct nvlist_printops *nvprt_dfltops; |
101 | struct nvlist_printops *nvprt_custops; |
102 | }; |
103 | |
104 | #define DFLTPRTOP(pctl, type) \ |
105 | ((pctl)->nvprt_dfltops->print_##type.op) |
106 | |
107 | #define DFLTPRTOPARG(pctl, type) \ |
108 | ((pctl)->nvprt_dfltops->print_##type.arg) |
109 | |
110 | #define CUSTPRTOP(pctl, type) \ |
111 | ((pctl)->nvprt_custops->print_##type.op) |
112 | |
113 | #define CUSTPRTOPARG(pctl, type) \ |
114 | ((pctl)->nvprt_custops->print_##type.arg) |
115 | |
116 | #define RENDER(pctl, type, nvl, name, val) \ |
117 | { \ |
118 | int done = 0; \ |
119 | if ((pctl)->nvprt_custops && CUSTPRTOP(pctl, type)) { \ |
120 | done = CUSTPRTOP(pctl, type)(pctl, \ |
121 | CUSTPRTOPARG(pctl, type), nvl, name, val); \ |
122 | } \ |
123 | if (!done) { \ |
124 | (void) DFLTPRTOP(pctl, type)(pctl, \ |
125 | DFLTPRTOPARG(pctl, type), nvl, name, val); \ |
126 | } \ |
127 | (void) fprintf(pctl->nvprt_fp, pctl->nvprt_eomfmt); \ |
128 | } |
129 | |
130 | #define ARENDER(pctl, type, nvl, name, arrp, count) \ |
131 | { \ |
132 | int done = 0; \ |
133 | if ((pctl)->nvprt_custops && CUSTPRTOP(pctl, type)) { \ |
134 | done = CUSTPRTOP(pctl, type)(pctl, \ |
135 | CUSTPRTOPARG(pctl, type), nvl, name, arrp, count); \ |
136 | } \ |
137 | if (!done) { \ |
138 | (void) DFLTPRTOP(pctl, type)(pctl, \ |
139 | DFLTPRTOPARG(pctl, type), nvl, name, arrp, count); \ |
140 | } \ |
141 | (void) fprintf(pctl->nvprt_fp, pctl->nvprt_eomfmt); \ |
142 | } |
143 | |
144 | static void nvlist_print_with_indent(nvlist_t *, nvlist_prtctl_t); |
145 | |
146 | /* |
147 | * ====================================================================== |
148 | * | | |
149 | * | Indentation | |
150 | * | | |
151 | * ====================================================================== |
152 | */ |
153 | |
154 | static void |
155 | indent(nvlist_prtctl_t pctl, int onemore) |
156 | { |
157 | int depth; |
158 | |
159 | switch (pctl->nvprt_indent_mode) { |
160 | case NVLIST_INDENT_ABS: |
161 | (void) fprintf(pctl->nvprt_fp, "%*s" , |
162 | pctl->nvprt_indent + onemore * pctl->nvprt_indentinc, "" ); |
163 | break; |
164 | |
165 | case NVLIST_INDENT_TABBED: |
166 | depth = pctl->nvprt_indent + onemore; |
167 | while (depth-- > 0) |
168 | (void) fprintf(pctl->nvprt_fp, "\t" ); |
169 | } |
170 | } |
171 | |
172 | /* |
173 | * ====================================================================== |
174 | * | | |
175 | * | Default nvlist member rendering functions. | |
176 | * | | |
177 | * ====================================================================== |
178 | */ |
179 | |
180 | /* |
181 | * Generate functions to print single-valued nvlist members. |
182 | * |
183 | * type_and_variant - suffix to form function name |
184 | * vtype - C type for the member value |
185 | * ptype - C type to cast value to for printing |
186 | * vfmt - format string for pair value, e.g "%d" or "0x%llx" |
187 | */ |
188 | |
189 | #define NVLIST_PRTFUNC(type_and_variant, vtype, ptype, vfmt) \ |
190 | static int \ |
191 | nvprint_##type_and_variant(nvlist_prtctl_t pctl, void *private, \ |
192 | nvlist_t *nvl, const char *name, vtype value) \ |
193 | { \ |
194 | FILE *fp = pctl->nvprt_fp; \ |
195 | NOTE(ARGUNUSED(private)) \ |
196 | NOTE(ARGUNUSED(nvl)) \ |
197 | indent(pctl, 1); \ |
198 | (void) fprintf(fp, pctl->nvprt_nmfmt, name); \ |
199 | (void) fprintf(fp, vfmt, (ptype)value); \ |
200 | return (1); \ |
201 | } |
202 | |
203 | NVLIST_PRTFUNC(boolean, int, int, "%d" ) |
204 | NVLIST_PRTFUNC(boolean_value, boolean_t, int, "%d" ) |
205 | NVLIST_PRTFUNC(byte, uchar_t, uchar_t, "0x%2.2x" ) |
206 | NVLIST_PRTFUNC(int8, int8_t, int, "%d" ) |
207 | NVLIST_PRTFUNC(uint8, uint8_t, uint8_t, "0x%x" ) |
208 | NVLIST_PRTFUNC(int16, int16_t, int16_t, "%d" ) |
209 | NVLIST_PRTFUNC(uint16, uint16_t, uint16_t, "0x%x" ) |
210 | NVLIST_PRTFUNC(int32, int32_t, int32_t, "%d" ) |
211 | NVLIST_PRTFUNC(uint32, uint32_t, uint32_t, "0x%x" ) |
212 | NVLIST_PRTFUNC(int64, int64_t, longlong_t, "%lld" ) |
213 | NVLIST_PRTFUNC(uint64, uint64_t, u_longlong_t, "0x%llx" ) |
214 | NVLIST_PRTFUNC(double, double, double, "0x%f" ) |
215 | NVLIST_PRTFUNC(string, char *, char *, "%s" ) |
216 | NVLIST_PRTFUNC(hrtime, hrtime_t, hrtime_t, "0x%llx" ) |
217 | |
218 | /* |
219 | * Generate functions to print array-valued nvlist members. |
220 | */ |
221 | |
222 | #define NVLIST_ARRPRTFUNC(type_and_variant, vtype, ptype, vfmt) \ |
223 | static int \ |
224 | nvaprint_##type_and_variant(nvlist_prtctl_t pctl, void *private, \ |
225 | nvlist_t *nvl, const char *name, vtype *valuep, uint_t count) \ |
226 | { \ |
227 | FILE *fp = pctl->nvprt_fp; \ |
228 | uint_t i; \ |
229 | NOTE(ARGUNUSED(private)) \ |
230 | NOTE(ARGUNUSED(nvl)) \ |
231 | for (i = 0; i < count; i++) { \ |
232 | if (i == 0 || pctl->nvprt_btwnarrfmt_nl) { \ |
233 | indent(pctl, 1); \ |
234 | (void) fprintf(fp, pctl->nvprt_nmfmt, name); \ |
235 | if (pctl->nvprt_btwnarrfmt_nl) \ |
236 | (void) fprintf(fp, "[%d]: ", i); \ |
237 | } \ |
238 | if (i != 0) \ |
239 | (void) fprintf(fp, pctl->nvprt_btwnarrfmt); \ |
240 | (void) fprintf(fp, vfmt, (ptype)valuep[i]); \ |
241 | } \ |
242 | return (1); \ |
243 | } |
244 | |
245 | NVLIST_ARRPRTFUNC(boolean_array, boolean_t, boolean_t, "%d" ) |
246 | NVLIST_ARRPRTFUNC(byte_array, uchar_t, uchar_t, "0x%2.2x" ) |
247 | NVLIST_ARRPRTFUNC(int8_array, int8_t, int8_t, "%d" ) |
248 | NVLIST_ARRPRTFUNC(uint8_array, uint8_t, uint8_t, "0x%x" ) |
249 | NVLIST_ARRPRTFUNC(int16_array, int16_t, int16_t, "%d" ) |
250 | NVLIST_ARRPRTFUNC(uint16_array, uint16_t, uint16_t, "0x%x" ) |
251 | NVLIST_ARRPRTFUNC(int32_array, int32_t, int32_t, "%d" ) |
252 | NVLIST_ARRPRTFUNC(uint32_array, uint32_t, uint32_t, "0x%x" ) |
253 | NVLIST_ARRPRTFUNC(int64_array, int64_t, longlong_t, "%lld" ) |
254 | NVLIST_ARRPRTFUNC(uint64_array, uint64_t, u_longlong_t, "0x%llx" ) |
255 | NVLIST_ARRPRTFUNC(string_array, char *, char *, "%s" ) |
256 | |
257 | /*ARGSUSED*/ |
258 | static int |
259 | nvprint_nvlist(nvlist_prtctl_t pctl, void *private, |
260 | nvlist_t *nvl, const char *name, nvlist_t *value) |
261 | { |
262 | FILE *fp = pctl->nvprt_fp; |
263 | |
264 | indent(pctl, 1); |
265 | (void) fprintf(fp, "%s = (embedded nvlist)\n" , name); |
266 | |
267 | pctl->nvprt_indent += pctl->nvprt_indentinc; |
268 | nvlist_print_with_indent(value, pctl); |
269 | pctl->nvprt_indent -= pctl->nvprt_indentinc; |
270 | |
271 | indent(pctl, 1); |
272 | (void) fprintf(fp, "(end %s)\n" , name); |
273 | |
274 | return (1); |
275 | } |
276 | |
277 | /*ARGSUSED*/ |
278 | static int |
279 | nvaprint_nvlist_array(nvlist_prtctl_t pctl, void *private, |
280 | nvlist_t *nvl, const char *name, nvlist_t **valuep, uint_t count) |
281 | { |
282 | FILE *fp = pctl->nvprt_fp; |
283 | uint_t i; |
284 | |
285 | indent(pctl, 1); |
286 | (void) fprintf(fp, "%s = (array of embedded nvlists)\n" , name); |
287 | |
288 | for (i = 0; i < count; i++) { |
289 | indent(pctl, 1); |
290 | (void) fprintf(fp, "(start %s[%d])\n" , name, i); |
291 | |
292 | pctl->nvprt_indent += pctl->nvprt_indentinc; |
293 | nvlist_print_with_indent(valuep[i], pctl); |
294 | pctl->nvprt_indent -= pctl->nvprt_indentinc; |
295 | |
296 | indent(pctl, 1); |
297 | (void) fprintf(fp, "(end %s[%d])\n" , name, i); |
298 | } |
299 | |
300 | return (1); |
301 | } |
302 | |
303 | /* |
304 | * ====================================================================== |
305 | * | | |
306 | * | Interfaces that allow control over formatting. | |
307 | * | | |
308 | * ====================================================================== |
309 | */ |
310 | |
311 | void |
312 | nvlist_prtctl_setdest(nvlist_prtctl_t pctl, FILE *fp) |
313 | { |
314 | pctl->nvprt_fp = fp; |
315 | } |
316 | |
317 | FILE * |
318 | nvlist_prtctl_getdest(nvlist_prtctl_t pctl) |
319 | { |
320 | return (pctl->nvprt_fp); |
321 | } |
322 | |
323 | |
324 | void |
325 | nvlist_prtctl_setindent(nvlist_prtctl_t pctl, enum nvlist_indent_mode mode, |
326 | int start, int inc) |
327 | { |
328 | if (mode < NVLIST_INDENT_ABS || mode > NVLIST_INDENT_TABBED) |
329 | mode = NVLIST_INDENT_TABBED; |
330 | |
331 | if (start < 0) |
332 | start = 0; |
333 | |
334 | if (inc < 0) |
335 | inc = 1; |
336 | |
337 | pctl->nvprt_indent_mode = mode; |
338 | pctl->nvprt_indent = start; |
339 | pctl->nvprt_indentinc = inc; |
340 | } |
341 | |
342 | void |
343 | nvlist_prtctl_doindent(nvlist_prtctl_t pctl, int onemore) |
344 | { |
345 | indent(pctl, onemore); |
346 | } |
347 | |
348 | |
349 | void |
350 | nvlist_prtctl_setfmt(nvlist_prtctl_t pctl, enum nvlist_prtctl_fmt which, |
351 | const char *fmt) |
352 | { |
353 | switch (which) { |
354 | case NVLIST_FMT_MEMBER_NAME: |
355 | if (fmt == NULL) |
356 | fmt = "%s = " ; |
357 | pctl->nvprt_nmfmt = fmt; |
358 | break; |
359 | |
360 | case NVLIST_FMT_MEMBER_POSTAMBLE: |
361 | if (fmt == NULL) |
362 | fmt = "\n" ; |
363 | pctl->nvprt_eomfmt = fmt; |
364 | break; |
365 | |
366 | case NVLIST_FMT_BTWN_ARRAY: |
367 | if (fmt == NULL) { |
368 | pctl->nvprt_btwnarrfmt = " " ; |
369 | pctl->nvprt_btwnarrfmt_nl = 0; |
370 | } else { |
371 | pctl->nvprt_btwnarrfmt = fmt; |
372 | pctl->nvprt_btwnarrfmt_nl = (strstr(fmt, "\n" ) != NULL); |
373 | } |
374 | break; |
375 | |
376 | default: |
377 | break; |
378 | } |
379 | } |
380 | |
381 | |
382 | void |
383 | nvlist_prtctl_dofmt(nvlist_prtctl_t pctl, enum nvlist_prtctl_fmt which, ...) |
384 | { |
385 | FILE *fp = pctl->nvprt_fp; |
386 | va_list ap; |
387 | char *name; |
388 | |
389 | va_start(ap, which); |
390 | |
391 | switch (which) { |
392 | case NVLIST_FMT_MEMBER_NAME: |
393 | name = va_arg(ap, char *); |
394 | (void) fprintf(fp, pctl->nvprt_nmfmt, name); |
395 | break; |
396 | |
397 | case NVLIST_FMT_MEMBER_POSTAMBLE: |
398 | (void) fprintf(fp, pctl->nvprt_eomfmt); |
399 | break; |
400 | |
401 | case NVLIST_FMT_BTWN_ARRAY: |
402 | (void) fprintf(fp, pctl->nvprt_btwnarrfmt); \ |
403 | break; |
404 | |
405 | default: |
406 | break; |
407 | } |
408 | |
409 | va_end(ap); |
410 | } |
411 | |
412 | /* |
413 | * ====================================================================== |
414 | * | | |
415 | * | Interfaces to allow appointment of replacement rendering functions.| |
416 | * | | |
417 | * ====================================================================== |
418 | */ |
419 | |
420 | #define NVLIST_PRINTCTL_REPLACE(type, vtype) \ |
421 | void \ |
422 | nvlist_prtctlop_##type(nvlist_prtctl_t pctl, \ |
423 | int (*func)(nvlist_prtctl_t, void *, nvlist_t *, const char *, vtype), \ |
424 | void *private) \ |
425 | { \ |
426 | CUSTPRTOP(pctl, type) = func; \ |
427 | CUSTPRTOPARG(pctl, type) = private; \ |
428 | } |
429 | |
430 | NVLIST_PRINTCTL_REPLACE(boolean, int) |
431 | NVLIST_PRINTCTL_REPLACE(boolean_value, boolean_t) |
432 | NVLIST_PRINTCTL_REPLACE(byte, uchar_t) |
433 | NVLIST_PRINTCTL_REPLACE(int8, int8_t) |
434 | NVLIST_PRINTCTL_REPLACE(uint8, uint8_t) |
435 | NVLIST_PRINTCTL_REPLACE(int16, int16_t) |
436 | NVLIST_PRINTCTL_REPLACE(uint16, uint16_t) |
437 | NVLIST_PRINTCTL_REPLACE(int32, int32_t) |
438 | NVLIST_PRINTCTL_REPLACE(uint32, uint32_t) |
439 | NVLIST_PRINTCTL_REPLACE(int64, int64_t) |
440 | NVLIST_PRINTCTL_REPLACE(uint64, uint64_t) |
441 | NVLIST_PRINTCTL_REPLACE(double, double) |
442 | NVLIST_PRINTCTL_REPLACE(string, char *) |
443 | NVLIST_PRINTCTL_REPLACE(hrtime, hrtime_t) |
444 | NVLIST_PRINTCTL_REPLACE(nvlist, nvlist_t *) |
445 | |
446 | #define NVLIST_PRINTCTL_AREPLACE(type, vtype) \ |
447 | void \ |
448 | nvlist_prtctlop_##type(nvlist_prtctl_t pctl, \ |
449 | int (*func)(nvlist_prtctl_t, void *, nvlist_t *, const char *, vtype, \ |
450 | uint_t), void *private) \ |
451 | { \ |
452 | CUSTPRTOP(pctl, type) = func; \ |
453 | CUSTPRTOPARG(pctl, type) = private; \ |
454 | } |
455 | |
456 | NVLIST_PRINTCTL_AREPLACE(boolean_array, boolean_t *) |
457 | NVLIST_PRINTCTL_AREPLACE(byte_array, uchar_t *) |
458 | NVLIST_PRINTCTL_AREPLACE(int8_array, int8_t *) |
459 | NVLIST_PRINTCTL_AREPLACE(uint8_array, uint8_t *) |
460 | NVLIST_PRINTCTL_AREPLACE(int16_array, int16_t *) |
461 | NVLIST_PRINTCTL_AREPLACE(uint16_array, uint16_t *) |
462 | NVLIST_PRINTCTL_AREPLACE(int32_array, int32_t *) |
463 | NVLIST_PRINTCTL_AREPLACE(uint32_array, uint32_t *) |
464 | NVLIST_PRINTCTL_AREPLACE(int64_array, int64_t *) |
465 | NVLIST_PRINTCTL_AREPLACE(uint64_array, uint64_t *) |
466 | NVLIST_PRINTCTL_AREPLACE(string_array, char **) |
467 | NVLIST_PRINTCTL_AREPLACE(nvlist_array, nvlist_t **) |
468 | |
469 | /* |
470 | * ====================================================================== |
471 | * | | |
472 | * | Interfaces to manage nvlist_prtctl_t cookies. | |
473 | * | | |
474 | * ====================================================================== |
475 | */ |
476 | |
477 | |
478 | static const struct nvlist_printops defprtops = { |
479 | { nvprint_boolean, NULL }, |
480 | { nvprint_boolean_value, NULL }, |
481 | { nvprint_byte, NULL }, |
482 | { nvprint_int8, NULL }, |
483 | { nvprint_uint8, NULL }, |
484 | { nvprint_int16, NULL }, |
485 | { nvprint_uint16, NULL }, |
486 | { nvprint_int32, NULL }, |
487 | { nvprint_uint32, NULL }, |
488 | { nvprint_int64, NULL }, |
489 | { nvprint_uint64, NULL }, |
490 | { nvprint_double, NULL }, |
491 | { nvprint_string, NULL }, |
492 | { nvprint_hrtime, NULL }, |
493 | { nvprint_nvlist, NULL }, |
494 | { nvaprint_boolean_array, NULL }, |
495 | { nvaprint_byte_array, NULL }, |
496 | { nvaprint_int8_array, NULL }, |
497 | { nvaprint_uint8_array, NULL }, |
498 | { nvaprint_int16_array, NULL }, |
499 | { nvaprint_uint16_array, NULL }, |
500 | { nvaprint_int32_array, NULL }, |
501 | { nvaprint_uint32_array, NULL }, |
502 | { nvaprint_int64_array, NULL }, |
503 | { nvaprint_uint64_array, NULL }, |
504 | { nvaprint_string_array, NULL }, |
505 | { nvaprint_nvlist_array, NULL }, |
506 | }; |
507 | |
508 | static void |
509 | prtctl_defaults(FILE *fp, struct nvlist_prtctl *pctl, |
510 | struct nvlist_printops *ops) |
511 | { |
512 | pctl->nvprt_fp = fp; |
513 | pctl->nvprt_indent_mode = NVLIST_INDENT_TABBED; |
514 | pctl->nvprt_indent = 0; |
515 | pctl->nvprt_indentinc = 1; |
516 | pctl->nvprt_nmfmt = "%s = " ; |
517 | pctl->nvprt_eomfmt = "\n" ; |
518 | pctl->nvprt_btwnarrfmt = " " ; |
519 | pctl->nvprt_btwnarrfmt_nl = 0; |
520 | |
521 | pctl->nvprt_dfltops = (struct nvlist_printops *)&defprtops; |
522 | pctl->nvprt_custops = ops; |
523 | } |
524 | |
525 | nvlist_prtctl_t |
526 | nvlist_prtctl_alloc(void) |
527 | { |
528 | struct nvlist_prtctl *pctl; |
529 | struct nvlist_printops *ops; |
530 | |
531 | if ((pctl = malloc(sizeof (*pctl))) == NULL) |
532 | return (NULL); |
533 | |
534 | if ((ops = calloc(1, sizeof (*ops))) == NULL) { |
535 | free(pctl); |
536 | return (NULL); |
537 | } |
538 | |
539 | prtctl_defaults(stdout, pctl, ops); |
540 | |
541 | return (pctl); |
542 | } |
543 | |
544 | void |
545 | nvlist_prtctl_free(nvlist_prtctl_t pctl) |
546 | { |
547 | if (pctl != NULL) { |
548 | free(pctl->nvprt_custops); |
549 | free(pctl); |
550 | } |
551 | } |
552 | |
553 | /* |
554 | * ====================================================================== |
555 | * | | |
556 | * | Top-level print request interfaces. | |
557 | * | | |
558 | * ====================================================================== |
559 | */ |
560 | |
561 | /* |
562 | * nvlist_print - Prints elements in an event buffer |
563 | */ |
564 | static void |
565 | nvlist_print_with_indent(nvlist_t *nvl, nvlist_prtctl_t pctl) |
566 | { |
567 | FILE *fp = pctl->nvprt_fp; |
568 | char *name; |
569 | uint_t nelem; |
570 | nvpair_t *nvp; |
571 | |
572 | if (nvl == NULL) |
573 | return; |
574 | |
575 | indent(pctl, 0); |
576 | (void) fprintf(fp, "nvlist version: %d\n" , NVL_VERSION(nvl)); |
577 | |
578 | nvp = nvlist_next_nvpair(nvl, NULL); |
579 | |
580 | while (nvp) { |
581 | data_type_t type = nvpair_type(nvp); |
582 | |
583 | name = nvpair_name(nvp); |
584 | nelem = 0; |
585 | |
586 | switch (type) { |
587 | case DATA_TYPE_BOOLEAN: { |
588 | RENDER(pctl, boolean, nvl, name, 1); |
589 | break; |
590 | } |
591 | case DATA_TYPE_BOOLEAN_VALUE: { |
592 | boolean_t val; |
593 | (void) nvpair_value_boolean_value(nvp, &val); |
594 | RENDER(pctl, boolean_value, nvl, name, val); |
595 | break; |
596 | } |
597 | case DATA_TYPE_BYTE: { |
598 | uchar_t val; |
599 | (void) nvpair_value_byte(nvp, &val); |
600 | RENDER(pctl, byte, nvl, name, val); |
601 | break; |
602 | } |
603 | case DATA_TYPE_INT8: { |
604 | int8_t val; |
605 | (void) nvpair_value_int8(nvp, &val); |
606 | RENDER(pctl, int8, nvl, name, val); |
607 | break; |
608 | } |
609 | case DATA_TYPE_UINT8: { |
610 | uint8_t val; |
611 | (void) nvpair_value_uint8(nvp, &val); |
612 | RENDER(pctl, uint8, nvl, name, val); |
613 | break; |
614 | } |
615 | case DATA_TYPE_INT16: { |
616 | int16_t val; |
617 | (void) nvpair_value_int16(nvp, &val); |
618 | RENDER(pctl, int16, nvl, name, val); |
619 | break; |
620 | } |
621 | case DATA_TYPE_UINT16: { |
622 | uint16_t val; |
623 | (void) nvpair_value_uint16(nvp, &val); |
624 | RENDER(pctl, uint16, nvl, name, val); |
625 | break; |
626 | } |
627 | case DATA_TYPE_INT32: { |
628 | int32_t val; |
629 | (void) nvpair_value_int32(nvp, &val); |
630 | RENDER(pctl, int32, nvl, name, val); |
631 | break; |
632 | } |
633 | case DATA_TYPE_UINT32: { |
634 | uint32_t val; |
635 | (void) nvpair_value_uint32(nvp, &val); |
636 | RENDER(pctl, uint32, nvl, name, val); |
637 | break; |
638 | } |
639 | case DATA_TYPE_INT64: { |
640 | int64_t val; |
641 | (void) nvpair_value_int64(nvp, &val); |
642 | RENDER(pctl, int64, nvl, name, val); |
643 | break; |
644 | } |
645 | case DATA_TYPE_UINT64: { |
646 | uint64_t val; |
647 | (void) nvpair_value_uint64(nvp, &val); |
648 | RENDER(pctl, uint64, nvl, name, val); |
649 | break; |
650 | } |
651 | case DATA_TYPE_DOUBLE: { |
652 | double val; |
653 | (void) nvpair_value_double(nvp, &val); |
654 | RENDER(pctl, double, nvl, name, val); |
655 | break; |
656 | } |
657 | case DATA_TYPE_STRING: { |
658 | char *val; |
659 | (void) nvpair_value_string(nvp, &val); |
660 | RENDER(pctl, string, nvl, name, val); |
661 | break; |
662 | } |
663 | case DATA_TYPE_BOOLEAN_ARRAY: { |
664 | boolean_t *val; |
665 | (void) nvpair_value_boolean_array(nvp, &val, &nelem); |
666 | ARENDER(pctl, boolean_array, nvl, name, val, nelem); |
667 | break; |
668 | } |
669 | case DATA_TYPE_BYTE_ARRAY: { |
670 | uchar_t *val; |
671 | (void) nvpair_value_byte_array(nvp, &val, &nelem); |
672 | ARENDER(pctl, byte_array, nvl, name, val, nelem); |
673 | break; |
674 | } |
675 | case DATA_TYPE_INT8_ARRAY: { |
676 | int8_t *val; |
677 | (void) nvpair_value_int8_array(nvp, &val, &nelem); |
678 | ARENDER(pctl, int8_array, nvl, name, val, nelem); |
679 | break; |
680 | } |
681 | case DATA_TYPE_UINT8_ARRAY: { |
682 | uint8_t *val; |
683 | (void) nvpair_value_uint8_array(nvp, &val, &nelem); |
684 | ARENDER(pctl, uint8_array, nvl, name, val, nelem); |
685 | break; |
686 | } |
687 | case DATA_TYPE_INT16_ARRAY: { |
688 | int16_t *val; |
689 | (void) nvpair_value_int16_array(nvp, &val, &nelem); |
690 | ARENDER(pctl, int16_array, nvl, name, val, nelem); |
691 | break; |
692 | } |
693 | case DATA_TYPE_UINT16_ARRAY: { |
694 | uint16_t *val; |
695 | (void) nvpair_value_uint16_array(nvp, &val, &nelem); |
696 | ARENDER(pctl, uint16_array, nvl, name, val, nelem); |
697 | break; |
698 | } |
699 | case DATA_TYPE_INT32_ARRAY: { |
700 | int32_t *val; |
701 | (void) nvpair_value_int32_array(nvp, &val, &nelem); |
702 | ARENDER(pctl, int32_array, nvl, name, val, nelem); |
703 | break; |
704 | } |
705 | case DATA_TYPE_UINT32_ARRAY: { |
706 | uint32_t *val; |
707 | (void) nvpair_value_uint32_array(nvp, &val, &nelem); |
708 | ARENDER(pctl, uint32_array, nvl, name, val, nelem); |
709 | break; |
710 | } |
711 | case DATA_TYPE_INT64_ARRAY: { |
712 | int64_t *val; |
713 | (void) nvpair_value_int64_array(nvp, &val, &nelem); |
714 | ARENDER(pctl, int64_array, nvl, name, val, nelem); |
715 | break; |
716 | } |
717 | case DATA_TYPE_UINT64_ARRAY: { |
718 | uint64_t *val; |
719 | (void) nvpair_value_uint64_array(nvp, &val, &nelem); |
720 | ARENDER(pctl, uint64_array, nvl, name, val, nelem); |
721 | break; |
722 | } |
723 | case DATA_TYPE_STRING_ARRAY: { |
724 | char **val; |
725 | (void) nvpair_value_string_array(nvp, &val, &nelem); |
726 | ARENDER(pctl, string_array, nvl, name, val, nelem); |
727 | break; |
728 | } |
729 | case DATA_TYPE_HRTIME: { |
730 | hrtime_t val; |
731 | (void) nvpair_value_hrtime(nvp, &val); |
732 | RENDER(pctl, hrtime, nvl, name, val); |
733 | break; |
734 | } |
735 | case DATA_TYPE_NVLIST: { |
736 | nvlist_t *val; |
737 | (void) nvpair_value_nvlist(nvp, &val); |
738 | RENDER(pctl, nvlist, nvl, name, val); |
739 | break; |
740 | } |
741 | case DATA_TYPE_NVLIST_ARRAY: { |
742 | nvlist_t **val; |
743 | (void) nvpair_value_nvlist_array(nvp, &val, &nelem); |
744 | ARENDER(pctl, nvlist_array, nvl, name, val, nelem); |
745 | break; |
746 | } |
747 | default: |
748 | (void) fprintf(fp, " unknown data type (%d)" , type); |
749 | break; |
750 | } |
751 | nvp = nvlist_next_nvpair(nvl, nvp); |
752 | } |
753 | } |
754 | |
755 | void |
756 | nvlist_print(FILE *fp, nvlist_t *nvl) |
757 | { |
758 | struct nvlist_prtctl pc; |
759 | |
760 | prtctl_defaults(fp, &pc, NULL); |
761 | nvlist_print_with_indent(nvl, &pc); |
762 | } |
763 | |
764 | void |
765 | nvlist_prt(nvlist_t *nvl, nvlist_prtctl_t pctl) |
766 | { |
767 | nvlist_print_with_indent(nvl, pctl); |
768 | } |
769 | |
770 | #define NVP(elem, type, vtype, ptype, format) { \ |
771 | vtype value; \ |
772 | \ |
773 | (void) nvpair_value_##type(elem, &value); \ |
774 | (void) printf("%*s%s: " format "\n", indent, "", \ |
775 | nvpair_name(elem), (ptype)value); \ |
776 | } |
777 | |
778 | #define NVPA(elem, type, vtype, ptype, format) { \ |
779 | uint_t i, count; \ |
780 | vtype *value; \ |
781 | \ |
782 | (void) nvpair_value_##type(elem, &value, &count); \ |
783 | for (i = 0; i < count; i++) { \ |
784 | (void) printf("%*s%s[%d]: " format "\n", indent, "", \ |
785 | nvpair_name(elem), i, (ptype)value[i]); \ |
786 | } \ |
787 | } |
788 | |
789 | /* |
790 | * Similar to nvlist_print() but handles arrays slightly differently. |
791 | */ |
792 | void |
793 | dump_nvlist(nvlist_t *list, int indent) |
794 | { |
795 | nvpair_t *elem = NULL; |
796 | boolean_t bool_value; |
797 | boolean_t *bool_array_value; |
798 | nvlist_t *nvlist_value; |
799 | nvlist_t **nvlist_array_value; |
800 | uint_t i, count; |
801 | |
802 | if (list == NULL) { |
803 | return; |
804 | } |
805 | |
806 | while ((elem = nvlist_next_nvpair(list, elem)) != NULL) { |
807 | switch (nvpair_type(elem)) { |
808 | case DATA_TYPE_BOOLEAN: |
809 | (void) printf("%*s%s\n" , indent, "" , nvpair_name(elem)); |
810 | break; |
811 | |
812 | case DATA_TYPE_BOOLEAN_VALUE: |
813 | (void) nvpair_value_boolean_value(elem, &bool_value); |
814 | (void) printf("%*s%s: %s\n" , indent, "" , |
815 | nvpair_name(elem), bool_value ? "true" : "false" ); |
816 | break; |
817 | |
818 | case DATA_TYPE_BYTE: |
819 | NVP(elem, byte, uchar_t, int, "%u" ); |
820 | break; |
821 | |
822 | case DATA_TYPE_INT8: |
823 | NVP(elem, int8, int8_t, int, "%d" ); |
824 | break; |
825 | |
826 | case DATA_TYPE_UINT8: |
827 | NVP(elem, uint8, uint8_t, int, "%u" ); |
828 | break; |
829 | |
830 | case DATA_TYPE_INT16: |
831 | NVP(elem, int16, int16_t, int, "%d" ); |
832 | break; |
833 | |
834 | case DATA_TYPE_UINT16: |
835 | NVP(elem, uint16, uint16_t, int, "%u" ); |
836 | break; |
837 | |
838 | case DATA_TYPE_INT32: |
839 | NVP(elem, int32, int32_t, long, "%ld" ); |
840 | break; |
841 | |
842 | case DATA_TYPE_UINT32: |
843 | NVP(elem, uint32, uint32_t, ulong_t, "%lu" ); |
844 | break; |
845 | |
846 | case DATA_TYPE_INT64: |
847 | NVP(elem, int64, int64_t, longlong_t, "%lld" ); |
848 | break; |
849 | |
850 | case DATA_TYPE_UINT64: |
851 | NVP(elem, uint64, uint64_t, u_longlong_t, "%llu" ); |
852 | break; |
853 | |
854 | case DATA_TYPE_STRING: |
855 | NVP(elem, string, char *, char *, "'%s'" ); |
856 | break; |
857 | |
858 | case DATA_TYPE_BOOLEAN_ARRAY: |
859 | (void) nvpair_value_boolean_array(elem, |
860 | &bool_array_value, &count); |
861 | for (i = 0; i < count; i++) { |
862 | (void) printf("%*s%s[%d]: %s\n" , indent, "" , |
863 | nvpair_name(elem), i, |
864 | bool_array_value[i] ? "true" : "false" ); |
865 | } |
866 | break; |
867 | |
868 | case DATA_TYPE_BYTE_ARRAY: |
869 | NVPA(elem, byte_array, uchar_t, int, "%u" ); |
870 | break; |
871 | |
872 | case DATA_TYPE_INT8_ARRAY: |
873 | NVPA(elem, int8_array, int8_t, int, "%d" ); |
874 | break; |
875 | |
876 | case DATA_TYPE_UINT8_ARRAY: |
877 | NVPA(elem, uint8_array, uint8_t, int, "%u" ); |
878 | break; |
879 | |
880 | case DATA_TYPE_INT16_ARRAY: |
881 | NVPA(elem, int16_array, int16_t, int, "%d" ); |
882 | break; |
883 | |
884 | case DATA_TYPE_UINT16_ARRAY: |
885 | NVPA(elem, uint16_array, uint16_t, int, "%u" ); |
886 | break; |
887 | |
888 | case DATA_TYPE_INT32_ARRAY: |
889 | NVPA(elem, int32_array, int32_t, long, "%ld" ); |
890 | break; |
891 | |
892 | case DATA_TYPE_UINT32_ARRAY: |
893 | NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu" ); |
894 | break; |
895 | |
896 | case DATA_TYPE_INT64_ARRAY: |
897 | NVPA(elem, int64_array, int64_t, longlong_t, "%lld" ); |
898 | break; |
899 | |
900 | case DATA_TYPE_UINT64_ARRAY: |
901 | NVPA(elem, uint64_array, uint64_t, u_longlong_t, |
902 | "%llu" ); |
903 | break; |
904 | |
905 | case DATA_TYPE_STRING_ARRAY: |
906 | NVPA(elem, string_array, char *, char *, "'%s'" ); |
907 | break; |
908 | |
909 | case DATA_TYPE_NVLIST: |
910 | (void) nvpair_value_nvlist(elem, &nvlist_value); |
911 | (void) printf("%*s%s:\n" , indent, "" , |
912 | nvpair_name(elem)); |
913 | dump_nvlist(nvlist_value, indent + 4); |
914 | break; |
915 | |
916 | case DATA_TYPE_NVLIST_ARRAY: |
917 | (void) nvpair_value_nvlist_array(elem, |
918 | &nvlist_array_value, &count); |
919 | for (i = 0; i < count; i++) { |
920 | (void) printf("%*s%s[%u]:\n" , indent, "" , |
921 | nvpair_name(elem), i); |
922 | dump_nvlist(nvlist_array_value[i], indent + 4); |
923 | } |
924 | break; |
925 | |
926 | default: |
927 | (void) printf(dgettext(TEXT_DOMAIN, "bad config type " |
928 | "%d for %s\n" ), nvpair_type(elem), |
929 | nvpair_name(elem)); |
930 | } |
931 | } |
932 | } |
933 | |
934 | /* |
935 | * ====================================================================== |
936 | * | | |
937 | * | Misc private interface. | |
938 | * | | |
939 | * ====================================================================== |
940 | */ |
941 | |
942 | /* |
943 | * Determine if string 'value' matches 'nvp' value. The 'value' string is |
944 | * converted, depending on the type of 'nvp', prior to match. For numeric |
945 | * types, a radix independent sscanf conversion of 'value' is used. If 'nvp' |
946 | * is an array type, 'ai' is the index into the array against which we are |
947 | * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass |
948 | * in a regex_t compilation of value in 'value_regex' to trigger regular |
949 | * expression string match instead of simple strcmp(). |
950 | * |
951 | * Return 1 on match, 0 on no-match, and -1 on error. If the error is |
952 | * related to value syntax error and 'ep' is non-NULL, *ep will point into |
953 | * the 'value' string at the location where the error exists. |
954 | * |
955 | * NOTE: It may be possible to move the non-regex_t version of this into |
956 | * common code used by library/kernel/boot. |
957 | */ |
958 | int |
959 | nvpair_value_match_regex(nvpair_t *nvp, int ai, |
960 | char *value, regex_t *value_regex, char **ep) |
961 | { |
962 | char *evalue; |
963 | uint_t a_len; |
964 | int sr; |
965 | |
966 | if (ep) |
967 | *ep = NULL; |
968 | |
969 | if ((nvp == NULL) || (value == NULL)) |
970 | return (-1); /* error fail match - invalid args */ |
971 | |
972 | /* make sure array and index combination make sense */ |
973 | if ((nvpair_type_is_array(nvp) && (ai < 0)) || |
974 | (!nvpair_type_is_array(nvp) && (ai >= 0))) |
975 | return (-1); /* error fail match - bad index */ |
976 | |
977 | /* non-string values should be single 'chunk' */ |
978 | if ((nvpair_type(nvp) != DATA_TYPE_STRING) && |
979 | (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) { |
980 | value += strspn(value, " \t" ); |
981 | evalue = value + strcspn(value, " \t" ); |
982 | if (*evalue) { |
983 | if (ep) |
984 | *ep = evalue; |
985 | return (-1); /* error fail match - syntax */ |
986 | } |
987 | } |
988 | |
989 | sr = EOF; |
990 | switch (nvpair_type(nvp)) { |
991 | case DATA_TYPE_STRING: { |
992 | char *val; |
993 | |
994 | /* check string value for match */ |
995 | if (nvpair_value_string(nvp, &val) == 0) { |
996 | if (value_regex) { |
997 | if (regexec(value_regex, val, |
998 | (size_t)0, NULL, 0) == 0) |
999 | return (1); /* match */ |
1000 | } else { |
1001 | if (strcmp(value, val) == 0) |
1002 | return (1); /* match */ |
1003 | } |
1004 | } |
1005 | break; |
1006 | } |
1007 | case DATA_TYPE_STRING_ARRAY: { |
1008 | char **val_array; |
1009 | |
1010 | /* check indexed string value of array for match */ |
1011 | if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) && |
1012 | (ai < a_len)) { |
1013 | if (value_regex) { |
1014 | if (regexec(value_regex, val_array[ai], |
1015 | (size_t)0, NULL, 0) == 0) |
1016 | return (1); |
1017 | } else { |
1018 | if (strcmp(value, val_array[ai]) == 0) |
1019 | return (1); |
1020 | } |
1021 | } |
1022 | break; |
1023 | } |
1024 | case DATA_TYPE_BYTE: { |
1025 | uchar_t val, val_arg; |
1026 | |
1027 | /* scanf uchar_t from value and check for match */ |
1028 | sr = sscanf(value, "%c" , &val_arg); |
1029 | if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) && |
1030 | (val == val_arg)) |
1031 | return (1); |
1032 | break; |
1033 | } |
1034 | case DATA_TYPE_BYTE_ARRAY: { |
1035 | uchar_t *val_array, val_arg; |
1036 | |
1037 | |
1038 | /* check indexed value of array for match */ |
1039 | sr = sscanf(value, "%c" , &val_arg); |
1040 | if ((sr == 1) && |
1041 | (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) && |
1042 | (ai < a_len) && |
1043 | (val_array[ai] == val_arg)) |
1044 | return (1); |
1045 | break; |
1046 | } |
1047 | case DATA_TYPE_INT8: { |
1048 | int8_t val, val_arg; |
1049 | |
1050 | /* scanf int8_t from value and check for match */ |
1051 | sr = sscanf(value, "%" SCNi8, &val_arg); |
1052 | if ((sr == 1) && |
1053 | (nvpair_value_int8(nvp, &val) == 0) && |
1054 | (val == val_arg)) |
1055 | return (1); |
1056 | break; |
1057 | } |
1058 | case DATA_TYPE_INT8_ARRAY: { |
1059 | int8_t *val_array, val_arg; |
1060 | |
1061 | /* check indexed value of array for match */ |
1062 | sr = sscanf(value, "%" SCNi8, &val_arg); |
1063 | if ((sr == 1) && |
1064 | (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) && |
1065 | (ai < a_len) && |
1066 | (val_array[ai] == val_arg)) |
1067 | return (1); |
1068 | break; |
1069 | } |
1070 | case DATA_TYPE_UINT8: { |
1071 | uint8_t val, val_arg; |
1072 | |
1073 | /* scanf uint8_t from value and check for match */ |
1074 | sr = sscanf(value, "%" SCNi8, (int8_t *)&val_arg); |
1075 | if ((sr == 1) && |
1076 | (nvpair_value_uint8(nvp, &val) == 0) && |
1077 | (val == val_arg)) |
1078 | return (1); |
1079 | break; |
1080 | } |
1081 | case DATA_TYPE_UINT8_ARRAY: { |
1082 | uint8_t *val_array, val_arg; |
1083 | |
1084 | /* check indexed value of array for match */ |
1085 | sr = sscanf(value, "%" SCNi8, (int8_t *)&val_arg); |
1086 | if ((sr == 1) && |
1087 | (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) && |
1088 | (ai < a_len) && |
1089 | (val_array[ai] == val_arg)) |
1090 | return (1); |
1091 | break; |
1092 | } |
1093 | case DATA_TYPE_INT16: { |
1094 | int16_t val, val_arg; |
1095 | |
1096 | /* scanf int16_t from value and check for match */ |
1097 | sr = sscanf(value, "%" SCNi16, &val_arg); |
1098 | if ((sr == 1) && |
1099 | (nvpair_value_int16(nvp, &val) == 0) && |
1100 | (val == val_arg)) |
1101 | return (1); |
1102 | break; |
1103 | } |
1104 | case DATA_TYPE_INT16_ARRAY: { |
1105 | int16_t *val_array, val_arg; |
1106 | |
1107 | /* check indexed value of array for match */ |
1108 | sr = sscanf(value, "%" SCNi16, &val_arg); |
1109 | if ((sr == 1) && |
1110 | (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) && |
1111 | (ai < a_len) && |
1112 | (val_array[ai] == val_arg)) |
1113 | return (1); |
1114 | break; |
1115 | } |
1116 | case DATA_TYPE_UINT16: { |
1117 | uint16_t val, val_arg; |
1118 | |
1119 | /* scanf uint16_t from value and check for match */ |
1120 | sr = sscanf(value, "%" SCNi16, (int16_t *)&val_arg); |
1121 | if ((sr == 1) && |
1122 | (nvpair_value_uint16(nvp, &val) == 0) && |
1123 | (val == val_arg)) |
1124 | return (1); |
1125 | break; |
1126 | } |
1127 | case DATA_TYPE_UINT16_ARRAY: { |
1128 | uint16_t *val_array, val_arg; |
1129 | |
1130 | /* check indexed value of array for match */ |
1131 | sr = sscanf(value, "%" SCNi16, (int16_t *)&val_arg); |
1132 | if ((sr == 1) && |
1133 | (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) && |
1134 | (ai < a_len) && |
1135 | (val_array[ai] == val_arg)) |
1136 | return (1); |
1137 | break; |
1138 | } |
1139 | case DATA_TYPE_INT32: { |
1140 | int32_t val, val_arg; |
1141 | |
1142 | /* scanf int32_t from value and check for match */ |
1143 | sr = sscanf(value, "%" SCNi32, &val_arg); |
1144 | if ((sr == 1) && |
1145 | (nvpair_value_int32(nvp, &val) == 0) && |
1146 | (val == val_arg)) |
1147 | return (1); |
1148 | break; |
1149 | } |
1150 | case DATA_TYPE_INT32_ARRAY: { |
1151 | int32_t *val_array, val_arg; |
1152 | |
1153 | /* check indexed value of array for match */ |
1154 | sr = sscanf(value, "%" SCNi32, &val_arg); |
1155 | if ((sr == 1) && |
1156 | (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) && |
1157 | (ai < a_len) && |
1158 | (val_array[ai] == val_arg)) |
1159 | return (1); |
1160 | break; |
1161 | } |
1162 | case DATA_TYPE_UINT32: { |
1163 | uint32_t val, val_arg; |
1164 | |
1165 | /* scanf uint32_t from value and check for match */ |
1166 | sr = sscanf(value, "%" SCNi32, (int32_t *)&val_arg); |
1167 | if ((sr == 1) && |
1168 | (nvpair_value_uint32(nvp, &val) == 0) && |
1169 | (val == val_arg)) |
1170 | return (1); |
1171 | break; |
1172 | } |
1173 | case DATA_TYPE_UINT32_ARRAY: { |
1174 | uint32_t *val_array, val_arg; |
1175 | |
1176 | /* check indexed value of array for match */ |
1177 | sr = sscanf(value, "%" SCNi32, (int32_t *)&val_arg); |
1178 | if ((sr == 1) && |
1179 | (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) && |
1180 | (ai < a_len) && |
1181 | (val_array[ai] == val_arg)) |
1182 | return (1); |
1183 | break; |
1184 | } |
1185 | case DATA_TYPE_INT64: { |
1186 | int64_t val, val_arg; |
1187 | |
1188 | /* scanf int64_t from value and check for match */ |
1189 | sr = sscanf(value, "%" SCNi64, &val_arg); |
1190 | if ((sr == 1) && |
1191 | (nvpair_value_int64(nvp, &val) == 0) && |
1192 | (val == val_arg)) |
1193 | return (1); |
1194 | break; |
1195 | } |
1196 | case DATA_TYPE_INT64_ARRAY: { |
1197 | int64_t *val_array, val_arg; |
1198 | |
1199 | /* check indexed value of array for match */ |
1200 | sr = sscanf(value, "%" SCNi64, &val_arg); |
1201 | if ((sr == 1) && |
1202 | (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) && |
1203 | (ai < a_len) && |
1204 | (val_array[ai] == val_arg)) |
1205 | return (1); |
1206 | break; |
1207 | } |
1208 | case DATA_TYPE_UINT64: { |
1209 | uint64_t val_arg, val; |
1210 | |
1211 | /* scanf uint64_t from value and check for match */ |
1212 | sr = sscanf(value, "%" SCNi64, (int64_t *)&val_arg); |
1213 | if ((sr == 1) && |
1214 | (nvpair_value_uint64(nvp, &val) == 0) && |
1215 | (val == val_arg)) |
1216 | return (1); |
1217 | break; |
1218 | } |
1219 | case DATA_TYPE_UINT64_ARRAY: { |
1220 | uint64_t *val_array, val_arg; |
1221 | |
1222 | /* check indexed value of array for match */ |
1223 | sr = sscanf(value, "%" SCNi64, (int64_t *)&val_arg); |
1224 | if ((sr == 1) && |
1225 | (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) && |
1226 | (ai < a_len) && |
1227 | (val_array[ai] == val_arg)) |
1228 | return (1); |
1229 | break; |
1230 | } |
1231 | case DATA_TYPE_BOOLEAN_VALUE: { |
1232 | int32_t val_arg; |
1233 | boolean_t val; |
1234 | |
1235 | /* scanf boolean_t from value and check for match */ |
1236 | sr = sscanf(value, "%" SCNi32, &val_arg); |
1237 | if ((sr == 1) && |
1238 | (nvpair_value_boolean_value(nvp, &val) == 0) && |
1239 | (val == val_arg)) |
1240 | return (1); |
1241 | break; |
1242 | } |
1243 | case DATA_TYPE_BOOLEAN_ARRAY: { |
1244 | boolean_t *val_array; |
1245 | int32_t val_arg; |
1246 | |
1247 | /* check indexed value of array for match */ |
1248 | sr = sscanf(value, "%" SCNi32, &val_arg); |
1249 | if ((sr == 1) && |
1250 | (nvpair_value_boolean_array(nvp, |
1251 | &val_array, &a_len) == 0) && |
1252 | (ai < a_len) && |
1253 | (val_array[ai] == val_arg)) |
1254 | return (1); |
1255 | break; |
1256 | } |
1257 | case DATA_TYPE_HRTIME: |
1258 | case DATA_TYPE_NVLIST: |
1259 | case DATA_TYPE_NVLIST_ARRAY: |
1260 | case DATA_TYPE_BOOLEAN: |
1261 | case DATA_TYPE_DOUBLE: |
1262 | case DATA_TYPE_UNKNOWN: |
1263 | default: |
1264 | /* |
1265 | * unknown/unsupported data type |
1266 | */ |
1267 | return (-1); /* error fail match */ |
1268 | } |
1269 | |
1270 | /* |
1271 | * check to see if sscanf failed conversion, return approximate |
1272 | * pointer to problem |
1273 | */ |
1274 | if (sr != 1) { |
1275 | if (ep) |
1276 | *ep = value; |
1277 | return (-1); /* error fail match - syntax */ |
1278 | } |
1279 | |
1280 | return (0); /* fail match */ |
1281 | } |
1282 | |
1283 | int |
1284 | nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep) |
1285 | { |
1286 | return (nvpair_value_match_regex(nvp, ai, value, NULL, ep)); |
1287 | } |
1288 | |