18fc25799SMartin Matuska /*
28fc25799SMartin Matuska * CDDL HEADER START
38fc25799SMartin Matuska *
48fc25799SMartin Matuska * The contents of this file are subject to the terms of the
58fc25799SMartin Matuska * Common Development and Distribution License (the "License").
68fc25799SMartin Matuska * You may not use this file except in compliance with the License.
78fc25799SMartin Matuska *
88fc25799SMartin Matuska * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98fc25799SMartin Matuska * or http://www.opensolaris.org/os/licensing.
108fc25799SMartin Matuska * See the License for the specific language governing permissions
118fc25799SMartin Matuska * and limitations under the License.
128fc25799SMartin Matuska *
138fc25799SMartin Matuska * When distributing Covered Code, include this CDDL HEADER in each
148fc25799SMartin Matuska * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158fc25799SMartin Matuska * If applicable, add the following below this CDDL HEADER, with the
168fc25799SMartin Matuska * fields enclosed by brackets "[]" replaced with your own identifying
178fc25799SMartin Matuska * information: Portions Copyright [yyyy] [name of copyright owner]
188fc25799SMartin Matuska *
198fc25799SMartin Matuska * CDDL HEADER END
208fc25799SMartin Matuska */
218fc25799SMartin Matuska /*
22*10b9d77bSPawel Jakub Dawidek * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
238fc25799SMartin Matuska * Use is subject to license terms.
248fc25799SMartin Matuska */
258fc25799SMartin Matuska
268fc25799SMartin Matuska #include <Python.h>
278fc25799SMartin Matuska #include <sys/zfs_ioctl.h>
288fc25799SMartin Matuska #include <sys/fs/zfs.h>
298fc25799SMartin Matuska #include <strings.h>
308fc25799SMartin Matuska #include <unistd.h>
318fc25799SMartin Matuska #include <libnvpair.h>
328fc25799SMartin Matuska #include <libintl.h>
338fc25799SMartin Matuska #include <libzfs.h>
344f1f4356SPawel Jakub Dawidek #include <libzfs_impl.h>
358fc25799SMartin Matuska #include "zfs_prop.h"
368fc25799SMartin Matuska
378fc25799SMartin Matuska static PyObject *ZFSError;
388fc25799SMartin Matuska static int zfsdevfd;
398fc25799SMartin Matuska
408fc25799SMartin Matuska #ifdef __lint
418fc25799SMartin Matuska #define dgettext(x, y) y
428fc25799SMartin Matuska #endif
438fc25799SMartin Matuska
448fc25799SMartin Matuska #define _(s) dgettext(TEXT_DOMAIN, s)
458fc25799SMartin Matuska
468fc25799SMartin Matuska /*PRINTFLIKE1*/
478fc25799SMartin Matuska static void
seterr(char * fmt,...)488fc25799SMartin Matuska seterr(char *fmt, ...)
498fc25799SMartin Matuska {
508fc25799SMartin Matuska char errstr[1024];
518fc25799SMartin Matuska va_list v;
528fc25799SMartin Matuska
538fc25799SMartin Matuska va_start(v, fmt);
548fc25799SMartin Matuska (void) vsnprintf(errstr, sizeof (errstr), fmt, v);
558fc25799SMartin Matuska va_end(v);
568fc25799SMartin Matuska
578fc25799SMartin Matuska PyErr_SetObject(ZFSError, Py_BuildValue("is", errno, errstr));
588fc25799SMartin Matuska }
598fc25799SMartin Matuska
608fc25799SMartin Matuska static char cmdstr[HIS_MAX_RECORD_LEN];
618fc25799SMartin Matuska
628fc25799SMartin Matuska static int
ioctl_with_cmdstr(int ioc,zfs_cmd_t * zc)63*10b9d77bSPawel Jakub Dawidek ioctl_with_cmdstr(int ioc, zfs_cmd_t *zc)
648fc25799SMartin Matuska {
658fc25799SMartin Matuska int err;
668fc25799SMartin Matuska
678fc25799SMartin Matuska if (cmdstr[0])
688fc25799SMartin Matuska zc->zc_history = (uint64_t)(uintptr_t)cmdstr;
698fc25799SMartin Matuska err = ioctl(zfsdevfd, ioc, zc);
708fc25799SMartin Matuska cmdstr[0] = '\0';
718fc25799SMartin Matuska return (err);
728fc25799SMartin Matuska }
738fc25799SMartin Matuska
748fc25799SMartin Matuska static PyObject *
nvl2py(nvlist_t * nvl)758fc25799SMartin Matuska nvl2py(nvlist_t *nvl)
768fc25799SMartin Matuska {
778fc25799SMartin Matuska PyObject *pyo;
788fc25799SMartin Matuska nvpair_t *nvp;
798fc25799SMartin Matuska
808fc25799SMartin Matuska pyo = PyDict_New();
818fc25799SMartin Matuska
828fc25799SMartin Matuska for (nvp = nvlist_next_nvpair(nvl, NULL); nvp;
838fc25799SMartin Matuska nvp = nvlist_next_nvpair(nvl, nvp)) {
848fc25799SMartin Matuska PyObject *pyval;
858fc25799SMartin Matuska char *sval;
868fc25799SMartin Matuska uint64_t ival;
878fc25799SMartin Matuska boolean_t bval;
888fc25799SMartin Matuska nvlist_t *nval;
898fc25799SMartin Matuska
908fc25799SMartin Matuska switch (nvpair_type(nvp)) {
918fc25799SMartin Matuska case DATA_TYPE_STRING:
928fc25799SMartin Matuska (void) nvpair_value_string(nvp, &sval);
938fc25799SMartin Matuska pyval = Py_BuildValue("s", sval);
948fc25799SMartin Matuska break;
958fc25799SMartin Matuska
968fc25799SMartin Matuska case DATA_TYPE_UINT64:
978fc25799SMartin Matuska (void) nvpair_value_uint64(nvp, &ival);
988fc25799SMartin Matuska pyval = Py_BuildValue("K", ival);
998fc25799SMartin Matuska break;
1008fc25799SMartin Matuska
1018fc25799SMartin Matuska case DATA_TYPE_NVLIST:
1028fc25799SMartin Matuska (void) nvpair_value_nvlist(nvp, &nval);
1038fc25799SMartin Matuska pyval = nvl2py(nval);
1048fc25799SMartin Matuska break;
1058fc25799SMartin Matuska
1068fc25799SMartin Matuska case DATA_TYPE_BOOLEAN:
1078fc25799SMartin Matuska Py_INCREF(Py_None);
1088fc25799SMartin Matuska pyval = Py_None;
1098fc25799SMartin Matuska break;
1108fc25799SMartin Matuska
1118fc25799SMartin Matuska case DATA_TYPE_BOOLEAN_VALUE:
1128fc25799SMartin Matuska (void) nvpair_value_boolean_value(nvp, &bval);
1138fc25799SMartin Matuska pyval = Py_BuildValue("i", bval);
1148fc25799SMartin Matuska break;
1158fc25799SMartin Matuska
1168fc25799SMartin Matuska default:
1178fc25799SMartin Matuska PyErr_SetNone(PyExc_ValueError);
1188fc25799SMartin Matuska Py_DECREF(pyo);
1198fc25799SMartin Matuska return (NULL);
1208fc25799SMartin Matuska }
1218fc25799SMartin Matuska
1228fc25799SMartin Matuska PyDict_SetItemString(pyo, nvpair_name(nvp), pyval);
1238fc25799SMartin Matuska Py_DECREF(pyval);
1248fc25799SMartin Matuska }
1258fc25799SMartin Matuska
1268fc25799SMartin Matuska return (pyo);
1278fc25799SMartin Matuska }
1288fc25799SMartin Matuska
1298fc25799SMartin Matuska static nvlist_t *
dict2nvl(PyObject * d)1308fc25799SMartin Matuska dict2nvl(PyObject *d)
1318fc25799SMartin Matuska {
1328fc25799SMartin Matuska nvlist_t *nvl;
1338fc25799SMartin Matuska int err;
1348fc25799SMartin Matuska PyObject *key, *value;
135*10b9d77bSPawel Jakub Dawidek int pos = 0;
1368fc25799SMartin Matuska
1378fc25799SMartin Matuska if (!PyDict_Check(d)) {
1388fc25799SMartin Matuska PyErr_SetObject(PyExc_ValueError, d);
1398fc25799SMartin Matuska return (NULL);
1408fc25799SMartin Matuska }
1418fc25799SMartin Matuska
1428fc25799SMartin Matuska err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
1438fc25799SMartin Matuska assert(err == 0);
1448fc25799SMartin Matuska
1458fc25799SMartin Matuska while (PyDict_Next(d, &pos, &key, &value)) {
1468fc25799SMartin Matuska char *keystr = PyString_AsString(key);
1478fc25799SMartin Matuska if (keystr == NULL) {
1488fc25799SMartin Matuska PyErr_SetObject(PyExc_KeyError, key);
1498fc25799SMartin Matuska nvlist_free(nvl);
1508fc25799SMartin Matuska return (NULL);
1518fc25799SMartin Matuska }
1528fc25799SMartin Matuska
1538fc25799SMartin Matuska if (PyDict_Check(value)) {
1548fc25799SMartin Matuska nvlist_t *valnvl = dict2nvl(value);
1558fc25799SMartin Matuska err = nvlist_add_nvlist(nvl, keystr, valnvl);
1568fc25799SMartin Matuska nvlist_free(valnvl);
1578fc25799SMartin Matuska } else if (value == Py_None) {
1588fc25799SMartin Matuska err = nvlist_add_boolean(nvl, keystr);
1598fc25799SMartin Matuska } else if (PyString_Check(value)) {
1608fc25799SMartin Matuska char *valstr = PyString_AsString(value);
1618fc25799SMartin Matuska err = nvlist_add_string(nvl, keystr, valstr);
1628fc25799SMartin Matuska } else if (PyInt_Check(value)) {
1638fc25799SMartin Matuska uint64_t valint = PyInt_AsUnsignedLongLongMask(value);
1648fc25799SMartin Matuska err = nvlist_add_uint64(nvl, keystr, valint);
1658fc25799SMartin Matuska } else if (PyBool_Check(value)) {
1668fc25799SMartin Matuska boolean_t valbool = value == Py_True ? B_TRUE : B_FALSE;
1678fc25799SMartin Matuska err = nvlist_add_boolean_value(nvl, keystr, valbool);
1688fc25799SMartin Matuska } else {
1698fc25799SMartin Matuska PyErr_SetObject(PyExc_ValueError, value);
1708fc25799SMartin Matuska nvlist_free(nvl);
1718fc25799SMartin Matuska return (NULL);
1728fc25799SMartin Matuska }
1738fc25799SMartin Matuska assert(err == 0);
1748fc25799SMartin Matuska }
1758fc25799SMartin Matuska
1768fc25799SMartin Matuska return (nvl);
1778fc25799SMartin Matuska }
1788fc25799SMartin Matuska
1798fc25799SMartin Matuska static PyObject *
fakepropval(uint64_t value)1808fc25799SMartin Matuska fakepropval(uint64_t value)
1818fc25799SMartin Matuska {
1828fc25799SMartin Matuska PyObject *d = PyDict_New();
1838fc25799SMartin Matuska PyDict_SetItemString(d, "value", Py_BuildValue("K", value));
1848fc25799SMartin Matuska return (d);
1858fc25799SMartin Matuska }
1868fc25799SMartin Matuska
1878fc25799SMartin Matuska static void
add_ds_props(zfs_cmd_t * zc,PyObject * nvl)1888fc25799SMartin Matuska add_ds_props(zfs_cmd_t *zc, PyObject *nvl)
1898fc25799SMartin Matuska {
1908fc25799SMartin Matuska dmu_objset_stats_t *s = &zc->zc_objset_stats;
1918fc25799SMartin Matuska PyDict_SetItemString(nvl, "numclones",
1928fc25799SMartin Matuska fakepropval(s->dds_num_clones));
1938fc25799SMartin Matuska PyDict_SetItemString(nvl, "issnap",
1948fc25799SMartin Matuska fakepropval(s->dds_is_snapshot));
1958fc25799SMartin Matuska PyDict_SetItemString(nvl, "inconsistent",
1968fc25799SMartin Matuska fakepropval(s->dds_inconsistent));
1978fc25799SMartin Matuska }
1988fc25799SMartin Matuska
1998fc25799SMartin Matuska /* On error, returns NULL but does not set python exception. */
2008fc25799SMartin Matuska static PyObject *
ioctl_with_dstnv(int ioc,zfs_cmd_t * zc)201*10b9d77bSPawel Jakub Dawidek ioctl_with_dstnv(int ioc, zfs_cmd_t *zc)
2028fc25799SMartin Matuska {
2038fc25799SMartin Matuska int nvsz = 2048;
2048fc25799SMartin Matuska void *nvbuf;
2058fc25799SMartin Matuska PyObject *pynv = NULL;
2068fc25799SMartin Matuska
2078fc25799SMartin Matuska again:
2088fc25799SMartin Matuska nvbuf = malloc(nvsz);
2098fc25799SMartin Matuska zc->zc_nvlist_dst_size = nvsz;
2108fc25799SMartin Matuska zc->zc_nvlist_dst = (uintptr_t)nvbuf;
2118fc25799SMartin Matuska
2128fc25799SMartin Matuska if (ioctl(zfsdevfd, ioc, zc) == 0) {
2138fc25799SMartin Matuska nvlist_t *nvl;
2148fc25799SMartin Matuska
2158fc25799SMartin Matuska errno = nvlist_unpack(nvbuf, zc->zc_nvlist_dst_size, &nvl, 0);
2168fc25799SMartin Matuska if (errno == 0) {
2178fc25799SMartin Matuska pynv = nvl2py(nvl);
2188fc25799SMartin Matuska nvlist_free(nvl);
2198fc25799SMartin Matuska }
2208fc25799SMartin Matuska } else if (errno == ENOMEM) {
2218fc25799SMartin Matuska free(nvbuf);
2228fc25799SMartin Matuska nvsz = zc->zc_nvlist_dst_size;
2238fc25799SMartin Matuska goto again;
2248fc25799SMartin Matuska }
2258fc25799SMartin Matuska free(nvbuf);
2268fc25799SMartin Matuska return (pynv);
2278fc25799SMartin Matuska }
2288fc25799SMartin Matuska
2298fc25799SMartin Matuska static PyObject *
py_next_dataset(PyObject * self,PyObject * args)2308fc25799SMartin Matuska py_next_dataset(PyObject *self, PyObject *args)
2318fc25799SMartin Matuska {
232*10b9d77bSPawel Jakub Dawidek int ioc;
2338fc25799SMartin Matuska uint64_t cookie;
2348fc25799SMartin Matuska zfs_cmd_t zc = { 0 };
2358fc25799SMartin Matuska int snaps;
2368fc25799SMartin Matuska char *name;
2378fc25799SMartin Matuska PyObject *nvl;
2388fc25799SMartin Matuska PyObject *ret = NULL;
2398fc25799SMartin Matuska
2408fc25799SMartin Matuska if (!PyArg_ParseTuple(args, "siK", &name, &snaps, &cookie))
2418fc25799SMartin Matuska return (NULL);
2428fc25799SMartin Matuska
2438fc25799SMartin Matuska (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
2448fc25799SMartin Matuska zc.zc_cookie = cookie;
2458fc25799SMartin Matuska
2468fc25799SMartin Matuska if (snaps)
2478fc25799SMartin Matuska ioc = ZFS_IOC_SNAPSHOT_LIST_NEXT;
2488fc25799SMartin Matuska else
2498fc25799SMartin Matuska ioc = ZFS_IOC_DATASET_LIST_NEXT;
2508fc25799SMartin Matuska
2518fc25799SMartin Matuska nvl = ioctl_with_dstnv(ioc, &zc);
2528fc25799SMartin Matuska if (nvl) {
2538fc25799SMartin Matuska add_ds_props(&zc, nvl);
2548fc25799SMartin Matuska ret = Py_BuildValue("sKO", zc.zc_name, zc.zc_cookie, nvl);
2558fc25799SMartin Matuska Py_DECREF(nvl);
2568fc25799SMartin Matuska } else if (errno == ESRCH) {
2578fc25799SMartin Matuska PyErr_SetNone(PyExc_StopIteration);
2588fc25799SMartin Matuska } else {
2598fc25799SMartin Matuska if (snaps)
2608fc25799SMartin Matuska seterr(_("cannot get snapshots of %s"), name);
2618fc25799SMartin Matuska else
2628fc25799SMartin Matuska seterr(_("cannot get child datasets of %s"), name);
2638fc25799SMartin Matuska }
2648fc25799SMartin Matuska return (ret);
2658fc25799SMartin Matuska }
2668fc25799SMartin Matuska
2678fc25799SMartin Matuska static PyObject *
py_dataset_props(PyObject * self,PyObject * args)2688fc25799SMartin Matuska py_dataset_props(PyObject *self, PyObject *args)
2698fc25799SMartin Matuska {
2708fc25799SMartin Matuska zfs_cmd_t zc = { 0 };
2718fc25799SMartin Matuska int snaps;
2728fc25799SMartin Matuska char *name;
2738fc25799SMartin Matuska PyObject *nvl;
2748fc25799SMartin Matuska
2758fc25799SMartin Matuska if (!PyArg_ParseTuple(args, "s", &name))
2768fc25799SMartin Matuska return (NULL);
2778fc25799SMartin Matuska
2788fc25799SMartin Matuska (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
2798fc25799SMartin Matuska
2808fc25799SMartin Matuska nvl = ioctl_with_dstnv(ZFS_IOC_OBJSET_STATS, &zc);
2818fc25799SMartin Matuska if (nvl) {
2828fc25799SMartin Matuska add_ds_props(&zc, nvl);
2838fc25799SMartin Matuska } else {
2848fc25799SMartin Matuska seterr(_("cannot access dataset %s"), name);
2858fc25799SMartin Matuska }
2868fc25799SMartin Matuska return (nvl);
2878fc25799SMartin Matuska }
2888fc25799SMartin Matuska
2898fc25799SMartin Matuska static PyObject *
py_get_fsacl(PyObject * self,PyObject * args)2908fc25799SMartin Matuska py_get_fsacl(PyObject *self, PyObject *args)
2918fc25799SMartin Matuska {
2928fc25799SMartin Matuska zfs_cmd_t zc = { 0 };
2938fc25799SMartin Matuska char *name;
2948fc25799SMartin Matuska PyObject *nvl;
2958fc25799SMartin Matuska
2968fc25799SMartin Matuska if (!PyArg_ParseTuple(args, "s", &name))
2978fc25799SMartin Matuska return (NULL);
2988fc25799SMartin Matuska
2998fc25799SMartin Matuska (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
3008fc25799SMartin Matuska
3018fc25799SMartin Matuska nvl = ioctl_with_dstnv(ZFS_IOC_GET_FSACL, &zc);
3028fc25799SMartin Matuska if (nvl == NULL)
3038fc25799SMartin Matuska seterr(_("cannot get permissions on %s"), name);
3048fc25799SMartin Matuska
3058fc25799SMartin Matuska return (nvl);
3068fc25799SMartin Matuska }
3078fc25799SMartin Matuska
3088fc25799SMartin Matuska static PyObject *
py_set_fsacl(PyObject * self,PyObject * args)3098fc25799SMartin Matuska py_set_fsacl(PyObject *self, PyObject *args)
3108fc25799SMartin Matuska {
3118fc25799SMartin Matuska int un;
3128fc25799SMartin Matuska size_t nvsz;
3138fc25799SMartin Matuska zfs_cmd_t zc = { 0 };
3148fc25799SMartin Matuska char *name, *nvbuf;
3158fc25799SMartin Matuska PyObject *dict, *file;
3168fc25799SMartin Matuska nvlist_t *nvl;
3178fc25799SMartin Matuska int err;
3188fc25799SMartin Matuska
3198fc25799SMartin Matuska if (!PyArg_ParseTuple(args, "siO!", &name, &un,
3208fc25799SMartin Matuska &PyDict_Type, &dict))
3218fc25799SMartin Matuska return (NULL);
3228fc25799SMartin Matuska
3238fc25799SMartin Matuska nvl = dict2nvl(dict);
3248fc25799SMartin Matuska if (nvl == NULL)
3258fc25799SMartin Matuska return (NULL);
3268fc25799SMartin Matuska
3278fc25799SMartin Matuska err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE);
3288fc25799SMartin Matuska assert(err == 0);
3298fc25799SMartin Matuska nvbuf = malloc(nvsz);
3308fc25799SMartin Matuska err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0);
3318fc25799SMartin Matuska assert(err == 0);
3328fc25799SMartin Matuska
3338fc25799SMartin Matuska (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
3348fc25799SMartin Matuska zc.zc_nvlist_src_size = nvsz;
3358fc25799SMartin Matuska zc.zc_nvlist_src = (uintptr_t)nvbuf;
3368fc25799SMartin Matuska zc.zc_perm_action = un;
3378fc25799SMartin Matuska
3388fc25799SMartin Matuska err = ioctl_with_cmdstr(ZFS_IOC_SET_FSACL, &zc);
3398fc25799SMartin Matuska free(nvbuf);
3408fc25799SMartin Matuska if (err) {
3418fc25799SMartin Matuska seterr(_("cannot set permissions on %s"), name);
3428fc25799SMartin Matuska return (NULL);
3438fc25799SMartin Matuska }
3448fc25799SMartin Matuska
3458fc25799SMartin Matuska Py_RETURN_NONE;
3468fc25799SMartin Matuska }
3478fc25799SMartin Matuska
3488fc25799SMartin Matuska static PyObject *
py_get_holds(PyObject * self,PyObject * args)349*10b9d77bSPawel Jakub Dawidek py_get_holds(PyObject *self, PyObject *args)
350*10b9d77bSPawel Jakub Dawidek {
351*10b9d77bSPawel Jakub Dawidek zfs_cmd_t zc = { 0 };
352*10b9d77bSPawel Jakub Dawidek char *name;
353*10b9d77bSPawel Jakub Dawidek PyObject *nvl;
354*10b9d77bSPawel Jakub Dawidek
355*10b9d77bSPawel Jakub Dawidek if (!PyArg_ParseTuple(args, "s", &name))
356*10b9d77bSPawel Jakub Dawidek return (NULL);
357*10b9d77bSPawel Jakub Dawidek
358*10b9d77bSPawel Jakub Dawidek (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
359*10b9d77bSPawel Jakub Dawidek
360*10b9d77bSPawel Jakub Dawidek nvl = ioctl_with_dstnv(ZFS_IOC_GET_HOLDS, &zc);
361*10b9d77bSPawel Jakub Dawidek if (nvl == NULL)
362*10b9d77bSPawel Jakub Dawidek seterr(_("cannot get holds for %s"), name);
363*10b9d77bSPawel Jakub Dawidek
364*10b9d77bSPawel Jakub Dawidek return (nvl);
365*10b9d77bSPawel Jakub Dawidek }
366*10b9d77bSPawel Jakub Dawidek
367*10b9d77bSPawel Jakub Dawidek static PyObject *
py_userspace_many(PyObject * self,PyObject * args)3688fc25799SMartin Matuska py_userspace_many(PyObject *self, PyObject *args)
3698fc25799SMartin Matuska {
3708fc25799SMartin Matuska zfs_cmd_t zc = { 0 };
3718fc25799SMartin Matuska zfs_userquota_prop_t type;
3728fc25799SMartin Matuska char *name, *propname;
3738fc25799SMartin Matuska int bufsz = 1<<20;
3748fc25799SMartin Matuska void *buf;
3758fc25799SMartin Matuska PyObject *dict, *file;
3768fc25799SMartin Matuska int error;
3778fc25799SMartin Matuska
3788fc25799SMartin Matuska if (!PyArg_ParseTuple(args, "ss", &name, &propname))
3798fc25799SMartin Matuska return (NULL);
3808fc25799SMartin Matuska
3818fc25799SMartin Matuska for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++)
3828fc25799SMartin Matuska if (strcmp(propname, zfs_userquota_prop_prefixes[type]) == 0)
3838fc25799SMartin Matuska break;
3848fc25799SMartin Matuska if (type == ZFS_NUM_USERQUOTA_PROPS) {
3858fc25799SMartin Matuska PyErr_SetString(PyExc_KeyError, propname);
3868fc25799SMartin Matuska return (NULL);
3878fc25799SMartin Matuska }
3888fc25799SMartin Matuska
3898fc25799SMartin Matuska dict = PyDict_New();
3908fc25799SMartin Matuska buf = malloc(bufsz);
3918fc25799SMartin Matuska
3928fc25799SMartin Matuska (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
3938fc25799SMartin Matuska zc.zc_objset_type = type;
3948fc25799SMartin Matuska zc.zc_cookie = 0;
3958fc25799SMartin Matuska
3968fc25799SMartin Matuska while (1) {
3978fc25799SMartin Matuska zfs_useracct_t *zua = buf;
3988fc25799SMartin Matuska
3998fc25799SMartin Matuska zc.zc_nvlist_dst = (uintptr_t)buf;
4008fc25799SMartin Matuska zc.zc_nvlist_dst_size = bufsz;
4018fc25799SMartin Matuska
4028fc25799SMartin Matuska error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_MANY, &zc);
4038fc25799SMartin Matuska if (error || zc.zc_nvlist_dst_size == 0)
4048fc25799SMartin Matuska break;
4058fc25799SMartin Matuska
4068fc25799SMartin Matuska while (zc.zc_nvlist_dst_size > 0) {
4078fc25799SMartin Matuska PyObject *pykey, *pyval;
4088fc25799SMartin Matuska
4098fc25799SMartin Matuska pykey = Py_BuildValue("sI",
4108fc25799SMartin Matuska zua->zu_domain, zua->zu_rid);
4118fc25799SMartin Matuska pyval = Py_BuildValue("K", zua->zu_space);
4128fc25799SMartin Matuska PyDict_SetItem(dict, pykey, pyval);
4138fc25799SMartin Matuska Py_DECREF(pykey);
4148fc25799SMartin Matuska Py_DECREF(pyval);
4158fc25799SMartin Matuska
4168fc25799SMartin Matuska zua++;
4178fc25799SMartin Matuska zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t);
4188fc25799SMartin Matuska }
4198fc25799SMartin Matuska }
4208fc25799SMartin Matuska
4218fc25799SMartin Matuska free(buf);
4228fc25799SMartin Matuska
4238fc25799SMartin Matuska if (error != 0) {
4248fc25799SMartin Matuska Py_DECREF(dict);
4258fc25799SMartin Matuska seterr(_("cannot get %s property on %s"), propname, name);
4268fc25799SMartin Matuska return (NULL);
4278fc25799SMartin Matuska }
4288fc25799SMartin Matuska
4298fc25799SMartin Matuska return (dict);
4308fc25799SMartin Matuska }
4318fc25799SMartin Matuska
4328fc25799SMartin Matuska static PyObject *
py_userspace_upgrade(PyObject * self,PyObject * args)4338fc25799SMartin Matuska py_userspace_upgrade(PyObject *self, PyObject *args)
4348fc25799SMartin Matuska {
4358fc25799SMartin Matuska zfs_cmd_t zc = { 0 };
4368fc25799SMartin Matuska char *name;
4378fc25799SMartin Matuska int error;
4388fc25799SMartin Matuska
4398fc25799SMartin Matuska if (!PyArg_ParseTuple(args, "s", &name))
4408fc25799SMartin Matuska return (NULL);
4418fc25799SMartin Matuska
4428fc25799SMartin Matuska (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
4438fc25799SMartin Matuska error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_UPGRADE, &zc);
4448fc25799SMartin Matuska
4458fc25799SMartin Matuska if (error != 0) {
4468fc25799SMartin Matuska seterr(_("cannot initialize user accounting information on %s"),
4478fc25799SMartin Matuska name);
4488fc25799SMartin Matuska return (NULL);
4498fc25799SMartin Matuska }
4508fc25799SMartin Matuska
4518fc25799SMartin Matuska Py_RETURN_NONE;
4528fc25799SMartin Matuska }
4538fc25799SMartin Matuska
4548fc25799SMartin Matuska static PyObject *
py_set_cmdstr(PyObject * self,PyObject * args)4558fc25799SMartin Matuska py_set_cmdstr(PyObject *self, PyObject *args)
4568fc25799SMartin Matuska {
4578fc25799SMartin Matuska char *str;
4588fc25799SMartin Matuska
4598fc25799SMartin Matuska if (!PyArg_ParseTuple(args, "s", &str))
4608fc25799SMartin Matuska return (NULL);
4618fc25799SMartin Matuska
4628fc25799SMartin Matuska (void) strlcpy(cmdstr, str, sizeof (cmdstr));
4638fc25799SMartin Matuska
4648fc25799SMartin Matuska Py_RETURN_NONE;
4658fc25799SMartin Matuska }
4668fc25799SMartin Matuska
4678fc25799SMartin Matuska static PyObject *
py_get_proptable(PyObject * self,PyObject * args)4688fc25799SMartin Matuska py_get_proptable(PyObject *self, PyObject *args)
4698fc25799SMartin Matuska {
4708fc25799SMartin Matuska zprop_desc_t *t = zfs_prop_get_table();
4718fc25799SMartin Matuska PyObject *d = PyDict_New();
4728fc25799SMartin Matuska zfs_prop_t i;
4738fc25799SMartin Matuska
4748fc25799SMartin Matuska for (i = 0; i < ZFS_NUM_PROPS; i++) {
4758fc25799SMartin Matuska zprop_desc_t *p = &t[i];
4768fc25799SMartin Matuska PyObject *tuple;
4778fc25799SMartin Matuska static const char *typetable[] =
4788fc25799SMartin Matuska {"number", "string", "index"};
4798fc25799SMartin Matuska static const char *attrtable[] =
4808fc25799SMartin Matuska {"default", "readonly", "inherit", "onetime"};
4818fc25799SMartin Matuska PyObject *indextable;
4828fc25799SMartin Matuska
4838fc25799SMartin Matuska if (p->pd_proptype == PROP_TYPE_INDEX) {
4848fc25799SMartin Matuska const zprop_index_t *it = p->pd_table;
4858fc25799SMartin Matuska indextable = PyDict_New();
4868fc25799SMartin Matuska int j;
4878fc25799SMartin Matuska for (j = 0; it[j].pi_name; j++) {
4888fc25799SMartin Matuska PyDict_SetItemString(indextable,
4898fc25799SMartin Matuska it[j].pi_name,
4908fc25799SMartin Matuska Py_BuildValue("K", it[j].pi_value));
4918fc25799SMartin Matuska }
4928fc25799SMartin Matuska } else {
4938fc25799SMartin Matuska Py_INCREF(Py_None);
4948fc25799SMartin Matuska indextable = Py_None;
4958fc25799SMartin Matuska }
4968fc25799SMartin Matuska
4978fc25799SMartin Matuska tuple = Py_BuildValue("sissKsissiiO",
4988fc25799SMartin Matuska p->pd_name, p->pd_propnum, typetable[p->pd_proptype],
4998fc25799SMartin Matuska p->pd_strdefault, p->pd_numdefault,
5008fc25799SMartin Matuska attrtable[p->pd_attr], p->pd_types,
5018fc25799SMartin Matuska p->pd_values, p->pd_colname,
5028fc25799SMartin Matuska p->pd_rightalign, p->pd_visible, indextable);
5038fc25799SMartin Matuska PyDict_SetItemString(d, p->pd_name, tuple);
5048fc25799SMartin Matuska Py_DECREF(tuple);
5058fc25799SMartin Matuska }
5068fc25799SMartin Matuska
5078fc25799SMartin Matuska return (d);
5088fc25799SMartin Matuska }
5098fc25799SMartin Matuska
5108fc25799SMartin Matuska static PyMethodDef zfsmethods[] = {
5118fc25799SMartin Matuska {"next_dataset", py_next_dataset, METH_VARARGS,
5128fc25799SMartin Matuska "Get next child dataset or snapshot."},
5138fc25799SMartin Matuska {"get_fsacl", py_get_fsacl, METH_VARARGS, "Get allowed permissions."},
5148fc25799SMartin Matuska {"set_fsacl", py_set_fsacl, METH_VARARGS, "Set allowed permissions."},
5158fc25799SMartin Matuska {"userspace_many", py_userspace_many, METH_VARARGS,
5168fc25799SMartin Matuska "Get user space accounting."},
5178fc25799SMartin Matuska {"userspace_upgrade", py_userspace_upgrade, METH_VARARGS,
5188fc25799SMartin Matuska "Upgrade fs to enable user space accounting."},
5198fc25799SMartin Matuska {"set_cmdstr", py_set_cmdstr, METH_VARARGS,
5208fc25799SMartin Matuska "Set command string for history logging."},
5218fc25799SMartin Matuska {"dataset_props", py_dataset_props, METH_VARARGS,
5228fc25799SMartin Matuska "Get dataset properties."},
5238fc25799SMartin Matuska {"get_proptable", py_get_proptable, METH_NOARGS,
5248fc25799SMartin Matuska "Get property table."},
525*10b9d77bSPawel Jakub Dawidek {"get_holds", py_get_holds, METH_VARARGS, "Get user holds."},
5268fc25799SMartin Matuska {NULL, NULL, 0, NULL}
5278fc25799SMartin Matuska };
5288fc25799SMartin Matuska
5298fc25799SMartin Matuska void
initioctl(void)5308fc25799SMartin Matuska initioctl(void)
5318fc25799SMartin Matuska {
5328fc25799SMartin Matuska PyObject *zfs_ioctl = Py_InitModule("zfs.ioctl", zfsmethods);
5338fc25799SMartin Matuska PyObject *zfs_util = PyImport_ImportModule("zfs.util");
5348fc25799SMartin Matuska PyObject *devfile;
5358fc25799SMartin Matuska
5368fc25799SMartin Matuska if (zfs_util == NULL)
5378fc25799SMartin Matuska return;
5388fc25799SMartin Matuska
5398fc25799SMartin Matuska ZFSError = PyObject_GetAttrString(zfs_util, "ZFSError");
5408fc25799SMartin Matuska devfile = PyObject_GetAttrString(zfs_util, "dev");
5418fc25799SMartin Matuska zfsdevfd = PyObject_AsFileDescriptor(devfile);
5428fc25799SMartin Matuska
5438fc25799SMartin Matuska zfs_prop_init();
5448fc25799SMartin Matuska }
545