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