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