mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-26 04:07:45 +03:00
Rebase to OpenSolaris b103, in the process we are removing any code which did not originate from the OpenSolaris source. These changes will be reintroduced in topic branches for easier tracking
This commit is contained in:
@@ -2,9 +2,8 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -20,24 +19,27 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _LIBNVPAIR_H
|
||||
#define _LIBNVPAIR_H
|
||||
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/nvpair.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <regex.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void nvlist_print(FILE *, nvlist_t *);
|
||||
int nvpair_value_match(nvpair_t *, int, char *, char **);
|
||||
int nvpair_value_match_regex(nvpair_t *, int, char *, regex_t *, char **);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_NVPAIR_H
|
||||
#define _SYS_NVPAIR_H
|
||||
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
@@ -67,7 +67,12 @@ typedef enum {
|
||||
DATA_TYPE_UINT8,
|
||||
DATA_TYPE_BOOLEAN_ARRAY,
|
||||
DATA_TYPE_INT8_ARRAY,
|
||||
#if !defined(_KERNEL)
|
||||
DATA_TYPE_UINT8_ARRAY,
|
||||
DATA_TYPE_DOUBLE
|
||||
#else
|
||||
DATA_TYPE_UINT8_ARRAY
|
||||
#endif
|
||||
} data_type_t;
|
||||
|
||||
typedef struct nvpair {
|
||||
@@ -188,6 +193,9 @@ int nvlist_add_uint64_array(nvlist_t *, const char *, uint64_t *, uint_t);
|
||||
int nvlist_add_string_array(nvlist_t *, const char *, char *const *, uint_t);
|
||||
int nvlist_add_nvlist_array(nvlist_t *, const char *, nvlist_t **, uint_t);
|
||||
int nvlist_add_hrtime(nvlist_t *, const char *, hrtime_t);
|
||||
#if !defined(_KERNEL)
|
||||
int nvlist_add_double(nvlist_t *, const char *, double);
|
||||
#endif
|
||||
|
||||
int nvlist_remove(nvlist_t *, const char *, data_type_t);
|
||||
int nvlist_remove_all(nvlist_t *, const char *);
|
||||
@@ -220,15 +228,21 @@ int nvlist_lookup_string_array(nvlist_t *, const char *, char ***, uint_t *);
|
||||
int nvlist_lookup_nvlist_array(nvlist_t *, const char *,
|
||||
nvlist_t ***, uint_t *);
|
||||
int nvlist_lookup_hrtime(nvlist_t *, const char *, hrtime_t *);
|
||||
int nvlist_lookup_pairs(nvlist_t *nvl, int, ...);
|
||||
int nvlist_lookup_pairs(nvlist_t *, int, ...);
|
||||
#if !defined(_KERNEL)
|
||||
int nvlist_lookup_double(nvlist_t *, const char *, double *);
|
||||
#endif
|
||||
|
||||
int nvlist_lookup_nvpair(nvlist_t *nvl, const char *, nvpair_t **);
|
||||
boolean_t nvlist_exists(nvlist_t *nvl, const char *);
|
||||
int nvlist_lookup_nvpair(nvlist_t *, const char *, nvpair_t **);
|
||||
int nvlist_lookup_nvpair_embedded_index(nvlist_t *, const char *, nvpair_t **,
|
||||
int *, char **);
|
||||
boolean_t nvlist_exists(nvlist_t *, const char *);
|
||||
|
||||
/* processing nvpair */
|
||||
nvpair_t *nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *);
|
||||
nvpair_t *nvlist_next_nvpair(nvlist_t *, nvpair_t *);
|
||||
char *nvpair_name(nvpair_t *);
|
||||
data_type_t nvpair_type(nvpair_t *);
|
||||
int nvpair_type_is_array(nvpair_t *);
|
||||
int nvpair_value_boolean_value(nvpair_t *, boolean_t *);
|
||||
int nvpair_value_byte(nvpair_t *, uchar_t *);
|
||||
int nvpair_value_int8(nvpair_t *, int8_t *);
|
||||
@@ -254,6 +268,9 @@ int nvpair_value_uint64_array(nvpair_t *, uint64_t **, uint_t *);
|
||||
int nvpair_value_string_array(nvpair_t *, char ***, uint_t *);
|
||||
int nvpair_value_nvlist_array(nvpair_t *, nvlist_t ***, uint_t *);
|
||||
int nvpair_value_hrtime(nvpair_t *, hrtime_t *);
|
||||
#if !defined(_KERNEL)
|
||||
int nvpair_value_double(nvpair_t *, double *);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#ifndef _NVPAIR_IMPL_H
|
||||
#define _NVPAIR_IMPL_H
|
||||
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (the "License"). You may not use this file except in compliance
|
||||
* with the License.
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
@@ -20,14 +19,16 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/inttypes.h>
|
||||
#include "libnvpair.h"
|
||||
|
||||
/*
|
||||
@@ -137,6 +138,12 @@ nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth)
|
||||
(void) fprintf(fp, " 0x%llx", (u_longlong_t)val);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_DOUBLE: {
|
||||
double val;
|
||||
(void) nvpair_value_double(nvp, &val);
|
||||
(void) fprintf(fp, " 0x%llf", val);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_STRING: {
|
||||
char *val;
|
||||
(void) nvpair_value_string(nvp, &val);
|
||||
@@ -264,3 +271,348 @@ nvlist_print(FILE *fp, nvlist_t *nvl)
|
||||
{
|
||||
nvlist_print_with_indent(fp, nvl, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if string 'value' matches 'nvp' value. The 'value' string is
|
||||
* converted, depending on the type of 'nvp', prior to match. For numeric
|
||||
* types, a radix independent sscanf conversion of 'value' is used. If 'nvp'
|
||||
* is an array type, 'ai' is the index into the array against which we are
|
||||
* checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass
|
||||
* in a regex_t compilation of value in 'value_regex' to trigger regular
|
||||
* expression string match instead of simple strcmp().
|
||||
*
|
||||
* Return 1 on match, 0 on no-match, and -1 on error. If the error is
|
||||
* related to value syntax error and 'ep' is non-NULL, *ep will point into
|
||||
* the 'value' string at the location where the error exists.
|
||||
*
|
||||
* NOTE: It may be possible to move the non-regex_t version of this into
|
||||
* common code used by library/kernel/boot.
|
||||
*/
|
||||
int
|
||||
nvpair_value_match_regex(nvpair_t *nvp, int ai,
|
||||
char *value, regex_t *value_regex, char **ep)
|
||||
{
|
||||
char *evalue;
|
||||
uint_t a_len;
|
||||
int sr;
|
||||
|
||||
if (ep)
|
||||
*ep = NULL;
|
||||
|
||||
if ((nvp == NULL) || (value == NULL))
|
||||
return (-1); /* error fail match - invalid args */
|
||||
|
||||
/* make sure array and index combination make sense */
|
||||
if ((nvpair_type_is_array(nvp) && (ai < 0)) ||
|
||||
(!nvpair_type_is_array(nvp) && (ai >= 0)))
|
||||
return (-1); /* error fail match - bad index */
|
||||
|
||||
/* non-string values should be single 'chunk' */
|
||||
if ((nvpair_type(nvp) != DATA_TYPE_STRING) &&
|
||||
(nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) {
|
||||
value += strspn(value, " \t");
|
||||
evalue = value + strcspn(value, " \t");
|
||||
if (*evalue) {
|
||||
if (ep)
|
||||
*ep = evalue;
|
||||
return (-1); /* error fail match - syntax */
|
||||
}
|
||||
}
|
||||
|
||||
sr = EOF;
|
||||
switch (nvpair_type(nvp)) {
|
||||
case DATA_TYPE_STRING: {
|
||||
char *val;
|
||||
|
||||
/* check string value for match */
|
||||
if (nvpair_value_string(nvp, &val) == 0) {
|
||||
if (value_regex) {
|
||||
if (regexec(value_regex, val,
|
||||
(size_t)0, NULL, 0) == 0)
|
||||
return (1); /* match */
|
||||
} else {
|
||||
if (strcmp(value, val) == 0)
|
||||
return (1); /* match */
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_STRING_ARRAY: {
|
||||
char **val_array;
|
||||
|
||||
/* check indexed string value of array for match */
|
||||
if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len)) {
|
||||
if (value_regex) {
|
||||
if (regexec(value_regex, val_array[ai],
|
||||
(size_t)0, NULL, 0) == 0)
|
||||
return (1);
|
||||
} else {
|
||||
if (strcmp(value, val_array[ai]) == 0)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_BYTE: {
|
||||
uchar_t val, val_arg;
|
||||
|
||||
/* scanf uchar_t from value and check for match */
|
||||
sr = sscanf(value, "%c", &val_arg);
|
||||
if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_BYTE_ARRAY: {
|
||||
uchar_t *val_array, val_arg;
|
||||
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%c", &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT8: {
|
||||
int8_t val, val_arg;
|
||||
|
||||
/* scanf int8_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi8, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int8(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT8_ARRAY: {
|
||||
int8_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi8, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT8: {
|
||||
uint8_t val, val_arg;
|
||||
|
||||
/* scanf uint8_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint8(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT8_ARRAY: {
|
||||
uint8_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT16: {
|
||||
int16_t val, val_arg;
|
||||
|
||||
/* scanf int16_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi16, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int16(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT16_ARRAY: {
|
||||
int16_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi16, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT16: {
|
||||
uint16_t val, val_arg;
|
||||
|
||||
/* scanf uint16_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint16(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT16_ARRAY: {
|
||||
uint16_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT32: {
|
||||
int32_t val, val_arg;
|
||||
|
||||
/* scanf int32_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi32, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int32(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT32_ARRAY: {
|
||||
int32_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi32, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT32: {
|
||||
uint32_t val, val_arg;
|
||||
|
||||
/* scanf uint32_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint32(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT32_ARRAY: {
|
||||
uint32_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT64: {
|
||||
int64_t val, val_arg;
|
||||
|
||||
/* scanf int64_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi64, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int64(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_INT64_ARRAY: {
|
||||
int64_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi64, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT64: {
|
||||
uint64_t val_arg, val;
|
||||
|
||||
/* scanf uint64_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint64(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_UINT64_ARRAY: {
|
||||
uint64_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_BOOLEAN_VALUE: {
|
||||
boolean_t val, val_arg;
|
||||
|
||||
/* scanf boolean_t from value and check for match */
|
||||
sr = sscanf(value, "%"SCNi32, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_boolean_value(nvp, &val) == 0) &&
|
||||
(val == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_BOOLEAN_ARRAY: {
|
||||
boolean_t *val_array, val_arg;
|
||||
|
||||
/* check indexed value of array for match */
|
||||
sr = sscanf(value, "%"SCNi32, &val_arg);
|
||||
if ((sr == 1) &&
|
||||
(nvpair_value_boolean_array(nvp,
|
||||
&val_array, &a_len) == 0) &&
|
||||
(ai < a_len) &&
|
||||
(val_array[ai] == val_arg))
|
||||
return (1);
|
||||
break;
|
||||
}
|
||||
case DATA_TYPE_HRTIME:
|
||||
case DATA_TYPE_NVLIST:
|
||||
case DATA_TYPE_NVLIST_ARRAY:
|
||||
case DATA_TYPE_BOOLEAN:
|
||||
case DATA_TYPE_DOUBLE:
|
||||
case DATA_TYPE_UNKNOWN:
|
||||
default:
|
||||
/*
|
||||
* unknown/unsupported data type
|
||||
*/
|
||||
return (-1); /* error fail match */
|
||||
}
|
||||
|
||||
/*
|
||||
* check to see if sscanf failed conversion, return approximate
|
||||
* pointer to problem
|
||||
*/
|
||||
if (sr != 1) {
|
||||
if (ep)
|
||||
*ep = value;
|
||||
return (-1); /* error fail match - syntax */
|
||||
}
|
||||
|
||||
return (0); /* fail match */
|
||||
}
|
||||
|
||||
int
|
||||
nvpair_value_match(nvpair_t *nvp, int ai, char *value, char **ep)
|
||||
{
|
||||
return (nvpair_value_match_regex(nvp, ai, value, NULL, ep));
|
||||
}
|
||||
|
||||
+267
-26
@@ -20,11 +20,11 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/stropts.h>
|
||||
#include <sys/debug.h>
|
||||
@@ -37,15 +37,19 @@
|
||||
|
||||
#if defined(_KERNEL) && !defined(_BOOT)
|
||||
#include <sys/varargs.h>
|
||||
#include <sys/ddi.h>
|
||||
#include <sys/sunddi.h>
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(s, m) ((size_t)(&(((s *)0)->m)))
|
||||
#define offsetof(s, m) ((size_t)(&(((s *)0)->m)))
|
||||
#endif
|
||||
|
||||
#define skip_whitespace(p) while ((*(p) == ' ') || (*(p) == '\t')) p++
|
||||
|
||||
/*
|
||||
* nvpair.c - Provides kernel & userland interfaces for manipulating
|
||||
@@ -204,7 +208,7 @@ nv_mem_free(nvpriv_t *nvp, void *buf, size_t size)
|
||||
static void
|
||||
nv_priv_init(nvpriv_t *priv, nv_alloc_t *nva, uint32_t stat)
|
||||
{
|
||||
bzero(priv, sizeof (priv));
|
||||
bzero(priv, sizeof (nvpriv_t));
|
||||
|
||||
priv->nvp_nva = nva;
|
||||
priv->nvp_stat = stat;
|
||||
@@ -398,6 +402,9 @@ i_validate_type_nelem(data_type_t type, uint_t nelem)
|
||||
case DATA_TYPE_STRING:
|
||||
case DATA_TYPE_HRTIME:
|
||||
case DATA_TYPE_NVLIST:
|
||||
#if !defined(_KERNEL)
|
||||
case DATA_TYPE_DOUBLE:
|
||||
#endif
|
||||
if (nelem != 1)
|
||||
return (EINVAL);
|
||||
break;
|
||||
@@ -736,6 +743,11 @@ i_get_value_size(data_type_t type, const void *data, uint_t nelem)
|
||||
case DATA_TYPE_UINT64:
|
||||
value_sz = sizeof (uint64_t);
|
||||
break;
|
||||
#if !defined(_KERNEL)
|
||||
case DATA_TYPE_DOUBLE:
|
||||
value_sz = sizeof (double);
|
||||
break;
|
||||
#endif
|
||||
case DATA_TYPE_STRING:
|
||||
if (data == NULL)
|
||||
value_sz = 0;
|
||||
@@ -1020,6 +1032,14 @@ nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val)
|
||||
return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val));
|
||||
}
|
||||
|
||||
#if !defined(_KERNEL)
|
||||
int
|
||||
nvlist_add_double(nvlist_t *nvl, const char *name, double val)
|
||||
{
|
||||
return (nvlist_add_common(nvl, name, DATA_TYPE_DOUBLE, 1, &val));
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
nvlist_add_string(nvlist_t *nvl, const char *name, const char *val)
|
||||
{
|
||||
@@ -1154,6 +1174,27 @@ nvpair_type(nvpair_t *nvp)
|
||||
return (NVP_TYPE(nvp));
|
||||
}
|
||||
|
||||
int
|
||||
nvpair_type_is_array(nvpair_t *nvp)
|
||||
{
|
||||
data_type_t type = NVP_TYPE(nvp);
|
||||
|
||||
if ((type == DATA_TYPE_BYTE_ARRAY) ||
|
||||
(type == DATA_TYPE_UINT8_ARRAY) ||
|
||||
(type == DATA_TYPE_INT16_ARRAY) ||
|
||||
(type == DATA_TYPE_UINT16_ARRAY) ||
|
||||
(type == DATA_TYPE_INT32_ARRAY) ||
|
||||
(type == DATA_TYPE_UINT32_ARRAY) ||
|
||||
(type == DATA_TYPE_INT64_ARRAY) ||
|
||||
(type == DATA_TYPE_UINT64_ARRAY) ||
|
||||
(type == DATA_TYPE_BOOLEAN_ARRAY) ||
|
||||
(type == DATA_TYPE_STRING_ARRAY) ||
|
||||
(type == DATA_TYPE_NVLIST_ARRAY))
|
||||
return (1);
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
|
||||
{
|
||||
@@ -1181,6 +1222,9 @@ nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
|
||||
case DATA_TYPE_INT64:
|
||||
case DATA_TYPE_UINT64:
|
||||
case DATA_TYPE_HRTIME:
|
||||
#if !defined(_KERNEL)
|
||||
case DATA_TYPE_DOUBLE:
|
||||
#endif
|
||||
if (data == NULL)
|
||||
return (EINVAL);
|
||||
bcopy(NVP_VALUE(nvp), data,
|
||||
@@ -1317,6 +1361,14 @@ nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val)
|
||||
return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val));
|
||||
}
|
||||
|
||||
#if !defined(_KERNEL)
|
||||
int
|
||||
nvlist_lookup_double(nvlist_t *nvl, const char *name, double *val)
|
||||
{
|
||||
return (nvlist_lookup_common(nvl, name, DATA_TYPE_DOUBLE, NULL, val));
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
|
||||
{
|
||||
@@ -1451,6 +1503,9 @@ nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
|
||||
case DATA_TYPE_HRTIME:
|
||||
case DATA_TYPE_STRING:
|
||||
case DATA_TYPE_NVLIST:
|
||||
#if !defined(_KERNEL)
|
||||
case DATA_TYPE_DOUBLE:
|
||||
#endif
|
||||
val = va_arg(ap, void *);
|
||||
ret = nvlist_lookup_common(nvl, name, type, NULL, val);
|
||||
break;
|
||||
@@ -1484,30 +1539,201 @@ nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the 'name'ed nvpair in the nvlist 'nvl'. If 'name' found, the function
|
||||
* returns zero and a pointer to the matching nvpair is returned in '*ret'
|
||||
* (given 'ret' is non-NULL). If 'sep' is specified then 'name' will penitrate
|
||||
* multiple levels of embedded nvlists, with 'sep' as the separator. As an
|
||||
* example, if sep is '.', name might look like: "a" or "a.b" or "a.c[3]" or
|
||||
* "a.d[3].e[1]". This matches the C syntax for array embed (for convience,
|
||||
* code also supports "a.d[3]e[1]" syntax).
|
||||
*
|
||||
* If 'ip' is non-NULL and the last name component is an array, return the
|
||||
* value of the "...[index]" array index in *ip. For an array reference that
|
||||
* is not indexed, *ip will be returned as -1. If there is a syntax error in
|
||||
* 'name', and 'ep' is non-NULL then *ep will be set to point to the location
|
||||
* inside the 'name' string where the syntax error was detected.
|
||||
*/
|
||||
static int
|
||||
nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
|
||||
nvpair_t **ret, int *ip, char **ep)
|
||||
{
|
||||
nvpair_t *nvp;
|
||||
const char *np;
|
||||
char *sepp;
|
||||
char *idxp, *idxep;
|
||||
nvlist_t **nva;
|
||||
long idx;
|
||||
int n;
|
||||
|
||||
if (ip)
|
||||
*ip = -1; /* not indexed */
|
||||
if (ep)
|
||||
*ep = NULL;
|
||||
|
||||
if ((nvl == NULL) || (name == NULL))
|
||||
return (EINVAL);
|
||||
|
||||
/* step through components of name */
|
||||
for (np = name; np && *np; np = sepp) {
|
||||
/* ensure unique names */
|
||||
if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME))
|
||||
return (ENOTSUP);
|
||||
|
||||
/* skip white space */
|
||||
skip_whitespace(np);
|
||||
if (*np == 0)
|
||||
break;
|
||||
|
||||
/* set 'sepp' to end of current component 'np' */
|
||||
if (sep)
|
||||
sepp = strchr(np, sep);
|
||||
else
|
||||
sepp = NULL;
|
||||
|
||||
/* find start of next "[ index ]..." */
|
||||
idxp = strchr(np, '[');
|
||||
|
||||
/* if sepp comes first, set idxp to NULL */
|
||||
if (sepp && idxp && (sepp < idxp))
|
||||
idxp = NULL;
|
||||
|
||||
/*
|
||||
* At this point 'idxp' is set if there is an index
|
||||
* expected for the current component.
|
||||
*/
|
||||
if (idxp) {
|
||||
/* set 'n' to length of current 'np' name component */
|
||||
n = idxp++ - np;
|
||||
|
||||
/* keep sepp up to date for *ep use as we advance */
|
||||
skip_whitespace(idxp);
|
||||
sepp = idxp;
|
||||
|
||||
/* determine the index value */
|
||||
#if defined(_KERNEL) && !defined(_BOOT)
|
||||
if (ddi_strtol(idxp, &idxep, 0, &idx))
|
||||
goto fail;
|
||||
#else
|
||||
idx = strtol(idxp, &idxep, 0);
|
||||
#endif
|
||||
if (idxep == idxp)
|
||||
goto fail;
|
||||
|
||||
/* keep sepp up to date for *ep use as we advance */
|
||||
sepp = idxep;
|
||||
|
||||
/* skip white space index value and check for ']' */
|
||||
skip_whitespace(sepp);
|
||||
if (*sepp++ != ']')
|
||||
goto fail;
|
||||
|
||||
/* for embedded arrays, support C syntax: "a[1].b" */
|
||||
skip_whitespace(sepp);
|
||||
if (sep && (*sepp == sep))
|
||||
sepp++;
|
||||
} else if (sepp) {
|
||||
n = sepp++ - np;
|
||||
} else {
|
||||
n = strlen(np);
|
||||
}
|
||||
|
||||
/* trim trailing whitespace by reducing length of 'np' */
|
||||
if (n == 0)
|
||||
goto fail;
|
||||
for (n--; (np[n] == ' ') || (np[n] == '\t'); n--)
|
||||
;
|
||||
n++;
|
||||
|
||||
/* skip whitespace, and set sepp to NULL if complete */
|
||||
if (sepp) {
|
||||
skip_whitespace(sepp);
|
||||
if (*sepp == 0)
|
||||
sepp = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point:
|
||||
* o 'n' is the length of current 'np' component.
|
||||
* o 'idxp' is set if there was an index, and value 'idx'.
|
||||
* o 'sepp' is set to the beginning of the next component,
|
||||
* and set to NULL if we have no more components.
|
||||
*
|
||||
* Search for nvpair with matching component name.
|
||||
*/
|
||||
for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
|
||||
nvp = nvlist_next_nvpair(nvl, nvp)) {
|
||||
|
||||
/* continue if no match on name */
|
||||
if (strncmp(np, nvpair_name(nvp), n) ||
|
||||
(strlen(nvpair_name(nvp)) != n))
|
||||
continue;
|
||||
|
||||
/* if indexed, verify type is array oriented */
|
||||
if (idxp && !nvpair_type_is_array(nvp))
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Full match found, return nvp and idx if this
|
||||
* was the last component.
|
||||
*/
|
||||
if (sepp == NULL) {
|
||||
if (ret)
|
||||
*ret = nvp;
|
||||
if (ip && idxp)
|
||||
*ip = (int)idx; /* return index */
|
||||
return (0); /* found */
|
||||
}
|
||||
|
||||
/*
|
||||
* More components: current match must be
|
||||
* of DATA_TYPE_NVLIST or DATA_TYPE_NVLIST_ARRAY
|
||||
* to support going deeper.
|
||||
*/
|
||||
if (nvpair_type(nvp) == DATA_TYPE_NVLIST) {
|
||||
nvl = EMBEDDED_NVL(nvp);
|
||||
break;
|
||||
} else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) {
|
||||
(void) nvpair_value_nvlist_array(nvp,
|
||||
&nva, (uint_t *)&n);
|
||||
if ((n < 0) || (idx >= n))
|
||||
goto fail;
|
||||
nvl = nva[idx];
|
||||
break;
|
||||
}
|
||||
|
||||
/* type does not support more levels */
|
||||
goto fail;
|
||||
}
|
||||
if (nvp == NULL)
|
||||
goto fail; /* 'name' not found */
|
||||
|
||||
/* search for match of next component in embedded 'nvl' list */
|
||||
}
|
||||
|
||||
fail: if (ep && sepp)
|
||||
*ep = sepp;
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return pointer to nvpair with specified 'name'.
|
||||
*/
|
||||
int
|
||||
nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret)
|
||||
{
|
||||
nvpriv_t *priv;
|
||||
nvpair_t *nvp;
|
||||
i_nvp_t *curr;
|
||||
return (nvlist_lookup_nvpair_ei_sep(nvl, name, 0, ret, NULL, NULL));
|
||||
}
|
||||
|
||||
if (name == NULL || nvl == NULL ||
|
||||
(priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME))
|
||||
return (ENOTSUP);
|
||||
|
||||
for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
|
||||
nvp = &curr->nvi_nvp;
|
||||
|
||||
if (strcmp(name, NVP_NAME(nvp)) == 0) {
|
||||
*ret = nvp;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
return (ENOENT);
|
||||
/*
|
||||
* Determine if named nvpair exists in nvlist (use embedded separator of '.'
|
||||
* and return array index). See nvlist_lookup_nvpair_ei_sep for more detailed
|
||||
* description.
|
||||
*/
|
||||
int nvlist_lookup_nvpair_embedded_index(nvlist_t *nvl,
|
||||
const char *name, nvpair_t **ret, int *ip, char **ep)
|
||||
{
|
||||
return (nvlist_lookup_nvpair_ei_sep(nvl, name, '.', ret, ip, ep));
|
||||
}
|
||||
|
||||
boolean_t
|
||||
@@ -1591,6 +1817,14 @@ nvpair_value_uint64(nvpair_t *nvp, uint64_t *val)
|
||||
return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val));
|
||||
}
|
||||
|
||||
#if !defined(_KERNEL)
|
||||
int
|
||||
nvpair_value_double(nvpair_t *nvp, double *val)
|
||||
{
|
||||
return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val));
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
nvpair_value_string(nvpair_t *nvp, char **val)
|
||||
{
|
||||
@@ -2728,7 +2962,11 @@ nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
|
||||
*/
|
||||
ret = xdr_longlong_t(xdr, (void *)buf);
|
||||
break;
|
||||
|
||||
#if !defined(_KERNEL)
|
||||
case DATA_TYPE_DOUBLE:
|
||||
ret = xdr_double(xdr, (void *)buf);
|
||||
break;
|
||||
#endif
|
||||
case DATA_TYPE_STRING:
|
||||
ret = xdr_string(xdr, &buf, buflen - 1);
|
||||
break;
|
||||
@@ -2834,6 +3072,9 @@ nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
|
||||
case DATA_TYPE_INT64:
|
||||
case DATA_TYPE_UINT64:
|
||||
case DATA_TYPE_HRTIME:
|
||||
#if !defined(_KERNEL)
|
||||
case DATA_TYPE_DOUBLE:
|
||||
#endif
|
||||
nvp_sz += 8;
|
||||
break;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/stropts.h>
|
||||
#include <sys/isa_defs.h>
|
||||
|
||||
@@ -24,26 +24,25 @@
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <sys/nvpair.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void *
|
||||
nv_alloc_sys(nv_alloc_t *nva, size_t size)
|
||||
{
|
||||
return (malloc(size));
|
||||
return (kmem_alloc(size, (int)(uintptr_t)nva->nva_arg));
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
nv_free_sys(nv_alloc_t *nva, void *buf, size_t size)
|
||||
{
|
||||
free(buf);
|
||||
kmem_free(buf, size);
|
||||
}
|
||||
|
||||
const nv_alloc_ops_t system_ops_def = {
|
||||
static const nv_alloc_ops_t system_ops = {
|
||||
NULL, /* nv_ao_init() */
|
||||
NULL, /* nv_ao_fini() */
|
||||
nv_alloc_sys, /* nv_ao_alloc() */
|
||||
@@ -51,9 +50,15 @@ const nv_alloc_ops_t system_ops_def = {
|
||||
NULL /* nv_ao_reset() */
|
||||
};
|
||||
|
||||
nv_alloc_t nv_alloc_nosleep_def = {
|
||||
&system_ops_def,
|
||||
NULL
|
||||
nv_alloc_t nv_alloc_sleep_def = {
|
||||
&system_ops,
|
||||
(void *)KM_SLEEP
|
||||
};
|
||||
|
||||
nv_alloc_t nv_alloc_nosleep_def = {
|
||||
&system_ops,
|
||||
(void *)KM_NOSLEEP
|
||||
};
|
||||
|
||||
nv_alloc_t *nv_alloc_sleep = &nv_alloc_sleep_def;
|
||||
nv_alloc_t *nv_alloc_nosleep = &nv_alloc_nosleep_def;
|
||||
|
||||
Reference in New Issue
Block a user