Page MenuHomeFreeBSD

D16690.id47180.diff
No OneTemporary

D16690.id47180.diff

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

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)

Event Timeline