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