.\" $OpenBSD: ibuf_add.3,v 1.1 2023/12/12 15:49:21 claudio Exp $ .\" .\" Copyright (c) 2023 Claudio Jeker .\" Copyright (c) 2010 Nicholas Marriott .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd $Mdocdate: December 12 2023 $ .Dt IBUF_ADD 3 .Os .Sh NAME .Nm ibuf_add , .Nm ibuf_add_ibuf , .Nm ibuf_add_h16 , .Nm ibuf_add_h32 , .Nm ibuf_add_h64 , .Nm ibuf_add_n16 , .Nm ibuf_add_n32 , .Nm ibuf_add_n64 , .Nm ibuf_add_n8 , .Nm ibuf_add_zero , .Nm ibuf_close , .Nm ibuf_data , .Nm ibuf_dynamic , .Nm ibuf_fd_avail , .Nm ibuf_fd_get , .Nm ibuf_fd_set , .Nm ibuf_free , .Nm ibuf_from_buffer , .Nm ibuf_from_ibuf , .Nm ibuf_get , .Nm ibuf_get_ibuf , .Nm ibuf_get_h16 , .Nm ibuf_get_h32 , .Nm ibuf_get_h64 , .Nm ibuf_get_n16 , .Nm ibuf_get_n32 , .Nm ibuf_get_n64 , .Nm ibuf_get_n8 , .Nm ibuf_left , .Nm ibuf_open , .Nm ibuf_reserve , .Nm ibuf_rewind , .Nm ibuf_seek , .Nm ibuf_set , .Nm ibuf_set_h16 , .Nm ibuf_set_h32 , .Nm ibuf_set_h64 , .Nm ibuf_set_n16 , .Nm ibuf_set_n32 , .Nm ibuf_set_n64 , .Nm ibuf_set_n8 , .Nm ibuf_size , .Nm ibuf_skip , .Nm ibuf_truncate , .Nm ibuf_write , .Nm msgbuf_clear , .Nm msgbuf_init , .Nm msgbuf_queuelen , .Nm msgbuf_write .Nd save buffer API for basic IO .Sh SYNOPSIS .In sys/queue.h .In imsg.h .Ft int .Fn ibuf_add "struct ibuf *buf" "const void *data" "size_t len" .Ft int .Fn ibuf_add_ibuf "struct ibuf *buf" "const struct ibuf *from" .Ft int .Fn ibuf_add_h16 "struct ibuf *buf" "uint64_t value" .Ft int .Fn ibuf_add_h32 "struct ibuf *buf" "uint64_t value" .Ft int .Fn ibuf_add_h64 "struct ibuf *buf" "uint64_t value" .Ft int .Fn ibuf_add_n16 "struct ibuf *buf" "uint64_t value" .Ft int .Fn ibuf_add_n32 "struct ibuf *buf" "uint64_t value" .Ft int .Fn ibuf_add_n64 "struct ibuf *buf" "uint64_t value" .Ft int .Fn ibuf_add_n8 "struct ibuf *buf" "uint64_t value" .Ft int .Fn ibuf_add_zero "struct ibuf *buf" "size_t len" .Ft void .Fn ibuf_close "struct msgbuf *msgbuf" "struct ibuf *buf" .Ft "void *" .Fn ibuf_data "struct ibuf *buf" .Ft "struct ibuf *" .Fn ibuf_dynamic "size_t len" "size_t max" .Ft int .Fn ibuf_fd_avail "struct ibuf *buf" .Ft int .Fn ibuf_fd_get "struct ibuf *buf" .Ft void .Fn ibuf_fd_set "struct ibuf *buf" "int fd" .Ft void .Fn ibuf_free "struct ibuf *buf" .Ft void .Fn ibuf_from_buffer "struct ibuf *buf" "void *data" "size_t len" .Ft void .Fn ibuf_from_ibuf "struct ibuf *buf" "const ibuf *from" .Ft int .Fn ibuf_get "struct ibuf *buf" "void *data" "size_t len" .Ft int .Fn ibuf_get_ibuf "struct ibuf *buf" "size_t len" "struct ibuf *new" .Ft int .Fn ibuf_get_h16 "struct ibuf *buf" "uint16_t *value" .Ft int .Fn ibuf_get_h32 "struct ibuf *buf" "uint32_t *value" .Ft int .Fn ibuf_get_h64 "struct ibuf *buf" "uint64_t *value" .Ft int .Fn ibuf_get_n16 "struct ibuf *buf" "uint16_t *value" .Ft int .Fn ibuf_get_n32 "struct ibuf *buf" "uint32_t *value" .Ft int .Fn ibuf_get_n64 "struct ibuf *buf" "uint64_t *value" .Ft int .Fn ibuf_get_n8 "struct ibuf *buf" "uint8_t *value" .Ft size_t .Fn ibuf_left "const struct ibuf *buf" .Ft "struct ibuf *" .Fn ibuf_open "size_t len" .Ft "void *" .Fn ibuf_reserve "struct ibuf *buf" "size_t len" .Ft void .Fn ibuf_rewind "struct ibuf *buf" .Ft "void *" .Fn ibuf_seek "struct ibuf *buf" "size_t pos" "size_t len" .Ft int .Fn ibuf_set "struct ibuf *buf" "size_t pos" "const void *data" \ "size_t len" .Ft int .Fn ibuf_set_h16 "struct ibuf *buf" "size_t pos" "uint64_t value" .Ft int .Fn ibuf_set_h32 "struct ibuf *buf" "size_t pos" "uint64_t value" .Ft int .Fn ibuf_set_h64 "struct ibuf *buf" "size_t pos" "uint64_t value" .Ft int .Fn ibuf_set_n16 "struct ibuf *buf" "size_t pos" "uint64_t value" .Ft int .Fn ibuf_set_n32 "struct ibuf *buf" "size_t pos" "uint64_t value" .Ft int .Fn ibuf_set_n64 "struct ibuf *buf" "size_t pos" "uint64_t value" .Ft int .Fn ibuf_set_n8 "struct ibuf *buf" "size_t pos" "uint64_t value" .Ft size_t .Fn ibuf_size "const struct ibuf *buf" .Ft int .Fn ibuf_skip "struct ibuf *buf" "size_t len" .Ft int .Fn ibuf_truncate "struct ibuf *buf" "size_t len" .Ft int .Fn ibuf_write "struct msgbuf *msgbuf" .Ft void .Fn msgbuf_init "struct msgbuf *msgbuf" .Ft void .Fn msgbuf_clear "struct msgbuf *msgbuf" .Ft uint32_t .Fn msgbuf_queuelen "struct msgbuf *msgbuf" .Ft int .Fn msgbuf_write "struct msgbuf *msgbuf" .Sh DESCRIPTION The ibuf API defines functions to manipulate buffers, used for example to construct imsgs with .Xr imsg_create 3 . A .Vt struct ibuf is a single buffer. It has a maximum size, a read and a write position. Buffers should be either constructed with the various .Fn ibuf_add and .Fn ibuf_set functions or consumed with the various .Fn ibuf_get functions. A .Vt struct msgbuf is used to queue the output buffers for transmission. .Pp .Fn ibuf_add appends a block of data to .Fa buf . 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_add_ibuf appends the buffer .Fa from to .Fa buf . 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_add_h16 , .Fn ibuf_add_h32 , and .Fn ibuf_add_h64 add a 2-byte, 4-byte, and 8-byte .Fa value to .Fa buf in host byte order. This function checks .Fa value to not overflow. 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_add_n8 , .Fn ibuf_add_n16 , .Fn ibuf_add_n32 , and .Fn ibuf_add_n64 add a 1-byte, 2-byte, 4-byte, and 8-byte .Fa value to .Fa buf in network byte order. This function checks .Fa value to not overflow. 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_add_zero appends a block of zeros to .Fa buf . 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_close appends .Fa buf to .Fa msgbuf ready to be sent. .Pp .Fn ibuf_data returns the pointer to the internal buffer. This function should only be used together with .Fn ibuf_size to process a previously generated buffer. .Pp .Fn ibuf_dynamic allocates a resizeable buffer of initial length .Fa len and maximum size .Fa max . Buffers allocated with .Fn ibuf_dynamic are automatically grown if necessary when data is added. .Pp .Fn ibuf_fd_avail , .Fn ibuf_fd_get and .Fn ibuf_fd_set are functions to check, get and set the file descriptor assigned to .Fa buf . After calling .Fn ibuf_fd_set the file descriptor is part of the .Fa buf and will be transmitted or closed by the ibuf API. Any previously set file descriptor will be closed before assigning a new descriptor. .Fn ibuf_fd_get returns the file descriptor and passes the responsibility to track the descriptor back to the program. .Fn ibuf_fd_avail returns true if there is a file descriptor set on .Fa buf . .Pp .Fn ibuf_free frees .Fa buf and any associated storage, and closes any file descriptor set with .Fn ibuf_fd_set . If .Fa buf is a NULL pointer, no action occurs. .Pp .Fn ibuf_from_buffer initializes the passed .Fa buf to point at .Fa data and spanning .Fa len bytes. The returned buffer can be read using the various .Fn ibuf_get functions . .Fn ibuf_from_ibuf duplicates the .Fa from ibuf into .Fa buf without modifying .Fa from . This allows safely peeking into an ibuf without consuming data. .Pp .Fn ibuf_get consumes a block of data from .Fa buf spanning .Fa len bytes. 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_get_ibuf consumes .Fa len bytes from the buffer .Fa buf and returns it in .Fa new covering this region. The data in this buffer is only valid as long as .Fa buf remains valid . There is no need to deallocate .Fa new using .Fn ibuf_free . 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_get_h16 , .Fn ibuf_get_h32 , and .Fn ibuf_get_h64 get a 2-byte, 4-byte, and 8-byte .Fa value from .Fa buf without altering byte order. 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_get_n8 , .Fn ibuf_get_n16 , .Fn ibuf_get_n32 , and .Fn ibuf_get_n64 get a 1-byte, 2-byte, 4-byte, and 8-byte .Fa value from .Fa buf converting the value from network to host byte order. 0 is returned on success and \-1 on failure. .Pp The .Fn ibuf_open function allocates a fixed-length buffer. The buffer may not be resized and may contain a maximum of .Fa len bytes. On success .Fn ibuf_open returns a pointer to the buffer; on failure it returns NULL. .Pp .Fn ibuf_reserve is used to reserve .Fa len bytes in .Fa buf . A pointer to the start of the reserved space is returned, or NULL on error. .Pp .Fn ibuf_rewind resets the read offset to the start of the buffer. .Pp .Fn ibuf_seek returns a pointer to the part of the buffer at offset .Fa pos and of extent .Fa len . NULL is returned if the requested range is outside the part of the buffer in use. .Pp .Fn ibuf_set replaces a part of .Fa buf at offset .Fa pos with the .Fa data of extent .Fa len . 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_set_h16 , .Fn ibuf_set_h32 and .Fn ibuf_set_h64 replace a 2-byte, 4-byte or 8-byte .Fa value at offset .Fa pos in the buffer .Fa buf in host byte order. This function checks .Fa value to not overflow. 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_set_n8 , .Fn ibuf_set_n16 , .Fn ibuf_set_n32 and .Fn ibuf_set_n64 replace a 1-byte, 2-byte, 4-byte or 8-byte .Fa value at offset .Fa pos in the buffer .Fa buf in network byte order. This function checks .Fa value to not overflow. 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_size and .Fn ibuf_left are functions which return the total bytes used and available in .Fa buf , respectively. .Pp .Fn ibuf_skip advances the read position in .Fa buf by .Fa len bytes. 0 is returned on success and \-1 on failure. .Pp .Fn ibuf_truncate truncates the buffer to .Fa len bytes if necessary zero extending the buffer. 0 is returned on success and \-1 on failure. .Pp The .Fn ibuf_write routine transmits as many pending buffers as possible from .Fa msgbuf using .Xr writev 2 . It returns 1 if it succeeds, \-1 on error and 0 when no buffers were pending or an EOF condition on the socket is detected. Temporary resource shortages are returned with errno .Er EAGAIN and require the application to retry again in the future. .Pp The .Fn msgbuf_init function initializes .Fa msgbuf so that buffers may be appended to it. The .Fa fd member should also be set directly before .Fn msgbuf_write is used. .Pp .Fn msgbuf_clear empties a msgbuf, removing and discarding any queued buffers. .Pp .Fn msgbuf_queuelen returns the number of messages queued in .Fa msgbuf . This function returns 0 if no messages are pending for transmission. .Pp The .Fn msgbuf_write routine calls .Xr sendmsg 2 to transmit buffers queued in .Fa msgbuf . It returns 1 if it succeeds, \-1 on error, and 0 when the queue was empty or an EOF condition on the socket is detected. Temporary resource shortages are returned with errno .Er EAGAIN and require the application to retry again in the future. .Sh SEE ALSO .Xr socketpair 2 , .Xr imsg_init 3 , .Xr unix 4