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/8.3/sys/kern/subr_sbuf.c 222579 2011-06-01 18:26:59Z mdf $");
   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 struct sbuf_drain {
   54         sbuf_drain_func *s_func;        /* drain function */
   55         void            *s_arg;         /* user-supplied drain argument */
   56         int              s_error;       /* current error code */
   57 };
   58 
   59 #ifdef _KERNEL
   60 static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers");
   61 #define SBMALLOC(size)          malloc(size, M_SBUF, M_WAITOK)
   62 #define SBFREE(buf)             free(buf, M_SBUF)
   63 #else /* _KERNEL */
   64 #define KASSERT(e, m)
   65 #define SBMALLOC(size)          malloc(size)
   66 #define SBFREE(buf)             free(buf)
   67 #endif /* _KERNEL */
   68 
   69 /*
   70  * Predicates
   71  */
   72 #define SBUF_ISDYNAMIC(s)       ((s)->s_flags & SBUF_DYNAMIC)
   73 #define SBUF_ISDYNSTRUCT(s)     ((s)->s_flags & SBUF_DYNSTRUCT)
   74 #define SBUF_ISFINISHED(s)      ((s)->s_flags & SBUF_FINISHED)
   75 #define SBUF_HASOVERFLOWED(s)   ((s)->s_flags & SBUF_OVERFLOWED)
   76 #define SBUF_HASROOM(s)         ((s)->s_len < (s)->s_size - 1)
   77 #define SBUF_FREESPACE(s)       ((s)->s_size - (s)->s_len - 1)
   78 #define SBUF_CANEXTEND(s)       ((s)->s_flags & SBUF_AUTOEXTEND)
   79 
   80 /*
   81  * Set / clear flags
   82  */
   83 #define SBUF_SETFLAG(s, f)      do { (s)->s_flags |= (f); } while (0)
   84 #define SBUF_CLEARFLAG(s, f)    do { (s)->s_flags &= ~(f); } while (0)
   85 
   86 #define SBUF_MINEXTENDSIZE      16              /* Should be power of 2. */
   87 #define SBUF_MAXEXTENDSIZE      PAGE_SIZE
   88 #define SBUF_MAXEXTENDINCR      PAGE_SIZE
   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 (%d >= %d)", s->s_len, 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 /*
  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         bcopy(s->s_buf, newbuf, 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 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 struct sbuf *
  179 sbuf_new(struct sbuf *s, char *buf, int length, int flags)
  180 {
  181 
  182         KASSERT(length >= 0,
  183             ("attempt to create an sbuf of negative length (%d)", length));
  184         KASSERT((flags & ~SBUF_USRFLAGMSK) == 0,
  185             ("%s called with invalid flags", __func__));
  186 
  187         flags &= SBUF_USRFLAGMSK;
  188         if (s == NULL) {
  189                 s = SBMALLOC(sizeof(*s));
  190                 if (s == NULL)
  191                         return (NULL);
  192                 bzero(s, sizeof(*s));
  193                 s->s_flags = flags;
  194                 SBUF_SETFLAG(s, SBUF_DYNSTRUCT);
  195         } else {
  196                 bzero(s, sizeof(*s));
  197                 s->s_flags = flags;
  198         }
  199         s->s_size = length;
  200         if (buf != NULL) {
  201                 s->s_buf = buf;
  202                 return (s);
  203         }
  204         if ((flags & SBUF_AUTOEXTEND) != 0)
  205                 s->s_size = sbuf_extendsize(s->s_size);
  206         s->s_buf = SBMALLOC(s->s_size);
  207         if (s->s_buf == NULL) {
  208                 if (SBUF_ISDYNSTRUCT(s))
  209                         SBFREE(s);
  210                 return (NULL);
  211         }
  212         SBUF_SETFLAG(s, SBUF_DYNAMIC);
  213         return (s);
  214 }
  215 
  216 #ifdef _KERNEL
  217 /*
  218  * Create an sbuf with uio data
  219  */
  220 struct sbuf *
  221 sbuf_uionew(struct sbuf *s, struct uio *uio, int *error)
  222 {
  223 
  224         KASSERT(uio != NULL,
  225             ("%s called with NULL uio pointer", __func__));
  226         KASSERT(error != NULL,
  227             ("%s called with NULL error pointer", __func__));
  228 
  229         s = sbuf_new(s, NULL, uio->uio_resid + 1, 0);
  230         if (s == NULL) {
  231                 *error = ENOMEM;
  232                 return (NULL);
  233         }
  234         *error = uiomove(s->s_buf, uio->uio_resid, uio);
  235         if (*error != 0) {
  236                 sbuf_delete(s);
  237                 return (NULL);
  238         }
  239         s->s_len = s->s_size - 1;
  240         *error = 0;
  241         return (s);
  242 }
  243 #endif
  244 
  245 /*
  246  * Clear an sbuf and reset its position.
  247  */
  248 void
  249 sbuf_clear(struct sbuf *s)
  250 {
  251 
  252         assert_sbuf_integrity(s);
  253         /* don't care if it's finished or not */
  254 
  255         SBUF_CLEARFLAG(s, SBUF_FINISHED);
  256         SBUF_CLEARFLAG(s, SBUF_OVERFLOWED);
  257         if (s->s_drain != NULL)
  258                 s->s_drain->s_error = 0;
  259         s->s_len = 0;
  260 }
  261 
  262 /*
  263  * Set the sbuf's end position to an arbitrary value.
  264  * Effectively truncates the sbuf at the new position.
  265  */
  266 int
  267 sbuf_setpos(struct sbuf *s, int pos)
  268 {
  269 
  270         assert_sbuf_integrity(s);
  271         assert_sbuf_state(s, 0);
  272 
  273         KASSERT(pos >= 0,
  274             ("attempt to seek to a negative position (%d)", pos));
  275         KASSERT(pos < s->s_size,
  276             ("attempt to seek past end of sbuf (%d >= %d)", pos, s->s_size));
  277 
  278         if (pos < 0 || pos > s->s_len)
  279                 return (-1);
  280         s->s_len = pos;
  281         return (0);
  282 }
  283 
  284 /*
  285  * Set up a drain function and argument on an sbuf to flush data to
  286  * when the sbuf buffer overflows.
  287  */
  288 void
  289 sbuf_set_drain(struct sbuf *s, sbuf_drain_func *func, void *ctx)
  290 {
  291 
  292         assert_sbuf_state(s, 0);
  293         assert_sbuf_integrity(s);
  294         KASSERT((s->s_drain != NULL && func == s->s_drain->s_func) ||
  295             s->s_len == 0,
  296             ("Cannot change drain to %p on non-empty sbuf %p", func, s));
  297         if (func == NULL) {
  298                 SBFREE(s->s_drain);
  299                 s->s_drain = NULL;
  300                 return;
  301         }
  302         if (s->s_drain == NULL) {
  303                 s->s_drain = SBMALLOC(sizeof(*s->s_drain));
  304                 if (s->s_drain == NULL)
  305                         return;
  306         }
  307         s->s_drain->s_func = func;
  308         s->s_drain->s_arg = ctx;
  309         s->s_drain->s_error = 0;
  310 }
  311 
  312 /*
  313  * Call the drain and process the return.
  314  */
  315 static int
  316 sbuf_drain(struct sbuf *s)
  317 {
  318         int len;
  319 
  320         KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s));
  321         len = s->s_drain->s_func(s->s_drain->s_arg, s->s_buf, s->s_len);
  322         if (len < 0) {
  323                 s->s_drain->s_error = -len;
  324                 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
  325                 return (s->s_drain->s_error);
  326         }
  327         KASSERT(len > 0 && len <= s->s_len,
  328             ("Bad drain amount %d for sbuf %p", len, s));
  329         s->s_len -= len;
  330         /*
  331          * Fast path for the expected case where all the data was
  332          * drained.
  333          */
  334         if (s->s_len == 0)
  335                 return (0);
  336         /*
  337          * Move the remaining characters to the beginning of the
  338          * string.
  339          */
  340         memmove(s->s_buf, s->s_buf + len, s->s_len);
  341         return (0);
  342 }
  343 
  344 /*
  345  * Append a byte to an sbuf.  This is the core function for appending
  346  * to an sbuf and is the main place that deals with extending the
  347  * buffer and marking overflow.
  348  */
  349 static void
  350 sbuf_put_byte(int c, struct sbuf *s)
  351 {
  352 
  353         assert_sbuf_integrity(s);
  354         assert_sbuf_state(s, 0);
  355 
  356         if (SBUF_HASOVERFLOWED(s))
  357                 return;
  358         if (SBUF_FREESPACE(s) <= 0) {
  359                 /* 
  360                  * If there is a drain, use it, otherwise extend the
  361                  * buffer.
  362                  */
  363                 if (s->s_drain != NULL)
  364                         (void)sbuf_drain(s);
  365                 else if (sbuf_extend(s, 1) < 0)
  366                         SBUF_SETFLAG(s, SBUF_OVERFLOWED);
  367                 if (SBUF_HASOVERFLOWED(s))
  368                         return;
  369         }
  370         s->s_buf[s->s_len++] = c;
  371 }
  372 
  373 /*
  374  * Append a non-NUL character to an sbuf.  This prototype signature is
  375  * suitable for use with kvprintf(9).
  376  */
  377 static void
  378 sbuf_putc_func(int c, void *arg)
  379 {
  380 
  381         if (c != '\0')
  382                 sbuf_put_byte(c, arg);
  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 (SBUF_HASOVERFLOWED(s))
  398                 return (-1);
  399         for (; str < end; str++) {
  400                 sbuf_put_byte(*str, s);
  401                 if (SBUF_HASOVERFLOWED(s))
  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 == NULL,
  418             ("Nonsensical copyin to sbuf %p with a drain", s));
  419 
  420         if (SBUF_HASOVERFLOWED(s))
  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 (SBUF_HASOVERFLOWED(s))
  462                 return (-1);
  463 
  464         while (*str != '\0') {
  465                 sbuf_put_byte(*str++, s);
  466                 if (SBUF_HASOVERFLOWED(s))
  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 == NULL,
  484             ("Nonsensical copyin to sbuf %p with a drain", s));
  485 
  486         if (SBUF_HASOVERFLOWED(s))
  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                 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
  499                 /* fall through */
  500         case 0:
  501                 s->s_len += done - 1;
  502                 break;
  503         default:
  504                 return (-1);    /* XXX */
  505         }
  506 
  507         return (done);
  508 }
  509 #endif
  510 
  511 /*
  512  * Copy a string into an sbuf.
  513  */
  514 int
  515 sbuf_cpy(struct sbuf *s, const char *str)
  516 {
  517 
  518         assert_sbuf_integrity(s);
  519         assert_sbuf_state(s, 0);
  520 
  521         sbuf_clear(s);
  522         return (sbuf_cat(s, str));
  523 }
  524 
  525 /*
  526  * Format the given argument list and append the resulting string to an sbuf.
  527  */
  528 #ifdef _KERNEL
  529 int
  530 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
  531 {
  532 
  533         assert_sbuf_integrity(s);
  534         assert_sbuf_state(s, 0);
  535 
  536         KASSERT(fmt != NULL,
  537             ("%s called with a NULL format string", __func__));
  538 
  539         (void)kvprintf(fmt, sbuf_putc_func, s, 10, ap);
  540         if (SBUF_HASOVERFLOWED(s))
  541                 return (-1);
  542         return (0);
  543 }
  544 #else /* !_KERNEL */
  545 int
  546 sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
  547 {
  548         va_list ap_copy;
  549         int error, len;
  550 
  551         assert_sbuf_integrity(s);
  552         assert_sbuf_state(s, 0);
  553 
  554         KASSERT(fmt != NULL,
  555             ("%s called with a NULL format string", __func__));
  556 
  557         if (SBUF_HASOVERFLOWED(s))
  558                 return (-1);
  559 
  560         /*
  561          * For the moment, there is no way to get vsnprintf(3) to hand
  562          * back a character at a time, to push everything into
  563          * sbuf_putc_func() as was done for the kernel.
  564          *
  565          * In userspace, while drains are useful, there's generally
  566          * not a problem attempting to malloc(3) on out of space.  So
  567          * expand a userland sbuf if there is not enough room for the
  568          * data produced by sbuf_[v]printf(3).
  569          */
  570 
  571         error = 0;
  572         do {
  573                 va_copy(ap_copy, ap);
  574                 len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1,
  575                     fmt, ap_copy);
  576                 va_end(ap_copy);
  577 
  578                 if (SBUF_FREESPACE(s) >= len)
  579                         break;
  580                 /* Cannot print with the current available space. */
  581                 if (s->s_drain != NULL && s->s_len > 0)
  582                         error = sbuf_drain(s);
  583                 else
  584                         error = sbuf_extend(s, len - SBUF_FREESPACE(s));
  585         } while (error == 0);
  586 
  587         /*
  588          * s->s_len is the length of the string, without the terminating nul.
  589          * When updating s->s_len, we must subtract 1 from the length that
  590          * we passed into vsnprintf() because that length includes the
  591          * terminating nul.
  592          *
  593          * vsnprintf() returns the amount that would have been copied,
  594          * given sufficient space, so don't over-increment s_len.
  595          */
  596         if (SBUF_FREESPACE(s) < len)
  597                 len = SBUF_FREESPACE(s);
  598         s->s_len += len;
  599         if (!SBUF_HASROOM(s) && !SBUF_CANEXTEND(s))
  600                 SBUF_SETFLAG(s, SBUF_OVERFLOWED);
  601 
  602         KASSERT(s->s_len < s->s_size,
  603             ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size));
  604 
  605         if (SBUF_HASOVERFLOWED(s))
  606                 return (-1);
  607         return (0);
  608 }
  609 #endif /* _KERNEL */
  610 
  611 /*
  612  * Format the given arguments and append the resulting string to an sbuf.
  613  */
  614 int
  615 sbuf_printf(struct sbuf *s, const char *fmt, ...)
  616 {
  617         va_list ap;
  618         int result;
  619 
  620         va_start(ap, fmt);
  621         result = sbuf_vprintf(s, fmt, ap);
  622         va_end(ap);
  623         return (result);
  624 }
  625 
  626 /*
  627  * Append a character to an sbuf.
  628  */
  629 int
  630 sbuf_putc(struct sbuf *s, int c)
  631 {
  632 
  633         sbuf_putc_func(c, s);
  634         if (SBUF_HASOVERFLOWED(s))
  635                 return (-1);
  636         return (0);
  637 }
  638 
  639 /*
  640  * Trim whitespace characters from end of an sbuf.
  641  */
  642 int
  643 sbuf_trim(struct sbuf *s)
  644 {
  645 
  646         assert_sbuf_integrity(s);
  647         assert_sbuf_state(s, 0);
  648         KASSERT(s->s_drain == NULL,
  649             ("%s makes no sense on sbuf %p with drain", __func__, s));
  650 
  651         if (SBUF_HASOVERFLOWED(s))
  652                 return (-1);
  653 
  654         while (s->s_len > 0 && isspace(s->s_buf[s->s_len-1]))
  655                 --s->s_len;
  656 
  657         return (0);
  658 }
  659 
  660 /*
  661  * Check if an sbuf overflowed
  662  */
  663 int
  664 sbuf_overflowed(struct sbuf *s)
  665 {
  666 
  667         return (SBUF_HASOVERFLOWED(s));
  668 }
  669 
  670 /*
  671  * Finish off an sbuf.
  672  */
  673 int
  674 sbuf_finish(struct sbuf *s)
  675 {
  676         int error = 0;
  677 
  678         assert_sbuf_integrity(s);
  679         assert_sbuf_state(s, 0);
  680 
  681         if (s->s_drain != NULL) {
  682                 error = s->s_drain->s_error;
  683                 while (s->s_len > 0 && error == 0)
  684                         error = sbuf_drain(s);
  685         } else if (SBUF_HASOVERFLOWED(s))
  686                 error = ENOMEM;
  687         s->s_buf[s->s_len] = '\0';
  688         SBUF_CLEARFLAG(s, SBUF_OVERFLOWED);
  689         SBUF_SETFLAG(s, SBUF_FINISHED);
  690 #ifdef _KERNEL
  691         return (error);
  692 #else
  693         /*XXX*/if (error) {
  694                 errno = error;
  695                 return (-1);
  696         } else
  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 == 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 int
  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 == NULL,
  726             ("%s makes no sense on sbuf %p with drain", __func__, s));
  727 
  728         if (SBUF_HASOVERFLOWED(s))
  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         if (s->s_drain != NULL)
  747                 SBFREE(s->s_drain);
  748         isdyn = SBUF_ISDYNSTRUCT(s);
  749         bzero(s, sizeof(*s));
  750         if (isdyn)
  751                 SBFREE(s);
  752 }
  753 
  754 /*
  755  * Check if an sbuf has been finished.
  756  */
  757 int
  758 sbuf_done(struct sbuf *s)
  759 {
  760 
  761         return (SBUF_ISFINISHED(s));
  762 }

Cache object: 340bc4bdb5c60ce1c2a7aa65a86bbf4d


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