IBUF_ADD(3) | Library Functions Manual | IBUF_ADD(3)

# NAME

`ibuf_add`, `ibuf_add_h16`, `ibuf_add_h32`, `ibuf_add_h64`, `ibuf_add_ibuf`, `ibuf_add_n16`, `ibuf_add_n32`, `ibuf_add_n64`, `ibuf_add_n8`, `ibuf_add_strbuf`, `ibuf_add_zero`, `ibuf_close`, `ibuf_data`, `ibuf_dynamic`, `ibuf_fd_avail`, `ibuf_fd_get`, `ibuf_fd_set`, `ibuf_free`, `ibuf_from_buffer`, `ibuf_from_ibuf`, `ibuf_get`, `ibuf_get_ibuf`, `ibuf_get_h16`, `ibuf_get_h32`, `ibuf_get_h64`, `ibuf_get_n16`, `ibuf_get_n32`, `ibuf_get_n64`, `ibuf_get_n8`, `ibuf_get_strbuf`, `ibuf_get_string`, `ibuf_left`, `ibuf_open`, `ibuf_read`, `ibuf_reserve`, `ibuf_rewind`, `ibuf_seek`, `ibuf_set`, `ibuf_set_h16`, `ibuf_set_h32`, `ibuf_set_h64`, `ibuf_set_n16`, `ibuf_set_n32`, `ibuf_set_n64`, `ibuf_set_n8`, `ibuf_set_maxsize`, `ibuf_size`, `ibuf_skip`, `ibuf_truncate`, `ibuf_write`, `msgbuf_clear`, `msgbuf_concat`, `msgbuf_free`, `msgbuf_get`, `msgbuf_new`, `msgbuf_new_reader`, `msgbuf_queuelen`, `msgbuf_read`, `msgbuf_write`, `ibufq_concat`, `ibufq_flush`, `ibufq_free`, `ibufq_new`, `ibufq_pop`, `ibufq_push`, `ibufq_queuelen` — save buffer API for basic IO

# SYNOPSIS

System Utilities Library (libutil, -lutil)
`#include <imsg.h>`

`#define IBUF_READ_SIZE 65535`

int
`ibuf_add`(struct ibuf *buf, const void *data, size_t len);

int
`ibuf_add_h16`(struct ibuf *buf, uint64_t value);

int
`ibuf_add_h32`(struct ibuf *buf, uint64_t value);

int
`ibuf_add_h64`(struct ibuf *buf, uint64_t value);

int
`ibuf_add_ibuf`(struct ibuf *buf, const struct ibuf *from);

int
`ibuf_add_n16`(struct ibuf *buf, uint64_t value);

int
`ibuf_add_n32`(struct ibuf *buf, uint64_t value);

int
`ibuf_add_n64`(struct ibuf *buf, uint64_t value);

int
`ibuf_add_n8`(struct ibuf *buf, uint64_t value);

int
`ibuf_add_strbuf`(struct ibuf *buf, const char *str, size_t len);

int
`ibuf_add_zero`(struct ibuf *buf, size_t len);

void
`ibuf_close`(struct msgbuf *msgbuf, struct ibuf *buf);

void *
`ibuf_data`(struct ibuf *buf);

struct ibuf *
`ibuf_dynamic`(size_t len, size_t max);

int
`ibuf_fd_avail`(struct ibuf *buf);

int
`ibuf_fd_get`(struct ibuf *buf);

void
`ibuf_fd_set`(struct ibuf *buf, int fd);

void
`ibuf_free`(struct ibuf *buf);

void
`ibuf_from_buffer`(struct ibuf *buf, void *data, size_t len);

void
`ibuf_from_ibuf`(struct ibuf *buf, const ibuf *from);

int
`ibuf_get`(struct ibuf *buf, void *data, size_t len);

int
`ibuf_get_ibuf`(struct ibuf *buf, size_t len, struct ibuf *new);

int
`ibuf_get_h16`(struct ibuf *buf, uint16_t *value);

int
`ibuf_get_h32`(struct ibuf *buf, uint32_t *value);

int
`ibuf_get_h64`(struct ibuf *buf, uint64_t *value);

int
`ibuf_get_n16`(struct ibuf *buf, uint16_t *value);

int
`ibuf_get_n32`(struct ibuf *buf, uint32_t *value);

int
`ibuf_get_n64`(struct ibuf *buf, uint64_t *value);

int
`ibuf_get_n8`(struct ibuf *buf, uint8_t *value);

int
`ibuf_get_strbuf`(struct ibuf *buf, char *str, size_t len);

char *
`ibuf_get_string`(struct ibuf *buf, size_t len);

size_t
`ibuf_left`(const struct ibuf *buf);

struct ibuf *
`ibuf_open`(size_t len);

int
`ibuf_read`(int fd, struct msgbuf *msgbuf);

void *
`ibuf_reserve`(struct ibuf *buf, size_t len);

void
`ibuf_rewind`(struct ibuf *buf);

void *
`ibuf_seek`(struct ibuf *buf, size_t pos, size_t len);

int
`ibuf_set`(struct ibuf *buf, size_t pos, const void *data, size_t len);

int
`ibuf_set_h16`(struct ibuf *buf, size_t pos, uint64_t value);

int
`ibuf_set_h32`(struct ibuf *buf, size_t pos, uint64_t value);

int
`ibuf_set_h64`(struct ibuf *buf, size_t pos, uint64_t value);

int
`ibuf_set_n16`(struct ibuf *buf, size_t pos, uint64_t value);

int
`ibuf_set_n32`(struct ibuf *buf, size_t pos, uint64_t value);

int
`ibuf_set_n64`(struct ibuf *buf, size_t pos, uint64_t value);

int
`ibuf_set_n8`(struct ibuf *buf, size_t pos, uint64_t value);

int
`ibuf_set_maxsize`(struct ibuf *buf, size_t max);

size_t
`ibuf_size`(const struct ibuf *buf);

int
`ibuf_skip`(struct ibuf *buf, size_t len);

int
`ibuf_truncate`(struct ibuf *buf, size_t len);

int
`ibuf_write`(int fd, struct msgbuf *msgbuf);

void
`msgbuf_clear`(struct msgbuf *msgbuf);

void
`msgbuf_concat`(struct msgbuf *msgbuf, struct ibufqueue *from);

void
`msgbuf_free`(struct msgbuf *msgbuf);

struct ibuf *
`msgbuf_get`(struct msgbuf *msgbuf);

struct msgbuf *
`msgbuf_new`(void);

struct msgbuf *
`msgbuf_new_reader`(size_t hdrsz, struct ibuf *(*readhdr)(struct ibuf *, void *, int *), void *arg);

uint32_t
`msgbuf_queuelen`(struct msgbuf *msgbuf);

int
`msgbuf_read`(int fd, struct msgbuf *msgbuf);

int
`msgbuf_write`(int fd, struct msgbuf *msgbuf);

void
`ibufq_concat`(struct ibufqueue *to, struct ibufqueue *from);

void
`ibufq_flush`(struct ibufqueue *bufq);

void
`ibufq_free`(struct ibufqueue *bufq);

struct ibufqueue *
`ibufq_new`(void);

struct ibuf *
`ibufq_pop`(struct ibufqueue *bufq);

void
`ibufq_push`(struct ibufqueue *bufq, struct ibuf *buf);

uint32_t
`ibufq_queuelen`(struct ibufqueue *bufq);

# DESCRIPTION

The ibuf API defines functions to manipulate buffers, used for example to construct imsgs with imsg_create(3). A 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 `ibuf_add`() and `ibuf_set`() functions or consumed with the various `ibuf_get`() functions. A struct msgbuf is used to queue the output buffers for transmission.

`ibuf_add`() appends a block of data to buf. 0 is returned on success and -1 on failure.

`ibuf_add_h16`(), `ibuf_add_h32`(), and `ibuf_add_h64`() add a 2-byte, 4-byte, and 8-byte value to buf in host byte order. This function checks value to not overflow. 0 is returned on success and -1 on failure.

`ibuf_add_ibuf`() appends the buffer from to buf. 0 is returned on success and -1 on failure.

`ibuf_add_n8`(), `ibuf_add_n16`(), `ibuf_add_n32`(), and `ibuf_add_n64`() add a 1-byte, 2-byte, 4-byte, and 8-byte value to buf in network byte order. This function checks value to not overflow. 0 is returned on success and -1 on failure.

`ibuf_add_strbuf`() appends a fixed-size buffer containing a string, zero-padded to len, which must be large enough to allow at least one NUL. 0 is returned on success and -1 on failure.

`ibuf_add_zero`() appends a block of zeros to buf. 0 is returned on success and -1 on failure.

`ibuf_close`() appends buf to msgbuf ready to be sent.

`ibuf_data`() returns the pointer to the internal buffer. This function should only be used together with `ibuf_size`() to process a previously generated buffer.

`ibuf_dynamic`() allocates a resizeable buffer of initial length len and maximum size max. Buffers allocated with `ibuf_dynamic`() are automatically grown if necessary when data is added.

`ibuf_fd_avail`(), `ibuf_fd_get`() and `ibuf_fd_set`() are functions to check, get and set the file descriptor assigned to buf. After calling `ibuf_fd_set`() the file descriptor is part of the buf and will be transmitted or closed by the ibuf API. Any previously set file descriptor will be closed before assigning a new descriptor. `ibuf_fd_get`() returns the file descriptor and passes the responsibility to track the descriptor back to the program. `ibuf_fd_avail`() returns true if there is a file descriptor set on buf.

`ibuf_free`() frees buf and any associated storage, and closes any file descriptor set with `ibuf_fd_set`(). If buf is a NULL pointer, no action occurs.

`ibuf_from_buffer`() initializes the passed buf to point at data and spanning len bytes. The returned buffer can be read using the various `ibuf_get`() functions. `ibuf_from_ibuf`() duplicates the from ibuf into buf without modifying from. This allows safely peeking into an ibuf without consuming data.

`ibuf_get`() consumes a block of data from buf spanning len bytes. 0 is returned on success and -1 on failure.

`ibuf_get_ibuf`() consumes len bytes from the buffer buf and returns it in new covering this region. The data in this buffer is only valid as long as buf remains valid. There is no need to deallocate new using `ibuf_free`(). 0 is returned on success and -1 on failure.

`ibuf_get_h16`(), `ibuf_get_h32`(), and `ibuf_get_h64`() get a 2-byte, 4-byte, and 8-byte value from buf without altering byte order. 0 is returned on success and -1 on failure.

`ibuf_get_n8`(), `ibuf_get_n16`(), `ibuf_get_n32`(), and `ibuf_get_n64`() get a 1-byte, 2-byte, 4-byte, and 8-byte value from buf converting the value from network to host byte order. 0 is returned on success and -1 on failure.

`ibuf_get_strbuf`() copies len bytes from the buffer buf into str, ensuring that it is NUL-terminated. 0 is returned on success and -1 on failure.

`ibuf_get_string`() consumes len bytes from the buffer buf and returns the result of passing the bytes and len to strndup(3). The returned pointer should be passed to free(3) when it is no longer needed. On error NULL is returned.

The `ibuf_open`() function allocates a fixed-length buffer. The buffer may not be resized and may contain a maximum of len bytes. On success `ibuf_open`() returns a pointer to the buffer; on failure it returns NULL.

The `ibuf_read`() routine receives pending messages using read(2). It calls the `readhdr`() callback to obtain a struct ibuf of the appropriate size. It returns 1 on success, 0 if the connection was closed and -1 on error and the global variable errno is set to indicate the error. The errors `EINTR` and `EAGAIN` are treated as follows: `EINTR` will automatically retry the read operation while `EAGAIN` will be ignored with a 1 return. The application will then retry the operation at a later stage.

`ibuf_reserve`() is used to reserve len bytes in buf. A pointer to the start of the reserved space is returned, or NULL on error.

`ibuf_rewind`() resets the read offset to the start of the buffer.

`ibuf_seek`() returns a pointer to the part of the buffer at offset pos and of extent len. NULL is returned if the requested range is outside the part of the buffer in use.

`ibuf_set`() replaces a part of buf at offset pos with the data of extent len. 0 is returned on success and -1 on failure.

`ibuf_set_h16`(), `ibuf_set_h32`() and `ibuf_set_h64`() replace a 2-byte, 4-byte or 8-byte value at offset pos in the buffer buf in host byte order. This function checks value to not overflow. 0 is returned on success and -1 on failure.

`ibuf_set_n8`(), `ibuf_set_n16`(), `ibuf_set_n32`() and `ibuf_set_n64`() replace a 1-byte, 2-byte, 4-byte or 8-byte value at offset pos in the buffer buf in network byte order. This function checks value to not overflow. 0 is returned on success and -1 on failure.

`ibuf_set_maxsize`() reduces the maximum payload of buf to max. 0 is returned on success and -1 on failure.

`ibuf_size`() and `ibuf_left`() are functions which return the total bytes used and available in buf, respectively.

`ibuf_skip`() advances the read position in buf by len bytes. 0 is returned on success and -1 on failure.

`ibuf_truncate`() truncates the buffer to len bytes if necessary zero extending the buffer. 0 is returned on success and -1 on failure.

The `ibuf_write`() routine transmits as many pending buffers as possible from msgbuf using writev(2). It returns 0 if it succeeds, -1 on error and the global variable errno is set to indicate the error. The errors `EINTR`, `EAGAIN`, and `ENOBUFS` are treated as follows: `EINTR` will automatically retry the write operation while the other errors are ignored with a 0 return. The application will then retry the operation at a later stage.

`msgbuf_clear`() empties a msgbuf, removing and discarding any queued buffers.

`msgbuf_concat`() moves all queued buffers from the ibufqueue from to the msgbuf. Afterwards the ibufqueue from is empty.

`msgbuf_free`() function frees the msgbuf allocated by `msgbuf_new`() or `msgbuf_new_reader`(). `msgbuf_get`() returns the next pending message. It should be called in a loop until NULL is returned. The ibuf returned must be freed by calling ibuf_free.

`msgbuf_new`() allocates a new message buffer structure which can be used with `ibuf_write`() or `msbuf_write`(). On error NULL is returned.

`msgbuf_new_reader`() allocates a new message buffer structure which can additionally be used with `ibuf_read`() and `msgbuf_read`(). The hdrsz argument defines the size of the ibuf passed to the readhdr callback. The readhdr callback parses the header and returns a new struct ibuf of the size of the full message. It can take ownership of the file descriptor passed in its int * argument. It should return NULL on error and set the global variable errno appropriately. The arg pointer is passed to the readhdr callback. On error `msgbuf_new_reader`() returns NULL.

`msgbuf_queuelen`() returns the number of messages queued in msgbuf. This function returns 0 if no messages are pending for transmission.

The `msgbuf_read`() routine receives pending messages using recvmsg(2) and supports file descriptor passing. The function calls the `readhdr`() callback function to get the total size of message. It returns 1 on success, 0 if the connection was closed and -1 on error and the global variable errno is set to indicate the error. The errors `EINTR` and `EAGAIN` are treated as follows: `EINTR` will automatically retry the read operation while `EAGAIN` will be ignored with a 1 return. The application will then retry the operation at a later stage.

The `msgbuf_write`() routine calls sendmsg(2) to transmit buffers queued in msgbuf and supports file descriptor passing. It returns 0 if it succeeds, -1 on error and the global variable errno is set to indicate the error. The errors `EINTR`, `EAGAIN`, and `ENOBUFS` are treated as follows: `EINTR` will automatically retry the write operation while the other errors are ignored with a 0 return. The application will then retry the operation at a later stage.

The ibufqueue API can be used to implement additional buffer queues. This can be useful in multithreaded applications to pass ibufs between different threads.

`ibufq_new`() allocates a new ibufqueue. On error NULL is returned.

`ibufq_free`() frees a previously allocated ibufqueue. All queued ibufs are flushed before.

`ibufq_flush`() frees any queued buffer.

`ibufq_push`() and `ibufq_pop`() queue and dequeue ibufs onto the ibufqueue bufq.

`ibufq_queuelen`() returns the number of buffers enqueued on bufq.

`ibufq_concat`() moves all buffers from from to to.

# SEE ALSO

socketpair(2), imsg_add(3), unix(4)

June 13, 2025 | Debian