Add sbuf_copyin(). Also add 'b' variants of sbuf_{cat,copyin,cpy}() which
ignore NUL bytes in the source string.
This commit is contained in:
parent
cd17b04723
commit
86b7e548ab
@ -32,7 +32,11 @@
|
||||
.Nm sbuf_new ,
|
||||
.Nm sbuf_clear ,
|
||||
.Nm sbuf_setpos ,
|
||||
.Nm sbuf_bcat ,
|
||||
.Nm sbuf_bcopyin ,
|
||||
.Nm sbuf_bcpy ,
|
||||
.Nm sbuf_cat ,
|
||||
.Nm sbuf_copyin ,
|
||||
.Nm sbuf_cpy ,
|
||||
.Nm sbuf_printf ,
|
||||
.Nm sbuf_putc ,
|
||||
@ -52,8 +56,16 @@
|
||||
.Ft int
|
||||
.Fn sbuf_setpos "struct sbuf *s" "int pos"
|
||||
.Ft int
|
||||
.Fn sbuf_bcat "struct sbuf *s" "const char *str" "size_t len"
|
||||
.Ft int
|
||||
.Fn sbuf_bcopyin "struct sbuf *s" "const void *uaddr" "size_t len"
|
||||
.Ft int
|
||||
.Fn sbuf_bcpy "struct sbuf *s" "const char *str" "size_t len"
|
||||
.Ft int
|
||||
.Fn sbuf_cat "struct sbuf *s" "const char *str"
|
||||
.Ft int
|
||||
.Fn sbuf_copyin "struct sbuf *s" "const void *uaddr" "size_t len"
|
||||
.Ft int
|
||||
.Fn sbuf_cpy "struct sbuf *s" "const char *str"
|
||||
.Ft int
|
||||
.Fn sbuf_printf "struct sbuf *s" "char *fmt" "..."
|
||||
@ -131,18 +143,57 @@ which is a value between zero and one less than the size of the
|
||||
storage buffer.
|
||||
.Pp
|
||||
The
|
||||
.Fn sbuf_bcat
|
||||
function appends the first
|
||||
.Fa len
|
||||
bytes from the byte string
|
||||
.Fa str
|
||||
to the
|
||||
.Fa sbuf .
|
||||
.Pp
|
||||
The
|
||||
.Fn sbuf_bcopyin
|
||||
function copies
|
||||
.Fa len
|
||||
bytes from the specified userland address into the
|
||||
.Fa sbuf .
|
||||
.Pp
|
||||
The
|
||||
.Fn sbuf_bcpy
|
||||
function replaces the contents of the
|
||||
.Fa sbuf
|
||||
with the first
|
||||
.Fa len
|
||||
bytes from the byte string
|
||||
.Fa str .
|
||||
.Pp
|
||||
The
|
||||
.Fn sbuf_cat
|
||||
function appends the string
|
||||
function appends the NUL-terminated string
|
||||
.Fa str
|
||||
to the
|
||||
.Fa sbuf
|
||||
at the current position.
|
||||
.Pp
|
||||
The
|
||||
.Fn sbuf_copyin
|
||||
function copies a NUL-terminated string from the specified userland
|
||||
address into the
|
||||
.Fa sbuf .
|
||||
If the
|
||||
.Fa len
|
||||
argument is non-zero, no more than
|
||||
.Fa len
|
||||
characters (not counting the terminating NUL) are copied; otherwise
|
||||
the entire string, or as much of it as can fit in the
|
||||
.Fa sbuf ,
|
||||
is copied.
|
||||
.Pp
|
||||
The
|
||||
.Fn sbuf_cpy
|
||||
function replaces the contents of the
|
||||
.Fa sbuf
|
||||
with those of the string
|
||||
with those of the NUL-terminated string
|
||||
.Fa str .
|
||||
This is equivalent to calling
|
||||
.Fn sbuf_cat
|
||||
@ -248,6 +299,8 @@ return
|
||||
.Dv NULL
|
||||
and \-1, respectively, if the buffer overflowed.
|
||||
.Sh SEE ALSO
|
||||
.Xr copyin 9 ,
|
||||
.Xr copyinstr 9 ,
|
||||
.Xr printf 3 ,
|
||||
.Xr strcat 3 ,
|
||||
.Xr strcpy 3
|
||||
|
@ -166,6 +166,72 @@ sbuf_setpos(struct sbuf *s, int pos)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@ -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.
|
||||
*/
|
||||
|
@ -54,6 +54,8 @@ __BEGIN_DECLS
|
||||
struct sbuf *sbuf_new(struct sbuf *s, char *buf, int length, int flags);
|
||||
void sbuf_clear(struct sbuf *s);
|
||||
int sbuf_setpos(struct sbuf *s, int pos);
|
||||
int sbuf_bcat(struct sbuf *s, const char *str, size_t len);
|
||||
int sbuf_bcpy(struct sbuf *s, const char *str, size_t len);
|
||||
int sbuf_cat(struct sbuf *s, const char *str);
|
||||
int sbuf_cpy(struct sbuf *s, const char *str);
|
||||
int sbuf_printf(struct sbuf *s, char *fmt, ...);
|
||||
@ -63,6 +65,11 @@ void sbuf_finish(struct sbuf *s);
|
||||
char *sbuf_data(struct sbuf *s);
|
||||
int sbuf_len(struct sbuf *s);
|
||||
void sbuf_delete(struct sbuf *s);
|
||||
|
||||
#ifdef _KERNEL
|
||||
int sbuf_bcopyin(struct sbuf *s, const void *uaddr, size_t len);
|
||||
int sbuf_copyin(struct sbuf *s, const void *uaddr, size_t len);
|
||||
#endif
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user