Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146230041
D49945.id154040.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D49945.id154040.diff
View Options
diff --git a/lib/libsbuf/Symbol.map b/lib/libsbuf/Symbol.map
--- a/lib/libsbuf/Symbol.map
+++ b/lib/libsbuf/Symbol.map
@@ -42,3 +42,7 @@
FBSD_1.6 {
sbuf_printf_drain;
};
+
+FBSD_1.8 {
+ sbuf_prepend;
+};
diff --git a/lib/libsbuf/tests/sbuf_string_test.c b/lib/libsbuf/tests/sbuf_string_test.c
--- a/lib/libsbuf/tests/sbuf_string_test.c
+++ b/lib/libsbuf/tests/sbuf_string_test.c
@@ -210,6 +210,54 @@
sbuf_delete(sb);
}
+ATF_TC_WITHOUT_HEAD(sbuf_prepend_test);
+ATF_TC_BODY(sbuf_prepend_test, tc)
+{
+ struct sbuf *sb;
+ size_t test_sbuf_len;
+ const char subsystem_part[] = "subsystem=kernel";
+ const char type_part[] = " type=none";
+ const char data_part[] = " data=foo";
+ const char full_string[] = "subsystem=kernel type=none data=foo";
+
+ sb = sbuf_new_auto();
+ ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
+ strerror(errno));
+
+ ATF_CHECK_MSG(sbuf_cpy(sb, data_part) == 0, "sbuf_cat failed");
+
+ test_sbuf_len = sbuf_len(sb);
+ ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)strlen(data_part),
+ "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
+ sizeof(data_part) - 1);
+
+ ATF_CHECK_MSG(sbuf_prepend(sb, type_part) == 0, "sbuf_prepend failed");
+
+ test_sbuf_len = sbuf_len(sb);
+ ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)(strlen(type_part) +
+ strlen(data_part)),
+ "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
+ sizeof(type_part) + sizeof(data_part) - 2);
+
+ ATF_CHECK_MSG(sbuf_prepend(sb, subsystem_part) == 0, "sbuf_prepend failed");
+
+ test_sbuf_len = sbuf_len(sb);
+ ATF_REQUIRE_MSG(test_sbuf_len == (ssize_t)(strlen(subsystem_part) +
+ strlen(type_part) + strlen(data_part)),
+ "sbuf_len(..) => %zd (actual) != %zu (expected)", test_sbuf_len,
+ sizeof(subsystem_part) + sizeof(type_part) + sizeof(data_part) - 3);
+
+ ATF_REQUIRE_MSG(sbuf_finish(sb) == 0, "sbuf_finish failed: %s",
+ strerror(errno));
+
+ ATF_REQUIRE_STREQ_MSG(sbuf_data(sb), full_string,
+ "sbuf (\"%s\") != test string (\"%s\")", sbuf_data(sb),
+ full_string);
+
+ sbuf_delete(sb);
+}
+
+
ATF_TC_WITHOUT_HEAD(sbuf_putc_test);
ATF_TC_BODY(sbuf_putc_test, tc)
{
@@ -282,6 +330,7 @@
ATF_TP_ADD_TC(tp, sbuf_bcpy_test);
ATF_TP_ADD_TC(tp, sbuf_cat_test);
ATF_TP_ADD_TC(tp, sbuf_cpy_test);
+ ATF_TP_ADD_TC(tp, sbuf_prepend_test);
ATF_TP_ADD_TC(tp, sbuf_putc_test);
ATF_TP_ADD_TC(tp, sbuf_trim_test);
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -1984,6 +1984,7 @@
sbuf.9 sbuf_new_auto.9 \
sbuf.9 sbuf_new_for_sysctl.9 \
sbuf.9 sbuf_nl_terminate.9 \
+ sbuf.9 sbuf_prepend.9 \
sbuf.9 sbuf_printf.9 \
sbuf.9 sbuf_printf_drain.9 \
sbuf.9 sbuf_putbuf.9 \
diff --git a/share/man/man9/sbuf.9 b/share/man/man9/sbuf.9
--- a/share/man/man9/sbuf.9
+++ b/share/man/man9/sbuf.9
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd October 3, 2023
+.Dd April 21, 2025
.Dt SBUF 9
.Os
.Sh NAME
@@ -43,6 +43,7 @@
.Nm sbuf_copyin ,
.Nm sbuf_cpy ,
.Nm sbuf_nl_terminate ,
+.Nm sbuf_prepend ,
.Nm sbuf_printf ,
.Nm sbuf_vprintf ,
.Nm sbuf_putc ,
@@ -131,6 +132,11 @@
.Ft int
.Fn sbuf_nl_terminate "struct sbuf *"
.Ft int
+.Fo sbuf_prepend
+.Fa "struct sbuf *s"
+.Fa "const char *str"
+.Fc
+.Ft int
.Fo sbuf_printf
.Fa "struct sbuf *s"
.Fa "const char *fmt" "..."
@@ -405,6 +411,12 @@
to the
.Fa sbuf
at the current position.
+The
+.Fn sbuf_prepend
+function prepends the NUL-terminated string
+.Fa str
+to the beginning of the
+.Fa sbuf .
.Pp
The
.Fn sbuf_set_drain
diff --git a/sys/kern/subr_sbuf.c b/sys/kern/subr_sbuf.c
--- a/sys/kern/subr_sbuf.c
+++ b/sys/kern/subr_sbuf.c
@@ -432,6 +432,59 @@
return (0);
}
+/*
+ * Prepend bytes to an sbuf. This is the core function for appending
+ * to an sbuf and is the main place that deals with extending the
+ * buffer and marking overflow.
+ */
+static void
+sbuf_prepend_bytes(struct sbuf *s, const char *buf, size_t len)
+{
+ size_t n, pos;
+
+ assert_sbuf_integrity(s);
+ assert_sbuf_state(s, 0);
+
+ if (s->s_error != 0)
+ return;
+
+ /*
+ * We can't prepend to sbufs with a drain function or sections at the
+ * moment.
+ */
+ if (s->s_drain_func != NULL || SBUF_ISSECTION(s)) {
+ s->s_error = ENXIO;
+ return;
+ }
+
+ /*
+ * We'll maintain the loop that sbuf_put_bytes() does since we can only
+ * allocate up to INT_MAX at a time.
+ */
+ pos = 0;
+ while (len > 0) {
+ if (SBUF_FREESPACE(s) <= 0) {
+ if (sbuf_extend(s, len > INT_MAX ? INT_MAX : len) < 0) {
+ s->s_error = ENOMEM;
+ return;
+ }
+ }
+ n = SBUF_FREESPACE(s);
+ if (len < n)
+ n = len;
+
+ /* Move anything currently in the way forward */
+ memmove(&s->s_buf[n + pos], &s->s_buf[pos], s->s_len - pos);
+
+ /* Append to anything previously prepended. */
+ memcpy(&s->s_buf[pos], buf, n);
+ s->s_len += n;
+ pos += n;
+ len -= n;
+ buf += n;
+ }
+}
+
/*
* Append bytes to an sbuf. This is the core function for appending
* to an sbuf and is the main place that deals with extending the
@@ -571,6 +624,21 @@
return (0);
}
+/*
+ * Prepend a string to an sbuf
+ */
+int
+sbuf_prepend(struct sbuf *s, const char *str)
+{
+ size_t n;
+
+ n = strlen(str);
+ sbuf_prepend_bytes(s, str, n);
+ if (s->s_error != 0)
+ return (-1);
+ return (0);
+}
+
#ifdef _KERNEL
/*
* Append a string from userland to an sbuf.
diff --git a/sys/sys/sbuf.h b/sys/sys/sbuf.h
--- a/sys/sys/sbuf.h
+++ b/sys/sys/sbuf.h
@@ -85,6 +85,7 @@
int sbuf_bcat(struct sbuf *, const void *, size_t);
int sbuf_bcpy(struct sbuf *, const void *, size_t);
int sbuf_cat(struct sbuf *, const char *);
+int sbuf_prepend(struct sbuf *, const char *);
int sbuf_cpy(struct sbuf *, const char *);
int sbuf_printf(struct sbuf *, const char *, ...)
__printflike(2, 3);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 1, 11:09 PM (8 m, 45 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29120445
Default Alt Text
D49945.id154040.diff (5 KB)
Attached To
Mode
D49945: libsbuf: add an sbuf_prepend() API
Attached
Detach File
Event Timeline
Log In to Comment