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

Cache object: cc251dfbecb32d82f423265a1f09956d


[ 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.