ioctl.c revision 1.1.1.1.2.2 1 1.1.1.1.2.2 pgoyette /*
2 1.1.1.1.2.2 pgoyette * CDDL HEADER START
3 1.1.1.1.2.2 pgoyette *
4 1.1.1.1.2.2 pgoyette * The contents of this file are subject to the terms of the
5 1.1.1.1.2.2 pgoyette * Common Development and Distribution License (the "License").
6 1.1.1.1.2.2 pgoyette * You may not use this file except in compliance with the License.
7 1.1.1.1.2.2 pgoyette *
8 1.1.1.1.2.2 pgoyette * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 1.1.1.1.2.2 pgoyette * or http://www.opensolaris.org/os/licensing.
10 1.1.1.1.2.2 pgoyette * See the License for the specific language governing permissions
11 1.1.1.1.2.2 pgoyette * and limitations under the License.
12 1.1.1.1.2.2 pgoyette *
13 1.1.1.1.2.2 pgoyette * When distributing Covered Code, include this CDDL HEADER in each
14 1.1.1.1.2.2 pgoyette * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 1.1.1.1.2.2 pgoyette * If applicable, add the following below this CDDL HEADER, with the
16 1.1.1.1.2.2 pgoyette * fields enclosed by brackets "[]" replaced with your own identifying
17 1.1.1.1.2.2 pgoyette * information: Portions Copyright [yyyy] [name of copyright owner]
18 1.1.1.1.2.2 pgoyette *
19 1.1.1.1.2.2 pgoyette * CDDL HEADER END
20 1.1.1.1.2.2 pgoyette */
21 1.1.1.1.2.2 pgoyette /*
22 1.1.1.1.2.2 pgoyette * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 1.1.1.1.2.2 pgoyette * Use is subject to license terms.
24 1.1.1.1.2.2 pgoyette */
25 1.1.1.1.2.2 pgoyette
26 1.1.1.1.2.2 pgoyette #include <Python.h>
27 1.1.1.1.2.2 pgoyette #include <sys/zfs_ioctl.h>
28 1.1.1.1.2.2 pgoyette #include <sys/fs/zfs.h>
29 1.1.1.1.2.2 pgoyette #include <strings.h>
30 1.1.1.1.2.2 pgoyette #include <unistd.h>
31 1.1.1.1.2.2 pgoyette #include <libnvpair.h>
32 1.1.1.1.2.2 pgoyette #include <libintl.h>
33 1.1.1.1.2.2 pgoyette #include <libzfs.h>
34 1.1.1.1.2.2 pgoyette #include <libzfs_impl.h>
35 1.1.1.1.2.2 pgoyette #include "zfs_prop.h"
36 1.1.1.1.2.2 pgoyette
37 1.1.1.1.2.2 pgoyette static PyObject *ZFSError;
38 1.1.1.1.2.2 pgoyette static int zfsdevfd;
39 1.1.1.1.2.2 pgoyette
40 1.1.1.1.2.2 pgoyette #ifdef __lint
41 1.1.1.1.2.2 pgoyette #define dgettext(x, y) y
42 1.1.1.1.2.2 pgoyette #endif
43 1.1.1.1.2.2 pgoyette
44 1.1.1.1.2.2 pgoyette #define _(s) dgettext(TEXT_DOMAIN, s)
45 1.1.1.1.2.2 pgoyette
46 1.1.1.1.2.2 pgoyette /*PRINTFLIKE1*/
47 1.1.1.1.2.2 pgoyette static void
48 1.1.1.1.2.2 pgoyette seterr(char *fmt, ...)
49 1.1.1.1.2.2 pgoyette {
50 1.1.1.1.2.2 pgoyette char errstr[1024];
51 1.1.1.1.2.2 pgoyette va_list v;
52 1.1.1.1.2.2 pgoyette
53 1.1.1.1.2.2 pgoyette va_start(v, fmt);
54 1.1.1.1.2.2 pgoyette (void) vsnprintf(errstr, sizeof (errstr), fmt, v);
55 1.1.1.1.2.2 pgoyette va_end(v);
56 1.1.1.1.2.2 pgoyette
57 1.1.1.1.2.2 pgoyette PyErr_SetObject(ZFSError, Py_BuildValue("is", errno, errstr));
58 1.1.1.1.2.2 pgoyette }
59 1.1.1.1.2.2 pgoyette
60 1.1.1.1.2.2 pgoyette static char cmdstr[HIS_MAX_RECORD_LEN];
61 1.1.1.1.2.2 pgoyette
62 1.1.1.1.2.2 pgoyette static int
63 1.1.1.1.2.2 pgoyette ioctl_with_cmdstr(int ioc, zfs_cmd_t *zc)
64 1.1.1.1.2.2 pgoyette {
65 1.1.1.1.2.2 pgoyette int err;
66 1.1.1.1.2.2 pgoyette
67 1.1.1.1.2.2 pgoyette if (cmdstr[0])
68 1.1.1.1.2.2 pgoyette zc->zc_history = (uint64_t)(uintptr_t)cmdstr;
69 1.1.1.1.2.2 pgoyette err = ioctl(zfsdevfd, ioc, zc);
70 1.1.1.1.2.2 pgoyette cmdstr[0] = '\0';
71 1.1.1.1.2.2 pgoyette return (err);
72 1.1.1.1.2.2 pgoyette }
73 1.1.1.1.2.2 pgoyette
74 1.1.1.1.2.2 pgoyette static PyObject *
75 1.1.1.1.2.2 pgoyette nvl2py(nvlist_t *nvl)
76 1.1.1.1.2.2 pgoyette {
77 1.1.1.1.2.2 pgoyette PyObject *pyo;
78 1.1.1.1.2.2 pgoyette nvpair_t *nvp;
79 1.1.1.1.2.2 pgoyette
80 1.1.1.1.2.2 pgoyette pyo = PyDict_New();
81 1.1.1.1.2.2 pgoyette
82 1.1.1.1.2.2 pgoyette for (nvp = nvlist_next_nvpair(nvl, NULL); nvp;
83 1.1.1.1.2.2 pgoyette nvp = nvlist_next_nvpair(nvl, nvp)) {
84 1.1.1.1.2.2 pgoyette PyObject *pyval;
85 1.1.1.1.2.2 pgoyette char *sval;
86 1.1.1.1.2.2 pgoyette uint64_t ival;
87 1.1.1.1.2.2 pgoyette boolean_t bval;
88 1.1.1.1.2.2 pgoyette nvlist_t *nval;
89 1.1.1.1.2.2 pgoyette
90 1.1.1.1.2.2 pgoyette switch (nvpair_type(nvp)) {
91 1.1.1.1.2.2 pgoyette case DATA_TYPE_STRING:
92 1.1.1.1.2.2 pgoyette (void) nvpair_value_string(nvp, &sval);
93 1.1.1.1.2.2 pgoyette pyval = Py_BuildValue("s", sval);
94 1.1.1.1.2.2 pgoyette break;
95 1.1.1.1.2.2 pgoyette
96 1.1.1.1.2.2 pgoyette case DATA_TYPE_UINT64:
97 1.1.1.1.2.2 pgoyette (void) nvpair_value_uint64(nvp, &ival);
98 1.1.1.1.2.2 pgoyette pyval = Py_BuildValue("K", ival);
99 1.1.1.1.2.2 pgoyette break;
100 1.1.1.1.2.2 pgoyette
101 1.1.1.1.2.2 pgoyette case DATA_TYPE_NVLIST:
102 1.1.1.1.2.2 pgoyette (void) nvpair_value_nvlist(nvp, &nval);
103 1.1.1.1.2.2 pgoyette pyval = nvl2py(nval);
104 1.1.1.1.2.2 pgoyette break;
105 1.1.1.1.2.2 pgoyette
106 1.1.1.1.2.2 pgoyette case DATA_TYPE_BOOLEAN:
107 1.1.1.1.2.2 pgoyette Py_INCREF(Py_None);
108 1.1.1.1.2.2 pgoyette pyval = Py_None;
109 1.1.1.1.2.2 pgoyette break;
110 1.1.1.1.2.2 pgoyette
111 1.1.1.1.2.2 pgoyette case DATA_TYPE_BOOLEAN_VALUE:
112 1.1.1.1.2.2 pgoyette (void) nvpair_value_boolean_value(nvp, &bval);
113 1.1.1.1.2.2 pgoyette pyval = Py_BuildValue("i", bval);
114 1.1.1.1.2.2 pgoyette break;
115 1.1.1.1.2.2 pgoyette
116 1.1.1.1.2.2 pgoyette default:
117 1.1.1.1.2.2 pgoyette PyErr_SetNone(PyExc_ValueError);
118 1.1.1.1.2.2 pgoyette Py_DECREF(pyo);
119 1.1.1.1.2.2 pgoyette return (NULL);
120 1.1.1.1.2.2 pgoyette }
121 1.1.1.1.2.2 pgoyette
122 1.1.1.1.2.2 pgoyette PyDict_SetItemString(pyo, nvpair_name(nvp), pyval);
123 1.1.1.1.2.2 pgoyette Py_DECREF(pyval);
124 1.1.1.1.2.2 pgoyette }
125 1.1.1.1.2.2 pgoyette
126 1.1.1.1.2.2 pgoyette return (pyo);
127 1.1.1.1.2.2 pgoyette }
128 1.1.1.1.2.2 pgoyette
129 1.1.1.1.2.2 pgoyette static nvlist_t *
130 1.1.1.1.2.2 pgoyette dict2nvl(PyObject *d)
131 1.1.1.1.2.2 pgoyette {
132 1.1.1.1.2.2 pgoyette nvlist_t *nvl;
133 1.1.1.1.2.2 pgoyette int err;
134 1.1.1.1.2.2 pgoyette PyObject *key, *value;
135 1.1.1.1.2.2 pgoyette int pos = 0;
136 1.1.1.1.2.2 pgoyette
137 1.1.1.1.2.2 pgoyette if (!PyDict_Check(d)) {
138 1.1.1.1.2.2 pgoyette PyErr_SetObject(PyExc_ValueError, d);
139 1.1.1.1.2.2 pgoyette return (NULL);
140 1.1.1.1.2.2 pgoyette }
141 1.1.1.1.2.2 pgoyette
142 1.1.1.1.2.2 pgoyette err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
143 1.1.1.1.2.2 pgoyette assert(err == 0);
144 1.1.1.1.2.2 pgoyette
145 1.1.1.1.2.2 pgoyette while (PyDict_Next(d, &pos, &key, &value)) {
146 1.1.1.1.2.2 pgoyette char *keystr = PyString_AsString(key);
147 1.1.1.1.2.2 pgoyette if (keystr == NULL) {
148 1.1.1.1.2.2 pgoyette PyErr_SetObject(PyExc_KeyError, key);
149 1.1.1.1.2.2 pgoyette nvlist_free(nvl);
150 1.1.1.1.2.2 pgoyette return (NULL);
151 1.1.1.1.2.2 pgoyette }
152 1.1.1.1.2.2 pgoyette
153 1.1.1.1.2.2 pgoyette if (PyDict_Check(value)) {
154 1.1.1.1.2.2 pgoyette nvlist_t *valnvl = dict2nvl(value);
155 1.1.1.1.2.2 pgoyette err = nvlist_add_nvlist(nvl, keystr, valnvl);
156 1.1.1.1.2.2 pgoyette nvlist_free(valnvl);
157 1.1.1.1.2.2 pgoyette } else if (value == Py_None) {
158 1.1.1.1.2.2 pgoyette err = nvlist_add_boolean(nvl, keystr);
159 1.1.1.1.2.2 pgoyette } else if (PyString_Check(value)) {
160 1.1.1.1.2.2 pgoyette char *valstr = PyString_AsString(value);
161 1.1.1.1.2.2 pgoyette err = nvlist_add_string(nvl, keystr, valstr);
162 1.1.1.1.2.2 pgoyette } else if (PyInt_Check(value)) {
163 1.1.1.1.2.2 pgoyette uint64_t valint = PyInt_AsUnsignedLongLongMask(value);
164 1.1.1.1.2.2 pgoyette err = nvlist_add_uint64(nvl, keystr, valint);
165 1.1.1.1.2.2 pgoyette } else if (PyBool_Check(value)) {
166 1.1.1.1.2.2 pgoyette boolean_t valbool = value == Py_True ? B_TRUE : B_FALSE;
167 1.1.1.1.2.2 pgoyette err = nvlist_add_boolean_value(nvl, keystr, valbool);
168 1.1.1.1.2.2 pgoyette } else {
169 1.1.1.1.2.2 pgoyette PyErr_SetObject(PyExc_ValueError, value);
170 1.1.1.1.2.2 pgoyette nvlist_free(nvl);
171 1.1.1.1.2.2 pgoyette return (NULL);
172 1.1.1.1.2.2 pgoyette }
173 1.1.1.1.2.2 pgoyette assert(err == 0);
174 1.1.1.1.2.2 pgoyette }
175 1.1.1.1.2.2 pgoyette
176 1.1.1.1.2.2 pgoyette return (nvl);
177 1.1.1.1.2.2 pgoyette }
178 1.1.1.1.2.2 pgoyette
179 1.1.1.1.2.2 pgoyette static PyObject *
180 1.1.1.1.2.2 pgoyette fakepropval(uint64_t value)
181 1.1.1.1.2.2 pgoyette {
182 1.1.1.1.2.2 pgoyette PyObject *d = PyDict_New();
183 1.1.1.1.2.2 pgoyette PyDict_SetItemString(d, "value", Py_BuildValue("K", value));
184 1.1.1.1.2.2 pgoyette return (d);
185 1.1.1.1.2.2 pgoyette }
186 1.1.1.1.2.2 pgoyette
187 1.1.1.1.2.2 pgoyette static void
188 1.1.1.1.2.2 pgoyette add_ds_props(zfs_cmd_t *zc, PyObject *nvl)
189 1.1.1.1.2.2 pgoyette {
190 1.1.1.1.2.2 pgoyette dmu_objset_stats_t *s = &zc->zc_objset_stats;
191 1.1.1.1.2.2 pgoyette PyDict_SetItemString(nvl, "numclones",
192 1.1.1.1.2.2 pgoyette fakepropval(s->dds_num_clones));
193 1.1.1.1.2.2 pgoyette PyDict_SetItemString(nvl, "issnap",
194 1.1.1.1.2.2 pgoyette fakepropval(s->dds_is_snapshot));
195 1.1.1.1.2.2 pgoyette PyDict_SetItemString(nvl, "inconsistent",
196 1.1.1.1.2.2 pgoyette fakepropval(s->dds_inconsistent));
197 1.1.1.1.2.2 pgoyette }
198 1.1.1.1.2.2 pgoyette
199 1.1.1.1.2.2 pgoyette /* On error, returns NULL but does not set python exception. */
200 1.1.1.1.2.2 pgoyette static PyObject *
201 1.1.1.1.2.2 pgoyette ioctl_with_dstnv(int ioc, zfs_cmd_t *zc)
202 1.1.1.1.2.2 pgoyette {
203 1.1.1.1.2.2 pgoyette int nvsz = 2048;
204 1.1.1.1.2.2 pgoyette void *nvbuf;
205 1.1.1.1.2.2 pgoyette PyObject *pynv = NULL;
206 1.1.1.1.2.2 pgoyette
207 1.1.1.1.2.2 pgoyette again:
208 1.1.1.1.2.2 pgoyette nvbuf = malloc(nvsz);
209 1.1.1.1.2.2 pgoyette zc->zc_nvlist_dst_size = nvsz;
210 1.1.1.1.2.2 pgoyette zc->zc_nvlist_dst = (uintptr_t)nvbuf;
211 1.1.1.1.2.2 pgoyette
212 1.1.1.1.2.2 pgoyette if (ioctl(zfsdevfd, ioc, zc) == 0) {
213 1.1.1.1.2.2 pgoyette nvlist_t *nvl;
214 1.1.1.1.2.2 pgoyette
215 1.1.1.1.2.2 pgoyette errno = nvlist_unpack(nvbuf, zc->zc_nvlist_dst_size, &nvl, 0);
216 1.1.1.1.2.2 pgoyette if (errno == 0) {
217 1.1.1.1.2.2 pgoyette pynv = nvl2py(nvl);
218 1.1.1.1.2.2 pgoyette nvlist_free(nvl);
219 1.1.1.1.2.2 pgoyette }
220 1.1.1.1.2.2 pgoyette } else if (errno == ENOMEM) {
221 1.1.1.1.2.2 pgoyette free(nvbuf);
222 1.1.1.1.2.2 pgoyette nvsz = zc->zc_nvlist_dst_size;
223 1.1.1.1.2.2 pgoyette goto again;
224 1.1.1.1.2.2 pgoyette }
225 1.1.1.1.2.2 pgoyette free(nvbuf);
226 1.1.1.1.2.2 pgoyette return (pynv);
227 1.1.1.1.2.2 pgoyette }
228 1.1.1.1.2.2 pgoyette
229 1.1.1.1.2.2 pgoyette static PyObject *
230 1.1.1.1.2.2 pgoyette py_next_dataset(PyObject *self, PyObject *args)
231 1.1.1.1.2.2 pgoyette {
232 1.1.1.1.2.2 pgoyette int ioc;
233 1.1.1.1.2.2 pgoyette uint64_t cookie;
234 1.1.1.1.2.2 pgoyette zfs_cmd_t zc = { 0 };
235 1.1.1.1.2.2 pgoyette int snaps;
236 1.1.1.1.2.2 pgoyette char *name;
237 1.1.1.1.2.2 pgoyette PyObject *nvl;
238 1.1.1.1.2.2 pgoyette PyObject *ret = NULL;
239 1.1.1.1.2.2 pgoyette
240 1.1.1.1.2.2 pgoyette if (!PyArg_ParseTuple(args, "siK", &name, &snaps, &cookie))
241 1.1.1.1.2.2 pgoyette return (NULL);
242 1.1.1.1.2.2 pgoyette
243 1.1.1.1.2.2 pgoyette (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
244 1.1.1.1.2.2 pgoyette zc.zc_cookie = cookie;
245 1.1.1.1.2.2 pgoyette
246 1.1.1.1.2.2 pgoyette if (snaps)
247 1.1.1.1.2.2 pgoyette ioc = ZFS_IOC_SNAPSHOT_LIST_NEXT;
248 1.1.1.1.2.2 pgoyette else
249 1.1.1.1.2.2 pgoyette ioc = ZFS_IOC_DATASET_LIST_NEXT;
250 1.1.1.1.2.2 pgoyette
251 1.1.1.1.2.2 pgoyette nvl = ioctl_with_dstnv(ioc, &zc);
252 1.1.1.1.2.2 pgoyette if (nvl) {
253 1.1.1.1.2.2 pgoyette add_ds_props(&zc, nvl);
254 1.1.1.1.2.2 pgoyette ret = Py_BuildValue("sKO", zc.zc_name, zc.zc_cookie, nvl);
255 1.1.1.1.2.2 pgoyette Py_DECREF(nvl);
256 1.1.1.1.2.2 pgoyette } else if (errno == ESRCH) {
257 1.1.1.1.2.2 pgoyette PyErr_SetNone(PyExc_StopIteration);
258 1.1.1.1.2.2 pgoyette } else {
259 1.1.1.1.2.2 pgoyette if (snaps)
260 1.1.1.1.2.2 pgoyette seterr(_("cannot get snapshots of %s"), name);
261 1.1.1.1.2.2 pgoyette else
262 1.1.1.1.2.2 pgoyette seterr(_("cannot get child datasets of %s"), name);
263 1.1.1.1.2.2 pgoyette }
264 1.1.1.1.2.2 pgoyette return (ret);
265 1.1.1.1.2.2 pgoyette }
266 1.1.1.1.2.2 pgoyette
267 1.1.1.1.2.2 pgoyette static PyObject *
268 1.1.1.1.2.2 pgoyette py_dataset_props(PyObject *self, PyObject *args)
269 1.1.1.1.2.2 pgoyette {
270 1.1.1.1.2.2 pgoyette zfs_cmd_t zc = { 0 };
271 1.1.1.1.2.2 pgoyette int snaps;
272 1.1.1.1.2.2 pgoyette char *name;
273 1.1.1.1.2.2 pgoyette PyObject *nvl;
274 1.1.1.1.2.2 pgoyette
275 1.1.1.1.2.2 pgoyette if (!PyArg_ParseTuple(args, "s", &name))
276 1.1.1.1.2.2 pgoyette return (NULL);
277 1.1.1.1.2.2 pgoyette
278 1.1.1.1.2.2 pgoyette (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
279 1.1.1.1.2.2 pgoyette
280 1.1.1.1.2.2 pgoyette nvl = ioctl_with_dstnv(ZFS_IOC_OBJSET_STATS, &zc);
281 1.1.1.1.2.2 pgoyette if (nvl) {
282 1.1.1.1.2.2 pgoyette add_ds_props(&zc, nvl);
283 1.1.1.1.2.2 pgoyette } else {
284 1.1.1.1.2.2 pgoyette seterr(_("cannot access dataset %s"), name);
285 1.1.1.1.2.2 pgoyette }
286 1.1.1.1.2.2 pgoyette return (nvl);
287 1.1.1.1.2.2 pgoyette }
288 1.1.1.1.2.2 pgoyette
289 1.1.1.1.2.2 pgoyette static PyObject *
290 1.1.1.1.2.2 pgoyette py_get_fsacl(PyObject *self, PyObject *args)
291 1.1.1.1.2.2 pgoyette {
292 1.1.1.1.2.2 pgoyette zfs_cmd_t zc = { 0 };
293 1.1.1.1.2.2 pgoyette char *name;
294 1.1.1.1.2.2 pgoyette PyObject *nvl;
295 1.1.1.1.2.2 pgoyette
296 1.1.1.1.2.2 pgoyette if (!PyArg_ParseTuple(args, "s", &name))
297 1.1.1.1.2.2 pgoyette return (NULL);
298 1.1.1.1.2.2 pgoyette
299 1.1.1.1.2.2 pgoyette (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
300 1.1.1.1.2.2 pgoyette
301 1.1.1.1.2.2 pgoyette nvl = ioctl_with_dstnv(ZFS_IOC_GET_FSACL, &zc);
302 1.1.1.1.2.2 pgoyette if (nvl == NULL)
303 1.1.1.1.2.2 pgoyette seterr(_("cannot get permissions on %s"), name);
304 1.1.1.1.2.2 pgoyette
305 1.1.1.1.2.2 pgoyette return (nvl);
306 1.1.1.1.2.2 pgoyette }
307 1.1.1.1.2.2 pgoyette
308 1.1.1.1.2.2 pgoyette static PyObject *
309 1.1.1.1.2.2 pgoyette py_set_fsacl(PyObject *self, PyObject *args)
310 1.1.1.1.2.2 pgoyette {
311 1.1.1.1.2.2 pgoyette int un;
312 1.1.1.1.2.2 pgoyette size_t nvsz;
313 1.1.1.1.2.2 pgoyette zfs_cmd_t zc = { 0 };
314 1.1.1.1.2.2 pgoyette char *name, *nvbuf;
315 1.1.1.1.2.2 pgoyette PyObject *dict, *file;
316 1.1.1.1.2.2 pgoyette nvlist_t *nvl;
317 1.1.1.1.2.2 pgoyette int err;
318 1.1.1.1.2.2 pgoyette
319 1.1.1.1.2.2 pgoyette if (!PyArg_ParseTuple(args, "siO!", &name, &un,
320 1.1.1.1.2.2 pgoyette &PyDict_Type, &dict))
321 1.1.1.1.2.2 pgoyette return (NULL);
322 1.1.1.1.2.2 pgoyette
323 1.1.1.1.2.2 pgoyette nvl = dict2nvl(dict);
324 1.1.1.1.2.2 pgoyette if (nvl == NULL)
325 1.1.1.1.2.2 pgoyette return (NULL);
326 1.1.1.1.2.2 pgoyette
327 1.1.1.1.2.2 pgoyette err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE);
328 1.1.1.1.2.2 pgoyette assert(err == 0);
329 1.1.1.1.2.2 pgoyette nvbuf = malloc(nvsz);
330 1.1.1.1.2.2 pgoyette err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0);
331 1.1.1.1.2.2 pgoyette assert(err == 0);
332 1.1.1.1.2.2 pgoyette
333 1.1.1.1.2.2 pgoyette (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
334 1.1.1.1.2.2 pgoyette zc.zc_nvlist_src_size = nvsz;
335 1.1.1.1.2.2 pgoyette zc.zc_nvlist_src = (uintptr_t)nvbuf;
336 1.1.1.1.2.2 pgoyette zc.zc_perm_action = un;
337 1.1.1.1.2.2 pgoyette
338 1.1.1.1.2.2 pgoyette err = ioctl_with_cmdstr(ZFS_IOC_SET_FSACL, &zc);
339 1.1.1.1.2.2 pgoyette free(nvbuf);
340 1.1.1.1.2.2 pgoyette if (err) {
341 1.1.1.1.2.2 pgoyette seterr(_("cannot set permissions on %s"), name);
342 1.1.1.1.2.2 pgoyette return (NULL);
343 1.1.1.1.2.2 pgoyette }
344 1.1.1.1.2.2 pgoyette
345 1.1.1.1.2.2 pgoyette Py_RETURN_NONE;
346 1.1.1.1.2.2 pgoyette }
347 1.1.1.1.2.2 pgoyette
348 1.1.1.1.2.2 pgoyette static PyObject *
349 1.1.1.1.2.2 pgoyette py_get_holds(PyObject *self, PyObject *args)
350 1.1.1.1.2.2 pgoyette {
351 1.1.1.1.2.2 pgoyette zfs_cmd_t zc = { 0 };
352 1.1.1.1.2.2 pgoyette char *name;
353 1.1.1.1.2.2 pgoyette PyObject *nvl;
354 1.1.1.1.2.2 pgoyette
355 1.1.1.1.2.2 pgoyette if (!PyArg_ParseTuple(args, "s", &name))
356 1.1.1.1.2.2 pgoyette return (NULL);
357 1.1.1.1.2.2 pgoyette
358 1.1.1.1.2.2 pgoyette (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
359 1.1.1.1.2.2 pgoyette
360 1.1.1.1.2.2 pgoyette nvl = ioctl_with_dstnv(ZFS_IOC_GET_HOLDS, &zc);
361 1.1.1.1.2.2 pgoyette if (nvl == NULL)
362 1.1.1.1.2.2 pgoyette seterr(_("cannot get holds for %s"), name);
363 1.1.1.1.2.2 pgoyette
364 1.1.1.1.2.2 pgoyette return (nvl);
365 1.1.1.1.2.2 pgoyette }
366 1.1.1.1.2.2 pgoyette
367 1.1.1.1.2.2 pgoyette static PyObject *
368 1.1.1.1.2.2 pgoyette py_userspace_many(PyObject *self, PyObject *args)
369 1.1.1.1.2.2 pgoyette {
370 1.1.1.1.2.2 pgoyette zfs_cmd_t zc = { 0 };
371 1.1.1.1.2.2 pgoyette zfs_userquota_prop_t type;
372 1.1.1.1.2.2 pgoyette char *name, *propname;
373 1.1.1.1.2.2 pgoyette int bufsz = 1<<20;
374 1.1.1.1.2.2 pgoyette void *buf;
375 1.1.1.1.2.2 pgoyette PyObject *dict, *file;
376 1.1.1.1.2.2 pgoyette int error;
377 1.1.1.1.2.2 pgoyette
378 1.1.1.1.2.2 pgoyette if (!PyArg_ParseTuple(args, "ss", &name, &propname))
379 1.1.1.1.2.2 pgoyette return (NULL);
380 1.1.1.1.2.2 pgoyette
381 1.1.1.1.2.2 pgoyette for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++)
382 1.1.1.1.2.2 pgoyette if (strcmp(propname, zfs_userquota_prop_prefixes[type]) == 0)
383 1.1.1.1.2.2 pgoyette break;
384 1.1.1.1.2.2 pgoyette if (type == ZFS_NUM_USERQUOTA_PROPS) {
385 1.1.1.1.2.2 pgoyette PyErr_SetString(PyExc_KeyError, propname);
386 1.1.1.1.2.2 pgoyette return (NULL);
387 1.1.1.1.2.2 pgoyette }
388 1.1.1.1.2.2 pgoyette
389 1.1.1.1.2.2 pgoyette dict = PyDict_New();
390 1.1.1.1.2.2 pgoyette buf = malloc(bufsz);
391 1.1.1.1.2.2 pgoyette
392 1.1.1.1.2.2 pgoyette (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
393 1.1.1.1.2.2 pgoyette zc.zc_objset_type = type;
394 1.1.1.1.2.2 pgoyette zc.zc_cookie = 0;
395 1.1.1.1.2.2 pgoyette
396 1.1.1.1.2.2 pgoyette while (1) {
397 1.1.1.1.2.2 pgoyette zfs_useracct_t *zua = buf;
398 1.1.1.1.2.2 pgoyette
399 1.1.1.1.2.2 pgoyette zc.zc_nvlist_dst = (uintptr_t)buf;
400 1.1.1.1.2.2 pgoyette zc.zc_nvlist_dst_size = bufsz;
401 1.1.1.1.2.2 pgoyette
402 1.1.1.1.2.2 pgoyette error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_MANY, &zc);
403 1.1.1.1.2.2 pgoyette if (error || zc.zc_nvlist_dst_size == 0)
404 1.1.1.1.2.2 pgoyette break;
405 1.1.1.1.2.2 pgoyette
406 1.1.1.1.2.2 pgoyette while (zc.zc_nvlist_dst_size > 0) {
407 1.1.1.1.2.2 pgoyette PyObject *pykey, *pyval;
408 1.1.1.1.2.2 pgoyette
409 1.1.1.1.2.2 pgoyette pykey = Py_BuildValue("sI",
410 1.1.1.1.2.2 pgoyette zua->zu_domain, zua->zu_rid);
411 1.1.1.1.2.2 pgoyette pyval = Py_BuildValue("K", zua->zu_space);
412 1.1.1.1.2.2 pgoyette PyDict_SetItem(dict, pykey, pyval);
413 1.1.1.1.2.2 pgoyette Py_DECREF(pykey);
414 1.1.1.1.2.2 pgoyette Py_DECREF(pyval);
415 1.1.1.1.2.2 pgoyette
416 1.1.1.1.2.2 pgoyette zua++;
417 1.1.1.1.2.2 pgoyette zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t);
418 1.1.1.1.2.2 pgoyette }
419 1.1.1.1.2.2 pgoyette }
420 1.1.1.1.2.2 pgoyette
421 1.1.1.1.2.2 pgoyette free(buf);
422 1.1.1.1.2.2 pgoyette
423 1.1.1.1.2.2 pgoyette if (error != 0) {
424 1.1.1.1.2.2 pgoyette Py_DECREF(dict);
425 1.1.1.1.2.2 pgoyette seterr(_("cannot get %s property on %s"), propname, name);
426 1.1.1.1.2.2 pgoyette return (NULL);
427 1.1.1.1.2.2 pgoyette }
428 1.1.1.1.2.2 pgoyette
429 1.1.1.1.2.2 pgoyette return (dict);
430 1.1.1.1.2.2 pgoyette }
431 1.1.1.1.2.2 pgoyette
432 1.1.1.1.2.2 pgoyette static PyObject *
433 1.1.1.1.2.2 pgoyette py_userspace_upgrade(PyObject *self, PyObject *args)
434 1.1.1.1.2.2 pgoyette {
435 1.1.1.1.2.2 pgoyette zfs_cmd_t zc = { 0 };
436 1.1.1.1.2.2 pgoyette char *name;
437 1.1.1.1.2.2 pgoyette int error;
438 1.1.1.1.2.2 pgoyette
439 1.1.1.1.2.2 pgoyette if (!PyArg_ParseTuple(args, "s", &name))
440 1.1.1.1.2.2 pgoyette return (NULL);
441 1.1.1.1.2.2 pgoyette
442 1.1.1.1.2.2 pgoyette (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
443 1.1.1.1.2.2 pgoyette error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_UPGRADE, &zc);
444 1.1.1.1.2.2 pgoyette
445 1.1.1.1.2.2 pgoyette if (error != 0) {
446 1.1.1.1.2.2 pgoyette seterr(_("cannot initialize user accounting information on %s"),
447 1.1.1.1.2.2 pgoyette name);
448 1.1.1.1.2.2 pgoyette return (NULL);
449 1.1.1.1.2.2 pgoyette }
450 1.1.1.1.2.2 pgoyette
451 1.1.1.1.2.2 pgoyette Py_RETURN_NONE;
452 1.1.1.1.2.2 pgoyette }
453 1.1.1.1.2.2 pgoyette
454 1.1.1.1.2.2 pgoyette static PyObject *
455 1.1.1.1.2.2 pgoyette py_set_cmdstr(PyObject *self, PyObject *args)
456 1.1.1.1.2.2 pgoyette {
457 1.1.1.1.2.2 pgoyette char *str;
458 1.1.1.1.2.2 pgoyette
459 1.1.1.1.2.2 pgoyette if (!PyArg_ParseTuple(args, "s", &str))
460 1.1.1.1.2.2 pgoyette return (NULL);
461 1.1.1.1.2.2 pgoyette
462 1.1.1.1.2.2 pgoyette (void) strlcpy(cmdstr, str, sizeof (cmdstr));
463 1.1.1.1.2.2 pgoyette
464 1.1.1.1.2.2 pgoyette Py_RETURN_NONE;
465 1.1.1.1.2.2 pgoyette }
466 1.1.1.1.2.2 pgoyette
467 1.1.1.1.2.2 pgoyette static PyObject *
468 1.1.1.1.2.2 pgoyette py_get_proptable(PyObject *self, PyObject *args)
469 1.1.1.1.2.2 pgoyette {
470 1.1.1.1.2.2 pgoyette zprop_desc_t *t = zfs_prop_get_table();
471 1.1.1.1.2.2 pgoyette PyObject *d = PyDict_New();
472 1.1.1.1.2.2 pgoyette zfs_prop_t i;
473 1.1.1.1.2.2 pgoyette
474 1.1.1.1.2.2 pgoyette for (i = 0; i < ZFS_NUM_PROPS; i++) {
475 1.1.1.1.2.2 pgoyette zprop_desc_t *p = &t[i];
476 1.1.1.1.2.2 pgoyette PyObject *tuple;
477 1.1.1.1.2.2 pgoyette static const char *typetable[] =
478 1.1.1.1.2.2 pgoyette {"number", "string", "index"};
479 1.1.1.1.2.2 pgoyette static const char *attrtable[] =
480 1.1.1.1.2.2 pgoyette {"default", "readonly", "inherit", "onetime"};
481 1.1.1.1.2.2 pgoyette PyObject *indextable;
482 1.1.1.1.2.2 pgoyette
483 1.1.1.1.2.2 pgoyette if (p->pd_proptype == PROP_TYPE_INDEX) {
484 1.1.1.1.2.2 pgoyette const zprop_index_t *it = p->pd_table;
485 1.1.1.1.2.2 pgoyette indextable = PyDict_New();
486 1.1.1.1.2.2 pgoyette int j;
487 1.1.1.1.2.2 pgoyette for (j = 0; it[j].pi_name; j++) {
488 1.1.1.1.2.2 pgoyette PyDict_SetItemString(indextable,
489 1.1.1.1.2.2 pgoyette it[j].pi_name,
490 1.1.1.1.2.2 pgoyette Py_BuildValue("K", it[j].pi_value));
491 1.1.1.1.2.2 pgoyette }
492 1.1.1.1.2.2 pgoyette } else {
493 1.1.1.1.2.2 pgoyette Py_INCREF(Py_None);
494 1.1.1.1.2.2 pgoyette indextable = Py_None;
495 1.1.1.1.2.2 pgoyette }
496 1.1.1.1.2.2 pgoyette
497 1.1.1.1.2.2 pgoyette tuple = Py_BuildValue("sissKsissiiO",
498 1.1.1.1.2.2 pgoyette p->pd_name, p->pd_propnum, typetable[p->pd_proptype],
499 1.1.1.1.2.2 pgoyette p->pd_strdefault, p->pd_numdefault,
500 1.1.1.1.2.2 pgoyette attrtable[p->pd_attr], p->pd_types,
501 1.1.1.1.2.2 pgoyette p->pd_values, p->pd_colname,
502 1.1.1.1.2.2 pgoyette p->pd_rightalign, p->pd_visible, indextable);
503 1.1.1.1.2.2 pgoyette PyDict_SetItemString(d, p->pd_name, tuple);
504 1.1.1.1.2.2 pgoyette Py_DECREF(tuple);
505 1.1.1.1.2.2 pgoyette }
506 1.1.1.1.2.2 pgoyette
507 1.1.1.1.2.2 pgoyette return (d);
508 1.1.1.1.2.2 pgoyette }
509 1.1.1.1.2.2 pgoyette
510 1.1.1.1.2.2 pgoyette static PyMethodDef zfsmethods[] = {
511 1.1.1.1.2.2 pgoyette {"next_dataset", py_next_dataset, METH_VARARGS,
512 1.1.1.1.2.2 pgoyette "Get next child dataset or snapshot."},
513 1.1.1.1.2.2 pgoyette {"get_fsacl", py_get_fsacl, METH_VARARGS, "Get allowed permissions."},
514 1.1.1.1.2.2 pgoyette {"set_fsacl", py_set_fsacl, METH_VARARGS, "Set allowed permissions."},
515 1.1.1.1.2.2 pgoyette {"userspace_many", py_userspace_many, METH_VARARGS,
516 1.1.1.1.2.2 pgoyette "Get user space accounting."},
517 1.1.1.1.2.2 pgoyette {"userspace_upgrade", py_userspace_upgrade, METH_VARARGS,
518 1.1.1.1.2.2 pgoyette "Upgrade fs to enable user space accounting."},
519 1.1.1.1.2.2 pgoyette {"set_cmdstr", py_set_cmdstr, METH_VARARGS,
520 1.1.1.1.2.2 pgoyette "Set command string for history logging."},
521 1.1.1.1.2.2 pgoyette {"dataset_props", py_dataset_props, METH_VARARGS,
522 1.1.1.1.2.2 pgoyette "Get dataset properties."},
523 1.1.1.1.2.2 pgoyette {"get_proptable", py_get_proptable, METH_NOARGS,
524 1.1.1.1.2.2 pgoyette "Get property table."},
525 1.1.1.1.2.2 pgoyette {"get_holds", py_get_holds, METH_VARARGS, "Get user holds."},
526 1.1.1.1.2.2 pgoyette {NULL, NULL, 0, NULL}
527 1.1.1.1.2.2 pgoyette };
528 1.1.1.1.2.2 pgoyette
529 1.1.1.1.2.2 pgoyette void
530 1.1.1.1.2.2 pgoyette initioctl(void)
531 1.1.1.1.2.2 pgoyette {
532 1.1.1.1.2.2 pgoyette PyObject *zfs_ioctl = Py_InitModule("zfs.ioctl", zfsmethods);
533 1.1.1.1.2.2 pgoyette PyObject *zfs_util = PyImport_ImportModule("zfs.util");
534 1.1.1.1.2.2 pgoyette PyObject *devfile;
535 1.1.1.1.2.2 pgoyette
536 1.1.1.1.2.2 pgoyette if (zfs_util == NULL)
537 1.1.1.1.2.2 pgoyette return;
538 1.1.1.1.2.2 pgoyette
539 1.1.1.1.2.2 pgoyette ZFSError = PyObject_GetAttrString(zfs_util, "ZFSError");
540 1.1.1.1.2.2 pgoyette devfile = PyObject_GetAttrString(zfs_util, "dev");
541 1.1.1.1.2.2 pgoyette zfsdevfd = PyObject_AsFileDescriptor(devfile);
542 1.1.1.1.2.2 pgoyette
543 1.1.1.1.2.2 pgoyette zfs_prop_init();
544 1.1.1.1.2.2 pgoyette }
545