Page MenuHomeFreeBSD

D21030.id60026.diff
No OneTemporary

D21030.id60026.diff

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

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)

Event Timeline