114843421SMatthew Ahrens /* 214843421SMatthew Ahrens * CDDL HEADER START 314843421SMatthew Ahrens * 414843421SMatthew Ahrens * The contents of this file are subject to the terms of the 514843421SMatthew Ahrens * Common Development and Distribution License (the "License"). 614843421SMatthew Ahrens * You may not use this file except in compliance with the License. 714843421SMatthew Ahrens * 814843421SMatthew Ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 914843421SMatthew Ahrens * or http://www.opensolaris.org/os/licensing. 1014843421SMatthew Ahrens * See the License for the specific language governing permissions 1114843421SMatthew Ahrens * and limitations under the License. 1214843421SMatthew Ahrens * 1314843421SMatthew Ahrens * When distributing Covered Code, include this CDDL HEADER in each 1414843421SMatthew Ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1514843421SMatthew Ahrens * If applicable, add the following below this CDDL HEADER, with the 1614843421SMatthew Ahrens * fields enclosed by brackets "[]" replaced with your own identifying 1714843421SMatthew Ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 1814843421SMatthew Ahrens * 1914843421SMatthew Ahrens * CDDL HEADER END 2014843421SMatthew Ahrens */ 2114843421SMatthew Ahrens /* 22e4d060fbSSam Falkner * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2314843421SMatthew Ahrens * Use is subject to license terms. 24*e8921a52SAndy Fiddaman * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. 2514843421SMatthew Ahrens */ 2614843421SMatthew Ahrens 2714843421SMatthew Ahrens #include <Python.h> 2814843421SMatthew Ahrens #include <sys/zfs_ioctl.h> 2914843421SMatthew Ahrens #include <sys/fs/zfs.h> 3014843421SMatthew Ahrens #include <strings.h> 3114843421SMatthew Ahrens #include <unistd.h> 3214843421SMatthew Ahrens #include <libnvpair.h> 3314843421SMatthew Ahrens #include <libintl.h> 3414843421SMatthew Ahrens #include <libzfs.h> 3514843421SMatthew Ahrens #include "zfs_prop.h" 3614843421SMatthew Ahrens 3714843421SMatthew Ahrens static PyObject *ZFSError; 3814843421SMatthew Ahrens static int zfsdevfd; 3914843421SMatthew Ahrens 4014843421SMatthew Ahrens #ifdef __lint 4114843421SMatthew Ahrens #define dgettext(x, y) y 4214843421SMatthew Ahrens #endif 4314843421SMatthew Ahrens 4414843421SMatthew Ahrens #define _(s) dgettext(TEXT_DOMAIN, s) 4514843421SMatthew Ahrens 4614843421SMatthew Ahrens /*PRINTFLIKE1*/ 4714843421SMatthew Ahrens static void 4814843421SMatthew Ahrens seterr(char *fmt, ...) 4914843421SMatthew Ahrens { 5014843421SMatthew Ahrens char errstr[1024]; 5114843421SMatthew Ahrens va_list v; 5214843421SMatthew Ahrens 5314843421SMatthew Ahrens va_start(v, fmt); 5414843421SMatthew Ahrens (void) vsnprintf(errstr, sizeof (errstr), fmt, v); 5514843421SMatthew Ahrens va_end(v); 5614843421SMatthew Ahrens 5714843421SMatthew Ahrens PyErr_SetObject(ZFSError, Py_BuildValue("is", errno, errstr)); 5814843421SMatthew Ahrens } 5914843421SMatthew Ahrens 6014843421SMatthew Ahrens static char cmdstr[HIS_MAX_RECORD_LEN]; 6114843421SMatthew Ahrens 6214843421SMatthew Ahrens static int 6314843421SMatthew Ahrens ioctl_with_cmdstr(int ioc, zfs_cmd_t *zc) 6414843421SMatthew Ahrens { 6514843421SMatthew Ahrens int err; 6614843421SMatthew Ahrens 6714843421SMatthew Ahrens if (cmdstr[0]) 6814843421SMatthew Ahrens zc->zc_history = (uint64_t)(uintptr_t)cmdstr; 6914843421SMatthew Ahrens err = ioctl(zfsdevfd, ioc, zc); 7014843421SMatthew Ahrens cmdstr[0] = '\0'; 7114843421SMatthew Ahrens return (err); 7214843421SMatthew Ahrens } 7314843421SMatthew Ahrens 7414843421SMatthew Ahrens static PyObject * 7514843421SMatthew Ahrens nvl2py(nvlist_t *nvl) 7614843421SMatthew Ahrens { 7714843421SMatthew Ahrens PyObject *pyo; 7814843421SMatthew Ahrens nvpair_t *nvp; 7914843421SMatthew Ahrens 8014843421SMatthew Ahrens pyo = PyDict_New(); 8114843421SMatthew Ahrens 8214843421SMatthew Ahrens for (nvp = nvlist_next_nvpair(nvl, NULL); nvp; 8314843421SMatthew Ahrens nvp = nvlist_next_nvpair(nvl, nvp)) { 8414843421SMatthew Ahrens PyObject *pyval; 8514843421SMatthew Ahrens char *sval; 8614843421SMatthew Ahrens uint64_t ival; 8714843421SMatthew Ahrens boolean_t bval; 8814843421SMatthew Ahrens nvlist_t *nval; 8914843421SMatthew Ahrens 9014843421SMatthew Ahrens switch (nvpair_type(nvp)) { 9114843421SMatthew Ahrens case DATA_TYPE_STRING: 9214843421SMatthew Ahrens (void) nvpair_value_string(nvp, &sval); 9314843421SMatthew Ahrens pyval = Py_BuildValue("s", sval); 9414843421SMatthew Ahrens break; 9514843421SMatthew Ahrens 9614843421SMatthew Ahrens case DATA_TYPE_UINT64: 9714843421SMatthew Ahrens (void) nvpair_value_uint64(nvp, &ival); 9814843421SMatthew Ahrens pyval = Py_BuildValue("K", ival); 9914843421SMatthew Ahrens break; 10014843421SMatthew Ahrens 10114843421SMatthew Ahrens case DATA_TYPE_NVLIST: 10214843421SMatthew Ahrens (void) nvpair_value_nvlist(nvp, &nval); 10314843421SMatthew Ahrens pyval = nvl2py(nval); 10414843421SMatthew Ahrens break; 10514843421SMatthew Ahrens 10614843421SMatthew Ahrens case DATA_TYPE_BOOLEAN: 10714843421SMatthew Ahrens Py_INCREF(Py_None); 10814843421SMatthew Ahrens pyval = Py_None; 10914843421SMatthew Ahrens break; 11014843421SMatthew Ahrens 11114843421SMatthew Ahrens case DATA_TYPE_BOOLEAN_VALUE: 11214843421SMatthew Ahrens (void) nvpair_value_boolean_value(nvp, &bval); 11314843421SMatthew Ahrens pyval = Py_BuildValue("i", bval); 11414843421SMatthew Ahrens break; 11514843421SMatthew Ahrens 11614843421SMatthew Ahrens default: 11714843421SMatthew Ahrens PyErr_SetNone(PyExc_ValueError); 11814843421SMatthew Ahrens Py_DECREF(pyo); 11914843421SMatthew Ahrens return (NULL); 12014843421SMatthew Ahrens } 12114843421SMatthew Ahrens 12214843421SMatthew Ahrens PyDict_SetItemString(pyo, nvpair_name(nvp), pyval); 12314843421SMatthew Ahrens Py_DECREF(pyval); 12414843421SMatthew Ahrens } 12514843421SMatthew Ahrens 12614843421SMatthew Ahrens return (pyo); 12714843421SMatthew Ahrens } 12814843421SMatthew Ahrens 12914843421SMatthew Ahrens static nvlist_t * 13014843421SMatthew Ahrens dict2nvl(PyObject *d) 13114843421SMatthew Ahrens { 13214843421SMatthew Ahrens nvlist_t *nvl; 13314843421SMatthew Ahrens int err; 13414843421SMatthew Ahrens PyObject *key, *value; 135*e8921a52SAndy Fiddaman Py_ssize_t pos = 0; 13614843421SMatthew Ahrens 13714843421SMatthew Ahrens if (!PyDict_Check(d)) { 13814843421SMatthew Ahrens PyErr_SetObject(PyExc_ValueError, d); 13914843421SMatthew Ahrens return (NULL); 14014843421SMatthew Ahrens } 14114843421SMatthew Ahrens 14214843421SMatthew Ahrens err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); 14314843421SMatthew Ahrens assert(err == 0); 14414843421SMatthew Ahrens 14514843421SMatthew Ahrens while (PyDict_Next(d, &pos, &key, &value)) { 146*e8921a52SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 147*e8921a52SAndy Fiddaman char *keystr = PyBytes_AsString(key); 148*e8921a52SAndy Fiddaman #else 14914843421SMatthew Ahrens char *keystr = PyString_AsString(key); 150*e8921a52SAndy Fiddaman #endif 15114843421SMatthew Ahrens if (keystr == NULL) { 15214843421SMatthew Ahrens PyErr_SetObject(PyExc_KeyError, key); 15314843421SMatthew Ahrens nvlist_free(nvl); 15414843421SMatthew Ahrens return (NULL); 15514843421SMatthew Ahrens } 15614843421SMatthew Ahrens 15714843421SMatthew Ahrens if (PyDict_Check(value)) { 15814843421SMatthew Ahrens nvlist_t *valnvl = dict2nvl(value); 15914843421SMatthew Ahrens err = nvlist_add_nvlist(nvl, keystr, valnvl); 16014843421SMatthew Ahrens nvlist_free(valnvl); 16114843421SMatthew Ahrens } else if (value == Py_None) { 16214843421SMatthew Ahrens err = nvlist_add_boolean(nvl, keystr); 163*e8921a52SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 164*e8921a52SAndy Fiddaman } else if (PyBytes_Check(value)) { 165*e8921a52SAndy Fiddaman #else 16614843421SMatthew Ahrens } else if (PyString_Check(value)) { 167*e8921a52SAndy Fiddaman #endif 168*e8921a52SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 169*e8921a52SAndy Fiddaman char *valstr = PyBytes_AsString(value); 170*e8921a52SAndy Fiddaman #else 17114843421SMatthew Ahrens char *valstr = PyString_AsString(value); 172*e8921a52SAndy Fiddaman #endif 17314843421SMatthew Ahrens err = nvlist_add_string(nvl, keystr, valstr); 174*e8921a52SAndy Fiddaman } else if (PyLong_Check(value)) { 175*e8921a52SAndy Fiddaman uint64_t valint = PyLong_AsUnsignedLongLongMask(value); 17614843421SMatthew Ahrens err = nvlist_add_uint64(nvl, keystr, valint); 17714843421SMatthew Ahrens } else if (PyBool_Check(value)) { 17814843421SMatthew Ahrens boolean_t valbool = value == Py_True ? B_TRUE : B_FALSE; 17914843421SMatthew Ahrens err = nvlist_add_boolean_value(nvl, keystr, valbool); 18014843421SMatthew Ahrens } else { 18114843421SMatthew Ahrens PyErr_SetObject(PyExc_ValueError, value); 18214843421SMatthew Ahrens nvlist_free(nvl); 18314843421SMatthew Ahrens return (NULL); 18414843421SMatthew Ahrens } 18514843421SMatthew Ahrens assert(err == 0); 18614843421SMatthew Ahrens } 18714843421SMatthew Ahrens 18814843421SMatthew Ahrens return (nvl); 18914843421SMatthew Ahrens } 19014843421SMatthew Ahrens 19114843421SMatthew Ahrens static PyObject * 19214843421SMatthew Ahrens fakepropval(uint64_t value) 19314843421SMatthew Ahrens { 19414843421SMatthew Ahrens PyObject *d = PyDict_New(); 19514843421SMatthew Ahrens PyDict_SetItemString(d, "value", Py_BuildValue("K", value)); 19614843421SMatthew Ahrens return (d); 19714843421SMatthew Ahrens } 19814843421SMatthew Ahrens 19914843421SMatthew Ahrens static void 20014843421SMatthew Ahrens add_ds_props(zfs_cmd_t *zc, PyObject *nvl) 20114843421SMatthew Ahrens { 20214843421SMatthew Ahrens dmu_objset_stats_t *s = &zc->zc_objset_stats; 20314843421SMatthew Ahrens PyDict_SetItemString(nvl, "numclones", 20414843421SMatthew Ahrens fakepropval(s->dds_num_clones)); 20514843421SMatthew Ahrens PyDict_SetItemString(nvl, "issnap", 20614843421SMatthew Ahrens fakepropval(s->dds_is_snapshot)); 20714843421SMatthew Ahrens PyDict_SetItemString(nvl, "inconsistent", 20814843421SMatthew Ahrens fakepropval(s->dds_inconsistent)); 20914843421SMatthew Ahrens } 21014843421SMatthew Ahrens 21114843421SMatthew Ahrens /* On error, returns NULL but does not set python exception. */ 21214843421SMatthew Ahrens static PyObject * 21314843421SMatthew Ahrens ioctl_with_dstnv(int ioc, zfs_cmd_t *zc) 21414843421SMatthew Ahrens { 21514843421SMatthew Ahrens int nvsz = 2048; 21614843421SMatthew Ahrens void *nvbuf; 21714843421SMatthew Ahrens PyObject *pynv = NULL; 21814843421SMatthew Ahrens 21914843421SMatthew Ahrens again: 22014843421SMatthew Ahrens nvbuf = malloc(nvsz); 22114843421SMatthew Ahrens zc->zc_nvlist_dst_size = nvsz; 22214843421SMatthew Ahrens zc->zc_nvlist_dst = (uintptr_t)nvbuf; 22314843421SMatthew Ahrens 22414843421SMatthew Ahrens if (ioctl(zfsdevfd, ioc, zc) == 0) { 22514843421SMatthew Ahrens nvlist_t *nvl; 22614843421SMatthew Ahrens 22714843421SMatthew Ahrens errno = nvlist_unpack(nvbuf, zc->zc_nvlist_dst_size, &nvl, 0); 22814843421SMatthew Ahrens if (errno == 0) { 22914843421SMatthew Ahrens pynv = nvl2py(nvl); 23014843421SMatthew Ahrens nvlist_free(nvl); 23114843421SMatthew Ahrens } 23214843421SMatthew Ahrens } else if (errno == ENOMEM) { 23314843421SMatthew Ahrens free(nvbuf); 23414843421SMatthew Ahrens nvsz = zc->zc_nvlist_dst_size; 23514843421SMatthew Ahrens goto again; 23614843421SMatthew Ahrens } 23714843421SMatthew Ahrens free(nvbuf); 23814843421SMatthew Ahrens return (pynv); 23914843421SMatthew Ahrens } 24014843421SMatthew Ahrens 24114843421SMatthew Ahrens static PyObject * 24214843421SMatthew Ahrens py_next_dataset(PyObject *self, PyObject *args) 24314843421SMatthew Ahrens { 24414843421SMatthew Ahrens int ioc; 24514843421SMatthew Ahrens uint64_t cookie; 24614843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 24714843421SMatthew Ahrens int snaps; 24814843421SMatthew Ahrens char *name; 24914843421SMatthew Ahrens PyObject *nvl; 25014843421SMatthew Ahrens PyObject *ret = NULL; 25114843421SMatthew Ahrens 25214843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "siK", &name, &snaps, &cookie)) 25314843421SMatthew Ahrens return (NULL); 25414843421SMatthew Ahrens 25514843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 25614843421SMatthew Ahrens zc.zc_cookie = cookie; 25714843421SMatthew Ahrens 25814843421SMatthew Ahrens if (snaps) 25914843421SMatthew Ahrens ioc = ZFS_IOC_SNAPSHOT_LIST_NEXT; 26014843421SMatthew Ahrens else 26114843421SMatthew Ahrens ioc = ZFS_IOC_DATASET_LIST_NEXT; 26214843421SMatthew Ahrens 26314843421SMatthew Ahrens nvl = ioctl_with_dstnv(ioc, &zc); 26414843421SMatthew Ahrens if (nvl) { 26514843421SMatthew Ahrens add_ds_props(&zc, nvl); 26614843421SMatthew Ahrens ret = Py_BuildValue("sKO", zc.zc_name, zc.zc_cookie, nvl); 26714843421SMatthew Ahrens Py_DECREF(nvl); 26814843421SMatthew Ahrens } else if (errno == ESRCH) { 26914843421SMatthew Ahrens PyErr_SetNone(PyExc_StopIteration); 27014843421SMatthew Ahrens } else { 27114843421SMatthew Ahrens if (snaps) 27214843421SMatthew Ahrens seterr(_("cannot get snapshots of %s"), name); 27314843421SMatthew Ahrens else 27414843421SMatthew Ahrens seterr(_("cannot get child datasets of %s"), name); 27514843421SMatthew Ahrens } 27614843421SMatthew Ahrens return (ret); 27714843421SMatthew Ahrens } 27814843421SMatthew Ahrens 27914843421SMatthew Ahrens static PyObject * 28014843421SMatthew Ahrens py_dataset_props(PyObject *self, PyObject *args) 28114843421SMatthew Ahrens { 28214843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 28314843421SMatthew Ahrens int snaps; 28414843421SMatthew Ahrens char *name; 28514843421SMatthew Ahrens PyObject *nvl; 28614843421SMatthew Ahrens 28714843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 28814843421SMatthew Ahrens return (NULL); 28914843421SMatthew Ahrens 29014843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 29114843421SMatthew Ahrens 29214843421SMatthew Ahrens nvl = ioctl_with_dstnv(ZFS_IOC_OBJSET_STATS, &zc); 29314843421SMatthew Ahrens if (nvl) { 29414843421SMatthew Ahrens add_ds_props(&zc, nvl); 29514843421SMatthew Ahrens } else { 29614843421SMatthew Ahrens seterr(_("cannot access dataset %s"), name); 29714843421SMatthew Ahrens } 29814843421SMatthew Ahrens return (nvl); 29914843421SMatthew Ahrens } 30014843421SMatthew Ahrens 30114843421SMatthew Ahrens static PyObject * 30214843421SMatthew Ahrens py_get_fsacl(PyObject *self, PyObject *args) 30314843421SMatthew Ahrens { 30414843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 30514843421SMatthew Ahrens char *name; 30614843421SMatthew Ahrens PyObject *nvl; 30714843421SMatthew Ahrens 30814843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 30914843421SMatthew Ahrens return (NULL); 31014843421SMatthew Ahrens 31114843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 31214843421SMatthew Ahrens 31314843421SMatthew Ahrens nvl = ioctl_with_dstnv(ZFS_IOC_GET_FSACL, &zc); 31414843421SMatthew Ahrens if (nvl == NULL) 31514843421SMatthew Ahrens seterr(_("cannot get permissions on %s"), name); 31614843421SMatthew Ahrens 31714843421SMatthew Ahrens return (nvl); 31814843421SMatthew Ahrens } 31914843421SMatthew Ahrens 32014843421SMatthew Ahrens static PyObject * 32114843421SMatthew Ahrens py_set_fsacl(PyObject *self, PyObject *args) 32214843421SMatthew Ahrens { 32314843421SMatthew Ahrens int un; 32414843421SMatthew Ahrens size_t nvsz; 32514843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 32614843421SMatthew Ahrens char *name, *nvbuf; 32714843421SMatthew Ahrens PyObject *dict, *file; 32814843421SMatthew Ahrens nvlist_t *nvl; 32914843421SMatthew Ahrens int err; 33014843421SMatthew Ahrens 33114843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "siO!", &name, &un, 33214843421SMatthew Ahrens &PyDict_Type, &dict)) 33314843421SMatthew Ahrens return (NULL); 33414843421SMatthew Ahrens 33514843421SMatthew Ahrens nvl = dict2nvl(dict); 33614843421SMatthew Ahrens if (nvl == NULL) 33714843421SMatthew Ahrens return (NULL); 33814843421SMatthew Ahrens 33914843421SMatthew Ahrens err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE); 34014843421SMatthew Ahrens assert(err == 0); 34114843421SMatthew Ahrens nvbuf = malloc(nvsz); 34214843421SMatthew Ahrens err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0); 34314843421SMatthew Ahrens assert(err == 0); 34414843421SMatthew Ahrens 34514843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 34614843421SMatthew Ahrens zc.zc_nvlist_src_size = nvsz; 34714843421SMatthew Ahrens zc.zc_nvlist_src = (uintptr_t)nvbuf; 34814843421SMatthew Ahrens zc.zc_perm_action = un; 34914843421SMatthew Ahrens 35014843421SMatthew Ahrens err = ioctl_with_cmdstr(ZFS_IOC_SET_FSACL, &zc); 35114843421SMatthew Ahrens free(nvbuf); 35214843421SMatthew Ahrens if (err) { 35314843421SMatthew Ahrens seterr(_("cannot set permissions on %s"), name); 35414843421SMatthew Ahrens return (NULL); 35514843421SMatthew Ahrens } 35614843421SMatthew Ahrens 35714843421SMatthew Ahrens Py_RETURN_NONE; 35814843421SMatthew Ahrens } 35914843421SMatthew Ahrens 360842727c2SChris Kirby static PyObject * 361842727c2SChris Kirby py_get_holds(PyObject *self, PyObject *args) 362842727c2SChris Kirby { 363842727c2SChris Kirby zfs_cmd_t zc = { 0 }; 364842727c2SChris Kirby char *name; 365842727c2SChris Kirby PyObject *nvl; 366842727c2SChris Kirby 367842727c2SChris Kirby if (!PyArg_ParseTuple(args, "s", &name)) 368842727c2SChris Kirby return (NULL); 369842727c2SChris Kirby 370842727c2SChris Kirby (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 371842727c2SChris Kirby 372842727c2SChris Kirby nvl = ioctl_with_dstnv(ZFS_IOC_GET_HOLDS, &zc); 373842727c2SChris Kirby if (nvl == NULL) 374842727c2SChris Kirby seterr(_("cannot get holds for %s"), name); 375842727c2SChris Kirby 376842727c2SChris Kirby return (nvl); 377842727c2SChris Kirby } 378842727c2SChris Kirby 37914843421SMatthew Ahrens static PyObject * 38014843421SMatthew Ahrens py_userspace_many(PyObject *self, PyObject *args) 38114843421SMatthew Ahrens { 38214843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 38314843421SMatthew Ahrens zfs_userquota_prop_t type; 38414843421SMatthew Ahrens char *name, *propname; 38514843421SMatthew Ahrens int bufsz = 1<<20; 38614843421SMatthew Ahrens void *buf; 38714843421SMatthew Ahrens PyObject *dict, *file; 38814843421SMatthew Ahrens int error; 38914843421SMatthew Ahrens 39014843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "ss", &name, &propname)) 39114843421SMatthew Ahrens return (NULL); 39214843421SMatthew Ahrens 39314843421SMatthew Ahrens for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) 39414843421SMatthew Ahrens if (strcmp(propname, zfs_userquota_prop_prefixes[type]) == 0) 39514843421SMatthew Ahrens break; 39614843421SMatthew Ahrens if (type == ZFS_NUM_USERQUOTA_PROPS) { 39714843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, propname); 39814843421SMatthew Ahrens return (NULL); 39914843421SMatthew Ahrens } 40014843421SMatthew Ahrens 40114843421SMatthew Ahrens dict = PyDict_New(); 40214843421SMatthew Ahrens buf = malloc(bufsz); 40314843421SMatthew Ahrens 40414843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 40514843421SMatthew Ahrens zc.zc_objset_type = type; 40614843421SMatthew Ahrens zc.zc_cookie = 0; 40714843421SMatthew Ahrens 40814843421SMatthew Ahrens while (1) { 40914843421SMatthew Ahrens zfs_useracct_t *zua = buf; 41014843421SMatthew Ahrens 41114843421SMatthew Ahrens zc.zc_nvlist_dst = (uintptr_t)buf; 41214843421SMatthew Ahrens zc.zc_nvlist_dst_size = bufsz; 41314843421SMatthew Ahrens 41414843421SMatthew Ahrens error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_MANY, &zc); 41514843421SMatthew Ahrens if (error || zc.zc_nvlist_dst_size == 0) 41614843421SMatthew Ahrens break; 41714843421SMatthew Ahrens 41814843421SMatthew Ahrens while (zc.zc_nvlist_dst_size > 0) { 41914843421SMatthew Ahrens PyObject *pykey, *pyval; 42014843421SMatthew Ahrens 42114843421SMatthew Ahrens pykey = Py_BuildValue("sI", 42214843421SMatthew Ahrens zua->zu_domain, zua->zu_rid); 42314843421SMatthew Ahrens pyval = Py_BuildValue("K", zua->zu_space); 42414843421SMatthew Ahrens PyDict_SetItem(dict, pykey, pyval); 42514843421SMatthew Ahrens Py_DECREF(pykey); 42614843421SMatthew Ahrens Py_DECREF(pyval); 42714843421SMatthew Ahrens 42814843421SMatthew Ahrens zua++; 42914843421SMatthew Ahrens zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t); 43014843421SMatthew Ahrens } 43114843421SMatthew Ahrens } 43214843421SMatthew Ahrens 43314843421SMatthew Ahrens free(buf); 43414843421SMatthew Ahrens 43514843421SMatthew Ahrens if (error != 0) { 43614843421SMatthew Ahrens Py_DECREF(dict); 43714843421SMatthew Ahrens seterr(_("cannot get %s property on %s"), propname, name); 43814843421SMatthew Ahrens return (NULL); 43914843421SMatthew Ahrens } 44014843421SMatthew Ahrens 44114843421SMatthew Ahrens return (dict); 44214843421SMatthew Ahrens } 44314843421SMatthew Ahrens 44414843421SMatthew Ahrens static PyObject * 44514843421SMatthew Ahrens py_userspace_upgrade(PyObject *self, PyObject *args) 44614843421SMatthew Ahrens { 44714843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 44814843421SMatthew Ahrens char *name; 44914843421SMatthew Ahrens int error; 45014843421SMatthew Ahrens 45114843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 45214843421SMatthew Ahrens return (NULL); 45314843421SMatthew Ahrens 45414843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 45514843421SMatthew Ahrens error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_UPGRADE, &zc); 45614843421SMatthew Ahrens 45714843421SMatthew Ahrens if (error != 0) { 45814843421SMatthew Ahrens seterr(_("cannot initialize user accounting information on %s"), 45914843421SMatthew Ahrens name); 46014843421SMatthew Ahrens return (NULL); 46114843421SMatthew Ahrens } 46214843421SMatthew Ahrens 46314843421SMatthew Ahrens Py_RETURN_NONE; 46414843421SMatthew Ahrens } 46514843421SMatthew Ahrens 46614843421SMatthew Ahrens static PyObject * 46714843421SMatthew Ahrens py_set_cmdstr(PyObject *self, PyObject *args) 46814843421SMatthew Ahrens { 46914843421SMatthew Ahrens char *str; 47014843421SMatthew Ahrens 47114843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &str)) 47214843421SMatthew Ahrens return (NULL); 47314843421SMatthew Ahrens 47414843421SMatthew Ahrens (void) strlcpy(cmdstr, str, sizeof (cmdstr)); 47514843421SMatthew Ahrens 47614843421SMatthew Ahrens Py_RETURN_NONE; 47714843421SMatthew Ahrens } 47814843421SMatthew Ahrens 47914843421SMatthew Ahrens static PyObject * 48014843421SMatthew Ahrens py_get_proptable(PyObject *self, PyObject *args) 48114843421SMatthew Ahrens { 48214843421SMatthew Ahrens zprop_desc_t *t = zfs_prop_get_table(); 48314843421SMatthew Ahrens PyObject *d = PyDict_New(); 48414843421SMatthew Ahrens zfs_prop_t i; 48514843421SMatthew Ahrens 48614843421SMatthew Ahrens for (i = 0; i < ZFS_NUM_PROPS; i++) { 48714843421SMatthew Ahrens zprop_desc_t *p = &t[i]; 48814843421SMatthew Ahrens PyObject *tuple; 48914843421SMatthew Ahrens static const char *typetable[] = 49014843421SMatthew Ahrens {"number", "string", "index"}; 49114843421SMatthew Ahrens static const char *attrtable[] = 49214843421SMatthew Ahrens {"default", "readonly", "inherit", "onetime"}; 49314843421SMatthew Ahrens PyObject *indextable; 49414843421SMatthew Ahrens 49514843421SMatthew Ahrens if (p->pd_proptype == PROP_TYPE_INDEX) { 49614843421SMatthew Ahrens const zprop_index_t *it = p->pd_table; 49714843421SMatthew Ahrens indextable = PyDict_New(); 49814843421SMatthew Ahrens int j; 49914843421SMatthew Ahrens for (j = 0; it[j].pi_name; j++) { 50014843421SMatthew Ahrens PyDict_SetItemString(indextable, 50114843421SMatthew Ahrens it[j].pi_name, 50214843421SMatthew Ahrens Py_BuildValue("K", it[j].pi_value)); 50314843421SMatthew Ahrens } 50414843421SMatthew Ahrens } else { 50514843421SMatthew Ahrens Py_INCREF(Py_None); 50614843421SMatthew Ahrens indextable = Py_None; 50714843421SMatthew Ahrens } 50814843421SMatthew Ahrens 50914843421SMatthew Ahrens tuple = Py_BuildValue("sissKsissiiO", 51014843421SMatthew Ahrens p->pd_name, p->pd_propnum, typetable[p->pd_proptype], 51114843421SMatthew Ahrens p->pd_strdefault, p->pd_numdefault, 51214843421SMatthew Ahrens attrtable[p->pd_attr], p->pd_types, 51314843421SMatthew Ahrens p->pd_values, p->pd_colname, 51414843421SMatthew Ahrens p->pd_rightalign, p->pd_visible, indextable); 51514843421SMatthew Ahrens PyDict_SetItemString(d, p->pd_name, tuple); 51614843421SMatthew Ahrens Py_DECREF(tuple); 51714843421SMatthew Ahrens } 51814843421SMatthew Ahrens 51914843421SMatthew Ahrens return (d); 52014843421SMatthew Ahrens } 52114843421SMatthew Ahrens 52214843421SMatthew Ahrens static PyMethodDef zfsmethods[] = { 52314843421SMatthew Ahrens {"next_dataset", py_next_dataset, METH_VARARGS, 52414843421SMatthew Ahrens "Get next child dataset or snapshot."}, 52514843421SMatthew Ahrens {"get_fsacl", py_get_fsacl, METH_VARARGS, "Get allowed permissions."}, 52614843421SMatthew Ahrens {"set_fsacl", py_set_fsacl, METH_VARARGS, "Set allowed permissions."}, 52714843421SMatthew Ahrens {"userspace_many", py_userspace_many, METH_VARARGS, 52814843421SMatthew Ahrens "Get user space accounting."}, 52914843421SMatthew Ahrens {"userspace_upgrade", py_userspace_upgrade, METH_VARARGS, 53014843421SMatthew Ahrens "Upgrade fs to enable user space accounting."}, 53114843421SMatthew Ahrens {"set_cmdstr", py_set_cmdstr, METH_VARARGS, 53214843421SMatthew Ahrens "Set command string for history logging."}, 53314843421SMatthew Ahrens {"dataset_props", py_dataset_props, METH_VARARGS, 53414843421SMatthew Ahrens "Get dataset properties."}, 53514843421SMatthew Ahrens {"get_proptable", py_get_proptable, METH_NOARGS, 53614843421SMatthew Ahrens "Get property table."}, 537842727c2SChris Kirby {"get_holds", py_get_holds, METH_VARARGS, "Get user holds."}, 53814843421SMatthew Ahrens {NULL, NULL, 0, NULL} 53914843421SMatthew Ahrens }; 54014843421SMatthew Ahrens 541*e8921a52SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 542*e8921a52SAndy Fiddaman static struct PyModuleDef zfs_module = { 543*e8921a52SAndy Fiddaman PyModuleDef_HEAD_INIT, 544*e8921a52SAndy Fiddaman "zfs.ioctl", 545*e8921a52SAndy Fiddaman NULL, 546*e8921a52SAndy Fiddaman -1, 547*e8921a52SAndy Fiddaman zfsmethods 548*e8921a52SAndy Fiddaman }; 549*e8921a52SAndy Fiddaman #endif 550*e8921a52SAndy Fiddaman 551*e8921a52SAndy Fiddaman static PyObject * 552*e8921a52SAndy Fiddaman moduleinit() 55314843421SMatthew Ahrens { 554*e8921a52SAndy Fiddaman PyObject *zfs_ioctl, *zfs_util, *devfile; 555*e8921a52SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 556*e8921a52SAndy Fiddaman zfs_ioctl = PyModule_Create(&zfs_module); 557*e8921a52SAndy Fiddaman #else 558*e8921a52SAndy Fiddaman zfs_ioctl = Py_InitModule("zfs.ioctl", zfsmethods); 559*e8921a52SAndy Fiddaman #endif 560*e8921a52SAndy Fiddaman zfs_util = PyImport_ImportModule("zfs.util"); 56114843421SMatthew Ahrens 56214843421SMatthew Ahrens if (zfs_util == NULL) 563*e8921a52SAndy Fiddaman return (NULL); 56414843421SMatthew Ahrens 56514843421SMatthew Ahrens ZFSError = PyObject_GetAttrString(zfs_util, "ZFSError"); 56614843421SMatthew Ahrens devfile = PyObject_GetAttrString(zfs_util, "dev"); 56714843421SMatthew Ahrens zfsdevfd = PyObject_AsFileDescriptor(devfile); 56814843421SMatthew Ahrens 56914843421SMatthew Ahrens zfs_prop_init(); 570*e8921a52SAndy Fiddaman 571*e8921a52SAndy Fiddaman return (zfs_ioctl); 572*e8921a52SAndy Fiddaman } 573*e8921a52SAndy Fiddaman 574*e8921a52SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 575*e8921a52SAndy Fiddaman PyMODINIT_FUNC 576*e8921a52SAndy Fiddaman PyInit_ioctl(void) 577*e8921a52SAndy Fiddaman { 578*e8921a52SAndy Fiddaman return (moduleinit()); 57914843421SMatthew Ahrens } 580*e8921a52SAndy Fiddaman #else 581*e8921a52SAndy Fiddaman PyMODINIT_FUNC 582*e8921a52SAndy Fiddaman initioctl(void) 583*e8921a52SAndy Fiddaman { 584*e8921a52SAndy Fiddaman (void) moduleinit(); 585*e8921a52SAndy Fiddaman } 586*e8921a52SAndy Fiddaman #endif 587