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