1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2000-2008 Poul-Henning Kamp
5 * Copyright (c) 2000-2008 Dag-Erling Smørgrav
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer
13 * in this position and unchanged.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 #include <sys/param.h>
33
34 #ifdef _KERNEL
35 #include <sys/ctype.h>
36 #include <sys/errno.h>
37 #include <sys/kernel.h>
38 #include <sys/limits.h>
39 #include <sys/malloc.h>
40 #include <sys/systm.h>
41 #include <sys/uio.h>
42 #include <machine/stdarg.h>
43 #else /* _KERNEL */
44 #include <ctype.h>
45 #include <errno.h>
46 #include <limits.h>
47 #include <stdarg.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #endif /* _KERNEL */
52
53 #include <sys/sbuf.h>
54
55 #ifdef _KERNEL
56 static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers");
57 #define SBMALLOC(size, flags) malloc(size, M_SBUF, (flags) | M_ZERO)
58 #define SBFREE(buf) free(buf, M_SBUF)
59 #else /* _KERNEL */
60 #define KASSERT(e, m)
61 #define SBMALLOC(size, flags) calloc(1, size)
62 #define SBFREE(buf) free(buf)
63 #endif /* _KERNEL */
64
65 /*
66 * Predicates
67 */
68 #define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC)
69 #define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT)
70 #define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED)
71 #define SBUF_ISDRAINATEOL(s) ((s)->s_flags & SBUF_DRAINATEOL)
72 #define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1)
73 #define SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len + 1))
74 #define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND)
75 #define SBUF_ISSECTION(s) ((s)->s_flags & SBUF_INSECTION)
76 #define SBUF_NULINCLUDED(s) ((s)->s_flags & SBUF_INCLUDENUL)
77 #define SBUF_ISDRAINTOEOR(s) ((s)->s_flags & SBUF_DRAINTOEOR)
78 #define SBUF_DODRAINTOEOR(s) (SBUF_ISSECTION(s) && SBUF_ISDRAINTOEOR(s))
79 #define SBUF_MALLOCFLAG(s) \
80 (((s)->s_flags & SBUF_NOWAIT) ? M_NOWAIT : M_WAITOK)
81
82 /*
83 * Set / clear flags
84 */
85 #define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0)
86 #define SBUF_CLEARFLAG(s, f) do { (s)->s_flags &= ~(f); } while (0)
87
88 #define SBUF_MINSIZE 2 /* Min is 1 byte + nulterm. */
89 #define SBUF_MINEXTENDSIZE 16 /* Should be power of 2. */
90
91 #ifdef PAGE_SIZE
92 #define SBUF_MAXEXTENDSIZE PAGE_SIZE
93 #define SBUF_MAXEXTENDINCR PAGE_SIZE
94 #else
95 #define SBUF_MAXEXTENDSIZE 4096
96 #define SBUF_MAXEXTENDINCR 4096
97 #endif
98
99 /*
100 * Debugging support
101 */
102 #if defined(_KERNEL) && defined(INVARIANTS)
103
104 static void
_assert_sbuf_integrity(const char * fun,struct sbuf * s)105 _assert_sbuf_integrity(const char *fun, struct sbuf *s)
106 {
107
108 KASSERT(s != NULL,
109 ("%s called with a NULL sbuf pointer", fun));
110 KASSERT(s->s_buf != NULL,
111 ("%s called with uninitialized or corrupt sbuf", fun));
112 if (SBUF_ISFINISHED(s) && SBUF_NULINCLUDED(s)) {
113 KASSERT(s->s_len <= s->s_size,
114 ("wrote past end of sbuf (%jd >= %jd)",
115 (intmax_t)s->s_len, (intmax_t)s->s_size));
116 } else {
117 KASSERT(s->s_len < s->s_size,
118 ("wrote past end of sbuf (%jd >= %jd)",
119 (intmax_t)s->s_len, (intmax_t)s->s_size));
120 }
121 }
122
123 static void
_assert_sbuf_state(const char * fun,struct sbuf * s,int state)124 _assert_sbuf_state(const char *fun, struct sbuf *s, int state)
125 {
126
127 KASSERT((s->s_flags & SBUF_FINISHED) == state,
128 ("%s called with %sfinished or corrupt sbuf", fun,
129 (state ? "un" : "")));
130 }
131
132 #define assert_sbuf_integrity(s) _assert_sbuf_integrity(__func__, (s))
133 #define assert_sbuf_state(s, i) _assert_sbuf_state(__func__, (s), (i))
134
135 #else /* _KERNEL && INVARIANTS */
136
137 #define assert_sbuf_integrity(s) do { } while (0)
138 #define assert_sbuf_state(s, i) do { } while (0)
139
140 #endif /* _KERNEL && INVARIANTS */
141
142 #ifdef CTASSERT
143 CTASSERT(powerof2(SBUF_MAXEXTENDSIZE));
144 CTASSERT(powerof2(SBUF_MAXEXTENDINCR));
145 #endif
146
147 static int
sbuf_extendsize(int size)148 sbuf_extendsize(int size)
149 {
150 int newsize;
151
152 if (size < (int)SBUF_MAXEXTENDSIZE) {
153 newsize = SBUF_MINEXTENDSIZE;
154 while (newsize < size)
155 newsize *= 2;
156 } else {
157 newsize = roundup2(size, SBUF_MAXEXTENDINCR);
158 }
159 KASSERT(newsize >= size, ("%s: %d < %d\n", __func__, newsize, size));
160 return (newsize);
161 }
162
163 /*
164 * Extend an sbuf.
165 */
166 static int
sbuf_extend(struct sbuf * s,int addlen)167 sbuf_extend(struct sbuf *s, int addlen)
168 {
169 char *newbuf;
170 int newsize;
171
172 if (!SBUF_CANEXTEND(s))
173 return (-1);
174 newsize = sbuf_extendsize(s->s_size + addlen);
175 newbuf = SBMALLOC(newsize, SBUF_MALLOCFLAG(s));
176 if (newbuf == NULL)
177 return (-1);
178 memcpy(newbuf, s->s_buf, s->s_size);
179 if (SBUF_ISDYNAMIC(s))
180 SBFREE(s->s_buf);
181 else
182 SBUF_SETFLAG(s, SBUF_DYNAMIC);
183 s->s_buf = newbuf;
184 s->s_size = newsize;
185 return (0);
186 }
187
188 /*
189 * Initialize an sbuf.
190 * If buf is non-NULL, it points to a static or already-allocated string
191 * big enough to hold at least length characters.
192 */
193 struct sbuf *
sbuf_new(struct sbuf * s,char * buf,int length,int flags)194 sbuf_new(struct sbuf *s, char *buf, int length, int flags)
195 {
196
197 KASSERT(length >= 0,
198 ("attempt to create an sbuf of negative length (%d)", length));
199 KASSERT((flags & ~SBUF_USRFLAGMSK) == 0,
200 ("%s called with invalid flags", __func__));
201 KASSERT((flags & SBUF_AUTOEXTEND) || length >= SBUF_MINSIZE,
202 ("sbuf buffer %d smaller than minimum %d bytes", length,
203 SBUF_MINSIZE));
204
205 flags &= SBUF_USRFLAGMSK;
206
207 /*
208 * Allocate 'DYNSTRUCT' sbuf from the heap, if NULL 's' was provided.
209 */
210 if (s == NULL) {
211 s = SBMALLOC(sizeof(*s),
212 (flags & SBUF_NOWAIT) ? M_NOWAIT : M_WAITOK);
213 if (s == NULL)
214 goto out;
215 SBUF_SETFLAG(s, SBUF_DYNSTRUCT);
216 } else {
217 /*
218 * DYNSTRUCT SBMALLOC sbufs are allocated with M_ZERO, but
219 * user-provided sbuf objects must be initialized.
220 */
221 memset(s, 0, sizeof(*s));
222 }
223
224 s->s_flags |= flags;
225 s->s_size = length;
226 s->s_buf = buf;
227 /*
228 * Never-written sbufs do not need \n termination.
229 */
230 SBUF_SETFLAG(s, SBUF_DRAINATEOL);
231
232 /*
233 * Allocate DYNAMIC, i.e., heap data buffer backing the sbuf, if no
234 * buffer was provided.
235 */
236 if (s->s_buf == NULL) {
237 if (SBUF_CANEXTEND(s))
238 s->s_size = sbuf_extendsize(s->s_size);
239 s->s_buf = SBMALLOC(s->s_size, SBUF_MALLOCFLAG(s));
240 if (s->s_buf == NULL)
241 goto out;
242 SBUF_SETFLAG(s, SBUF_DYNAMIC);
243 }
244
245 out:
246 if (s != NULL && s->s_buf == NULL) {
247 if (SBUF_ISDYNSTRUCT(s))
248 SBFREE(s);
249 s = NULL;
250 }
251 return (s);
252 }
253
254 #ifdef _KERNEL
255 /*
256 * Create an sbuf with uio data
257 */
258 struct sbuf *
sbuf_uionew(struct sbuf * s,struct uio * uio,int * error)259 sbuf_uionew(struct sbuf *s, struct uio *uio, int *error)
260 {
261
262 KASSERT(uio != NULL,
263 ("%s called with NULL uio pointer", __func__));
264 KASSERT(error != NULL,
265 ("%s called with NULL error pointer", __func__));
266
267 if (uio->uio_resid >= INT_MAX || uio->uio_resid < SBUF_MINSIZE - 1) {
268 *error = EINVAL;
269 return (NULL);
270 }
271 s = sbuf_new(s, NULL, uio->uio_resid + 1, 0);
272 if (s == NULL) {
273 *error = ENOMEM;
274 return (NULL);
275 }
276 *error = uiomove(s->s_buf, uio->uio_resid, uio);
277 if (*error != 0) {
278 sbuf_delete(s);
279 return (NULL);
280 }
281 s->s_len = s->s_size - 1;
282 if (SBUF_ISSECTION(s))
283 s->s_sect_len = s->s_size - 1;
284 *error = 0;
285 return (s);
286 }
287 #endif
288
289 int
sbuf_get_flags(struct sbuf * s)290 sbuf_get_flags(struct sbuf *s)
291 {
292
293 return (s->s_flags & SBUF_USRFLAGMSK);
294 }
295
296 void
sbuf_clear_flags(struct sbuf * s,int flags)297 sbuf_clear_flags(struct sbuf *s, int flags)
298 {
299
300 s->s_flags &= ~(flags & SBUF_USRFLAGMSK);
301 }
302
303 void
sbuf_set_flags(struct sbuf * s,int flags)304 sbuf_set_flags(struct sbuf *s, int flags)
305 {
306
307 s->s_flags |= (flags & SBUF_USRFLAGMSK);
308 }
309
310 /*
311 * Clear an sbuf and reset its position.
312 */
313 void
sbuf_clear(struct sbuf * s)314 sbuf_clear(struct sbuf *s)
315 {
316
317 assert_sbuf_integrity(s);
318 /* don't care if it's finished or not */
319 KASSERT(s->s_drain_func == NULL,
320 ("%s makes no sense on sbuf %p with drain", __func__, s));
321
322 SBUF_CLEARFLAG(s, SBUF_FINISHED);
323 s->s_error = 0;
324 s->s_len = 0;
325 s->s_rec_off = 0;
326 s->s_sect_len = 0;
327 }
328
329 /*
330 * Set the sbuf's end position to an arbitrary value.
331 * Effectively truncates the sbuf at the new position.
332 */
333 int
sbuf_setpos(struct sbuf * s,ssize_t pos)334 sbuf_setpos(struct sbuf *s, ssize_t pos)
335 {
336
337 assert_sbuf_integrity(s);
338 assert_sbuf_state(s, 0);
339
340 KASSERT(pos >= 0,
341 ("attempt to seek to a negative position (%jd)", (intmax_t)pos));
342 KASSERT(pos < s->s_size,
343 ("attempt to seek past end of sbuf (%jd >= %jd)",
344 (intmax_t)pos, (intmax_t)s->s_size));
345 KASSERT(!SBUF_ISSECTION(s),
346 ("attempt to seek when in a section"));
347
348 if (pos < 0 || pos > s->s_len)
349 return (-1);
350 s->s_len = pos;
351 return (0);
352 }
353
354 /*
355 * Drain into a counter. Counts amount of data without producing output.
356 * Useful for cases like sysctl, where user may first request only size.
357 * This allows to avoid pointless allocation/freeing of large buffers.
358 */
359 int
sbuf_count_drain(void * arg,const char * data __unused,int len)360 sbuf_count_drain(void *arg, const char *data __unused, int len)
361 {
362 size_t *sizep;
363
364 sizep = (size_t *)arg;
365 *sizep += len;
366 return (len);
367 }
368
369 /*
370 * Set up a drain function and argument on an sbuf to flush data to
371 * when the sbuf buffer overflows.
372 */
373 void
sbuf_set_drain(struct sbuf * s,sbuf_drain_func * func,void * ctx)374 sbuf_set_drain(struct sbuf *s, sbuf_drain_func *func, void *ctx)
375 {
376
377 assert_sbuf_state(s, 0);
378 assert_sbuf_integrity(s);
379 KASSERT(func == s->s_drain_func || s->s_len == 0,
380 ("Cannot change drain to %p on non-empty sbuf %p", func, s));
381 s->s_drain_func = func;
382 s->s_drain_arg = ctx;
383 }
384
385 /*
386 * Call the drain and process the return.
387 */
388 int
sbuf_drain(struct sbuf * s)389 sbuf_drain(struct sbuf *s)
390 {
391 int len;
392
393 /*
394 * Immediately return when no work to do,
395 * or an error has already been accumulated.
396 */
397 if ((s->s_len == 0) || (s->s_error != 0))
398 return(s->s_error);
399
400 if (SBUF_DODRAINTOEOR(s) && s->s_rec_off == 0)
401 return (s->s_error = EDEADLK);
402 len = s->s_drain_func(s->s_drain_arg, s->s_buf,
403 SBUF_DODRAINTOEOR(s) ? s->s_rec_off : s->s_len);
404 if (len <= 0) {
405 s->s_error = len ? -len : EDEADLK;
406 return (s->s_error);
407 }
408 KASSERT(len > 0 && len <= s->s_len,
409 ("Bad drain amount %d for sbuf %p", len, s));
410 s->s_len -= len;
411 s->s_rec_off -= len;
412 /*
413 * Fast path for the expected case where all the data was
414 * drained.
415 */
416 if (s->s_len == 0) {
417 /*
418 * When the s_buf is entirely drained, we need to remember if
419 * the last character was a '\n' or not for
420 * sbuf_nl_terminate().
421 */
422 if (s->s_buf[len - 1] == '\n')
423 SBUF_SETFLAG(s, SBUF_DRAINATEOL);
424 else
425 SBUF_CLEARFLAG(s, SBUF_DRAINATEOL);
426 return (0);
427 }
428 /*
429 * Move the remaining characters to the beginning of the
430 * string.
431 */
432 memmove(s->s_buf, s->s_buf + len, s->s_len);
433 return (0);
434 }
435
436 /*
437 * Append bytes to an sbuf. This is the core function for appending
438 * to an sbuf and is the main place that deals with extending the
439 * buffer and marking overflow.
440 */
441 static void
sbuf_put_bytes(struct sbuf * s,const char * buf,size_t len)442 sbuf_put_bytes(struct sbuf *s, const char *buf, size_t len)
443 {
444 size_t n;
445
446 assert_sbuf_integrity(s);
447 assert_sbuf_state(s, 0);
448
449 if (s->s_error != 0)
450 return;
451 while (len > 0) {
452 if (SBUF_FREESPACE(s) <= 0) {
453 /*
454 * If there is a drain, use it, otherwise extend the
455 * buffer.
456 */
457 if (s->s_drain_func != NULL)
458 (void)sbuf_drain(s);
459 else if (sbuf_extend(s, len > INT_MAX ? INT_MAX : len)
460 < 0)
461 s->s_error = ENOMEM;
462 if (s->s_error != 0)
463 return;
464 }
465 n = SBUF_FREESPACE(s);
466 if (len < n)
467 n = len;
468 memcpy(&s->s_buf[s->s_len], buf, n);
469 s->s_len += n;
470 if (SBUF_ISSECTION(s))
471 s->s_sect_len += n;
472 len -= n;
473 buf += n;
474 }
475 }
476
477 static void
sbuf_put_byte(struct sbuf * s,char c)478 sbuf_put_byte(struct sbuf *s, char c)
479 {
480
481 assert_sbuf_integrity(s);
482 assert_sbuf_state(s, 0);
483
484 if (__predict_false(s->s_error != 0))
485 return;
486 if (__predict_false(SBUF_FREESPACE(s) <= 0)) {
487 /*
488 * If there is a drain, use it, otherwise extend the
489 * buffer.
490 */
491 if (s->s_drain_func != NULL)
492 (void)sbuf_drain(s);
493 else if (sbuf_extend(s, 1) < 0)
494 s->s_error = ENOMEM;
495 if (s->s_error != 0)
496 return;
497 }
498 s->s_buf[s->s_len++] = c;
499 if (SBUF_ISSECTION(s))
500 s->s_sect_len++;
501 }
502
503 /*
504 * Append a byte string to an sbuf.
505 */
506 int
sbuf_bcat(struct sbuf * s,const void * buf,size_t len)507 sbuf_bcat(struct sbuf *s, const void *buf, size_t len)
508 {
509
510 sbuf_put_bytes(s, buf, len);
511 if (s->s_error != 0)
512 return (-1);
513 return (0);
514 }
515
516 #ifdef _KERNEL
517 /*
518 * Copy a byte string from userland into an sbuf.
519 */
520 int
sbuf_bcopyin(struct sbuf * s,const void * uaddr,size_t len)521 sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len)
522 {
523
524 assert_sbuf_integrity(s);
525 assert_sbuf_state(s, 0);
526 KASSERT(s->s_drain_func == NULL,
527 ("Nonsensical copyin to sbuf %p with a drain", s));
528
529 if (s->s_error != 0)
530 return (-1);
531 if (len == 0)
532 return (0);
533 if (len > SBUF_FREESPACE(s)) {
534 sbuf_extend(s, len - SBUF_FREESPACE(s));
535 if (SBUF_FREESPACE(s) < len)
536 len = SBUF_FREESPACE(s);
537 }
538 if (copyin(uaddr, s->s_buf + s->s_len, len) != 0)
539 return (-1);
540 s->s_len += len;
541
542 return (0);
543 }
544 #endif
545
546 /*
547 * Copy a byte string into an sbuf.
548 */
549 int
sbuf_bcpy(struct sbuf * s,const void * buf,size_t len)550 sbuf_bcpy(struct sbuf *s, const void *buf, size_t len)
551 {
552
553 assert_sbuf_integrity(s);
554 assert_sbuf_state(s, 0);
555
556 sbuf_clear(s);
557 return (sbuf_bcat(s, buf, len));
558 }
559
560 /*
561 * Append a string to an sbuf.
562 */
563 int
sbuf_cat(struct sbuf * s,const char * str)564 sbuf_cat(struct sbuf *s, const char *str)
565 {
566 size_t n;
567
568 n = strlen(str);
569 sbuf_put_bytes(s, str, n);
570 if (s->s_error != 0)
571 return (-1);
572 return (0);
573 }
574
575 #ifdef _KERNEL
576 /*
577 * Append a string from userland to an sbuf.
578 */
579 int
sbuf_copyin(struct sbuf * s,const void * uaddr,size_t len)580 sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len)
581 {
582 size_t done;
583
584 assert_sbuf_integrity(s);
585 assert_sbuf_state(s, 0);
586 KASSERT(s->s_drain_func == NULL,
587 ("Nonsensical copyin to sbuf %p with a drain", s));
588
589 if (s->s_error != 0)
590 return (-1);
591
592 if (len == 0)
593 len = SBUF_FREESPACE(s); /* XXX return 0? */
594 if (len > SBUF_FREESPACE(s)) {
595 sbuf_extend(s, len);
596 if (SBUF_FREESPACE(s) < len)
597 len = SBUF_FREESPACE(s);
598 }
599 switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) {
600 case ENAMETOOLONG:
601 s->s_error = ENOMEM;
602 /* fall through */
603 case 0:
604 s->s_len += done - 1;
605 if (SBUF_ISSECTION(s))
606 s->s_sect_len += done - 1;
607 break;
608 default:
609 return (-1); /* XXX */
610 }
611
612 return (done);
613 }
614 #endif
615
616 /*
617 * Copy a string into an sbuf.
618 */
619 int
sbuf_cpy(struct sbuf * s,const char * str)620 sbuf_cpy(struct sbuf *s, const char *str)
621 {
622
623 assert_sbuf_integrity(s);
624 assert_sbuf_state(s, 0);
625
626 sbuf_clear(s);
627 return (sbuf_cat(s, str));
628 }
629
630 /*
631 * Format the given argument list and append the resulting string to an sbuf.
632 */
633 #ifdef _KERNEL
634
635 /*
636 * Append a non-NUL character to an sbuf. This prototype signature is
637 * suitable for use with kvprintf(9).
638 */
639 static void
sbuf_putc_func(int c,void * arg)640 sbuf_putc_func(int c, void *arg)
641 {
642
643 if (__predict_true(c != '\0'))
644 sbuf_put_byte(arg, c);
645 }
646
647 int
sbuf_vprintf(struct sbuf * s,const char * fmt,va_list ap)648 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
649 {
650
651 assert_sbuf_integrity(s);
652 assert_sbuf_state(s, 0);
653
654 KASSERT(fmt != NULL,
655 ("%s called with a NULL format string", __func__));
656
657 (void)kvprintf(fmt, sbuf_putc_func, s, 10, ap);
658 if (s->s_error != 0)
659 return (-1);
660 return (0);
661 }
662 #else /* !_KERNEL */
663 int
sbuf_vprintf(struct sbuf * s,const char * fmt,va_list ap)664 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
665 {
666 va_list ap_copy;
667 int error, len;
668
669 assert_sbuf_integrity(s);
670 assert_sbuf_state(s, 0);
671
672 KASSERT(fmt != NULL,
673 ("%s called with a NULL format string", __func__));
674
675 if (s->s_error != 0)
676 return (-1);
677
678 /*
679 * For the moment, there is no way to get vsnprintf(3) to hand
680 * back a character at a time, to push everything into
681 * sbuf_putc_func() as was done for the kernel.
682 *
683 * In userspace, while drains are useful, there's generally
684 * not a problem attempting to malloc(3) on out of space. So
685 * expand a userland sbuf if there is not enough room for the
686 * data produced by sbuf_[v]printf(3).
687 */
688
689 error = 0;
690 do {
691 va_copy(ap_copy, ap);
692 len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1,
693 fmt, ap_copy);
694 if (len < 0) {
695 s->s_error = errno;
696 return (-1);
697 }
698 va_end(ap_copy);
699
700 if (SBUF_FREESPACE(s) >= len)
701 break;
702 /* Cannot print with the current available space. */
703 if (s->s_drain_func != NULL && s->s_len > 0)
704 error = sbuf_drain(s); /* sbuf_drain() sets s_error. */
705 else if (sbuf_extend(s, len - SBUF_FREESPACE(s)) != 0)
706 s->s_error = error = ENOMEM;
707 } while (error == 0);
708
709 /*
710 * s->s_len is the length of the string, without the terminating nul.
711 * When updating s->s_len, we must subtract 1 from the length that
712 * we passed into vsnprintf() because that length includes the
713 * terminating nul.
714 *
715 * vsnprintf() returns the amount that would have been copied,
716 * given sufficient space, so don't over-increment s_len.
717 */
718 if (SBUF_FREESPACE(s) < len)
719 len = SBUF_FREESPACE(s);
720 s->s_len += len;
721 if (SBUF_ISSECTION(s))
722 s->s_sect_len += len;
723
724 KASSERT(s->s_len < s->s_size,
725 ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size));
726
727 if (s->s_error != 0)
728 return (-1);
729 return (0);
730 }
731 #endif /* _KERNEL */
732
733 /*
734 * Format the given arguments and append the resulting string to an sbuf.
735 */
736 int
sbuf_printf(struct sbuf * s,const char * fmt,...)737 sbuf_printf(struct sbuf *s, const char *fmt, ...)
738 {
739 va_list ap;
740 int result;
741
742 va_start(ap, fmt);
743 result = sbuf_vprintf(s, fmt, ap);
744 va_end(ap);
745 return (result);
746 }
747
748 /*
749 * Append a character to an sbuf.
750 */
751 int
sbuf_putc(struct sbuf * s,int c)752 sbuf_putc(struct sbuf *s, int c)
753 {
754
755 sbuf_put_byte(s, c);
756 if (s->s_error != 0)
757 return (-1);
758 return (0);
759 }
760
761 /*
762 * Append a trailing newline to a non-empty sbuf, if one is not already
763 * present. Handles sbufs with drain functions correctly.
764 */
765 int
sbuf_nl_terminate(struct sbuf * s)766 sbuf_nl_terminate(struct sbuf *s)
767 {
768
769 assert_sbuf_integrity(s);
770 assert_sbuf_state(s, 0);
771
772 /*
773 * If the s_buf isn't empty, the last byte is simply s_buf[s_len - 1].
774 *
775 * If the s_buf is empty because a drain function drained it, we
776 * remember if the last byte was a \n with the SBUF_DRAINATEOL flag in
777 * sbuf_drain().
778 *
779 * In either case, we only append a \n if the previous character was
780 * something else.
781 */
782 if (s->s_len == 0) {
783 if (!SBUF_ISDRAINATEOL(s))
784 sbuf_put_byte(s, '\n');
785 } else if (s->s_buf[s->s_len - 1] != '\n')
786 sbuf_put_byte(s, '\n');
787
788 if (s->s_error != 0)
789 return (-1);
790 return (0);
791 }
792
793 /*
794 * Trim whitespace characters from end of an sbuf.
795 */
796 int
sbuf_trim(struct sbuf * s)797 sbuf_trim(struct sbuf *s)
798 {
799
800 assert_sbuf_integrity(s);
801 assert_sbuf_state(s, 0);
802 KASSERT(s->s_drain_func == NULL,
803 ("%s makes no sense on sbuf %p with drain", __func__, s));
804
805 if (s->s_error != 0)
806 return (-1);
807
808 while (s->s_len > 0 && isspace(s->s_buf[s->s_len-1])) {
809 --s->s_len;
810 if (SBUF_ISSECTION(s))
811 s->s_sect_len--;
812 }
813
814 return (0);
815 }
816
817 /*
818 * Check if an sbuf has an error.
819 */
820 int
sbuf_error(const struct sbuf * s)821 sbuf_error(const struct sbuf *s)
822 {
823
824 return (s->s_error);
825 }
826
827 /*
828 * Finish off an sbuf.
829 */
830 int
sbuf_finish(struct sbuf * s)831 sbuf_finish(struct sbuf *s)
832 {
833
834 assert_sbuf_integrity(s);
835 assert_sbuf_state(s, 0);
836
837 s->s_buf[s->s_len] = '\0';
838 if (SBUF_NULINCLUDED(s))
839 s->s_len++;
840 if (s->s_drain_func != NULL) {
841 while (s->s_len > 0 && s->s_error == 0)
842 s->s_error = sbuf_drain(s);
843 }
844 SBUF_SETFLAG(s, SBUF_FINISHED);
845 #ifdef _KERNEL
846 return (s->s_error);
847 #else
848 if (s->s_error != 0) {
849 errno = s->s_error;
850 return (-1);
851 }
852 return (0);
853 #endif
854 }
855
856 /*
857 * Return a pointer to the sbuf data.
858 */
859 char *
sbuf_data(struct sbuf * s)860 sbuf_data(struct sbuf *s)
861 {
862
863 assert_sbuf_integrity(s);
864 assert_sbuf_state(s, SBUF_FINISHED);
865 KASSERT(s->s_drain_func == NULL,
866 ("%s makes no sense on sbuf %p with drain", __func__, s));
867
868 return (s->s_buf);
869 }
870
871 /*
872 * Return the length of the sbuf data.
873 */
874 ssize_t
sbuf_len(struct sbuf * s)875 sbuf_len(struct sbuf *s)
876 {
877
878 assert_sbuf_integrity(s);
879 /* don't care if it's finished or not */
880 KASSERT(s->s_drain_func == NULL,
881 ("%s makes no sense on sbuf %p with drain", __func__, s));
882
883 if (s->s_error != 0)
884 return (-1);
885
886 /* If finished, nulterm is already in len, else add one. */
887 if (SBUF_NULINCLUDED(s) && !SBUF_ISFINISHED(s))
888 return (s->s_len + 1);
889 return (s->s_len);
890 }
891
892 /*
893 * Clear an sbuf, free its buffer if necessary.
894 */
895 void
sbuf_delete(struct sbuf * s)896 sbuf_delete(struct sbuf *s)
897 {
898 int isdyn;
899
900 assert_sbuf_integrity(s);
901 /* don't care if it's finished or not */
902
903 if (SBUF_ISDYNAMIC(s))
904 SBFREE(s->s_buf);
905 isdyn = SBUF_ISDYNSTRUCT(s);
906 memset(s, 0, sizeof(*s));
907 if (isdyn)
908 SBFREE(s);
909 }
910
911 /*
912 * Check if an sbuf has been finished.
913 */
914 int
sbuf_done(const struct sbuf * s)915 sbuf_done(const struct sbuf *s)
916 {
917
918 return (SBUF_ISFINISHED(s));
919 }
920
921 /*
922 * Start a section.
923 */
924 void
sbuf_start_section(struct sbuf * s,ssize_t * old_lenp)925 sbuf_start_section(struct sbuf *s, ssize_t *old_lenp)
926 {
927
928 assert_sbuf_integrity(s);
929 assert_sbuf_state(s, 0);
930
931 if (!SBUF_ISSECTION(s)) {
932 KASSERT(s->s_sect_len == 0,
933 ("s_sect_len != 0 when starting a section"));
934 if (old_lenp != NULL)
935 *old_lenp = -1;
936 s->s_rec_off = s->s_len;
937 SBUF_SETFLAG(s, SBUF_INSECTION);
938 } else {
939 KASSERT(old_lenp != NULL,
940 ("s_sect_len should be saved when starting a subsection"));
941 *old_lenp = s->s_sect_len;
942 s->s_sect_len = 0;
943 }
944 }
945
946 /*
947 * End the section padding to the specified length with the specified
948 * character.
949 */
950 ssize_t
sbuf_end_section(struct sbuf * s,ssize_t old_len,size_t pad,int c)951 sbuf_end_section(struct sbuf *s, ssize_t old_len, size_t pad, int c)
952 {
953 ssize_t len;
954
955 assert_sbuf_integrity(s);
956 assert_sbuf_state(s, 0);
957 KASSERT(SBUF_ISSECTION(s),
958 ("attempt to end a section when not in a section"));
959
960 if (pad > 1) {
961 len = roundup(s->s_sect_len, pad) - s->s_sect_len;
962 for (; s->s_error == 0 && len > 0; len--)
963 sbuf_put_byte(s, c);
964 }
965 len = s->s_sect_len;
966 if (old_len == -1) {
967 s->s_rec_off = s->s_sect_len = 0;
968 SBUF_CLEARFLAG(s, SBUF_INSECTION);
969 } else {
970 s->s_sect_len += old_len;
971 }
972 if (s->s_error != 0)
973 return (-1);
974 return (len);
975 }
976