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