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: releng/10.4/sys/kern/subr_sbuf.c 321112 2017-07-18 08:15:02Z ngie $");
   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 static int
  359 sbuf_drain(struct sbuf *s)
  360 {
  361         int len;
  362 
  363         KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s));
  364         KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s));
  365         len = s->s_drain_func(s->s_drain_arg, s->s_buf, s->s_len);
  366         if (len < 0) {
  367                 s->s_error = -len;
  368                 return (s->s_error);
  369         }
  370         KASSERT(len > 0 && len <= s->s_len,
  371             ("Bad drain amount %d for sbuf %p", len, s));
  372         s->s_len -= len;
  373         /*
  374          * Fast path for the expected case where all the data was
  375          * drained.
  376          */
  377         if (s->s_len == 0)
  378                 return (0);
  379         /*
  380          * Move the remaining characters to the beginning of the
  381          * string.
  382          */
  383         memmove(s->s_buf, s->s_buf + len, s->s_len);
  384         return (0);
  385 }
  386 
  387 /*
  388  * Append bytes to an sbuf.  This is the core function for appending
  389  * to an sbuf and is the main place that deals with extending the
  390  * buffer and marking overflow.
  391  */
  392 static void
  393 sbuf_put_bytes(struct sbuf *s, const char *buf, size_t len)
  394 {
  395         size_t n;
  396 
  397         assert_sbuf_integrity(s);
  398         assert_sbuf_state(s, 0);
  399 
  400         if (s->s_error != 0)
  401                 return;
  402         while (len > 0) {
  403                 if (SBUF_FREESPACE(s) <= 0) {
  404                         /*
  405                          * If there is a drain, use it, otherwise extend the
  406                          * buffer.
  407                          */
  408                         if (s->s_drain_func != NULL)
  409                                 (void)sbuf_drain(s);
  410                         else if (sbuf_extend(s, len > INT_MAX ? INT_MAX : len)
  411                             < 0)
  412                                 s->s_error = ENOMEM;
  413                         if (s->s_error != 0)
  414                                 return;
  415                 }
  416                 n = SBUF_FREESPACE(s);
  417                 if (len < n)
  418                         n = len;
  419                 memcpy(&s->s_buf[s->s_len], buf, n);
  420                 s->s_len += n;
  421                 if (SBUF_ISSECTION(s))
  422                         s->s_sect_len += n;
  423                 len -= n;
  424                 buf += n;
  425         }
  426 }
  427 
  428 static void
  429 sbuf_put_byte(struct sbuf *s, char c)
  430 {
  431 
  432         sbuf_put_bytes(s, &c, 1);
  433 }
  434 
  435 /*
  436  * Append a byte string to an sbuf.
  437  */
  438 int
  439 sbuf_bcat(struct sbuf *s, const void *buf, size_t len)
  440 {
  441 
  442         sbuf_put_bytes(s, buf, len);
  443         if (s->s_error != 0)
  444                 return (-1);
  445         return (0);
  446 }
  447 
  448 #ifdef _KERNEL
  449 /*
  450  * Copy a byte string from userland into an sbuf.
  451  */
  452 int
  453 sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len)
  454 {
  455 
  456         assert_sbuf_integrity(s);
  457         assert_sbuf_state(s, 0);
  458         KASSERT(s->s_drain_func == NULL,
  459             ("Nonsensical copyin to sbuf %p with a drain", s));
  460 
  461         if (s->s_error != 0)
  462                 return (-1);
  463         if (len == 0)
  464                 return (0);
  465         if (len > SBUF_FREESPACE(s)) {
  466                 sbuf_extend(s, len - SBUF_FREESPACE(s));
  467                 if (SBUF_FREESPACE(s) < len)
  468                         len = SBUF_FREESPACE(s);
  469         }
  470         if (copyin(uaddr, s->s_buf + s->s_len, len) != 0)
  471                 return (-1);
  472         s->s_len += len;
  473 
  474         return (0);
  475 }
  476 #endif
  477 
  478 /*
  479  * Copy a byte string into an sbuf.
  480  */
  481 int
  482 sbuf_bcpy(struct sbuf *s, const void *buf, size_t len)
  483 {
  484 
  485         assert_sbuf_integrity(s);
  486         assert_sbuf_state(s, 0);
  487 
  488         sbuf_clear(s);
  489         return (sbuf_bcat(s, buf, len));
  490 }
  491 
  492 /*
  493  * Append a string to an sbuf.
  494  */
  495 int
  496 sbuf_cat(struct sbuf *s, const char *str)
  497 {
  498         size_t n;
  499 
  500         n = strlen(str);
  501         sbuf_put_bytes(s, str, n);
  502         if (s->s_error != 0)
  503                 return (-1);
  504         return (0);
  505 }
  506 
  507 #ifdef _KERNEL
  508 /*
  509  * Append a string from userland to an sbuf.
  510  */
  511 int
  512 sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len)
  513 {
  514         size_t done;
  515 
  516         assert_sbuf_integrity(s);
  517         assert_sbuf_state(s, 0);
  518         KASSERT(s->s_drain_func == NULL,
  519             ("Nonsensical copyin to sbuf %p with a drain", s));
  520 
  521         if (s->s_error != 0)
  522                 return (-1);
  523 
  524         if (len == 0)
  525                 len = SBUF_FREESPACE(s);        /* XXX return 0? */
  526         if (len > SBUF_FREESPACE(s)) {
  527                 sbuf_extend(s, len);
  528                 if (SBUF_FREESPACE(s) < len)
  529                         len = SBUF_FREESPACE(s);
  530         }
  531         switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) {
  532         case ENAMETOOLONG:
  533                 s->s_error = ENOMEM;
  534                 /* fall through */
  535         case 0:
  536                 s->s_len += done - 1;
  537                 if (SBUF_ISSECTION(s))
  538                         s->s_sect_len += done - 1;
  539                 break;
  540         default:
  541                 return (-1);    /* XXX */
  542         }
  543 
  544         return (done);
  545 }
  546 #endif
  547 
  548 /*
  549  * Copy a string into an sbuf.
  550  */
  551 int
  552 sbuf_cpy(struct sbuf *s, const char *str)
  553 {
  554 
  555         assert_sbuf_integrity(s);
  556         assert_sbuf_state(s, 0);
  557 
  558         sbuf_clear(s);
  559         return (sbuf_cat(s, str));
  560 }
  561 
  562 /*
  563  * Format the given argument list and append the resulting string to an sbuf.
  564  */
  565 #ifdef _KERNEL
  566 
  567 /*
  568  * Append a non-NUL character to an sbuf.  This prototype signature is
  569  * suitable for use with kvprintf(9).
  570  */
  571 static void
  572 sbuf_putc_func(int c, void *arg)
  573 {
  574 
  575         if (c != '\0')
  576                 sbuf_put_byte(arg, c);
  577 }
  578 
  579 int
  580 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
  581 {
  582 
  583         assert_sbuf_integrity(s);
  584         assert_sbuf_state(s, 0);
  585 
  586         KASSERT(fmt != NULL,
  587             ("%s called with a NULL format string", __func__));
  588 
  589         (void)kvprintf(fmt, sbuf_putc_func, s, 10, ap);
  590         if (s->s_error != 0)
  591                 return (-1);
  592         return (0);
  593 }
  594 #else /* !_KERNEL */
  595 int
  596 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
  597 {
  598         va_list ap_copy;
  599         int error, len;
  600 
  601         assert_sbuf_integrity(s);
  602         assert_sbuf_state(s, 0);
  603 
  604         KASSERT(fmt != NULL,
  605             ("%s called with a NULL format string", __func__));
  606 
  607         if (s->s_error != 0)
  608                 return (-1);
  609 
  610         /*
  611          * For the moment, there is no way to get vsnprintf(3) to hand
  612          * back a character at a time, to push everything into
  613          * sbuf_putc_func() as was done for the kernel.
  614          *
  615          * In userspace, while drains are useful, there's generally
  616          * not a problem attempting to malloc(3) on out of space.  So
  617          * expand a userland sbuf if there is not enough room for the
  618          * data produced by sbuf_[v]printf(3).
  619          */
  620 
  621         error = 0;
  622         do {
  623                 va_copy(ap_copy, ap);
  624                 len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1,
  625                     fmt, ap_copy);
  626                 if (len < 0) {
  627                         s->s_error = errno;
  628                         return (-1);
  629                 }
  630                 va_end(ap_copy);
  631 
  632                 if (SBUF_FREESPACE(s) >= len)
  633                         break;
  634                 /* Cannot print with the current available space. */
  635                 if (s->s_drain_func != NULL && s->s_len > 0)
  636                         error = sbuf_drain(s);
  637                 else
  638                         error = sbuf_extend(s, len - SBUF_FREESPACE(s));
  639         } while (error == 0);
  640 
  641         /*
  642          * s->s_len is the length of the string, without the terminating nul.
  643          * When updating s->s_len, we must subtract 1 from the length that
  644          * we passed into vsnprintf() because that length includes the
  645          * terminating nul.
  646          *
  647          * vsnprintf() returns the amount that would have been copied,
  648          * given sufficient space, so don't over-increment s_len.
  649          */
  650         if (SBUF_FREESPACE(s) < len)
  651                 len = SBUF_FREESPACE(s);
  652         s->s_len += len;
  653         if (SBUF_ISSECTION(s))
  654                 s->s_sect_len += len;
  655         if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s))
  656                 s->s_error = ENOMEM;
  657 
  658         KASSERT(s->s_len < s->s_size,
  659             ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size));
  660 
  661         if (s->s_error != 0)
  662                 return (-1);
  663         return (0);
  664 }
  665 #endif /* _KERNEL */
  666 
  667 /*
  668  * Format the given arguments and append the resulting string to an sbuf.
  669  */
  670 int
  671 sbuf_printf(struct sbuf *s, const char *fmt, ...)
  672 {
  673         va_list ap;
  674         int result;
  675 
  676         va_start(ap, fmt);
  677         result = sbuf_vprintf(s, fmt, ap);
  678         va_end(ap);
  679         return (result);
  680 }
  681 
  682 /*
  683  * Append a character to an sbuf.
  684  */
  685 int
  686 sbuf_putc(struct sbuf *s, int c)
  687 {
  688 
  689         sbuf_put_byte(s, c);
  690         if (s->s_error != 0)
  691                 return (-1);
  692         return (0);
  693 }
  694 
  695 /*
  696  * Trim whitespace characters from end of an sbuf.
  697  */
  698 int
  699 sbuf_trim(struct sbuf *s)
  700 {
  701 
  702         assert_sbuf_integrity(s);
  703         assert_sbuf_state(s, 0);
  704         KASSERT(s->s_drain_func == NULL,
  705             ("%s makes no sense on sbuf %p with drain", __func__, s));
  706 
  707         if (s->s_error != 0)
  708                 return (-1);
  709 
  710         while (s->s_len > 0 && isspace(s->s_buf[s->s_len-1])) {
  711                 --s->s_len;
  712                 if (SBUF_ISSECTION(s))
  713                         s->s_sect_len--;
  714         }
  715 
  716         return (0);
  717 }
  718 
  719 /*
  720  * Check if an sbuf has an error.
  721  */
  722 int
  723 sbuf_error(const struct sbuf *s)
  724 {
  725 
  726         return (s->s_error);
  727 }
  728 
  729 /*
  730  * Finish off an sbuf.
  731  */
  732 int
  733 sbuf_finish(struct sbuf *s)
  734 {
  735 
  736         assert_sbuf_integrity(s);
  737         assert_sbuf_state(s, 0);
  738 
  739         s->s_buf[s->s_len] = '\0';
  740         if (SBUF_NULINCLUDED(s))
  741                 s->s_len++;
  742         if (s->s_drain_func != NULL) {
  743                 while (s->s_len > 0 && s->s_error == 0)
  744                         s->s_error = sbuf_drain(s);
  745         }
  746         SBUF_SETFLAG(s, SBUF_FINISHED);
  747 #ifdef _KERNEL
  748         return (s->s_error);
  749 #else
  750         if (s->s_error != 0) {
  751                 errno = s->s_error;
  752                 return (-1);
  753         }
  754         return (0);
  755 #endif
  756 }
  757 
  758 /*
  759  * Return a pointer to the sbuf data.
  760  */
  761 char *
  762 sbuf_data(struct sbuf *s)
  763 {
  764 
  765         assert_sbuf_integrity(s);
  766         assert_sbuf_state(s, SBUF_FINISHED);
  767         KASSERT(s->s_drain_func == NULL,
  768             ("%s makes no sense on sbuf %p with drain", __func__, s));
  769 
  770         return (s->s_buf);
  771 }
  772 
  773 /*
  774  * Return the length of the sbuf data.
  775  */
  776 ssize_t
  777 sbuf_len(struct sbuf *s)
  778 {
  779 
  780         assert_sbuf_integrity(s);
  781         /* don't care if it's finished or not */
  782         KASSERT(s->s_drain_func == NULL,
  783             ("%s makes no sense on sbuf %p with drain", __func__, s));
  784 
  785         if (s->s_error != 0)
  786                 return (-1);
  787 
  788         /* If finished, nulterm is already in len, else add one. */
  789         if (SBUF_NULINCLUDED(s) && !SBUF_ISFINISHED(s))
  790                 return (s->s_len + 1);
  791         return (s->s_len);
  792 }
  793 
  794 /*
  795  * Clear an sbuf, free its buffer if necessary.
  796  */
  797 void
  798 sbuf_delete(struct sbuf *s)
  799 {
  800         int isdyn;
  801 
  802         assert_sbuf_integrity(s);
  803         /* don't care if it's finished or not */
  804 
  805         if (SBUF_ISDYNAMIC(s))
  806                 SBFREE(s->s_buf);
  807         isdyn = SBUF_ISDYNSTRUCT(s);
  808         memset(s, 0, sizeof(*s));
  809         if (isdyn)
  810                 SBFREE(s);
  811 }
  812 
  813 /*
  814  * Check if an sbuf has been finished.
  815  */
  816 int
  817 sbuf_done(const struct sbuf *s)
  818 {
  819 
  820         return (SBUF_ISFINISHED(s));
  821 }
  822 
  823 /*
  824  * Start a section.
  825  */
  826 void
  827 sbuf_start_section(struct sbuf *s, ssize_t *old_lenp)
  828 {
  829 
  830         assert_sbuf_integrity(s);
  831         assert_sbuf_state(s, 0);
  832 
  833         if (!SBUF_ISSECTION(s)) {
  834                 KASSERT(s->s_sect_len == 0,
  835                     ("s_sect_len != 0 when starting a section"));
  836                 if (old_lenp != NULL)
  837                         *old_lenp = -1;
  838                 SBUF_SETFLAG(s, SBUF_INSECTION);
  839         } else {
  840                 KASSERT(old_lenp != NULL,
  841                     ("s_sect_len should be saved when starting a subsection"));
  842                 *old_lenp = s->s_sect_len;
  843                 s->s_sect_len = 0;
  844         }
  845 }
  846 
  847 /*
  848  * End the section padding to the specified length with the specified
  849  * character.
  850  */
  851 ssize_t
  852 sbuf_end_section(struct sbuf *s, ssize_t old_len, size_t pad, int c)
  853 {
  854         ssize_t len;
  855 
  856         assert_sbuf_integrity(s);
  857         assert_sbuf_state(s, 0);
  858         KASSERT(SBUF_ISSECTION(s),
  859             ("attempt to end a section when not in a section"));
  860 
  861         if (pad > 1) {
  862                 len = roundup(s->s_sect_len, pad) - s->s_sect_len;
  863                 for (; s->s_error == 0 && len > 0; len--)
  864                         sbuf_put_byte(s, c);
  865         }
  866         len = s->s_sect_len;
  867         if (old_len == -1) {
  868                 s->s_sect_len = 0;
  869                 SBUF_CLEARFLAG(s, SBUF_INSECTION);
  870         } else {
  871                 s->s_sect_len += old_len;
  872         }
  873         if (s->s_error != 0)
  874                 return (-1);
  875         return (len);
  876 }

Cache object: e44713254d55146dff7f8d82947aa089


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