xref: /openbsd-src/lib/libutil/ibuf_add.3 (revision ff59764deb7c720c75d582b75dac4b924ec7c8a6)
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