Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147593484
D21030.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D21030.id.diff
View Options
Index: head/share/man/man9/sbuf.9
===================================================================
--- head/share/man/man9/sbuf.9
+++ head/share/man/man9/sbuf.9
@@ -44,6 +44,7 @@
.Nm sbuf_cat ,
.Nm sbuf_copyin ,
.Nm sbuf_cpy ,
+.Nm sbuf_nl_terminate ,
.Nm sbuf_printf ,
.Nm sbuf_vprintf ,
.Nm sbuf_putc ,
@@ -123,6 +124,8 @@
.Fa "const char *str"
.Fc
.Ft int
+.Fn sbuf_nl_terminate "struct sbuf *"
+.Ft int
.Fo sbuf_printf
.Fa "struct sbuf *s"
.Fa "const char *fmt" "..."
@@ -440,10 +443,14 @@
The drain will be called for every byte added to the sbuf.
The
.Fn sbuf_bcopyin ,
+.Fn sbuf_bcpy ,
+.Fn sbuf_clear ,
.Fn sbuf_copyin ,
+.Fn sbuf_cpy ,
.Fn sbuf_trim ,
+.Fn sbuf_data ,
and
-.Fn sbuf_data
+.Fn sbuf_len
functions cannot be used on an sbuf with a drain.
.Pp
The
@@ -474,6 +481,11 @@
.Fn sbuf_clear
or
.Fn sbuf_setpos .
+.Pp
+The
+.Fn sbuf_nl_terminate
+function appends a trailing newline character, if the current line is non-empty
+and not already terminated by a newline character.
.Pp
The
.Fn sbuf_printf
Index: head/sys/kern/subr_sbuf.c
===================================================================
--- head/sys/kern/subr_sbuf.c
+++ head/sys/kern/subr_sbuf.c
@@ -70,6 +70,7 @@
#define SBUF_ISDYNAMIC(s) ((s)->s_flags & SBUF_DYNAMIC)
#define SBUF_ISDYNSTRUCT(s) ((s)->s_flags & SBUF_DYNSTRUCT)
#define SBUF_ISFINISHED(s) ((s)->s_flags & SBUF_FINISHED)
+#define SBUF_ISDRAINATEOL(s) ((s)->s_flags & SBUF_DRAINATEOL)
#define SBUF_HASROOM(s) ((s)->s_len < (s)->s_size - 1)
#define SBUF_FREESPACE(s) ((s)->s_size - ((s)->s_len + 1))
#define SBUF_CANEXTEND(s) ((s)->s_flags & SBUF_AUTOEXTEND)
@@ -225,6 +226,10 @@
s->s_flags |= flags;
s->s_size = length;
s->s_buf = buf;
+ /*
+ * Never-written sbufs do not need \n termination.
+ */
+ SBUF_SETFLAG(s, SBUF_DRAINATEOL);
/*
* Allocate DYNAMIC, i.e., heap data buffer backing the sbuf, if no
@@ -310,6 +315,8 @@
assert_sbuf_integrity(s);
/* don't care if it's finished or not */
+ KASSERT(s->s_drain_func == NULL,
+ ("%s makes no sense on sbuf %p with drain", __func__, s));
SBUF_CLEARFLAG(s, SBUF_FINISHED);
s->s_error = 0;
@@ -384,6 +391,7 @@
KASSERT(s->s_len > 0, ("Shouldn't drain empty sbuf %p", s));
KASSERT(s->s_error == 0, ("Called %s with error on %p", __func__, s));
+
if (SBUF_DODRAINTOEOR(s) && s->s_rec_off == 0)
return (s->s_error = EDEADLK);
len = s->s_drain_func(s->s_drain_arg, s->s_buf,
@@ -400,8 +408,18 @@
* Fast path for the expected case where all the data was
* drained.
*/
- if (s->s_len == 0)
+ if (s->s_len == 0) {
+ /*
+ * When the s_buf is entirely drained, we need to remember if
+ * the last character was a '\n' or not for
+ * sbuf_nl_terminate().
+ */
+ if (s->s_buf[len - 1] == '\n')
+ SBUF_SETFLAG(s, SBUF_DRAINATEOL);
+ else
+ SBUF_CLEARFLAG(s, SBUF_DRAINATEOL);
return (0);
+ }
/*
* Move the remaining characters to the beginning of the
* string.
@@ -711,6 +729,38 @@
{
sbuf_put_byte(s, c);
+ if (s->s_error != 0)
+ return (-1);
+ return (0);
+}
+
+/*
+ * Append a trailing newline to a non-empty sbuf, if one is not already
+ * present. Handles sbufs with drain functions correctly.
+ */
+int
+sbuf_nl_terminate(struct sbuf *s)
+{
+
+ assert_sbuf_integrity(s);
+ assert_sbuf_state(s, 0);
+
+ /*
+ * If the s_buf isn't empty, the last byte is simply s_buf[s_len - 1].
+ *
+ * If the s_buf is empty because a drain function drained it, we
+ * remember if the last byte was a \n with the SBUF_DRAINATEOL flag in
+ * sbuf_drain().
+ *
+ * In either case, we only append a \n if the previous character was
+ * something else.
+ */
+ if (s->s_len == 0) {
+ if (!SBUF_ISDRAINATEOL(s))
+ sbuf_put_byte(s, '\n');
+ } else if (s->s_buf[s->s_len - 1] != '\n')
+ sbuf_put_byte(s, '\n');
+
if (s->s_error != 0)
return (-1);
return (0);
Index: head/sys/sys/sbuf.h
===================================================================
--- head/sys/sys/sbuf.h
+++ head/sys/sys/sbuf.h
@@ -58,6 +58,7 @@
#define SBUF_FINISHED 0x00020000 /* set by sbuf_finish() */
#define SBUF_DYNSTRUCT 0x00080000 /* sbuf must be freed */
#define SBUF_INSECTION 0x00100000 /* set by sbuf_start_section() */
+#define SBUF_DRAINATEOL 0x00200000 /* drained contents ended in \n */
int s_flags; /* flags */
ssize_t s_sect_len; /* current length of section */
ssize_t s_rec_off; /* current record start offset */
@@ -91,6 +92,7 @@
__printflike(2, 3);
int sbuf_vprintf(struct sbuf *, const char *, __va_list)
__printflike(2, 0);
+int sbuf_nl_terminate(struct sbuf *);
int sbuf_putc(struct sbuf *, int);
void sbuf_set_drain(struct sbuf *, sbuf_drain_func *, void *);
int sbuf_trim(struct sbuf *);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Mar 13, 4:50 AM (1 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29598753
Default Alt Text
D21030.id.diff (4 KB)
Attached To
Mode
D21030: sbuf(9): Add sbuf_nl_terminate() API
Attached
Detach File
Event Timeline
Log In to Comment