diff options
author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2001-06-11 17:05:52 +0000 |
---|---|---|
committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2001-06-11 17:05:52 +0000 |
commit | b0def2b54805e62cfd2d4bf71236fdb91d7618b9 (patch) | |
tree | cc2047d7b2d1136314711a47d5c6025ee1784d50 /sys/kern/subr_sbuf.c | |
parent | 21ceb6efa2572847dfcb49302f2d2e2c1fb005a6 (diff) | |
download | src-b0def2b54805e62cfd2d4bf71236fdb91d7618b9.tar.gz src-b0def2b54805e62cfd2d4bf71236fdb91d7618b9.zip |
Notes
Diffstat (limited to 'sys/kern/subr_sbuf.c')
-rw-r--r-- | sys/kern/subr_sbuf.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/sys/kern/subr_sbuf.c b/sys/kern/subr_sbuf.c index 6de352da4003..0493aefb6e6b 100644 --- a/sys/kern/subr_sbuf.c +++ b/sys/kern/subr_sbuf.c @@ -167,6 +167,72 @@ sbuf_setpos(struct sbuf *s, int pos) } /* + * Append a byte string to an sbuf. + */ +int +sbuf_bcat(struct sbuf *s, const char *str, size_t len) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + + while (len-- && SBUF_HASROOM(s)) + s->s_buf[s->s_len++] = *str++; + if (len) { + SBUF_SETFLAG(s, SBUF_OVERFLOWED); + return (-1); + } + return (0); +} + +#ifdef _KERNEL +/* + * Copy a byte string from userland into an sbuf. + */ +int +sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + + if (len == 0) + return (0); + if (len > (s->s_size - s->s_len - 1)) + len = s->s_size - s->s_len - 1; + switch (copyin(uaddr, s->s_buf + s->s_len, len)) { + case ENAMETOOLONG: + SBUF_SETFLAG(s, SBUF_OVERFLOWED); + /* fall through */ + case 0: + s->s_len += len; + break; + default: + return (-1); /* XXX */ + } + + return (0); +} +#endif + +/* + * Copy a byte string into an sbuf. + */ +int +sbuf_bcpy(struct sbuf *s, const char *str, size_t len) +{ + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + sbuf_clear(s); + return (sbuf_bcat(s, str, len)); +} + +/* * Append a string to an sbuf. */ int @@ -187,6 +253,38 @@ sbuf_cat(struct sbuf *s, const char *str) return (0); } +#ifdef _KERNEL +/* + * Copy a string from userland into an sbuf. + */ +int +sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len) +{ + size_t done; + + assert_sbuf_integrity(s); + assert_sbuf_state(s, 0); + + if (SBUF_HASOVERFLOWED(s)) + return (-1); + + if (len == 0 || len > (s->s_size - s->s_len - 1)) + len = s->s_size - s->s_len - 1; + switch (copyinstr(uaddr, s->s_buf + s->s_len, len + 1, &done)) { + case ENAMETOOLONG: + SBUF_SETFLAG(s, SBUF_OVERFLOWED); + /* fall through */ + case 0: + s->s_len += done - 1; + break; + default: + return (-1); /* XXX */ + } + + return (0); +} +#endif + /* * Copy a string into an sbuf. */ |