Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F136656397
D16690.id47180.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D16690.id47180.diff
View Options
Index: lib/libsbuf/Symbol.map
===================================================================
--- lib/libsbuf/Symbol.map
+++ lib/libsbuf/Symbol.map
@@ -37,5 +37,6 @@
FBSD_1.5 {
sbuf_putbuf;
+ sbuf_printf_drain;
};
Index: lib/libsbuf/tests/sbuf_core_test.c
===================================================================
--- lib/libsbuf/tests/sbuf_core_test.c
+++ lib/libsbuf/tests/sbuf_core_test.c
@@ -64,6 +64,9 @@
*/
child_proc = atf_utils_fork();
if (child_proc == 0) {
+ ATF_REQUIRE_EQ_MSG(0, sbuf_finish(sb), "sbuf_finish failed: %s",
+ strerror(errno));
+
sbuf_putbuf(sb);
exit(0);
}
@@ -101,6 +104,34 @@
sbuf_delete(sb);
}
+static int
+drain_ret0(void *arg, const char *data, int len)
+{
+
+ (void)arg;
+ (void)data;
+ (void)len;
+
+ return 0;
+}
+
+ATF_TC_WITHOUT_HEAD(sbuf_drain_ret0_test);
+ATF_TC_BODY(sbuf_drain_ret0_test, tc)
+{
+ struct sbuf *sb;
+
+ sb = sbuf_new_auto();
+
+ sbuf_set_drain(sb, drain_ret0, NULL);
+
+ sbuf_cat(sb, test_string);
+
+ ATF_CHECK_EQ_MSG(-1, sbuf_finish(sb),
+ "required to return error when drain func returns 0");
+ ATF_CHECK_EQ_MSG(EDEADLK, errno,
+ "errno required to be EDEADLK when drain func returns 0");
+}
+
ATF_TC_WITHOUT_HEAD(sbuf_len_test);
ATF_TC_BODY(sbuf_len_test, tc)
{
@@ -132,6 +163,34 @@
sbuf_delete(sb);
}
+ATF_TC_WITHOUT_HEAD(sbuf_new_fixedlen);
+ATF_TC_BODY(sbuf_new_fixedlen, tc)
+{
+ char buf[strlen(test_string) + 1];
+ struct sbuf sb;
+ pid_t child_proc;
+
+ sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
+
+ sbuf_cat(&sb, test_string);
+
+ child_proc = atf_utils_fork();
+ if (child_proc == 0) {
+ ATF_REQUIRE_EQ_MSG(0, sbuf_finish(&sb), "sbuf_finish failed: %s",
+ strerror(errno));
+
+ sbuf_putbuf(&sb);
+ exit(0);
+ }
+ atf_utils_wait(child_proc, 0, test_string, "");
+
+ sbuf_putc(&sb, ' ');
+
+ ATF_CHECK_EQ_MSG(-1, sbuf_finish(&sb), "failed to return error on overflow");
+
+ sbuf_delete(&sb);
+}
+
ATF_TC_WITHOUT_HEAD(sbuf_setpos_test);
ATF_TC_BODY(sbuf_setpos_test, tc)
{
@@ -191,7 +250,9 @@
ATF_TP_ADD_TC(tp, sbuf_clear_test);
ATF_TP_ADD_TC(tp, sbuf_done_and_sbuf_finish_test);
+ ATF_TP_ADD_TC(tp, sbuf_drain_ret0_test);
ATF_TP_ADD_TC(tp, sbuf_len_test);
+ ATF_TP_ADD_TC(tp, sbuf_new_fixedlen);
#if 0
/* TODO */
#ifdef HAVE_SBUF_CLEAR_FLAGS
Index: lib/libsbuf/tests/sbuf_stdio_test.c
===================================================================
--- lib/libsbuf/tests/sbuf_stdio_test.c
+++ lib/libsbuf/tests/sbuf_stdio_test.c
@@ -60,6 +60,60 @@
return (rc);
}
+ATF_TC_WITHOUT_HEAD(sbuf_printf_drain_null_test);
+ATF_TC_BODY(sbuf_printf_drain_null_test, tc)
+{
+ struct sbuf *sb;
+ char buf[2];
+ pid_t child_proc;
+
+ sb = sbuf_new(NULL, buf, sizeof(buf), SBUF_FIXEDLEN);
+ ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
+ strerror(errno));
+
+ child_proc = atf_utils_fork();
+ if (child_proc == 0) {
+ sbuf_set_drain(sb, sbuf_printf_drain, NULL);
+
+ ATF_REQUIRE_EQ_MSG(0, sbuf_cat(sb, test_string),
+ "sbuf_cat failed");
+
+ ATF_CHECK_EQ(0, sbuf_finish(sb));
+ exit(0);
+ }
+ atf_utils_wait(child_proc, 0, test_string, "");
+
+ sbuf_delete(sb);
+}
+
+ATF_TC_WITHOUT_HEAD(sbuf_printf_drain_test);
+ATF_TC_BODY(sbuf_printf_drain_test, tc)
+{
+ struct sbuf *sb;
+ char buf[2];
+ pid_t child_proc;
+ size_t cnt = 0;
+
+ sb = sbuf_new(NULL, buf, sizeof(buf), SBUF_FIXEDLEN);
+ ATF_REQUIRE_MSG(sb != NULL, "sbuf_new_auto failed: %s",
+ strerror(errno));
+
+ child_proc = atf_utils_fork();
+ if (child_proc == 0) {
+ sbuf_set_drain(sb, sbuf_printf_drain, &cnt);
+
+ ATF_REQUIRE_EQ_MSG(0, sbuf_cat(sb, test_string),
+ "sbuf_cat failed");
+
+ ATF_CHECK_EQ(0, sbuf_finish(sb));
+ ATF_CHECK_EQ(strlen(test_string), cnt);
+ exit(0);
+ }
+ atf_utils_wait(child_proc, 0, test_string, "");
+
+ sbuf_delete(sb);
+}
+
ATF_TC_WITHOUT_HEAD(sbuf_printf_test);
ATF_TC_BODY(sbuf_printf_test, tc)
{
@@ -107,6 +161,7 @@
child_proc = atf_utils_fork();
if (child_proc == 0) {
+ ATF_CHECK_EQ(0, sbuf_finish(sb));
sbuf_putbuf(sb);
exit(0);
}
@@ -153,6 +208,8 @@
ATF_TP_ADD_TCS(tp)
{
+ ATF_TP_ADD_TC(tp, sbuf_printf_drain_null_test);
+ ATF_TP_ADD_TC(tp, sbuf_printf_drain_test);
ATF_TP_ADD_TC(tp, sbuf_printf_test);
ATF_TP_ADD_TC(tp, sbuf_putbuf_test);
ATF_TP_ADD_TC(tp, sbuf_vprintf_test);
Index: share/man/man9/Makefile
===================================================================
--- share/man/man9/Makefile
+++ share/man/man9/Makefile
@@ -1778,6 +1778,8 @@
sbuf.9 sbuf_new_auto.9 \
sbuf.9 sbuf_new_for_sysctl.9 \
sbuf.9 sbuf_printf.9 \
+ sbuf.9 sbuf_printf_drain.9 \
+ sbuf.9 sbuf_putbuf.9 \
sbuf.9 sbuf_putc.9 \
sbuf.9 sbuf_set_drain.9 \
sbuf.9 sbuf_set_flags.9 \
Index: share/man/man9/sbuf.9
===================================================================
--- share/man/man9/sbuf.9
+++ share/man/man9/sbuf.9
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 23, 2018
+.Dd August 19, 2018
.Dt SBUF 9
.Os
.Sh NAME
@@ -58,6 +58,7 @@
.Nm sbuf_start_section ,
.Nm sbuf_end_section ,
.Nm sbuf_hexdump ,
+.Nm sbuf_printf_drain ,
.Nm sbuf_putbuf
.Nd safe string composition
.Sh SYNOPSIS
@@ -192,6 +193,12 @@
.Fa "int flags"
.Fc
.Ft void
+.Fo sbuf_printf_drain
+.Fa "void *arg"
+.Fa "const char *data"
+.Fa "int len"
+.Fc
+.Ft void
.Fo sbuf_putbuf
.Fa "struct sbuf *s"
.Fc
@@ -278,7 +285,9 @@
records being split.
If a record grows sufficiently large such that it fills the
.Fa sbuf
-and therefore cannot be drained without being split, an error of EDEADLK is set.
+and therefore cannot be drained without being split, an error of
+.Er EDEADLK
+is set.
.El
.Pp
Note that if
@@ -419,7 +428,9 @@
If negative, the return value indicates the negative error code which
will be returned from this or a later call to
.Fn sbuf_finish .
-The returned drained length cannot be zero.
+If the returned drained length is 0, an error of
+.Er EDEADLK
+is set.
To do unbuffered draining, initialize the sbuf with a two-byte buffer.
The drain will be called for every byte added to the sbuf.
The
@@ -492,7 +503,9 @@
.Fn sbuf_error
function returns any error value that the
.Fa sbuf
-may have accumulated, either from the drain function, or ENOMEM if the
+may have accumulated, either from the drain function, or
+.Er ENOMEM
+if the
.Fa sbuf
overflowed.
This function is generally not needed and instead the error code from
@@ -574,9 +587,21 @@
man page for more details on the interface.
.Pp
The
+.Fn sbuf_printf_drain
+function is a drain function that will call printf, or log to the console.
+The argument
+.Fa arg
+must be either NULL, or a valid pointer to a size_t, and the total bytes
+drained will accumulated into it.
+.Pp
+The
.Fn sbuf_putbuf
function printfs the sbuf to stdout if in userland, and to the console
and log if in the kernel.
+The
+.Fa sbuf
+must be finished before calling
+.Fn sbuf_putbuf .
It does not drain the buffer or update any pointers.
.Sh NOTES
If an operation caused an
@@ -655,7 +680,9 @@
.Pp
The
.Fn sbuf_finish 9
-function (the kernel version) returns ENOMEM if the sbuf overflowed before
+function (the kernel version) returns
+.Er ENOMEM
+if the sbuf overflowed before
being finished,
or returns the error code from the drain if one is attached.
.Pp
Index: sys/kern/kern_sysctl.c
===================================================================
--- sys/kern/kern_sysctl.c
+++ sys/kern/kern_sysctl.c
@@ -322,13 +322,6 @@
freeenv(penv);
}
-static int
-sbuf_printf_drain(void *arg __unused, const char *data, int len)
-{
-
- return (printf("%.*s", len, data));
-}
-
/*
* Locate the path to a given oid. Returns the length of the resulting path,
* or -1 if the oid was not found. nodes must have room for CTL_MAXNAME
Index: sys/kern/subr_bus.c
===================================================================
--- sys/kern/subr_bus.c
+++ sys/kern/subr_bus.c
@@ -2416,13 +2416,31 @@
int
device_printf(device_t dev, const char * fmt, ...)
{
+ char buf[128];
+ struct sbuf sb;
+ const char *name;
va_list ap;
int retval;
- retval = device_print_prettyname(dev);
+ retval = 0;
+
+ sbuf_new(&sb, buf, sizeof buf, SBUF_FIXEDLEN);
+ sbuf_set_drain(&sb, sbuf_printf_drain, &retval);
+
+ name = device_get_name(dev);
+
+ if (name == NULL)
+ sbuf_cat(&sb, "unknown: ");
+ else
+ sbuf_printf(&sb, "%s%d: ", name, device_get_unit(dev));
+
va_start(ap, fmt);
- retval += vprintf(fmt, ap);
+ sbuf_vprintf(&sb, fmt, ap);
va_end(ap);
+
+ sbuf_finish(&sb);
+ sbuf_delete(&sb);
+
return (retval);
}
Index: sys/kern/subr_prf.c
===================================================================
--- sys/kern/subr_prf.c
+++ sys/kern/subr_prf.c
@@ -1282,3 +1282,43 @@
printf("%s", sbuf_data(sb));
}
#endif
+
+int
+sbuf_printf_drain(void *arg, const char *data, int len)
+{
+ size_t *retvalptr;
+ size_t tmpint;
+ int r;
+#ifdef _KERNEL
+ char *dataptr;
+ char oldchr;
+#endif
+
+ if (arg == NULL)
+ retvalptr = &tmpint;
+ else
+ retvalptr = arg;
+
+#ifdef _KERNEL
+ /*
+ * This is allowed as an extra byte is always resvered for
+ * terminating NUL byte. Save and restore the byte because
+ * we might be flushing a record, and there may be valid
+ * data after the buffer.
+ */
+ oldchr = data[len];
+ dataptr = __DECONST(char *, data);
+ dataptr[len] = '\0';
+
+ prf_putbuf(dataptr, TOLOG | TOCONS, -1);
+ r = len;
+
+ dataptr[len] = oldchr;
+#else
+ r = printf("%.*s", len, data);
+#endif
+
+ *retvalptr += r;
+
+ return r;
+}
Index: sys/sys/sbuf.h
===================================================================
--- sys/sys/sbuf.h
+++ sys/sys/sbuf.h
@@ -103,6 +103,7 @@
ssize_t sbuf_end_section(struct sbuf *, ssize_t, size_t, int);
void sbuf_hexdump(struct sbuf *, const void *, int, const char *,
int);
+int sbuf_printf_drain(void *arg, const char *data, int len);
void sbuf_putbuf(struct sbuf *);
#ifdef _KERNEL
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 19, 6:45 PM (19 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25664704
Default Alt Text
D16690.id47180.diff (9 KB)
Attached To
Mode
D16690: make device_printf use sbuf
Attached
Detach File
Event Timeline
Log In to Comment