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

Cache object: 91bac6de1ce49b55d0bcafc654436f4a


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