xref: /freebsd/share/man/man9/nv.9 (revision dd21556857e8d40f66bf5ad54754d9d52669ebf7)
1.\"
2.\" Copyright (c) 2013 The FreeBSD Foundation
3.\" Copyright (c) 2013-2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
4.\" All rights reserved.
5.\"
6.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
7.\" the FreeBSD Foundation.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.Dd January 3, 2025
31.Dt NV 9
32.Os
33.Sh NAME
34.Nm nvlist_create ,
35.Nm nvlist_destroy ,
36.Nm nvlist_error ,
37.Nm nvlist_set_error ,
38.Nm nvlist_empty ,
39.Nm nvlist_flags ,
40.Nm nvlist_exists ,
41.Nm nvlist_free ,
42.Nm nvlist_clone ,
43.Nm nvlist_dump ,
44.Nm nvlist_fdump ,
45.Nm nvlist_size ,
46.Nm nvlist_pack ,
47.Nm nvlist_unpack ,
48.Nm nvlist_send ,
49.Nm nvlist_recv ,
50.Nm nvlist_xfer ,
51.Nm nvlist_in_array ,
52.Nm nvlist_next ,
53.Nm nvlist_add ,
54.Nm nvlist_move ,
55.Nm nvlist_get ,
56.Nm nvlist_take ,
57.Nm nvlist_append
58.Nd "library for name/value pairs"
59.Sh LIBRARY
60.Lb libnv
61.Sh SYNOPSIS
62.In sys/nv.h
63.Ft "nvlist_t *"
64.Fn nvlist_create "int flags"
65.Ft void
66.Fn nvlist_destroy "nvlist_t *nvl"
67.Ft int
68.Fn nvlist_error "const nvlist_t *nvl"
69.Ft void
70.Fn nvlist_set_error "nvlist_t *nvl" "int error"
71.Ft bool
72.Fn nvlist_empty "const nvlist_t *nvl"
73.Ft int
74.Fn nvlist_flags "const nvlist_t *nvl"
75.Ft bool
76.Fn nvlist_in_array "const nvlist_t *nvl"
77.\"
78.Ft "nvlist_t *"
79.Fn nvlist_clone "const nvlist_t *nvl"
80.\"
81.Ft void
82.Fn nvlist_dump "const nvlist_t *nvl" "int fd"
83.Ft void
84.Fn nvlist_fdump "const nvlist_t *nvl" "FILE *fp"
85.\"
86.Ft size_t
87.Fn nvlist_size "const nvlist_t *nvl"
88.Ft "void *"
89.Fn nvlist_pack "const nvlist_t *nvl" "size_t *sizep"
90.Ft "nvlist_t *"
91.Fn nvlist_unpack "const void *buf" "size_t size" "int flags"
92.\"
93.Ft int
94.Fn nvlist_send "int sock" "const nvlist_t *nvl"
95.Ft "nvlist_t *"
96.Fn nvlist_recv "int sock" "int flags"
97.Ft "nvlist_t *"
98.Fn nvlist_xfer "int sock" "nvlist_t *nvl" "int flags"
99.\"
100.Ft "const char *"
101.Fn nvlist_next "const nvlist_t *nvl" "int *typep" "void **cookiep"
102.\"
103.Ft bool
104.Fn nvlist_exists "const nvlist_t *nvl" "const char *name"
105.Ft bool
106.Fn nvlist_exists_type "const nvlist_t *nvl" "const char *name" "int type"
107.Ft bool
108.Fn nvlist_exists_null "const nvlist_t *nvl" "const char *name"
109.Ft bool
110.Fn nvlist_exists_bool "const nvlist_t *nvl" "const char *name"
111.Ft bool
112.Fn nvlist_exists_number "const nvlist_t *nvl" "const char *name"
113.Ft bool
114.Fn nvlist_exists_string "const nvlist_t *nvl" "const char *name"
115.Ft bool
116.Fn nvlist_exists_nvlist "const nvlist_t *nvl" "const char *name"
117.Ft bool
118.Fn nvlist_exists_descriptor "const nvlist_t *nvl" "const char *name"
119.Ft bool
120.Fn nvlist_exists_binary "const nvlist_t *nvl" "const char *name"
121.Ft bool
122.Fn nvlist_exists_bool_array "const nvlist_t *nvl" "const char *name"
123.Ft bool
124.Fn nvlist_exists_number_array "const nvlist_t *nvl" "const char *name"
125.Ft bool
126.Fn nvlist_exists_string_array "const nvlist_t *nvl" "const char *name"
127.Ft bool
128.Fn nvlist_exists_nvlist_array "const nvlist_t *nvl" "const char *name"
129.Ft bool
130.Fn nvlist_exists_descriptor_array "const nvlist_t *nvl" "const char *name"
131.\"
132.Ft void
133.Fn nvlist_add_null "nvlist_t *nvl" "const char *name"
134.Ft void
135.Fn nvlist_add_bool "nvlist_t *nvl" "const char *name" "bool value"
136.Ft void
137.Fn nvlist_add_number "nvlist_t *nvl" "const char *name" "uint64_t value"
138.Ft void
139.Fn nvlist_add_string "nvlist_t *nvl" "const char *name" "const char *value"
140.Ft void
141.Fn nvlist_add_stringf "nvlist_t *nvl" "const char *name" "const char *valuefmt" "..."
142.Ft void
143.Fn nvlist_add_stringv "nvlist_t *nvl" "const char *name" "const char *valuefmt" "va_list valueap"
144.Ft void
145.Fn nvlist_add_nvlist "nvlist_t *nvl" "const char *name" "const nvlist_t *value"
146.Ft void
147.Fn nvlist_add_descriptor "nvlist_t *nvl" "const char *name" "int value"
148.Ft void
149.Fn nvlist_add_binary "nvlist_t *nvl" "const char *name" "const void *value" "size_t size"
150.Ft void
151.Fn nvlist_add_bool_array "nvlist_t *nvl" "const char *name" "const bool *value" "size_t nitems"
152.
153.Ft void
154.Fn nvlist_add_number_array "nvlist_t *nvl" "const char *name" "const uint64_t *value" "size_t nitems"
155.
156.Ft void
157.Fn nvlist_add_string_array "nvlist_t *nvl" "const char *name" "const char * const * value" "size_t nitems"
158.
159.Ft void
160.Fn nvlist_add_nvlist_array "nvlist_t *nvl" "const char *name" "const nvlist_t * const * value" "size_t nitems"
161.
162.Ft void
163.Fn nvlist_add_descriptor_array "nvlist_t *nvl" "const char *name" "const int *value" "size_t nitems"
164.\"
165.Ft void
166.Fn nvlist_move_string "nvlist_t *nvl" "const char *name" "char *value"
167.Ft void
168.Fn nvlist_move_nvlist "nvlist_t *nvl" "const char *name" "nvlist_t *value"
169.Ft void
170.Fn nvlist_move_descriptor "nvlist_t *nvl" "const char *name" "int value"
171.Ft void
172.Fn nvlist_move_binary "nvlist_t *nvl" "const char *name" "void *value" "size_t size"
173.Ft void
174.Fn nvlist_move_bool_array "nvlist_t *nvl" "const char *name" "bool *value" "size_t nitems"
175.
176.Ft void
177.Fn nvlist_move_number_array "nvlist_t *nvl" "const char *name" "uint64_t *value" "size_t nitems"
178.
179.Ft void
180.Fn nvlist_move_string_array "nvlist_t *nvl" "const char *name" "char **value" "size_t nitems"
181.
182.Ft void
183.Fn nvlist_move_nvlist_array "nvlist_t *nvl" "const char *name" "nvlist_t **value" "size_t nitems"
184.
185.Ft void
186.Fn nvlist_move_descriptor_array "nvlist_t *nvl" "const char *name" "int *value" "size_t nitems"
187.\"
188.Ft bool
189.Fn nvlist_get_bool "const nvlist_t *nvl" "const char *name"
190.Ft uint64_t
191.Fn nvlist_get_number "const nvlist_t *nvl" "const char *name"
192.Ft "const char *"
193.Fn nvlist_get_string "const nvlist_t *nvl" "const char *name"
194.Ft "const nvlist_t *"
195.Fn nvlist_get_nvlist "const nvlist_t *nvl" "const char *name"
196.Ft int
197.Fn nvlist_get_descriptor "const nvlist_t *nvl" "const char *name"
198.Ft "const void *"
199.Fn nvlist_get_binary "const nvlist_t *nvl" "const char *name" "size_t *sizep"
200.Ft "const bool *"
201.Fn nvlist_get_bool_array "const nvlist_t *nvl" "const char *name" "size_t *nitems"
202.Ft "const uint64_t *"
203.Fn nvlist_get_number_array "const nvlist_t *nvl" "const char *name" "size_t *nitems"
204.Ft "const char * const *"
205.Fn nvlist_get_string_array "const nvlist_t *nvl" "const char *name" "size_t *nitems"
206.Ft "const nvlist_t * const *"
207.Fn nvlist_get_nvlist_array "const nvlist_t *nvl" "const char *name" "size_t *nitems"
208.Ft "const int *"
209.Fn nvlist_get_descriptor_array "const nvlist_t *nvl" "const char *name" "size_t *nitems"
210.Ft "const nvlist_t *"
211.Fn nvlist_get_parent "const nvlist_t *nvl" "void **cookiep"
212.Ft "const nvlist_t *"
213.Fn nvlist_get_array_next "const nvlist_t *nvl"
214.Ft "const nvlist_t *"
215.Fn nvlist_get_pararr "const nvlist_t *nvl" "void **cookiep"
216.\"
217.Ft bool
218.Fn nvlist_take_bool "nvlist_t *nvl" "const char *name"
219.Ft uint64_t
220.Fn nvlist_take_number "nvlist_t *nvl" "const char *name"
221.Ft "char *"
222.Fn nvlist_take_string "nvlist_t *nvl" "const char *name"
223.Ft "nvlist_t *"
224.Fn nvlist_take_nvlist "nvlist_t *nvl" "const char *name"
225.Ft int
226.Fn nvlist_take_descriptor "nvlist_t *nvl" "const char *name"
227.Ft "void *"
228.Fn nvlist_take_binary "nvlist_t *nvl" "const char *name" "size_t *sizep"
229.Ft "bool *"
230.Fn nvlist_take_bool_array "nvlist_t *nvl" "const char *name" "size_t *nitems"
231.Ft "uint64_t **"
232.Fn nvlist_take_number_array "nvlist_t *nvl" "const char *name" "size_t *nitems"
233.Ft "char **"
234.Fn nvlist_take_string_array "nvlist_t *nvl" "const char *name" "size_t *nitems"
235.Ft "nvlist_t **"
236.Fn nvlist_take_nvlist_array "nvlist_t *nvl" "const char *name" "size_t *nitems"
237.Ft "int *"
238.Fn nvlist_take_descriptor_array "nvlist_t *nvl" "const char *name" "size_t *nitems"
239.\"
240.Ft void
241.Fn nvlist_append_bool_array "nvlist_t *nvl" "const char *name" "const bool value"
242.Ft void
243.Fn nvlist_append_number_array "nvlist_t *nvl" "const char *name" "const uint64_t value"
244.Ft void
245.Fn nvlist_append_string_array "nvlist_t *nvl" "const char *name" "const char * const value"
246.Ft void
247.Fn nvlist_append_nvlist_array "nvlist_t *nvl" "const char *name" "const nvlist_t * const value"
248.Ft void
249.Fn nvlist_append_descriptor_array "nvlist_t *nvl" "const char *name" "int value"
250.\"
251.Ft void
252.Fn nvlist_free "nvlist_t *nvl" "const char *name"
253.Ft void
254.Fn nvlist_free_type "nvlist_t *nvl" "const char *name" "int type"
255.\"
256.Ft void
257.Fn nvlist_free_null "nvlist_t *nvl" "const char *name"
258.Ft void
259.Fn nvlist_free_bool "nvlist_t *nvl" "const char *name"
260.Ft void
261.Fn nvlist_free_number "nvlist_t *nvl" "const char *name"
262.Ft void
263.Fn nvlist_free_string "nvlist_t *nvl" "const char *name"
264.Ft void
265.Fn nvlist_free_nvlist "nvlist_t *nvl" "const char *name"
266.Ft void
267.Fn nvlist_free_descriptor "nvlist_t *nvl" "const char *name"
268.Ft void
269.Fn nvlist_free_binary "nvlist_t *nvl" "const char *name"
270.Ft void
271.Fn nvlist_free_bool_array "nvlist_t *nvl" "const char *name"
272.Ft void
273.Fn nvlist_free_number_array "nvlist_t *nvl" "const char *name"
274.Ft void
275.Fn nvlist_free_string_array "nvlist_t *nvl" "const char *name"
276.Ft void
277.Fn nvlist_free_nvlist_array "nvlist_t *nvl" "const char *name"
278.Ft void
279.Fn nvlist_free_descriptor_array "nvlist_t *nvl" "const char *name"
280.Sh DESCRIPTION
281The
282.Nm libnv
283library permits creating and managing name value pairs as well as
284sending and receiving
285them over sockets.
286A group (list) of name value pairs is called an
287.Nm nvlist .
288The API supports the following data types for values:
289.Bl -ohang -offset indent
290.It Sy null ( NV_TYPE_NULL )
291There is no data associated with the name.
292.It Sy bool ( NV_TYPE_BOOL )
293The value can be either
294.Dv true
295or
296.Dv false .
297.It Sy number ( NV_TYPE_NUMBER )
298The value is a number stored as
299.Vt uint64_t .
300.It Sy string ( NV_TYPE_STRING )
301The value is a C string.
302.It Sy nvlist ( NV_TYPE_NVLIST )
303The value is a nested nvlist.
304.It Sy descriptor ( NV_TYPE_DESCRIPTOR )
305The value is a file descriptor.
306Note that file descriptors can be sent only over
307.Xr unix 4
308domain sockets.
309.It Sy binary ( NV_TYPE_BINARY )
310The value is a binary buffer.
311.It Sy bool array ( NV_TYPE_BOOL_ARRAY )
312The value is an array of boolean values.
313.It Sy number array ( NV_TYPE_NUMBER_ARRAY )
314The value is an array of numbers, each stored as
315.Vt uint64_t .
316.It Sy string array ( NV_TYPE_STRING_ARRAY )
317The value is an array of C strings.
318.It Sy nvlist array  ( NV_TYPE_NVLIST_ARRAY )
319The value is an array of nvlists.
320When an nvlist is added to an array, it becomes part of the primary nvlist.
321Traversing these arrays can be done using the
322.Fn nvlist_get_array_next
323and
324.Fn nvlist_get_pararr
325functions.
326.It Sy descriptor array ( NV_TYPE_DESCRIPTOR_ARRAY )
327The value is an array of files descriptors.
328.El
329.Pp
330The
331.Fn nvlist_create
332function allocates memory and initializes an nvlist.
333.Pp
334The following flags can be provided:
335.Pp
336.Bl -tag -width "NV_FLAG_IGNORE_CASE" -compact -offset indent
337.It Dv NV_FLAG_IGNORE_CASE
338Perform case-insensitive lookups of provided names.
339.It Dv NV_FLAG_NO_UNIQUE
340Names in the nvlist do not have to be unique.
341.El
342.Pp
343The
344.Fn nvlist_destroy
345function destroys the given nvlist.
346This function does nothing if
347.Fa nvl
348is
349.Dv NULL .
350This function never modifies
351.Va errno .
352.Pp
353The
354.Fn nvlist_error
355function returns the first error set on
356.Fa nvl .
357If
358.Fa nvl
359is not in the error state,
360this function returns zero.
361If
362.Fa nvl
363is
364.Dv NULL ,
365.Er ENOMEM
366is returned.
367.Pp
368The
369.Fn nvlist_set_error
370function sets an the error value for
371.Fa nvl .
372Subsequent calls to
373.Fn nvlist_error
374will return
375.Fa error .
376This function cannot be used to clear the error state from an nvlist.
377This function does nothing if the nvlist is already in the error state.
378.Pp
379The
380.Fn nvlist_empty
381function returns
382.Dv true
383if
384.Fa nvl
385is empty and
386.Dv false
387otherwise.
388The nvlist must not be in the error state.
389.Pp
390The
391.Fn nvlist_flags
392function returns the flags used to create
393.Fa nvl
394with the
395.Fn nvlist_create ,
396.Fn nvlist_recv ,
397.Fn nvlist_unpack ,
398or
399.Fn nvlist_xfer
400functions.
401.Pp
402The
403.Fn nvlist_in_array
404function returns
405.Dv true
406if
407.Fa nvl
408is part of an array that is a member of another nvlist.
409.Pp
410The
411.Fn nvlist_clone
412function clones
413.Fa nvl .
414The clone shares no resources with its origin.
415This also means that all file descriptors that are part of the nvlist will be
416duplicated with the
417.Xr dup 2
418system call before placing them in the clone.
419.Pp
420The
421.Fn nvlist_dump
422function dumps nvlist content for debugging purposes to the file descriptor
423.Fa fd .
424.Pp
425The
426.Fn nvlist_fdump
427dumps nvlist content for debugging purposes to the file stream
428.Fa fp .
429.Pp
430The
431.Fn nvlist_size
432function returns the size of the binary buffer that would be generated by the
433.Fn nvlist_pack
434function.
435.Pp
436The
437.Fn nvlist_pack
438function converts the given nvlist to a binary buffer.
439The function allocates memory for the buffer which should be freed with the
440.Xr free 3
441function.
442If the
443.Fa sizep
444argument is not
445.Dv NULL ,
446the size of the buffer is stored there.
447This function returns
448.Dv NULL
449in case of an error (allocation failure).
450If the nvlist contains any file descriptors
451.Dv NULL
452will be returned.
453The nvlist must not be in the error state.
454.Pp
455The
456.Fn nvlist_unpack
457function converts a binary buffer to a new nvlist.
458The
459.Fa flags
460argument has the same meaning as the
461.Fa flags
462argument passed to
463.Fn nvlist_create .
464If
465.Fa flags
466do not match the flags used to create the initial nvlist before it was packed,
467this function will fail.
468The flags of nested nvlists are not validated by this function.
469The caller is responsible for validating the flags on any nested nvlists using
470.Fn nvlist_flags .
471This function returns the new nvlist on success or
472.Dv NULL
473in case of an error.
474.Pp
475The
476.Fn nvlist_send
477function sends
478.Fa nvl
479over the socket
480.Fa sock .
481Note that nvlists that contain file descriptors can only be sent over
482.Xr unix 4
483domain sockets.
484.Pp
485The
486.Fn nvlist_recv
487function receives an nvlist over the socket
488.Fa sock .
489As with
490.Fn nvlist_unpack ,
491the
492.Fa flags
493argument is used to construct the new nvlist and must match the flags used
494to construct the original nvlist written to
495.Fa sock
496by the peer.
497The flags of nested nvlists are not validated by this function.
498The caller is responsible for validating the flags on any nested nvlists using
499.Fn nvlist_flags .
500This function returns the new nvlist on success or
501.Dv NULL
502in case of an error.
503.Pp
504The
505.Fn nvlist_xfer
506function sends
507.Fa nvl
508over the socket
509.Fa sock
510argument and then receives a new nvlist over the same socket.
511The
512.Fa flags
513argument applies to the new nvlist similar to
514.Fn nvlist_recv .
515The nvlist
516.Fa nvl
517is always destroyed.
518This function returns the new nvlist on success or
519.Dv NULL
520in case of an error.
521.Pp
522The
523.Fn nvlist_next
524function iterates over
525.Fa nvl
526returning the names and types of subsequent
527elements.
528The
529.Fa cookiep
530argument determines which element is returned.
531If
532.Va *cookiep
533is
534.Dv NULL ,
535the values for the first element in the list are returned.
536Otherwise,
537.Va *cookiep
538should contain the result of a prior call to
539.Fn nvlist_next
540in which case values for the next element from
541.Fa nvl
542are returned.
543This function returns
544.Dv NULL
545when there are no more elements on
546.Fa nvl .
547The
548.Fa typep
549argument can be
550.Dv NULL .
551Elements may not be removed from
552.Fa nvl
553the nvlist while traversing it.
554.Fa nvl
555must not be in the error state.
556Additional actions can be performed on an element identified by a cookie
557via the
558.Xr cnv 9
559API .
560.Pp
561The
562.Fn nvlist_exists
563function returns
564.Dv true
565if an element named
566.Fa name
567exists in
568.Fa nvl
569(regardless of type) or
570.Dv false
571otherwise.
572The nvlist must not be in the error state.
573.Pp
574The
575.Fn nvlist_exists_type
576function returns
577.Dv true
578if an element named
579.Fa name
580of type
581.Fa type
582exists or
583.Dv false
584otherwise.
585The nvlist must not be in the error state.
586.Pp
587The
588.Fn nvlist_exists_null ,
589.Fn nvlist_exists_bool ,
590.Fn nvlist_exists_number ,
591.Fn nvlist_exists_string ,
592.Fn nvlist_exists_nvlist ,
593.Fn nvlist_exists_descriptor ,
594.Fn nvlist_exists_binary ,
595.Fn nvlist_exists_bool_array ,
596.Fn nvlist_exists_number_array ,
597.Fn nvlist_exists_string_array ,
598.Fn nvlist_exists_nvlist_array ,
599.Fn nvlist_exists_descriptor_array
600functions return
601.Dv true
602if element named
603.Fa name
604with the type determined by the function name
605exists or
606.Dv false
607otherwise.
608The nvlist must not be in the error state.
609.Pp
610The
611.Fn nvlist_add_null ,
612.Fn nvlist_add_bool ,
613.Fn nvlist_add_number ,
614.Fn nvlist_add_string ,
615.Fn nvlist_add_stringf ,
616.Fn nvlist_add_stringv ,
617.Fn nvlist_add_nvlist ,
618.Fn nvlist_add_descriptor ,
619.Fn nvlist_add_binary ,
620.Fn nvlist_add_bool_array ,
621.Fn nvlist_add_number_array ,
622.Fn nvlist_add_string_array ,
623.Fn nvlist_add_nvlist_array ,
624.Fn nvlist_add_descriptor_array
625functions add an element to
626.Fa nvl .
627When adding a string or binary buffer, these functions allocate memory
628and copy the data.
629When adding an nvlist, the
630.Fa value
631nvlist is cloned and the clone is added to
632.Fa nvl .
633When adding a file descriptor, the descriptor is duplicated via the
634.Xr dup 2
635system call and the new file descriptor is added.
636The array functions fail if there are any
637.Dv NULL
638elements in the array, or if the array pointer is
639.Dv NULL .
640If an error occurs while adding a new element,
641an internal error is set which can be
642examined using the
643.Fn nvlist_error
644function.
645.Pp
646The
647.Fn nvlist_move_string ,
648.Fn nvlist_move_nvlist ,
649.Fn nvlist_move_descriptor ,
650.Fn nvlist_move_binary ,
651.Fn nvlist_move_bool_array ,
652.Fn nvlist_move_number_array ,
653.Fn nvlist_move_string_array ,
654.Fn nvlist_move_nvlist_array ,
655.Fn nvlist_move_descriptor_array
656functions add an element to
657.Fa nvl ,
658but unlike the
659.Fn nvlist_add_<type>
660functions they consume the given resource.
661For string, file descriptor, binary buffer, or nvlist values,
662no value should be moved into an nvlist multiple times;
663doing so will cause that value to be freed multiple times.
664Note that strings or binary buffers must be allocated with
665.Xr malloc 3 ,
666and the pointers will be released via
667.Xr free 3
668when
669.Fa nvl
670is destroyed.
671The array functions fail if there are any
672.Dv NULL
673elements, or if the array pointer is
674.Dv NULL .
675If an error occurs while adding new element, the resource is destroyed and
676an internal error is set which can be examined using the
677.Fn nvlist_error
678function.
679.Pp
680The
681.Fn nvlist_get_bool ,
682.Fn nvlist_get_number ,
683.Fn nvlist_get_string ,
684.Fn nvlist_get_nvlist ,
685.Fn nvlist_get_descriptor ,
686.Fn nvlist_get_binary ,
687.Fn nvlist_get_bool_array ,
688.Fn nvlist_get_number_array ,
689.Fn nvlist_get_string_array ,
690.Fn nvlist_get_nvlist_array ,
691.Fn nvlist_get_descriptor_array
692functions return the value of the first element in
693.Fa nvl
694named
695.Fa name .
696For string, nvlist, file descriptor, binary buffer, or array values,
697the returned resource must not be modified - it still belongs to
698.Fa nvl .
699.Pp
700If an element named
701.Fa name
702does not exist, the program aborts.
703To avoid this, the caller should check for the existence of the element before
704trying to obtain the value or use the
705.Xr dnv 9
706extension which provides a default value in the case of a missing element.
707.Pp
708The nvlist must not be in the error state.
709.Pp
710The
711.Fn nvlist_get_parent
712function returns the parent nvlist of
713.Fa nvl .
714.Pp
715The
716.Fn nvlist_get_array_next
717function returns the next element after
718.Fa nvl
719from an array of nvlists.
720If
721.Fa nvl
722is not in an array of nvlists or it is the last element,
723this function returns
724.Dv NULL .
725An nvlist is only in an nvlist array if it was added to an nvlist array using
726.Fn nvlist_add_nvlist_array ,
727.Fn nvlist_append_nvlist_array ,
728or
729.Fn nvlist_move_nvlist_array .
730.Pp
731The
732.Fn nvlist_get_pararr
733function returns the next element after
734.Fn nvl
735from an array of nvlists.
736If
737.Fn nvl
738is the last element in an array of nvlists,
739the parent nvlist of
740.Fa nvl is
741returned.
742If
743.Fn nvl
744is not in an array of nvlists,
745.Dv NULL
746is returned.
747.Pp
748The
749.Fn nvlist_take_bool ,
750.Fn nvlist_take_number ,
751.Fn nvlist_take_string ,
752.Fn nvlist_take_nvlist ,
753.Fn nvlist_take_descriptor ,
754.Fn nvlist_take_binary ,
755.Fn nvlist_take_bool_array ,
756.Fn nvlist_take_number_array ,
757.Fn nvlist_take_string_array ,
758.Fn nvlist_take_nvlist_array ,
759.Fn nvlist_take_descriptor_array
760functions return the value of the element named
761.Fa name
762and remove the element from
763.Fa nvl .
764For string and binary buffer values, the caller is responsible for freeing
765the returned value using the
766.Xr free 3
767function.
768For nvlist values, the caller is responsible for destroying the returned nvlist
769using the
770.Fn nvlist_destroy
771function.
772For file descriptor values, the caller is responsible for closing the
773returned descriptor
774using the
775.Fn close 2
776system call.
777For array values, the caller is responsible for destroying every element of
778the array based on the element type.
779In addition, the caller must also free the pointer to the array using the
780.Xr free 3
781function.
782.Pp
783If an element named
784.Fa name
785does not exist, the program aborts.
786To avoid this, the caller should check for the existence of the element before
787trying to obtain the value or use the
788.Xr dnv 9
789extension which provides a default value in the case of a missing element.
790.Pp
791The nvlist must not be in the error state.
792.Pp
793The
794.Fn nvlist_append_bool_array ,
795.Fn nvlist_append_number_array ,
796.Fn nvlist_append_string_array ,
797.Fn nvlist_append_nvlist_array ,
798.Fn nvlist_append_descriptor_array
799functions append an element to an existing array using the same semantics
800as the add functions (that is, the element will be copied when applicable).
801If the array named
802.Fa name
803does not exist, then it will be created
804as if using the
805.Fn nvlist_add_<type>_array
806function.
807If an error occurs while appending a new element,
808an internal error is set on
809.Fa nvl .
810.Pp
811The
812.Fn nvlist_free
813function removes the first element named
814.Fa name
815from
816.Fa nvl
817(regardless of type)
818and frees all resources associated with it.
819If no element named
820.Fa name
821exists, the program aborts.
822The nvlist must not be in the error state.
823.Pp
824The
825.Fn nvlist_free_type
826function removes the first element named
827.Fa name
828of type
829.Fa type
830from
831.Fa nvl
832and frees all resources associated with it.
833If no element named
834.Fa name
835of type
836.Fa type
837exists, the program aborts.
838The nvlist must not be in the error state.
839.Pp
840The
841.Fn nvlist_free_null ,
842.Fn nvlist_free_bool ,
843.Fn nvlist_free_number ,
844.Fn nvlist_free_string ,
845.Fn nvlist_free_nvlist ,
846.Fn nvlist_free_descriptor ,
847.Fn nvlist_free_binary ,
848.Fn nvlist_free_bool_array ,
849.Fn nvlist_free_number_array ,
850.Fn nvlist_free_string_array ,
851.Fn nvlist_free_nvlist_array ,
852.Fn nvlist_free_descriptor_array
853functions remove the first element named
854.Fa name
855with the type determined by the function name from
856.Fa nvl
857free all resources associated with it.
858If no element named
859.Fa name
860with the appropriate type exists, the program aborts.
861The nvlist must not be in the error state.
862.Ss Notes
863The
864.Fn nvlist_pack
865and
866.Fn nvlist_unpack
867functions handle byte-order conversions, so binary buffers can be
868packed and unpacked on hosts with different endianness.
869.Pp
870The
871.Fn nvlist_recv ,
872.Fn nvlist_send ,
873and
874.Fn nvlist_xfer
875functions can transfer nvlists between hosts with different endianness.
876.Ss Kernel Considerations
877The
878.Nm nv ,
879.Nm cnv ,
880and
881.Nm dnv
882APIs can be used in the kernel with the following differences:
883.Bl -bullet
884.It
885File descriptor and file descriptor array value types are not supported.
886.It
887.Fn nvlist_recv ,
888.Fn nvlist_send ,
889and
890.Fn nvlist_xfer
891are not supported.
892.It
893All memory allocations use the
894.Dv M_NVLIST
895memory type with
896.Xr malloc 9
897and
898.Xr free 9 .
899As a result, any allocated buffers moved into an nvlist must be allocated with
900.Dv M_NVLIST ,
901and buffers returned by functions such as
902.Fn nvlist_pack
903must be freed with
904.Dv M_NVLIST .
905.El
906.Sh EXAMPLES
907The following example demonstrates how to prepare an nvlist and send it over a
908.Xr unix 4
909domain socket.
910.Bd -literal
911nvlist_t *nvl;
912int fd;
913
914fd = open("/tmp/foo", O_RDONLY);
915if (fd < 0)
916        err(1, "open(\\"/tmp/foo\\") failed");
917
918nvl = nvlist_create(0);
919
920/*
921 * There is no need to check if nvlist_create() succeeded
922 * as the nvlist_add_<type>() functions can cope.
923 * If it failed, nvlist_send() will fail.
924 */
925nvlist_add_string(nvl, "filename", "/tmp/foo");
926nvlist_add_number(nvl, "flags", O_RDONLY);
927
928/*
929 * We just want to send the descriptor, so we can give it
930 * for the nvlist to consume (that is why we use nvlist_move
931 * not nvlist_add).
932 */
933nvlist_move_descriptor(nvl, "fd", fd);
934if (nvlist_send(sock, nvl) < 0) {
935	nvlist_destroy(nvl);
936	err(1, "nvlist_send() failed");
937}
938nvlist_destroy(nvl);
939.Ed
940.Pp
941Receiving an nvlist and retrieving element values:
942.Bd -literal
943nvlist_t *nvl;
944const char *command;
945char *filename;
946int fd;
947
948nvl = nvlist_recv(sock, 0);
949if (nvl == NULL)
950	err(1, "nvlist_recv() failed");
951
952/* For command we accept a pointer to the nvlist's internal buffer. */
953command = nvlist_get_string(nvl, "command");
954
955/*
956 * For filename we remove it from the nvlist and take
957 * ownership of the buffer.
958 */
959filename = nvlist_take_string(nvl, "filename");
960
961/* The same for the file descriptor. */
962fd = nvlist_take_descriptor(nvl, "fd");
963
964printf("command=%s filename=%s fd=%d\n", command, filename, fd);
965
966/* command is freed by nvlist_destroy() */
967nvlist_destroy(nvl);
968free(filename);
969close(fd);
970.Ed
971.Pp
972Iterating over an nvlist:
973.Bd -literal
974nvlist_t *nvl;
975const char *name;
976void *cookie;
977int type;
978
979nvl = nvlist_recv(sock, 0);
980if (nvl == NULL)
981	err(1, "nvlist_recv() failed");
982
983cookie = NULL;
984while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
985	printf("%s=", name);
986	switch (type) {
987	case NV_TYPE_NUMBER:
988		printf("%ju", (uintmax_t)nvlist_get_number(nvl, name));
989		break;
990	case NV_TYPE_STRING:
991		printf("%s", nvlist_get_string(nvl, name));
992		break;
993	default:
994		printf("N/A");
995		break;
996	}
997	printf("\\n");
998}
999.Ed
1000.Pp
1001Iterating over every nested nvlist:
1002.Bd -literal
1003nvlist_t *nvl;
1004const char *name;
1005void *cookie;
1006int type;
1007
1008nvl = nvlist_recv(sock, 0);
1009if (nvl == NULL)
1010	err(1, "nvlist_recv() failed");
1011
1012cookie = NULL;
1013do {
1014	while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
1015		if (type == NV_TYPE_NVLIST) {
1016			nvl = nvlist_get_nvlist(nvl, name);
1017			cookie = NULL;
1018		}
1019	}
1020} while ((nvl = nvlist_get_parent(nvl, &cookie)) != NULL);
1021.Ed
1022.Pp
1023Iterating over every nested nvlist and every nvlist element:
1024.Bd -literal
1025nvlist_t *nvl;
1026const nvlist_t * const *array;
1027const char *name;
1028void *cookie;
1029int type;
1030
1031nvl = nvlist_recv(sock, 0);
1032if (nvl == null)
1033	err(1, "nvlist_recv() failed");
1034
1035cookie = NULL;
1036do {
1037	while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
1038		if (type == NV_TYPE_NVLIST) {
1039			nvl = nvlist_get_nvlist(nvl, name);
1040			cookie = NULL;
1041		} else if (type == NV_TYPE_NVLIST_ARRAY) {
1042			nvl = nvlist_get_nvlist_array(nvl, name, NULL)[0];
1043			cookie = NULL;
1044		}
1045	}
1046} while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
1047.Ed
1048.Pp
1049Or alternatively:
1050.Bd -literal
1051nvlist_t *nvl, *tmp;
1052const nvlist_t * const *array;
1053const char *name;
1054void *cookie;
1055int type;
1056
1057nvl = nvlist_recv(sock, 0);
1058if (nvl == null)
1059	err(1, "nvlist_recv() failed");
1060
1061cooke = NULL;
1062tmp = nvl;
1063do {
1064	do {
1065		nvl = tmp;
1066		while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
1067			if (type == NV_TYPE_NVLIST) {
1068				nvl = nvlist_get_nvlist(nvl, name);
1069				cookie = NULL;
1070			} else if (type == NV_TYPE_NVLIST_ARRAY) {
1071				nvl = nvlist_get_nvlist_array(nvl, name,
1072				    NULL)[0];
1073				cookie = NULL;
1074			}
1075		}
1076		cookie = NULL;
1077	} while ((tmp = nvlist_get_array_next(nvl)) != NULL);
1078} while ((tmp = nvlist_get_parent(nvl, &cookie)) != NULL);
1079.Ed
1080.Sh SEE ALSO
1081.Xr close 2 ,
1082.Xr dup 2 ,
1083.Xr open 2 ,
1084.Xr err 3 ,
1085.Xr free 3 ,
1086.Xr printf 3 ,
1087.Xr unix 4
1088.Sh HISTORY
1089The
1090.Nm libnv
1091library appeared in
1092.Fx 11.0 .
1093.Sh AUTHORS
1094.An -nosplit
1095The
1096.Nm libnv
1097library was implemented by
1098.An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net
1099under sponsorship from the FreeBSD Foundation.
1100