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