Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147744764
D21030.id60026.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D21030.id60026.diff
View Options
Index: sys/kern/subr_sbuf.c
===================================================================
--- sys/kern/subr_sbuf.c
+++ 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_HASTRAILINGNL(s) ((s)->s_flags & SBUF_TRAILINGNL)
#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,7 @@
s->s_flags |= flags;
s->s_size = length;
s->s_buf = buf;
+ SBUF_SETFLAG(s, SBUF_TRAILINGNL);
/*
* Allocate DYNAMIC, i.e., heap data buffer backing the sbuf, if no
@@ -310,6 +312,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 +388,12 @@
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 (s->s_buf[s->s_len - 1] == '\n')
+ SBUF_SETFLAG(s, SBUF_TRAILINGNL);
+ else
+ SBUF_CLEARFLAG(s, SBUF_TRAILINGNL);
+
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,
@@ -716,6 +726,34 @@
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);
+
+ /*
+ * We track NL-termination status of fully drained buffers with the
+ * SBUF_TRAILINGNL flag in sbuf_drain().
+ *
+ * If the buffer isn't empty, we can just refer to it.
+ */
+ if (__predict_false(s->s_len == 0)) {
+ if (__predict_true(!SBUF_HASTRAILINGNL(s)))
+ sbuf_put_byte(s, '\n');
+ } else if (__predict_true(s->s_buf[s->s_len - 1] != '\n'))
+ sbuf_put_byte(s, '\n');
+
+ if (s->s_error != 0)
+ return (-1);
+ return (0);
+}
+
/*
* Trim whitespace characters from end of an sbuf.
*/
Index: sys/sys/sbuf.h
===================================================================
--- sys/sys/sbuf.h
+++ 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_TRAILINGNL 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
Sat, Mar 14, 8:47 AM (21 h, 8 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29661978
Default Alt Text
D21030.id60026.diff (3 KB)
Attached To
Mode
D21030: sbuf(9): Add sbuf_nl_terminate() API
Attached
Detach File
Event Timeline
Log In to Comment