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