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