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 /*
31 __FBSDID("$FreeBSD: release/10.0.0/sys/kern/subr_sbuf.c 255805 2013-09-22 23:47:56Z des $");
32 */
33 
34 #include <sys/param.h>
35 
36 #ifdef _KERNEL
37 #include <sys/ctype.h>
38 #include <sys/errno.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/systm.h>
42 #include <sys/uio.h>
43 #include <machine/stdarg.h>
44 #else /* _KERNEL */
45 #include <ctype.h>
46 #include <errno.h>
47 #include <stdarg.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #endif /* _KERNEL */
52 
53 /* HACK */
54 /*
55 #include <sys/sbuf.h>
56 */
57 #include "t_config.h"
58 #include "include/sys/sbuf.h"
59 #define	roundup2(x, y)	(((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
60 /* /HACK */
61 
62 #ifdef _KERNEL
63 static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers");
64 #define	SBMALLOC(size)		malloc(size, M_SBUF, M_WAITOK|M_ZERO)
65 #define	SBFREE(buf)		free(buf, M_SBUF)
66 #else /* _KERNEL */
67 #define	KASSERT(e, m)
68 #define	SBMALLOC(size)		calloc(1, size)
69 #define	SBFREE(buf)		free(buf)
70 #endif /* _KERNEL */
71 
72 /*
73  * Predicates
74  */
75 #define	SBUF_ISDYNAMIC(s)	((s)->s_flags & SBUF_DYNAMIC)
76 #define	SBUF_ISDYNSTRUCT(s)	((s)->s_flags & SBUF_DYNSTRUCT)
77 #define	SBUF_ISFINISHED(s)	((s)->s_flags & SBUF_FINISHED)
78 #define	SBUF_HASROOM(s)		((s)->s_len < (s)->s_size - 1)
79 #define	SBUF_FREESPACE(s)	((s)->s_size - ((s)->s_len + 1))
80 #define	SBUF_CANEXTEND(s)	((s)->s_flags & SBUF_AUTOEXTEND)
81 #define	SBUF_ISSECTION(s)	((s)->s_flags & SBUF_INSECTION)
82 
83 /*
84  * Set / clear flags
85  */
86 #define	SBUF_SETFLAG(s, f)	do { (s)->s_flags |= (f); } while (0)
87 #define	SBUF_CLEARFLAG(s, f)	do { (s)->s_flags &= ~(f); } while (0)
88 
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 	KASSERT(s->s_len < s->s_size,
113 	    ("wrote past end of sbuf (%jd >= %jd)",
114 	    (intmax_t)s->s_len, (intmax_t)s->s_size));
115 }
116 
117 static void
_assert_sbuf_state(const char * fun,struct sbuf * s,int state)118 _assert_sbuf_state(const char *fun, struct sbuf *s, int state)
119 {
120 
121 	KASSERT((s->s_flags & SBUF_FINISHED) == state,
122 	    ("%s called with %sfinished or corrupt sbuf", fun,
123 	    (state ? "un" : "")));
124 }
125 
126 #define	assert_sbuf_integrity(s) _assert_sbuf_integrity(__func__, (s))
127 #define	assert_sbuf_state(s, i)	 _assert_sbuf_state(__func__, (s), (i))
128 
129 #else /* _KERNEL && INVARIANTS */
130 
131 #define	assert_sbuf_integrity(s) do { } while (0)
132 #define	assert_sbuf_state(s, i)	 do { } while (0)
133 
134 #endif /* _KERNEL && INVARIANTS */
135 
136 #ifdef CTASSERT
137 CTASSERT(powerof2(SBUF_MAXEXTENDSIZE));
138 CTASSERT(powerof2(SBUF_MAXEXTENDINCR));
139 #endif
140 
141 static int
sbuf_extendsize(int size)142 sbuf_extendsize(int size)
143 {
144 	int newsize;
145 
146 	if (size < (int)SBUF_MAXEXTENDSIZE) {
147 		newsize = SBUF_MINEXTENDSIZE;
148 		while (newsize < size)
149 			newsize *= 2;
150 	} else {
151 		newsize = roundup2(size, SBUF_MAXEXTENDINCR);
152 	}
153 	KASSERT(newsize >= size, ("%s: %d < %d\n", __func__, newsize, size));
154 	return (newsize);
155 }
156 
157 /*
158  * Extend an sbuf.
159  */
160 static int
sbuf_extend(struct sbuf * s,int addlen)161 sbuf_extend(struct sbuf *s, int addlen)
162 {
163 	char *newbuf;
164 	int newsize;
165 
166 	if (!SBUF_CANEXTEND(s))
167 		return (-1);
168 	newsize = sbuf_extendsize(s->s_size + addlen);
169 	newbuf = SBMALLOC(newsize);
170 	if (newbuf == NULL)
171 		return (-1);
172 	memcpy(newbuf, s->s_buf, s->s_size);
173 	if (SBUF_ISDYNAMIC(s))
174 		SBFREE(s->s_buf);
175 	else
176 		SBUF_SETFLAG(s, SBUF_DYNAMIC);
177 	s->s_buf = newbuf;
178 	s->s_size = newsize;
179 	return (0);
180 }
181 
182 /*
183  * Initialize the internals of an sbuf.
184  * If buf is non-NULL, it points to a static or already-allocated string
185  * big enough to hold at least length characters.
186  */
187 static struct sbuf *
sbuf_newbuf(struct sbuf * s,char * buf,int length,int flags)188 sbuf_newbuf(struct sbuf *s, char *buf, int length, int flags)
189 {
190 
191 	memset(s, 0, sizeof(*s));
192 	s->s_flags = flags;
193 	s->s_size = length;
194 	s->s_buf = buf;
195 
196 	if ((s->s_flags & SBUF_AUTOEXTEND) == 0) {
197 		KASSERT(s->s_size >= 0,
198 		    ("attempt to create a too small sbuf"));
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 *
sbuf_new(struct sbuf * s,char * buf,int length,int flags)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 *
sbuf_uionew(struct sbuf * s,struct uio * uio,int * error)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 /*
275  * Clear an sbuf and reset its position.
276  */
277 void
sbuf_clear(struct sbuf * s)278 sbuf_clear(struct sbuf *s)
279 {
280 
281 	assert_sbuf_integrity(s);
282 	/* don't care if it's finished or not */
283 
284 	SBUF_CLEARFLAG(s, SBUF_FINISHED);
285 	s->s_error = 0;
286 	s->s_len = 0;
287 	s->s_sect_len = 0;
288 }
289 
290 /*
291  * Set the sbuf's end position to an arbitrary value.
292  * Effectively truncates the sbuf at the new position.
293  */
294 int
sbuf_setpos(struct sbuf * s,ssize_t pos)295 sbuf_setpos(struct sbuf *s, ssize_t pos)
296 {
297 
298 	assert_sbuf_integrity(s);
299 	assert_sbuf_state(s, 0);
300 
301 	KASSERT(pos >= 0,
302 	    ("attempt to seek to a negative position (%jd)", (intmax_t)pos));
303 	KASSERT(pos < s->s_size,
304 	    ("attempt to seek past end of sbuf (%jd >= %jd)",
305 	    (intmax_t)pos, (intmax_t)s->s_size));
306 	KASSERT(!SBUF_ISSECTION(s),
307 	    ("attempt to seek when in a section"));
308 
309 	if (pos < 0 || pos > s->s_len)
310 		return (-1);
311 	s->s_len = pos;
312 	return (0);
313 }
314 
315 /*
316  * Set up a drain function and argument on an sbuf to flush data to
317  * when the sbuf buffer overflows.
318  */
319 void
sbuf_set_drain(struct sbuf * s,sbuf_drain_func * func,void * ctx)320 sbuf_set_drain(struct sbuf *s, sbuf_drain_func *func, void *ctx)
321 {
322 
323 	assert_sbuf_state(s, 0);
324 	assert_sbuf_integrity(s);
325 	KASSERT(func == s->s_drain_func || s->s_len == 0,
326 	    ("Cannot change drain to %p on non-empty sbuf %p", func, s));
327 	s->s_drain_func = func;
328 	s->s_drain_arg = ctx;
329 }
330 
331 /*
332  * Call the drain and process the return.
333  */
334 static int
sbuf_drain(struct sbuf * s)335 sbuf_drain(struct sbuf *s)
336 {
337 	int len;
338 
339 	KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s));
340 	KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s));
341 	len = s->s_drain_func(s->s_drain_arg, s->s_buf, s->s_len);
342 	if (len < 0) {
343 		s->s_error = -len;
344 		return (s->s_error);
345 	}
346 	KASSERT(len > 0 && len <= s->s_len,
347 	    ("Bad drain amount %d for sbuf %p", len, s));
348 	s->s_len -= len;
349 	/*
350 	 * Fast path for the expected case where all the data was
351 	 * drained.
352 	 */
353 	if (s->s_len == 0)
354 		return (0);
355 	/*
356 	 * Move the remaining characters to the beginning of the
357 	 * string.
358 	 */
359 	memmove(s->s_buf, s->s_buf + len, s->s_len);
360 	return (0);
361 }
362 
363 /*
364  * Append a byte to an sbuf.  This is the core function for appending
365  * to an sbuf and is the main place that deals with extending the
366  * buffer and marking overflow.
367  */
368 static void
sbuf_put_byte(struct sbuf * s,int c)369 sbuf_put_byte(struct sbuf *s, int c)
370 {
371 
372 	assert_sbuf_integrity(s);
373 	assert_sbuf_state(s, 0);
374 
375 	if (s->s_error != 0)
376 		return;
377 	if (SBUF_FREESPACE(s) <= 0) {
378 		/*
379 		 * If there is a drain, use it, otherwise extend the
380 		 * buffer.
381 		 */
382 		if (s->s_drain_func != NULL)
383 			(void)sbuf_drain(s);
384 		else if (sbuf_extend(s, 1) < 0)
385 			s->s_error = ENOMEM;
386 		if (s->s_error != 0)
387 			return;
388 	}
389 	s->s_buf[s->s_len++] = c;
390 	if (SBUF_ISSECTION(s))
391 		s->s_sect_len++;
392 }
393 
394 /*
395  * Append a byte string to an sbuf.
396  */
397 int
sbuf_bcat(struct sbuf * s,const void * buf,size_t len)398 sbuf_bcat(struct sbuf *s, const void *buf, size_t len)
399 {
400 	const char *str = buf;
401 	const char *end = str + len;
402 
403 	assert_sbuf_integrity(s);
404 	assert_sbuf_state(s, 0);
405 
406 	if (s->s_error != 0)
407 		return (-1);
408 	for (; str < end; str++) {
409 		sbuf_put_byte(s, *str);
410 		if (s->s_error != 0)
411 			return (-1);
412 	}
413 	return (0);
414 }
415 
416 #ifdef _KERNEL
417 /*
418  * Copy a byte string from userland into an sbuf.
419  */
420 int
sbuf_bcopyin(struct sbuf * s,const void * uaddr,size_t len)421 sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len)
422 {
423 
424 	assert_sbuf_integrity(s);
425 	assert_sbuf_state(s, 0);
426 	KASSERT(s->s_drain_func == NULL,
427 	    ("Nonsensical copyin to sbuf %p with a drain", s));
428 
429 	if (s->s_error != 0)
430 		return (-1);
431 	if (len == 0)
432 		return (0);
433 	if (len > SBUF_FREESPACE(s)) {
434 		sbuf_extend(s, len - SBUF_FREESPACE(s));
435 		if (SBUF_FREESPACE(s) < len)
436 			len = SBUF_FREESPACE(s);
437 	}
438 	if (copyin(uaddr, s->s_buf + s->s_len, len) != 0)
439 		return (-1);
440 	s->s_len += len;
441 
442 	return (0);
443 }
444 #endif
445 
446 /*
447  * Copy a byte string into an sbuf.
448  */
449 int
sbuf_bcpy(struct sbuf * s,const void * buf,size_t len)450 sbuf_bcpy(struct sbuf *s, const void *buf, size_t len)
451 {
452 
453 	assert_sbuf_integrity(s);
454 	assert_sbuf_state(s, 0);
455 
456 	sbuf_clear(s);
457 	return (sbuf_bcat(s, buf, len));
458 }
459 
460 /*
461  * Append a string to an sbuf.
462  */
463 int
sbuf_cat(struct sbuf * s,const char * str)464 sbuf_cat(struct sbuf *s, const char *str)
465 {
466 
467 	assert_sbuf_integrity(s);
468 	assert_sbuf_state(s, 0);
469 
470 	if (s->s_error != 0)
471 		return (-1);
472 
473 	while (*str != '\0') {
474 		sbuf_put_byte(s, *str++);
475 		if (s->s_error != 0)
476 			return (-1);
477 	}
478 	return (0);
479 }
480 
481 #ifdef _KERNEL
482 /*
483  * Append a string from userland to an sbuf.
484  */
485 int
sbuf_copyin(struct sbuf * s,const void * uaddr,size_t len)486 sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len)
487 {
488 	size_t done;
489 
490 	assert_sbuf_integrity(s);
491 	assert_sbuf_state(s, 0);
492 	KASSERT(s->s_drain_func == NULL,
493 	    ("Nonsensical copyin to sbuf %p with a drain", s));
494 
495 	if (s->s_error != 0)
496 		return (-1);
497 
498 	if (len == 0)
499 		len = SBUF_FREESPACE(s);	/* XXX return 0? */
500 	if (len > SBUF_FREESPACE(s)) {
501 		sbuf_extend(s, len);
502 		if (SBUF_FREESPACE(s) < len)
503 			len = SBUF_FREESPACE(s);
504 	}
505 	switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) {
506 	case ENAMETOOLONG:
507 		s->s_error = ENOMEM;
508 		/* fall through */
509 	case 0:
510 		s->s_len += done - 1;
511 		if (SBUF_ISSECTION(s))
512 			s->s_sect_len += done - 1;
513 		break;
514 	default:
515 		return (-1);	/* XXX */
516 	}
517 
518 	return (done);
519 }
520 #endif
521 
522 /*
523  * Copy a string into an sbuf.
524  */
525 int
sbuf_cpy(struct sbuf * s,const char * str)526 sbuf_cpy(struct sbuf *s, const char *str)
527 {
528 
529 	assert_sbuf_integrity(s);
530 	assert_sbuf_state(s, 0);
531 
532 	sbuf_clear(s);
533 	return (sbuf_cat(s, str));
534 }
535 
536 /*
537  * Format the given argument list and append the resulting string to an sbuf.
538  */
539 #ifdef _KERNEL
540 
541 /*
542  * Append a non-NUL character to an sbuf.  This prototype signature is
543  * suitable for use with kvprintf(9).
544  */
545 static void
sbuf_putc_func(int c,void * arg)546 sbuf_putc_func(int c, void *arg)
547 {
548 
549 	if (c != '\0')
550 		sbuf_put_byte(arg, c);
551 }
552 
553 int
sbuf_vprintf(struct sbuf * s,const char * fmt,va_list ap)554 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
555 {
556 
557 	assert_sbuf_integrity(s);
558 	assert_sbuf_state(s, 0);
559 
560 	KASSERT(fmt != NULL,
561 	    ("%s called with a NULL format string", __func__));
562 
563 	(void)kvprintf(fmt, sbuf_putc_func, s, 10, ap);
564 	if (s->s_error != 0)
565 		return (-1);
566 	return (0);
567 }
568 #else /* !_KERNEL */
569 int
sbuf_vprintf(struct sbuf * s,const char * fmt,va_list ap)570 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
571 {
572 	va_list ap_copy;
573 	int error, len;
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
sbuf_printf(struct sbuf * s,const char * fmt,...)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
sbuf_putc(struct sbuf * s,int c)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
sbuf_trim(struct sbuf * s)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
sbuf_error(const struct sbuf * s)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
sbuf_finish(struct sbuf * s)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 *
sbuf_data(struct sbuf * s)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
sbuf_len(struct sbuf * s)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
sbuf_delete(struct sbuf * s)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
sbuf_done(const struct sbuf * s)781 sbuf_done(const struct sbuf *s)
782 {
783 
784 	return (SBUF_ISFINISHED(s));
785 }
786 
787 /*
788  * Start a section.
789  */
790 void
sbuf_start_section(struct sbuf * s,ssize_t * old_lenp)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
sbuf_end_section(struct sbuf * s,ssize_t old_len,size_t pad,int c)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