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