39#include <sys/kernel.h>
40#include <sys/limits.h>
41#include <sys/malloc.h>
44#include <machine/stdarg.h>
59#define SBMALLOC(size, flags) malloc(size, M_SBUF, (flags) | M_ZERO)
60#define SBFREE(buf) free(buf, M_SBUF)
63#define SBMALLOC(size, flags) calloc(1, size)
64#define SBFREE(buf) free(buf)
70#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC)
71#define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT)
72#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED)
73#define SBUF_ISDRAINATEOL(s) ((s)->s_flags & SBUF_DRAINATEOL)
74#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1)
75#define SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len + 1))
76#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND)
77#define SBUF_ISSECTION(s) ((s)->s_flags & SBUF_INSECTION)
78#define SBUF_NULINCLUDED(s) ((s)->s_flags & SBUF_INCLUDENUL)
79#define SBUF_ISDRAINTOEOR(s) ((s)->s_flags & SBUF_DRAINTOEOR)
80#define SBUF_DODRAINTOEOR(s) (SBUF_ISSECTION(s) && SBUF_ISDRAINTOEOR(s))
81#define SBUF_MALLOCFLAG(s) \
82 (((s)->s_flags & SBUF_NOWAIT) ? M_NOWAIT : M_WAITOK)
87#define SBUF_SETFLAG(s, f) do { (s)->s_flags |= (f); } while (0)
88#define SBUF_CLEARFLAG(s, f) do { (s)->s_flags &= ~(f); } while (0)
91#define SBUF_MINEXTENDSIZE 16
94#define SBUF_MAXEXTENDSIZE PAGE_SIZE
95#define SBUF_MAXEXTENDINCR PAGE_SIZE
97#define SBUF_MAXEXTENDSIZE 4096
98#define SBUF_MAXEXTENDINCR 4096
104#if defined(_KERNEL) && defined(INVARIANTS)
107_assert_sbuf_integrity(
const char *fun,
struct sbuf *s)
111 (
"%s called with a NULL sbuf pointer", fun));
112 KASSERT(s->s_buf != NULL,
113 (
"%s called with uninitialized or corrupt sbuf", fun));
115 KASSERT(s->s_len <= s->s_size,
116 (
"wrote past end of sbuf (%jd >= %jd)",
117 (intmax_t)s->s_len, (intmax_t)s->s_size));
119 KASSERT(s->s_len < s->s_size,
120 (
"wrote past end of sbuf (%jd >= %jd)",
121 (intmax_t)s->s_len, (intmax_t)s->s_size));
126_assert_sbuf_state(
const char *fun,
struct sbuf *s,
int state)
129 KASSERT((s->s_flags & SBUF_FINISHED) == state,
130 (
"%s called with %sfinished or corrupt sbuf", fun,
131 (state ?
"un" :
"")));
134#define assert_sbuf_integrity(s) _assert_sbuf_integrity(__func__, (s))
135#define assert_sbuf_state(s, i) _assert_sbuf_state(__func__, (s), (i))
139#define assert_sbuf_integrity(s) do { } while (0)
140#define assert_sbuf_state(s, i) do { } while (0)
156 while (newsize < size)
161 KASSERT(newsize >= size, (
"%s: %d < %d\n", __func__, newsize, size));
180 memcpy(newbuf, s->s_buf, s->s_size);
200 (
"attempt to create an sbuf of negative length (%d)", length));
201 KASSERT((
flags & ~SBUF_USRFLAGMSK) == 0,
202 (
"%s called with invalid flags", __func__));
204 (
"sbuf buffer %d smaller than minimum %d bytes", length,
207 flags &= SBUF_USRFLAGMSK;
214 (
flags & SBUF_NOWAIT) ? M_NOWAIT : M_WAITOK);
223 memset(s, 0,
sizeof(*s));
238 if (s->s_buf == NULL) {
242 if (s->s_buf == NULL)
248 if (s != NULL && s->s_buf == NULL) {
265 (
"%s called with NULL uio pointer", __func__));
266 KASSERT(error != NULL,
267 (
"%s called with NULL error pointer", __func__));
269 if (uio->uio_resid >= INT_MAX || uio->uio_resid <
SBUF_MINSIZE - 1) {
273 s =
sbuf_new(s, NULL, uio->uio_resid + 1, 0);
278 *error =
uiomove(s->s_buf, uio->uio_resid, uio);
283 s->s_len = s->s_size - 1;
285 s->s_sect_len = s->s_size - 1;
295 return (s->s_flags & SBUF_USRFLAGMSK);
302 s->s_flags &= ~(
flags & SBUF_USRFLAGMSK);
309 s->s_flags |= (
flags & SBUF_USRFLAGMSK);
321 KASSERT(s->s_drain_func == NULL,
322 (
"%s makes no sense on sbuf %p with drain", __func__, s));
343 (
"attempt to seek to a negative position (%jd)", (intmax_t)pos));
344 KASSERT(pos < s->s_size,
345 (
"attempt to seek past end of sbuf (%jd >= %jd)",
346 (intmax_t)pos, (intmax_t)s->s_size));
348 (
"attempt to seek when in a section"));
350 if (pos < 0 || pos > s->s_len)
366 sizep = (
size_t *)arg;
381 KASSERT(func == s->s_drain_func || s->s_len == 0,
382 (
"Cannot change drain to %p on non-empty sbuf %p", func, s));
383 s->s_drain_func = func;
384 s->s_drain_arg = ctx;
399 if ((s->s_len == 0) || (s->s_error != 0))
403 return (s->s_error = EDEADLK);
404 len = s->s_drain_func(s->s_drain_arg, s->s_buf,
407 s->s_error = len ? -len : EDEADLK;
410 KASSERT(len > 0 && len <= s->s_len,
411 (
"Bad drain amount %d for sbuf %p", len, s));
424 if (s->s_buf[len - 1] ==
'\n')
434 memmove(s->s_buf, s->s_buf + len, s->s_len);
459 if (s->s_drain_func != NULL)
461 else if (
sbuf_extend(s, len > INT_MAX ? INT_MAX : len)
470 memcpy(&s->s_buf[s->s_len],
buf, n);
486 if (__predict_false(s->s_error != 0))
493 if (s->s_drain_func != NULL)
500 s->s_buf[s->s_len++] = c;
528 KASSERT(s->s_drain_func == NULL,
529 (
"Nonsensical copyin to sbuf %p with a drain", s));
540 if (copyin(uaddr, s->s_buf + s->s_len, len) != 0)
588 KASSERT(s->s_drain_func == NULL,
589 (
"Nonsensical copyin to sbuf %p with a drain", s));
601 switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) {
606 s->s_len += done - 1;
608 s->s_sect_len += done - 1;
645 if (__predict_true(c !=
'\0'))
657 (
"%s called with a NULL format string", __func__));
666sbuf_vprintf(
struct sbuf *s,
const char *fmt, va_list ap)
675 (
"%s called with a NULL format string", __func__));
693 va_copy(ap_copy, ap);
705 if (s->s_drain_func != NULL && s->s_len > 0)
708 s->s_error = error = ENOMEM;
709 }
while (error == 0);
724 s->s_sect_len += len;
726 KASSERT(s->s_len < s->s_size,
727 (
"wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size));
787 }
else if (s->s_buf[s->s_len - 1] !=
'\n')
804 KASSERT(s->s_drain_func == NULL,
805 (
"%s makes no sense on sbuf %p with drain", __func__, s));
810 while (s->s_len > 0 && isspace(s->s_buf[s->s_len-1])) {
839 s->s_buf[s->s_len] =
'\0';
842 if (s->s_drain_func != NULL) {
843 while (s->s_len > 0 && s->s_error == 0)
850 if (s->s_error != 0) {
867 KASSERT(s->s_drain_func == NULL,
868 (
"%s makes no sense on sbuf %p with drain", __func__, s));
882 KASSERT(s->s_drain_func == NULL,
883 (
"%s makes no sense on sbuf %p with drain", __func__, s));
890 return (s->s_len + 1);
908 memset(s, 0,
sizeof(*s));
934 KASSERT(s->s_sect_len == 0,
935 (
"s_sect_len != 0 when starting a section"));
936 if (old_lenp != NULL)
938 s->s_rec_off = s->s_len;
941 KASSERT(old_lenp != NULL,
942 (
"s_sect_len should be saved when starting a subsection"));
943 *old_lenp = s->s_sect_len;
960 (
"attempt to end a section when not in a section"));
963 len = roundup(s->s_sect_len, pad) - s->s_sect_len;
964 for (; s->s_error == 0 && len > 0; len--)
969 s->s_rec_off = s->s_sect_len = 0;
972 s->s_sect_len += old_len;
CTASSERT(MAXSHELLCMDLEN >=MAXINTERP+3)
int vsnprintf(char *str, size_t size, const char *format, va_list ap)
int kvprintf(char const *fmt, void(*func)(int, void *), void *arg, int radix, va_list ap)
#define SBUF_ISDRAINATEOL(s)
#define SBUF_FREESPACE(s)
void sbuf_clear_flags(struct sbuf *s, int flags)
static void sbuf_put_byte(struct sbuf *s, char c)
int sbuf_finish(struct sbuf *s)
void sbuf_start_section(struct sbuf *s, ssize_t *old_lenp)
#define SBUF_MINEXTENDSIZE
int sbuf_putc(struct sbuf *s, int c)
#define SBUF_ISDYNAMIC(s)
#define SBUF_DODRAINTOEOR(s)
#define SBUF_ISFINISHED(s)
int sbuf_drain(struct sbuf *s)
#define SBUF_ISDYNSTRUCT(s)
#define SBMALLOC(size, flags)
#define SBUF_CLEARFLAG(s, f)
static MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers")
#define assert_sbuf_integrity(s)
ssize_t sbuf_end_section(struct sbuf *s, ssize_t old_len, size_t pad, int c)
void sbuf_delete(struct sbuf *s)
int sbuf_printf(struct sbuf *s, const char *fmt,...)
void sbuf_set_drain(struct sbuf *s, sbuf_drain_func *func, void *ctx)
#define SBUF_MAXEXTENDSIZE
int sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
int sbuf_bcat(struct sbuf *s, const void *buf, size_t len)
ssize_t sbuf_len(struct sbuf *s)
char * sbuf_data(struct sbuf *s)
int sbuf_error(const struct sbuf *s)
void sbuf_set_flags(struct sbuf *s, int flags)
static int sbuf_extend(struct sbuf *s, int addlen)
int sbuf_count_drain(void *arg, const char *data __unused, int len)
void sbuf_clear(struct sbuf *s)
int sbuf_nl_terminate(struct sbuf *s)
#define SBUF_MAXEXTENDINCR
#define SBUF_CANEXTEND(s)
int sbuf_cpy(struct sbuf *s, const char *str)
int sbuf_setpos(struct sbuf *s, ssize_t pos)
int sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len)
int sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len)
#define SBUF_NULINCLUDED(s)
static int sbuf_extendsize(int size)
#define SBUF_SETFLAG(s, f)
struct sbuf * sbuf_new(struct sbuf *s, char *buf, int length, int flags)
int sbuf_done(const struct sbuf *s)
#define assert_sbuf_state(s, i)
static void sbuf_put_bytes(struct sbuf *s, const char *buf, size_t len)
int sbuf_cat(struct sbuf *s, const char *str)
static void sbuf_putc_func(int c, void *arg)
#define SBUF_MALLOCFLAG(s)
int sbuf_trim(struct sbuf *s)
int sbuf_get_flags(struct sbuf *s)
int sbuf_bcpy(struct sbuf *s, const void *buf, size_t len)
struct sbuf * sbuf_uionew(struct sbuf *s, struct uio *uio, int *error)
#define SBUF_ISSECTION(s)
int uiomove(void *cp, int n, struct uio *uio)