summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_sysctl.c
diff options
context:
space:
mode:
authormdf <mdf@FreeBSD.org>2010-09-09 18:33:46 +0000
committermdf <mdf@FreeBSD.org>2010-09-09 18:33:46 +0000
commitbc5468425338dbee3cd3da7d6bc2a1290ba8d2ce (patch)
treefb245e2e8ce30565e64963b84e00c3b93d9bc280 /sys/kern/kern_sysctl.c
parenta7b4070f1f143143442a97cffdf24fc59814851f (diff)
downloadFreeBSD-src-bc5468425338dbee3cd3da7d6bc2a1290ba8d2ce.zip
FreeBSD-src-bc5468425338dbee3cd3da7d6bc2a1290ba8d2ce.tar.gz
Add a drain function for struct sysctl_req, and use it for a variety of
handlers, some of which had to do awkward things to get a large enough FIXEDLEN buffer. Note that some sysctl handlers were explicitly outputting a trailing NUL byte. This behaviour was preserved, though it should not be necessary. Reviewed by: phk
Diffstat (limited to 'sys/kern/kern_sysctl.c')
-rw-r--r--sys/kern/kern_sysctl.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index b83502c..49ccc50 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/jail.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/sbuf.h>
#include <sys/sx.h>
#include <sys/sysproto.h>
#include <sys/uio.h>
@@ -1544,3 +1545,30 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
}
return (error);
}
+
+/*
+ * Drain into a sysctl struct. The user buffer must be wired.
+ */
+static int
+sbuf_sysctl_drain(void *arg, const char *data, int len)
+{
+ struct sysctl_req *req = arg;
+ int error;
+
+ error = SYSCTL_OUT(req, data, len);
+ KASSERT(error >= 0, ("Got unexpected negative value %d", error));
+ return (error == 0 ? len : -error);
+}
+
+struct sbuf *
+sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length,
+ struct sysctl_req *req)
+{
+
+ /* Wire the user buffer, so we can write without blocking. */
+ sysctl_wire_old_buffer(req, 0);
+
+ s = sbuf_new(s, buf, length, SBUF_FIXEDLEN);
+ sbuf_set_drain(s, sbuf_sysctl_drain, req);
+ return (s);
+}
OpenPOWER on IntegriCloud