1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5185029Spjd * Common Development and Distribution License (the "License"). 6185029Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22219089Spjd * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 23236884Smm * Copyright (c) 2012 by Delphix. All rights reserved. 24168404Spjd */ 25168404Spjd 26219089Spjd#include <solaris.h> 27185029Spjd#include <inttypes.h> 28168404Spjd#include <unistd.h> 29307124Smav#include <string.h> 30219089Spjd#include <libintl.h> 31219089Spjd#include <stdarg.h> 32168404Spjd#include "libnvpair.h" 33168404Spjd 34168404Spjd/* 35168404Spjd * libnvpair - A tools library for manipulating <name, value> pairs. 36168404Spjd * 37168404Spjd * This library provides routines packing an unpacking nv pairs 38168404Spjd * for transporting data across process boundaries, transporting 39168404Spjd * between kernel and userland, and possibly saving onto disk files. 40168404Spjd */ 41168404Spjd 42219089Spjd/* 43219089Spjd * Print control structure. 44219089Spjd */ 45219089Spjd 46219089Spjd#define DEFINEOP(opname, vtype) \ 47219089Spjd struct { \ 48219089Spjd int (*op)(struct nvlist_prtctl *, void *, nvlist_t *, \ 49219089Spjd const char *, vtype); \ 50219089Spjd void *arg; \ 51219089Spjd } opname 52219089Spjd 53219089Spjd#define DEFINEARROP(opname, vtype) \ 54219089Spjd struct { \ 55219089Spjd int (*op)(struct nvlist_prtctl *, void *, nvlist_t *, \ 56219089Spjd const char *, vtype, uint_t); \ 57219089Spjd void *arg; \ 58219089Spjd } opname 59219089Spjd 60219089Spjdstruct nvlist_printops { 61219089Spjd DEFINEOP(print_boolean, int); 62219089Spjd DEFINEOP(print_boolean_value, boolean_t); 63219089Spjd DEFINEOP(print_byte, uchar_t); 64219089Spjd DEFINEOP(print_int8, int8_t); 65219089Spjd DEFINEOP(print_uint8, uint8_t); 66219089Spjd DEFINEOP(print_int16, int16_t); 67219089Spjd DEFINEOP(print_uint16, uint16_t); 68219089Spjd DEFINEOP(print_int32, int32_t); 69219089Spjd DEFINEOP(print_uint32, uint32_t); 70219089Spjd DEFINEOP(print_int64, int64_t); 71219089Spjd DEFINEOP(print_uint64, uint64_t); 72219089Spjd DEFINEOP(print_double, double); 73219089Spjd DEFINEOP(print_string, char *); 74219089Spjd DEFINEOP(print_hrtime, hrtime_t); 75219089Spjd DEFINEOP(print_nvlist, nvlist_t *); 76219089Spjd DEFINEARROP(print_boolean_array, boolean_t *); 77219089Spjd DEFINEARROP(print_byte_array, uchar_t *); 78219089Spjd DEFINEARROP(print_int8_array, int8_t *); 79219089Spjd DEFINEARROP(print_uint8_array, uint8_t *); 80219089Spjd DEFINEARROP(print_int16_array, int16_t *); 81219089Spjd DEFINEARROP(print_uint16_array, uint16_t *); 82219089Spjd DEFINEARROP(print_int32_array, int32_t *); 83219089Spjd DEFINEARROP(print_uint32_array, uint32_t *); 84219089Spjd DEFINEARROP(print_int64_array, int64_t *); 85219089Spjd DEFINEARROP(print_uint64_array, uint64_t *); 86219089Spjd DEFINEARROP(print_string_array, char **); 87219089Spjd DEFINEARROP(print_nvlist_array, nvlist_t **); 88219089Spjd}; 89219089Spjd 90219089Spjdstruct nvlist_prtctl { 91219089Spjd FILE *nvprt_fp; /* output destination */ 92219089Spjd enum nvlist_indent_mode nvprt_indent_mode; /* see above */ 93219089Spjd int nvprt_indent; /* absolute indent, or tab depth */ 94219089Spjd int nvprt_indentinc; /* indent or tab increment */ 95219089Spjd const char *nvprt_nmfmt; /* member name format, max one %s */ 96219089Spjd const char *nvprt_eomfmt; /* after member format, e.g. "\n" */ 97219089Spjd const char *nvprt_btwnarrfmt; /* between array members */ 98219089Spjd int nvprt_btwnarrfmt_nl; /* nvprt_eoamfmt includes newline? */ 99219089Spjd struct nvlist_printops *nvprt_dfltops; 100219089Spjd struct nvlist_printops *nvprt_custops; 101219089Spjd}; 102219089Spjd 103219089Spjd#define DFLTPRTOP(pctl, type) \ 104219089Spjd ((pctl)->nvprt_dfltops->print_##type.op) 105219089Spjd 106219089Spjd#define DFLTPRTOPARG(pctl, type) \ 107219089Spjd ((pctl)->nvprt_dfltops->print_##type.arg) 108219089Spjd 109219089Spjd#define CUSTPRTOP(pctl, type) \ 110219089Spjd ((pctl)->nvprt_custops->print_##type.op) 111219089Spjd 112219089Spjd#define CUSTPRTOPARG(pctl, type) \ 113219089Spjd ((pctl)->nvprt_custops->print_##type.arg) 114219089Spjd 115219089Spjd#define RENDER(pctl, type, nvl, name, val) \ 116219089Spjd { \ 117219089Spjd int done = 0; \ 118219089Spjd if ((pctl)->nvprt_custops && CUSTPRTOP(pctl, type)) { \ 119219089Spjd done = CUSTPRTOP(pctl, type)(pctl, \ 120219089Spjd CUSTPRTOPARG(pctl, type), nvl, name, val); \ 121219089Spjd } \ 122219089Spjd if (!done) { \ 123219089Spjd (void) DFLTPRTOP(pctl, type)(pctl, \ 124219089Spjd DFLTPRTOPARG(pctl, type), nvl, name, val); \ 125219089Spjd } \ 126219089Spjd (void) fprintf(pctl->nvprt_fp, pctl->nvprt_eomfmt); \ 127219089Spjd } 128219089Spjd 129219089Spjd#define ARENDER(pctl, type, nvl, name, arrp, count) \ 130219089Spjd { \ 131219089Spjd int done = 0; \ 132219089Spjd if ((pctl)->nvprt_custops && CUSTPRTOP(pctl, type)) { \ 133219089Spjd done = CUSTPRTOP(pctl, type)(pctl, \ 134219089Spjd CUSTPRTOPARG(pctl, type), nvl, name, arrp, count); \ 135219089Spjd } \ 136219089Spjd if (!done) { \ 137219089Spjd (void) DFLTPRTOP(pctl, type)(pctl, \ 138219089Spjd DFLTPRTOPARG(pctl, type), nvl, name, arrp, count); \ 139219089Spjd } \ 140219089Spjd (void) fprintf(pctl->nvprt_fp, pctl->nvprt_eomfmt); \ 141219089Spjd } 142219089Spjd 143219089Spjdstatic void nvlist_print_with_indent(nvlist_t *, nvlist_prtctl_t); 144219089Spjd 145219089Spjd/* 146219089Spjd * ====================================================================== 147219089Spjd * | | 148219089Spjd * | Indentation | 149219089Spjd * | | 150219089Spjd * ====================================================================== 151219089Spjd */ 152219089Spjd 153168404Spjdstatic void 154219089Spjdindent(nvlist_prtctl_t pctl, int onemore) 155168404Spjd{ 156219089Spjd int depth; 157219089Spjd 158219089Spjd switch (pctl->nvprt_indent_mode) { 159219089Spjd case NVLIST_INDENT_ABS: 160219089Spjd (void) fprintf(pctl->nvprt_fp, "%*s", 161219089Spjd pctl->nvprt_indent + onemore * pctl->nvprt_indentinc, ""); 162219089Spjd break; 163219089Spjd 164219089Spjd case NVLIST_INDENT_TABBED: 165219089Spjd depth = pctl->nvprt_indent + onemore; 166219089Spjd while (depth-- > 0) 167219089Spjd (void) fprintf(pctl->nvprt_fp, "\t"); 168219089Spjd } 169168404Spjd} 170168404Spjd 171168404Spjd/* 172219089Spjd * ====================================================================== 173219089Spjd * | | 174219089Spjd * | Default nvlist member rendering functions. | 175219089Spjd * | | 176219089Spjd * ====================================================================== 177168404Spjd */ 178219089Spjd 179219089Spjd/* 180219089Spjd * Generate functions to print single-valued nvlist members. 181219089Spjd * 182219089Spjd * type_and_variant - suffix to form function name 183219089Spjd * vtype - C type for the member value 184219089Spjd * ptype - C type to cast value to for printing 185219089Spjd * vfmt - format string for pair value, e.g "%d" or "0x%llx" 186219089Spjd */ 187219089Spjd 188219089Spjd#define NVLIST_PRTFUNC(type_and_variant, vtype, ptype, vfmt) \ 189219089Spjdstatic int \ 190219089Spjdnvprint_##type_and_variant(nvlist_prtctl_t pctl, void *private, \ 191219089Spjd nvlist_t *nvl, const char *name, vtype value) \ 192219089Spjd{ \ 193219089Spjd FILE *fp = pctl->nvprt_fp; \ 194219089Spjd NOTE(ARGUNUSED(private)) \ 195219089Spjd NOTE(ARGUNUSED(nvl)) \ 196219089Spjd indent(pctl, 1); \ 197219089Spjd (void) fprintf(fp, pctl->nvprt_nmfmt, name); \ 198219089Spjd (void) fprintf(fp, vfmt, (ptype)value); \ 199219089Spjd return (1); \ 200219089Spjd} 201219089Spjd 202219089SpjdNVLIST_PRTFUNC(boolean, int, int, "%d") 203219089SpjdNVLIST_PRTFUNC(boolean_value, boolean_t, int, "%d") 204219089SpjdNVLIST_PRTFUNC(byte, uchar_t, uchar_t, "0x%2.2x") 205219089SpjdNVLIST_PRTFUNC(int8, int8_t, int, "%d") 206219089SpjdNVLIST_PRTFUNC(uint8, uint8_t, uint8_t, "0x%x") 207219089SpjdNVLIST_PRTFUNC(int16, int16_t, int16_t, "%d") 208219089SpjdNVLIST_PRTFUNC(uint16, uint16_t, uint16_t, "0x%x") 209219089SpjdNVLIST_PRTFUNC(int32, int32_t, int32_t, "%d") 210219089SpjdNVLIST_PRTFUNC(uint32, uint32_t, uint32_t, "0x%x") 211219089SpjdNVLIST_PRTFUNC(int64, int64_t, longlong_t, "%lld") 212219089SpjdNVLIST_PRTFUNC(uint64, uint64_t, u_longlong_t, "0x%llx") 213302846SasomersNVLIST_PRTFUNC(double, double, double, "0x%f") 214219089SpjdNVLIST_PRTFUNC(string, char *, char *, "%s") 215219089SpjdNVLIST_PRTFUNC(hrtime, hrtime_t, hrtime_t, "0x%llx") 216219089Spjd 217219089Spjd/* 218219089Spjd * Generate functions to print array-valued nvlist members. 219219089Spjd */ 220219089Spjd 221219089Spjd#define NVLIST_ARRPRTFUNC(type_and_variant, vtype, ptype, vfmt) \ 222219089Spjdstatic int \ 223219089Spjdnvaprint_##type_and_variant(nvlist_prtctl_t pctl, void *private, \ 224219089Spjd nvlist_t *nvl, const char *name, vtype *valuep, uint_t count) \ 225219089Spjd{ \ 226219089Spjd FILE *fp = pctl->nvprt_fp; \ 227219089Spjd uint_t i; \ 228219089Spjd NOTE(ARGUNUSED(private)) \ 229219089Spjd NOTE(ARGUNUSED(nvl)) \ 230219089Spjd for (i = 0; i < count; i++) { \ 231219089Spjd if (i == 0 || pctl->nvprt_btwnarrfmt_nl) { \ 232219089Spjd indent(pctl, 1); \ 233219089Spjd (void) fprintf(fp, pctl->nvprt_nmfmt, name); \ 234219089Spjd if (pctl->nvprt_btwnarrfmt_nl) \ 235219089Spjd (void) fprintf(fp, "[%d]: ", i); \ 236219089Spjd } \ 237219089Spjd if (i != 0) \ 238219089Spjd (void) fprintf(fp, pctl->nvprt_btwnarrfmt); \ 239219089Spjd (void) fprintf(fp, vfmt, (ptype)valuep[i]); \ 240219089Spjd } \ 241219089Spjd return (1); \ 242219089Spjd} 243219089Spjd 244219089SpjdNVLIST_ARRPRTFUNC(boolean_array, boolean_t, boolean_t, "%d") 245219089SpjdNVLIST_ARRPRTFUNC(byte_array, uchar_t, uchar_t, "0x%2.2x") 246219089SpjdNVLIST_ARRPRTFUNC(int8_array, int8_t, int8_t, "%d") 247219089SpjdNVLIST_ARRPRTFUNC(uint8_array, uint8_t, uint8_t, "0x%x") 248219089SpjdNVLIST_ARRPRTFUNC(int16_array, int16_t, int16_t, "%d") 249219089SpjdNVLIST_ARRPRTFUNC(uint16_array, uint16_t, uint16_t, "0x%x") 250219089SpjdNVLIST_ARRPRTFUNC(int32_array, int32_t, int32_t, "%d") 251219089SpjdNVLIST_ARRPRTFUNC(uint32_array, uint32_t, uint32_t, "0x%x") 252219089SpjdNVLIST_ARRPRTFUNC(int64_array, int64_t, longlong_t, "%lld") 253219089SpjdNVLIST_ARRPRTFUNC(uint64_array, uint64_t, u_longlong_t, "0x%llx") 254219089SpjdNVLIST_ARRPRTFUNC(string_array, char *, char *, "%s") 255219089Spjd 256219089Spjd/*ARGSUSED*/ 257219089Spjdstatic int 258219089Spjdnvprint_nvlist(nvlist_prtctl_t pctl, void *private, 259219089Spjd nvlist_t *nvl, const char *name, nvlist_t *value) 260219089Spjd{ 261219089Spjd FILE *fp = pctl->nvprt_fp; 262219089Spjd 263219089Spjd indent(pctl, 1); 264219089Spjd (void) fprintf(fp, "%s = (embedded nvlist)\n", name); 265219089Spjd 266219089Spjd pctl->nvprt_indent += pctl->nvprt_indentinc; 267219089Spjd nvlist_print_with_indent(value, pctl); 268219089Spjd pctl->nvprt_indent -= pctl->nvprt_indentinc; 269219089Spjd 270219089Spjd indent(pctl, 1); 271219089Spjd (void) fprintf(fp, "(end %s)\n", name); 272219089Spjd 273219089Spjd return (1); 274219089Spjd} 275219089Spjd 276219089Spjd/*ARGSUSED*/ 277219089Spjdstatic int 278219089Spjdnvaprint_nvlist_array(nvlist_prtctl_t pctl, void *private, 279219089Spjd nvlist_t *nvl, const char *name, nvlist_t **valuep, uint_t count) 280219089Spjd{ 281219089Spjd FILE *fp = pctl->nvprt_fp; 282219089Spjd uint_t i; 283219089Spjd 284219089Spjd indent(pctl, 1); 285219089Spjd (void) fprintf(fp, "%s = (array of embedded nvlists)\n", name); 286219089Spjd 287219089Spjd for (i = 0; i < count; i++) { 288219089Spjd indent(pctl, 1); 289219089Spjd (void) fprintf(fp, "(start %s[%d])\n", name, i); 290219089Spjd 291219089Spjd pctl->nvprt_indent += pctl->nvprt_indentinc; 292219089Spjd nvlist_print_with_indent(valuep[i], pctl); 293219089Spjd pctl->nvprt_indent -= pctl->nvprt_indentinc; 294219089Spjd 295219089Spjd indent(pctl, 1); 296219089Spjd (void) fprintf(fp, "(end %s[%d])\n", name, i); 297219089Spjd } 298219089Spjd 299219089Spjd return (1); 300219089Spjd} 301219089Spjd 302219089Spjd/* 303219089Spjd * ====================================================================== 304219089Spjd * | | 305219089Spjd * | Interfaces that allow control over formatting. | 306219089Spjd * | | 307219089Spjd * ====================================================================== 308219089Spjd */ 309219089Spjd 310168404Spjdvoid 311219089Spjdnvlist_prtctl_setdest(nvlist_prtctl_t pctl, FILE *fp) 312168404Spjd{ 313219089Spjd pctl->nvprt_fp = fp; 314219089Spjd} 315219089Spjd 316219089SpjdFILE * 317219089Spjdnvlist_prtctl_getdest(nvlist_prtctl_t pctl) 318219089Spjd{ 319219089Spjd return (pctl->nvprt_fp); 320219089Spjd} 321219089Spjd 322219089Spjd 323219089Spjdvoid 324219089Spjdnvlist_prtctl_setindent(nvlist_prtctl_t pctl, enum nvlist_indent_mode mode, 325219089Spjd int start, int inc) 326219089Spjd{ 327219089Spjd if (mode < NVLIST_INDENT_ABS || mode > NVLIST_INDENT_TABBED) 328219089Spjd mode = NVLIST_INDENT_TABBED; 329219089Spjd 330219089Spjd if (start < 0) 331219089Spjd start = 0; 332219089Spjd 333219089Spjd if (inc < 0) 334219089Spjd inc = 1; 335219089Spjd 336219089Spjd pctl->nvprt_indent_mode = mode; 337219089Spjd pctl->nvprt_indent = start; 338219089Spjd pctl->nvprt_indentinc = inc; 339219089Spjd} 340219089Spjd 341219089Spjdvoid 342219089Spjdnvlist_prtctl_doindent(nvlist_prtctl_t pctl, int onemore) 343219089Spjd{ 344219089Spjd indent(pctl, onemore); 345219089Spjd} 346219089Spjd 347219089Spjd 348219089Spjdvoid 349219089Spjdnvlist_prtctl_setfmt(nvlist_prtctl_t pctl, enum nvlist_prtctl_fmt which, 350219089Spjd const char *fmt) 351219089Spjd{ 352219089Spjd switch (which) { 353219089Spjd case NVLIST_FMT_MEMBER_NAME: 354219089Spjd if (fmt == NULL) 355219089Spjd fmt = "%s = "; 356219089Spjd pctl->nvprt_nmfmt = fmt; 357219089Spjd break; 358219089Spjd 359219089Spjd case NVLIST_FMT_MEMBER_POSTAMBLE: 360219089Spjd if (fmt == NULL) 361219089Spjd fmt = "\n"; 362219089Spjd pctl->nvprt_eomfmt = fmt; 363219089Spjd break; 364219089Spjd 365219089Spjd case NVLIST_FMT_BTWN_ARRAY: 366219089Spjd if (fmt == NULL) { 367219089Spjd pctl->nvprt_btwnarrfmt = " "; 368219089Spjd pctl->nvprt_btwnarrfmt_nl = 0; 369219089Spjd } else { 370219089Spjd pctl->nvprt_btwnarrfmt = fmt; 371219089Spjd pctl->nvprt_btwnarrfmt_nl = (strstr(fmt, "\n") != NULL); 372219089Spjd } 373219089Spjd break; 374219089Spjd 375219089Spjd default: 376219089Spjd break; 377219089Spjd } 378219089Spjd} 379219089Spjd 380219089Spjd 381219089Spjdvoid 382219089Spjdnvlist_prtctl_dofmt(nvlist_prtctl_t pctl, enum nvlist_prtctl_fmt which, ...) 383219089Spjd{ 384219089Spjd FILE *fp = pctl->nvprt_fp; 385219089Spjd va_list ap; 386168404Spjd char *name; 387219089Spjd 388219089Spjd va_start(ap, which); 389219089Spjd 390219089Spjd switch (which) { 391219089Spjd case NVLIST_FMT_MEMBER_NAME: 392219089Spjd name = va_arg(ap, char *); 393219089Spjd (void) fprintf(fp, pctl->nvprt_nmfmt, name); 394219089Spjd break; 395219089Spjd 396219089Spjd case NVLIST_FMT_MEMBER_POSTAMBLE: 397219089Spjd (void) fprintf(fp, pctl->nvprt_eomfmt); 398219089Spjd break; 399219089Spjd 400219089Spjd case NVLIST_FMT_BTWN_ARRAY: 401219089Spjd (void) fprintf(fp, pctl->nvprt_btwnarrfmt); \ 402219089Spjd break; 403219089Spjd 404219089Spjd default: 405219089Spjd break; 406219089Spjd } 407219089Spjd 408219089Spjd va_end(ap); 409219089Spjd} 410219089Spjd 411219089Spjd/* 412219089Spjd * ====================================================================== 413219089Spjd * | | 414219089Spjd * | Interfaces to allow appointment of replacement rendering functions.| 415219089Spjd * | | 416219089Spjd * ====================================================================== 417219089Spjd */ 418219089Spjd 419219089Spjd#define NVLIST_PRINTCTL_REPLACE(type, vtype) \ 420219089Spjdvoid \ 421219089Spjdnvlist_prtctlop_##type(nvlist_prtctl_t pctl, \ 422219089Spjd int (*func)(nvlist_prtctl_t, void *, nvlist_t *, const char *, vtype), \ 423219089Spjd void *private) \ 424219089Spjd{ \ 425219089Spjd CUSTPRTOP(pctl, type) = func; \ 426219089Spjd CUSTPRTOPARG(pctl, type) = private; \ 427219089Spjd} 428219089Spjd 429219089SpjdNVLIST_PRINTCTL_REPLACE(boolean, int) 430219089SpjdNVLIST_PRINTCTL_REPLACE(boolean_value, boolean_t) 431219089SpjdNVLIST_PRINTCTL_REPLACE(byte, uchar_t) 432219089SpjdNVLIST_PRINTCTL_REPLACE(int8, int8_t) 433219089SpjdNVLIST_PRINTCTL_REPLACE(uint8, uint8_t) 434219089SpjdNVLIST_PRINTCTL_REPLACE(int16, int16_t) 435219089SpjdNVLIST_PRINTCTL_REPLACE(uint16, uint16_t) 436219089SpjdNVLIST_PRINTCTL_REPLACE(int32, int32_t) 437219089SpjdNVLIST_PRINTCTL_REPLACE(uint32, uint32_t) 438219089SpjdNVLIST_PRINTCTL_REPLACE(int64, int64_t) 439219089SpjdNVLIST_PRINTCTL_REPLACE(uint64, uint64_t) 440219089SpjdNVLIST_PRINTCTL_REPLACE(double, double) 441219089SpjdNVLIST_PRINTCTL_REPLACE(string, char *) 442219089SpjdNVLIST_PRINTCTL_REPLACE(hrtime, hrtime_t) 443219089SpjdNVLIST_PRINTCTL_REPLACE(nvlist, nvlist_t *) 444219089Spjd 445219089Spjd#define NVLIST_PRINTCTL_AREPLACE(type, vtype) \ 446219089Spjdvoid \ 447219089Spjdnvlist_prtctlop_##type(nvlist_prtctl_t pctl, \ 448219089Spjd int (*func)(nvlist_prtctl_t, void *, nvlist_t *, const char *, vtype, \ 449219089Spjd uint_t), void *private) \ 450219089Spjd{ \ 451219089Spjd CUSTPRTOP(pctl, type) = func; \ 452219089Spjd CUSTPRTOPARG(pctl, type) = private; \ 453219089Spjd} 454219089Spjd 455219089SpjdNVLIST_PRINTCTL_AREPLACE(boolean_array, boolean_t *) 456219089SpjdNVLIST_PRINTCTL_AREPLACE(byte_array, uchar_t *) 457219089SpjdNVLIST_PRINTCTL_AREPLACE(int8_array, int8_t *) 458219089SpjdNVLIST_PRINTCTL_AREPLACE(uint8_array, uint8_t *) 459219089SpjdNVLIST_PRINTCTL_AREPLACE(int16_array, int16_t *) 460219089SpjdNVLIST_PRINTCTL_AREPLACE(uint16_array, uint16_t *) 461219089SpjdNVLIST_PRINTCTL_AREPLACE(int32_array, int32_t *) 462219089SpjdNVLIST_PRINTCTL_AREPLACE(uint32_array, uint32_t *) 463219089SpjdNVLIST_PRINTCTL_AREPLACE(int64_array, int64_t *) 464219089SpjdNVLIST_PRINTCTL_AREPLACE(uint64_array, uint64_t *) 465219089SpjdNVLIST_PRINTCTL_AREPLACE(string_array, char **) 466219089SpjdNVLIST_PRINTCTL_AREPLACE(nvlist_array, nvlist_t **) 467219089Spjd 468219089Spjd/* 469219089Spjd * ====================================================================== 470219089Spjd * | | 471219089Spjd * | Interfaces to manage nvlist_prtctl_t cookies. | 472219089Spjd * | | 473219089Spjd * ====================================================================== 474219089Spjd */ 475219089Spjd 476219089Spjd 477219089Spjdstatic const struct nvlist_printops defprtops = { 478219089Spjd { nvprint_boolean, NULL }, 479219089Spjd { nvprint_boolean_value, NULL }, 480219089Spjd { nvprint_byte, NULL }, 481219089Spjd { nvprint_int8, NULL }, 482219089Spjd { nvprint_uint8, NULL }, 483219089Spjd { nvprint_int16, NULL }, 484219089Spjd { nvprint_uint16, NULL }, 485219089Spjd { nvprint_int32, NULL }, 486219089Spjd { nvprint_uint32, NULL }, 487219089Spjd { nvprint_int64, NULL }, 488219089Spjd { nvprint_uint64, NULL }, 489219089Spjd { nvprint_double, NULL }, 490219089Spjd { nvprint_string, NULL }, 491219089Spjd { nvprint_hrtime, NULL }, 492219089Spjd { nvprint_nvlist, NULL }, 493219089Spjd { nvaprint_boolean_array, NULL }, 494219089Spjd { nvaprint_byte_array, NULL }, 495219089Spjd { nvaprint_int8_array, NULL }, 496219089Spjd { nvaprint_uint8_array, NULL }, 497219089Spjd { nvaprint_int16_array, NULL }, 498219089Spjd { nvaprint_uint16_array, NULL }, 499219089Spjd { nvaprint_int32_array, NULL }, 500219089Spjd { nvaprint_uint32_array, NULL }, 501219089Spjd { nvaprint_int64_array, NULL }, 502219089Spjd { nvaprint_uint64_array, NULL }, 503219089Spjd { nvaprint_string_array, NULL }, 504219089Spjd { nvaprint_nvlist_array, NULL }, 505219089Spjd}; 506219089Spjd 507219089Spjdstatic void 508219089Spjdprtctl_defaults(FILE *fp, struct nvlist_prtctl *pctl, 509219089Spjd struct nvlist_printops *ops) 510219089Spjd{ 511219089Spjd pctl->nvprt_fp = fp; 512219089Spjd pctl->nvprt_indent_mode = NVLIST_INDENT_TABBED; 513219089Spjd pctl->nvprt_indent = 0; 514219089Spjd pctl->nvprt_indentinc = 1; 515219089Spjd pctl->nvprt_nmfmt = "%s = "; 516219089Spjd pctl->nvprt_eomfmt = "\n"; 517219089Spjd pctl->nvprt_btwnarrfmt = " "; 518219089Spjd pctl->nvprt_btwnarrfmt_nl = 0; 519219089Spjd 520219089Spjd pctl->nvprt_dfltops = (struct nvlist_printops *)&defprtops; 521219089Spjd pctl->nvprt_custops = ops; 522219089Spjd} 523219089Spjd 524219089Spjdnvlist_prtctl_t 525219089Spjdnvlist_prtctl_alloc(void) 526219089Spjd{ 527219089Spjd struct nvlist_prtctl *pctl; 528219089Spjd struct nvlist_printops *ops; 529219089Spjd 530219089Spjd if ((pctl = malloc(sizeof (*pctl))) == NULL) 531219089Spjd return (NULL); 532219089Spjd 533219089Spjd if ((ops = calloc(1, sizeof (*ops))) == NULL) { 534219089Spjd free(pctl); 535219089Spjd return (NULL); 536219089Spjd } 537219089Spjd 538219089Spjd prtctl_defaults(stdout, pctl, ops); 539219089Spjd 540219089Spjd return (pctl); 541219089Spjd} 542219089Spjd 543219089Spjdvoid 544219089Spjdnvlist_prtctl_free(nvlist_prtctl_t pctl) 545219089Spjd{ 546219089Spjd if (pctl != NULL) { 547219089Spjd free(pctl->nvprt_custops); 548219089Spjd free(pctl); 549219089Spjd } 550219089Spjd} 551219089Spjd 552219089Spjd/* 553219089Spjd * ====================================================================== 554219089Spjd * | | 555219089Spjd * | Top-level print request interfaces. | 556219089Spjd * | | 557219089Spjd * ====================================================================== 558219089Spjd */ 559219089Spjd 560219089Spjd/* 561219089Spjd * nvlist_print - Prints elements in an event buffer 562219089Spjd */ 563219089Spjdstatic void 564219089Spjdnvlist_print_with_indent(nvlist_t *nvl, nvlist_prtctl_t pctl) 565219089Spjd{ 566219089Spjd FILE *fp = pctl->nvprt_fp; 567219089Spjd char *name; 568168404Spjd uint_t nelem; 569168404Spjd nvpair_t *nvp; 570168404Spjd 571168404Spjd if (nvl == NULL) 572168404Spjd return; 573168404Spjd 574219089Spjd indent(pctl, 0); 575168404Spjd (void) fprintf(fp, "nvlist version: %d\n", NVL_VERSION(nvl)); 576168404Spjd 577168404Spjd nvp = nvlist_next_nvpair(nvl, NULL); 578168404Spjd 579168404Spjd while (nvp) { 580168404Spjd data_type_t type = nvpair_type(nvp); 581168404Spjd 582168404Spjd name = nvpair_name(nvp); 583168404Spjd nelem = 0; 584219089Spjd 585168404Spjd switch (type) { 586168404Spjd case DATA_TYPE_BOOLEAN: { 587219089Spjd RENDER(pctl, boolean, nvl, name, 1); 588168404Spjd break; 589168404Spjd } 590168404Spjd case DATA_TYPE_BOOLEAN_VALUE: { 591168404Spjd boolean_t val; 592168404Spjd (void) nvpair_value_boolean_value(nvp, &val); 593219089Spjd RENDER(pctl, boolean_value, nvl, name, val); 594168404Spjd break; 595168404Spjd } 596168404Spjd case DATA_TYPE_BYTE: { 597168404Spjd uchar_t val; 598168404Spjd (void) nvpair_value_byte(nvp, &val); 599219089Spjd RENDER(pctl, byte, nvl, name, val); 600168404Spjd break; 601168404Spjd } 602168404Spjd case DATA_TYPE_INT8: { 603168404Spjd int8_t val; 604168404Spjd (void) nvpair_value_int8(nvp, &val); 605219089Spjd RENDER(pctl, int8, nvl, name, val); 606168404Spjd break; 607168404Spjd } 608168404Spjd case DATA_TYPE_UINT8: { 609168404Spjd uint8_t val; 610168404Spjd (void) nvpair_value_uint8(nvp, &val); 611219089Spjd RENDER(pctl, uint8, nvl, name, val); 612168404Spjd break; 613168404Spjd } 614168404Spjd case DATA_TYPE_INT16: { 615168404Spjd int16_t val; 616168404Spjd (void) nvpair_value_int16(nvp, &val); 617219089Spjd RENDER(pctl, int16, nvl, name, val); 618168404Spjd break; 619168404Spjd } 620168404Spjd case DATA_TYPE_UINT16: { 621168404Spjd uint16_t val; 622168404Spjd (void) nvpair_value_uint16(nvp, &val); 623219089Spjd RENDER(pctl, uint16, nvl, name, val); 624168404Spjd break; 625168404Spjd } 626168404Spjd case DATA_TYPE_INT32: { 627168404Spjd int32_t val; 628168404Spjd (void) nvpair_value_int32(nvp, &val); 629219089Spjd RENDER(pctl, int32, nvl, name, val); 630168404Spjd break; 631168404Spjd } 632168404Spjd case DATA_TYPE_UINT32: { 633168404Spjd uint32_t val; 634168404Spjd (void) nvpair_value_uint32(nvp, &val); 635219089Spjd RENDER(pctl, uint32, nvl, name, val); 636168404Spjd break; 637168404Spjd } 638168404Spjd case DATA_TYPE_INT64: { 639168404Spjd int64_t val; 640168404Spjd (void) nvpair_value_int64(nvp, &val); 641219089Spjd RENDER(pctl, int64, nvl, name, val); 642168404Spjd break; 643168404Spjd } 644168404Spjd case DATA_TYPE_UINT64: { 645168404Spjd uint64_t val; 646168404Spjd (void) nvpair_value_uint64(nvp, &val); 647219089Spjd RENDER(pctl, uint64, nvl, name, val); 648168404Spjd break; 649168404Spjd } 650185029Spjd case DATA_TYPE_DOUBLE: { 651185029Spjd double val; 652185029Spjd (void) nvpair_value_double(nvp, &val); 653219089Spjd RENDER(pctl, double, nvl, name, val); 654185029Spjd break; 655185029Spjd } 656168404Spjd case DATA_TYPE_STRING: { 657168404Spjd char *val; 658168404Spjd (void) nvpair_value_string(nvp, &val); 659219089Spjd RENDER(pctl, string, nvl, name, val); 660168404Spjd break; 661168404Spjd } 662168404Spjd case DATA_TYPE_BOOLEAN_ARRAY: { 663168404Spjd boolean_t *val; 664168404Spjd (void) nvpair_value_boolean_array(nvp, &val, &nelem); 665219089Spjd ARENDER(pctl, boolean_array, nvl, name, val, nelem); 666168404Spjd break; 667168404Spjd } 668168404Spjd case DATA_TYPE_BYTE_ARRAY: { 669168404Spjd uchar_t *val; 670168404Spjd (void) nvpair_value_byte_array(nvp, &val, &nelem); 671219089Spjd ARENDER(pctl, byte_array, nvl, name, val, nelem); 672168404Spjd break; 673168404Spjd } 674168404Spjd case DATA_TYPE_INT8_ARRAY: { 675168404Spjd int8_t *val; 676168404Spjd (void) nvpair_value_int8_array(nvp, &val, &nelem); 677219089Spjd ARENDER(pctl, int8_array, nvl, name, val, nelem); 678168404Spjd break; 679168404Spjd } 680168404Spjd case DATA_TYPE_UINT8_ARRAY: { 681168404Spjd uint8_t *val; 682168404Spjd (void) nvpair_value_uint8_array(nvp, &val, &nelem); 683219089Spjd ARENDER(pctl, uint8_array, nvl, name, val, nelem); 684168404Spjd break; 685168404Spjd } 686168404Spjd case DATA_TYPE_INT16_ARRAY: { 687168404Spjd int16_t *val; 688168404Spjd (void) nvpair_value_int16_array(nvp, &val, &nelem); 689219089Spjd ARENDER(pctl, int16_array, nvl, name, val, nelem); 690168404Spjd break; 691168404Spjd } 692168404Spjd case DATA_TYPE_UINT16_ARRAY: { 693168404Spjd uint16_t *val; 694168404Spjd (void) nvpair_value_uint16_array(nvp, &val, &nelem); 695219089Spjd ARENDER(pctl, uint16_array, nvl, name, val, nelem); 696168404Spjd break; 697168404Spjd } 698168404Spjd case DATA_TYPE_INT32_ARRAY: { 699168404Spjd int32_t *val; 700168404Spjd (void) nvpair_value_int32_array(nvp, &val, &nelem); 701219089Spjd ARENDER(pctl, int32_array, nvl, name, val, nelem); 702168404Spjd break; 703168404Spjd } 704168404Spjd case DATA_TYPE_UINT32_ARRAY: { 705168404Spjd uint32_t *val; 706168404Spjd (void) nvpair_value_uint32_array(nvp, &val, &nelem); 707219089Spjd ARENDER(pctl, uint32_array, nvl, name, val, nelem); 708168404Spjd break; 709168404Spjd } 710168404Spjd case DATA_TYPE_INT64_ARRAY: { 711168404Spjd int64_t *val; 712168404Spjd (void) nvpair_value_int64_array(nvp, &val, &nelem); 713219089Spjd ARENDER(pctl, int64_array, nvl, name, val, nelem); 714168404Spjd break; 715168404Spjd } 716168404Spjd case DATA_TYPE_UINT64_ARRAY: { 717168404Spjd uint64_t *val; 718168404Spjd (void) nvpair_value_uint64_array(nvp, &val, &nelem); 719219089Spjd ARENDER(pctl, uint64_array, nvl, name, val, nelem); 720168404Spjd break; 721168404Spjd } 722168404Spjd case DATA_TYPE_STRING_ARRAY: { 723168404Spjd char **val; 724168404Spjd (void) nvpair_value_string_array(nvp, &val, &nelem); 725219089Spjd ARENDER(pctl, string_array, nvl, name, val, nelem); 726168404Spjd break; 727168404Spjd } 728168404Spjd case DATA_TYPE_HRTIME: { 729168404Spjd hrtime_t val; 730168404Spjd (void) nvpair_value_hrtime(nvp, &val); 731219089Spjd RENDER(pctl, hrtime, nvl, name, val); 732168404Spjd break; 733168404Spjd } 734168404Spjd case DATA_TYPE_NVLIST: { 735168404Spjd nvlist_t *val; 736168404Spjd (void) nvpair_value_nvlist(nvp, &val); 737219089Spjd RENDER(pctl, nvlist, nvl, name, val); 738168404Spjd break; 739168404Spjd } 740168404Spjd case DATA_TYPE_NVLIST_ARRAY: { 741168404Spjd nvlist_t **val; 742168404Spjd (void) nvpair_value_nvlist_array(nvp, &val, &nelem); 743219089Spjd ARENDER(pctl, nvlist_array, nvl, name, val, nelem); 744168404Spjd break; 745168404Spjd } 746168404Spjd default: 747168404Spjd (void) fprintf(fp, " unknown data type (%d)", type); 748168404Spjd break; 749168404Spjd } 750168404Spjd nvp = nvlist_next_nvpair(nvl, nvp); 751168404Spjd } 752168404Spjd} 753168404Spjd 754168404Spjdvoid 755168404Spjdnvlist_print(FILE *fp, nvlist_t *nvl) 756168404Spjd{ 757219089Spjd struct nvlist_prtctl pc; 758219089Spjd 759219089Spjd prtctl_defaults(fp, &pc, NULL); 760219089Spjd nvlist_print_with_indent(nvl, &pc); 761168404Spjd} 762185029Spjd 763219089Spjdvoid 764219089Spjdnvlist_prt(nvlist_t *nvl, nvlist_prtctl_t pctl) 765219089Spjd{ 766219089Spjd nvlist_print_with_indent(nvl, pctl); 767219089Spjd} 768219089Spjd 769219089Spjd#define NVP(elem, type, vtype, ptype, format) { \ 770219089Spjd vtype value; \ 771219089Spjd\ 772219089Spjd (void) nvpair_value_##type(elem, &value); \ 773219089Spjd (void) printf("%*s%s: " format "\n", indent, "", \ 774219089Spjd nvpair_name(elem), (ptype)value); \ 775219089Spjd} 776219089Spjd 777219089Spjd#define NVPA(elem, type, vtype, ptype, format) { \ 778219089Spjd uint_t i, count; \ 779219089Spjd vtype *value; \ 780219089Spjd\ 781219089Spjd (void) nvpair_value_##type(elem, &value, &count); \ 782219089Spjd for (i = 0; i < count; i++) { \ 783219089Spjd (void) printf("%*s%s[%d]: " format "\n", indent, "", \ 784219089Spjd nvpair_name(elem), i, (ptype)value[i]); \ 785219089Spjd } \ 786219089Spjd} 787219089Spjd 788185029Spjd/* 789219089Spjd * Similar to nvlist_print() but handles arrays slightly differently. 790219089Spjd */ 791219089Spjdvoid 792219089Spjddump_nvlist(nvlist_t *list, int indent) 793219089Spjd{ 794219089Spjd nvpair_t *elem = NULL; 795219089Spjd boolean_t bool_value; 796282751Savg boolean_t *bool_array_value; 797219089Spjd nvlist_t *nvlist_value; 798219089Spjd nvlist_t **nvlist_array_value; 799219089Spjd uint_t i, count; 800219089Spjd 801219089Spjd if (list == NULL) { 802219089Spjd return; 803219089Spjd } 804219089Spjd 805219089Spjd while ((elem = nvlist_next_nvpair(list, elem)) != NULL) { 806219089Spjd switch (nvpair_type(elem)) { 807236884Smm case DATA_TYPE_BOOLEAN: 808236884Smm (void) printf("%*s%s\n", indent, "", nvpair_name(elem)); 809236884Smm break; 810236884Smm 811219089Spjd case DATA_TYPE_BOOLEAN_VALUE: 812219089Spjd (void) nvpair_value_boolean_value(elem, &bool_value); 813219089Spjd (void) printf("%*s%s: %s\n", indent, "", 814219089Spjd nvpair_name(elem), bool_value ? "true" : "false"); 815219089Spjd break; 816219089Spjd 817219089Spjd case DATA_TYPE_BYTE: 818219089Spjd NVP(elem, byte, uchar_t, int, "%u"); 819219089Spjd break; 820219089Spjd 821219089Spjd case DATA_TYPE_INT8: 822219089Spjd NVP(elem, int8, int8_t, int, "%d"); 823219089Spjd break; 824219089Spjd 825219089Spjd case DATA_TYPE_UINT8: 826219089Spjd NVP(elem, uint8, uint8_t, int, "%u"); 827219089Spjd break; 828219089Spjd 829219089Spjd case DATA_TYPE_INT16: 830219089Spjd NVP(elem, int16, int16_t, int, "%d"); 831219089Spjd break; 832219089Spjd 833219089Spjd case DATA_TYPE_UINT16: 834219089Spjd NVP(elem, uint16, uint16_t, int, "%u"); 835219089Spjd break; 836219089Spjd 837219089Spjd case DATA_TYPE_INT32: 838219089Spjd NVP(elem, int32, int32_t, long, "%ld"); 839219089Spjd break; 840219089Spjd 841219089Spjd case DATA_TYPE_UINT32: 842219089Spjd NVP(elem, uint32, uint32_t, ulong_t, "%lu"); 843219089Spjd break; 844219089Spjd 845219089Spjd case DATA_TYPE_INT64: 846219089Spjd NVP(elem, int64, int64_t, longlong_t, "%lld"); 847219089Spjd break; 848219089Spjd 849219089Spjd case DATA_TYPE_UINT64: 850219089Spjd NVP(elem, uint64, uint64_t, u_longlong_t, "%llu"); 851219089Spjd break; 852219089Spjd 853219089Spjd case DATA_TYPE_STRING: 854219089Spjd NVP(elem, string, char *, char *, "'%s'"); 855219089Spjd break; 856219089Spjd 857282751Savg case DATA_TYPE_BOOLEAN_ARRAY: 858282751Savg (void) nvpair_value_boolean_array(elem, 859282751Savg &bool_array_value, &count); 860282751Savg for (i = 0; i < count; i++) { 861282751Savg (void) printf("%*s%s[%d]: %s\n", indent, "", 862282751Savg nvpair_name(elem), i, 863282751Savg bool_array_value[i] ? "true" : "false"); 864282751Savg } 865282751Savg break; 866282751Savg 867219089Spjd case DATA_TYPE_BYTE_ARRAY: 868219089Spjd NVPA(elem, byte_array, uchar_t, int, "%u"); 869219089Spjd break; 870219089Spjd 871219089Spjd case DATA_TYPE_INT8_ARRAY: 872219089Spjd NVPA(elem, int8_array, int8_t, int, "%d"); 873219089Spjd break; 874219089Spjd 875219089Spjd case DATA_TYPE_UINT8_ARRAY: 876219089Spjd NVPA(elem, uint8_array, uint8_t, int, "%u"); 877219089Spjd break; 878219089Spjd 879219089Spjd case DATA_TYPE_INT16_ARRAY: 880219089Spjd NVPA(elem, int16_array, int16_t, int, "%d"); 881219089Spjd break; 882219089Spjd 883219089Spjd case DATA_TYPE_UINT16_ARRAY: 884219089Spjd NVPA(elem, uint16_array, uint16_t, int, "%u"); 885219089Spjd break; 886219089Spjd 887219089Spjd case DATA_TYPE_INT32_ARRAY: 888219089Spjd NVPA(elem, int32_array, int32_t, long, "%ld"); 889219089Spjd break; 890219089Spjd 891219089Spjd case DATA_TYPE_UINT32_ARRAY: 892219089Spjd NVPA(elem, uint32_array, uint32_t, ulong_t, "%lu"); 893219089Spjd break; 894219089Spjd 895219089Spjd case DATA_TYPE_INT64_ARRAY: 896219089Spjd NVPA(elem, int64_array, int64_t, longlong_t, "%lld"); 897219089Spjd break; 898219089Spjd 899219089Spjd case DATA_TYPE_UINT64_ARRAY: 900219089Spjd NVPA(elem, uint64_array, uint64_t, u_longlong_t, 901219089Spjd "%llu"); 902219089Spjd break; 903219089Spjd 904219089Spjd case DATA_TYPE_STRING_ARRAY: 905219089Spjd NVPA(elem, string_array, char *, char *, "'%s'"); 906219089Spjd break; 907219089Spjd 908219089Spjd case DATA_TYPE_NVLIST: 909219089Spjd (void) nvpair_value_nvlist(elem, &nvlist_value); 910219089Spjd (void) printf("%*s%s:\n", indent, "", 911219089Spjd nvpair_name(elem)); 912219089Spjd dump_nvlist(nvlist_value, indent + 4); 913219089Spjd break; 914219089Spjd 915219089Spjd case DATA_TYPE_NVLIST_ARRAY: 916219089Spjd (void) nvpair_value_nvlist_array(elem, 917219089Spjd &nvlist_array_value, &count); 918219089Spjd for (i = 0; i < count; i++) { 919219089Spjd (void) printf("%*s%s[%u]:\n", indent, "", 920219089Spjd nvpair_name(elem), i); 921219089Spjd dump_nvlist(nvlist_array_value[i], indent + 4); 922219089Spjd } 923219089Spjd break; 924219089Spjd 925219089Spjd default: 926219089Spjd (void) printf(dgettext(TEXT_DOMAIN, "bad config type " 927219089Spjd "%d for %s\n"), nvpair_type(elem), 928219089Spjd nvpair_name(elem)); 929219089Spjd } 930219089Spjd } 931219089Spjd} 932219089Spjd 933219089Spjd/* 934219089Spjd * ====================================================================== 935219089Spjd * | | 936219089Spjd * | Misc private interface. | 937219089Spjd * | | 938219089Spjd * ====================================================================== 939219089Spjd */ 940219089Spjd 941219089Spjd/* 942185029Spjd * Determine if string 'value' matches 'nvp' value. The 'value' string is 943185029Spjd * converted, depending on the type of 'nvp', prior to match. For numeric 944185029Spjd * types, a radix independent sscanf conversion of 'value' is used. If 'nvp' 945185029Spjd * is an array type, 'ai' is the index into the array against which we are 946185029Spjd * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass 947185029Spjd * in a regex_t compilation of value in 'value_regex' to trigger regular 948185029Spjd * expression string match instead of simple strcmp(). 949185029Spjd * 950185029Spjd * Return 1 on match, 0 on no-match, and -1 on error. If the error is 951185029Spjd * related to value syntax error and 'ep' is non-NULL, *ep will point into 952185029Spjd * the 'value' string at the location where the error exists. 953185029Spjd * 954185029Spjd * NOTE: It may be possible to move the non-regex_t version of this into 955185029Spjd * common code used by library/kernel/boot. 956185029Spjd */ 957185029Spjdint 958185029Spjdnvpair_value_match_regex(nvpair_t *nvp, int ai, 959185029Spjd char *value, regex_t *value_regex, char **ep) 960185029Spjd{ 961185029Spjd char *evalue; 962185029Spjd uint_t a_len; 963185029Spjd int sr; 964185029Spjd 965185029Spjd if (ep) 966185029Spjd *ep = NULL; 967185029Spjd 968185029Spjd if ((nvp == NULL) || (value == NULL)) 969185029Spjd return (-1); /* error fail match - invalid args */ 970185029Spjd 971185029Spjd /* make sure array and index combination make sense */ 972185029Spjd if ((nvpair_type_is_array(nvp) && (ai < 0)) || 973185029Spjd (!nvpair_type_is_array(nvp) && (ai >= 0))) 974185029Spjd return (-1); /* error fail match - bad index */ 975185029Spjd 976185029Spjd /* non-string values should be single 'chunk' */ 977185029Spjd if ((nvpair_type(nvp) != DATA_TYPE_STRING) && 978185029Spjd (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) { 979185029Spjd value += strspn(value, " \t"); 980185029Spjd evalue = value + strcspn(value, " \t"); 981185029Spjd if (*evalue) { 982185029Spjd if (ep) 983185029Spjd *ep = evalue; 984185029Spjd return (-1); /* error fail match - syntax */ 985185029Spjd } 986185029Spjd } 987185029Spjd 988185029Spjd sr = EOF; 989185029Spjd switch (nvpair_type(nvp)) { 990185029Spjd case DATA_TYPE_STRING: { 991185029Spjd char *val; 992185029Spjd 993185029Spjd /* check string value for match */ 994185029Spjd if (nvpair_value_string(nvp, &val) == 0) { 995185029Spjd if (value_regex) { 996185029Spjd if (regexec(value_regex, val, 997185029Spjd (size_t)0, NULL, 0) == 0) 998185029Spjd return (1); /* match */ 999185029Spjd } else { 1000185029Spjd if (strcmp(value, val) == 0) 1001185029Spjd return (1); /* match */ 1002185029Spjd } 1003185029Spjd } 1004185029Spjd break; 1005185029Spjd } 1006185029Spjd case DATA_TYPE_STRING_ARRAY: { 1007185029Spjd char **val_array; 1008185029Spjd 1009185029Spjd /* check indexed string value of array for match */ 1010185029Spjd if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) && 1011185029Spjd (ai < a_len)) { 1012185029Spjd if (value_regex) { 1013185029Spjd if (regexec(value_regex, val_array[ai], 1014185029Spjd (size_t)0, NULL, 0) == 0) 1015185029Spjd return (1); 1016185029Spjd } else { 1017185029Spjd if (strcmp(value, val_array[ai]) == 0) 1018185029Spjd return (1); 1019185029Spjd } 1020185029Spjd } 1021185029Spjd break; 1022185029Spjd } 1023185029Spjd case DATA_TYPE_BYTE: { 1024185029Spjd uchar_t val, val_arg; 1025185029Spjd 1026185029Spjd /* scanf uchar_t from value and check for match */ 1027185029Spjd sr = sscanf(value, "%c", &val_arg); 1028185029Spjd if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) && 1029185029Spjd (val == val_arg)) 1030185029Spjd return (1); 1031185029Spjd break; 1032185029Spjd } 1033185029Spjd case DATA_TYPE_BYTE_ARRAY: { 1034185029Spjd uchar_t *val_array, val_arg; 1035185029Spjd 1036185029Spjd 1037185029Spjd /* check indexed value of array for match */ 1038185029Spjd sr = sscanf(value, "%c", &val_arg); 1039185029Spjd if ((sr == 1) && 1040185029Spjd (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) && 1041185029Spjd (ai < a_len) && 1042185029Spjd (val_array[ai] == val_arg)) 1043185029Spjd return (1); 1044185029Spjd break; 1045185029Spjd } 1046185029Spjd case DATA_TYPE_INT8: { 1047185029Spjd int8_t val, val_arg; 1048185029Spjd 1049185029Spjd /* scanf int8_t from value and check for match */ 1050185029Spjd sr = sscanf(value, "%"SCNi8, &val_arg); 1051185029Spjd if ((sr == 1) && 1052185029Spjd (nvpair_value_int8(nvp, &val) == 0) && 1053185029Spjd (val == val_arg)) 1054185029Spjd return (1); 1055185029Spjd break; 1056185029Spjd } 1057185029Spjd case DATA_TYPE_INT8_ARRAY: { 1058185029Spjd int8_t *val_array, val_arg; 1059185029Spjd 1060185029Spjd /* check indexed value of array for match */ 1061185029Spjd sr = sscanf(value, "%"SCNi8, &val_arg); 1062185029Spjd if ((sr == 1) && 1063185029Spjd (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) && 1064185029Spjd (ai < a_len) && 1065185029Spjd (val_array[ai] == val_arg)) 1066185029Spjd return (1); 1067185029Spjd break; 1068185029Spjd } 1069185029Spjd case DATA_TYPE_UINT8: { 1070185029Spjd uint8_t val, val_arg; 1071185029Spjd 1072185029Spjd /* scanf uint8_t from value and check for match */ 1073185029Spjd sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 1074185029Spjd if ((sr == 1) && 1075185029Spjd (nvpair_value_uint8(nvp, &val) == 0) && 1076185029Spjd (val == val_arg)) 1077185029Spjd return (1); 1078185029Spjd break; 1079185029Spjd } 1080185029Spjd case DATA_TYPE_UINT8_ARRAY: { 1081185029Spjd uint8_t *val_array, val_arg; 1082185029Spjd 1083185029Spjd /* check indexed value of array for match */ 1084185029Spjd sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); 1085185029Spjd if ((sr == 1) && 1086185029Spjd (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) && 1087185029Spjd (ai < a_len) && 1088185029Spjd (val_array[ai] == val_arg)) 1089185029Spjd return (1); 1090185029Spjd break; 1091185029Spjd } 1092185029Spjd case DATA_TYPE_INT16: { 1093185029Spjd int16_t val, val_arg; 1094185029Spjd 1095185029Spjd /* scanf int16_t from value and check for match */ 1096185029Spjd sr = sscanf(value, "%"SCNi16, &val_arg); 1097185029Spjd if ((sr == 1) && 1098185029Spjd (nvpair_value_int16(nvp, &val) == 0) && 1099185029Spjd (val == val_arg)) 1100185029Spjd return (1); 1101185029Spjd break; 1102185029Spjd } 1103185029Spjd case DATA_TYPE_INT16_ARRAY: { 1104185029Spjd int16_t *val_array, val_arg; 1105185029Spjd 1106185029Spjd /* check indexed value of array for match */ 1107185029Spjd sr = sscanf(value, "%"SCNi16, &val_arg); 1108185029Spjd if ((sr == 1) && 1109185029Spjd (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) && 1110185029Spjd (ai < a_len) && 1111185029Spjd (val_array[ai] == val_arg)) 1112185029Spjd return (1); 1113185029Spjd break; 1114185029Spjd } 1115185029Spjd case DATA_TYPE_UINT16: { 1116185029Spjd uint16_t val, val_arg; 1117185029Spjd 1118185029Spjd /* scanf uint16_t from value and check for match */ 1119185029Spjd sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 1120185029Spjd if ((sr == 1) && 1121185029Spjd (nvpair_value_uint16(nvp, &val) == 0) && 1122185029Spjd (val == val_arg)) 1123185029Spjd return (1); 1124185029Spjd break; 1125185029Spjd } 1126185029Spjd case DATA_TYPE_UINT16_ARRAY: { 1127185029Spjd uint16_t *val_array, val_arg; 1128185029Spjd 1129185029Spjd /* check indexed value of array for match */ 1130185029Spjd sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); 1131185029Spjd if ((sr == 1) && 1132185029Spjd (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) && 1133185029Spjd (ai < a_len) && 1134185029Spjd (val_array[ai] == val_arg)) 1135185029Spjd return (1); 1136185029Spjd break; 1137185029Spjd } 1138185029Spjd case DATA_TYPE_INT32: { 1139185029Spjd int32_t val, val_arg; 1140185029Spjd 1141185029Spjd /* scanf int32_t from value and check for match */ 1142185029Spjd sr = sscanf(value, "%"SCNi32, &val_arg); 1143185029Spjd if ((sr == 1) && 1144185029Spjd (nvpair_value_int32(nvp, &val) == 0) && 1145185029Spjd (val == val_arg)) 1146185029Spjd return (1); 1147185029Spjd break; 1148185029Spjd } 1149185029Spjd case DATA_TYPE_INT32_ARRAY: { 1150185029Spjd int32_t *val_array, val_arg; 1151185029Spjd 1152185029Spjd /* check indexed value of array for match */ 1153185029Spjd sr = sscanf(value, "%"SCNi32, &val_arg); 1154185029Spjd if ((sr == 1) && 1155185029Spjd (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) && 1156185029Spjd (ai < a_len) && 1157185029Spjd (val_array[ai] == val_arg)) 1158185029Spjd return (1); 1159185029Spjd break; 1160185029Spjd } 1161185029Spjd case DATA_TYPE_UINT32: { 1162185029Spjd uint32_t val, val_arg; 1163185029Spjd 1164185029Spjd /* scanf uint32_t from value and check for match */ 1165185029Spjd sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 1166185029Spjd if ((sr == 1) && 1167185029Spjd (nvpair_value_uint32(nvp, &val) == 0) && 1168185029Spjd (val == val_arg)) 1169185029Spjd return (1); 1170185029Spjd break; 1171185029Spjd } 1172185029Spjd case DATA_TYPE_UINT32_ARRAY: { 1173185029Spjd uint32_t *val_array, val_arg; 1174185029Spjd 1175185029Spjd /* check indexed value of array for match */ 1176185029Spjd sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); 1177185029Spjd if ((sr == 1) && 1178185029Spjd (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) && 1179185029Spjd (ai < a_len) && 1180185029Spjd (val_array[ai] == val_arg)) 1181185029Spjd return (1); 1182185029Spjd break; 1183185029Spjd } 1184185029Spjd case DATA_TYPE_INT64: { 1185185029Spjd int64_t val, val_arg; 1186185029Spjd 1187185029Spjd /* scanf int64_t from value and check for match */ 1188185029Spjd sr = sscanf(value, "%"SCNi64, &val_arg); 1189185029Spjd if ((sr == 1) && 1190185029Spjd (nvpair_value_int64(nvp, &val) == 0) && 1191185029Spjd (val == val_arg)) 1192185029Spjd return (1); 1193185029Spjd break; 1194185029Spjd } 1195185029Spjd case DATA_TYPE_INT64_ARRAY: { 1196185029Spjd int64_t *val_array, val_arg; 1197185029Spjd 1198185029Spjd /* check indexed value of array for match */ 1199185029Spjd sr = sscanf(value, "%"SCNi64, &val_arg); 1200185029Spjd if ((sr == 1) && 1201185029Spjd (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) && 1202185029Spjd (ai < a_len) && 1203185029Spjd (val_array[ai] == val_arg)) 1204185029Spjd return (1); 1205185029Spjd break; 1206185029Spjd } 1207185029Spjd case DATA_TYPE_UINT64: { 1208185029Spjd uint64_t val_arg, val; 1209185029Spjd 1210185029Spjd /* scanf uint64_t from value and check for match */ 1211185029Spjd sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 1212185029Spjd if ((sr == 1) && 1213185029Spjd (nvpair_value_uint64(nvp, &val) == 0) && 1214185029Spjd (val == val_arg)) 1215185029Spjd return (1); 1216185029Spjd break; 1217185029Spjd } 1218185029Spjd case DATA_TYPE_UINT64_ARRAY: { 1219185029Spjd uint64_t *val_array, val_arg; 1220185029Spjd 1221185029Spjd /* check indexed value of array for match */ 1222185029Spjd sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); 1223185029Spjd if ((sr == 1) && 1224185029Spjd (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) && 1225185029Spjd (ai < a_len) && 1226185029Spjd (val_array[ai] == val_arg)) 1227185029Spjd return (1); 1228185029Spjd break; 1229185029Spjd } 1230185029Spjd case DATA_TYPE_BOOLEAN_VALUE: { 1231307124Smav int32_t val_arg; 1232307124Smav boolean_t val; 1233185029Spjd 1234185029Spjd /* scanf boolean_t from value and check for match */ 1235185029Spjd sr = sscanf(value, "%"SCNi32, &val_arg); 1236185029Spjd if ((sr == 1) && 1237185029Spjd (nvpair_value_boolean_value(nvp, &val) == 0) && 1238185029Spjd (val == val_arg)) 1239185029Spjd return (1); 1240185029Spjd break; 1241185029Spjd } 1242185029Spjd case DATA_TYPE_BOOLEAN_ARRAY: { 1243307124Smav boolean_t *val_array; 1244307124Smav int32_t val_arg; 1245185029Spjd 1246185029Spjd /* check indexed value of array for match */ 1247185029Spjd sr = sscanf(value, "%"SCNi32, &val_arg); 1248185029Spjd if ((sr == 1) && 1249185029Spjd (nvpair_value_boolean_array(nvp, 1250185029Spjd &val_array, &a_len) == 0) && 1251185029Spjd (ai < a_len) && 1252185029Spjd (val_array[ai] == val_arg)) 1253185029Spjd return (1); 1254185029Spjd break; 1255185029Spjd } 1256185029Spjd case DATA_TYPE_HRTIME: 1257185029Spjd case DATA_TYPE_NVLIST: 1258185029Spjd case DATA_TYPE_NVLIST_ARRAY: 1259185029Spjd case DATA_TYPE_BOOLEAN: 1260185029Spjd case DATA_TYPE_DOUBLE: 1261185029Spjd case DATA_TYPE_UNKNOWN: 1262185029Spjd default: 1263185029Spjd /* 1264185029Spjd * unknown/unsupported data type 1265185029Spjd */ 1266185029Spjd return (-1); /* error fail match */ 1267185029Spjd } 1268185029Spjd 1269185029Spjd /* 1270185029Spjd * check to see if sscanf failed conversion, return approximate 1271185029Spjd * pointer to problem 1272185029Spjd */ 1273185029Spjd if (sr != 1) { 1274185029Spjd if (ep) 1275185029Spjd *ep = value; 1276185029Spjd return (-1); /* error fail match - syntax */ 1277185029Spjd } 1278185029Spjd 1279185029Spjd return (0); /* fail match */ 1280185029Spjd} 1281185029Spjd 1282185029Spjdint 1283185029Spjdnvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep) 1284185029Spjd{ 1285185029Spjd return (nvpair_value_match_regex(nvp, ai, value, NULL, ep)); 1286185029Spjd} 1287