xref: /freebsd/share/man/man9/nv.9 (revision aa1a8ff2d6dbc51ef058f46f3db5a8bb77967145)
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 February 2, 2023
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 allows to easily manage name value pairs as well as send and receive
284them over sockets.
285A group (list) of name value pairs is called an
286.Nm nvlist .
287The API supports the following data types:
288.Bl -ohang -offset indent
289.It Sy null ( NV_TYPE_NULL )
290There is no data associated with the name.
291.It Sy bool ( NV_TYPE_BOOL )
292The value can be either
293.Dv true
294or
295.Dv false .
296.It Sy number ( NV_TYPE_NUMBER )
297The value is a number stored as
298.Vt uint64_t .
299.It Sy string ( NV_TYPE_STRING )
300The value is a C string.
301.It Sy nvlist ( NV_TYPE_NVLIST )
302The value is a nested nvlist.
303.It Sy descriptor ( NV_TYPE_DESCRIPTOR )
304The value is a file descriptor.
305Note that file descriptors can be sent only over
306.Xr unix 4
307domain sockets.
308.It Sy binary ( NV_TYPE_BINARY )
309The value is a binary buffer.
310.It Sy bool array ( NV_TYPE_BOOL_ARRAY )
311The value is an array of boolean values.
312.It Sy number array ( NV_TYPE_NUMBER_ARRAY )
313The value is an array of numbers, each stored as
314.Vt uint64_t .
315.It Sy string array ( NV_TYPE_STRING_ARRAY )
316The value is an array of C strings.
317.It Sy nvlist array  ( NV_TYPE_NVLIST_ARRAY )
318The value is an array of nvlists.
319When an nvlist is added to an array, it becomes part of the primary nvlist.
320Traversing these arrays can be done using the
321.Fn nvlist_get_array_next
322and
323.Fn nvlist_get_pararr
324functions.
325.It Sy descriptor array ( NV_TYPE_DESCRIPTOR_ARRAY )
326The value is an array of files descriptors.
327.El
328.Pp
329The
330.Fn nvlist_create
331function allocates memory and initializes an nvlist.
332.Pp
333The following flag can be provided:
334.Pp
335.Bl -tag -width "NV_FLAG_IGNORE_CASE" -compact -offset indent
336.It Dv NV_FLAG_IGNORE_CASE
337Perform case-insensitive lookups of provided names.
338.It Dv NV_FLAG_NO_UNIQUE
339Names in the nvlist do not have to be unique.
340.El
341.Pp
342The
343.Fn nvlist_destroy
344function destroys the given nvlist.
345Function does nothing if
346.Dv NULL
347nvlist is provided.
348Function never modifies the
349.Va errno
350global variable.
351.Pp
352The
353.Fn nvlist_error
354function returns any error value that the nvlist accumulated.
355If the given nvlist is
356.Dv NULL
357the
358.Er ENOMEM
359error will be returned.
360.Pp
361The
362.Fn nvlist_set_error
363function sets an nvlist to be in the error state.
364Subsequent calls to
365.Fn nvlist_error
366will return the given error value.
367This function cannot be used to clear the error state from an nvlist.
368This function does nothing if the nvlist is already in the error state.
369.Pp
370The
371.Fn nvlist_empty
372function returns
373.Dv true
374if the given nvlist is empty and
375.Dv false
376otherwise.
377The nvlist must not be in error state.
378.Pp
379The
380.Fn nvlist_flags
381function returns flags used to create the nvlist with the
382.Fn nvlist_create
383function.
384.Pp
385The
386.Fn nvlist_in_array
387function returns
388.Dv true
389if
390.Fa nvl
391is part of an array that is a member of another nvlist.
392.Pp
393The
394.Fn nvlist_clone
395functions clones the given nvlist.
396The clone shares no resources with its origin.
397This also means that all file descriptors that are part of the nvlist will be
398duplicated with the
399.Xr dup 2
400system call before placing them in the clone.
401.Pp
402The
403.Fn nvlist_dump
404dumps nvlist content for debugging purposes to the given file descriptor
405.Fa fd .
406.Pp
407The
408.Fn nvlist_fdump
409dumps nvlist content for debugging purposes to the given file stream
410.Fa fp .
411.Pp
412The
413.Fn nvlist_size
414function returns the size of the given nvlist after converting it to binary
415buffer with the
416.Fn nvlist_pack
417function.
418.Pp
419The
420.Fn nvlist_pack
421function converts the given nvlist to a binary buffer.
422The function allocates memory for the buffer, which should be freed with the
423.Xr free 3
424function.
425If the
426.Fa sizep
427argument is not
428.Dv NULL ,
429the size of the buffer will be stored there.
430The function returns
431.Dv NULL
432in case of an error (allocation failure).
433If the nvlist contains any file descriptors
434.Dv NULL
435will be returned.
436The nvlist must not be in error state.
437.Pp
438The
439.Fn nvlist_unpack
440function converts the given buffer to the nvlist.
441The
442.Fa flags
443argument defines what type of the top level nvlist is expected to be.
444Flags are set up using the
445.Fn nvlist_create
446function.
447If the nvlist flags do not match the flags passed to
448.Fn nvlist_unpack ,
449the nvlist will not be returned.
450Every nested nvlist list should be checked using
451.Fn nvlist_flags
452function.
453The function returns
454.Dv NULL
455in case of an error.
456.Pp
457The
458.Fn nvlist_send
459function sends the given nvlist over the socket given by the
460.Fa sock
461argument.
462Note that nvlist that contains file descriptors can only be send over
463.Xr unix 4
464domain sockets.
465.Pp
466The
467.Fn nvlist_recv
468function receives nvlist over the socket given by the
469.Fa sock
470argument.
471The
472.Fa flags
473argument defines what type of the top level nvlist is expected to be.
474Flags are set up using the
475.Fn nvlist_create
476function.
477If the nvlist flags do not match the flags passed to
478.Fn nvlist_recv ,
479the nvlist will not be returned.
480Every nested nvlist list should be checked using
481.Fn nvlist_flags
482function.
483.Pp
484The
485.Fn nvlist_xfer
486function sends the given nvlist over the socket given by the
487.Fa sock
488argument and receives nvlist over the same socket.
489The
490.Fa flags
491argument defines what type of the top level nvlist is expected to be.
492Flags are set up using the
493.Fn nvlist_create
494function.
495If the nvlist flags do not match the flags passed to
496.Fn nvlist_xfer ,
497the nvlist will not be returned.
498Every nested nvlist list should be checked using
499.Fn nvlist_flags
500function.
501The given nvlist is always destroyed.
502.Pp
503The
504.Fn nvlist_next
505function iterates over the given nvlist returning names and types of subsequent
506elements.
507The
508.Fa cookiep
509argument allows the function to figure out which element should be returned
510next.
511The
512.Va *cookiep
513should be set to
514.Dv NULL
515for the first call and should not be changed later.
516Returning
517.Dv NULL
518means there are no more elements on the nvlist.
519The
520.Fa typep
521argument can be NULL.
522Elements may not be removed from the nvlist while traversing it.
523The nvlist must not be in error state.
524Note that
525.Fn nvlist_next
526will handle
527.Va cookiep
528being set to
529.Dv NULL .
530In this case first element is returned or
531.Dv NULL
532if nvlist is empty.
533This behavior simplifies removing the first element from the list.
534.Pp
535The
536.Fn nvlist_exists
537function returns
538.Dv true
539if element of the given name exists (besides of its type) or
540.Dv false
541otherwise.
542The nvlist must not be in error state.
543.Pp
544The
545.Fn nvlist_exists_type
546function returns
547.Dv true
548if element of the given name and the given type exists or
549.Dv false
550otherwise.
551The nvlist must not be in error state.
552.Pp
553The
554.Fn nvlist_exists_null ,
555.Fn nvlist_exists_bool ,
556.Fn nvlist_exists_number ,
557.Fn nvlist_exists_string ,
558.Fn nvlist_exists_nvlist ,
559.Fn nvlist_exists_descriptor ,
560.Fn nvlist_exists_binary ,
561.Fn nvlist_exists_bool_array ,
562.Fn nvlist_exists_number_array ,
563.Fn nvlist_exists_string_array ,
564.Fn nvlist_exists_nvlist_array ,
565.Fn nvlist_exists_descriptor_array
566functions return
567.Dv true
568if element of the given name and the given type determined by the function name
569exists or
570.Dv false
571otherwise.
572The nvlist must not be in error state.
573.Pp
574The
575.Fn nvlist_add_null ,
576.Fn nvlist_add_bool ,
577.Fn nvlist_add_number ,
578.Fn nvlist_add_string ,
579.Fn nvlist_add_stringf ,
580.Fn nvlist_add_stringv ,
581.Fn nvlist_add_nvlist ,
582.Fn nvlist_add_descriptor ,
583.Fn nvlist_add_binary ,
584.Fn nvlist_add_bool_array ,
585.Fn nvlist_add_number_array ,
586.Fn nvlist_add_string_array ,
587.Fn nvlist_add_nvlist_array ,
588.Fn nvlist_add_descriptor_array
589functions add element to the given nvlist.
590When adding string or binary buffer the functions will allocate memory
591and copy the data over.
592When adding nvlist, the nvlist will be cloned and clone will be added.
593When adding descriptor, the descriptor will be duplicated using the
594.Xr dup 2
595system call and the new descriptor will be added.
596The array functions will fail if there are any
597.Dv NULL
598elements in the array, or if the array pointer is
599.Dv NULL .
600If an error occurs while adding new element, internal error is set which can be
601examined using the
602.Fn nvlist_error
603function.
604.Pp
605The
606.Fn nvlist_move_string ,
607.Fn nvlist_move_nvlist ,
608.Fn nvlist_move_descriptor ,
609.Fn nvlist_move_binary ,
610.Fn nvlist_move_bool_array ,
611.Fn nvlist_move_number_array ,
612.Fn nvlist_move_string_array ,
613.Fn nvlist_move_nvlist_array ,
614.Fn nvlist_move_descriptor_array
615functions add new element to the given nvlist, but unlike
616.Fn nvlist_add_<type>
617functions they will consume the given resource.
618In the case of strings, descriptors, or nvlists every elements must be
619unique, or it could cause a double free.
620The array functions will fail if there are any
621.Dv NULL
622elements, or if the array pointer is
623.Dv NULL .
624If an error occurs while adding new element, the resource is destroyed and
625internal error is set which can be examined using the
626.Fn nvlist_error
627function.
628.Pp
629The
630.Fn nvlist_get_bool ,
631.Fn nvlist_get_number ,
632.Fn nvlist_get_string ,
633.Fn nvlist_get_nvlist ,
634.Fn nvlist_get_descriptor ,
635.Fn nvlist_get_binary ,
636.Fn nvlist_get_bool_array ,
637.Fn nvlist_get_number_array ,
638.Fn nvlist_get_string_array ,
639.Fn nvlist_get_nvlist_array ,
640.Fn nvlist_get_descriptor_array
641functions return the value that corresponds to the given key name.
642In the case of strings, nvlists, descriptors, binary, or arrays, the returned
643resource should not be modified - they still belong to the nvlist.
644If an element of the given name does not exist, the program will be aborted.
645To avoid this, the caller should check for the existence of the name before
646trying to obtain the value, or use the
647.Xr dnvlist 3
648extension, which can provide a default value in the case of a missing element.
649The nvlist must not be in error state.
650.Pp
651The
652.Fn nvlist_get_parent
653function returns the parent nvlist of the nested nvlist.
654.Pp
655The
656.Fn nvlist_get_array_next
657function returns the next element from the array or
658.Dv NULL
659if the nvlist is not in array or it is the last element.
660Note that
661.Fn nvlist_get_array_next
662only works if you added the nvlist array using the
663.Fn nvlist_move_nvlist_array
664or
665.Fn nvlist_add_nvlist_array
666functions.
667.Pp
668The
669.Fn nvlist_get_pararr
670function returns the next element in the array, or if not available
671the parent of the nested nvlist.
672.Pp
673The
674.Fn nvlist_take_bool ,
675.Fn nvlist_take_number ,
676.Fn nvlist_take_string ,
677.Fn nvlist_take_nvlist ,
678.Fn nvlist_take_descriptor ,
679.Fn nvlist_take_binary ,
680.Fn nvlist_take_bool_array ,
681.Fn nvlist_take_number_array ,
682.Fn nvlist_take_string_array ,
683.Fn nvlist_take_nvlist_array ,
684.Fn nvlist_take_descriptor_array
685functions return value associated with the given name and remove the element
686from the nvlist.
687In case of string and binary values, the caller is responsible for free returned
688memory using the
689.Xr free 3
690function.
691In case of nvlist, the caller is responsible for destroying returned nvlist
692using the
693.Fn nvlist_destroy
694function.
695In case of descriptor, the caller is responsible for closing returned descriptor
696using the
697.Fn close 2
698system call.
699If an element of the given name does not exist, the program will be aborted.
700To avoid that the caller should check for the existence of the given name
701before trying to obtain the value, or use the
702.Xr dnvlist 3
703extension, which can provide a default value in the case of a missing element.
704In the case of an array of strings or binary values, the caller is responsible
705for freeing every element of the array using the
706.Xr free 3
707function.
708In the case of an array of nvlists, the caller is responsible for destroying
709every element of array using the
710.Fn nvlist_destroy
711function.
712In the case of descriptors, the caller is responsible for closing every
713element of array using the
714.Fn close 2
715system call.
716In every case involving an array, the caller must also free the pointer to
717the array using the
718.Xr free 3
719function.
720The nvlist must not be in error state.
721.Pp
722The
723.Fn nvlist_append_bool_array ,
724.Fn nvlist_append_number_array ,
725.Fn nvlist_append_string_array ,
726.Fn nvlist_append_nvlist_array ,
727.Fn nvlist_append_descriptor_array
728functions append an element to the existing array using the same semantics
729as the add functions (i.e. the element will be copied when applicable).
730If the array for a given key does not exist, then it will be created
731as if using the
732.Fn nvlist_add_<type>_array
733function.
734The internal error is set on append failure.
735.Pp
736The
737.Fn nvlist_free
738function removes element of the given name from the nvlist (besides of its type)
739and frees all resources associated with it.
740If element of the given name does not exist, the program will be aborted.
741The nvlist must not be in error state.
742.Pp
743The
744.Fn nvlist_free_type
745function removes element of the given name and the given type from the nvlist
746and frees all resources associated with it.
747If element of the given name and the given type does not exist, the program
748will be aborted.
749The nvlist must not be in error state.
750.Pp
751The
752.Fn nvlist_free_null ,
753.Fn nvlist_free_bool ,
754.Fn nvlist_free_number ,
755.Fn nvlist_free_string ,
756.Fn nvlist_free_nvlist ,
757.Fn nvlist_free_descriptor ,
758.Fn nvlist_free_binary ,
759.Fn nvlist_free_bool_array ,
760.Fn nvlist_free_number_array ,
761.Fn nvlist_free_string_array ,
762.Fn nvlist_free_nvlist_array ,
763.Fn nvlist_free_descriptor_array
764functions remove element of the given name and the given type determined by the
765function name from the nvlist and free all resources associated with it.
766If element of the given name and the given type does not exist, the program
767will be aborted.
768The nvlist must not be in error state.
769.Sh NOTES
770The
771.Fn nvlist_pack
772and
773.Fn nvlist_unpack
774functions handle the byte-order conversions, so the binary buffer can be
775packed/unpacked by the hosts with the different endianness.
776.Sh EXAMPLES
777The following example demonstrates how to prepare an nvlist and send it over
778.Xr unix 4
779domain socket.
780.Bd -literal
781nvlist_t *nvl;
782int fd;
783
784fd = open("/tmp/foo", O_RDONLY);
785if (fd < 0)
786        err(1, "open(\\"/tmp/foo\\") failed");
787
788nvl = nvlist_create(0);
789/*
790 * There is no need to check if nvlist_create() succeeded,
791 * as the nvlist_add_<type>() functions can cope.
792 * If it failed, nvlist_send() will fail.
793 */
794nvlist_add_string(nvl, "filename", "/tmp/foo");
795nvlist_add_number(nvl, "flags", O_RDONLY);
796/*
797 * We just want to send the descriptor, so we can give it
798 * for the nvlist to consume (that's why we use nvlist_move
799 * not nvlist_add).
800 */
801nvlist_move_descriptor(nvl, "fd", fd);
802if (nvlist_send(sock, nvl) < 0) {
803	nvlist_destroy(nvl);
804	err(1, "nvlist_send() failed");
805}
806nvlist_destroy(nvl);
807.Ed
808.Pp
809Receiving nvlist and getting data:
810.Bd -literal
811nvlist_t *nvl;
812const char *command;
813char *filename;
814int fd;
815
816nvl = nvlist_recv(sock, 0);
817if (nvl == NULL)
818	err(1, "nvlist_recv() failed");
819
820/* For command we take pointer to nvlist's buffer. */
821command = nvlist_get_string(nvl, "command");
822/*
823 * For filename we remove it from the nvlist and take
824 * ownership of the buffer.
825 */
826filename = nvlist_take_string(nvl, "filename");
827/* The same for the descriptor. */
828fd = nvlist_take_descriptor(nvl, "fd");
829
830printf("command=%s filename=%s fd=%d\n", command, filename, fd);
831
832nvlist_destroy(nvl);
833free(filename);
834close(fd);
835/* command was freed by nvlist_destroy() */
836.Ed
837.Pp
838Iterating over nvlist:
839.Bd -literal
840nvlist_t *nvl;
841const char *name;
842void *cookie;
843int type;
844
845nvl = nvlist_recv(sock, 0);
846if (nvl == NULL)
847	err(1, "nvlist_recv() failed");
848
849cookie = NULL;
850while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
851	printf("%s=", name);
852	switch (type) {
853	case NV_TYPE_NUMBER:
854		printf("%ju", (uintmax_t)nvlist_get_number(nvl, name));
855		break;
856	case NV_TYPE_STRING:
857		printf("%s", nvlist_get_string(nvl, name));
858		break;
859	default:
860		printf("N/A");
861		break;
862	}
863	printf("\\n");
864}
865.Ed
866.Pp
867Iterating over every nested nvlist:
868.Bd -literal
869nvlist_t *nvl;
870const char *name;
871void *cookie;
872int type;
873
874nvl = nvlist_recv(sock, 0);
875if (nvl == NULL)
876	err(1, "nvlist_recv() failed");
877
878cookie = NULL;
879do {
880	while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
881		if (type == NV_TYPE_NVLIST) {
882			nvl = nvlist_get_nvlist(nvl, name);
883			cookie = NULL;
884		}
885	}
886} while ((nvl = nvlist_get_parent(nvl, &cookie)) != NULL);
887.Ed
888.Pp
889Iterating over every nested nvlist and every nvlist element:
890.Bd -literal
891nvlist_t *nvl;
892const nvlist_t * const *array;
893const char *name;
894void *cookie;
895int type;
896
897nvl = nvlist_recv(sock, 0);
898if (nvl == null)
899	err(1, "nvlist_recv() failed");
900
901cookie = null;
902do {
903	while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
904		if (type == NV_TYPE_NVLIST) {
905			nvl = nvlist_get_nvlist(nvl, name);
906			cookie = NULL;
907		} else if (type == NV_TYPE_NVLIST_ARRAY) {
908			nvl = nvlist_get_nvlist_array(nvl, name, NULL)[0];
909			cookie = NULL;
910		}
911	}
912} while ((nvl = nvlist_get_pararr(nvl, &cookie)) != NULL);
913.Ed
914.Pp
915Or alternatively:
916.Bd -literal
917nvlist_t *nvl, *tmp;
918const nvlist_t * const *array;
919const char *name;
920void *cookie;
921int type;
922
923nvl = nvlist_recv(sock, 0);
924if (nvl == null)
925	err(1, "nvlist_recv() failed");
926
927cooke = NULL;
928tmp = nvl;
929do {
930	do {
931		nvl = tmp;
932		while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
933			if (type == NV_TYPE_NVLIST) {
934				nvl = nvlist_get_nvlist(nvl, name);
935				cookie = NULL;
936			} else if (type == NV_TYPE_NVLIST_ARRAY) {
937				nvl = nvlist_get_nvlist_array(nvl, name,
938				    NULL)[0];
939				cookie = NULL;
940			}
941		}
942		cookie = NULL;
943	} while ((tmp = nvlist_get_array_next(nvl)) != NULL);
944} while ((tmp = nvlist_get_parent(nvl, &cookie)) != NULL);
945.Ed
946.Sh SEE ALSO
947.Xr close 2 ,
948.Xr dup 2 ,
949.Xr open 2 ,
950.Xr err 3 ,
951.Xr free 3 ,
952.Xr printf 3 ,
953.Xr unix 4
954.Sh HISTORY
955The
956.Nm libnv
957library appeared in
958.Fx 11.0 .
959.Sh AUTHORS
960.An -nosplit
961The
962.Nm libnv
963library was implemented by
964.An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net
965under sponsorship from the FreeBSD Foundation.
966