1.\" $OpenBSD: ibuf_add.3,v 1.6 2024/11/26 13:57:31 claudio Exp $ 2.\" 3.\" Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org> 4.\" Copyright (c) 2010 Nicholas Marriott <nicm@openbsd.org> 5.\" 6.\" Permission to use, copy, modify, and distribute this software for any 7.\" purpose with or without fee is hereby granted, provided that the above 8.\" copyright notice and this permission notice appear in all copies. 9.\" 10.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14.\" WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17.\" 18.Dd $Mdocdate: November 26 2024 $ 19.Dt IBUF_ADD 3 20.Os 21.Sh NAME 22.Nm ibuf_add , 23.Nm ibuf_add_h16 , 24.Nm ibuf_add_h32 , 25.Nm ibuf_add_h64 , 26.Nm ibuf_add_ibuf , 27.Nm ibuf_add_n16 , 28.Nm ibuf_add_n32 , 29.Nm ibuf_add_n64 , 30.Nm ibuf_add_n8 , 31.Nm ibuf_add_zero , 32.Nm ibuf_close , 33.Nm ibuf_data , 34.Nm ibuf_dynamic , 35.Nm ibuf_fd_avail , 36.Nm ibuf_fd_get , 37.Nm ibuf_fd_set , 38.Nm ibuf_free , 39.Nm ibuf_from_buffer , 40.Nm ibuf_from_ibuf , 41.Nm ibuf_get , 42.Nm ibuf_get_ibuf , 43.Nm ibuf_get_h16 , 44.Nm ibuf_get_h32 , 45.Nm ibuf_get_h64 , 46.Nm ibuf_get_n16 , 47.Nm ibuf_get_n32 , 48.Nm ibuf_get_n64 , 49.Nm ibuf_get_n8 , 50.Nm ibuf_get_string , 51.Nm ibuf_left , 52.Nm ibuf_open , 53.Nm ibuf_read , 54.Nm ibuf_reserve , 55.Nm ibuf_rewind , 56.Nm ibuf_seek , 57.Nm ibuf_set , 58.Nm ibuf_set_h16 , 59.Nm ibuf_set_h32 , 60.Nm ibuf_set_h64 , 61.Nm ibuf_set_n16 , 62.Nm ibuf_set_n32 , 63.Nm ibuf_set_n64 , 64.Nm ibuf_set_n8 , 65.Nm ibuf_size , 66.Nm ibuf_skip , 67.Nm ibuf_truncate , 68.Nm ibuf_write , 69.Nm msgbuf_clear , 70.Nm msgbuf_free , 71.Nm msgbuf_get , 72.Nm msgbuf_new , 73.Nm msgbuf_new_reader , 74.Nm msgbuf_queuelen , 75.Nm msgbuf_read , 76.Nm msgbuf_write 77.Nd save buffer API for basic IO 78.Sh SYNOPSIS 79.In sys/queue.h 80.In imsg.h 81.Fd #define IBUF_READ_SIZE 65535 82.Ft int 83.Fn ibuf_add "struct ibuf *buf" "const void *data" "size_t len" 84.Ft int 85.Fn ibuf_add_h16 "struct ibuf *buf" "uint64_t value" 86.Ft int 87.Fn ibuf_add_h32 "struct ibuf *buf" "uint64_t value" 88.Ft int 89.Fn ibuf_add_h64 "struct ibuf *buf" "uint64_t value" 90.Ft int 91.Fn ibuf_add_ibuf "struct ibuf *buf" "const struct ibuf *from" 92.Ft int 93.Fn ibuf_add_n16 "struct ibuf *buf" "uint64_t value" 94.Ft int 95.Fn ibuf_add_n32 "struct ibuf *buf" "uint64_t value" 96.Ft int 97.Fn ibuf_add_n64 "struct ibuf *buf" "uint64_t value" 98.Ft int 99.Fn ibuf_add_n8 "struct ibuf *buf" "uint64_t value" 100.Ft int 101.Fn ibuf_add_zero "struct ibuf *buf" "size_t len" 102.Ft void 103.Fn ibuf_close "struct msgbuf *msgbuf" "struct ibuf *buf" 104.Ft "void *" 105.Fn ibuf_data "struct ibuf *buf" 106.Ft "struct ibuf *" 107.Fn ibuf_dynamic "size_t len" "size_t max" 108.Ft int 109.Fn ibuf_fd_avail "struct ibuf *buf" 110.Ft int 111.Fn ibuf_fd_get "struct ibuf *buf" 112.Ft void 113.Fn ibuf_fd_set "struct ibuf *buf" "int fd" 114.Ft void 115.Fn ibuf_free "struct ibuf *buf" 116.Ft void 117.Fn ibuf_from_buffer "struct ibuf *buf" "void *data" "size_t len" 118.Ft void 119.Fn ibuf_from_ibuf "struct ibuf *buf" "const ibuf *from" 120.Ft int 121.Fn ibuf_get "struct ibuf *buf" "void *data" "size_t len" 122.Ft int 123.Fn ibuf_get_ibuf "struct ibuf *buf" "size_t len" "struct ibuf *new" 124.Ft int 125.Fn ibuf_get_h16 "struct ibuf *buf" "uint16_t *value" 126.Ft int 127.Fn ibuf_get_h32 "struct ibuf *buf" "uint32_t *value" 128.Ft int 129.Fn ibuf_get_h64 "struct ibuf *buf" "uint64_t *value" 130.Ft int 131.Fn ibuf_get_n16 "struct ibuf *buf" "uint16_t *value" 132.Ft int 133.Fn ibuf_get_n32 "struct ibuf *buf" "uint32_t *value" 134.Ft int 135.Fn ibuf_get_n64 "struct ibuf *buf" "uint64_t *value" 136.Ft int 137.Fn ibuf_get_n8 "struct ibuf *buf" "uint8_t *value" 138.Ft "char *" 139.Fn ibuf_get_string "struct ibuf *buf" "size_t len" 140.Ft size_t 141.Fn ibuf_left "const struct ibuf *buf" 142.Ft "struct ibuf *" 143.Fn ibuf_open "size_t len" 144.Ft int 145.Fn ibuf_read "int fd" "struct msgbuf *msgbuf" 146.Ft "void *" 147.Fn ibuf_reserve "struct ibuf *buf" "size_t len" 148.Ft void 149.Fn ibuf_rewind "struct ibuf *buf" 150.Ft "void *" 151.Fn ibuf_seek "struct ibuf *buf" "size_t pos" "size_t len" 152.Ft int 153.Fn ibuf_set "struct ibuf *buf" "size_t pos" "const void *data" \ 154 "size_t len" 155.Ft int 156.Fn ibuf_set_h16 "struct ibuf *buf" "size_t pos" "uint64_t value" 157.Ft int 158.Fn ibuf_set_h32 "struct ibuf *buf" "size_t pos" "uint64_t value" 159.Ft int 160.Fn ibuf_set_h64 "struct ibuf *buf" "size_t pos" "uint64_t value" 161.Ft int 162.Fn ibuf_set_n16 "struct ibuf *buf" "size_t pos" "uint64_t value" 163.Ft int 164.Fn ibuf_set_n32 "struct ibuf *buf" "size_t pos" "uint64_t value" 165.Ft int 166.Fn ibuf_set_n64 "struct ibuf *buf" "size_t pos" "uint64_t value" 167.Ft int 168.Fn ibuf_set_n8 "struct ibuf *buf" "size_t pos" "uint64_t value" 169.Ft size_t 170.Fn ibuf_size "const struct ibuf *buf" 171.Ft int 172.Fn ibuf_skip "struct ibuf *buf" "size_t len" 173.Ft int 174.Fn ibuf_truncate "struct ibuf *buf" "size_t len" 175.Ft int 176.Fn ibuf_write "struct msgbuf *msgbuf" 177.Ft void 178.Fn msgbuf_clear "struct msgbuf *msgbuf" 179.Ft void 180.Fn msgbuf_free "struct msgbuf *msgbuf" 181.Ft "struct ibuf *" 182.Fn msgbuf_get "struct msgbuf *msgbuf" 183.Ft "struct msgbuf *" 184.Fn msgbuf_new void 185.Ft "struct msgbuf *" 186.Fn msgbuf_new_reader "size_t hdrsz" \ 187 "struct ibuf *(*readhdr)(struct ibuf *, void *, int *)" "void *arg" 188.Ft uint32_t 189.Fn msgbuf_queuelen "struct msgbuf *msgbuf" 190.Ft int 191.Fn msgbuf_read "struct msgbuf *msgbuf" 192.Ft int 193.Fn msgbuf_write "struct msgbuf *msgbuf" 194.Sh DESCRIPTION 195The ibuf API defines functions to manipulate buffers, used for example to 196construct imsgs with 197.Xr imsg_create 3 . 198A 199.Vt struct ibuf 200is a single buffer. 201It has a maximum size, a read and a write position. 202Buffers should be either constructed with the various 203.Fn ibuf_add 204and 205.Fn ibuf_set 206functions or consumed with the various 207.Fn ibuf_get 208functions. 209A 210.Vt struct msgbuf 211is used to queue the output buffers for transmission. 212.Pp 213.Fn ibuf_add 214appends a block of data to 215.Fa buf . 2160 is returned on success and \-1 on failure. 217.Pp 218.Fn ibuf_add_h16 , 219.Fn ibuf_add_h32 , 220and 221.Fn ibuf_add_h64 222add a 2-byte, 4-byte, and 8-byte 223.Fa value 224to 225.Fa buf 226in host byte order. 227This function checks 228.Fa value 229to not overflow. 2300 is returned on success and \-1 on failure. 231.Pp 232.Fn ibuf_add_ibuf 233appends the buffer 234.Fa from 235to 236.Fa buf . 2370 is returned on success and \-1 on failure. 238.Pp 239.Fn ibuf_add_n8 , 240.Fn ibuf_add_n16 , 241.Fn ibuf_add_n32 , 242and 243.Fn ibuf_add_n64 244add a 1-byte, 2-byte, 4-byte, and 8-byte 245.Fa value 246to 247.Fa buf 248in network byte order. 249This function checks 250.Fa value 251to not overflow. 2520 is returned on success and \-1 on failure. 253.Pp 254.Fn ibuf_add_zero 255appends a block of zeros to 256.Fa buf . 2570 is returned on success and \-1 on failure. 258.Pp 259.Fn ibuf_close 260appends 261.Fa buf 262to 263.Fa msgbuf 264ready to be sent. 265.Pp 266.Fn ibuf_data 267returns the pointer to the internal buffer. 268This function should only be used together with 269.Fn ibuf_size 270to process a previously generated buffer. 271.Pp 272.Fn ibuf_dynamic 273allocates a resizeable buffer of initial length 274.Fa len 275and maximum size 276.Fa max . 277Buffers allocated with 278.Fn ibuf_dynamic 279are automatically grown if necessary when data is added. 280.Pp 281.Fn ibuf_fd_avail , 282.Fn ibuf_fd_get 283and 284.Fn ibuf_fd_set 285are functions to check, get and set the file descriptor assigned to 286.Fa buf . 287After calling 288.Fn ibuf_fd_set 289the file descriptor is part of the 290.Fa buf 291and will be transmitted or closed by the ibuf API. 292Any previously set file descriptor will be closed before assigning a 293new descriptor. 294.Fn ibuf_fd_get 295returns the file descriptor and passes the responsibility to track the 296descriptor back to the program. 297.Fn ibuf_fd_avail 298returns true if there is a file descriptor set on 299.Fa buf . 300.Pp 301.Fn ibuf_free 302frees 303.Fa buf 304and any associated storage, and closes any file descriptor set with 305.Fn ibuf_fd_set . 306If 307.Fa buf 308is a NULL pointer, no action occurs. 309.Pp 310.Fn ibuf_from_buffer 311initializes the passed 312.Fa buf 313to point at 314.Fa data 315and spanning 316.Fa len 317bytes. 318The returned buffer can be read using the various 319.Fn ibuf_get 320functions. 321.Fn ibuf_from_ibuf 322duplicates the 323.Fa from 324ibuf into 325.Fa buf 326without modifying 327.Fa from . 328This allows safely peeking into an ibuf without consuming data. 329.Pp 330.Fn ibuf_get 331consumes a block of data from 332.Fa buf 333spanning 334.Fa len 335bytes. 3360 is returned on success and \-1 on failure. 337.Pp 338.Fn ibuf_get_ibuf 339consumes 340.Fa len 341bytes from the buffer 342.Fa buf 343and returns it in 344.Fa new 345covering this region. 346The data in this buffer is only valid as long as 347.Fa buf 348remains valid. 349There is no need to deallocate 350.Fa new 351using 352.Fn ibuf_free . 3530 is returned on success and \-1 on failure. 354.Pp 355.Fn ibuf_get_h16 , 356.Fn ibuf_get_h32 , 357and 358.Fn ibuf_get_h64 359get a 2-byte, 4-byte, and 8-byte 360.Fa value 361from 362.Fa buf 363without altering byte order. 3640 is returned on success and \-1 on failure. 365.Pp 366.Fn ibuf_get_n8 , 367.Fn ibuf_get_n16 , 368.Fn ibuf_get_n32 , 369and 370.Fn ibuf_get_n64 371get a 1-byte, 2-byte, 4-byte, and 8-byte 372.Fa value 373from 374.Fa buf 375converting the value from network to host byte order. 3760 is returned on success and \-1 on failure. 377.Pp 378.Fn ibuf_get_string 379consumes 380.Fa len 381bytes from the buffer 382.Fa buf 383and returns the result of passing the bytes and len to 384.Xr strndup 3 . 385The returned pointer should be passed to 386.Xr free 3 387when it is no longer needed. 388On error NULL is returned. 389.Pp 390The 391.Fn ibuf_open 392function allocates a fixed-length buffer. 393The buffer may not be resized and may contain a maximum of 394.Fa len 395bytes. 396On success 397.Fn ibuf_open 398returns a pointer to the buffer; on failure it returns NULL. 399.Pp 400The 401.Fn ibuf_read 402routine receives pending messages using 403.Xr read 2 . 404It calls the 405.Fn readhdr 406callback to obtain a 407.Vt struct ibuf 408of the appropriate size. 409It returns 1 on success, 0 if the connection was closed and \-1 on error 410and the global variable errno is set to indicate the error. 411The errors 412.Er EINTR 413and 414.Er EAGAIN 415are treated as follows: 416.Er EINTR 417will automatically retry the read operation while 418.Er EAGAIN 419will be ignored with a 1 return. 420The application will then retry the operation at a later stage. 421.Pp 422.Fn ibuf_reserve 423is used to reserve 424.Fa len 425bytes in 426.Fa buf . 427A pointer to the start of the reserved space is returned, or NULL on error. 428.Pp 429.Fn ibuf_rewind 430resets the read offset to the start of the buffer. 431.Pp 432.Fn ibuf_seek 433returns a pointer to the part of the buffer at offset 434.Fa pos 435and of extent 436.Fa len . 437NULL is returned if the requested range is outside the part of the buffer 438in use. 439.Pp 440.Fn ibuf_set 441replaces a part of 442.Fa buf 443at offset 444.Fa pos 445with the 446.Fa data 447of extent 448.Fa len . 4490 is returned on success and \-1 on failure. 450.Pp 451.Fn ibuf_set_h16 , 452.Fn ibuf_set_h32 453and 454.Fn ibuf_set_h64 455replace a 2-byte, 4-byte or 8-byte 456.Fa value 457at offset 458.Fa pos 459in the buffer 460.Fa buf 461in host byte order. 462This function checks 463.Fa value 464to not overflow. 4650 is returned on success and \-1 on failure. 466.Pp 467.Fn ibuf_set_n8 , 468.Fn ibuf_set_n16 , 469.Fn ibuf_set_n32 470and 471.Fn ibuf_set_n64 472replace a 1-byte, 2-byte, 4-byte or 8-byte 473.Fa value 474at offset 475.Fa pos 476in the buffer 477.Fa buf 478in network byte order. 479This function checks 480.Fa value 481to not overflow. 4820 is returned on success and \-1 on failure. 483.Pp 484.Fn ibuf_size 485and 486.Fn ibuf_left 487are functions which return the total bytes used and available in 488.Fa buf , 489respectively. 490.Pp 491.Fn ibuf_skip 492advances the read position in 493.Fa buf 494by 495.Fa len 496bytes. 4970 is returned on success and \-1 on failure. 498.Pp 499.Fn ibuf_truncate 500truncates the buffer to 501.Fa len 502bytes if necessary zero extending the buffer. 5030 is returned on success and \-1 on failure. 504.Pp 505The 506.Fn ibuf_write 507routine transmits as many pending buffers as possible from 508.Fa msgbuf 509using 510.Xr writev 2 . 511It returns 0 if it succeeds, -1 on error and the global variable 512.Va errno 513is set to indicate the error. 514The errors 515.Er EINTR , 516.Er EAGAIN , 517and 518.Er ENOBUFS 519are treated as follows: 520.Er EINTR 521will automatically retry the write operation while the other errors are 522ignored with a 0 return. 523The application will then retry the operation at a later stage. 524.Pp 525.Fn msgbuf_clear 526empties a msgbuf, removing and discarding any queued buffers. 527.Pp 528.Fn msgbuf_free 529function frees the 530.Fa msgbuf 531allocated by 532.Fn msgbuf_new 533or 534.Fn msgbuf_new_reader . 535.Fn msgbuf_get 536returns the next pending message. 537It should be called in a loop until NULL is returned. 538The ibuf returned must be freed by calling 539.Fa ibuf_free . 540.Pp 541.Fn msgbuf_new 542allocates a new message buffer structure which can be used with 543.Fn ibuf_write 544or 545.Fn msbuf_write . 546On error NULL is returned. 547.Pp 548.Fn msgbuf_new_reader 549allocates a new message buffer structure which can additionally be used with 550.Fn ibuf_read 551and 552.Fn msgbuf_read . 553The 554.Fa hdrsz 555argument defines the size of the ibuf passed to the 556.Fa readhdr 557callback. 558The 559.Fa readhdr 560callback parses the header and returns a new 561.Vt struct ibuf 562of the size of the full message. 563It can take ownership of the file descriptor passed in its 564.Vt "int *" 565argument. 566It should return NULL on error and set the global variable 567.Va errno 568appropriately. 569The 570.Fa arg 571pointer is passed to the 572.Fa readhdr 573callback. 574On error 575.Fn msgbuf_new_reader 576returns NULL. 577.Pp 578.Fn msgbuf_queuelen 579returns the number of messages queued in 580.Fa msgbuf . 581This function returns 0 if no messages are pending for transmission. 582.Pp 583The 584.Fn msgbuf_read 585routine receives pending messages using 586.Xr recvmsg 2 and supports file descriptor passing. 587The function calls the 588.Fn readhdr 589callback function to get the total size of message. 590It returns 1 on success, 0 if the connection was closed and \-1 on error 591and the global variable errno is set to indicate the error. 592The errors 593.Er EINTR 594and 595.Er EAGAIN 596are treated as follows: 597.Er EINTR 598will automatically retry the read operation while 599.Er EAGAIN 600will be ignored with a 1 return. 601The application will then retry the operation at a later stage. 602.Pp 603The 604.Fn msgbuf_write 605routine calls 606.Xr sendmsg 2 607to transmit buffers queued in 608.Fa msgbuf 609and supports file descriptor passing. 610It returns 0 if it succeeds, -1 on error and the global variable 611.Va errno 612is set to indicate the error. 613The errors 614.Er EINTR , 615.Er EAGAIN , 616and 617.Er ENOBUFS 618are treated as follows: 619.Er EINTR 620will automatically retry the write operation while the other errors are 621ignored with a 0 return. 622The application will then retry the operation at a later stage. 623.Sh SEE ALSO 624.Xr socketpair 2 , 625.Xr imsg_add 3 , 626.Xr unix 4 627