| @@ -1,57 +1,84 @@ | | | @@ -1,57 +1,84 @@ |
1 | $NetBSD: patch-sysctlmodule.c,v 1.1 2019/09/09 07:09:47 maya Exp $ | | 1 | $NetBSD: patch-sysctlmodule.c,v 1.2 2019/09/15 15:17:06 fox Exp $ |
2 | | | 2 | |
3 | Port to python 3 | | 3 | Port to python 3 |
4 | | | 4 | |
| | | 5 | Fixes how new integer data is inserted into nodes. It now sets the |
| | | 6 | CTL_IMMEDIATE flag and value is placed in sysctl_idata. This fixes |
| | | 7 | the failing test for creating and destroying integer type nodes. |
| | | 8 | |
5 | --- sysctlmodule.c.orig 2010-04-10 17:41:18.000000000 +0000 | | 9 | --- sysctlmodule.c.orig 2010-04-10 17:41:18.000000000 +0000 |
6 | +++ sysctlmodule.c | | 10 | +++ sysctlmodule.c |
7 | @@ -33,6 +33,21 @@ | | 11 | @@ -33,7 +33,22 @@ |
8 | #include <errno.h> | | 12 | #include <errno.h> |
9 | #include <sys/sysctl.h> | | 13 | #include <sys/sysctl.h> |
10 | | | 14 | |
| | | 15 | -/* |
11 | +struct module_state { | | 16 | +struct module_state { |
12 | + PyObject *error; | | 17 | + PyObject *error; |
13 | +}; | | 18 | +}; |
14 | + | | 19 | + |
15 | +#if PY_MAJOR_VERSION >= 3 | | 20 | +#if PY_MAJOR_VERSION >= 3 |
16 | +#define PyInt_AsLong PyLong_AsLong | | 21 | +#define PyInt_AsLong PyLong_AsLong |
17 | +#define PyInt_CheckExact PyLong_CheckExact | | 22 | +#define PyInt_CheckExact PyLong_CheckExact |
18 | +#define PyString_CheckExact(val) PyUnicode_CheckExact(val) | | 23 | +#define PyString_CheckExact(val) PyUnicode_CheckExact(val) |
19 | +#define PyString_FromStringAndSize PyUnicode_FromStringAndSize | | 24 | +#define PyString_FromStringAndSize PyUnicode_FromStringAndSize |
20 | +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) | | 25 | +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) |
21 | +#else | | 26 | +#else |
22 | +#define GETSTATE(m) (&_state) | | 27 | +#define GETSTATE(m) (&_state) |
23 | +static struct module_state _state; | | 28 | +static struct module_state _state; |
24 | +#endif | | 29 | +#endif |
25 | + | | 30 | + |
26 | /* | | 31 | +/* |
27 | * create Python object of type similar to the MIB node 'name' | | 32 | * create Python object of type similar to the MIB node 'name' |
28 | * This is basically the laziest way to do this, as we outsource the | | 33 | * This is basically the laziest way to do this, as we outsource the |
| | | 34 | * type recognition to the sysctl(3) API. Fantastic! :-) |
| | | 35 | @@ -94,9 +109,9 @@ node_to_object(const char *name, void *v |
| | | 36 | return o; |
| | | 37 | } |
| | | 38 | |
| | | 39 | -/* |
| | | 40 | +/* |
| | | 41 | * SYSCTL_TYPEMASK is used as an error type. This is an implementation |
| | | 42 | - * detail. |
| | | 43 | + * detail. |
| | | 44 | */ |
| | | 45 | static uint32_t |
| | | 46 | nodetype(char *nodepath) |
29 | @@ -104,14 +119,12 @@ nodetype(char *nodepath) | | 47 | @@ -104,14 +119,12 @@ nodetype(char *nodepath) |
30 | | | 48 | |
31 | int rv; | | 49 | int rv; |
32 | char cname[SYSCTL_NAMELEN]; | | 50 | char cname[SYSCTL_NAMELEN]; |
33 | - int csz; | | 51 | - int csz; |
34 | + size_t csz = SYSCTL_NAMELEN; | | 52 | + size_t csz = SYSCTL_NAMELEN; |
35 | | | 53 | |
36 | struct sysctlnode *rnode = NULL; | | 54 | struct sysctlnode *rnode = NULL; |
37 | | | 55 | |
38 | assert (nodepath != NULL); | | 56 | assert (nodepath != NULL); |
39 | | | 57 | |
40 | - csz = SYSCTL_NAMELEN; | | 58 | - csz = SYSCTL_NAMELEN; |
41 | - | | 59 | - |
42 | rv = sysctlgetmibinfo(nodepath, NULL, NULL, cname, &csz, &rnode, SYSCTL_VERSION); | | 60 | rv = sysctlgetmibinfo(nodepath, NULL, NULL, cname, &csz, &rnode, SYSCTL_VERSION); |
43 | | | 61 | |
44 | if (rv == -1 || rnode == NULL) { | | 62 | if (rv == -1 || rnode == NULL) { |
| | | 63 | @@ -133,7 +146,7 @@ nodetype(char *nodepath) |
| | | 64 | * discarded ), and a new one, with requested string is assigned. |
| | | 65 | * |
| | | 66 | * XXX: This is a workaround for sysctl(3) not allowing strings longer |
| | | 67 | - * than the current value. |
| | | 68 | + * than the current value. |
| | | 69 | * See: http://mail-index.netbsd.org/tech-kern/2009/10/22/msg006329.html |
| | | 70 | */ |
| | | 71 | |
45 | @@ -149,7 +162,7 @@ write_sysctl_string(char *name, char *va | | 72 | @@ -149,7 +162,7 @@ write_sysctl_string(char *name, char *va |
46 | size_t nodelen; | | 73 | size_t nodelen; |
47 | | | 74 | |
48 | char cname[SYSCTL_NAMELEN]; | | 75 | char cname[SYSCTL_NAMELEN]; |
49 | - int csz = SYSCTL_NAMELEN; | | 76 | - int csz = SYSCTL_NAMELEN; |
50 | + size_t csz = SYSCTL_NAMELEN; | | 77 | + size_t csz = SYSCTL_NAMELEN; |
51 | | | 78 | |
52 | /* Sanity checks */ | | 79 | /* Sanity checks */ |
53 | | | 80 | |
54 | @@ -237,7 +250,7 @@ read_sysctl(PyObject *self, PyObject *ar | | 81 | @@ -237,7 +250,7 @@ read_sysctl(PyObject *self, PyObject *ar |
55 | { | | 82 | { |
56 | PyObject *o; | | 83 | PyObject *o; |
57 | void *val; | | 84 | void *val; |
| @@ -79,75 +106,128 @@ Port to python 3 | | | @@ -79,75 +106,128 @@ Port to python 3 |
79 | + if (val == NULL) { | | 106 | + if (val == NULL) { |
80 | PyErr_NoMemory(); | | 107 | PyErr_NoMemory(); |
81 | return NULL; | | 108 | return NULL; |
82 | } | | 109 | } |
83 | @@ -309,7 +320,7 @@ write_sysctl(PyObject *self, PyObject *a | | 110 | @@ -309,7 +320,7 @@ write_sysctl(PyObject *self, PyObject *a |
84 | | | 111 | |
85 | /* Arrange to obtain the oldvalue */ | | 112 | /* Arrange to obtain the oldvalue */ |
86 | oldval = NULL; | | 113 | oldval = NULL; |
87 | - len = 0; | | 114 | - len = 0; |
88 | + len = 4; | | 115 | + len = 4; |
89 | | | 116 | |
90 | rv = sysctlbyname(name, NULL, &len, NULL, 0); | | 117 | rv = sysctlbyname(name, NULL, &len, NULL, 0); |
91 | | | 118 | |
| | | 119 | @@ -350,7 +361,7 @@ write_sysctl(PyObject *self, PyObject *a |
| | | 120 | return NULL; |
| | | 121 | } |
| | | 122 | |
| | | 123 | - /* |
| | | 124 | + /* |
| | | 125 | * Strings are handled specially. We just use |
| | | 126 | * read_sysctl() to record the previous string value. |
| | | 127 | * We ignore and free(oldval) |
| | | 128 | @@ -424,7 +435,7 @@ getnewleafname(const char *name, char *c |
| | | 129 | |
| | | 130 | /* |
| | | 131 | * Get the common prefix of name from what's already in the MIB and |
| | | 132 | - * what's been requested |
| | | 133 | + * what's been requested |
| | | 134 | */ |
| | | 135 | static void |
| | | 136 | getprefixname(const char *name, char *pname) |
92 | @@ -445,7 +456,7 @@ create_node(const char *name, int ctl_ty | | 137 | @@ -445,7 +456,7 @@ create_node(const char *name, int ctl_ty |
93 | { | | 138 | { |
94 | | | 139 | |
95 | int mib[CTL_MAXNAME]; | | 140 | int mib[CTL_MAXNAME]; |
96 | - u_int miblen = CTL_MAXNAME; | | 141 | - u_int miblen = CTL_MAXNAME; |
97 | + size_t miblen = CTL_MAXNAME; | | 142 | + size_t miblen = CTL_MAXNAME; |
98 | | | 143 | |
99 | char cname[SYSCTL_NAMELEN]; /* Canonical name */ | | 144 | char cname[SYSCTL_NAMELEN]; /* Canonical name */ |
100 | char pname[SYSCTL_NAMELEN]; /* The Canonical prefix */ | | 145 | char pname[SYSCTL_NAMELEN]; /* The Canonical prefix */ |
101 | @@ -456,6 +467,7 @@ create_node(const char *name, int ctl_ty | | 146 | @@ -456,6 +467,7 @@ create_node(const char *name, int ctl_ty |
102 | struct sysctlnode node; | | 147 | struct sysctlnode node; |
103 | size_t nodelen; | | 148 | size_t nodelen; |
104 | | | 149 | |
105 | + | | 150 | + |
106 | /* Check for NULL ptr dereference */ | | 151 | /* Check for NULL ptr dereference */ |
107 | assert (value != NULL || vlen == 0); | | 152 | assert (value != NULL || vlen == 0); |
108 | | | 153 | |
109 | @@ -533,7 +545,7 @@ create_sysctl(PyObject *self, PyObject * | | 154 | @@ -504,7 +516,12 @@ create_node(const char *name, int ctl_ty |
| | | 155 | memset(&node, 0, nodelen); |
| | | 156 | node.sysctl_num = CTL_CREATE; |
| | | 157 | node.sysctl_flags = SYSCTL_VERSION | flags | ctl_type; |
| | | 158 | - node.sysctl_data = value; |
| | | 159 | + if (ctl_type == CTLTYPE_INT) { |
| | | 160 | + node.sysctl_idata = *(int *) value; |
| | | 161 | + } |
| | | 162 | + else { |
| | | 163 | + node.sysctl_data = value; |
| | | 164 | + } |
| | | 165 | node.sysctl_size = vlen; |
| | | 166 | |
| | | 167 | snprintf(node.sysctl_name, csz + 1, cname); |
| | | 168 | @@ -533,7 +550,7 @@ create_sysctl(PyObject *self, PyObject * |
110 | const char *typename = NULL; | | 169 | const char *typename = NULL; |
111 | size_t typelen = 0; | | 170 | size_t typelen = 0; |
112 | | | 171 | |
113 | - int len, rv; | | 172 | - int len, rv; |
114 | + int rv; | | 173 | + int rv; |
115 | | | 174 | |
116 | /* XXX: Royal mess... needs more thought */ | | 175 | /* XXX: Royal mess... needs more thought */ |
117 | if (!PyArg_ParseTuple(args, "s|s#O: Incorrect values passed to sysctl.write", &name, &typename, &typelen, &value)) { | | 176 | if (!PyArg_ParseTuple(args, "s|s#O: Incorrect values passed to sysctl.write", &name, &typename, &typelen, &value)) { |
118 | @@ -546,7 +558,7 @@ create_sysctl(PyObject *self, PyObject * | | 177 | @@ -546,7 +563,7 @@ create_sysctl(PyObject *self, PyObject * |
119 | } | | 178 | } |
120 | | | 179 | |
121 | /* XXX: Arrange to obtain the oldvalue */ | | 180 | /* XXX: Arrange to obtain the oldvalue */ |
122 | - len = 0; | | 181 | - len = 0; |
123 | + /*len = 4;*/ | | 182 | + /*len = 4;*/ |
124 | | | 183 | |
125 | if ((typename == NULL && typelen == 0) | | 184 | if ((typename == NULL && typelen == 0) |
126 | || (!strncmp(typename, "CTLTYPE_NODE", typelen)) ) { | | 185 | || (!strncmp(typename, "CTLTYPE_NODE", typelen)) ) { |
127 | @@ -593,7 +605,12 @@ create_sysctl(PyObject *self, PyObject * | | 186 | @@ -578,7 +595,7 @@ create_sysctl(PyObject *self, PyObject * |
| | | 187 | } |
| | | 188 | } |
| | | 189 | |
| | | 190 | - if (!create_node(name, CTLTYPE_INT, CTLFLAG_READWRITE, &intval, sizeof intval)) { |
| | | 191 | + if (!create_node(name, CTLTYPE_INT, CTLFLAG_READWRITE|CTLFLAG_IMMEDIATE, &intval, sizeof intval)) { |
| | | 192 | return NULL; |
| | | 193 | } else { |
| | | 194 | Py_RETURN_NONE; |
| | | 195 | @@ -593,7 +610,12 @@ create_sysctl(PyObject *self, PyObject * |
128 | PyErr_SetString(PyExc_TypeError, "Value passed is of wrong type"); | | 196 | PyErr_SetString(PyExc_TypeError, "Value passed is of wrong type"); |
129 | return NULL; | | 197 | return NULL; |
130 | } | | 198 | } |
131 | +#if PY_MAJOR_VERSION >= 3 | | 199 | +#if PY_MAJOR_VERSION >= 3 |
132 | + strval = PyUnicode_AsUTF8AndSize(value, &vlen); | | 200 | + strval = (char *) PyUnicode_AsUTF8AndSize(value, &vlen); |
133 | + if (strval == NULL) { | | 201 | + if (strval == NULL) { |
134 | +#else | | 202 | +#else |
135 | if (-1 == PyString_AsStringAndSize(value, &strval, &vlen)) { | | 203 | if (-1 == PyString_AsStringAndSize(value, &strval, &vlen)) { |
136 | +#endif | | 204 | +#endif |
137 | PyErr_SetString(PyExc_TypeError, "Error decoding string from buffer \n"); | | 205 | PyErr_SetString(PyExc_TypeError, "Error decoding string from buffer \n"); |
138 | return NULL; | | 206 | return NULL; |
139 | } | | 207 | } |
140 | @@ -694,8 +711,61 @@ static PyMethodDef sysctl_methods[] = { | | 208 | @@ -682,9 +704,9 @@ destroy_sysctl(PyObject *self, PyObject |
| | | 209 | } |
| | | 210 | |
| | | 211 | static PyMethodDef sysctl_methods[] = { |
| | | 212 | - { "read", read_sysctl, METH_VARARGS, |
| | | 213 | + { "read", read_sysctl, METH_VARARGS, |
| | | 214 | "read value from sysctl node." }, |
| | | 215 | - { "write", write_sysctl, METH_VARARGS, |
| | | 216 | + { "write", write_sysctl, METH_VARARGS, |
| | | 217 | "write value to sysctl node." }, |
| | | 218 | { "create", create_sysctl, METH_VARARGS, |
| | | 219 | "create a sysctl node." }, |
| | | 220 | @@ -694,8 +716,61 @@ static PyMethodDef sysctl_methods[] = { |
141 | }; | | 221 | }; |
142 | | | 222 | |
143 | | | 223 | |
144 | + | | 224 | + |
145 | +#if PY_MAJOR_VERSION >= 3 | | 225 | +#if PY_MAJOR_VERSION >= 3 |
146 | + | | 226 | + |
147 | +static int sysctl_traverse(PyObject *m, visitproc visit, void *arg) { | | 227 | +static int sysctl_traverse(PyObject *m, visitproc visit, void *arg) { |
148 | + Py_VISIT(GETSTATE(m)->error); | | 228 | + Py_VISIT(GETSTATE(m)->error); |
149 | + return 0; | | 229 | + return 0; |
150 | +} | | 230 | +} |
151 | + | | 231 | + |
152 | +static int sysctl_clear(PyObject *m) { | | 232 | +static int sysctl_clear(PyObject *m) { |
153 | + Py_CLEAR(GETSTATE(m)->error); | | 233 | + Py_CLEAR(GETSTATE(m)->error); |