Home | History | Annotate | Line # | Download | only in libnvpair
libnvpair.c revision 1.1.1.1
      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 }
    619