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