Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src The new sysctl query interface returns the same information ...



details:   https://anonhg.NetBSD.org/src/rev/d5716c03062b
branches:  trunk
changeset: 559830:d5716c03062b
user:      atatat <atatat%NetBSD.org@localhost>
date:      Wed Mar 24 16:34:34 2004 +0000

description:
The new sysctl query interface returns the same information as the old
one, but you must pass in an empty node that indicates the version
you're using.

diffstat:

 lib/libc/gen/sysctl.c    |   63 ++++++++++++++++++---
 sbin/sysctl/sysctlutil.c |   16 +++-
 sys/kern/kern_sysctl.c   |  139 +++++++++++++++++++++++++++++++++++-----------
 3 files changed, 171 insertions(+), 47 deletions(-)

diffs (truncated from 422 to 300 lines):

diff -r 74e35663b105 -r d5716c03062b lib/libc/gen/sysctl.c
--- a/lib/libc/gen/sysctl.c     Wed Mar 24 16:34:29 2004 +0000
+++ b/lib/libc/gen/sysctl.c     Wed Mar 24 16:34:34 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sysctl.c,v 1.17 2004/03/24 16:29:10 atatat Exp $       */
+/*     $NetBSD: sysctl.c,v 1.18 2004/03/24 16:34:34 atatat Exp $       */
 
 /*-
  * Copyright (c) 1993
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)sysctl.c   8.2 (Berkeley) 1/4/94";
 #else
-__RCSID("$NetBSD: sysctl.c,v 1.17 2004/03/24 16:29:10 atatat Exp $");
+__RCSID("$NetBSD: sysctl.c,v 1.18 2004/03/24 16:34:34 atatat Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -58,6 +58,12 @@
  */
 static int user_sysctl(int *, u_int, void *, size_t *, const void *, size_t);
 
+/*
+ * copies out individual nodes taking target version into account
+ */
+static size_t __cvt_node_out(uint, const struct sysctlnode *, void **,
+                            size_t *);
+
 #include <stdlib.h>
 
 int
@@ -129,7 +135,7 @@
                        .sysctl_size = sizeof(_PATH_STDPATH),
                        .sysctl_name = "cs_path",
                        .sysctl_num = USER_CS_PATH,
-                       .sysctl_un = { .scu_data = _PATH_STDPATH, },
+                       .sysctl_data = _PATH_STDPATH,
                },
                _INT("bc_base_max", USER_BC_BASE_MAX, BC_BASE_MAX),
                _INT("bc_dim_max", USER_BC_DIM_MAX, BC_DIM_MAX),
@@ -198,20 +204,35 @@
        /*
         * none of these nodes are writable and they're all terminal (for now)
         */
-       if (newp != NULL || newlen != 0)
-               return (EPERM);
        if (namelen != 1)
                return (EINVAL);
 
        l = *oldlenp;
        if (name[0] == CTL_QUERY) {
-               sz = clen * sizeof(struct sysctlnode);
-               l = MIN(l, sz);
-               if (oldp != NULL)
-                       memcpy(oldp, &sysctl_usermib[0], l);
+               uint v;
+               node = newp;
+               if (node == NULL) {
+                       v = SYSCTL_VERS_0;
+                       newlen = sizeof(struct sysctlnode);
+               }
+               else if (SYSCTL_VERS(node->sysctl_flags) == SYSCTL_VERS_0 &&
+                        newlen == sizeof(struct sysctlnode))
+                       v = SYSCTL_VERS_0;
+               else
+                       return (EINVAL);
+
+               sz = 0;
+               for (ni = 0; ni < clen; ni++)
+                       sz += __cvt_node_out(v, &sysctl_usermib[ni], &oldp, &l);
                *oldlenp = sz;
                return (0);
        }
+
+       /*
+        * none of these nodes are writable
+        */
+       if (newp != NULL || newlen != 0)
+               return (EPERM);
        
        node = &sysctl_usermib[0];
        for (ni = 0; ni < clen; ni++)
@@ -243,3 +264,27 @@
 
        return (0);
 }
+
+static size_t
+__cvt_node_out(uint v, const struct sysctlnode *n, void **o, size_t *l)
+{
+       const void *src = n;
+       size_t sz;
+
+       switch (v) {
+       case SYSCTL_VERSION:
+               sz = sizeof(struct sysctlnode);
+               break;
+       default:
+               sz = 0;
+               break;
+       }
+
+       if (sz > 0 && *o != NULL && *l >= sz) {
+               memcpy(*o, src, sz);
+               *o = sz + (caddr_t)*o;
+               *l -= sz;
+       }
+
+       return(sz);
+}
diff -r 74e35663b105 -r d5716c03062b sbin/sysctl/sysctlutil.c
--- a/sbin/sysctl/sysctlutil.c  Wed Mar 24 16:34:29 2004 +0000
+++ b/sbin/sysctl/sysctlutil.c  Wed Mar 24 16:34:34 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sysctlutil.c,v 1.5 2004/03/24 15:34:56 atatat Exp $ */
+/*     $NetBSD: sysctlutil.c,v 1.6 2004/03/24 16:34:34 atatat Exp $ */
 
 #include <sys/param.h>
 #define __USE_NEW_SYSCTL
@@ -59,6 +59,7 @@
 int
 learn_tree(int *name, u_int namelen, struct sysctlnode *pnode)
 {
+       struct sysctlnode qnode;
        int rc;
        size_t sz;
 
@@ -82,7 +83,10 @@
        name[namelen] = CTL_QUERY;
        pnode->sysctl_clen = 0;
        pnode->sysctl_csize = 0;
-       rc = sysctl(name, namelen + 1, pnode->sysctl_child, &sz, NULL, 0);
+       memset(&qnode, 0, sizeof(qnode));
+       qnode.sysctl_flags = SYSCTL_VERSION;
+       rc = sysctl(name, namelen + 1, pnode->sysctl_child, &sz,
+                   &qnode, sizeof(qnode));
        if (sz == 0) {
                free(pnode->sysctl_child);
                pnode->sysctl_child = NULL;
@@ -103,7 +107,7 @@
                        return (-1);
 
                rc = sysctl(name, namelen + 1, pnode->sysctl_child, &sz,
-                           NULL, 0);
+                           &qnode, sizeof(qnode));
                if (rc) {
                        free(pnode->sysctl_child);
                        pnode->sysctl_child = NULL;
@@ -178,7 +182,7 @@
 static void
 relearnhead(void)
 {
-       struct sysctlnode *h, *i, *o;
+       struct sysctlnode *h, *i, *o, qnode;
        size_t si, so;
        int rc, name, nlen, olen, ni, oi, t;
 
@@ -197,10 +201,12 @@
        si = 0;
        so = sysctl_mibroot.sysctl_clen * sizeof(struct sysctlnode);
        name = CTL_QUERY;
+       memset(&qnode, 0, sizeof(qnode));
+       qnode.sysctl_flags = SYSCTL_VERSION;
        do {
                si = so;
                h = malloc(si);
-               rc = sysctl(&name, 1, h, &so, NULL, 0);
+               rc = sysctl(&name, 1, h, &so, &qnode, sizeof(qnode));
                if (rc == -1 && errno != ENOMEM)
                        return;
                if (si < so)
diff -r 74e35663b105 -r d5716c03062b sys/kern/kern_sysctl.c
--- a/sys/kern/kern_sysctl.c    Wed Mar 24 16:34:29 2004 +0000
+++ b/sys/kern/kern_sysctl.c    Wed Mar 24 16:34:34 2004 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_sysctl.c,v 1.161 2004/03/24 15:34:53 atatat Exp $ */
+/*     $NetBSD: kern_sysctl.c,v 1.162 2004/03/24 16:34:34 atatat Exp $ */
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -75,7 +75,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sysctl.c,v 1.161 2004/03/24 15:34:53 atatat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sysctl.c,v 1.162 2004/03/24 16:34:34 atatat Exp $");
 
 #include "opt_defcorename.h"
 #include "opt_insecure.h"
@@ -99,6 +99,11 @@
 static int sysctl_alloc(struct sysctlnode *, int);
 static int sysctl_realloc(struct sysctlnode *);
 
+static int sysctl_cvt_in(struct lwp *, int *, const void *, size_t,
+                        struct sysctlnode *);
+static int sysctl_cvt_out(struct lwp *, int, const struct sysctlnode *,
+                         void *, size_t, size_t *);
+
 /*
  * the "root" of the new sysctl tree
  */
@@ -565,17 +570,15 @@
 int
 sysctl_query(SYSCTLFN_ARGS)
 {
-       int error, ni, elim;
+       int error, ni, elim, v;
        size_t out, left, t;
-       struct sysctlnode *enode, *onode;
+       struct sysctlnode *enode, *onode, qnode;
 
        if (SYSCTL_VERS(rnode->sysctl_flags) != SYSCTL_VERSION) {
                printf("sysctl_query: rnode %p wrong version\n", rnode);
                return (EINVAL);
        }
 
-       if (newp != NULL)
-               return (EPERM);
        if (SYSCTL_TYPE(rnode->sysctl_flags) != CTLTYPE_NODE)
                return (ENOTDIR);
        if (namelen != 1 || name[0] != CTL_QUERY)
@@ -588,6 +591,23 @@
        enode = NULL;
 
        /*
+        * translate the given request to a current node
+        */
+       error = sysctl_cvt_in(l, &v, newp, newlen, &qnode);
+       if (error)
+               return (error);
+
+       /*
+        * if the request specifies a version, check it
+        */
+       if (qnode.sysctl_ver != 0) {
+               enode = (struct sysctlnode *)rnode; /* discard const */
+               if (qnode.sysctl_ver != enode->sysctl_ver &&
+                   qnode.sysctl_ver != sysctl_rootof(enode)->sysctl_ver)
+                       return (EINVAL);
+       }
+
+       /*
         * process has overlay tree
         */
        if (l && l->l_proc->p_emul->e_sysctlovly) {
@@ -607,7 +627,6 @@
        }
 
        for (ni = 0; ni < rnode->sysctl_clen; ni++) {
-               t = MIN(left, sizeof(struct sysctlnode));
                onode = &rnode->sysctl_child[ni];
                if (enode && enode->sysctl_num == onode->sysctl_num) {
                        if (SYSCTL_TYPE(enode->sysctl_flags) != CTLTYPE_NODE)
@@ -617,12 +636,13 @@
                        else
                                enode = NULL;
                }
-               if (oldp != NULL && t > 0)
-                       error = sysctl_copyout(l, onode, (char*)oldp + out, t);
+               error = sysctl_cvt_out(l, v, onode, oldp, left, &t);
                if (error)
                        return (error);
-               out += sizeof(struct sysctlnode);
-               left -= t;
+               if (oldp != NULL)
+                       oldp = (char*)oldp + t;
+               out += t;
+               left -= MIN(left, t);
        }
 
        /*
@@ -651,7 +671,7 @@
 sysctl_create(SYSCTLFN_RWARGS)
 {
        struct sysctlnode nnode, *node, *pnode;
-       int error, ni, at, nm, type, sz, flags, rw, anum;
+       int error, ni, at, nm, type, sz, flags, rw, anum, v;
        void *own;
 
        error = 0;
@@ -704,9 +724,9 @@
                return (ENOTDIR);
        pnode = rnode;
 
-       if (newp == NULL || newlen != sizeof(struct sysctlnode))
+       if (newp == NULL)
                return (EINVAL);
-       error = sysctl_copyin(l, newp, &nnode, MIN(sizeof(nnode), newlen));
+       error = sysctl_cvt_in(l, &v, newp, newlen, &nnode);
        if (error)
                return (error);
 
@@ -775,15 +795,12 @@
        for (ni = at = 0; ni < pnode->sysctl_clen; ni++) {
                if (nm == node[ni].sysctl_num ||
                    strcmp(nnode.sysctl_name, node[ni].sysctl_name) == 0) {
-                       if (oldp != NULL) {
-                               /*
-                                * ignore error here, since we
-                                * are already fixed on EEXIST



Home | Main Index | Thread Index | Old Index