The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_sbuf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 6eeca20fe07d7489501d66a1166b4047


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.