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