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

Cache object: f32e9e76b84bd0a218a7660301616aaf


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