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