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