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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/debug.h>
30 #include <sys/nvpair.h>
31 #include <sys/nvpair_impl.h>
32 #include <rpc/types.h>
35 #if defined(_KERNEL) && !defined(_BOOT)
36 #include <sys/varargs.h>
37 #include <sys/sunddi.h>
45 #define offsetof(s, m) ((size_t)(&(((s *)0)->m)))
47 #define skip_whitespace(p) while ((*(p) == ' ') || (*(p) == '\t')) p++
50 * nvpair.c - Provides kernel & userland interfaces for manipulating
65 * +--------------+ last i_nvp in list
66 * | nvpriv_t | +--------------------->
68 * +--+- nvp_list | | +------------+
69 * | | nvp_last -+--+ + nv_alloc_t |
70 * | | nvp_curr | |------------|
71 * | | nvp_nva -+----> | nva_ops |
72 * | | nvp_stat | | nva_arg |
73 * | +--------------+ +------------+
77 * +---------------------+ +-------------------+
78 * | i_nvp_t | +-->| i_nvp_t | +-->
79 * |---------------------| | |-------------------| |
80 * | nvi_next -+--+ | nvi_next -+--+
81 * | nvi_prev (NULL) | <----+ nvi_prev |
82 * | . . . . . . . . . . | | . . . . . . . . . |
83 * | nvp (nvpair_t) | | nvp (nvpair_t) |
84 * | - nvp_size | | - nvp_size |
85 * | - nvp_name_sz | | - nvp_name_sz |
86 * | - nvp_value_elem | | - nvp_value_elem |
87 * | - nvp_type | | - nvp_type |
88 * | - data ... | | - data ... |
89 * +---------------------+ +-------------------+
93 * +---------------------+ +---------------------+
94 * | i_nvp_t | +--> +-->| i_nvp_t (last) |
95 * |---------------------| | | |---------------------|
96 * | nvi_next -+--+ ... --+ | nvi_next (NULL) |
97 * <-+- nvi_prev |<-- ... <----+ nvi_prev |
98 * | . . . . . . . . . | | . . . . . . . . . |
99 * | nvp (nvpair_t) | | nvp (nvpair_t) |
100 * | - nvp_size | | - nvp_size |
101 * | - nvp_name_sz | | - nvp_name_sz |
102 * | - nvp_value_elem | | - nvp_value_elem |
103 * | - DATA_TYPE_NVLIST | | - nvp_type |
104 * | - data (embedded) | | - data ... |
105 * | nvlist name | +---------------------+
106 * | +--------------+ |
108 * | |--------------| |
109 * | | nvl_version | |
111 * | | nvl_priv --+---+---->
114 * | +--------------+ |
115 * +---------------------+
118 * N.B. nvpair_t may be aligned on 4 byte boundary, so +4 will
119 * allow value to be aligned on 8 byte boundary
121 * name_len is the length of the name string including the null terminator
124 #define NVP_SIZE_CALC(name_len, data_len) \
125 (NV_ALIGN((sizeof (nvpair_t)) + name_len) + NV_ALIGN(data_len))
127 static int i_get_value_size(data_type_t type, const void *data, uint_t nelem);
128 static int nvlist_add_common(nvlist_t *nvl, const char *name, data_type_t type,
129 uint_t nelem, const void *data);
131 #define NV_STAT_EMBEDDED 0x1
132 #define EMBEDDED_NVL(nvp) ((nvlist_t *)(void *)NVP_VALUE(nvp))
133 #define EMBEDDED_NVL_ARRAY(nvp) ((nvlist_t **)(void *)NVP_VALUE(nvp))
135 #define NVP_VALOFF(nvp) (NV_ALIGN(sizeof (nvpair_t) + (nvp)->nvp_name_sz))
136 #define NVPAIR2I_NVP(nvp) \
137 ((i_nvp_t *)((size_t)(nvp) - offsetof(i_nvp_t, nvi_nvp)))
141 nv_alloc_init(nv_alloc_t *nva, const nv_alloc_ops_t *nvo, /* args */ ...)
149 va_start(valist, nvo);
150 if (nva->nva_ops->nv_ao_init != NULL)
151 err = nva->nva_ops->nv_ao_init(nva, valist);
158 nv_alloc_reset(nv_alloc_t *nva)
160 if (nva->nva_ops->nv_ao_reset != NULL)
161 nva->nva_ops->nv_ao_reset(nva);
165 nv_alloc_fini(nv_alloc_t *nva)
167 if (nva->nva_ops->nv_ao_fini != NULL)
168 nva->nva_ops->nv_ao_fini(nva);
172 nvlist_lookup_nv_alloc(nvlist_t *nvl)
177 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
180 return (priv->nvp_nva);
184 nv_mem_zalloc(nvpriv_t *nvp, size_t size)
186 nv_alloc_t *nva = nvp->nvp_nva;
189 if ((buf = nva->nva_ops->nv_ao_alloc(nva, size)) != NULL)
196 nv_mem_free(nvpriv_t *nvp, void *buf, size_t size)
198 nv_alloc_t *nva = nvp->nvp_nva;
200 nva->nva_ops->nv_ao_free(nva, buf, size);
204 nv_priv_init(nvpriv_t *priv, nv_alloc_t *nva, uint32_t stat)
206 bzero(priv, sizeof (nvpriv_t));
209 priv->nvp_stat = stat;
213 nv_priv_alloc(nv_alloc_t *nva)
218 * nv_mem_alloc() cannot called here because it needs the priv
221 if ((priv = nva->nva_ops->nv_ao_alloc(nva, sizeof (nvpriv_t))) == NULL)
224 nv_priv_init(priv, nva, 0);
230 * Embedded lists need their own nvpriv_t's. We create a new
231 * nvpriv_t using the parameters and allocator from the parent
235 nv_priv_alloc_embedded(nvpriv_t *priv)
239 if ((emb_priv = nv_mem_zalloc(priv, sizeof (nvpriv_t))) == NULL)
242 nv_priv_init(emb_priv, priv->nvp_nva, NV_STAT_EMBEDDED);
248 nvlist_init(nvlist_t *nvl, uint32_t nvflag, nvpriv_t *priv)
250 nvl->nvl_version = NV_VERSION;
251 nvl->nvl_nvflag = nvflag & (NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE);
252 nvl->nvl_priv = (uint64_t)(uintptr_t)priv;
258 * nvlist_alloc - Allocate nvlist.
262 nvlist_alloc(nvlist_t **nvlp, uint_t nvflag, int kmflag)
264 #if defined(_KERNEL) && !defined(_BOOT)
265 return (nvlist_xalloc(nvlp, nvflag,
266 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
268 return (nvlist_xalloc(nvlp, nvflag, nv_alloc_nosleep));
273 nvlist_xalloc(nvlist_t **nvlp, uint_t nvflag, nv_alloc_t *nva)
277 if (nvlp == NULL || nva == NULL)
280 if ((priv = nv_priv_alloc(nva)) == NULL)
283 if ((*nvlp = nv_mem_zalloc(priv,
284 NV_ALIGN(sizeof (nvlist_t)))) == NULL) {
285 nv_mem_free(priv, priv, sizeof (nvpriv_t));
289 nvlist_init(*nvlp, nvflag, priv);
295 * nvp_buf_alloc - Allocate i_nvp_t for storing a new nv pair.
298 nvp_buf_alloc(nvlist_t *nvl, size_t len)
300 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
306 * Allocate the buffer
308 nvsize = len + offsetof(i_nvp_t, nvi_nvp);
310 if ((buf = nv_mem_zalloc(priv, nvsize)) == NULL)
320 * nvp_buf_free - de-Allocate an i_nvp_t.
323 nvp_buf_free(nvlist_t *nvl, nvpair_t *nvp)
325 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
326 size_t nvsize = nvp->nvp_size + offsetof(i_nvp_t, nvi_nvp);
328 nv_mem_free(priv, NVPAIR2I_NVP(nvp), nvsize);
332 * nvp_buf_link - link a new nv pair into the nvlist.
335 nvp_buf_link(nvlist_t *nvl, nvpair_t *nvp)
337 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
338 i_nvp_t *curr = NVPAIR2I_NVP(nvp);
340 /* Put element at end of nvlist */
341 if (priv->nvp_list == NULL) {
342 priv->nvp_list = priv->nvp_last = curr;
344 curr->nvi_prev = priv->nvp_last;
345 priv->nvp_last->nvi_next = curr;
346 priv->nvp_last = curr;
351 * nvp_buf_unlink - unlink an removed nvpair out of the nvlist.
354 nvp_buf_unlink(nvlist_t *nvl, nvpair_t *nvp)
356 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
357 i_nvp_t *curr = NVPAIR2I_NVP(nvp);
360 * protect nvlist_next_nvpair() against walking on freed memory.
362 if (priv->nvp_curr == curr)
363 priv->nvp_curr = curr->nvi_next;
365 if (curr == priv->nvp_list)
366 priv->nvp_list = curr->nvi_next;
368 curr->nvi_prev->nvi_next = curr->nvi_next;
370 if (curr == priv->nvp_last)
371 priv->nvp_last = curr->nvi_prev;
373 curr->nvi_next->nvi_prev = curr->nvi_prev;
377 * take a nvpair type and number of elements and make sure the are valid
380 i_validate_type_nelem(data_type_t type, uint_t nelem)
383 case DATA_TYPE_BOOLEAN:
387 case DATA_TYPE_BOOLEAN_VALUE:
390 case DATA_TYPE_UINT8:
391 case DATA_TYPE_INT16:
392 case DATA_TYPE_UINT16:
393 case DATA_TYPE_INT32:
394 case DATA_TYPE_UINT32:
395 case DATA_TYPE_INT64:
396 case DATA_TYPE_UINT64:
397 case DATA_TYPE_STRING:
398 case DATA_TYPE_HRTIME:
399 case DATA_TYPE_NVLIST:
400 #if !defined(_KERNEL)
401 case DATA_TYPE_DOUBLE:
406 case DATA_TYPE_BOOLEAN_ARRAY:
407 case DATA_TYPE_BYTE_ARRAY:
408 case DATA_TYPE_INT8_ARRAY:
409 case DATA_TYPE_UINT8_ARRAY:
410 case DATA_TYPE_INT16_ARRAY:
411 case DATA_TYPE_UINT16_ARRAY:
412 case DATA_TYPE_INT32_ARRAY:
413 case DATA_TYPE_UINT32_ARRAY:
414 case DATA_TYPE_INT64_ARRAY:
415 case DATA_TYPE_UINT64_ARRAY:
416 case DATA_TYPE_STRING_ARRAY:
417 case DATA_TYPE_NVLIST_ARRAY:
418 /* we allow arrays with 0 elements */
427 * Verify nvp_name_sz and check the name string length.
430 i_validate_nvpair_name(nvpair_t *nvp)
432 if ((nvp->nvp_name_sz <= 0) ||
433 (nvp->nvp_size < NVP_SIZE_CALC(nvp->nvp_name_sz, 0)))
436 /* verify the name string, make sure its terminated */
437 if (NVP_NAME(nvp)[nvp->nvp_name_sz - 1] != '\0')
440 return (strlen(NVP_NAME(nvp)) == nvp->nvp_name_sz - 1 ? 0 : EFAULT);
444 i_validate_nvpair_value(data_type_t type, uint_t nelem, const void *data)
447 case DATA_TYPE_BOOLEAN_VALUE:
448 if (*(boolean_t *)data != B_TRUE &&
449 *(boolean_t *)data != B_FALSE)
452 case DATA_TYPE_BOOLEAN_ARRAY: {
455 for (i = 0; i < nelem; i++)
456 if (((boolean_t *)data)[i] != B_TRUE &&
457 ((boolean_t *)data)[i] != B_FALSE)
469 * This function takes a pointer to what should be a nvpair and it's size
470 * and then verifies that all the nvpair fields make sense and can be
471 * trusted. This function is used when decoding packed nvpairs.
474 i_validate_nvpair(nvpair_t *nvp)
476 data_type_t type = NVP_TYPE(nvp);
479 /* verify nvp_name_sz, check the name string length */
480 if (i_validate_nvpair_name(nvp) != 0)
483 if (i_validate_nvpair_value(type, NVP_NELEM(nvp), NVP_VALUE(nvp)) != 0)
487 * verify nvp_type, nvp_value_elem, and also possibly
488 * verify string values and get the value size.
490 size2 = i_get_value_size(type, NVP_VALUE(nvp), NVP_NELEM(nvp));
491 size1 = nvp->nvp_size - NVP_VALOFF(nvp);
492 if (size2 < 0 || size1 != NV_ALIGN(size2))
499 nvlist_copy_pairs(nvlist_t *snvl, nvlist_t *dnvl)
504 if ((priv = (nvpriv_t *)(uintptr_t)snvl->nvl_priv) == NULL)
507 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
508 nvpair_t *nvp = &curr->nvi_nvp;
511 if ((err = nvlist_add_common(dnvl, NVP_NAME(nvp), NVP_TYPE(nvp),
512 NVP_NELEM(nvp), NVP_VALUE(nvp))) != 0)
520 * Frees all memory allocated for an nvpair (like embedded lists) with
521 * the exception of the nvpair buffer itself.
524 nvpair_free(nvpair_t *nvp)
526 switch (NVP_TYPE(nvp)) {
527 case DATA_TYPE_NVLIST:
528 nvlist_free(EMBEDDED_NVL(nvp));
530 case DATA_TYPE_NVLIST_ARRAY: {
531 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
534 for (i = 0; i < NVP_NELEM(nvp); i++)
536 nvlist_free(nvlp[i]);
545 * nvlist_free - free an unpacked nvlist
548 nvlist_free(nvlist_t *nvl)
554 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
558 * Unpacked nvlist are linked through i_nvp_t
560 curr = priv->nvp_list;
561 while (curr != NULL) {
562 nvpair_t *nvp = &curr->nvi_nvp;
563 curr = curr->nvi_next;
566 nvp_buf_free(nvl, nvp);
569 if (!(priv->nvp_stat & NV_STAT_EMBEDDED))
570 nv_mem_free(priv, nvl, NV_ALIGN(sizeof (nvlist_t)));
574 nv_mem_free(priv, priv, sizeof (nvpriv_t));
578 nvlist_contains_nvp(nvlist_t *nvl, nvpair_t *nvp)
580 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
586 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
587 if (&curr->nvi_nvp == nvp)
594 * Make a copy of nvlist
598 nvlist_dup(nvlist_t *nvl, nvlist_t **nvlp, int kmflag)
600 #if defined(_KERNEL) && !defined(_BOOT)
601 return (nvlist_xdup(nvl, nvlp,
602 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
604 return (nvlist_xdup(nvl, nvlp, nv_alloc_nosleep));
609 nvlist_xdup(nvlist_t *nvl, nvlist_t **nvlp, nv_alloc_t *nva)
614 if (nvl == NULL || nvlp == NULL)
617 if ((err = nvlist_xalloc(&ret, nvl->nvl_nvflag, nva)) != 0)
620 if ((err = nvlist_copy_pairs(nvl, ret)) != 0)
629 * Remove all with matching name
632 nvlist_remove_all(nvlist_t *nvl, const char *name)
638 if (nvl == NULL || name == NULL ||
639 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
642 curr = priv->nvp_list;
643 while (curr != NULL) {
644 nvpair_t *nvp = &curr->nvi_nvp;
646 curr = curr->nvi_next;
647 if (strcmp(name, NVP_NAME(nvp)) != 0)
650 nvp_buf_unlink(nvl, nvp);
652 nvp_buf_free(nvl, nvp);
661 * Remove first one with matching name and type
664 nvlist_remove(nvlist_t *nvl, const char *name, data_type_t type)
669 if (nvl == NULL || name == NULL ||
670 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
673 curr = priv->nvp_list;
674 while (curr != NULL) {
675 nvpair_t *nvp = &curr->nvi_nvp;
677 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type) {
678 nvp_buf_unlink(nvl, nvp);
680 nvp_buf_free(nvl, nvp);
684 curr = curr->nvi_next;
691 * This function calculates the size of an nvpair value.
693 * The data argument controls the behavior in case of the data types
694 * DATA_TYPE_STRING and
695 * DATA_TYPE_STRING_ARRAY
696 * Is data == NULL then the size of the string(s) is excluded.
699 i_get_value_size(data_type_t type, const void *data, uint_t nelem)
703 if (i_validate_type_nelem(type, nelem) != 0)
706 /* Calculate required size for holding value */
708 case DATA_TYPE_BOOLEAN:
711 case DATA_TYPE_BOOLEAN_VALUE:
712 value_sz = sizeof (boolean_t);
715 value_sz = sizeof (uchar_t);
718 value_sz = sizeof (int8_t);
720 case DATA_TYPE_UINT8:
721 value_sz = sizeof (uint8_t);
723 case DATA_TYPE_INT16:
724 value_sz = sizeof (int16_t);
726 case DATA_TYPE_UINT16:
727 value_sz = sizeof (uint16_t);
729 case DATA_TYPE_INT32:
730 value_sz = sizeof (int32_t);
732 case DATA_TYPE_UINT32:
733 value_sz = sizeof (uint32_t);
735 case DATA_TYPE_INT64:
736 value_sz = sizeof (int64_t);
738 case DATA_TYPE_UINT64:
739 value_sz = sizeof (uint64_t);
741 #if !defined(_KERNEL)
742 case DATA_TYPE_DOUBLE:
743 value_sz = sizeof (double);
746 case DATA_TYPE_STRING:
750 value_sz = strlen(data) + 1;
752 case DATA_TYPE_BOOLEAN_ARRAY:
753 value_sz = (uint64_t)nelem * sizeof (boolean_t);
755 case DATA_TYPE_BYTE_ARRAY:
756 value_sz = (uint64_t)nelem * sizeof (uchar_t);
758 case DATA_TYPE_INT8_ARRAY:
759 value_sz = (uint64_t)nelem * sizeof (int8_t);
761 case DATA_TYPE_UINT8_ARRAY:
762 value_sz = (uint64_t)nelem * sizeof (uint8_t);
764 case DATA_TYPE_INT16_ARRAY:
765 value_sz = (uint64_t)nelem * sizeof (int16_t);
767 case DATA_TYPE_UINT16_ARRAY:
768 value_sz = (uint64_t)nelem * sizeof (uint16_t);
770 case DATA_TYPE_INT32_ARRAY:
771 value_sz = (uint64_t)nelem * sizeof (int32_t);
773 case DATA_TYPE_UINT32_ARRAY:
774 value_sz = (uint64_t)nelem * sizeof (uint32_t);
776 case DATA_TYPE_INT64_ARRAY:
777 value_sz = (uint64_t)nelem * sizeof (int64_t);
779 case DATA_TYPE_UINT64_ARRAY:
780 value_sz = (uint64_t)nelem * sizeof (uint64_t);
782 case DATA_TYPE_STRING_ARRAY:
783 value_sz = (uint64_t)nelem * sizeof (uint64_t);
786 char *const *strs = data;
789 /* no alignment requirement for strings */
790 for (i = 0; i < nelem; i++) {
793 value_sz += strlen(strs[i]) + 1;
797 case DATA_TYPE_HRTIME:
798 value_sz = sizeof (hrtime_t);
800 case DATA_TYPE_NVLIST:
801 value_sz = NV_ALIGN(sizeof (nvlist_t));
803 case DATA_TYPE_NVLIST_ARRAY:
804 value_sz = (uint64_t)nelem * sizeof (uint64_t) +
805 (uint64_t)nelem * NV_ALIGN(sizeof (nvlist_t));
811 return (value_sz > INT32_MAX ? -1 : (int)value_sz);
815 nvlist_copy_embedded(nvlist_t *nvl, nvlist_t *onvl, nvlist_t *emb_nvl)
820 if ((priv = nv_priv_alloc_embedded((nvpriv_t *)(uintptr_t)
821 nvl->nvl_priv)) == NULL)
824 nvlist_init(emb_nvl, onvl->nvl_nvflag, priv);
826 if ((err = nvlist_copy_pairs(onvl, emb_nvl)) != 0) {
827 nvlist_free(emb_nvl);
828 emb_nvl->nvl_priv = 0;
835 * nvlist_add_common - Add new <name,value> pair to nvlist
838 nvlist_add_common(nvlist_t *nvl, const char *name,
839 data_type_t type, uint_t nelem, const void *data)
844 int nvp_sz, name_sz, value_sz;
847 if (name == NULL || nvl == NULL || nvl->nvl_priv == 0)
850 if (nelem != 0 && data == NULL)
854 * Verify type and nelem and get the value size.
855 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
856 * is the size of the string(s) included.
858 if ((value_sz = i_get_value_size(type, data, nelem)) < 0)
861 if (i_validate_nvpair_value(type, nelem, data) != 0)
865 * If we're adding an nvlist or nvlist array, ensure that we are not
866 * adding the input nvlist to itself, which would cause recursion,
867 * and ensure that no NULL nvlist pointers are present.
870 case DATA_TYPE_NVLIST:
871 if (data == nvl || data == NULL)
874 case DATA_TYPE_NVLIST_ARRAY: {
875 nvlist_t **onvlp = (nvlist_t **)data;
876 for (i = 0; i < nelem; i++) {
877 if (onvlp[i] == nvl || onvlp[i] == NULL)
886 /* calculate sizes of the nvpair elements and the nvpair itself */
887 name_sz = strlen(name) + 1;
889 nvp_sz = NVP_SIZE_CALC(name_sz, value_sz);
891 if ((nvp = nvp_buf_alloc(nvl, nvp_sz)) == NULL)
894 ASSERT(nvp->nvp_size == nvp_sz);
895 nvp->nvp_name_sz = name_sz;
896 nvp->nvp_value_elem = nelem;
897 nvp->nvp_type = type;
898 bcopy(name, NVP_NAME(nvp), name_sz);
901 case DATA_TYPE_BOOLEAN:
903 case DATA_TYPE_STRING_ARRAY: {
904 char *const *strs = data;
905 char *buf = NVP_VALUE(nvp);
906 char **cstrs = (void *)buf;
908 /* skip pre-allocated space for pointer array */
909 buf += nelem * sizeof (uint64_t);
910 for (i = 0; i < nelem; i++) {
911 int slen = strlen(strs[i]) + 1;
912 bcopy(strs[i], buf, slen);
918 case DATA_TYPE_NVLIST: {
919 nvlist_t *nnvl = EMBEDDED_NVL(nvp);
920 nvlist_t *onvl = (nvlist_t *)data;
922 if ((err = nvlist_copy_embedded(nvl, onvl, nnvl)) != 0) {
923 nvp_buf_free(nvl, nvp);
928 case DATA_TYPE_NVLIST_ARRAY: {
929 nvlist_t **onvlp = (nvlist_t **)data;
930 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
931 nvlist_t *embedded = (nvlist_t *)
932 ((uintptr_t)nvlp + nelem * sizeof (uint64_t));
934 for (i = 0; i < nelem; i++) {
935 if ((err = nvlist_copy_embedded(nvl,
936 onvlp[i], embedded)) != 0) {
938 * Free any successfully created lists
941 nvp_buf_free(nvl, nvp);
945 nvlp[i] = embedded++;
950 bcopy(data, NVP_VALUE(nvp), value_sz);
953 /* if unique name, remove before add */
954 if (nvl->nvl_nvflag & NV_UNIQUE_NAME)
955 (void) nvlist_remove_all(nvl, name);
956 else if (nvl->nvl_nvflag & NV_UNIQUE_NAME_TYPE)
957 (void) nvlist_remove(nvl, name, type);
959 nvp_buf_link(nvl, nvp);
965 nvlist_add_boolean(nvlist_t *nvl, const char *name)
967 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN, 0, NULL));
971 nvlist_add_boolean_value(nvlist_t *nvl, const char *name, boolean_t val)
973 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_VALUE, 1, &val));
977 nvlist_add_byte(nvlist_t *nvl, const char *name, uchar_t val)
979 return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE, 1, &val));
983 nvlist_add_int8(nvlist_t *nvl, const char *name, int8_t val)
985 return (nvlist_add_common(nvl, name, DATA_TYPE_INT8, 1, &val));
989 nvlist_add_uint8(nvlist_t *nvl, const char *name, uint8_t val)
991 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8, 1, &val));
995 nvlist_add_int16(nvlist_t *nvl, const char *name, int16_t val)
997 return (nvlist_add_common(nvl, name, DATA_TYPE_INT16, 1, &val));
1001 nvlist_add_uint16(nvlist_t *nvl, const char *name, uint16_t val)
1003 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16, 1, &val));
1007 nvlist_add_int32(nvlist_t *nvl, const char *name, int32_t val)
1009 return (nvlist_add_common(nvl, name, DATA_TYPE_INT32, 1, &val));
1013 nvlist_add_uint32(nvlist_t *nvl, const char *name, uint32_t val)
1015 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32, 1, &val));
1019 nvlist_add_int64(nvlist_t *nvl, const char *name, int64_t val)
1021 return (nvlist_add_common(nvl, name, DATA_TYPE_INT64, 1, &val));
1025 nvlist_add_uint64(nvlist_t *nvl, const char *name, uint64_t val)
1027 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64, 1, &val));
1030 #if !defined(_KERNEL)
1032 nvlist_add_double(nvlist_t *nvl, const char *name, double val)
1034 return (nvlist_add_common(nvl, name, DATA_TYPE_DOUBLE, 1, &val));
1039 nvlist_add_string(nvlist_t *nvl, const char *name, const char *val)
1041 return (nvlist_add_common(nvl, name, DATA_TYPE_STRING, 1, (void *)val));
1045 nvlist_add_boolean_array(nvlist_t *nvl, const char *name,
1046 boolean_t *a, uint_t n)
1048 return (nvlist_add_common(nvl, name, DATA_TYPE_BOOLEAN_ARRAY, n, a));
1052 nvlist_add_byte_array(nvlist_t *nvl, const char *name, uchar_t *a, uint_t n)
1054 return (nvlist_add_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
1058 nvlist_add_int8_array(nvlist_t *nvl, const char *name, int8_t *a, uint_t n)
1060 return (nvlist_add_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
1064 nvlist_add_uint8_array(nvlist_t *nvl, const char *name, uint8_t *a, uint_t n)
1066 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
1070 nvlist_add_int16_array(nvlist_t *nvl, const char *name, int16_t *a, uint_t n)
1072 return (nvlist_add_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
1076 nvlist_add_uint16_array(nvlist_t *nvl, const char *name, uint16_t *a, uint_t n)
1078 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
1082 nvlist_add_int32_array(nvlist_t *nvl, const char *name, int32_t *a, uint_t n)
1084 return (nvlist_add_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
1088 nvlist_add_uint32_array(nvlist_t *nvl, const char *name, uint32_t *a, uint_t n)
1090 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
1094 nvlist_add_int64_array(nvlist_t *nvl, const char *name, int64_t *a, uint_t n)
1096 return (nvlist_add_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
1100 nvlist_add_uint64_array(nvlist_t *nvl, const char *name, uint64_t *a, uint_t n)
1102 return (nvlist_add_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
1106 nvlist_add_string_array(nvlist_t *nvl, const char *name,
1107 char *const *a, uint_t n)
1109 return (nvlist_add_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
1113 nvlist_add_hrtime(nvlist_t *nvl, const char *name, hrtime_t val)
1115 return (nvlist_add_common(nvl, name, DATA_TYPE_HRTIME, 1, &val));
1119 nvlist_add_nvlist(nvlist_t *nvl, const char *name, nvlist_t *val)
1121 return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST, 1, val));
1125 nvlist_add_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **a, uint_t n)
1127 return (nvlist_add_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
1130 /* reading name-value pairs */
1132 nvlist_next_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1138 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1141 curr = NVPAIR2I_NVP(nvp);
1144 * Ensure that nvp is a valid nvpair on this nvlist.
1145 * NB: nvp_curr is used only as a hint so that we don't always
1146 * have to walk the list to determine if nvp is still on the list.
1149 curr = priv->nvp_list;
1150 else if (priv->nvp_curr == curr || nvlist_contains_nvp(nvl, nvp))
1151 curr = curr->nvi_next;
1155 priv->nvp_curr = curr;
1157 return (curr != NULL ? &curr->nvi_nvp : NULL);
1161 nvpair_name(nvpair_t *nvp)
1163 return (NVP_NAME(nvp));
1167 nvpair_type(nvpair_t *nvp)
1169 return (NVP_TYPE(nvp));
1173 nvpair_type_is_array(nvpair_t *nvp)
1175 data_type_t type = NVP_TYPE(nvp);
1177 if ((type == DATA_TYPE_BYTE_ARRAY) ||
1178 (type == DATA_TYPE_UINT8_ARRAY) ||
1179 (type == DATA_TYPE_INT16_ARRAY) ||
1180 (type == DATA_TYPE_UINT16_ARRAY) ||
1181 (type == DATA_TYPE_INT32_ARRAY) ||
1182 (type == DATA_TYPE_UINT32_ARRAY) ||
1183 (type == DATA_TYPE_INT64_ARRAY) ||
1184 (type == DATA_TYPE_UINT64_ARRAY) ||
1185 (type == DATA_TYPE_BOOLEAN_ARRAY) ||
1186 (type == DATA_TYPE_STRING_ARRAY) ||
1187 (type == DATA_TYPE_NVLIST_ARRAY))
1194 nvpair_value_common(nvpair_t *nvp, data_type_t type, uint_t *nelem, void *data)
1196 if (nvp == NULL || nvpair_type(nvp) != type)
1200 * For non-array types, we copy the data.
1201 * For array types (including string), we set a pointer.
1204 case DATA_TYPE_BOOLEAN:
1209 case DATA_TYPE_BOOLEAN_VALUE:
1210 case DATA_TYPE_BYTE:
1211 case DATA_TYPE_INT8:
1212 case DATA_TYPE_UINT8:
1213 case DATA_TYPE_INT16:
1214 case DATA_TYPE_UINT16:
1215 case DATA_TYPE_INT32:
1216 case DATA_TYPE_UINT32:
1217 case DATA_TYPE_INT64:
1218 case DATA_TYPE_UINT64:
1219 case DATA_TYPE_HRTIME:
1220 #if !defined(_KERNEL)
1221 case DATA_TYPE_DOUBLE:
1225 bcopy(NVP_VALUE(nvp), data,
1226 (size_t)i_get_value_size(type, NULL, 1));
1231 case DATA_TYPE_NVLIST:
1232 case DATA_TYPE_STRING:
1235 *(void **)data = (void *)NVP_VALUE(nvp);
1240 case DATA_TYPE_BOOLEAN_ARRAY:
1241 case DATA_TYPE_BYTE_ARRAY:
1242 case DATA_TYPE_INT8_ARRAY:
1243 case DATA_TYPE_UINT8_ARRAY:
1244 case DATA_TYPE_INT16_ARRAY:
1245 case DATA_TYPE_UINT16_ARRAY:
1246 case DATA_TYPE_INT32_ARRAY:
1247 case DATA_TYPE_UINT32_ARRAY:
1248 case DATA_TYPE_INT64_ARRAY:
1249 case DATA_TYPE_UINT64_ARRAY:
1250 case DATA_TYPE_STRING_ARRAY:
1251 case DATA_TYPE_NVLIST_ARRAY:
1252 if (nelem == NULL || data == NULL)
1254 if ((*nelem = NVP_NELEM(nvp)) != 0)
1255 *(void **)data = (void *)NVP_VALUE(nvp);
1257 *(void **)data = NULL;
1268 nvlist_lookup_common(nvlist_t *nvl, const char *name, data_type_t type,
1269 uint_t *nelem, void *data)
1275 if (name == NULL || nvl == NULL ||
1276 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1279 if (!(nvl->nvl_nvflag & (NV_UNIQUE_NAME | NV_UNIQUE_NAME_TYPE)))
1282 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
1283 nvp = &curr->nvi_nvp;
1285 if (strcmp(name, NVP_NAME(nvp)) == 0 && NVP_TYPE(nvp) == type)
1286 return (nvpair_value_common(nvp, type, nelem, data));
1293 nvlist_lookup_boolean(nvlist_t *nvl, const char *name)
1295 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BOOLEAN, NULL, NULL));
1299 nvlist_lookup_boolean_value(nvlist_t *nvl, const char *name, boolean_t *val)
1301 return (nvlist_lookup_common(nvl, name,
1302 DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1306 nvlist_lookup_byte(nvlist_t *nvl, const char *name, uchar_t *val)
1308 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE, NULL, val));
1312 nvlist_lookup_int8(nvlist_t *nvl, const char *name, int8_t *val)
1314 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8, NULL, val));
1318 nvlist_lookup_uint8(nvlist_t *nvl, const char *name, uint8_t *val)
1320 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8, NULL, val));
1324 nvlist_lookup_int16(nvlist_t *nvl, const char *name, int16_t *val)
1326 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16, NULL, val));
1330 nvlist_lookup_uint16(nvlist_t *nvl, const char *name, uint16_t *val)
1332 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16, NULL, val));
1336 nvlist_lookup_int32(nvlist_t *nvl, const char *name, int32_t *val)
1338 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32, NULL, val));
1342 nvlist_lookup_uint32(nvlist_t *nvl, const char *name, uint32_t *val)
1344 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32, NULL, val));
1348 nvlist_lookup_int64(nvlist_t *nvl, const char *name, int64_t *val)
1350 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64, NULL, val));
1354 nvlist_lookup_uint64(nvlist_t *nvl, const char *name, uint64_t *val)
1356 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64, NULL, val));
1359 #if !defined(_KERNEL)
1361 nvlist_lookup_double(nvlist_t *nvl, const char *name, double *val)
1363 return (nvlist_lookup_common(nvl, name, DATA_TYPE_DOUBLE, NULL, val));
1368 nvlist_lookup_string(nvlist_t *nvl, const char *name, char **val)
1370 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING, NULL, val));
1374 nvlist_lookup_nvlist(nvlist_t *nvl, const char *name, nvlist_t **val)
1376 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST, NULL, val));
1380 nvlist_lookup_boolean_array(nvlist_t *nvl, const char *name,
1381 boolean_t **a, uint_t *n)
1383 return (nvlist_lookup_common(nvl, name,
1384 DATA_TYPE_BOOLEAN_ARRAY, n, a));
1388 nvlist_lookup_byte_array(nvlist_t *nvl, const char *name,
1389 uchar_t **a, uint_t *n)
1391 return (nvlist_lookup_common(nvl, name, DATA_TYPE_BYTE_ARRAY, n, a));
1395 nvlist_lookup_int8_array(nvlist_t *nvl, const char *name, int8_t **a, uint_t *n)
1397 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT8_ARRAY, n, a));
1401 nvlist_lookup_uint8_array(nvlist_t *nvl, const char *name,
1402 uint8_t **a, uint_t *n)
1404 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT8_ARRAY, n, a));
1408 nvlist_lookup_int16_array(nvlist_t *nvl, const char *name,
1409 int16_t **a, uint_t *n)
1411 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT16_ARRAY, n, a));
1415 nvlist_lookup_uint16_array(nvlist_t *nvl, const char *name,
1416 uint16_t **a, uint_t *n)
1418 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT16_ARRAY, n, a));
1422 nvlist_lookup_int32_array(nvlist_t *nvl, const char *name,
1423 int32_t **a, uint_t *n)
1425 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT32_ARRAY, n, a));
1429 nvlist_lookup_uint32_array(nvlist_t *nvl, const char *name,
1430 uint32_t **a, uint_t *n)
1432 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT32_ARRAY, n, a));
1436 nvlist_lookup_int64_array(nvlist_t *nvl, const char *name,
1437 int64_t **a, uint_t *n)
1439 return (nvlist_lookup_common(nvl, name, DATA_TYPE_INT64_ARRAY, n, a));
1443 nvlist_lookup_uint64_array(nvlist_t *nvl, const char *name,
1444 uint64_t **a, uint_t *n)
1446 return (nvlist_lookup_common(nvl, name, DATA_TYPE_UINT64_ARRAY, n, a));
1450 nvlist_lookup_string_array(nvlist_t *nvl, const char *name,
1451 char ***a, uint_t *n)
1453 return (nvlist_lookup_common(nvl, name, DATA_TYPE_STRING_ARRAY, n, a));
1457 nvlist_lookup_nvlist_array(nvlist_t *nvl, const char *name,
1458 nvlist_t ***a, uint_t *n)
1460 return (nvlist_lookup_common(nvl, name, DATA_TYPE_NVLIST_ARRAY, n, a));
1464 nvlist_lookup_hrtime(nvlist_t *nvl, const char *name, hrtime_t *val)
1466 return (nvlist_lookup_common(nvl, name, DATA_TYPE_HRTIME, NULL, val));
1470 nvlist_lookup_pairs(nvlist_t *nvl, int flag, ...)
1474 int noentok = (flag & NV_FLAG_NOENTOK ? 1 : 0);
1478 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
1483 switch (type = va_arg(ap, data_type_t)) {
1484 case DATA_TYPE_BOOLEAN:
1485 ret = nvlist_lookup_common(nvl, name, type, NULL, NULL);
1488 case DATA_TYPE_BOOLEAN_VALUE:
1489 case DATA_TYPE_BYTE:
1490 case DATA_TYPE_INT8:
1491 case DATA_TYPE_UINT8:
1492 case DATA_TYPE_INT16:
1493 case DATA_TYPE_UINT16:
1494 case DATA_TYPE_INT32:
1495 case DATA_TYPE_UINT32:
1496 case DATA_TYPE_INT64:
1497 case DATA_TYPE_UINT64:
1498 case DATA_TYPE_HRTIME:
1499 case DATA_TYPE_STRING:
1500 case DATA_TYPE_NVLIST:
1501 #if !defined(_KERNEL)
1502 case DATA_TYPE_DOUBLE:
1504 val = va_arg(ap, void *);
1505 ret = nvlist_lookup_common(nvl, name, type, NULL, val);
1508 case DATA_TYPE_BYTE_ARRAY:
1509 case DATA_TYPE_BOOLEAN_ARRAY:
1510 case DATA_TYPE_INT8_ARRAY:
1511 case DATA_TYPE_UINT8_ARRAY:
1512 case DATA_TYPE_INT16_ARRAY:
1513 case DATA_TYPE_UINT16_ARRAY:
1514 case DATA_TYPE_INT32_ARRAY:
1515 case DATA_TYPE_UINT32_ARRAY:
1516 case DATA_TYPE_INT64_ARRAY:
1517 case DATA_TYPE_UINT64_ARRAY:
1518 case DATA_TYPE_STRING_ARRAY:
1519 case DATA_TYPE_NVLIST_ARRAY:
1520 val = va_arg(ap, void *);
1521 nelem = va_arg(ap, uint_t *);
1522 ret = nvlist_lookup_common(nvl, name, type, nelem, val);
1529 if (ret == ENOENT && noentok)
1538 * Find the 'name'ed nvpair in the nvlist 'nvl'. If 'name' found, the function
1539 * returns zero and a pointer to the matching nvpair is returned in '*ret'
1540 * (given 'ret' is non-NULL). If 'sep' is specified then 'name' will penitrate
1541 * multiple levels of embedded nvlists, with 'sep' as the separator. As an
1542 * example, if sep is '.', name might look like: "a" or "a.b" or "a.c[3]" or
1543 * "a.d[3].e[1]". This matches the C syntax for array embed (for convience,
1544 * code also supports "a.d[3]e[1]" syntax).
1546 * If 'ip' is non-NULL and the last name component is an array, return the
1547 * value of the "...[index]" array index in *ip. For an array reference that
1548 * is not indexed, *ip will be returned as -1. If there is a syntax error in
1549 * 'name', and 'ep' is non-NULL then *ep will be set to point to the location
1550 * inside the 'name' string where the syntax error was detected.
1553 nvlist_lookup_nvpair_ei_sep(nvlist_t *nvl, const char *name, const char sep,
1554 nvpair_t **ret, int *ip, char **ep)
1565 *ip = -1; /* not indexed */
1569 if ((nvl == NULL) || (name == NULL))
1572 /* step through components of name */
1573 for (np = name; np && *np; np = sepp) {
1574 /* ensure unique names */
1575 if (!(nvl->nvl_nvflag & NV_UNIQUE_NAME))
1578 /* skip white space */
1579 skip_whitespace(np);
1583 /* set 'sepp' to end of current component 'np' */
1585 sepp = strchr(np, sep);
1589 /* find start of next "[ index ]..." */
1590 idxp = strchr(np, '[');
1592 /* if sepp comes first, set idxp to NULL */
1593 if (sepp && idxp && (sepp < idxp))
1597 * At this point 'idxp' is set if there is an index
1598 * expected for the current component.
1601 /* set 'n' to length of current 'np' name component */
1604 /* keep sepp up to date for *ep use as we advance */
1605 skip_whitespace(idxp);
1608 /* determine the index value */
1609 #if defined(_KERNEL) && !defined(_BOOT)
1610 if (ddi_strtol(idxp, &idxep, 0, &idx))
1613 idx = strtol(idxp, &idxep, 0);
1618 /* keep sepp up to date for *ep use as we advance */
1621 /* skip white space index value and check for ']' */
1622 skip_whitespace(sepp);
1626 /* for embedded arrays, support C syntax: "a[1].b" */
1627 skip_whitespace(sepp);
1628 if (sep && (*sepp == sep))
1636 /* trim trailing whitespace by reducing length of 'np' */
1639 for (n--; (np[n] == ' ') || (np[n] == '\t'); n--)
1643 /* skip whitespace, and set sepp to NULL if complete */
1645 skip_whitespace(sepp);
1652 * o 'n' is the length of current 'np' component.
1653 * o 'idxp' is set if there was an index, and value 'idx'.
1654 * o 'sepp' is set to the beginning of the next component,
1655 * and set to NULL if we have no more components.
1657 * Search for nvpair with matching component name.
1659 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
1660 nvp = nvlist_next_nvpair(nvl, nvp)) {
1662 /* continue if no match on name */
1663 if (strncmp(np, nvpair_name(nvp), n) ||
1664 (strlen(nvpair_name(nvp)) != n))
1667 /* if indexed, verify type is array oriented */
1668 if (idxp && !nvpair_type_is_array(nvp))
1672 * Full match found, return nvp and idx if this
1673 * was the last component.
1679 *ip = (int)idx; /* return index */
1680 return (0); /* found */
1684 * More components: current match must be
1685 * of DATA_TYPE_NVLIST or DATA_TYPE_NVLIST_ARRAY
1686 * to support going deeper.
1688 if (nvpair_type(nvp) == DATA_TYPE_NVLIST) {
1689 nvl = EMBEDDED_NVL(nvp);
1691 } else if (nvpair_type(nvp) == DATA_TYPE_NVLIST_ARRAY) {
1692 (void) nvpair_value_nvlist_array(nvp,
1693 &nva, (uint_t *)&n);
1694 if ((n < 0) || (idx >= n))
1700 /* type does not support more levels */
1704 goto fail; /* 'name' not found */
1706 /* search for match of next component in embedded 'nvl' list */
1709 fail: if (ep && sepp)
1715 * Return pointer to nvpair with specified 'name'.
1718 nvlist_lookup_nvpair(nvlist_t *nvl, const char *name, nvpair_t **ret)
1720 return (nvlist_lookup_nvpair_ei_sep(nvl, name, 0, ret, NULL, NULL));
1724 * Determine if named nvpair exists in nvlist (use embedded separator of '.'
1725 * and return array index). See nvlist_lookup_nvpair_ei_sep for more detailed
1728 int nvlist_lookup_nvpair_embedded_index(nvlist_t *nvl,
1729 const char *name, nvpair_t **ret, int *ip, char **ep)
1731 return (nvlist_lookup_nvpair_ei_sep(nvl, name, '.', ret, ip, ep));
1735 nvlist_exists(nvlist_t *nvl, const char *name)
1741 if (name == NULL || nvl == NULL ||
1742 (priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
1745 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
1746 nvp = &curr->nvi_nvp;
1748 if (strcmp(name, NVP_NAME(nvp)) == 0)
1756 nvpair_value_boolean_value(nvpair_t *nvp, boolean_t *val)
1758 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_VALUE, NULL, val));
1762 nvpair_value_byte(nvpair_t *nvp, uchar_t *val)
1764 return (nvpair_value_common(nvp, DATA_TYPE_BYTE, NULL, val));
1768 nvpair_value_int8(nvpair_t *nvp, int8_t *val)
1770 return (nvpair_value_common(nvp, DATA_TYPE_INT8, NULL, val));
1774 nvpair_value_uint8(nvpair_t *nvp, uint8_t *val)
1776 return (nvpair_value_common(nvp, DATA_TYPE_UINT8, NULL, val));
1780 nvpair_value_int16(nvpair_t *nvp, int16_t *val)
1782 return (nvpair_value_common(nvp, DATA_TYPE_INT16, NULL, val));
1786 nvpair_value_uint16(nvpair_t *nvp, uint16_t *val)
1788 return (nvpair_value_common(nvp, DATA_TYPE_UINT16, NULL, val));
1792 nvpair_value_int32(nvpair_t *nvp, int32_t *val)
1794 return (nvpair_value_common(nvp, DATA_TYPE_INT32, NULL, val));
1798 nvpair_value_uint32(nvpair_t *nvp, uint32_t *val)
1800 return (nvpair_value_common(nvp, DATA_TYPE_UINT32, NULL, val));
1804 nvpair_value_int64(nvpair_t *nvp, int64_t *val)
1806 return (nvpair_value_common(nvp, DATA_TYPE_INT64, NULL, val));
1810 nvpair_value_uint64(nvpair_t *nvp, uint64_t *val)
1812 return (nvpair_value_common(nvp, DATA_TYPE_UINT64, NULL, val));
1815 #if !defined(_KERNEL)
1817 nvpair_value_double(nvpair_t *nvp, double *val)
1819 return (nvpair_value_common(nvp, DATA_TYPE_DOUBLE, NULL, val));
1824 nvpair_value_string(nvpair_t *nvp, char **val)
1826 return (nvpair_value_common(nvp, DATA_TYPE_STRING, NULL, val));
1830 nvpair_value_nvlist(nvpair_t *nvp, nvlist_t **val)
1832 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST, NULL, val));
1836 nvpair_value_boolean_array(nvpair_t *nvp, boolean_t **val, uint_t *nelem)
1838 return (nvpair_value_common(nvp, DATA_TYPE_BOOLEAN_ARRAY, nelem, val));
1842 nvpair_value_byte_array(nvpair_t *nvp, uchar_t **val, uint_t *nelem)
1844 return (nvpair_value_common(nvp, DATA_TYPE_BYTE_ARRAY, nelem, val));
1848 nvpair_value_int8_array(nvpair_t *nvp, int8_t **val, uint_t *nelem)
1850 return (nvpair_value_common(nvp, DATA_TYPE_INT8_ARRAY, nelem, val));
1854 nvpair_value_uint8_array(nvpair_t *nvp, uint8_t **val, uint_t *nelem)
1856 return (nvpair_value_common(nvp, DATA_TYPE_UINT8_ARRAY, nelem, val));
1860 nvpair_value_int16_array(nvpair_t *nvp, int16_t **val, uint_t *nelem)
1862 return (nvpair_value_common(nvp, DATA_TYPE_INT16_ARRAY, nelem, val));
1866 nvpair_value_uint16_array(nvpair_t *nvp, uint16_t **val, uint_t *nelem)
1868 return (nvpair_value_common(nvp, DATA_TYPE_UINT16_ARRAY, nelem, val));
1872 nvpair_value_int32_array(nvpair_t *nvp, int32_t **val, uint_t *nelem)
1874 return (nvpair_value_common(nvp, DATA_TYPE_INT32_ARRAY, nelem, val));
1878 nvpair_value_uint32_array(nvpair_t *nvp, uint32_t **val, uint_t *nelem)
1880 return (nvpair_value_common(nvp, DATA_TYPE_UINT32_ARRAY, nelem, val));
1884 nvpair_value_int64_array(nvpair_t *nvp, int64_t **val, uint_t *nelem)
1886 return (nvpair_value_common(nvp, DATA_TYPE_INT64_ARRAY, nelem, val));
1890 nvpair_value_uint64_array(nvpair_t *nvp, uint64_t **val, uint_t *nelem)
1892 return (nvpair_value_common(nvp, DATA_TYPE_UINT64_ARRAY, nelem, val));
1896 nvpair_value_string_array(nvpair_t *nvp, char ***val, uint_t *nelem)
1898 return (nvpair_value_common(nvp, DATA_TYPE_STRING_ARRAY, nelem, val));
1902 nvpair_value_nvlist_array(nvpair_t *nvp, nvlist_t ***val, uint_t *nelem)
1904 return (nvpair_value_common(nvp, DATA_TYPE_NVLIST_ARRAY, nelem, val));
1908 nvpair_value_hrtime(nvpair_t *nvp, hrtime_t *val)
1910 return (nvpair_value_common(nvp, DATA_TYPE_HRTIME, NULL, val));
1914 * Add specified pair to the list.
1917 nvlist_add_nvpair(nvlist_t *nvl, nvpair_t *nvp)
1919 if (nvl == NULL || nvp == NULL)
1922 return (nvlist_add_common(nvl, NVP_NAME(nvp), NVP_TYPE(nvp),
1923 NVP_NELEM(nvp), NVP_VALUE(nvp)));
1927 * Merge the supplied nvlists and put the result in dst.
1928 * The merged list will contain all names specified in both lists,
1929 * the values are taken from nvl in the case of duplicates.
1930 * Return 0 on success.
1934 nvlist_merge(nvlist_t *dst, nvlist_t *nvl, int flag)
1936 if (nvl == NULL || dst == NULL)
1940 return (nvlist_copy_pairs(nvl, dst));
1946 * Encoding related routines
1948 #define NVS_OP_ENCODE 0
1949 #define NVS_OP_DECODE 1
1950 #define NVS_OP_GETSIZE 2
1952 typedef struct nvs_ops nvs_ops_t;
1956 const nvs_ops_t *nvs_ops;
1962 * nvs operations are:
1964 * encoding / decoding of a nvlist header (nvlist_t)
1965 * calculates the size used for header and end detection
1968 * responsible for the first part of encoding / decoding of an nvpair
1969 * calculates the decoded size of an nvpair
1972 * second part of encoding / decoding of an nvpair
1975 * calculates the encoding size of an nvpair
1978 * encodes the end detection mark (zeros).
1981 int (*nvs_nvlist)(nvstream_t *, nvlist_t *, size_t *);
1982 int (*nvs_nvpair)(nvstream_t *, nvpair_t *, size_t *);
1983 int (*nvs_nvp_op)(nvstream_t *, nvpair_t *);
1984 int (*nvs_nvp_size)(nvstream_t *, nvpair_t *, size_t *);
1985 int (*nvs_nvl_fini)(nvstream_t *);
1989 char nvh_encoding; /* nvs encoding method */
1990 char nvh_endian; /* nvs endian */
1991 char nvh_reserved1; /* reserved for future use */
1992 char nvh_reserved2; /* reserved for future use */
1996 nvs_encode_pairs(nvstream_t *nvs, nvlist_t *nvl)
1998 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2002 * Walk nvpair in list and encode each nvpair
2004 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next)
2005 if (nvs->nvs_ops->nvs_nvpair(nvs, &curr->nvi_nvp, NULL) != 0)
2008 return (nvs->nvs_ops->nvs_nvl_fini(nvs));
2012 nvs_decode_pairs(nvstream_t *nvs, nvlist_t *nvl)
2019 * Get decoded size of next pair in stream, alloc
2020 * memory for nvpair_t, then decode the nvpair
2022 while ((err = nvs->nvs_ops->nvs_nvpair(nvs, NULL, &nvsize)) == 0) {
2023 if (nvsize == 0) /* end of list */
2026 /* make sure len makes sense */
2027 if (nvsize < NVP_SIZE_CALC(1, 0))
2030 if ((nvp = nvp_buf_alloc(nvl, nvsize)) == NULL)
2033 if ((err = nvs->nvs_ops->nvs_nvp_op(nvs, nvp)) != 0) {
2034 nvp_buf_free(nvl, nvp);
2038 if (i_validate_nvpair(nvp) != 0) {
2040 nvp_buf_free(nvl, nvp);
2044 nvp_buf_link(nvl, nvp);
2050 nvs_getsize_pairs(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2052 nvpriv_t *priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv;
2054 uint64_t nvsize = *buflen;
2058 * Get encoded size of nvpairs in nvlist
2060 for (curr = priv->nvp_list; curr != NULL; curr = curr->nvi_next) {
2061 if (nvs->nvs_ops->nvs_nvp_size(nvs, &curr->nvi_nvp, &size) != 0)
2064 if ((nvsize += size) > INT32_MAX)
2073 nvs_operation(nvstream_t *nvs, nvlist_t *nvl, size_t *buflen)
2077 if (nvl->nvl_priv == 0)
2081 * Perform the operation, starting with header, then each nvpair
2083 if ((err = nvs->nvs_ops->nvs_nvlist(nvs, nvl, buflen)) != 0)
2086 switch (nvs->nvs_op) {
2088 err = nvs_encode_pairs(nvs, nvl);
2092 err = nvs_decode_pairs(nvs, nvl);
2095 case NVS_OP_GETSIZE:
2096 err = nvs_getsize_pairs(nvs, nvl, buflen);
2107 nvs_embedded(nvstream_t *nvs, nvlist_t *embedded)
2109 switch (nvs->nvs_op) {
2111 return (nvs_operation(nvs, embedded, NULL));
2113 case NVS_OP_DECODE: {
2117 if (embedded->nvl_version != NV_VERSION)
2120 if ((priv = nv_priv_alloc_embedded(nvs->nvs_priv)) == NULL)
2123 nvlist_init(embedded, embedded->nvl_nvflag, priv);
2125 if ((err = nvs_operation(nvs, embedded, NULL)) != 0)
2126 nvlist_free(embedded);
2137 nvs_embedded_nvl_array(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2139 size_t nelem = NVP_NELEM(nvp);
2140 nvlist_t **nvlp = EMBEDDED_NVL_ARRAY(nvp);
2143 switch (nvs->nvs_op) {
2145 for (i = 0; i < nelem; i++)
2146 if (nvs_embedded(nvs, nvlp[i]) != 0)
2150 case NVS_OP_DECODE: {
2151 size_t len = nelem * sizeof (uint64_t);
2152 nvlist_t *embedded = (nvlist_t *)((uintptr_t)nvlp + len);
2154 bzero(nvlp, len); /* don't trust packed data */
2155 for (i = 0; i < nelem; i++) {
2156 if (nvs_embedded(nvs, embedded) != 0) {
2161 nvlp[i] = embedded++;
2165 case NVS_OP_GETSIZE: {
2166 uint64_t nvsize = 0;
2168 for (i = 0; i < nelem; i++) {
2171 if (nvs_operation(nvs, nvlp[i], &nvp_sz) != 0)
2174 if ((nvsize += nvp_sz) > INT32_MAX)
2188 static int nvs_native(nvstream_t *, nvlist_t *, char *, size_t *);
2189 static int nvs_xdr(nvstream_t *, nvlist_t *, char *, size_t *);
2192 * Common routine for nvlist operations:
2193 * encode, decode, getsize (encoded size).
2196 nvlist_common(nvlist_t *nvl, char *buf, size_t *buflen, int encoding,
2202 #if BYTE_ORDER == _LITTLE_ENDIAN
2203 int host_endian = 1;
2205 int host_endian = 0;
2206 #endif /* _LITTLE_ENDIAN */
2207 nvs_header_t *nvh = (void *)buf;
2209 if (buflen == NULL || nvl == NULL ||
2210 (nvs.nvs_priv = (nvpriv_t *)(uintptr_t)nvl->nvl_priv) == NULL)
2213 nvs.nvs_op = nvs_op;
2216 * For NVS_OP_ENCODE and NVS_OP_DECODE make sure an nvlist and
2217 * a buffer is allocated. The first 4 bytes in the buffer are
2218 * used for encoding method and host endian.
2222 if (buf == NULL || *buflen < sizeof (nvs_header_t))
2225 nvh->nvh_encoding = encoding;
2226 nvh->nvh_endian = nvl_endian = host_endian;
2227 nvh->nvh_reserved1 = 0;
2228 nvh->nvh_reserved2 = 0;
2232 if (buf == NULL || *buflen < sizeof (nvs_header_t))
2235 /* get method of encoding from first byte */
2236 encoding = nvh->nvh_encoding;
2237 nvl_endian = nvh->nvh_endian;
2240 case NVS_OP_GETSIZE:
2241 nvl_endian = host_endian;
2244 * add the size for encoding
2246 *buflen = sizeof (nvs_header_t);
2254 * Create an nvstream with proper encoding method
2257 case NV_ENCODE_NATIVE:
2259 * check endianness, in case we are unpacking
2262 if (nvl_endian != host_endian)
2264 err = nvs_native(&nvs, nvl, buf, buflen);
2267 err = nvs_xdr(&nvs, nvl, buf, buflen);
2278 nvlist_size(nvlist_t *nvl, size_t *size, int encoding)
2280 return (nvlist_common(nvl, NULL, size, encoding, NVS_OP_GETSIZE));
2284 * Pack nvlist into contiguous memory
2288 nvlist_pack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2291 #if defined(_KERNEL) && !defined(_BOOT)
2292 return (nvlist_xpack(nvl, bufp, buflen, encoding,
2293 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2295 return (nvlist_xpack(nvl, bufp, buflen, encoding, nv_alloc_nosleep));
2300 nvlist_xpack(nvlist_t *nvl, char **bufp, size_t *buflen, int encoding,
2308 if (nva == NULL || nvl == NULL || bufp == NULL || buflen == NULL)
2312 return (nvlist_common(nvl, *bufp, buflen, encoding,
2316 * Here is a difficult situation:
2317 * 1. The nvlist has fixed allocator properties.
2318 * All other nvlist routines (like nvlist_add_*, ...) use
2320 * 2. When using nvlist_pack() the user can specify his own
2321 * allocator properties (e.g. by using KM_NOSLEEP).
2323 * We use the user specified properties (2). A clearer solution
2324 * will be to remove the kmflag from nvlist_pack(), but we will
2325 * not change the interface.
2327 nv_priv_init(&nvpriv, nva, 0);
2329 if (err = nvlist_size(nvl, &alloc_size, encoding))
2332 if ((buf = nv_mem_zalloc(&nvpriv, alloc_size)) == NULL)
2335 if ((err = nvlist_common(nvl, buf, &alloc_size, encoding,
2336 NVS_OP_ENCODE)) != 0) {
2337 nv_mem_free(&nvpriv, buf, alloc_size);
2339 *buflen = alloc_size;
2347 * Unpack buf into an nvlist_t
2351 nvlist_unpack(char *buf, size_t buflen, nvlist_t **nvlp, int kmflag)
2353 #if defined(_KERNEL) && !defined(_BOOT)
2354 return (nvlist_xunpack(buf, buflen, nvlp,
2355 (kmflag == KM_SLEEP ? nv_alloc_sleep : nv_alloc_nosleep)));
2357 return (nvlist_xunpack(buf, buflen, nvlp, nv_alloc_nosleep));
2362 nvlist_xunpack(char *buf, size_t buflen, nvlist_t **nvlp, nv_alloc_t *nva)
2370 if ((err = nvlist_xalloc(&nvl, 0, nva)) != 0)
2373 if ((err = nvlist_common(nvl, buf, &buflen, 0, NVS_OP_DECODE)) != 0)
2382 * Native encoding functions
2386 * This structure is used when decoding a packed nvpair in
2387 * the native format. n_base points to a buffer containing the
2388 * packed nvpair. n_end is a pointer to the end of the buffer.
2389 * (n_end actually points to the first byte past the end of the
2390 * buffer.) n_curr is a pointer that lies between n_base and n_end.
2391 * It points to the current data that we are decoding.
2392 * The amount of data left in the buffer is equal to n_end - n_curr.
2393 * n_flag is used to recognize a packed embedded list.
2402 nvs_native_create(nvstream_t *nvs, nvs_native_t *native, char *buf,
2405 switch (nvs->nvs_op) {
2408 nvs->nvs_private = native;
2409 native->n_curr = native->n_base = buf;
2410 native->n_end = buf + buflen;
2414 case NVS_OP_GETSIZE:
2415 nvs->nvs_private = native;
2416 native->n_curr = native->n_base = native->n_end = NULL;
2426 nvs_native_destroy(nvstream_t *nvs)
2431 native_cp(nvstream_t *nvs, void *buf, size_t size)
2433 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2435 if (native->n_curr + size > native->n_end)
2439 * The bcopy() below eliminates alignment requirement
2440 * on the buffer (stream) and is preferred over direct access.
2442 switch (nvs->nvs_op) {
2444 bcopy(buf, native->n_curr, size);
2447 bcopy(native->n_curr, buf, size);
2453 native->n_curr += size;
2458 * operate on nvlist_t header
2461 nvs_native_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2463 nvs_native_t *native = nvs->nvs_private;
2465 switch (nvs->nvs_op) {
2469 return (0); /* packed embedded list */
2473 /* copy version and nvflag of the nvlist_t */
2474 if (native_cp(nvs, &nvl->nvl_version, sizeof (int32_t)) != 0 ||
2475 native_cp(nvs, &nvl->nvl_nvflag, sizeof (int32_t)) != 0)
2480 case NVS_OP_GETSIZE:
2482 * if calculate for packed embedded list
2483 * 4 for end of the embedded list
2485 * 2 * sizeof (int32_t) for nvl_version and nvl_nvflag
2486 * and 4 for end of the entire list
2488 if (native->n_flag) {
2492 *size += 2 * sizeof (int32_t) + 4;
2503 nvs_native_nvl_fini(nvstream_t *nvs)
2505 if (nvs->nvs_op == NVS_OP_ENCODE) {
2506 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2508 * Add 4 zero bytes at end of nvlist. They are used
2509 * for end detection by the decode routine.
2511 if (native->n_curr + sizeof (int) > native->n_end)
2514 bzero(native->n_curr, sizeof (int));
2515 native->n_curr += sizeof (int);
2522 nvpair_native_embedded(nvstream_t *nvs, nvpair_t *nvp)
2524 if (nvs->nvs_op == NVS_OP_ENCODE) {
2525 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2526 char *packed = (void *)
2527 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2529 * Null out the pointer that is meaningless in the packed
2530 * structure. The address may not be aligned, so we have
2533 bzero(packed + offsetof(nvlist_t, nvl_priv),
2534 sizeof(((nvlist_t *)NULL)->nvl_priv));
2537 return (nvs_embedded(nvs, EMBEDDED_NVL(nvp)));
2541 nvpair_native_embedded_array(nvstream_t *nvs, nvpair_t *nvp)
2543 if (nvs->nvs_op == NVS_OP_ENCODE) {
2544 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2545 char *value = native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp);
2546 size_t len = NVP_NELEM(nvp) * sizeof (uint64_t);
2549 * Null out pointers that are meaningless in the packed
2550 * structure. The addresses may not be aligned, so we have
2556 for (i = 0; i < NVP_NELEM(nvp); i++) {
2558 * Null out the pointer that is meaningless in the
2559 * packed structure. The address may not be aligned,
2560 * so we have to use bzero.
2562 bzero(value + offsetof(nvlist_t, nvl_priv),
2563 sizeof(((nvlist_t *)NULL)->nvl_priv));
2564 value += sizeof(nvlist_t);
2568 return (nvs_embedded_nvl_array(nvs, nvp, NULL));
2572 nvpair_native_string_array(nvstream_t *nvs, nvpair_t *nvp)
2574 switch (nvs->nvs_op) {
2575 case NVS_OP_ENCODE: {
2576 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2577 uint64_t *strp = (void *)
2578 (native->n_curr - nvp->nvp_size + NVP_VALOFF(nvp));
2580 * Null out pointers that are meaningless in the packed
2581 * structure. The addresses may not be aligned, so we have
2584 bzero(strp, NVP_NELEM(nvp) * sizeof (uint64_t));
2587 case NVS_OP_DECODE: {
2588 char **strp = (void *)NVP_VALUE(nvp);
2589 char *buf = ((char *)strp + NVP_NELEM(nvp) * sizeof (uint64_t));
2592 for (i = 0; i < NVP_NELEM(nvp); i++) {
2594 buf += strlen(buf) + 1;
2602 nvs_native_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2609 * We do the initial bcopy of the data before we look at
2610 * the nvpair type, because when we're decoding, we won't
2611 * have the correct values for the pair until we do the bcopy.
2613 switch (nvs->nvs_op) {
2616 if (native_cp(nvs, nvp, nvp->nvp_size) != 0)
2623 /* verify nvp_name_sz, check the name string length */
2624 if (i_validate_nvpair_name(nvp) != 0)
2627 type = NVP_TYPE(nvp);
2630 * Verify type and nelem and get the value size.
2631 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2632 * is the size of the string(s) excluded.
2634 if ((value_sz = i_get_value_size(type, NULL, NVP_NELEM(nvp))) < 0)
2637 if (NVP_SIZE_CALC(nvp->nvp_name_sz, value_sz) > nvp->nvp_size)
2641 case DATA_TYPE_NVLIST:
2642 ret = nvpair_native_embedded(nvs, nvp);
2644 case DATA_TYPE_NVLIST_ARRAY:
2645 ret = nvpair_native_embedded_array(nvs, nvp);
2647 case DATA_TYPE_STRING_ARRAY:
2648 nvpair_native_string_array(nvs, nvp);
2658 nvs_native_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2660 uint64_t nvp_sz = nvp->nvp_size;
2662 switch (NVP_TYPE(nvp)) {
2663 case DATA_TYPE_NVLIST: {
2666 if (nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize) != 0)
2672 case DATA_TYPE_NVLIST_ARRAY: {
2675 if (nvs_embedded_nvl_array(nvs, nvp, &nvsize) != 0)
2685 if (nvp_sz > INT32_MAX)
2694 nvs_native_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
2696 switch (nvs->nvs_op) {
2698 return (nvs_native_nvp_op(nvs, nvp));
2700 case NVS_OP_DECODE: {
2701 nvs_native_t *native = (nvs_native_t *)nvs->nvs_private;
2704 /* try to read the size value from the stream */
2705 if (native->n_curr + sizeof (int32_t) > native->n_end)
2707 bcopy(native->n_curr, &decode_len, sizeof (int32_t));
2709 /* sanity check the size value */
2710 if (decode_len < 0 ||
2711 decode_len > native->n_end - native->n_curr)
2717 * If at the end of the stream then move the cursor
2718 * forward, otherwise nvpair_native_op() will read
2719 * the entire nvpair at the same cursor position.
2722 native->n_curr += sizeof (int32_t);
2733 static const nvs_ops_t nvs_native_ops = {
2737 nvs_native_nvp_size,
2742 nvs_native(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
2744 nvs_native_t native;
2747 nvs->nvs_ops = &nvs_native_ops;
2749 if ((err = nvs_native_create(nvs, &native, buf + sizeof (nvs_header_t),
2750 *buflen - sizeof (nvs_header_t))) != 0)
2753 err = nvs_operation(nvs, nvl, buflen);
2755 nvs_native_destroy(nvs);
2761 * XDR encoding functions
2763 * An xdr packed nvlist is encoded as:
2765 * - encoding methode and host endian (4 bytes)
2766 * - nvl_version (4 bytes)
2767 * - nvl_nvflag (4 bytes)
2769 * - encoded nvpairs, the format of one xdr encoded nvpair is:
2770 * - encoded size of the nvpair (4 bytes)
2771 * - decoded size of the nvpair (4 bytes)
2772 * - name string, (4 + sizeof(NV_ALIGN4(string))
2773 * a string is coded as size (4 bytes) and data
2774 * - data type (4 bytes)
2775 * - number of elements in the nvpair (4 bytes)
2778 * - 2 zero's for end of the entire list (8 bytes)
2781 nvs_xdr_create(nvstream_t *nvs, XDR *xdr, char *buf, size_t buflen)
2783 /* xdr data must be 4 byte aligned */
2784 if ((ulong_t)buf % 4 != 0)
2787 switch (nvs->nvs_op) {
2789 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_ENCODE);
2790 nvs->nvs_private = xdr;
2793 xdrmem_create(xdr, buf, (uint_t)buflen, XDR_DECODE);
2794 nvs->nvs_private = xdr;
2796 case NVS_OP_GETSIZE:
2797 nvs->nvs_private = NULL;
2805 nvs_xdr_destroy(nvstream_t *nvs)
2807 switch (nvs->nvs_op) {
2810 xdr_destroy((XDR *)nvs->nvs_private);
2818 nvs_xdr_nvlist(nvstream_t *nvs, nvlist_t *nvl, size_t *size)
2820 switch (nvs->nvs_op) {
2822 case NVS_OP_DECODE: {
2823 XDR *xdr = nvs->nvs_private;
2825 if (!xdr_int(xdr, &nvl->nvl_version) ||
2826 !xdr_u_int(xdr, &nvl->nvl_nvflag))
2830 case NVS_OP_GETSIZE: {
2832 * 2 * 4 for nvl_version + nvl_nvflag
2833 * and 8 for end of the entire list
2845 nvs_xdr_nvl_fini(nvstream_t *nvs)
2847 if (nvs->nvs_op == NVS_OP_ENCODE) {
2848 XDR *xdr = nvs->nvs_private;
2851 if (!xdr_int(xdr, &zero) || !xdr_int(xdr, &zero))
2859 * The format of xdr encoded nvpair is:
2860 * encode_size, decode_size, name string, data type, nelem, data
2863 nvs_xdr_nvp_op(nvstream_t *nvs, nvpair_t *nvp)
2867 char *buf_end = (char *)nvp + nvp->nvp_size;
2869 uint_t nelem, buflen;
2871 XDR *xdr = nvs->nvs_private;
2873 ASSERT(xdr != NULL && nvp != NULL);
2876 if ((buf = NVP_NAME(nvp)) >= buf_end)
2878 buflen = buf_end - buf;
2880 if (!xdr_string(xdr, &buf, buflen - 1))
2882 nvp->nvp_name_sz = strlen(buf) + 1;
2884 /* type and nelem */
2885 if (!xdr_int(xdr, (int *)&nvp->nvp_type) ||
2886 !xdr_int(xdr, &nvp->nvp_value_elem))
2889 type = NVP_TYPE(nvp);
2890 nelem = nvp->nvp_value_elem;
2893 * Verify type and nelem and get the value size.
2894 * In case of data types DATA_TYPE_STRING and DATA_TYPE_STRING_ARRAY
2895 * is the size of the string(s) excluded.
2897 if ((value_sz = i_get_value_size(type, NULL, nelem)) < 0)
2900 /* if there is no data to extract then return */
2905 if ((buf = NVP_VALUE(nvp)) >= buf_end)
2907 buflen = buf_end - buf;
2909 if (buflen < value_sz)
2913 case DATA_TYPE_NVLIST:
2914 if (nvs_embedded(nvs, (void *)buf) == 0)
2918 case DATA_TYPE_NVLIST_ARRAY:
2919 if (nvs_embedded_nvl_array(nvs, nvp, NULL) == 0)
2923 case DATA_TYPE_BOOLEAN:
2927 case DATA_TYPE_BYTE:
2928 case DATA_TYPE_INT8:
2929 case DATA_TYPE_UINT8:
2930 ret = xdr_char(xdr, buf);
2933 case DATA_TYPE_INT16:
2934 ret = xdr_short(xdr, (void *)buf);
2937 case DATA_TYPE_UINT16:
2938 ret = xdr_u_short(xdr, (void *)buf);
2941 case DATA_TYPE_BOOLEAN_VALUE:
2942 case DATA_TYPE_INT32:
2943 ret = xdr_int(xdr, (void *)buf);
2946 case DATA_TYPE_UINT32:
2947 ret = xdr_u_int(xdr, (void *)buf);
2950 case DATA_TYPE_INT64:
2951 ret = xdr_longlong_t(xdr, (void *)buf);
2954 case DATA_TYPE_UINT64:
2955 ret = xdr_u_longlong_t(xdr, (void *)buf);
2958 case DATA_TYPE_HRTIME:
2960 * NOTE: must expose the definition of hrtime_t here
2962 ret = xdr_longlong_t(xdr, (void *)buf);
2964 #if !defined(_KERNEL)
2965 case DATA_TYPE_DOUBLE:
2966 ret = xdr_double(xdr, (void *)buf);
2969 case DATA_TYPE_STRING:
2970 ret = xdr_string(xdr, &buf, buflen - 1);
2973 case DATA_TYPE_BYTE_ARRAY:
2974 ret = xdr_opaque(xdr, buf, nelem);
2977 case DATA_TYPE_INT8_ARRAY:
2978 case DATA_TYPE_UINT8_ARRAY:
2979 ret = xdr_array(xdr, &buf, &nelem, buflen, sizeof (int8_t),
2980 (xdrproc_t)xdr_char);
2983 case DATA_TYPE_INT16_ARRAY:
2984 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int16_t),
2985 sizeof (int16_t), (xdrproc_t)xdr_short);
2988 case DATA_TYPE_UINT16_ARRAY:
2989 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint16_t),
2990 sizeof (uint16_t), (xdrproc_t)xdr_u_short);
2993 case DATA_TYPE_BOOLEAN_ARRAY:
2994 case DATA_TYPE_INT32_ARRAY:
2995 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int32_t),
2996 sizeof (int32_t), (xdrproc_t)xdr_int);
2999 case DATA_TYPE_UINT32_ARRAY:
3000 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint32_t),
3001 sizeof (uint32_t), (xdrproc_t)xdr_u_int);
3004 case DATA_TYPE_INT64_ARRAY:
3005 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (int64_t),
3006 sizeof (int64_t), (xdrproc_t)xdr_longlong_t);
3009 case DATA_TYPE_UINT64_ARRAY:
3010 ret = xdr_array(xdr, &buf, &nelem, buflen / sizeof (uint64_t),
3011 sizeof (uint64_t), (xdrproc_t)xdr_u_longlong_t);
3014 case DATA_TYPE_STRING_ARRAY: {
3015 size_t len = nelem * sizeof (uint64_t);
3016 char **strp = (void *)buf;
3019 if (nvs->nvs_op == NVS_OP_DECODE)
3020 bzero(buf, len); /* don't trust packed data */
3022 for (i = 0; i < nelem; i++) {
3029 if (xdr_string(xdr, &buf, buflen - 1) != TRUE)
3032 if (nvs->nvs_op == NVS_OP_DECODE)
3034 len = strlen(buf) + 1;
3043 return (ret == TRUE ? 0 : EFAULT);
3047 nvs_xdr_nvp_size(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3049 data_type_t type = NVP_TYPE(nvp);
3051 * encode_size + decode_size + name string size + data type + nelem
3052 * where name string size = 4 + NV_ALIGN4(strlen(NVP_NAME(nvp)))
3054 uint64_t nvp_sz = 4 + 4 + 4 + NV_ALIGN4(strlen(NVP_NAME(nvp))) + 4 + 4;
3057 case DATA_TYPE_BOOLEAN:
3060 case DATA_TYPE_BOOLEAN_VALUE:
3061 case DATA_TYPE_BYTE:
3062 case DATA_TYPE_INT8:
3063 case DATA_TYPE_UINT8:
3064 case DATA_TYPE_INT16:
3065 case DATA_TYPE_UINT16:
3066 case DATA_TYPE_INT32:
3067 case DATA_TYPE_UINT32:
3068 nvp_sz += 4; /* 4 is the minimum xdr unit */
3071 case DATA_TYPE_INT64:
3072 case DATA_TYPE_UINT64:
3073 case DATA_TYPE_HRTIME:
3074 #if !defined(_KERNEL)
3075 case DATA_TYPE_DOUBLE:
3080 case DATA_TYPE_STRING:
3081 nvp_sz += 4 + NV_ALIGN4(strlen((char *)NVP_VALUE(nvp)));
3084 case DATA_TYPE_BYTE_ARRAY:
3085 nvp_sz += NV_ALIGN4(NVP_NELEM(nvp));
3088 case DATA_TYPE_BOOLEAN_ARRAY:
3089 case DATA_TYPE_INT8_ARRAY:
3090 case DATA_TYPE_UINT8_ARRAY:
3091 case DATA_TYPE_INT16_ARRAY:
3092 case DATA_TYPE_UINT16_ARRAY:
3093 case DATA_TYPE_INT32_ARRAY:
3094 case DATA_TYPE_UINT32_ARRAY:
3095 nvp_sz += 4 + 4 * (uint64_t)NVP_NELEM(nvp);
3098 case DATA_TYPE_INT64_ARRAY:
3099 case DATA_TYPE_UINT64_ARRAY:
3100 nvp_sz += 4 + 8 * (uint64_t)NVP_NELEM(nvp);
3103 case DATA_TYPE_STRING_ARRAY: {
3105 char **strs = (void *)NVP_VALUE(nvp);
3107 for (i = 0; i < NVP_NELEM(nvp); i++)
3108 nvp_sz += 4 + NV_ALIGN4(strlen(strs[i]));
3113 case DATA_TYPE_NVLIST:
3114 case DATA_TYPE_NVLIST_ARRAY: {
3116 int old_nvs_op = nvs->nvs_op;
3119 nvs->nvs_op = NVS_OP_GETSIZE;
3120 if (type == DATA_TYPE_NVLIST)
3121 err = nvs_operation(nvs, EMBEDDED_NVL(nvp), &nvsize);
3123 err = nvs_embedded_nvl_array(nvs, nvp, &nvsize);
3124 nvs->nvs_op = old_nvs_op;
3137 if (nvp_sz > INT32_MAX)
3147 * The NVS_XDR_MAX_LEN macro takes a packed xdr buffer of size x and estimates
3148 * the largest nvpair that could be encoded in the buffer.
3150 * See comments above nvpair_xdr_op() for the format of xdr encoding.
3151 * The size of a xdr packed nvpair without any data is 5 words.
3153 * Using the size of the data directly as an estimate would be ok
3154 * in all cases except one. If the data type is of DATA_TYPE_STRING_ARRAY
3155 * then the actual nvpair has space for an array of pointers to index
3156 * the strings. These pointers are not encoded into the packed xdr buffer.
3158 * If the data is of type DATA_TYPE_STRING_ARRAY and all the strings are
3159 * of length 0, then each string is endcoded in xdr format as a single word.
3160 * Therefore when expanded to an nvpair there will be 2.25 word used for
3161 * each string. (a int64_t allocated for pointer usage, and a single char
3162 * for the null termination.)
3164 * This is the calculation performed by the NVS_XDR_MAX_LEN macro.
3166 #define NVS_XDR_HDR_LEN ((size_t)(5 * 4))
3167 #define NVS_XDR_DATA_LEN(y) (((size_t)(y) <= NVS_XDR_HDR_LEN) ? \
3168 0 : ((size_t)(y) - NVS_XDR_HDR_LEN))
3169 #define NVS_XDR_MAX_LEN(x) (NVP_SIZE_CALC(1, 0) + \
3170 (NVS_XDR_DATA_LEN(x) * 2) + \
3171 NV_ALIGN4((NVS_XDR_DATA_LEN(x) / 4)))
3174 nvs_xdr_nvpair(nvstream_t *nvs, nvpair_t *nvp, size_t *size)
3176 XDR *xdr = nvs->nvs_private;
3177 int32_t encode_len, decode_len;
3179 switch (nvs->nvs_op) {
3180 case NVS_OP_ENCODE: {
3183 if (nvs_xdr_nvp_size(nvs, nvp, &nvsize) != 0)
3186 decode_len = nvp->nvp_size;
3187 encode_len = nvsize;
3188 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3191 return (nvs_xdr_nvp_op(nvs, nvp));
3193 case NVS_OP_DECODE: {
3194 struct xdr_bytesrec bytesrec;
3196 /* get the encode and decode size */
3197 if (!xdr_int(xdr, &encode_len) || !xdr_int(xdr, &decode_len))
3201 /* are we at the end of the stream? */
3205 /* sanity check the size parameter */
3206 if (!xdr_control(xdr, XDR_GET_BYTES_AVAIL, &bytesrec))
3209 if (*size > NVS_XDR_MAX_LEN(bytesrec.xc_num_avail))
3220 static const struct nvs_ops nvs_xdr_ops = {
3229 nvs_xdr(nvstream_t *nvs, nvlist_t *nvl, char *buf, size_t *buflen)
3234 nvs->nvs_ops = &nvs_xdr_ops;
3236 if ((err = nvs_xdr_create(nvs, &xdr, buf + sizeof (nvs_header_t),
3237 *buflen - sizeof (nvs_header_t))) != 0)
3240 err = nvs_operation(nvs, nvl, buflen);
3242 nvs_xdr_destroy(nvs);