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

Cache object: 0f1244b14746c9e8ede442e786df4b6a


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