Home | History | Annotate | Line # | Download | only in dist
      1  1.11  riastrad /*	$NetBSD: nvlist.c,v 1.11 2024/09/11 15:01:11 riastradh Exp $	*/
      2   1.2  christos 
      3   1.1  christos /*-
      4   1.1  christos  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
      5   1.1  christos  *
      6   1.1  christos  * Copyright (c) 2009-2013 The FreeBSD Foundation
      7   1.1  christos  * Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo (at) FreeBSD.org>
      8   1.1  christos  * All rights reserved.
      9   1.1  christos  *
     10   1.1  christos  * This software was developed by Pawel Jakub Dawidek under sponsorship from
     11   1.1  christos  * the FreeBSD Foundation.
     12   1.1  christos  *
     13   1.1  christos  * Redistribution and use in source and binary forms, with or without
     14   1.1  christos  * modification, are permitted provided that the following conditions
     15   1.1  christos  * are met:
     16   1.1  christos  * 1. Redistributions of source code must retain the above copyright
     17   1.1  christos  *    notice, this list of conditions and the following disclaimer.
     18   1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     19   1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     20   1.1  christos  *    documentation and/or other materials provided with the distribution.
     21   1.1  christos  *
     22   1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
     23   1.1  christos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24   1.1  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25   1.1  christos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
     26   1.1  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27   1.1  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28   1.1  christos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29   1.1  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30   1.1  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31   1.1  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32   1.1  christos  * SUCH DAMAGE.
     33   1.1  christos  */
     34   1.1  christos 
     35   1.1  christos #include <sys/cdefs.h>
     36   1.2  christos #ifdef __FreeBSD__
     37   1.1  christos __FBSDID("$FreeBSD: head/sys/contrib/libnv/nvlist.c 335347 2018-06-18 22:57:32Z oshogbo $");
     38   1.2  christos #else
     39  1.11  riastrad __RCSID("$NetBSD: nvlist.c,v 1.11 2024/09/11 15:01:11 riastradh Exp $");
     40   1.2  christos #endif
     41   1.1  christos 
     42   1.1  christos #include <sys/param.h>
     43   1.1  christos #include <sys/endian.h>
     44   1.1  christos #include <sys/queue.h>
     45   1.1  christos 
     46   1.2  christos #if defined(_KERNEL) || defined(_STANDALONE)
     47   1.1  christos 
     48   1.1  christos #include <sys/errno.h>
     49   1.1  christos #include <sys/kernel.h>
     50   1.1  christos #include <sys/lock.h>
     51   1.1  christos #include <sys/malloc.h>
     52   1.1  christos #include <sys/systm.h>
     53   1.1  christos 
     54   1.2  christos #ifdef __FreeBSD__
     55   1.1  christos #include <machine/stdarg.h>
     56   1.2  christos #endif
     57   1.1  christos 
     58   1.1  christos #else
     59   1.1  christos #include <sys/socket.h>
     60   1.1  christos 
     61   1.1  christos #include <errno.h>
     62   1.1  christos #include <stdarg.h>
     63   1.1  christos #include <stdbool.h>
     64   1.1  christos #include <stdint.h>
     65   1.1  christos #include <stdio.h>
     66   1.1  christos #include <stdlib.h>
     67   1.1  christos #include <string.h>
     68   1.1  christos #include <unistd.h>
     69   1.1  christos 
     70   1.1  christos #include "msgio.h"
     71   1.1  christos #endif
     72   1.1  christos 
     73   1.1  christos #ifdef HAVE_PJDLOG
     74   1.1  christos #include <pjdlog.h>
     75   1.1  christos #endif
     76   1.1  christos 
     77   1.2  christos #ifdef __FreeBSD__
     78   1.1  christos #include <sys/nv.h>
     79   1.2  christos #else
     80   1.3  christos #include "nv.h"
     81   1.2  christos #endif
     82   1.1  christos 
     83   1.1  christos #include "nv_impl.h"
     84   1.1  christos #include "nvlist_impl.h"
     85   1.1  christos #include "nvpair_impl.h"
     86   1.1  christos 
     87   1.1  christos #ifndef	HAVE_PJDLOG
     88   1.2  christos #if defined(_KERNEL) || defined(_STANDALONE)
     89   1.2  christos #ifdef __FreeBSD__
     90   1.1  christos #define	PJDLOG_ASSERT(...)		MPASS(__VA_ARGS__)
     91   1.2  christos #else
     92   1.2  christos #define	PJDLOG_ASSERT(...)		KASSERT(__VA_ARGS__)
     93   1.2  christos #endif
     94   1.1  christos #define	PJDLOG_RASSERT(expr, ...)	KASSERT(expr, (__VA_ARGS__))
     95   1.1  christos #define	PJDLOG_ABORT(...)		panic(__VA_ARGS__)
     96   1.1  christos #else
     97   1.2  christos #ifndef __lint__
     98   1.1  christos #include <assert.h>
     99   1.1  christos #define	PJDLOG_ASSERT(...)		assert(__VA_ARGS__)
    100   1.1  christos #define	PJDLOG_RASSERT(expr, ...)	assert(expr)
    101   1.1  christos #define	PJDLOG_ABORT(...)		do {				\
    102   1.1  christos 	fprintf(stderr, "%s:%u: ", __FILE__, __LINE__);			\
    103   1.1  christos 	fprintf(stderr, __VA_ARGS__);					\
    104   1.1  christos 	fprintf(stderr, "\n");						\
    105   1.1  christos 	abort();							\
    106   1.2  christos } while (/*CONSTCOND*/0)
    107   1.2  christos #else
    108   1.2  christos #define	PJDLOG_ASSERT(...)
    109   1.2  christos #define	PJDLOG_RASSERT(expr, ...)
    110   1.2  christos #define	PJDLOG_ABORT(...)
    111   1.2  christos #endif
    112   1.1  christos #endif
    113   1.1  christos #endif
    114   1.1  christos 
    115   1.1  christos #define	NV_FLAG_PRIVATE_MASK	(NV_FLAG_BIG_ENDIAN | NV_FLAG_IN_ARRAY)
    116   1.1  christos #define	NV_FLAG_PUBLIC_MASK	(NV_FLAG_IGNORE_CASE | NV_FLAG_NO_UNIQUE)
    117   1.1  christos #define	NV_FLAG_ALL_MASK	(NV_FLAG_PRIVATE_MASK | NV_FLAG_PUBLIC_MASK)
    118   1.1  christos 
    119   1.1  christos #define	NVLIST_MAGIC	0x6e766c	/* "nvl" */
    120   1.1  christos struct nvlist {
    121   1.1  christos 	int		 nvl_magic;
    122   1.1  christos 	int		 nvl_error;
    123   1.1  christos 	int		 nvl_flags;
    124   1.1  christos 	nvpair_t	*nvl_parent;
    125   1.1  christos 	nvpair_t	*nvl_array_next;
    126   1.1  christos 	struct nvl_head	 nvl_head;
    127   1.1  christos };
    128   1.1  christos 
    129   1.1  christos #define	NVLIST_ASSERT(nvl)	do {					\
    130   1.1  christos 	PJDLOG_ASSERT((nvl) != NULL);					\
    131   1.1  christos 	PJDLOG_ASSERT((nvl)->nvl_magic == NVLIST_MAGIC);		\
    132   1.2  christos } while (/*CONSTCOND*/0)
    133   1.1  christos 
    134   1.1  christos #ifdef _KERNEL
    135   1.1  christos MALLOC_DEFINE(M_NVLIST, "nvlist", "kernel nvlist");
    136   1.1  christos #endif
    137   1.1  christos 
    138   1.1  christos #define	NVPAIR_ASSERT(nvp)	nvpair_assert(nvp)
    139   1.1  christos 
    140   1.1  christos #define	NVLIST_HEADER_MAGIC	0x6c
    141   1.1  christos #define	NVLIST_HEADER_VERSION	0x00
    142   1.1  christos struct nvlist_header {
    143   1.1  christos 	uint8_t		nvlh_magic;
    144   1.1  christos 	uint8_t		nvlh_version;
    145   1.1  christos 	uint8_t		nvlh_flags;
    146   1.1  christos 	uint64_t	nvlh_descriptors;
    147   1.1  christos 	uint64_t	nvlh_size;
    148   1.1  christos } __packed;
    149   1.1  christos 
    150   1.1  christos nvlist_t *
    151   1.1  christos nvlist_create(int flags)
    152   1.1  christos {
    153   1.1  christos 	nvlist_t *nvl;
    154   1.1  christos 
    155   1.1  christos 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
    156   1.1  christos 
    157   1.1  christos 	nvl = nv_malloc(sizeof(*nvl));
    158   1.1  christos 	if (nvl == NULL)
    159   1.1  christos 		return (NULL);
    160   1.1  christos 	nvl->nvl_error = 0;
    161   1.1  christos 	nvl->nvl_flags = flags;
    162   1.1  christos 	nvl->nvl_parent = NULL;
    163   1.1  christos 	nvl->nvl_array_next = NULL;
    164   1.1  christos 	TAILQ_INIT(&nvl->nvl_head);
    165   1.1  christos 	nvl->nvl_magic = NVLIST_MAGIC;
    166   1.1  christos 
    167   1.1  christos 	return (nvl);
    168   1.1  christos }
    169   1.1  christos 
    170   1.1  christos void
    171   1.1  christos nvlist_destroy(nvlist_t *nvl)
    172   1.1  christos {
    173   1.1  christos 	nvpair_t *nvp;
    174   1.1  christos 
    175   1.1  christos 	if (nvl == NULL)
    176   1.1  christos 		return;
    177   1.1  christos 
    178   1.1  christos 	ERRNO_SAVE();
    179   1.1  christos 
    180   1.1  christos 	NVLIST_ASSERT(nvl);
    181   1.1  christos 
    182   1.1  christos 	while ((nvp = nvlist_first_nvpair(nvl)) != NULL) {
    183   1.1  christos 		nvlist_remove_nvpair(nvl, nvp);
    184   1.1  christos 		nvpair_free(nvp);
    185   1.1  christos 	}
    186   1.1  christos 	if (nvl->nvl_array_next != NULL)
    187   1.1  christos 		nvpair_free_structure(nvl->nvl_array_next);
    188   1.1  christos 	nvl->nvl_array_next = NULL;
    189   1.1  christos 	nvl->nvl_parent = NULL;
    190   1.1  christos 	nvl->nvl_magic = 0;
    191   1.1  christos 	nv_free(nvl);
    192   1.1  christos 
    193   1.1  christos 	ERRNO_RESTORE();
    194   1.1  christos }
    195   1.1  christos 
    196   1.1  christos void
    197   1.1  christos nvlist_set_error(nvlist_t *nvl, int error)
    198   1.1  christos {
    199   1.1  christos 
    200   1.1  christos 	PJDLOG_ASSERT(error != 0);
    201   1.1  christos 
    202   1.1  christos 	/*
    203   1.1  christos 	 * Check for error != 0 so that we don't do the wrong thing if somebody
    204   1.1  christos 	 * tries to abuse this API when asserts are disabled.
    205   1.1  christos 	 */
    206   1.1  christos 	if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
    207   1.1  christos 		nvl->nvl_error = error;
    208   1.1  christos }
    209   1.1  christos 
    210   1.1  christos int
    211   1.1  christos nvlist_error(const nvlist_t *nvl)
    212   1.1  christos {
    213   1.1  christos 
    214   1.1  christos 	if (nvl == NULL)
    215   1.1  christos 		return (ENOMEM);
    216   1.1  christos 
    217   1.1  christos 	NVLIST_ASSERT(nvl);
    218   1.1  christos 
    219   1.1  christos 	return (nvl->nvl_error);
    220   1.1  christos }
    221   1.1  christos 
    222   1.1  christos nvpair_t *
    223   1.1  christos nvlist_get_nvpair_parent(const nvlist_t *nvl)
    224   1.1  christos {
    225   1.1  christos 
    226   1.1  christos 	NVLIST_ASSERT(nvl);
    227   1.1  christos 
    228   1.1  christos 	return (nvl->nvl_parent);
    229   1.1  christos }
    230   1.1  christos 
    231   1.1  christos const nvlist_t *
    232   1.1  christos nvlist_get_parent(const nvlist_t *nvl, void **cookiep)
    233   1.1  christos {
    234   1.1  christos 	nvpair_t *nvp;
    235   1.1  christos 
    236   1.1  christos 	NVLIST_ASSERT(nvl);
    237   1.1  christos 
    238   1.1  christos 	nvp = nvl->nvl_parent;
    239   1.1  christos 	if (cookiep != NULL)
    240   1.1  christos 		*cookiep = nvp;
    241   1.1  christos 	if (nvp == NULL)
    242   1.1  christos 		return (NULL);
    243   1.1  christos 
    244   1.1  christos 	return (nvpair_nvlist(nvp));
    245   1.1  christos }
    246   1.1  christos 
    247   1.1  christos void
    248   1.1  christos nvlist_set_parent(nvlist_t *nvl, nvpair_t *parent)
    249   1.1  christos {
    250   1.1  christos 
    251   1.1  christos 	NVLIST_ASSERT(nvl);
    252   1.1  christos 
    253   1.1  christos 	nvl->nvl_parent = parent;
    254   1.1  christos }
    255   1.1  christos 
    256   1.1  christos void
    257   1.1  christos nvlist_set_array_next(nvlist_t *nvl, nvpair_t *ele)
    258   1.1  christos {
    259   1.1  christos 
    260   1.1  christos 	NVLIST_ASSERT(nvl);
    261   1.1  christos 
    262   1.1  christos 	if (ele != NULL) {
    263   1.1  christos 		nvl->nvl_flags |= NV_FLAG_IN_ARRAY;
    264   1.1  christos 	} else {
    265   1.1  christos 		nvl->nvl_flags &= ~NV_FLAG_IN_ARRAY;
    266   1.1  christos 		nv_free(nvl->nvl_array_next);
    267   1.1  christos 	}
    268   1.1  christos 
    269   1.1  christos 	nvl->nvl_array_next = ele;
    270   1.1  christos }
    271   1.1  christos 
    272   1.7     rmind nvpair_t *
    273   1.7     rmind nvlist_get_array_next_nvpair(nvlist_t *nvl)
    274   1.7     rmind {
    275   1.7     rmind 
    276   1.7     rmind 	NVLIST_ASSERT(nvl);
    277   1.7     rmind 
    278   1.7     rmind 	return (nvl->nvl_array_next);
    279   1.7     rmind }
    280   1.7     rmind 
    281   1.1  christos bool
    282   1.1  christos nvlist_in_array(const nvlist_t *nvl)
    283   1.1  christos {
    284   1.1  christos 
    285   1.1  christos 	NVLIST_ASSERT(nvl);
    286   1.1  christos 
    287   1.1  christos 	return ((nvl->nvl_flags & NV_FLAG_IN_ARRAY) != 0);
    288   1.1  christos }
    289   1.1  christos 
    290   1.1  christos const nvlist_t *
    291   1.1  christos nvlist_get_array_next(const nvlist_t *nvl)
    292   1.1  christos {
    293   1.1  christos 	nvpair_t *nvp;
    294   1.1  christos 
    295   1.1  christos 	NVLIST_ASSERT(nvl);
    296   1.1  christos 
    297   1.1  christos 	nvp = nvl->nvl_array_next;
    298   1.1  christos 	if (nvp == NULL)
    299   1.1  christos 		return (NULL);
    300   1.1  christos 
    301   1.1  christos 	return (nvpair_get_nvlist(nvp));
    302   1.1  christos }
    303   1.1  christos 
    304   1.1  christos const nvlist_t *
    305   1.1  christos nvlist_get_pararr(const nvlist_t *nvl, void **cookiep)
    306   1.1  christos {
    307   1.1  christos 	const nvlist_t *ret;
    308   1.1  christos 
    309   1.1  christos 	ret = nvlist_get_array_next(nvl);
    310   1.1  christos 	if (ret != NULL) {
    311   1.1  christos 		if (cookiep != NULL)
    312   1.1  christos 			*cookiep = NULL;
    313   1.1  christos 		return (ret);
    314   1.1  christos 	}
    315   1.1  christos 
    316   1.1  christos 	return (nvlist_get_parent(nvl, cookiep));
    317   1.1  christos }
    318   1.1  christos 
    319   1.1  christos bool
    320   1.1  christos nvlist_empty(const nvlist_t *nvl)
    321   1.1  christos {
    322   1.1  christos 
    323   1.1  christos 	NVLIST_ASSERT(nvl);
    324   1.1  christos 	PJDLOG_ASSERT(nvl->nvl_error == 0);
    325   1.1  christos 
    326   1.1  christos 	return (nvlist_first_nvpair(nvl) == NULL);
    327   1.1  christos }
    328   1.1  christos 
    329   1.1  christos int
    330   1.1  christos nvlist_flags(const nvlist_t *nvl)
    331   1.1  christos {
    332   1.1  christos 
    333   1.1  christos 	NVLIST_ASSERT(nvl);
    334   1.1  christos 	PJDLOG_ASSERT(nvl->nvl_error == 0);
    335   1.1  christos 
    336   1.1  christos 	return (nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
    337   1.1  christos }
    338   1.1  christos 
    339   1.1  christos void
    340   1.1  christos nvlist_set_flags(nvlist_t *nvl, int flags)
    341   1.1  christos {
    342   1.1  christos 
    343   1.1  christos 	NVLIST_ASSERT(nvl);
    344   1.1  christos 	PJDLOG_ASSERT(nvl->nvl_error == 0);
    345   1.1  christos 
    346   1.1  christos 	nvl->nvl_flags = flags;
    347   1.1  christos }
    348   1.1  christos 
    349   1.5  christos __dead void
    350   1.1  christos nvlist_report_missing(int type, const char *name)
    351   1.1  christos {
    352   1.1  christos 
    353   1.1  christos 	PJDLOG_ABORT("Element '%s' of type %s doesn't exist.",
    354   1.1  christos 	    name, nvpair_type_string(type));
    355   1.1  christos }
    356   1.1  christos 
    357   1.1  christos static nvpair_t *
    358   1.1  christos nvlist_find(const nvlist_t *nvl, int type, const char *name)
    359   1.1  christos {
    360   1.1  christos 	nvpair_t *nvp;
    361   1.1  christos 
    362   1.1  christos 	NVLIST_ASSERT(nvl);
    363   1.1  christos 	PJDLOG_ASSERT(nvl->nvl_error == 0);
    364   1.1  christos 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
    365   1.1  christos 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
    366   1.1  christos 
    367   1.1  christos 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
    368   1.1  christos 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
    369   1.1  christos 		if (type != NV_TYPE_NONE && nvpair_type(nvp) != type)
    370   1.1  christos 			continue;
    371   1.1  christos 		if ((nvl->nvl_flags & NV_FLAG_IGNORE_CASE) != 0) {
    372   1.1  christos 			if (strcasecmp(nvpair_name(nvp), name) != 0)
    373   1.1  christos 				continue;
    374   1.1  christos 		} else {
    375   1.1  christos 			if (strcmp(nvpair_name(nvp), name) != 0)
    376   1.1  christos 				continue;
    377   1.1  christos 		}
    378   1.1  christos 		break;
    379   1.1  christos 	}
    380   1.1  christos 
    381   1.1  christos 	if (nvp == NULL)
    382   1.1  christos 		ERRNO_SET(ENOENT);
    383   1.1  christos 
    384   1.1  christos 	return (nvp);
    385   1.1  christos }
    386   1.1  christos 
    387   1.1  christos bool
    388   1.1  christos nvlist_exists_type(const nvlist_t *nvl, const char *name, int type)
    389   1.1  christos {
    390   1.1  christos 
    391   1.1  christos 	NVLIST_ASSERT(nvl);
    392   1.1  christos 	PJDLOG_ASSERT(nvl->nvl_error == 0);
    393   1.1  christos 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
    394   1.1  christos 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
    395   1.1  christos 
    396   1.1  christos 	return (nvlist_find(nvl, type, name) != NULL);
    397   1.1  christos }
    398   1.1  christos 
    399   1.1  christos void
    400   1.1  christos nvlist_free_type(nvlist_t *nvl, const char *name, int type)
    401   1.1  christos {
    402   1.1  christos 	nvpair_t *nvp;
    403   1.1  christos 
    404   1.1  christos 	NVLIST_ASSERT(nvl);
    405   1.1  christos 	PJDLOG_ASSERT(nvl->nvl_error == 0);
    406   1.1  christos 	PJDLOG_ASSERT(type == NV_TYPE_NONE ||
    407   1.1  christos 	    (type >= NV_TYPE_FIRST && type <= NV_TYPE_LAST));
    408   1.1  christos 
    409   1.1  christos 	nvp = nvlist_find(nvl, type, name);
    410   1.1  christos 	if (nvp != NULL)
    411   1.1  christos 		nvlist_free_nvpair(nvl, nvp);
    412   1.1  christos 	else
    413   1.1  christos 		nvlist_report_missing(type, name);
    414   1.1  christos }
    415   1.1  christos 
    416   1.1  christos nvlist_t *
    417   1.1  christos nvlist_clone(const nvlist_t *nvl)
    418   1.1  christos {
    419   1.1  christos 	nvlist_t *newnvl;
    420   1.1  christos 	nvpair_t *nvp, *newnvp;
    421   1.1  christos 
    422   1.1  christos 	NVLIST_ASSERT(nvl);
    423   1.1  christos 
    424   1.1  christos 	if (nvl->nvl_error != 0) {
    425   1.1  christos 		ERRNO_SET(nvl->nvl_error);
    426   1.1  christos 		return (NULL);
    427   1.1  christos 	}
    428   1.1  christos 
    429   1.1  christos 	newnvl = nvlist_create(nvl->nvl_flags & NV_FLAG_PUBLIC_MASK);
    430   1.1  christos 	for (nvp = nvlist_first_nvpair(nvl); nvp != NULL;
    431   1.1  christos 	    nvp = nvlist_next_nvpair(nvl, nvp)) {
    432   1.1  christos 		newnvp = nvpair_clone(nvp);
    433   1.1  christos 		if (newnvp == NULL)
    434   1.1  christos 			break;
    435   1.1  christos 		(void)nvlist_move_nvpair(newnvl, newnvp);
    436   1.1  christos 	}
    437   1.1  christos 	if (nvp != NULL) {
    438   1.1  christos 		nvlist_destroy(newnvl);
    439   1.1  christos 		return (NULL);
    440   1.1  christos 	}
    441   1.1  christos 	return (newnvl);
    442   1.1  christos }
    443   1.1  christos 
    444   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
    445   1.1  christos static bool
    446   1.1  christos nvlist_dump_error_check(const nvlist_t *nvl, int fd, int level)
    447   1.1  christos {
    448   1.1  christos 
    449   1.1  christos 	if (nvlist_error(nvl) != 0) {
    450   1.1  christos 		dprintf(fd, "%*serror: %d\n", level * 4, "",
    451   1.1  christos 		    nvlist_error(nvl));
    452   1.1  christos 		return (true);
    453   1.1  christos 	}
    454   1.1  christos 
    455   1.1  christos 	return (false);
    456   1.1  christos }
    457   1.1  christos 
    458   1.1  christos /*
    459   1.1  christos  * Dump content of nvlist.
    460   1.1  christos  */
    461   1.1  christos void
    462   1.1  christos nvlist_dump(const nvlist_t *nvl, int fd)
    463   1.1  christos {
    464   1.1  christos 	const nvlist_t *tmpnvl;
    465   1.1  christos 	nvpair_t *nvp, *tmpnvp;
    466   1.1  christos 	void *cookie;
    467   1.1  christos 	int level;
    468   1.1  christos 
    469   1.1  christos 	level = 0;
    470   1.1  christos 	if (nvlist_dump_error_check(nvl, fd, level))
    471   1.1  christos 		return;
    472   1.1  christos 
    473   1.1  christos 	nvp = nvlist_first_nvpair(nvl);
    474   1.1  christos 	while (nvp != NULL) {
    475   1.1  christos 		dprintf(fd, "%*s%s (%s):", level * 4, "", nvpair_name(nvp),
    476   1.1  christos 		    nvpair_type_string(nvpair_type(nvp)));
    477   1.1  christos 		switch (nvpair_type(nvp)) {
    478   1.1  christos 		case NV_TYPE_NULL:
    479   1.1  christos 			dprintf(fd, " null\n");
    480   1.1  christos 			break;
    481   1.1  christos 		case NV_TYPE_BOOL:
    482   1.1  christos 			dprintf(fd, " %s\n", nvpair_get_bool(nvp) ?
    483   1.1  christos 			    "TRUE" : "FALSE");
    484   1.1  christos 			break;
    485   1.1  christos 		case NV_TYPE_NUMBER:
    486   1.1  christos 			dprintf(fd, " %ju (%jd) (0x%jx)\n",
    487   1.1  christos 			    (uintmax_t)nvpair_get_number(nvp),
    488   1.1  christos 			    (intmax_t)nvpair_get_number(nvp),
    489   1.1  christos 			    (uintmax_t)nvpair_get_number(nvp));
    490   1.1  christos 			break;
    491   1.1  christos 		case NV_TYPE_STRING:
    492   1.1  christos 			dprintf(fd, " [%s]\n", nvpair_get_string(nvp));
    493   1.1  christos 			break;
    494   1.1  christos 		case NV_TYPE_NVLIST:
    495   1.1  christos 			dprintf(fd, "\n");
    496   1.1  christos 			tmpnvl = nvpair_get_nvlist(nvp);
    497   1.1  christos 			if (nvlist_dump_error_check(tmpnvl, fd, level + 1))
    498   1.1  christos 				break;
    499   1.1  christos 			tmpnvp = nvlist_first_nvpair(tmpnvl);
    500   1.1  christos 			if (tmpnvp != NULL) {
    501   1.1  christos 				nvl = tmpnvl;
    502   1.1  christos 				nvp = tmpnvp;
    503   1.1  christos 				level++;
    504   1.1  christos 				continue;
    505   1.1  christos 			}
    506   1.1  christos 			break;
    507   1.1  christos 		case NV_TYPE_DESCRIPTOR:
    508   1.1  christos 			dprintf(fd, " %d\n", nvpair_get_descriptor(nvp));
    509   1.1  christos 			break;
    510   1.1  christos 		case NV_TYPE_BINARY:
    511   1.1  christos 		    {
    512   1.1  christos 			const unsigned char *binary;
    513   1.1  christos 			unsigned int ii;
    514   1.1  christos 			size_t size;
    515   1.1  christos 
    516   1.1  christos 			binary = nvpair_get_binary(nvp, &size);
    517   1.1  christos 			dprintf(fd, " %zu ", size);
    518   1.1  christos 			for (ii = 0; ii < size; ii++)
    519   1.1  christos 				dprintf(fd, "%02hhx", binary[ii]);
    520   1.1  christos 			dprintf(fd, "\n");
    521   1.1  christos 			break;
    522   1.1  christos 		    }
    523   1.1  christos 		case NV_TYPE_BOOL_ARRAY:
    524   1.1  christos 		    {
    525   1.1  christos 			const bool *value;
    526   1.1  christos 			unsigned int ii;
    527   1.1  christos 			size_t nitems;
    528   1.1  christos 
    529   1.1  christos 			value = nvpair_get_bool_array(nvp, &nitems);
    530   1.1  christos 			dprintf(fd, " [ ");
    531   1.1  christos 			for (ii = 0; ii < nitems; ii++) {
    532   1.1  christos 				dprintf(fd, "%s", value[ii] ? "TRUE" : "FALSE");
    533   1.1  christos 				if (ii != nitems - 1)
    534   1.1  christos 					dprintf(fd, ", ");
    535   1.1  christos 			}
    536   1.1  christos 			dprintf(fd, " ]\n");
    537   1.1  christos 			break;
    538   1.1  christos 		    }
    539   1.1  christos 		case NV_TYPE_STRING_ARRAY:
    540   1.1  christos 		    {
    541   1.1  christos 			const char * const *value;
    542   1.1  christos 			unsigned int ii;
    543   1.1  christos 			size_t nitems;
    544   1.1  christos 
    545   1.1  christos 			value = nvpair_get_string_array(nvp, &nitems);
    546   1.1  christos 			dprintf(fd, " [ ");
    547   1.1  christos 			for (ii = 0; ii < nitems; ii++) {
    548   1.1  christos 				if (value[ii] == NULL)
    549   1.1  christos 					dprintf(fd, "NULL");
    550   1.1  christos 				else
    551   1.1  christos 					dprintf(fd, "\"%s\"", value[ii]);
    552   1.1  christos 				if (ii != nitems - 1)
    553   1.1  christos 					dprintf(fd, ", ");
    554   1.1  christos 			}
    555   1.1  christos 			dprintf(fd, " ]\n");
    556   1.1  christos 			break;
    557   1.1  christos 		    }
    558   1.1  christos 		case NV_TYPE_NUMBER_ARRAY:
    559   1.1  christos 		    {
    560   1.1  christos 			const uint64_t *value;
    561   1.1  christos 			unsigned int ii;
    562   1.1  christos 			size_t nitems;
    563   1.1  christos 
    564   1.1  christos 			value = nvpair_get_number_array(nvp, &nitems);
    565   1.1  christos 			dprintf(fd, " [ ");
    566   1.1  christos 			for (ii = 0; ii < nitems; ii++) {
    567   1.1  christos 				dprintf(fd, "%ju (%jd) (0x%jx)",
    568   1.1  christos 				    value[ii], value[ii], value[ii]);
    569   1.1  christos 				if (ii != nitems - 1)
    570   1.1  christos 					dprintf(fd, ", ");
    571   1.1  christos 			}
    572   1.1  christos 			dprintf(fd, " ]\n");
    573   1.1  christos 			break;
    574   1.1  christos 		    }
    575   1.1  christos 		case NV_TYPE_DESCRIPTOR_ARRAY:
    576   1.1  christos 		    {
    577   1.1  christos 			const int *value;
    578   1.1  christos 			unsigned int ii;
    579   1.1  christos 			size_t nitems;
    580   1.1  christos 
    581   1.1  christos 			value = nvpair_get_descriptor_array(nvp, &nitems);
    582   1.1  christos 			dprintf(fd, " [ ");
    583   1.1  christos 			for (ii = 0; ii < nitems; ii++) {
    584   1.1  christos 				dprintf(fd, "%d", value[ii]);
    585   1.1  christos 				if (ii != nitems - 1)
    586   1.1  christos 					dprintf(fd, ", ");
    587   1.1  christos 			}
    588   1.1  christos 			dprintf(fd, " ]\n");
    589   1.1  christos 			break;
    590   1.1  christos 		    }
    591   1.1  christos 		case NV_TYPE_NVLIST_ARRAY:
    592   1.1  christos 		    {
    593   1.1  christos 			const nvlist_t * const *value;
    594   1.1  christos 			unsigned int ii;
    595   1.1  christos 			size_t nitems;
    596   1.1  christos 
    597   1.1  christos 			value = nvpair_get_nvlist_array(nvp, &nitems);
    598   1.1  christos 			dprintf(fd, " %zu\n", nitems);
    599   1.1  christos 			tmpnvl = NULL;
    600   1.1  christos 			tmpnvp = NULL;
    601   1.1  christos 			for (ii = 0; ii < nitems; ii++) {
    602   1.1  christos 				if (nvlist_dump_error_check(value[ii], fd,
    603   1.1  christos 				    level + 1)) {
    604   1.1  christos 					break;
    605   1.1  christos 				}
    606   1.1  christos 
    607   1.1  christos 				if (tmpnvl == NULL) {
    608   1.1  christos 					tmpnvp = nvlist_first_nvpair(value[ii]);
    609   1.1  christos 					if (tmpnvp != NULL) {
    610   1.1  christos 						tmpnvl = value[ii];
    611   1.1  christos 					} else {
    612   1.1  christos 						dprintf(fd, "%*s,\n",
    613   1.1  christos 						    (level + 1) * 4, "");
    614   1.1  christos 					}
    615   1.1  christos 				}
    616   1.1  christos 			}
    617   1.1  christos 			if (tmpnvp != NULL) {
    618   1.1  christos 				nvl = tmpnvl;
    619   1.1  christos 				nvp = tmpnvp;
    620   1.1  christos 				level++;
    621   1.1  christos 				continue;
    622   1.1  christos 			}
    623   1.1  christos 			break;
    624   1.1  christos 		    }
    625   1.1  christos 		default:
    626   1.1  christos 			PJDLOG_ABORT("Unknown type: %d.", nvpair_type(nvp));
    627   1.1  christos 		}
    628   1.1  christos 
    629   1.1  christos 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
    630   1.1  christos 			do {
    631   1.1  christos 				cookie = NULL;
    632   1.1  christos 				if (nvlist_in_array(nvl))
    633   1.1  christos 					dprintf(fd, "%*s,\n", level * 4, "");
    634   1.1  christos 				nvl = nvlist_get_pararr(nvl, &cookie);
    635   1.1  christos 				if (nvl == NULL)
    636   1.1  christos 					return;
    637   1.1  christos 				if (nvlist_in_array(nvl) && cookie == NULL) {
    638   1.1  christos 					nvp = nvlist_first_nvpair(nvl);
    639   1.1  christos 				} else {
    640   1.1  christos 					nvp = cookie;
    641   1.1  christos 					level--;
    642   1.1  christos 				}
    643   1.1  christos 			} while (nvp == NULL);
    644   1.1  christos 			if (nvlist_in_array(nvl) && cookie == NULL)
    645   1.1  christos 				break;
    646   1.1  christos 		}
    647   1.1  christos 	}
    648   1.1  christos }
    649   1.1  christos 
    650   1.1  christos void
    651   1.1  christos nvlist_fdump(const nvlist_t *nvl, FILE *fp)
    652   1.1  christos {
    653   1.1  christos 
    654   1.1  christos 	fflush(fp);
    655   1.1  christos 	nvlist_dump(nvl, fileno(fp));
    656   1.1  christos }
    657   1.1  christos #endif
    658   1.1  christos 
    659   1.1  christos /*
    660   1.1  christos  * The function obtains size of the nvlist after nvlist_pack().
    661   1.1  christos  */
    662   1.1  christos size_t
    663   1.1  christos nvlist_size(const nvlist_t *nvl)
    664   1.1  christos {
    665   1.1  christos 	const nvlist_t *tmpnvl;
    666   1.1  christos 	const nvlist_t * const *nvlarray;
    667   1.1  christos 	const nvpair_t *nvp, *tmpnvp;
    668   1.1  christos 	void *cookie;
    669   1.1  christos 	size_t size, nitems;
    670   1.1  christos 	unsigned int ii;
    671   1.1  christos 
    672   1.1  christos 	NVLIST_ASSERT(nvl);
    673   1.1  christos 	PJDLOG_ASSERT(nvl->nvl_error == 0);
    674   1.1  christos 
    675   1.1  christos 	size = sizeof(struct nvlist_header);
    676   1.1  christos 	nvp = nvlist_first_nvpair(nvl);
    677   1.1  christos 	while (nvp != NULL) {
    678   1.1  christos 		size += nvpair_header_size();
    679   1.1  christos 		size += strlen(nvpair_name(nvp)) + 1;
    680   1.1  christos 		if (nvpair_type(nvp) == NV_TYPE_NVLIST) {
    681   1.1  christos 			size += sizeof(struct nvlist_header);
    682   1.1  christos 			size += nvpair_header_size() + 1;
    683   1.1  christos 			tmpnvl = nvpair_get_nvlist(nvp);
    684   1.1  christos 			PJDLOG_ASSERT(tmpnvl->nvl_error == 0);
    685   1.1  christos 			tmpnvp = nvlist_first_nvpair(tmpnvl);
    686   1.1  christos 			if (tmpnvp != NULL) {
    687   1.1  christos 				nvl = tmpnvl;
    688   1.1  christos 				nvp = tmpnvp;
    689   1.1  christos 				continue;
    690   1.1  christos 			}
    691   1.1  christos 		} else if (nvpair_type(nvp) == NV_TYPE_NVLIST_ARRAY) {
    692   1.1  christos 			nvlarray = nvpair_get_nvlist_array(nvp, &nitems);
    693   1.1  christos 			PJDLOG_ASSERT(nitems > 0);
    694   1.1  christos 
    695   1.1  christos 			size += (nvpair_header_size() + 1) * nitems;
    696   1.1  christos 			size += sizeof(struct nvlist_header) * nitems;
    697   1.1  christos 
    698   1.1  christos 			tmpnvl = NULL;
    699   1.1  christos 			tmpnvp = NULL;
    700   1.1  christos 			for (ii = 0; ii < nitems; ii++) {
    701   1.1  christos 				PJDLOG_ASSERT(nvlarray[ii]->nvl_error == 0);
    702   1.1  christos 				tmpnvp = nvlist_first_nvpair(nvlarray[ii]);
    703   1.1  christos 				if (tmpnvp != NULL) {
    704   1.1  christos 					tmpnvl = nvlarray[ii];
    705   1.1  christos 					break;
    706   1.1  christos 				}
    707   1.1  christos 			}
    708   1.1  christos 			if (tmpnvp != NULL) {
    709   1.1  christos 				nvp = tmpnvp;
    710   1.1  christos 				nvl = tmpnvl;
    711   1.1  christos 				continue;
    712   1.1  christos 			}
    713   1.1  christos 
    714   1.1  christos 		} else {
    715   1.1  christos 			size += nvpair_size(nvp);
    716   1.1  christos 		}
    717   1.1  christos 
    718   1.1  christos 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
    719   1.1  christos 			do {
    720   1.1  christos 				cookie = NULL;
    721   1.1  christos 				nvl = nvlist_get_pararr(nvl, &cookie);
    722   1.1  christos 				if (nvl == NULL)
    723   1.1  christos 					goto out;
    724   1.1  christos 				if (nvlist_in_array(nvl) && cookie == NULL) {
    725   1.1  christos 					nvp = nvlist_first_nvpair(nvl);
    726   1.1  christos 				} else {
    727   1.1  christos 					nvp = cookie;
    728   1.1  christos 				}
    729   1.1  christos 			} while (nvp == NULL);
    730   1.1  christos 			if (nvlist_in_array(nvl) && cookie == NULL)
    731   1.1  christos 				break;
    732   1.1  christos 		}
    733   1.1  christos 	}
    734   1.1  christos 
    735   1.1  christos out:
    736   1.1  christos 	return (size);
    737   1.1  christos }
    738   1.1  christos 
    739   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
    740   1.1  christos static int *
    741   1.1  christos nvlist_xdescriptors(const nvlist_t *nvl, int *descs)
    742   1.1  christos {
    743   1.1  christos 	void *cookie;
    744   1.1  christos 	nvpair_t *nvp;
    745   1.1  christos 	int type;
    746   1.1  christos 
    747   1.1  christos 	NVLIST_ASSERT(nvl);
    748   1.1  christos 	PJDLOG_ASSERT(nvl->nvl_error == 0);
    749   1.1  christos 
    750   1.1  christos 	cookie = NULL;
    751   1.1  christos 	do {
    752   1.1  christos 		while (nvlist_next(nvl, &type, &cookie) != NULL) {
    753   1.1  christos 			nvp = cookie;
    754   1.1  christos 			switch (type) {
    755   1.1  christos 			case NV_TYPE_DESCRIPTOR:
    756   1.1  christos 				*descs = nvpair_get_descriptor(nvp);
    757   1.1  christos 				descs++;
    758   1.1  christos 				break;
    759   1.1  christos 			case NV_TYPE_DESCRIPTOR_ARRAY:
    760   1.1  christos 			    {
    761   1.1  christos 				const int *value;
    762   1.1  christos 				size_t nitems;
    763   1.1  christos 				unsigned int ii;
    764   1.1  christos 
    765   1.1  christos 				value = nvpair_get_descriptor_array(nvp,
    766   1.1  christos 				    &nitems);
    767   1.1  christos 				for (ii = 0; ii < nitems; ii++) {
    768   1.1  christos 					*descs = value[ii];
    769   1.1  christos 					descs++;
    770   1.1  christos 				}
    771   1.1  christos 				break;
    772   1.1  christos 			    }
    773   1.1  christos 			case NV_TYPE_NVLIST:
    774   1.1  christos 				nvl = nvpair_get_nvlist(nvp);
    775   1.1  christos 				cookie = NULL;
    776   1.1  christos 				break;
    777   1.1  christos 			case NV_TYPE_NVLIST_ARRAY:
    778   1.1  christos 			    {
    779   1.1  christos 				const nvlist_t * const *value;
    780   1.1  christos 				size_t nitems;
    781   1.1  christos 
    782   1.1  christos 				value = nvpair_get_nvlist_array(nvp, &nitems);
    783   1.1  christos 				PJDLOG_ASSERT(value != NULL);
    784   1.1  christos 				PJDLOG_ASSERT(nitems > 0);
    785   1.1  christos 
    786   1.1  christos 				nvl = value[0];
    787   1.1  christos 				cookie = NULL;
    788   1.1  christos 				break;
    789   1.1  christos 			    }
    790   1.1  christos 			}
    791   1.1  christos 		}
    792   1.1  christos 	} while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
    793   1.1  christos 
    794   1.1  christos 	return (descs);
    795   1.1  christos }
    796   1.1  christos #endif
    797   1.1  christos 
    798   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
    799   1.1  christos int *
    800   1.1  christos nvlist_descriptors(const nvlist_t *nvl, size_t *nitemsp)
    801   1.1  christos {
    802   1.1  christos 	size_t nitems;
    803   1.1  christos 	int *fds;
    804   1.1  christos 
    805   1.1  christos 	nitems = nvlist_ndescriptors(nvl);
    806  1.10  riastrad 	fds = nv_calloc(nitems + 1, sizeof(fds[0]));
    807   1.1  christos 	if (fds == NULL)
    808   1.1  christos 		return (NULL);
    809   1.1  christos 	if (nitems > 0)
    810   1.1  christos 		nvlist_xdescriptors(nvl, fds);
    811   1.1  christos 	fds[nitems] = -1;
    812   1.1  christos 	if (nitemsp != NULL)
    813   1.1  christos 		*nitemsp = nitems;
    814   1.1  christos 	return (fds);
    815   1.1  christos }
    816   1.1  christos #endif
    817   1.1  christos 
    818   1.1  christos size_t
    819   1.1  christos nvlist_ndescriptors(const nvlist_t *nvl)
    820   1.1  christos {
    821   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
    822   1.1  christos 	void *cookie;
    823   1.1  christos 	nvpair_t *nvp;
    824   1.1  christos 	size_t ndescs;
    825   1.1  christos 	int type;
    826   1.1  christos 
    827   1.1  christos 	NVLIST_ASSERT(nvl);
    828   1.1  christos 	PJDLOG_ASSERT(nvl->nvl_error == 0);
    829   1.1  christos 
    830   1.1  christos 	ndescs = 0;
    831   1.1  christos 	cookie = NULL;
    832   1.1  christos 	do {
    833   1.1  christos 		while (nvlist_next(nvl, &type, &cookie) != NULL) {
    834   1.1  christos 			nvp = cookie;
    835   1.1  christos 			switch (type) {
    836   1.1  christos 			case NV_TYPE_DESCRIPTOR:
    837   1.1  christos 				ndescs++;
    838   1.1  christos 				break;
    839   1.1  christos 			case NV_TYPE_NVLIST:
    840   1.1  christos 				nvl = nvpair_get_nvlist(nvp);
    841   1.1  christos 				cookie = NULL;
    842   1.1  christos 				break;
    843   1.1  christos 			case NV_TYPE_NVLIST_ARRAY:
    844   1.1  christos 			    {
    845   1.1  christos 				const nvlist_t * const *value;
    846   1.1  christos 				size_t nitems;
    847   1.1  christos 
    848   1.1  christos 				value = nvpair_get_nvlist_array(nvp, &nitems);
    849   1.1  christos 				PJDLOG_ASSERT(value != NULL);
    850   1.1  christos 				PJDLOG_ASSERT(nitems > 0);
    851   1.1  christos 
    852   1.1  christos 				nvl = value[0];
    853   1.1  christos 				cookie = NULL;
    854   1.1  christos 				break;
    855   1.1  christos 			    }
    856   1.1  christos 			case NV_TYPE_DESCRIPTOR_ARRAY:
    857   1.1  christos 			    {
    858   1.1  christos 				size_t nitems;
    859   1.1  christos 
    860   1.1  christos 				(void)nvpair_get_descriptor_array(nvp,
    861   1.1  christos 				    &nitems);
    862   1.1  christos 				ndescs += nitems;
    863   1.1  christos 				break;
    864   1.1  christos 			    }
    865   1.1  christos 			}
    866   1.1  christos 		}
    867   1.1  christos 	} while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
    868   1.1  christos 
    869   1.1  christos 	return (ndescs);
    870   1.1  christos #else
    871   1.1  christos 	return (0);
    872   1.1  christos #endif
    873   1.1  christos }
    874   1.1  christos 
    875   1.1  christos static unsigned char *
    876   1.1  christos nvlist_pack_header(const nvlist_t *nvl, unsigned char *ptr, size_t *leftp)
    877   1.1  christos {
    878   1.1  christos 	struct nvlist_header nvlhdr;
    879   1.1  christos 
    880   1.1  christos 	NVLIST_ASSERT(nvl);
    881   1.1  christos 
    882   1.1  christos 	nvlhdr.nvlh_magic = NVLIST_HEADER_MAGIC;
    883   1.1  christos 	nvlhdr.nvlh_version = NVLIST_HEADER_VERSION;
    884   1.1  christos 	nvlhdr.nvlh_flags = nvl->nvl_flags;
    885   1.1  christos #if BYTE_ORDER == BIG_ENDIAN
    886   1.1  christos 	nvlhdr.nvlh_flags |= NV_FLAG_BIG_ENDIAN;
    887   1.1  christos #endif
    888   1.1  christos 	nvlhdr.nvlh_descriptors = nvlist_ndescriptors(nvl);
    889   1.1  christos 	nvlhdr.nvlh_size = *leftp - sizeof(nvlhdr);
    890   1.1  christos 	PJDLOG_ASSERT(*leftp >= sizeof(nvlhdr));
    891   1.1  christos 	memcpy(ptr, &nvlhdr, sizeof(nvlhdr));
    892   1.1  christos 	ptr += sizeof(nvlhdr);
    893   1.1  christos 	*leftp -= sizeof(nvlhdr);
    894   1.1  christos 
    895   1.1  christos 	return (ptr);
    896   1.1  christos }
    897   1.1  christos 
    898   1.1  christos static void *
    899   1.1  christos nvlist_xpack(const nvlist_t *nvl, int64_t *fdidxp, size_t *sizep)
    900   1.1  christos {
    901   1.1  christos 	unsigned char *buf, *ptr;
    902   1.1  christos 	size_t left, size;
    903   1.1  christos 	const nvlist_t *tmpnvl;
    904   1.1  christos 	nvpair_t *nvp, *tmpnvp;
    905   1.1  christos 	void *cookie;
    906   1.1  christos 
    907   1.1  christos 	NVLIST_ASSERT(nvl);
    908   1.1  christos 
    909   1.1  christos 	if (nvl->nvl_error != 0) {
    910   1.1  christos 		ERRNO_SET(nvl->nvl_error);
    911   1.1  christos 		return (NULL);
    912   1.1  christos 	}
    913   1.1  christos 
    914   1.1  christos 	size = nvlist_size(nvl);
    915   1.1  christos 	buf = nv_malloc(size);
    916   1.1  christos 	if (buf == NULL)
    917   1.1  christos 		return (NULL);
    918   1.1  christos 
    919   1.1  christos 	ptr = buf;
    920   1.1  christos 	left = size;
    921   1.1  christos 
    922   1.1  christos 	ptr = nvlist_pack_header(nvl, ptr, &left);
    923   1.1  christos 
    924   1.1  christos 	nvp = nvlist_first_nvpair(nvl);
    925   1.1  christos 	while (nvp != NULL) {
    926   1.1  christos 		NVPAIR_ASSERT(nvp);
    927   1.1  christos 
    928   1.1  christos 		nvpair_init_datasize(nvp);
    929   1.1  christos 		ptr = nvpair_pack_header(nvp, ptr, &left);
    930   1.1  christos 		if (ptr == NULL)
    931   1.1  christos 			goto fail;
    932   1.1  christos 		switch (nvpair_type(nvp)) {
    933   1.1  christos 		case NV_TYPE_NULL:
    934   1.1  christos 			ptr = nvpair_pack_null(nvp, ptr, &left);
    935   1.1  christos 			break;
    936   1.1  christos 		case NV_TYPE_BOOL:
    937   1.1  christos 			ptr = nvpair_pack_bool(nvp, ptr, &left);
    938   1.1  christos 			break;
    939   1.1  christos 		case NV_TYPE_NUMBER:
    940   1.1  christos 			ptr = nvpair_pack_number(nvp, ptr, &left);
    941   1.1  christos 			break;
    942   1.1  christos 		case NV_TYPE_STRING:
    943   1.1  christos 			ptr = nvpair_pack_string(nvp, ptr, &left);
    944   1.1  christos 			break;
    945   1.1  christos 		case NV_TYPE_NVLIST:
    946   1.1  christos 			tmpnvl = nvpair_get_nvlist(nvp);
    947   1.1  christos 			ptr = nvlist_pack_header(tmpnvl, ptr, &left);
    948   1.1  christos 			if (ptr == NULL)
    949   1.1  christos 				goto fail;
    950   1.1  christos 			tmpnvp = nvlist_first_nvpair(tmpnvl);
    951   1.1  christos 			if (tmpnvp != NULL) {
    952   1.1  christos 				nvl = tmpnvl;
    953   1.1  christos 				nvp = tmpnvp;
    954   1.1  christos 				continue;
    955   1.1  christos 			}
    956   1.1  christos 			ptr = nvpair_pack_nvlist_up(ptr, &left);
    957   1.1  christos 			break;
    958   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
    959   1.1  christos 		case NV_TYPE_DESCRIPTOR:
    960   1.1  christos 			ptr = nvpair_pack_descriptor(nvp, ptr, fdidxp, &left);
    961   1.1  christos 			break;
    962   1.1  christos 		case NV_TYPE_DESCRIPTOR_ARRAY:
    963   1.1  christos 			ptr = nvpair_pack_descriptor_array(nvp, ptr, fdidxp,
    964   1.1  christos 			    &left);
    965   1.1  christos 			break;
    966   1.1  christos #endif
    967   1.1  christos 		case NV_TYPE_BINARY:
    968   1.1  christos 			ptr = nvpair_pack_binary(nvp, ptr, &left);
    969   1.1  christos 			break;
    970   1.1  christos 		case NV_TYPE_BOOL_ARRAY:
    971   1.1  christos 			ptr = nvpair_pack_bool_array(nvp, ptr, &left);
    972   1.1  christos 			break;
    973   1.1  christos 		case NV_TYPE_NUMBER_ARRAY:
    974   1.1  christos 			ptr = nvpair_pack_number_array(nvp, ptr, &left);
    975   1.1  christos 			break;
    976   1.1  christos 		case NV_TYPE_STRING_ARRAY:
    977   1.1  christos 			ptr = nvpair_pack_string_array(nvp, ptr, &left);
    978   1.1  christos 			break;
    979   1.1  christos 		case NV_TYPE_NVLIST_ARRAY:
    980   1.1  christos 		    {
    981   1.1  christos 			const nvlist_t * const * value;
    982   1.1  christos 			size_t nitems;
    983   1.1  christos 			unsigned int ii;
    984   1.1  christos 
    985   1.1  christos 			tmpnvl = NULL;
    986   1.1  christos 			value = nvpair_get_nvlist_array(nvp, &nitems);
    987   1.1  christos 			for (ii = 0; ii < nitems; ii++) {
    988   1.1  christos 				ptr = nvlist_pack_header(value[ii], ptr, &left);
    989   1.1  christos 				if (ptr == NULL)
    990   1.1  christos 					goto out;
    991   1.1  christos 				tmpnvp = nvlist_first_nvpair(value[ii]);
    992   1.1  christos 				if (tmpnvp != NULL) {
    993   1.1  christos 					tmpnvl = value[ii];
    994   1.1  christos 					break;
    995   1.1  christos 				}
    996   1.1  christos 				ptr = nvpair_pack_nvlist_array_next(ptr, &left);
    997   1.1  christos 				if (ptr == NULL)
    998   1.1  christos 					goto out;
    999   1.1  christos 			}
   1000   1.1  christos 			if (tmpnvl != NULL) {
   1001   1.1  christos 				nvl = tmpnvl;
   1002   1.1  christos 				nvp = tmpnvp;
   1003   1.1  christos 				continue;
   1004   1.1  christos 			}
   1005   1.1  christos 			break;
   1006   1.1  christos 		    }
   1007   1.1  christos 		default:
   1008   1.1  christos 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
   1009   1.1  christos 		}
   1010   1.1  christos 		if (ptr == NULL)
   1011   1.1  christos 			goto fail;
   1012   1.1  christos 		while ((nvp = nvlist_next_nvpair(nvl, nvp)) == NULL) {
   1013   1.1  christos 			do {
   1014   1.1  christos 				cookie = NULL;
   1015   1.1  christos 				if (nvlist_in_array(nvl)) {
   1016   1.1  christos 					ptr = nvpair_pack_nvlist_array_next(ptr,
   1017   1.1  christos 					    &left);
   1018   1.1  christos 					if (ptr == NULL)
   1019   1.1  christos 						goto fail;
   1020   1.1  christos 				}
   1021   1.1  christos 				nvl = nvlist_get_pararr(nvl, &cookie);
   1022   1.1  christos 				if (nvl == NULL)
   1023   1.1  christos 					goto out;
   1024   1.1  christos 				if (nvlist_in_array(nvl) && cookie == NULL) {
   1025   1.1  christos 					nvp = nvlist_first_nvpair(nvl);
   1026   1.1  christos 					ptr = nvlist_pack_header(nvl, ptr,
   1027   1.1  christos 					    &left);
   1028   1.1  christos 					if (ptr == NULL)
   1029   1.1  christos 						goto fail;
   1030   1.1  christos 				} else if (nvpair_type((nvpair_t *)cookie) !=
   1031   1.1  christos 				    NV_TYPE_NVLIST_ARRAY) {
   1032   1.1  christos 					ptr = nvpair_pack_nvlist_up(ptr, &left);
   1033   1.1  christos 					if (ptr == NULL)
   1034   1.1  christos 						goto fail;
   1035   1.1  christos 					nvp = cookie;
   1036   1.1  christos 				} else {
   1037   1.1  christos 					nvp = cookie;
   1038   1.1  christos 				}
   1039   1.1  christos 			} while (nvp == NULL);
   1040   1.1  christos 			if (nvlist_in_array(nvl) && cookie == NULL)
   1041   1.1  christos 				break;
   1042   1.1  christos 		}
   1043   1.1  christos 	}
   1044   1.1  christos 
   1045   1.1  christos out:
   1046   1.1  christos 	if (sizep != NULL)
   1047   1.1  christos 		*sizep = size;
   1048   1.1  christos 	return (buf);
   1049   1.1  christos fail:
   1050   1.1  christos 	nv_free(buf);
   1051   1.1  christos 	return (NULL);
   1052   1.1  christos }
   1053   1.1  christos 
   1054   1.1  christos void *
   1055   1.1  christos nvlist_pack(const nvlist_t *nvl, size_t *sizep)
   1056   1.1  christos {
   1057   1.1  christos 
   1058   1.1  christos 	NVLIST_ASSERT(nvl);
   1059   1.1  christos 
   1060   1.1  christos 	if (nvl->nvl_error != 0) {
   1061   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1062   1.1  christos 		return (NULL);
   1063   1.1  christos 	}
   1064   1.1  christos 
   1065   1.1  christos 	if (nvlist_ndescriptors(nvl) > 0) {
   1066   1.1  christos 		ERRNO_SET(EOPNOTSUPP);
   1067   1.1  christos 		return (NULL);
   1068   1.1  christos 	}
   1069   1.1  christos 
   1070   1.1  christos 	return (nvlist_xpack(nvl, NULL, sizep));
   1071   1.1  christos }
   1072   1.1  christos 
   1073   1.1  christos static bool
   1074   1.1  christos nvlist_check_header(struct nvlist_header *nvlhdrp)
   1075   1.1  christos {
   1076   1.1  christos 
   1077  1.11  riastrad 	if (nvlhdrp->nvlh_size > SIZE_MAX - sizeof(*nvlhdrp)) {
   1078   1.9  riastrad 		ERRNO_SET(EINVAL);
   1079   1.9  riastrad 		return (false);
   1080   1.9  riastrad 	}
   1081   1.1  christos 	if (nvlhdrp->nvlh_magic != NVLIST_HEADER_MAGIC) {
   1082   1.1  christos 		ERRNO_SET(EINVAL);
   1083   1.1  christos 		return (false);
   1084   1.1  christos 	}
   1085   1.1  christos 	if ((nvlhdrp->nvlh_flags & ~NV_FLAG_ALL_MASK) != 0) {
   1086   1.1  christos 		ERRNO_SET(EINVAL);
   1087   1.1  christos 		return (false);
   1088   1.1  christos 	}
   1089   1.1  christos #if BYTE_ORDER == BIG_ENDIAN
   1090   1.1  christos 	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) == 0) {
   1091   1.1  christos 		nvlhdrp->nvlh_size = le64toh(nvlhdrp->nvlh_size);
   1092   1.1  christos 		nvlhdrp->nvlh_descriptors = le64toh(nvlhdrp->nvlh_descriptors);
   1093   1.1  christos 	}
   1094   1.1  christos #else
   1095   1.1  christos 	if ((nvlhdrp->nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0) {
   1096   1.1  christos 		nvlhdrp->nvlh_size = be64toh(nvlhdrp->nvlh_size);
   1097   1.1  christos 		nvlhdrp->nvlh_descriptors = be64toh(nvlhdrp->nvlh_descriptors);
   1098   1.1  christos 	}
   1099   1.1  christos #endif
   1100   1.1  christos 	return (true);
   1101   1.1  christos }
   1102   1.1  christos 
   1103   1.1  christos const unsigned char *
   1104   1.1  christos nvlist_unpack_header(nvlist_t *nvl, const unsigned char *ptr, size_t nfds,
   1105   1.1  christos     bool *isbep, size_t *leftp)
   1106   1.1  christos {
   1107   1.1  christos 	struct nvlist_header nvlhdr;
   1108   1.1  christos 	int inarrayf;
   1109   1.1  christos 
   1110   1.1  christos 	if (*leftp < sizeof(nvlhdr))
   1111   1.1  christos 		goto fail;
   1112   1.1  christos 
   1113   1.1  christos 	memcpy(&nvlhdr, ptr, sizeof(nvlhdr));
   1114   1.1  christos 
   1115   1.1  christos 	if (!nvlist_check_header(&nvlhdr))
   1116   1.1  christos 		goto fail;
   1117   1.1  christos 
   1118   1.1  christos 	if (nvlhdr.nvlh_size != *leftp - sizeof(nvlhdr))
   1119   1.1  christos 		goto fail;
   1120   1.1  christos 
   1121   1.1  christos 	/*
   1122   1.1  christos 	 * nvlh_descriptors might be smaller than nfds in embedded nvlists.
   1123   1.1  christos 	 */
   1124   1.1  christos 	if (nvlhdr.nvlh_descriptors > nfds)
   1125   1.1  christos 		goto fail;
   1126   1.1  christos 
   1127   1.1  christos 	if ((nvlhdr.nvlh_flags & ~NV_FLAG_ALL_MASK) != 0)
   1128   1.1  christos 		goto fail;
   1129   1.1  christos 
   1130   1.1  christos 	inarrayf = (nvl->nvl_flags & NV_FLAG_IN_ARRAY);
   1131   1.1  christos 	nvl->nvl_flags = (nvlhdr.nvlh_flags & NV_FLAG_PUBLIC_MASK) | inarrayf;
   1132   1.1  christos 
   1133   1.1  christos 	ptr += sizeof(nvlhdr);
   1134   1.1  christos 	if (isbep != NULL)
   1135   1.1  christos 		*isbep = (((int)nvlhdr.nvlh_flags & NV_FLAG_BIG_ENDIAN) != 0);
   1136   1.1  christos 	*leftp -= sizeof(nvlhdr);
   1137   1.1  christos 
   1138   1.1  christos 	return (ptr);
   1139   1.1  christos fail:
   1140   1.1  christos 	ERRNO_SET(EINVAL);
   1141   1.1  christos 	return (NULL);
   1142   1.1  christos }
   1143   1.1  christos 
   1144   1.1  christos static nvlist_t *
   1145   1.1  christos nvlist_xunpack(const void *buf, size_t size, const int *fds, size_t nfds,
   1146   1.1  christos     int flags)
   1147   1.1  christos {
   1148   1.1  christos 	const unsigned char *ptr;
   1149   1.1  christos 	nvlist_t *nvl, *retnvl, *tmpnvl, *array;
   1150   1.1  christos 	nvpair_t *nvp;
   1151   1.1  christos 	size_t left;
   1152   1.1  christos 	bool isbe;
   1153   1.1  christos 
   1154   1.1  christos 	PJDLOG_ASSERT((flags & ~(NV_FLAG_PUBLIC_MASK)) == 0);
   1155   1.1  christos 
   1156   1.1  christos 	left = size;
   1157   1.1  christos 	ptr = buf;
   1158   1.1  christos 
   1159   1.1  christos 	tmpnvl = array = NULL;
   1160   1.1  christos 	nvl = retnvl = nvlist_create(0);
   1161   1.1  christos 	if (nvl == NULL)
   1162   1.1  christos 		goto fail;
   1163   1.1  christos 
   1164   1.1  christos 	ptr = nvlist_unpack_header(nvl, ptr, nfds, &isbe, &left);
   1165   1.1  christos 	if (ptr == NULL)
   1166   1.1  christos 		goto fail;
   1167   1.1  christos 	if (nvl->nvl_flags != flags) {
   1168   1.1  christos 		ERRNO_SET(EILSEQ);
   1169   1.1  christos 		goto fail;
   1170   1.1  christos 	}
   1171   1.1  christos 
   1172   1.1  christos 	while (left > 0) {
   1173   1.1  christos 		ptr = nvpair_unpack(isbe, ptr, &left, &nvp);
   1174   1.1  christos 		if (ptr == NULL)
   1175   1.1  christos 			goto fail;
   1176   1.1  christos 		switch (nvpair_type(nvp)) {
   1177   1.1  christos 		case NV_TYPE_NULL:
   1178   1.1  christos 			ptr = nvpair_unpack_null(isbe, nvp, ptr, &left);
   1179   1.1  christos 			break;
   1180   1.1  christos 		case NV_TYPE_BOOL:
   1181   1.1  christos 			ptr = nvpair_unpack_bool(isbe, nvp, ptr, &left);
   1182   1.1  christos 			break;
   1183   1.1  christos 		case NV_TYPE_NUMBER:
   1184   1.1  christos 			ptr = nvpair_unpack_number(isbe, nvp, ptr, &left);
   1185   1.1  christos 			break;
   1186   1.1  christos 		case NV_TYPE_STRING:
   1187   1.1  christos 			ptr = nvpair_unpack_string(isbe, nvp, ptr, &left);
   1188   1.1  christos 			break;
   1189   1.1  christos 		case NV_TYPE_NVLIST:
   1190   1.1  christos 			ptr = nvpair_unpack_nvlist(isbe, nvp, ptr, &left, nfds,
   1191   1.1  christos 			    &tmpnvl);
   1192   1.1  christos 			if (tmpnvl == NULL || ptr == NULL)
   1193   1.1  christos 				goto fail;
   1194   1.1  christos 			nvlist_set_parent(tmpnvl, nvp);
   1195   1.1  christos 			break;
   1196   1.6     rmind #if !defined(_KERNEL) && !defined(_STANDALONE) && !defined(__NetBSD__)
   1197   1.1  christos 		case NV_TYPE_DESCRIPTOR:
   1198   1.1  christos 			ptr = nvpair_unpack_descriptor(isbe, nvp, ptr, &left,
   1199   1.1  christos 			    fds, nfds);
   1200   1.1  christos 			break;
   1201   1.1  christos 		case NV_TYPE_DESCRIPTOR_ARRAY:
   1202   1.1  christos 			ptr = nvpair_unpack_descriptor_array(isbe, nvp, ptr,
   1203   1.1  christos 			    &left, fds, nfds);
   1204   1.1  christos 			break;
   1205   1.1  christos #endif
   1206   1.1  christos 		case NV_TYPE_BINARY:
   1207   1.1  christos 			ptr = nvpair_unpack_binary(isbe, nvp, ptr, &left);
   1208   1.1  christos 			break;
   1209   1.1  christos 		case NV_TYPE_NVLIST_UP:
   1210   1.1  christos 			if (nvl->nvl_parent == NULL)
   1211   1.1  christos 				goto fail;
   1212   1.1  christos 			nvl = nvpair_nvlist(nvl->nvl_parent);
   1213   1.1  christos 			nvpair_free_structure(nvp);
   1214   1.1  christos 			continue;
   1215   1.1  christos 		case NV_TYPE_NVLIST_ARRAY_NEXT:
   1216   1.1  christos 			if (nvl->nvl_array_next == NULL) {
   1217   1.1  christos 				if (nvl->nvl_parent == NULL)
   1218   1.1  christos 					goto fail;
   1219   1.1  christos 				nvl = nvpair_nvlist(nvl->nvl_parent);
   1220   1.1  christos 			} else {
   1221   1.1  christos 				nvl = __DECONST(nvlist_t *,
   1222   1.1  christos 				    nvlist_get_array_next(nvl));
   1223   1.1  christos 				ptr = nvlist_unpack_header(nvl, ptr, nfds,
   1224   1.1  christos 				    &isbe, &left);
   1225   1.1  christos 				if (ptr == NULL)
   1226   1.1  christos 					goto fail;
   1227   1.1  christos 			}
   1228   1.1  christos 			nvpair_free_structure(nvp);
   1229   1.1  christos 			continue;
   1230   1.1  christos 		case NV_TYPE_BOOL_ARRAY:
   1231   1.1  christos 			ptr = nvpair_unpack_bool_array(isbe, nvp, ptr, &left);
   1232   1.1  christos 			break;
   1233   1.1  christos 		case NV_TYPE_NUMBER_ARRAY:
   1234   1.1  christos 			ptr = nvpair_unpack_number_array(isbe, nvp, ptr, &left);
   1235   1.1  christos 			break;
   1236   1.1  christos 		case NV_TYPE_STRING_ARRAY:
   1237   1.1  christos 			ptr = nvpair_unpack_string_array(isbe, nvp, ptr, &left);
   1238   1.1  christos 			break;
   1239   1.1  christos 		case NV_TYPE_NVLIST_ARRAY:
   1240   1.1  christos 			ptr = nvpair_unpack_nvlist_array(isbe, nvp, ptr, &left,
   1241   1.1  christos 			    &array);
   1242   1.1  christos 			if (ptr == NULL)
   1243   1.1  christos 				goto fail;
   1244   1.1  christos 			PJDLOG_ASSERT(array != NULL);
   1245   1.1  christos 			tmpnvl = array;
   1246   1.1  christos 			do {
   1247   1.1  christos 				nvlist_set_parent(array, nvp);
   1248   1.1  christos 				array = __DECONST(nvlist_t *,
   1249   1.1  christos 				    nvlist_get_array_next(array));
   1250   1.1  christos 			} while (array != NULL);
   1251   1.1  christos 			ptr = nvlist_unpack_header(tmpnvl, ptr, nfds, &isbe,
   1252   1.1  christos 			    &left);
   1253   1.1  christos 			break;
   1254   1.1  christos 		default:
   1255   1.1  christos 			PJDLOG_ABORT("Invalid type (%d).", nvpair_type(nvp));
   1256   1.1  christos 		}
   1257   1.1  christos 		if (ptr == NULL)
   1258   1.1  christos 			goto fail;
   1259   1.1  christos 		if (!nvlist_move_nvpair(nvl, nvp))
   1260   1.1  christos 			goto fail;
   1261   1.1  christos 		if (tmpnvl != NULL) {
   1262   1.1  christos 			nvl = tmpnvl;
   1263   1.1  christos 			tmpnvl = NULL;
   1264   1.1  christos 		}
   1265   1.1  christos 	}
   1266   1.1  christos 
   1267   1.1  christos 	return (retnvl);
   1268   1.1  christos fail:
   1269   1.1  christos 	nvlist_destroy(retnvl);
   1270   1.1  christos 	return (NULL);
   1271   1.1  christos }
   1272   1.1  christos 
   1273   1.1  christos nvlist_t *
   1274   1.1  christos nvlist_unpack(const void *buf, size_t size, int flags)
   1275   1.1  christos {
   1276   1.1  christos 
   1277   1.1  christos 	return (nvlist_xunpack(buf, size, NULL, 0, flags));
   1278   1.1  christos }
   1279   1.1  christos 
   1280   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(WITH_MSGIO)
   1281   1.1  christos int
   1282   1.1  christos nvlist_send(int sock, const nvlist_t *nvl)
   1283   1.1  christos {
   1284   1.1  christos 	size_t datasize, nfds;
   1285   1.1  christos 	int *fds;
   1286   1.1  christos 	void *data;
   1287   1.1  christos 	int64_t fdidx;
   1288   1.1  christos 	int ret;
   1289   1.1  christos 
   1290   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1291   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1292   1.1  christos 		return (-1);
   1293   1.1  christos 	}
   1294   1.1  christos 
   1295   1.1  christos 	fds = nvlist_descriptors(nvl, &nfds);
   1296   1.1  christos 	if (fds == NULL)
   1297   1.1  christos 		return (-1);
   1298   1.1  christos 
   1299   1.1  christos 	ret = -1;
   1300   1.1  christos 	fdidx = 0;
   1301   1.1  christos 
   1302   1.1  christos 	data = nvlist_xpack(nvl, &fdidx, &datasize);
   1303   1.1  christos 	if (data == NULL)
   1304   1.1  christos 		goto out;
   1305   1.1  christos 
   1306   1.1  christos 	if (buf_send(sock, data, datasize) == -1)
   1307   1.1  christos 		goto out;
   1308   1.1  christos 
   1309   1.1  christos 	if (nfds > 0) {
   1310   1.1  christos 		if (fd_send(sock, fds, nfds) == -1)
   1311   1.1  christos 			goto out;
   1312   1.1  christos 	}
   1313   1.1  christos 
   1314   1.1  christos 	ret = 0;
   1315   1.1  christos out:
   1316   1.1  christos 	ERRNO_SAVE();
   1317   1.1  christos 	nv_free(fds);
   1318   1.1  christos 	nv_free(data);
   1319   1.1  christos 	ERRNO_RESTORE();
   1320   1.1  christos 	return (ret);
   1321   1.1  christos }
   1322   1.1  christos 
   1323   1.1  christos nvlist_t *
   1324   1.1  christos nvlist_recv(int sock, int flags)
   1325   1.1  christos {
   1326   1.1  christos 	struct nvlist_header nvlhdr;
   1327   1.1  christos 	nvlist_t *nvl, *ret;
   1328   1.1  christos 	unsigned char *buf;
   1329   1.1  christos 	size_t nfds, size, i;
   1330   1.1  christos 	int *fds;
   1331   1.1  christos 
   1332   1.1  christos 	if (buf_recv(sock, &nvlhdr, sizeof(nvlhdr)) == -1)
   1333   1.1  christos 		return (NULL);
   1334   1.1  christos 
   1335   1.1  christos 	if (!nvlist_check_header(&nvlhdr))
   1336   1.1  christos 		return (NULL);
   1337   1.1  christos 
   1338   1.1  christos 	nfds = (size_t)nvlhdr.nvlh_descriptors;
   1339   1.1  christos 	size = sizeof(nvlhdr) + (size_t)nvlhdr.nvlh_size;
   1340   1.1  christos 
   1341   1.1  christos 	buf = nv_malloc(size);
   1342   1.1  christos 	if (buf == NULL)
   1343   1.1  christos 		return (NULL);
   1344   1.1  christos 
   1345   1.1  christos 	memcpy(buf, &nvlhdr, sizeof(nvlhdr));
   1346   1.1  christos 
   1347   1.1  christos 	ret = NULL;
   1348   1.1  christos 	fds = NULL;
   1349   1.1  christos 
   1350   1.1  christos 	if (buf_recv(sock, buf + sizeof(nvlhdr), size - sizeof(nvlhdr)) == -1)
   1351   1.1  christos 		goto out;
   1352   1.1  christos 
   1353   1.1  christos 	if (nfds > 0) {
   1354  1.10  riastrad 		fds = nv_calloc(nfds, sizeof(fds[0]));
   1355   1.1  christos 		if (fds == NULL)
   1356   1.1  christos 			goto out;
   1357   1.1  christos 		if (fd_recv(sock, fds, nfds) == -1)
   1358   1.1  christos 			goto out;
   1359   1.1  christos 	}
   1360   1.1  christos 
   1361   1.1  christos 	nvl = nvlist_xunpack(buf, size, fds, nfds, flags);
   1362   1.1  christos 	if (nvl == NULL) {
   1363   1.1  christos 		ERRNO_SAVE();
   1364   1.1  christos 		for (i = 0; i < nfds; i++)
   1365   1.1  christos 			close(fds[i]);
   1366   1.1  christos 		ERRNO_RESTORE();
   1367   1.1  christos 		goto out;
   1368   1.1  christos 	}
   1369   1.1  christos 
   1370   1.1  christos 	ret = nvl;
   1371   1.1  christos out:
   1372   1.1  christos 	ERRNO_SAVE();
   1373   1.1  christos 	nv_free(buf);
   1374   1.1  christos 	nv_free(fds);
   1375   1.1  christos 	ERRNO_RESTORE();
   1376   1.1  christos 
   1377   1.1  christos 	return (ret);
   1378   1.1  christos }
   1379   1.1  christos 
   1380   1.1  christos nvlist_t *
   1381   1.1  christos nvlist_xfer(int sock, nvlist_t *nvl, int flags)
   1382   1.1  christos {
   1383   1.1  christos 
   1384   1.1  christos 	if (nvlist_send(sock, nvl) < 0) {
   1385   1.1  christos 		nvlist_destroy(nvl);
   1386   1.1  christos 		return (NULL);
   1387   1.1  christos 	}
   1388   1.1  christos 	nvlist_destroy(nvl);
   1389   1.1  christos 	return (nvlist_recv(sock, flags));
   1390   1.1  christos }
   1391   1.1  christos #endif
   1392   1.1  christos 
   1393   1.1  christos nvpair_t *
   1394   1.1  christos nvlist_first_nvpair(const nvlist_t *nvl)
   1395   1.1  christos {
   1396   1.1  christos 
   1397   1.1  christos 	NVLIST_ASSERT(nvl);
   1398   1.1  christos 
   1399   1.1  christos 	return (TAILQ_FIRST(&nvl->nvl_head));
   1400   1.1  christos }
   1401   1.1  christos 
   1402   1.1  christos nvpair_t *
   1403   1.1  christos nvlist_next_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
   1404   1.1  christos {
   1405   1.1  christos 	nvpair_t *retnvp;
   1406   1.1  christos 
   1407   1.1  christos 	NVLIST_ASSERT(nvl);
   1408   1.1  christos 	NVPAIR_ASSERT(nvp);
   1409   1.1  christos 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
   1410   1.1  christos 
   1411   1.1  christos 	retnvp = nvpair_next(nvp);
   1412   1.1  christos 	PJDLOG_ASSERT(retnvp == NULL || nvpair_nvlist(retnvp) == nvl);
   1413   1.1  christos 
   1414   1.1  christos 	return (retnvp);
   1415   1.1  christos 
   1416   1.1  christos }
   1417   1.1  christos 
   1418   1.1  christos nvpair_t *
   1419   1.1  christos nvlist_prev_nvpair(const nvlist_t *nvl, const nvpair_t *nvp)
   1420   1.1  christos {
   1421   1.1  christos 	nvpair_t *retnvp;
   1422   1.1  christos 
   1423   1.1  christos 	NVLIST_ASSERT(nvl);
   1424   1.1  christos 	NVPAIR_ASSERT(nvp);
   1425   1.1  christos 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
   1426   1.1  christos 
   1427   1.1  christos 	retnvp = nvpair_prev(nvp);
   1428   1.1  christos 	PJDLOG_ASSERT(nvpair_nvlist(retnvp) == nvl);
   1429   1.1  christos 
   1430   1.1  christos 	return (retnvp);
   1431   1.1  christos }
   1432   1.1  christos 
   1433   1.1  christos const char *
   1434   1.1  christos nvlist_next(const nvlist_t *nvl, int *typep, void **cookiep)
   1435   1.1  christos {
   1436   1.1  christos 	nvpair_t *nvp;
   1437   1.1  christos 
   1438   1.1  christos 	NVLIST_ASSERT(nvl);
   1439   1.1  christos 
   1440   1.1  christos 	if (cookiep == NULL || *cookiep == NULL)
   1441   1.1  christos 		nvp = nvlist_first_nvpair(nvl);
   1442   1.1  christos 	else
   1443   1.1  christos 		nvp = nvlist_next_nvpair(nvl, *cookiep);
   1444   1.1  christos 	if (nvp == NULL)
   1445   1.1  christos 		return (NULL);
   1446   1.1  christos 	if (typep != NULL)
   1447   1.1  christos 		*typep = nvpair_type(nvp);
   1448   1.1  christos 	if (cookiep != NULL)
   1449   1.1  christos 		*cookiep = nvp;
   1450   1.1  christos 	return (nvpair_name(nvp));
   1451   1.1  christos }
   1452   1.1  christos 
   1453   1.1  christos bool
   1454   1.1  christos nvlist_exists(const nvlist_t *nvl, const char *name)
   1455   1.1  christos {
   1456   1.1  christos 
   1457   1.1  christos 	return (nvlist_find(nvl, NV_TYPE_NONE, name) != NULL);
   1458   1.1  christos }
   1459   1.1  christos 
   1460   1.1  christos #define	NVLIST_EXISTS(type, TYPE)					\
   1461   1.1  christos bool									\
   1462   1.1  christos nvlist_exists_##type(const nvlist_t *nvl, const char *name)		\
   1463   1.1  christos {									\
   1464   1.1  christos 									\
   1465   1.1  christos 	return (nvlist_find(nvl, NV_TYPE_##TYPE, name) != NULL);	\
   1466   1.1  christos }
   1467   1.1  christos 
   1468   1.1  christos NVLIST_EXISTS(null, NULL)
   1469   1.1  christos NVLIST_EXISTS(bool, BOOL)
   1470   1.1  christos NVLIST_EXISTS(number, NUMBER)
   1471   1.1  christos NVLIST_EXISTS(string, STRING)
   1472   1.1  christos NVLIST_EXISTS(nvlist, NVLIST)
   1473   1.1  christos NVLIST_EXISTS(binary, BINARY)
   1474   1.1  christos NVLIST_EXISTS(bool_array, BOOL_ARRAY)
   1475   1.1  christos NVLIST_EXISTS(number_array, NUMBER_ARRAY)
   1476   1.1  christos NVLIST_EXISTS(string_array, STRING_ARRAY)
   1477   1.1  christos NVLIST_EXISTS(nvlist_array, NVLIST_ARRAY)
   1478   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   1479   1.1  christos NVLIST_EXISTS(descriptor, DESCRIPTOR)
   1480   1.1  christos NVLIST_EXISTS(descriptor_array, DESCRIPTOR_ARRAY)
   1481   1.1  christos #endif
   1482   1.1  christos 
   1483   1.1  christos #undef	NVLIST_EXISTS
   1484   1.1  christos 
   1485   1.1  christos void
   1486   1.1  christos nvlist_add_nvpair(nvlist_t *nvl, const nvpair_t *nvp)
   1487   1.1  christos {
   1488   1.1  christos 	nvpair_t *newnvp;
   1489   1.1  christos 
   1490   1.1  christos 	NVPAIR_ASSERT(nvp);
   1491   1.1  christos 
   1492   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1493   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1494   1.1  christos 		return;
   1495   1.1  christos 	}
   1496   1.1  christos 	if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
   1497   1.1  christos 		if (nvlist_exists(nvl, nvpair_name(nvp))) {
   1498   1.1  christos 			nvl->nvl_error = EEXIST;
   1499   1.1  christos 			ERRNO_SET(nvlist_error(nvl));
   1500   1.1  christos 			return;
   1501   1.1  christos 		}
   1502   1.1  christos 	}
   1503   1.1  christos 
   1504   1.1  christos 	newnvp = nvpair_clone(nvp);
   1505   1.1  christos 	if (newnvp == NULL) {
   1506   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1507   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1508   1.1  christos 		return;
   1509   1.1  christos 	}
   1510   1.1  christos 
   1511   1.1  christos 	nvpair_insert(&nvl->nvl_head, newnvp, nvl);
   1512   1.1  christos }
   1513   1.1  christos 
   1514   1.8     rmind #if !defined(_STANDALONE)
   1515   1.1  christos void
   1516   1.1  christos nvlist_add_stringf(nvlist_t *nvl, const char *name, const char *valuefmt, ...)
   1517   1.1  christos {
   1518   1.1  christos 	va_list valueap;
   1519   1.1  christos 
   1520   1.1  christos 	va_start(valueap, valuefmt);
   1521   1.1  christos 	nvlist_add_stringv(nvl, name, valuefmt, valueap);
   1522   1.1  christos 	va_end(valueap);
   1523   1.1  christos }
   1524   1.1  christos 
   1525   1.1  christos void
   1526   1.1  christos nvlist_add_stringv(nvlist_t *nvl, const char *name, const char *valuefmt,
   1527   1.1  christos     va_list valueap)
   1528   1.1  christos {
   1529   1.1  christos 	nvpair_t *nvp;
   1530   1.1  christos 
   1531   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1532   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1533   1.1  christos 		return;
   1534   1.1  christos 	}
   1535   1.1  christos 
   1536   1.1  christos 	nvp = nvpair_create_stringv(name, valuefmt, valueap);
   1537   1.1  christos 	if (nvp == NULL) {
   1538   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1539   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1540   1.1  christos 	} else {
   1541   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1542   1.1  christos 	}
   1543   1.1  christos }
   1544   1.4  christos #endif
   1545   1.1  christos 
   1546   1.1  christos void
   1547   1.1  christos nvlist_add_null(nvlist_t *nvl, const char *name)
   1548   1.1  christos {
   1549   1.1  christos 	nvpair_t *nvp;
   1550   1.1  christos 
   1551   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1552   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1553   1.1  christos 		return;
   1554   1.1  christos 	}
   1555   1.1  christos 
   1556   1.1  christos 	nvp = nvpair_create_null(name);
   1557   1.1  christos 	if (nvp == NULL) {
   1558   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1559   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1560   1.1  christos 	} else {
   1561   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1562   1.1  christos 	}
   1563   1.1  christos }
   1564   1.1  christos 
   1565   1.1  christos void
   1566   1.1  christos nvlist_add_binary(nvlist_t *nvl, const char *name, const void *value,
   1567   1.1  christos     size_t size)
   1568   1.1  christos {
   1569   1.1  christos 	nvpair_t *nvp;
   1570   1.1  christos 
   1571   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1572   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1573   1.1  christos 		return;
   1574   1.1  christos 	}
   1575   1.1  christos 
   1576   1.1  christos 	nvp = nvpair_create_binary(name, value, size);
   1577   1.1  christos 	if (nvp == NULL) {
   1578   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1579   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1580   1.1  christos 	} else {
   1581   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1582   1.1  christos 	}
   1583   1.1  christos }
   1584   1.1  christos 
   1585   1.1  christos 
   1586   1.1  christos #define	NVLIST_ADD(vtype, type)						\
   1587   1.1  christos void									\
   1588   1.1  christos nvlist_add_##type(nvlist_t *nvl, const char *name, vtype value)		\
   1589   1.1  christos {									\
   1590   1.1  christos 	nvpair_t *nvp;							\
   1591   1.1  christos 									\
   1592   1.1  christos 	if (nvlist_error(nvl) != 0) {					\
   1593   1.1  christos 		ERRNO_SET(nvlist_error(nvl));				\
   1594   1.1  christos 		return;							\
   1595   1.1  christos 	}								\
   1596   1.1  christos 									\
   1597   1.1  christos 	nvp = nvpair_create_##type(name, value);			\
   1598   1.1  christos 	if (nvp == NULL) {						\
   1599   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);		\
   1600   1.1  christos 		ERRNO_SET(nvl->nvl_error);				\
   1601   1.1  christos 	} else {							\
   1602   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);			\
   1603   1.1  christos 	}								\
   1604   1.1  christos }
   1605   1.1  christos 
   1606   1.1  christos NVLIST_ADD(bool, bool)
   1607   1.1  christos NVLIST_ADD(uint64_t, number)
   1608   1.1  christos NVLIST_ADD(const char *, string)
   1609   1.1  christos NVLIST_ADD(const nvlist_t *, nvlist)
   1610   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   1611   1.1  christos NVLIST_ADD(int, descriptor);
   1612   1.1  christos #endif
   1613   1.1  christos 
   1614   1.1  christos #undef	NVLIST_ADD
   1615   1.1  christos 
   1616   1.1  christos #define	NVLIST_ADD_ARRAY(vtype, type)					\
   1617   1.1  christos void									\
   1618   1.1  christos nvlist_add_##type##_array(nvlist_t *nvl, const char *name, vtype value,	\
   1619   1.1  christos     size_t nitems)							\
   1620   1.1  christos {									\
   1621   1.1  christos 	nvpair_t *nvp;							\
   1622   1.1  christos 									\
   1623   1.1  christos 	if (nvlist_error(nvl) != 0) {					\
   1624   1.1  christos 		ERRNO_SET(nvlist_error(nvl));				\
   1625   1.1  christos 		return;							\
   1626   1.1  christos 	}								\
   1627   1.1  christos 									\
   1628   1.1  christos 	nvp = nvpair_create_##type##_array(name, value, nitems);	\
   1629   1.1  christos 	if (nvp == NULL) {						\
   1630   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);		\
   1631   1.1  christos 		ERRNO_SET(nvl->nvl_error);				\
   1632   1.1  christos 	} else {							\
   1633   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);			\
   1634   1.1  christos 	}								\
   1635   1.1  christos }
   1636   1.1  christos 
   1637   1.1  christos NVLIST_ADD_ARRAY(const bool *, bool)
   1638   1.1  christos NVLIST_ADD_ARRAY(const uint64_t *, number)
   1639   1.1  christos NVLIST_ADD_ARRAY(const char * const *, string)
   1640   1.1  christos NVLIST_ADD_ARRAY(const nvlist_t * const *, nvlist)
   1641   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   1642   1.1  christos NVLIST_ADD_ARRAY(const int *, descriptor)
   1643   1.1  christos #endif
   1644   1.1  christos 
   1645   1.1  christos #undef	NVLIST_ADD_ARRAY
   1646   1.1  christos 
   1647   1.1  christos #define	NVLIST_APPEND_ARRAY(vtype, type, TYPE)				\
   1648   1.1  christos void									\
   1649   1.1  christos nvlist_append_##type##_array(nvlist_t *nvl, const char *name, vtype value)\
   1650   1.1  christos {									\
   1651   1.1  christos 	nvpair_t *nvp;							\
   1652   1.1  christos 									\
   1653   1.1  christos 	if (nvlist_error(nvl) != 0) {					\
   1654   1.1  christos 		ERRNO_SET(nvlist_error(nvl));				\
   1655   1.1  christos 		return;							\
   1656   1.1  christos 	}								\
   1657   1.1  christos 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);		\
   1658   1.1  christos 	if (nvp == NULL) {						\
   1659   1.1  christos 		nvlist_add_##type##_array(nvl, name, &value, 1);	\
   1660   1.1  christos 		return;							\
   1661   1.1  christos 	}								\
   1662   1.1  christos 	if (nvpair_append_##type##_array(nvp, value) == -1) {		\
   1663   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);		\
   1664   1.1  christos 		ERRNO_SET(nvl->nvl_error);				\
   1665   1.1  christos 	}								\
   1666   1.1  christos }
   1667   1.1  christos 
   1668   1.1  christos NVLIST_APPEND_ARRAY(const bool, bool, BOOL)
   1669   1.1  christos NVLIST_APPEND_ARRAY(const uint64_t, number, NUMBER)
   1670   1.1  christos NVLIST_APPEND_ARRAY(const char *, string, STRING)
   1671   1.1  christos NVLIST_APPEND_ARRAY(const nvlist_t *, nvlist, NVLIST)
   1672   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   1673   1.1  christos NVLIST_APPEND_ARRAY(const int, descriptor, DESCRIPTOR)
   1674   1.1  christos #endif
   1675   1.1  christos 
   1676   1.1  christos #undef	NVLIST_APPEND_ARRAY
   1677   1.1  christos 
   1678   1.1  christos bool
   1679   1.1  christos nvlist_move_nvpair(nvlist_t *nvl, nvpair_t *nvp)
   1680   1.1  christos {
   1681   1.1  christos 
   1682   1.1  christos 	NVPAIR_ASSERT(nvp);
   1683   1.1  christos 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == NULL);
   1684   1.1  christos 
   1685   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1686   1.1  christos 		nvpair_free(nvp);
   1687   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1688   1.1  christos 		return (false);
   1689   1.1  christos 	}
   1690   1.1  christos 	if ((nvl->nvl_flags & NV_FLAG_NO_UNIQUE) == 0) {
   1691   1.1  christos 		if (nvlist_exists(nvl, nvpair_name(nvp))) {
   1692   1.1  christos 			nvpair_free(nvp);
   1693   1.1  christos 			nvl->nvl_error = EEXIST;
   1694   1.1  christos 			ERRNO_SET(nvl->nvl_error);
   1695   1.1  christos 			return (false);
   1696   1.1  christos 		}
   1697   1.1  christos 	}
   1698   1.1  christos 
   1699   1.1  christos 	nvpair_insert(&nvl->nvl_head, nvp, nvl);
   1700   1.1  christos 	return (true);
   1701   1.1  christos }
   1702   1.1  christos 
   1703   1.1  christos void
   1704   1.1  christos nvlist_move_string(nvlist_t *nvl, const char *name, char *value)
   1705   1.1  christos {
   1706   1.1  christos 	nvpair_t *nvp;
   1707   1.1  christos 
   1708   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1709   1.1  christos 		nv_free(value);
   1710   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1711   1.1  christos 		return;
   1712   1.1  christos 	}
   1713   1.1  christos 
   1714   1.1  christos 	nvp = nvpair_move_string(name, value);
   1715   1.1  christos 	if (nvp == NULL) {
   1716   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1717   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1718   1.1  christos 	} else {
   1719   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1720   1.1  christos 	}
   1721   1.1  christos }
   1722   1.1  christos 
   1723   1.1  christos void
   1724   1.1  christos nvlist_move_nvlist(nvlist_t *nvl, const char *name, nvlist_t *value)
   1725   1.1  christos {
   1726   1.1  christos 	nvpair_t *nvp;
   1727   1.1  christos 
   1728   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1729   1.1  christos 		if (value != NULL && nvlist_get_nvpair_parent(value) != NULL)
   1730   1.1  christos 			nvlist_destroy(value);
   1731   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1732   1.1  christos 		return;
   1733   1.1  christos 	}
   1734   1.1  christos 
   1735   1.1  christos 	nvp = nvpair_move_nvlist(name, value);
   1736   1.1  christos 	if (nvp == NULL) {
   1737   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1738   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1739   1.1  christos 	} else {
   1740   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1741   1.1  christos 	}
   1742   1.1  christos }
   1743   1.1  christos 
   1744   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   1745   1.1  christos void
   1746   1.1  christos nvlist_move_descriptor(nvlist_t *nvl, const char *name, int value)
   1747   1.1  christos {
   1748   1.1  christos 	nvpair_t *nvp;
   1749   1.1  christos 
   1750   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1751   1.1  christos 		close(value);
   1752   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1753   1.1  christos 		return;
   1754   1.1  christos 	}
   1755   1.1  christos 
   1756   1.1  christos 	nvp = nvpair_move_descriptor(name, value);
   1757   1.1  christos 	if (nvp == NULL) {
   1758   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1759   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1760   1.1  christos 	} else {
   1761   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1762   1.1  christos 	}
   1763   1.1  christos }
   1764   1.1  christos #endif
   1765   1.1  christos 
   1766   1.1  christos void
   1767   1.1  christos nvlist_move_binary(nvlist_t *nvl, const char *name, void *value, size_t size)
   1768   1.1  christos {
   1769   1.1  christos 	nvpair_t *nvp;
   1770   1.1  christos 
   1771   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1772   1.1  christos 		nv_free(value);
   1773   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1774   1.1  christos 		return;
   1775   1.1  christos 	}
   1776   1.1  christos 
   1777   1.1  christos 	nvp = nvpair_move_binary(name, value, size);
   1778   1.1  christos 	if (nvp == NULL) {
   1779   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1780   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1781   1.1  christos 	} else {
   1782   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1783   1.1  christos 	}
   1784   1.1  christos }
   1785   1.1  christos 
   1786   1.1  christos void
   1787   1.1  christos nvlist_move_bool_array(nvlist_t *nvl, const char *name, bool *value,
   1788   1.1  christos     size_t nitems)
   1789   1.1  christos {
   1790   1.1  christos 	nvpair_t *nvp;
   1791   1.1  christos 
   1792   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1793   1.1  christos 		nv_free(value);
   1794   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1795   1.1  christos 		return;
   1796   1.1  christos 	}
   1797   1.1  christos 
   1798   1.1  christos 	nvp = nvpair_move_bool_array(name, value, nitems);
   1799   1.1  christos 	if (nvp == NULL) {
   1800   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1801   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1802   1.1  christos 	} else {
   1803   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1804   1.1  christos 	}
   1805   1.1  christos }
   1806   1.1  christos 
   1807   1.1  christos void
   1808   1.1  christos nvlist_move_string_array(nvlist_t *nvl, const char *name, char **value,
   1809   1.1  christos     size_t nitems)
   1810   1.1  christos {
   1811   1.1  christos 	nvpair_t *nvp;
   1812   1.1  christos 	size_t i;
   1813   1.1  christos 
   1814   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1815   1.1  christos 		if (value != NULL) {
   1816   1.1  christos 			for (i = 0; i < nitems; i++)
   1817   1.1  christos 				nv_free(value[i]);
   1818   1.1  christos 			nv_free(value);
   1819   1.1  christos 		}
   1820   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1821   1.1  christos 		return;
   1822   1.1  christos 	}
   1823   1.1  christos 
   1824   1.1  christos 	nvp = nvpair_move_string_array(name, value, nitems);
   1825   1.1  christos 	if (nvp == NULL) {
   1826   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1827   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1828   1.1  christos 	} else {
   1829   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1830   1.1  christos 	}
   1831   1.1  christos }
   1832   1.1  christos 
   1833   1.1  christos void
   1834   1.1  christos nvlist_move_nvlist_array(nvlist_t *nvl, const char *name, nvlist_t **value,
   1835   1.1  christos     size_t nitems)
   1836   1.1  christos {
   1837   1.1  christos 	nvpair_t *nvp;
   1838   1.1  christos 	size_t i;
   1839   1.1  christos 
   1840   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1841   1.1  christos 		if (value != NULL) {
   1842   1.1  christos 			for (i = 0; i < nitems; i++) {
   1843   1.1  christos 				if (nvlist_get_pararr(value[i], NULL) == NULL)
   1844   1.1  christos 					nvlist_destroy(value[i]);
   1845   1.1  christos 			}
   1846   1.1  christos 		}
   1847   1.1  christos 		nv_free(value);
   1848   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1849   1.1  christos 		return;
   1850   1.1  christos 	}
   1851   1.1  christos 
   1852   1.1  christos 	nvp = nvpair_move_nvlist_array(name, value, nitems);
   1853   1.1  christos 	if (nvp == NULL) {
   1854   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1855   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1856   1.1  christos 	} else {
   1857   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1858   1.1  christos 	}
   1859   1.1  christos }
   1860   1.1  christos 
   1861   1.1  christos void
   1862   1.1  christos nvlist_move_number_array(nvlist_t *nvl, const char *name, uint64_t *value,
   1863   1.1  christos     size_t nitems)
   1864   1.1  christos {
   1865   1.1  christos 	nvpair_t *nvp;
   1866   1.1  christos 
   1867   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1868   1.1  christos 		nv_free(value);
   1869   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1870   1.1  christos 		return;
   1871   1.1  christos 	}
   1872   1.1  christos 
   1873   1.1  christos 	nvp = nvpair_move_number_array(name, value, nitems);
   1874   1.1  christos 	if (nvp == NULL) {
   1875   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1876   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1877   1.1  christos 	} else {
   1878   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1879   1.1  christos 	}
   1880   1.1  christos }
   1881   1.1  christos 
   1882   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   1883   1.1  christos void
   1884   1.1  christos nvlist_move_descriptor_array(nvlist_t *nvl, const char *name, int *value,
   1885   1.1  christos     size_t nitems)
   1886   1.1  christos {
   1887   1.1  christos 	nvpair_t *nvp;
   1888   1.1  christos 	size_t i;
   1889   1.1  christos 
   1890   1.1  christos 	if (nvlist_error(nvl) != 0) {
   1891   1.1  christos 		if (value != 0) {
   1892   1.1  christos 			for (i = 0; i < nitems; i++)
   1893   1.1  christos 				close(value[i]);
   1894   1.1  christos 			nv_free(value);
   1895   1.1  christos 		}
   1896   1.1  christos 
   1897   1.1  christos 		ERRNO_SET(nvlist_error(nvl));
   1898   1.1  christos 		return;
   1899   1.1  christos 	}
   1900   1.1  christos 
   1901   1.1  christos 	nvp = nvpair_move_descriptor_array(name, value, nitems);
   1902   1.1  christos 	if (nvp == NULL) {
   1903   1.1  christos 		nvl->nvl_error = ERRNO_OR_DEFAULT(ENOMEM);
   1904   1.1  christos 		ERRNO_SET(nvl->nvl_error);
   1905   1.1  christos 	} else {
   1906   1.1  christos 		(void)nvlist_move_nvpair(nvl, nvp);
   1907   1.1  christos 	}
   1908   1.1  christos }
   1909   1.1  christos #endif
   1910   1.1  christos 
   1911   1.1  christos const nvpair_t *
   1912   1.1  christos nvlist_get_nvpair(const nvlist_t *nvl, const char *name)
   1913   1.1  christos {
   1914   1.1  christos 
   1915   1.1  christos 	return (nvlist_find(nvl, NV_TYPE_NONE, name));
   1916   1.1  christos }
   1917   1.1  christos 
   1918   1.1  christos #define	NVLIST_GET(ftype, type, TYPE)					\
   1919   1.1  christos ftype									\
   1920   1.1  christos nvlist_get_##type(const nvlist_t *nvl, const char *name)		\
   1921   1.1  christos {									\
   1922   1.1  christos 	const nvpair_t *nvp;						\
   1923   1.1  christos 									\
   1924   1.1  christos 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
   1925   1.1  christos 	if (nvp == NULL)						\
   1926   1.1  christos 		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
   1927   1.1  christos 	return (nvpair_get_##type(nvp));				\
   1928   1.1  christos }
   1929   1.1  christos 
   1930   1.1  christos NVLIST_GET(bool, bool, BOOL)
   1931   1.1  christos NVLIST_GET(uint64_t, number, NUMBER)
   1932   1.1  christos NVLIST_GET(const char *, string, STRING)
   1933   1.1  christos NVLIST_GET(const nvlist_t *, nvlist, NVLIST)
   1934   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   1935   1.1  christos NVLIST_GET(int, descriptor, DESCRIPTOR)
   1936   1.1  christos #endif
   1937   1.1  christos 
   1938   1.1  christos #undef	NVLIST_GET
   1939   1.1  christos 
   1940   1.1  christos const void *
   1941   1.1  christos nvlist_get_binary(const nvlist_t *nvl, const char *name, size_t *sizep)
   1942   1.1  christos {
   1943   1.1  christos 	nvpair_t *nvp;
   1944   1.1  christos 
   1945   1.1  christos 	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
   1946   1.1  christos 	if (nvp == NULL)
   1947   1.1  christos 		nvlist_report_missing(NV_TYPE_BINARY, name);
   1948   1.1  christos 
   1949   1.1  christos 	return (nvpair_get_binary(nvp, sizep));
   1950   1.1  christos }
   1951   1.1  christos 
   1952   1.1  christos #define	NVLIST_GET_ARRAY(ftype, type, TYPE)				\
   1953   1.1  christos ftype									\
   1954   1.1  christos nvlist_get_##type##_array(const nvlist_t *nvl, const char *name,	\
   1955   1.1  christos     size_t *nitems)							\
   1956   1.1  christos {									\
   1957   1.1  christos 	const nvpair_t *nvp;						\
   1958   1.1  christos 									\
   1959   1.1  christos 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);		\
   1960   1.1  christos 	if (nvp == NULL)						\
   1961   1.1  christos 		nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name);	\
   1962   1.1  christos 	return (nvpair_get_##type##_array(nvp, nitems));		\
   1963   1.1  christos }
   1964   1.1  christos 
   1965   1.1  christos NVLIST_GET_ARRAY(const bool *, bool, BOOL)
   1966   1.1  christos NVLIST_GET_ARRAY(const uint64_t *, number, NUMBER)
   1967   1.1  christos NVLIST_GET_ARRAY(const char * const *, string, STRING)
   1968   1.1  christos NVLIST_GET_ARRAY(const nvlist_t * const *, nvlist, NVLIST)
   1969   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   1970   1.1  christos NVLIST_GET_ARRAY(const int *, descriptor, DESCRIPTOR)
   1971   1.1  christos #endif
   1972   1.1  christos 
   1973   1.1  christos #undef	NVLIST_GET_ARRAY
   1974   1.1  christos 
   1975   1.1  christos #define	NVLIST_TAKE(ftype, type, TYPE)					\
   1976   1.1  christos ftype									\
   1977   1.1  christos nvlist_take_##type(nvlist_t *nvl, const char *name)			\
   1978   1.1  christos {									\
   1979   1.1  christos 	nvpair_t *nvp;							\
   1980   1.1  christos 	ftype value;							\
   1981   1.1  christos 									\
   1982   1.1  christos 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE, name);			\
   1983   1.1  christos 	if (nvp == NULL)						\
   1984   1.1  christos 		nvlist_report_missing(NV_TYPE_##TYPE, name);		\
   1985   1.1  christos 	value = (ftype)(intptr_t)nvpair_get_##type(nvp);		\
   1986   1.1  christos 	nvlist_remove_nvpair(nvl, nvp);					\
   1987   1.1  christos 	nvpair_free_structure(nvp);					\
   1988   1.1  christos 	return (value);							\
   1989   1.1  christos }
   1990   1.1  christos 
   1991   1.1  christos NVLIST_TAKE(bool, bool, BOOL)
   1992   1.1  christos NVLIST_TAKE(uint64_t, number, NUMBER)
   1993   1.1  christos NVLIST_TAKE(char *, string, STRING)
   1994   1.1  christos NVLIST_TAKE(nvlist_t *, nvlist, NVLIST)
   1995   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   1996   1.1  christos NVLIST_TAKE(int, descriptor, DESCRIPTOR)
   1997   1.1  christos #endif
   1998   1.1  christos 
   1999   1.1  christos #undef	NVLIST_TAKE
   2000   1.1  christos 
   2001   1.1  christos void *
   2002   1.1  christos nvlist_take_binary(nvlist_t *nvl, const char *name, size_t *sizep)
   2003   1.1  christos {
   2004   1.1  christos 	nvpair_t *nvp;
   2005   1.1  christos 	void *value;
   2006   1.1  christos 
   2007   1.1  christos 	nvp = nvlist_find(nvl, NV_TYPE_BINARY, name);
   2008   1.1  christos 	if (nvp == NULL)
   2009   1.1  christos 		nvlist_report_missing(NV_TYPE_BINARY, name);
   2010   1.1  christos 
   2011   1.1  christos 	value = (void *)(intptr_t)nvpair_get_binary(nvp, sizep);
   2012   1.1  christos 	nvlist_remove_nvpair(nvl, nvp);
   2013   1.1  christos 	nvpair_free_structure(nvp);
   2014   1.1  christos 	return (value);
   2015   1.1  christos }
   2016   1.1  christos 
   2017   1.1  christos #define	NVLIST_TAKE_ARRAY(ftype, type, TYPE)				\
   2018   1.1  christos ftype									\
   2019   1.1  christos nvlist_take_##type##_array(nvlist_t *nvl, const char *name,		\
   2020   1.1  christos     size_t *nitems)							\
   2021   1.1  christos {									\
   2022   1.1  christos 	nvpair_t *nvp;							\
   2023   1.1  christos 	ftype value;							\
   2024   1.1  christos 									\
   2025   1.1  christos 	nvp = nvlist_find(nvl, NV_TYPE_##TYPE##_ARRAY, name);		\
   2026   1.1  christos 	if (nvp == NULL)						\
   2027   1.1  christos 		nvlist_report_missing(NV_TYPE_##TYPE##_ARRAY, name);	\
   2028   1.1  christos 	value = (ftype)(intptr_t)nvpair_get_##type##_array(nvp, nitems);\
   2029   1.1  christos 	nvlist_remove_nvpair(nvl, nvp);					\
   2030   1.1  christos 	nvpair_free_structure(nvp);					\
   2031   1.1  christos 	return (value);							\
   2032   1.1  christos }
   2033   1.1  christos 
   2034   1.1  christos NVLIST_TAKE_ARRAY(bool *, bool, BOOL)
   2035   1.1  christos NVLIST_TAKE_ARRAY(uint64_t *, number, NUMBER)
   2036   1.1  christos NVLIST_TAKE_ARRAY(char **, string, STRING)
   2037   1.1  christos NVLIST_TAKE_ARRAY(nvlist_t **, nvlist, NVLIST)
   2038   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   2039   1.1  christos NVLIST_TAKE_ARRAY(int *, descriptor, DESCRIPTOR)
   2040   1.1  christos #endif
   2041   1.1  christos 
   2042   1.1  christos void
   2043   1.1  christos nvlist_remove_nvpair(nvlist_t *nvl, nvpair_t *nvp)
   2044   1.1  christos {
   2045   1.1  christos 
   2046   1.1  christos 	NVLIST_ASSERT(nvl);
   2047   1.1  christos 	NVPAIR_ASSERT(nvp);
   2048   1.1  christos 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
   2049   1.1  christos 
   2050   1.1  christos 	nvpair_remove(&nvl->nvl_head, nvp, nvl);
   2051   1.1  christos }
   2052   1.1  christos 
   2053   1.1  christos void
   2054   1.1  christos nvlist_free(nvlist_t *nvl, const char *name)
   2055   1.1  christos {
   2056   1.1  christos 
   2057   1.1  christos 	nvlist_free_type(nvl, name, NV_TYPE_NONE);
   2058   1.1  christos }
   2059   1.1  christos 
   2060   1.1  christos #define	NVLIST_FREE(type, TYPE)						\
   2061   1.1  christos void									\
   2062   1.1  christos nvlist_free_##type(nvlist_t *nvl, const char *name)			\
   2063   1.1  christos {									\
   2064   1.1  christos 									\
   2065   1.1  christos 	nvlist_free_type(nvl, name, NV_TYPE_##TYPE);			\
   2066   1.1  christos }
   2067   1.1  christos 
   2068   1.1  christos NVLIST_FREE(null, NULL)
   2069   1.1  christos NVLIST_FREE(bool, BOOL)
   2070   1.1  christos NVLIST_FREE(number, NUMBER)
   2071   1.1  christos NVLIST_FREE(string, STRING)
   2072   1.1  christos NVLIST_FREE(nvlist, NVLIST)
   2073   1.1  christos NVLIST_FREE(binary, BINARY)
   2074   1.1  christos NVLIST_FREE(bool_array, BOOL_ARRAY)
   2075   1.1  christos NVLIST_FREE(number_array, NUMBER_ARRAY)
   2076   1.1  christos NVLIST_FREE(string_array, STRING_ARRAY)
   2077   1.1  christos NVLIST_FREE(nvlist_array, NVLIST_ARRAY)
   2078   1.2  christos #if !defined(_KERNEL) && !defined(_STANDALONE)
   2079   1.1  christos NVLIST_FREE(descriptor, DESCRIPTOR)
   2080   1.1  christos NVLIST_FREE(descriptor_array, DESCRIPTOR_ARRAY)
   2081   1.1  christos #endif
   2082   1.1  christos 
   2083   1.1  christos #undef	NVLIST_FREE
   2084   1.1  christos 
   2085   1.1  christos void
   2086   1.1  christos nvlist_free_nvpair(nvlist_t *nvl, nvpair_t *nvp)
   2087   1.1  christos {
   2088   1.1  christos 
   2089   1.1  christos 	NVLIST_ASSERT(nvl);
   2090   1.1  christos 	NVPAIR_ASSERT(nvp);
   2091   1.1  christos 	PJDLOG_ASSERT(nvpair_nvlist(nvp) == nvl);
   2092   1.1  christos 
   2093   1.1  christos 	nvlist_remove_nvpair(nvl, nvp);
   2094   1.1  christos 	nvpair_free(nvp);
   2095   1.1  christos }
   2096   1.1  christos 
   2097