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