---
name: "nvlist"
section: "9"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["freebsd"]
url: "https://new.carta.tech/libnv"
---

# nvlist(9)

library for name/value pairs

Part of [libnv(9)](/libnv/9.md).

## NAME

**nvlist\_create**, **nvlist\_destroy**, **nvlist\_error**, **nvlist\_set\_error**, **nvlist\_empty**, **nvlist\_flags**, **nvlist\_exists**, **nvlist\_free**, **nvlist\_clone**, **nvlist\_dump**, **nvlist\_fdump**, **nvlist\_size**, **nvlist\_pack**, **nvlist\_unpack**, **nvlist\_send**, **nvlist\_recv**, **nvlist\_xfer**, **nvlist\_in\_array**, **nvlist\_next**, **nvlist\_add**, **nvlist\_move**, **nvlist\_get**, **nvlist\_take**, **nvlist\_append** – library for name/value pairs

## LIBRARY

library “libnv”

## SYNOPSIS

**#include \<sys/nv.h\>**

*nvlist\_t \**\

**nvlist\_create**(*int flags*);

*void*\

**nvlist\_destroy**(*nvlist\_t \*nvl*);

*int*\

**nvlist\_error**(*const nvlist\_t \*nvl*);

*void*\

**nvlist\_set\_error**(*nvlist\_t \*nvl*, *int error*);

*bool*\

**nvlist\_empty**(*const nvlist\_t \*nvl*);

*int*\

**nvlist\_flags**(*const nvlist\_t \*nvl*);

*bool*\

**nvlist\_in\_array**(*const nvlist\_t \*nvl*);

*nvlist\_t \**\

**nvlist\_clone**(*const nvlist\_t \*nvl*);

*void*\

**nvlist\_dump**(*const nvlist\_t \*nvl*, *int fd*);

*void*\

**nvlist\_fdump**(*const nvlist\_t \*nvl*, *FILE \*fp*);

*size\_t*\

**nvlist\_size**(*const nvlist\_t \*nvl*);

*void \**\

**nvlist\_pack**(*const nvlist\_t \*nvl*, *size\_t \*sizep*);

*nvlist\_t \**\

**nvlist\_unpack**(*const void \*buf*, *size\_t size*, *int flags*);

*int*\

**nvlist\_send**(*int sock*, *const nvlist\_t \*nvl*);

*nvlist\_t \**\

**nvlist\_recv**(*int sock*, *int flags*);

*nvlist\_t \**\

**nvlist\_xfer**(*int sock*, *nvlist\_t \*nvl*, *int flags*);

*const char \**\

**nvlist\_next**(*const nvlist\_t \*nvl*, *int \*typep*, *void \*\*cookiep*);

*bool*\

**nvlist\_exists**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_type**(*const nvlist\_t \*nvl*, *const char \*name*, *int type*);

*bool*\

**nvlist\_exists\_null**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_bool**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_number**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_string**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_nvlist**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_descriptor**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_binary**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_bool\_array**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_number\_array**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_string\_array**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_nvlist\_array**(*const nvlist\_t \*nvl*, *const char \*name*);

*bool*\

**nvlist\_exists\_descriptor\_array**(*const nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_add\_null**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_add\_bool**(*nvlist\_t \*nvl*, *const char \*name*, *bool value*);

*void*\

**nvlist\_add\_number**(*nvlist\_t \*nvl*, *const char \*name*, *uint64\_t value*);

*void*\

**nvlist\_add\_string**(*nvlist\_t \*nvl*, *const char \*name*, *const char \*value*);

*void*\

**nvlist\_add\_stringf**(*nvlist\_t \*nvl*, *const char \*name*, *const char \*valuefmt*, *...*);

*void*\

**nvlist\_add\_stringv**(*nvlist\_t \*nvl*, *const char \*name*, *const char \*valuefmt*, *va\_list valueap*);

*void*\

**nvlist\_add\_nvlist**(*nvlist\_t \*nvl*, *const char \*name*, *const nvlist\_t \*value*);

*void*\

**nvlist\_add\_descriptor**(*nvlist\_t \*nvl*, *const char \*name*, *int value*);

*void*\

**nvlist\_add\_binary**(*nvlist\_t \*nvl*, *const char \*name*, *const void \*value*, *size\_t size*);

*void*\

**nvlist\_add\_bool\_array**(*nvlist\_t \*nvl*, *const char \*name*, *const bool \*value*, *size\_t nitems*);

*void*\

**nvlist\_add\_number\_array**(*nvlist\_t \*nvl*, *const char \*name*, *const uint64\_t \*value*, *size\_t nitems*);

*void*\

**nvlist\_add\_string\_array**(*nvlist\_t \*nvl*, *const char \*name*, *const char \* const \* value*, *size\_t nitems*);

*void*\

**nvlist\_add\_nvlist\_array**(*nvlist\_t \*nvl*, *const char \*name*, *const nvlist\_t \* const \* value*, *size\_t nitems*);

*void*\

**nvlist\_add\_descriptor\_array**(*nvlist\_t \*nvl*, *const char \*name*, *const int \*value*, *size\_t nitems*);

*void*\

**nvlist\_move\_string**(*nvlist\_t \*nvl*, *const char \*name*, *char \*value*);

*void*\

**nvlist\_move\_nvlist**(*nvlist\_t \*nvl*, *const char \*name*, *nvlist\_t \*value*);

*void*\

**nvlist\_move\_descriptor**(*nvlist\_t \*nvl*, *const char \*name*, *int value*);

*void*\

**nvlist\_move\_binary**(*nvlist\_t \*nvl*, *const char \*name*, *void \*value*, *size\_t size*);

*void*\

**nvlist\_move\_bool\_array**(*nvlist\_t \*nvl*, *const char \*name*, *bool \*value*, *size\_t nitems*);

*void*\

**nvlist\_move\_number\_array**(*nvlist\_t \*nvl*, *const char \*name*, *uint64\_t \*value*, *size\_t nitems*);

*void*\

**nvlist\_move\_string\_array**(*nvlist\_t \*nvl*, *const char \*name*, *char \*\*value*, *size\_t nitems*);

*void*\

**nvlist\_move\_nvlist\_array**(*nvlist\_t \*nvl*, *const char \*name*, *nvlist\_t \*\*value*, *size\_t nitems*);

*void*\

**nvlist\_move\_descriptor\_array**(*nvlist\_t \*nvl*, *const char \*name*, *int \*value*, *size\_t nitems*);

*bool*\

**nvlist\_get\_bool**(*const nvlist\_t \*nvl*, *const char \*name*);

*uint64\_t*\

**nvlist\_get\_number**(*const nvlist\_t \*nvl*, *const char \*name*);

*const char \**\

**nvlist\_get\_string**(*const nvlist\_t \*nvl*, *const char \*name*);

*const nvlist\_t \**\

**nvlist\_get\_nvlist**(*const nvlist\_t \*nvl*, *const char \*name*);

*int*\

**nvlist\_get\_descriptor**(*const nvlist\_t \*nvl*, *const char \*name*);

*const void \**\

**nvlist\_get\_binary**(*const nvlist\_t \*nvl*, *const char \*name*, *size\_t \*sizep*);

*const bool \**\

**nvlist\_get\_bool\_array**(*const nvlist\_t \*nvl*, *const char \*name*, *size\_t \*nitems*);

*const uint64\_t \**\

**nvlist\_get\_number\_array**(*const nvlist\_t \*nvl*, *const char \*name*, *size\_t \*nitems*);

*const char \* const \**\

**nvlist\_get\_string\_array**(*const nvlist\_t \*nvl*, *const char \*name*, *size\_t \*nitems*);

*const nvlist\_t \* const \**\

**nvlist\_get\_nvlist\_array**(*const nvlist\_t \*nvl*, *const char \*name*, *size\_t \*nitems*);

*const int \**\

**nvlist\_get\_descriptor\_array**(*const nvlist\_t \*nvl*, *const char \*name*, *size\_t \*nitems*);

*const nvlist\_t \**\

**nvlist\_get\_parent**(*const nvlist\_t \*nvl*, *void \*\*cookiep*);

*const nvlist\_t \**\

**nvlist\_get\_array\_next**(*const nvlist\_t \*nvl*);

*const nvlist\_t \**\

**nvlist\_get\_pararr**(*const nvlist\_t \*nvl*, *void \*\*cookiep*);

*bool*\

**nvlist\_take\_bool**(*nvlist\_t \*nvl*, *const char \*name*);

*uint64\_t*\

**nvlist\_take\_number**(*nvlist\_t \*nvl*, *const char \*name*);

*char \**\

**nvlist\_take\_string**(*nvlist\_t \*nvl*, *const char \*name*);

*nvlist\_t \**\

**nvlist\_take\_nvlist**(*nvlist\_t \*nvl*, *const char \*name*);

*int*\

**nvlist\_take\_descriptor**(*nvlist\_t \*nvl*, *const char \*name*);

*void \**\

**nvlist\_take\_binary**(*nvlist\_t \*nvl*, *const char \*name*, *size\_t \*sizep*);

*bool \**\

**nvlist\_take\_bool\_array**(*nvlist\_t \*nvl*, *const char \*name*, *size\_t \*nitems*);

*uint64\_t \*\**\

**nvlist\_take\_number\_array**(*nvlist\_t \*nvl*, *const char \*name*, *size\_t \*nitems*);

*char \*\**\

**nvlist\_take\_string\_array**(*nvlist\_t \*nvl*, *const char \*name*, *size\_t \*nitems*);

*nvlist\_t \*\**\

**nvlist\_take\_nvlist\_array**(*nvlist\_t \*nvl*, *const char \*name*, *size\_t \*nitems*);

*int \**\

**nvlist\_take\_descriptor\_array**(*nvlist\_t \*nvl*, *const char \*name*, *size\_t \*nitems*);

*void*\

**nvlist\_append\_bool\_array**(*nvlist\_t \*nvl*, *const char \*name*, *const bool value*);

*void*\

**nvlist\_append\_number\_array**(*nvlist\_t \*nvl*, *const char \*name*, *const uint64\_t value*);

*void*\

**nvlist\_append\_string\_array**(*nvlist\_t \*nvl*, *const char \*name*, *const char \* const value*);

*void*\

**nvlist\_append\_nvlist\_array**(*nvlist\_t \*nvl*, *const char \*name*, *const nvlist\_t \* const value*);

*void*\

**nvlist\_append\_descriptor\_array**(*nvlist\_t \*nvl*, *const char \*name*, *int value*);

*void*\

**nvlist\_free**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_type**(*nvlist\_t \*nvl*, *const char \*name*, *int type*);

*void*\

**nvlist\_free\_null**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_bool**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_number**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_string**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_nvlist**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_descriptor**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_binary**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_bool\_array**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_number\_array**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_string\_array**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_nvlist\_array**(*nvlist\_t \*nvl*, *const char \*name*);

*void*\

**nvlist\_free\_descriptor\_array**(*nvlist\_t \*nvl*, *const char \*name*);

## DESCRIPTION

The **libnv** library permits creating and managing name value pairs as well as sending and receiving them over sockets. A group (list) of name value pairs is called an **nvlist**. The API supports the following data types for values:

- **null** (**NV\_TYPE\_NULL**)

  There is no data associated with the name.

- **bool** (**NV\_TYPE\_BOOL**)

  The value can be either true or false.

- **number** (**NV\_TYPE\_NUMBER**)

  The value is a number stored as *uint64\_t*.

- **string** (**NV\_TYPE\_STRING**)

  The value is a C string.

- **nvlist** (**NV\_TYPE\_NVLIST**)

  The value is a nested nvlist.

- **descriptor** (**NV\_TYPE\_DESCRIPTOR**)

  The value is a file descriptor. Note that file descriptors can be sent only over [unix(4)](/unix/4.md) domain sockets.

- **binary** (**NV\_TYPE\_BINARY**)

  The value is a binary buffer.

- **bool** **array** (**NV\_TYPE\_BOOL\_ARRAY**)

  The value is an array of boolean values.

- **number** **array** (**NV\_TYPE\_NUMBER\_ARRAY**)

  The value is an array of numbers, each stored as *uint64\_t*.

- **string** **array** (**NV\_TYPE\_STRING\_ARRAY**)

  The value is an array of C strings.

- **nvlist** **array** (**NV\_TYPE\_NVLIST\_ARRAY**)

  The value is an array of nvlists. When an nvlist is added to an array, it becomes part of the primary nvlist. Traversing these arrays can be done using the **nvlist\_get\_array\_next**() and **nvlist\_get\_pararr**() functions.

- **descriptor** **array** (**NV\_TYPE\_DESCRIPTOR\_ARRAY**)

  The value is an array of files descriptors.

The **nvlist\_create**() function allocates memory and initializes an nvlist.

The following flags can be provided:

- NV\_FLAG\_IGNORE\_CASE

  Perform case-insensitive lookups of provided names.

- NV\_FLAG\_NO\_UNIQUE

  Names in the nvlist do not have to be unique.

The **nvlist\_destroy**() function destroys the given nvlist. This function does nothing if *nvl* is NULL. This function never modifies *errno*.

The **nvlist\_error**() function returns the first error set on *nvl*. If *nvl* is not in the error state, this function returns zero. If *nvl* is NULL, ENOMEM is returned.

The **nvlist\_set\_error**() function sets an the error value for *nvl*. Subsequent calls to **nvlist\_error**() will return *error*. This function cannot be used to clear the error state from an nvlist. This function does nothing if the nvlist is already in the error state.

The **nvlist\_empty**() function returns true if *nvl* is empty and false otherwise. The nvlist must not be in the error state.

The **nvlist\_flags**() function returns the flags used to create *nvl* with the **nvlist\_create**(), **nvlist\_recv**(), **nvlist\_unpack**(), or **nvlist\_xfer**() functions.

The **nvlist\_in\_array**() function returns true if *nvl* is part of an array that is a member of another nvlist.

The **nvlist\_clone**() function clones *nvl*. The clone shares no resources with its origin. This also means that all file descriptors that are part of the nvlist will be duplicated with the [dup(2)](/dup/2.md) system call before placing them in the clone.

The **nvlist\_dump**() function dumps nvlist content for debugging purposes to the file descriptor *fd*.

The **nvlist\_fdump**() dumps nvlist content for debugging purposes to the file stream *fp*.

The **nvlist\_size**() function returns the size of the binary buffer that would be generated by the **nvlist\_pack**() function.

The **nvlist\_pack**() function converts the given nvlist to a binary buffer. The function allocates memory for the buffer which should be freed with the [free(3)](/free/3.md) function. If the *sizep* argument is not NULL, the size of the buffer is stored there. This function returns NULL in case of an error (allocation failure). If the nvlist contains any file descriptors NULL will be returned. The nvlist must not be in the error state.

The **nvlist\_unpack**() function converts a binary buffer to a new nvlist. The *flags* argument has the same meaning as the *flags* argument passed to **nvlist\_create**(). If *flags* do not match the flags used to create the initial nvlist before it was packed, this function will fail. The flags of nested nvlists are not validated by this function. The caller is responsible for validating the flags on any nested nvlists using **nvlist\_flags**(). This function returns the new nvlist on success or NULL in case of an error.

The **nvlist\_send**() function sends *nvl* over the socket *sock*. Note that nvlists that contain file descriptors can only be sent over [unix(4)](/unix/4.md) domain sockets.

The **nvlist\_recv**() function receives an nvlist over the socket *sock*. As with **nvlist\_unpack**(), the *flags* argument is used to construct the new nvlist and must match the flags used to construct the original nvlist written to *sock* by the peer. The flags of nested nvlists are not validated by this function. The caller is responsible for validating the flags on any nested nvlists using **nvlist\_flags**(). This function returns the new nvlist on success or NULL in case of an error.

The **nvlist\_xfer**() function sends *nvl* over the socket *sock* argument and then receives a new nvlist over the same socket. The *flags* argument applies to the new nvlist similar to **nvlist\_recv**(). The nvlist *nvl* is always destroyed. This function returns the new nvlist on success or NULL in case of an error.

The **nvlist\_next**() function iterates over *nvl* returning the names and types of subsequent elements. The *cookiep* argument determines which element is returned. If *\*cookiep* is NULL, the values for the first element in the list are returned. Otherwise, *\*cookiep* should contain the result of a prior call to **nvlist\_next**() in which case values for the next element from *nvl* are returned. This function returns NULL when there are no more elements on *nvl*. The *typep* argument can be NULL. Elements may not be removed from *nvl* the nvlist while traversing it. *nvl* must not be in the error state. Additional actions can be performed on an element identified by a cookie via the [cnv(9)](/cnv/9.md) API .

The **nvlist\_exists**() function returns true if an element named *name* exists in *nvl* (regardless of type) or false otherwise. The nvlist must not be in the error state.

The **nvlist\_exists\_type**() function returns true if an element named *name* of type *type* exists or false otherwise. The nvlist must not be in the error state.

The **nvlist\_exists\_null**(), **nvlist\_exists\_bool**(), **nvlist\_exists\_number**(), **nvlist\_exists\_string**(), **nvlist\_exists\_nvlist**(), **nvlist\_exists\_descriptor**(), **nvlist\_exists\_binary**(), **nvlist\_exists\_bool\_array**(), **nvlist\_exists\_number\_array**(), **nvlist\_exists\_string\_array**(), **nvlist\_exists\_nvlist\_array**(), **nvlist\_exists\_descriptor\_array**() functions return true if element named *name* with the type determined by the function name exists or false otherwise. The nvlist must not be in the error state.

The **nvlist\_add\_null**(), **nvlist\_add\_bool**(), **nvlist\_add\_number**(), **nvlist\_add\_string**(), **nvlist\_add\_stringf**(), **nvlist\_add\_stringv**(), **nvlist\_add\_nvlist**(), **nvlist\_add\_descriptor**(), **nvlist\_add\_binary**(), **nvlist\_add\_bool\_array**(), **nvlist\_add\_number\_array**(), **nvlist\_add\_string\_array**(), **nvlist\_add\_nvlist\_array**(), **nvlist\_add\_descriptor\_array**() functions add an element to *nvl*. When adding a string or binary buffer, these functions allocate memory and copy the data. When adding an nvlist, the *value* nvlist is cloned and the clone is added to *nvl*. When adding a file descriptor, the descriptor is duplicated via the [dup(2)](/dup/2.md) system call and the new file descriptor is added. The array functions fail if there are any NULL elements in the array, or if the array pointer is NULL. If an error occurs while adding a new element, an internal error is set which can be examined using the **nvlist\_error**() function.

The **nvlist\_move\_string**(), **nvlist\_move\_nvlist**(), **nvlist\_move\_descriptor**(), **nvlist\_move\_binary**(), **nvlist\_move\_bool\_array**(), **nvlist\_move\_number\_array**(), **nvlist\_move\_string\_array**(), **nvlist\_move\_nvlist\_array**(), **nvlist\_move\_descriptor\_array**() functions add an element to *nvl*, but unlike the **nvlist\_add\_\<type\>**() functions they consume the given resource. For string, file descriptor, binary buffer, or nvlist values, no value should be moved into an nvlist multiple times; doing so will cause that value to be freed multiple times. Note that strings or binary buffers must be allocated with [malloc(3)](/malloc/3.md), and the pointers will be released via [free(3)](/free/3.md) when *nvl* is destroyed. The array functions fail if there are any NULL elements, or if the array pointer is NULL. If an error occurs while adding new element, the resource is destroyed and an internal error is set which can be examined using the **nvlist\_error**() function.

The **nvlist\_get\_bool**(), **nvlist\_get\_number**(), **nvlist\_get\_string**(), **nvlist\_get\_nvlist**(), **nvlist\_get\_descriptor**(), **nvlist\_get\_binary**(), **nvlist\_get\_bool\_array**(), **nvlist\_get\_number\_array**(), **nvlist\_get\_string\_array**(), **nvlist\_get\_nvlist\_array**(), **nvlist\_get\_descriptor\_array**() functions return the value of the first element in *nvl* named *name*. For string, nvlist, file descriptor, binary buffer, or array values, the returned resource must not be modified - it still belongs to *nvl*.

If an element named *name* does not exist, the program aborts. To avoid this, the caller should check for the existence of the element before trying to obtain the value or use the [dnv(9)](/dnv/9.md) extension which provides a default value in the case of a missing element.

The nvlist must not be in the error state.

The **nvlist\_get\_parent**() function returns the parent nvlist of *nvl*.

The **nvlist\_get\_array\_next**() function returns the next element after *nvl* from an array of nvlists. If *nvl* is not in an array of nvlists or it is the last element, this function returns NULL. An nvlist is only in an nvlist array if it was added to an nvlist array using **nvlist\_add\_nvlist\_array**(), **nvlist\_append\_nvlist\_array**(), or **nvlist\_move\_nvlist\_array**().

The **nvlist\_get\_pararr**() function returns the next element after **nvl**() from an array of nvlists. If **nvl**() is the last element in an array of nvlists, the parent nvlist of *nvl*, *is* returned. If **nvl**() is not in an array of nvlists, NULL is returned.

The **nvlist\_take\_bool**(), **nvlist\_take\_number**(), **nvlist\_take\_string**(), **nvlist\_take\_nvlist**(), **nvlist\_take\_descriptor**(), **nvlist\_take\_binary**(), **nvlist\_take\_bool\_array**(), **nvlist\_take\_number\_array**(), **nvlist\_take\_string\_array**(), **nvlist\_take\_nvlist\_array**(), **nvlist\_take\_descriptor\_array**() functions return the value of the element named *name* and remove the element from *nvl*. For string and binary buffer values, the caller is responsible for freeing the returned value using the [free(3)](/free/3.md) function. For nvlist values, the caller is responsible for destroying the returned nvlist using the **nvlist\_destroy**() function. For file descriptor values, the caller is responsible for closing the returned descriptor using the **close**(*2*) system call. For array values, the caller is responsible for destroying every element of the array based on the element type. In addition, the caller must also free the pointer to the array using the [free(3)](/free/3.md) function.

If an element named *name* does not exist, the program aborts. To avoid this, the caller should check for the existence of the element before trying to obtain the value or use the [dnv(9)](/dnv/9.md) extension which provides a default value in the case of a missing element.

The nvlist must not be in the error state.

The **nvlist\_append\_bool\_array**(), **nvlist\_append\_number\_array**(), **nvlist\_append\_string\_array**(), **nvlist\_append\_nvlist\_array**(), **nvlist\_append\_descriptor\_array**() functions append an element to an existing array using the same semantics as the add functions (that is, the element will be copied when applicable). If the array named *name* does not exist, then it will be created as if using the **nvlist\_add\_\<type\>\_array**() function. If an error occurs while appending a new element, an internal error is set on *nvl*.

The **nvlist\_free**() function removes the first element named *name* from *nvl* (regardless of type) and frees all resources associated with it. If no element named *name* exists, the program aborts. The nvlist must not be in the error state.

The **nvlist\_free\_type**() function removes the first element named *name* of type *type* from *nvl* and frees all resources associated with it. If no element named *name* of type *type* exists, the program aborts. The nvlist must not be in the error state.

The **nvlist\_free\_null**(), **nvlist\_free\_bool**(), **nvlist\_free\_number**(), **nvlist\_free\_string**(), **nvlist\_free\_nvlist**(), **nvlist\_free\_descriptor**(), **nvlist\_free\_binary**(), **nvlist\_free\_bool\_array**(), **nvlist\_free\_number\_array**(), **nvlist\_free\_string\_array**(), **nvlist\_free\_nvlist\_array**(), **nvlist\_free\_descriptor\_array**() functions remove the first element named *name* with the type determined by the function name from *nvl* free all resources associated with it. If no element named *name* with the appropriate type exists, the program aborts. The nvlist must not be in the error state.

### Notes

The **nvlist\_pack**() and **nvlist\_unpack**() functions handle byte-order conversions, so binary buffers can be packed and unpacked on hosts with different endianness.

The **nvlist\_recv**(), **nvlist\_send**(), and **nvlist\_xfer**() functions can transfer nvlists between hosts with different endianness.

### Kernel Considerations

The **nv**, **cnv**, and **dnv** APIs can be used in the kernel with the following differences:

- File descriptor and file descriptor array value types are not supported.

- **nvlist\_recv**(), **nvlist\_send**(), and **nvlist\_xfer**() are not supported.

- All memory allocations use the M\_NVLIST memory type with [malloc(9)](/malloc/9.md) and [free(9)](/free/9.md). As a result, any allocated buffers moved into an nvlist must be allocated with M\_NVLIST, and buffers returned by functions such as **nvlist\_pack**() must be freed with M\_NVLIST.

## EXAMPLES

The following example demonstrates how to prepare an nvlist and send it over a [unix(4)](/unix/4.md) domain socket.

```
nvlist_t *nvl;
int fd;
fd = open("/tmp/foo", O_RDONLY);
if (fd < 0)
        err(1, "open(\"/tmp/foo\") failed");
nvl = nvlist_create(0);
/*
 * There is no need to check if nvlist_create() succeeded
 * as the nvlist_add_<type>() functions can cope.
 * If it failed, nvlist_send() will fail.
 */
nvlist_add_string(nvl, "filename", "/tmp/foo");
nvlist_add_number(nvl, "flags", O_RDONLY);
/*
 * We just want to send the descriptor, so we can give it
 * for the nvlist to consume (that is why we use nvlist_move
 * not nvlist_add).
 */
nvlist_move_descriptor(nvl, "fd", fd);
if (nvlist_send(sock, nvl) < 0) {
	nvlist_destroy(nvl);
	err(1, "nvlist_send() failed");
}
nvlist_destroy(nvl);
```

Receiving an nvlist and retrieving element values:

```
nvlist_t *nvl;
const char *command;
char *filename;
int fd;
nvl = nvlist_recv(sock, 0);
if (nvl == NULL)
	err(1, "nvlist_recv() failed");
/* For command we accept a pointer to the nvlist's internal buffer. */
command = nvlist_get_string(nvl, "command");
/*
 * For filename we remove it from the nvlist and take
 * ownership of the buffer.
 */
filename = nvlist_take_string(nvl, "filename");
/* The same for the file descriptor. */
fd = nvlist_take_descriptor(nvl, "fd");
printf("command=%s filename=%s fd=%d0, command, filename, fd);
/* command is freed by nvlist_destroy() */
nvlist_destroy(nvl);
free(filename);
close(fd);
```

Iterating over an nvlist:

```
nvlist_t *nvl;
const char *name;
void *cookie;
int type;
nvl = nvlist_recv(sock, 0);
if (nvl == NULL)
	err(1, "nvlist_recv() failed");
cookie = NULL;
while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
	printf("%s=", name);
	switch (type) {
	case NV_TYPE_NUMBER:
		printf("%ju", (uintmax_t)nvlist_get_number(nvl, name));
		break;
	case NV_TYPE_STRING:
		printf("%s", nvlist_get_string(nvl, name));
		break;
	default:
		printf("N/A");
		break;
	}
	printf("\n");
}
```

Iterating over every nested nvlist:

```
nvlist_t *nvl;
const char *name;
void *cookie;
int type;
nvl = nvlist_recv(sock, 0);
if (nvl == NULL)
	err(1, "nvlist_recv() failed");
cookie = NULL;
do {
	while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
		if (type == NV_TYPE_NVLIST) {
			nvl = nvlist_get_nvlist(nvl, name);
			cookie = NULL;
		}
	}
} while ((nvl = nvlist_get_parent(nvl, &cookie)) != NULL);
```

Iterating over every nested nvlist and every nvlist element:

```
nvlist_t *nvl;
const nvlist_t * const *array;
const char *name;
void *cookie;
int type;
nvl = nvlist_recv(sock, 0);
if (nvl == null)
	err(1, "nvlist_recv() failed");
cookie = NULL;
do {
	while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
		if (type == NV_TYPE_NVLIST) {
			nvl = nvlist_get_nvlist(nvl, name);
			cookie = NULL;
		} else if (type == NV_TYPE_NVLIST_ARRAY) {
			nvl = nvlist_get_nvlist_array(nvl, name, NULL)[0];
			cookie = NULL;
		}
	}
} while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
```

Or alternatively:

```
nvlist_t *nvl, *tmp;
const nvlist_t * const *array;
const char *name;
void *cookie;
int type;
nvl = nvlist_recv(sock, 0);
if (nvl == null)
	err(1, "nvlist_recv() failed");
cooke = NULL;
tmp = nvl;
do {
	do {
		nvl = tmp;
		while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
			if (type == NV_TYPE_NVLIST) {
				nvl = nvlist_get_nvlist(nvl, name);
				cookie = NULL;
			} else if (type == NV_TYPE_NVLIST_ARRAY) {
				nvl = nvlist_get_nvlist_array(nvl, name,
				    NULL)[0];
				cookie = NULL;
			}
		}
		cookie = NULL;
	} while ((tmp = nvlist_get_array_next(nvl)) != NULL);
} while ((tmp = nvlist_get_parent(nvl, &cookie)) != NULL);
```

## SEE ALSO

[close(2)](/close/2.md), [dup(2)](/dup/2.md), [open(2)](/open/2.md), [err(3)](/err/3.md), [free(3)](/free/3.md), [printf(3)](/printf/3.md), [unix(4)](/unix/4.md)

## HISTORY

The **libnv** library appeared in FreeBSD 11.0.

## AUTHORS

The **libnv** library was implemented by Pawel Jakub Dawidek ⟨*pawel@dawidek.net*⟩ under sponsorship from the FreeBSD Foundation.
