xref: /freebsd/share/man/man9/nv.9 (revision 276da39af92f48350aa01091a2b8b3e735217eea)
1.\"
2.\" Copyright (c) 2013 The FreeBSD Foundation
3.\" All rights reserved.
4.\"
5.\" This documentation was written by Pawel Jakub Dawidek under sponsorship
6.\" the FreeBSD Foundation.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\"    notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\"    notice, this list of conditions and the following disclaimer in the
15.\"    documentation and/or other materials provided with the distribution.
16.\"
17.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27.\" SUCH DAMAGE.
28.\"
29.\" $FreeBSD$
30.\"
31.Dd July 4, 2015
32.Dt NV 9
33.Os
34.Sh NAME
35.Nm nvlist_create ,
36.Nm nvlist_destroy ,
37.Nm nvlist_error ,
38.Nm nvlist_set_error ,
39.Nm nvlist_empty ,
40.Nm nvlist_flags ,
41.Nm nvlist_exists ,
42.Nm nvlist_free ,
43.Nm nvlist_clone ,
44.Nm nvlist_dump ,
45.Nm nvlist_fdump ,
46.Nm nvlist_size ,
47.Nm nvlist_pack ,
48.Nm nvlist_unpack ,
49.Nm nvlist_send ,
50.Nm nvlist_recv ,
51.Nm nvlist_xfer ,
52.Nm nvlist_next ,
53.Nm nvlist_add ,
54.Nm nvlist_move ,
55.Nm nvlist_get ,
56.Nm nvlist_take
57.Nd "library for name/value pairs"
58.Sh LIBRARY
59.Lb libnv
60.Sh SYNOPSIS
61.In nv.h
62.Ft "nvlist_t *"
63.Fn nvlist_create "int flags"
64.Ft void
65.Fn nvlist_destroy "nvlist_t *nvl"
66.Ft int
67.Fn nvlist_error "const nvlist_t *nvl"
68.Ft void
69.Fn nvlist_set_error "nvlist_t *nvl, int error"
70.Ft bool
71.Fn nvlist_empty "const nvlist_t *nvl"
72.Ft int
73.Fn nvlist_flags "const nvlist_t *nvl"
74.\"
75.Ft "nvlist_t *"
76.Fn nvlist_clone "const nvlist_t *nvl"
77.\"
78.Ft void
79.Fn nvlist_dump "const nvlist_t *nvl, int fd"
80.Ft void
81.Fn nvlist_fdump "const nvlist_t *nvl, FILE *fp"
82.\"
83.Ft size_t
84.Fn nvlist_size "const nvlist_t *nvl"
85.Ft "void *"
86.Fn nvlist_pack "const nvlist_t *nvl" "size_t *sizep"
87.Ft "nvlist_t *"
88.Fn nvlist_unpack "const void *buf" "size_t size" "int flags"
89.\"
90.Ft int
91.Fn nvlist_send "int sock" "const nvlist_t *nvl"
92.Ft "nvlist_t *"
93.Fn nvlist_recv "int sock" "int flags"
94.Ft "nvlist_t *"
95.Fn nvlist_xfer "int sock" "nvlist_t *nvl" "int flags"
96.\"
97.Ft "const char *"
98.Fn nvlist_next "const nvlist_t *nvl" "int *typep" "void **cookiep"
99.\"
100.Ft bool
101.Fn nvlist_exists "const nvlist_t *nvl" "const char *name"
102.Ft bool
103.Fn nvlist_exists_type "const nvlist_t *nvl" "const char *name" "int type"
104.Ft bool
105.Fn nvlist_exists_null "const nvlist_t *nvl" "const char *name"
106.Ft bool
107.Fn nvlist_exists_bool "const nvlist_t *nvl" "const char *name"
108.Ft bool
109.Fn nvlist_exists_number "const nvlist_t *nvl" "const char *name"
110.Ft bool
111.Fn nvlist_exists_string "const nvlist_t *nvl" "const char *name"
112.Ft bool
113.Fn nvlist_exists_nvlist "const nvlist_t *nvl" "const char *name"
114.Ft bool
115.Fn nvlist_exists_descriptor "const nvlist_t *nvl" "const char *name"
116.Ft bool
117.Fn nvlist_exists_binary "const nvlist_t *nvl" "const char *name"
118.\"
119.Ft void
120.Fn nvlist_add_null "nvlist_t *nvl" "const char *name"
121.Ft void
122.Fn nvlist_add_bool "nvlist_t *nvl" "const char *name" "bool value"
123.Ft void
124.Fn nvlist_add_number "nvlist_t *nvl" "const char *name" "uint64_t value"
125.Ft void
126.Fn nvlist_add_string "nvlist_t *nvl" "const char *name" "const char *value"
127.Ft void
128.Fn nvlist_add_stringf "nvlist_t *nvl" "const char *name" "const char *valuefmt" "..."
129.Ft void
130.Fn nvlist_add_stringv "nvlist_t *nvl" "const char *name" "const char *valuefmt" "va_list valueap"
131.Ft void
132.Fn nvlist_add_nvlist "nvlist_t *nvl" "const char *name" "const nvlist_t *value"
133.Ft void
134.Fn nvlist_add_descriptor "nvlist_t *nvl" "const char *name" "int value"
135.Ft void
136.Fn nvlist_add_binary "nvlist_t *nvl" "const char *name" "const void *value" "size_t size"
137.\"
138.Ft void
139.Fn nvlist_move_string "nvlist_t *nvl" "const char *name" "char *value"
140.Ft void
141.Fn nvlist_move_nvlist "nvlist_t *nvl" "const char *name" "nvlist_t *value"
142.Ft void
143.Fn nvlist_move_descriptor "nvlist_t *nvl" "const char *name" "int value"
144.Ft void
145.Fn nvlist_move_binary "nvlist_t *nvl" "const char *name" "void *value" "size_t size"
146.\"
147.Ft bool
148.Fn nvlist_get_bool "const nvlist_t *nvl" "const char *name"
149.Ft uint64_t
150.Fn nvlist_get_number "const nvlist_t *nvl" "const char *name"
151.Ft "const char *"
152.Fn nvlist_get_string "const nvlist_t *nvl" "const char *name"
153.Ft "const nvlist_t *"
154.Fn nvlist_get_nvlist "const nvlist_t *nvl" "const char *name"
155.Ft int
156.Fn nvlist_get_descriptor "const nvlist_t *nvl" "const char *name"
157.Ft "const void *"
158.Fn nvlist_get_binary "const nvlist_t *nvl" "const char *name" "size_t *sizep"
159.Ft "const nvlist_t *"
160.Fn nvlist_get_parent "const nvlist_t *nvl" "void **cookiep"
161.\"
162.Ft bool
163.Fn nvlist_take_bool "nvlist_t *nvl" "const char *name"
164.Ft uint64_t
165.Fn nvlist_take_number "nvlist_t *nvl" "const char *name"
166.Ft "char *"
167.Fn nvlist_take_string "nvlist_t *nvl" "const char *name"
168.Ft "nvlist_t *"
169.Fn nvlist_take_nvlist "nvlist_t *nvl" "const char *name"
170.Ft int
171.Fn nvlist_take_descriptor "nvlist_t *nvl" "const char *name"
172.Ft "void *"
173.Fn nvlist_take_binary "nvlist_t *nvl" "const char *name" "size_t *sizep"
174.\"
175.Ft void
176.Fn nvlist_free "nvlist_t *nvl" "const char *name"
177.Ft void
178.Fn nvlist_free_type "nvlist_t *nvl" "const char *name" "int type"
179.\"
180.Ft void
181.Fn nvlist_free_null "nvlist_t *nvl" "const char *name"
182.Ft void
183.Fn nvlist_free_bool "nvlist_t *nvl" "const char *name"
184.Ft void
185.Fn nvlist_free_number "nvlist_t *nvl" "const char *name"
186.Ft void
187.Fn nvlist_free_string "nvlist_t *nvl" "const char *name"
188.Ft void
189.Fn nvlist_free_nvlist "nvlist_t *nvl" "const char *name"
190.Ft void
191.Fn nvlist_free_descriptor "nvlist_t *nvl" "const char *name"
192.Ft void
193.Fn nvlist_free_binary "nvlist_t *nvl" "const char *name"
194.Sh DESCRIPTION
195The
196.Nm libnv
197library allows to easily manage name value pairs as well as send and receive
198them over sockets.
199A group (list) of name value pairs is called an
200.Nm nvlist .
201The API supports the following data types:
202.Bl -ohang -offset indent
203.It Sy null ( NV_TYPE_NULL )
204There is no data associated with the name.
205.It Sy bool ( NV_TYPE_BOOL )
206The value can be either
207.Dv true
208or
209.Dv false .
210.It Sy number ( NV_TYPE_NUMBER )
211The value is a number stored as
212.Vt uint64_t .
213.It Sy string ( NV_TYPE_STRING )
214The value is a C string.
215.It Sy nvlist ( NV_TYPE_NVLIST )
216The value is a nested nvlist.
217.It Sy descriptor ( NV_TYPE_DESCRIPTOR )
218The value is a file descriptor.
219Note that file descriptors can be sent only over
220.Xr unix 4
221domain sockets.
222.It Sy binary ( NV_TYPE_BINARY )
223The value is a binary buffer.
224.El
225.Pp
226The
227.Fn nvlist_create
228function allocates memory and initializes an nvlist.
229.Pp
230The following flag can be provided:
231.Pp
232.Bl -tag -width "NV_FLAG_IGNORE_CASE" -compact -offset indent
233.It Dv NV_FLAG_IGNORE_CASE
234Perform case-insensitive lookups of provided names.
235.It Dv NV_FLAG_NO_UNIQUE
236Names in the nvlist do not have to be unique.
237.El
238.Pp
239The
240.Fn nvlist_destroy
241function destroys the given nvlist.
242Function does nothing if
243.Dv NULL
244nvlist is provided.
245Function never modifies the
246.Va errno
247global variable.
248.Pp
249The
250.Fn nvlist_error
251function returns any error value that the nvlist accumulated.
252If the given nvlist is
253.Dv NULL
254the
255.Er ENOMEM
256error will be returned.
257.Pp
258The
259.Fn nvlist_set_error
260function sets an nvlist to be in the error state.
261Subsequent calls to
262.Fn nvlist_error
263will return the given error value.
264This function cannot be used to clear the error state from an nvlist.
265This function does nothing if the nvlist is already in the error state.
266.Pp
267The
268.Fn nvlist_empty
269function returns
270.Dv true
271if the given nvlist is empty and
272.Dv false
273otherwise.
274The nvlist must not be in error state.
275.Pp
276The
277.Fn nvlist_flags
278function returns flags used to create the nvlist with the
279.Fn nvlist_create
280function.
281.Pp
282The
283.Fn nvlist_clone
284functions clones the given nvlist.
285The clone shares no resources with its origin.
286This also means that all file descriptors that are part of the nvlist will be
287duplicated with the
288.Xr dup 2
289system call before placing them in the clone.
290.Pp
291The
292.Fn nvlist_dump
293dumps nvlist content for debugging purposes to the given file descriptor
294.Fa fd .
295.Pp
296The
297.Fn nvlist_fdump
298dumps nvlist content for debugging purposes to the given file stream
299.Fa fp .
300.Pp
301The
302.Fn nvlist_size
303function returns the size of the given nvlist after converting it to binary
304buffer with the
305.Fn nvlist_pack
306function.
307.Pp
308The
309.Fn nvlist_pack
310function converts the given nvlist to a binary buffer.
311The function allocates memory for the buffer, which should be freed with the
312.Xr free 3
313function.
314If the
315.Fa sizep
316argument is not
317.Dv NULL ,
318the size of the buffer will be stored there.
319The function returns
320.Dv NULL
321in case of an error (allocation failure).
322If the nvlist contains any file descriptors
323.Dv NULL
324will be returned.
325The nvlist must not be in error state.
326.Pp
327The
328.Fn nvlist_unpack
329function converts the given buffer to the nvlist.
330The
331.Fa flags
332argument defines what type of the top level nvlist is expected to be.
333Flags are set up using the
334.Fn nvlist_create
335function.
336If the nvlist flags do not match the flags passed to
337.Fn nvlist_unpack ,
338the nvlist will not be returned.
339Every nested nvlist list should be checked using
340.Fn nvlist_flags
341function.
342The function returns
343.Dv NULL
344in case of an error.
345.Pp
346The
347.Fn nvlist_send
348function sends the given nvlist over the socket given by the
349.Fa sock
350argument.
351Note that nvlist that contains file descriptors can only be send over
352.Xr unix 4
353domain sockets.
354.Pp
355The
356.Fn nvlist_recv
357function receives nvlist over the socket given by the
358.Fa sock
359argument.
360The
361.Fa flags
362argument defines what type of the top level nvlist is expected to be.
363Flags are set up using the
364.Fn nvlist_create
365function.
366If the nvlist flags do not match the flags passed to
367.Fn nvlist_recv ,
368the nvlist will not be returned.
369Every nested nvlist list should be checked using
370.Fn nvlist_flags
371function.
372.Pp
373The
374.Fn nvlist_xfer
375function sends the given nvlist over the socket given by the
376.Fa sock
377argument and receives nvlist over the same socket.
378The
379.Fa flags
380argument defines what type of the top level nvlist is expected to be.
381Flags are set up using the
382.Fn nvlist_create
383function.
384If the nvlist flags do not match the flags passed to
385.Fn nvlist_xfer ,
386the nvlist will not be returned.
387Every nested nvlist list should be checked using
388.Fn nvlist_flags
389function.
390The given nvlist is always destroyed.
391.Pp
392The
393.Fn nvlist_next
394function iterates over the given nvlist returning names and types of subsequent
395elements.
396The
397.Fa cookiep
398argument allows the function to figure out which element should be returned
399next.
400The
401.Va *cookiep
402should be set to
403.Dv NULL
404for the first call and should not be changed later.
405Returning
406.Dv NULL
407means there are no more elements on the nvlist.
408The
409.Fa typep
410argument can be NULL.
411Elements may not be removed from the nvlist while traversing it.
412The nvlist must not be in error state.
413.Pp
414The
415.Fn nvlist_exists
416function returns
417.Dv true
418if element of the given name exists (besides of its type) or
419.Dv false
420otherwise.
421The nvlist must not be in error state.
422.Pp
423The
424.Fn nvlist_exists_type
425function returns
426.Dv true
427if element of the given name and the given type exists or
428.Dv false
429otherwise.
430The nvlist must not be in error state.
431.Pp
432The
433.Fn nvlist_exists_null ,
434.Fn nvlist_exists_bool ,
435.Fn nvlist_exists_number ,
436.Fn nvlist_exists_string ,
437.Fn nvlist_exists_nvlist ,
438.Fn nvlist_exists_descriptor ,
439.Fn nvlist_exists_binary
440functions return
441.Dv true
442if element of the given name and the given type determined by the function name
443exists or
444.Dv false
445otherwise.
446The nvlist must not be in error state.
447.Pp
448The
449.Fn nvlist_add_null ,
450.Fn nvlist_add_bool ,
451.Fn nvlist_add_number ,
452.Fn nvlist_add_string ,
453.Fn nvlist_add_stringf ,
454.Fn nvlist_add_stringv ,
455.Fn nvlist_add_nvlist ,
456.Fn nvlist_add_descriptor ,
457.Fn nvlist_add_binary
458functions add element to the given nvlist.
459When adding string or binary buffor the functions will allocate memory
460and copy the data over.
461When adding nvlist, the nvlist will be cloned and clone will be added.
462When adding descriptor, the descriptor will be duplicated using the
463.Xr dup 2
464system call and the new descriptor will be added.
465If an error occurs while adding new element, internal error is set which can be
466examined using the
467.Fn nvlist_error
468function.
469.Pp
470The
471.Fn nvlist_move_string ,
472.Fn nvlist_move_nvlist ,
473.Fn nvlist_move_descriptor ,
474.Fn nvlist_move_binary
475functions add new element to the given nvlist, but unlike
476.Fn nvlist_add_<type>
477functions they will consume the given resource.
478If an error occurs while adding new element, the resource is destroyed and
479internal error is set which can be examined using the
480.Fn nvlist_error
481function.
482.Pp
483The
484.Fn nvlist_get_bool ,
485.Fn nvlist_get_number ,
486.Fn nvlist_get_string ,
487.Fn nvlist_get_nvlist ,
488.Fn nvlist_get_descriptor ,
489.Fn nvlist_get_binary
490functions allow to obtain value of the given name.
491In case of string, nvlist, descriptor or binary, returned resource should
492not be modified - it still belongs to the nvlist.
493If element of the given name does not exist, the program will be aborted.
494To avoid that the caller should check for existence before trying to obtain
495the value or use
496.Xr dnvlist 3
497extension, which allows to provide default value for a missing element.
498The nvlist must not be in error state.
499.Pp
500The
501.Fn nvlist_get_parent
502function allows to obtain the parent nvlist from the nested nvlist.
503.Pp
504The
505.Fn nvlist_take_bool ,
506.Fn nvlist_take_number ,
507.Fn nvlist_take_string ,
508.Fn nvlist_take_nvlist ,
509.Fn nvlist_take_descriptor ,
510.Fn nvlist_take_binary
511functions return value associated with the given name and remove the element
512from the nvlist.
513In case of string and binary values, the caller is responsible for free returned
514memory using the
515.Xr free 3
516function.
517In case of nvlist, the caller is responsible for destroying returned nvlist
518using the
519.Fn nvlist_destroy
520function.
521In case of descriptor, the caller is responsible for closing returned descriptor
522using the
523.Fn close 2
524system call.
525If element of the given name does not exist, the program will be aborted.
526To avoid that the caller should check for existence before trying to obtain
527the value or use
528.Xr dnvlist 3
529extension, which allows to provide default value for a missing element.
530The nvlist must not be in error state.
531.Pp
532The
533.Fn nvlist_free
534function removes element of the given name from the nvlist (besides of its type)
535and frees all resources associated with it.
536If element of the given name does not exist, the program will be aborted.
537The nvlist must not be in error state.
538.Pp
539The
540.Fn nvlist_free_type
541function removes element of the given name and the given type from the nvlist
542and frees all resources associated with it.
543If element of the given name and the given type does not exist, the program
544will be aborted.
545The nvlist must not be in error state.
546.Pp
547The
548.Fn nvlist_free_null ,
549.Fn nvlist_free_bool ,
550.Fn nvlist_free_number ,
551.Fn nvlist_free_string ,
552.Fn nvlist_free_nvlist ,
553.Fn nvlist_free_descriptor ,
554.Fn nvlist_free_binary
555functions remove element of the given name and the given type determined by the
556function name from the nvlist and free all resources associated with it.
557If element of the given name and the given type does not exist, the program
558will be aborted.
559The nvlist must not be in error state.
560.Sh EXAMPLES
561The following example demonstrates how to prepare an nvlist and send it over
562.Xr unix 4
563domain socket.
564.Bd -literal
565nvlist_t *nvl;
566int fd;
567
568fd = open("/tmp/foo", O_RDONLY);
569if (fd < 0)
570        err(1, "open(\\"/tmp/foo\\") failed");
571
572nvl = nvlist_create(0);
573/*
574 * There is no need to check if nvlist_create() succeeded,
575 * as the nvlist_add_<type>() functions can cope.
576 * If it failed, nvlist_send() will fail.
577 */
578nvlist_add_string(nvl, "filename", "/tmp/foo");
579nvlist_add_number(nvl, "flags", O_RDONLY);
580/*
581 * We just want to send the descriptor, so we can give it
582 * for the nvlist to consume (that's why we use nvlist_move
583 * not nvlist_add).
584 */
585nvlist_move_descriptor(nvl, "fd", fd);
586if (nvlist_send(sock, nvl) < 0) {
587	nvlist_destroy(nvl);
588	err(1, "nvlist_send() failed");
589}
590nvlist_destroy(nvl);
591.Ed
592.Pp
593Receiving nvlist and getting data:
594.Bd -literal
595nvlist_t *nvl;
596const char *command;
597char *filename;
598int fd;
599
600nvl = nvlist_recv(sock, 0);
601if (nvl == NULL)
602	err(1, "nvlist_recv() failed");
603
604/* For command we take pointer to nvlist's buffer. */
605command = nvlist_get_string(nvl, "command");
606/*
607 * For filename we remove it from the nvlist and take
608 * ownership of the buffer.
609 */
610filename = nvlist_take_string(nvl, "filename");
611/* The same for the descriptor. */
612fd = nvlist_take_descriptor(nvl, "fd");
613
614printf("command=%s filename=%s fd=%d\n", command, filename, fd);
615
616nvlist_destroy(nvl);
617free(filename);
618close(fd);
619/* command was freed by nvlist_destroy() */
620.Ed
621.Pp
622Iterating over nvlist:
623.Bd -literal
624nvlist_t *nvl;
625const char *name;
626void *cookie;
627int type;
628
629nvl = nvlist_recv(sock, 0);
630if (nvl == NULL)
631	err(1, "nvlist_recv() failed");
632
633cookie = NULL;
634while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
635	printf("%s=", name);
636	switch (type) {
637	case NV_TYPE_NUMBER:
638		printf("%ju", (uintmax_t)nvlist_get_number(nvl, name));
639		break;
640	case NV_TYPE_STRING:
641		printf("%s", nvlist_get_string(nvl, name));
642		break;
643	default:
644		printf("N/A");
645		break;
646	}
647	printf("\\n");
648}
649.Ed
650.Pp
651Iterating over every nested nvlist:
652.Bd -literal
653nvlist_t *nvl;
654const char *name;
655void *cookie;
656int type;
657
658nvl = nvlist_recv(sock, 0);
659if (nvl == NULL)
660	err(1, "nvlist_recv() failed");
661
662cookie = NULL;
663do {
664	while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
665		if (type == NV_TYPE_NVLIST) {
666			nvl = nvlist_get_nvlist(nvl, name);
667			cookie = NULL;
668		}
669	}
670} while ((nvl = nvlist_get_parent(nvl, &cookie)) != NULL);
671.Ed
672.Sh SEE ALSO
673.Xr close 2 ,
674.Xr dup 2 ,
675.Xr open 2 ,
676.Xr err 3 ,
677.Xr free 3 ,
678.Xr printf 3 ,
679.Xr unix 4
680.Sh HISTORY
681The
682.Nm libnv
683library appeared in
684.Fx 11.0 .
685.Sh AUTHORS
686.An -nosplit
687The
688.Nm libnv
689library was implemented by
690.An Pawel Jakub Dawidek Aq Mt pawel@dawidek.net
691under sponsorship from the FreeBSD Foundation.
692