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. 24d561bb99SAndy 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; 135d561bb99SAndy 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*019853a6SAndy Fiddaman const char *keystr; 147d561bb99SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 148*019853a6SAndy Fiddaman keystr = PyUnicode_AsUTF8(key); 149d561bb99SAndy Fiddaman #else 150*019853a6SAndy Fiddaman keystr = PyString_AsString(key); 151d561bb99SAndy Fiddaman #endif 15214843421SMatthew Ahrens if (keystr == NULL) { 15314843421SMatthew Ahrens PyErr_SetObject(PyExc_KeyError, key); 15414843421SMatthew Ahrens nvlist_free(nvl); 15514843421SMatthew Ahrens return (NULL); 15614843421SMatthew Ahrens } 15714843421SMatthew Ahrens 15814843421SMatthew Ahrens if (PyDict_Check(value)) { 15914843421SMatthew Ahrens nvlist_t *valnvl = dict2nvl(value); 16014843421SMatthew Ahrens err = nvlist_add_nvlist(nvl, keystr, valnvl); 16114843421SMatthew Ahrens nvlist_free(valnvl); 16214843421SMatthew Ahrens } else if (value == Py_None) { 16314843421SMatthew Ahrens err = nvlist_add_boolean(nvl, keystr); 164d561bb99SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 165d2b4b850SAlexander Pyhalov } else if (PyUnicode_Check(value)) { 166d561bb99SAndy Fiddaman #else 16714843421SMatthew Ahrens } else if (PyString_Check(value)) { 168d561bb99SAndy Fiddaman #endif 169*019853a6SAndy Fiddaman const char *valstr; 170d561bb99SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 171*019853a6SAndy Fiddaman valstr = PyUnicode_AsUTF8(value); 172d561bb99SAndy Fiddaman #else 173*019853a6SAndy Fiddaman valstr = PyString_AsString(value); 174d561bb99SAndy Fiddaman #endif 17514843421SMatthew Ahrens err = nvlist_add_string(nvl, keystr, valstr); 176d561bb99SAndy Fiddaman } else if (PyLong_Check(value)) { 177d561bb99SAndy Fiddaman uint64_t valint = PyLong_AsUnsignedLongLongMask(value); 17814843421SMatthew Ahrens err = nvlist_add_uint64(nvl, keystr, valint); 17914843421SMatthew Ahrens } else if (PyBool_Check(value)) { 18014843421SMatthew Ahrens boolean_t valbool = value == Py_True ? B_TRUE : B_FALSE; 18114843421SMatthew Ahrens err = nvlist_add_boolean_value(nvl, keystr, valbool); 18214843421SMatthew Ahrens } else { 18314843421SMatthew Ahrens PyErr_SetObject(PyExc_ValueError, value); 18414843421SMatthew Ahrens nvlist_free(nvl); 18514843421SMatthew Ahrens return (NULL); 18614843421SMatthew Ahrens } 18714843421SMatthew Ahrens assert(err == 0); 18814843421SMatthew Ahrens } 18914843421SMatthew Ahrens 19014843421SMatthew Ahrens return (nvl); 19114843421SMatthew Ahrens } 19214843421SMatthew Ahrens 19314843421SMatthew Ahrens static PyObject * 19414843421SMatthew Ahrens fakepropval(uint64_t value) 19514843421SMatthew Ahrens { 19614843421SMatthew Ahrens PyObject *d = PyDict_New(); 19714843421SMatthew Ahrens PyDict_SetItemString(d, "value", Py_BuildValue("K", value)); 19814843421SMatthew Ahrens return (d); 19914843421SMatthew Ahrens } 20014843421SMatthew Ahrens 20114843421SMatthew Ahrens static void 20214843421SMatthew Ahrens add_ds_props(zfs_cmd_t *zc, PyObject *nvl) 20314843421SMatthew Ahrens { 20414843421SMatthew Ahrens dmu_objset_stats_t *s = &zc->zc_objset_stats; 20514843421SMatthew Ahrens PyDict_SetItemString(nvl, "numclones", 20614843421SMatthew Ahrens fakepropval(s->dds_num_clones)); 20714843421SMatthew Ahrens PyDict_SetItemString(nvl, "issnap", 20814843421SMatthew Ahrens fakepropval(s->dds_is_snapshot)); 20914843421SMatthew Ahrens PyDict_SetItemString(nvl, "inconsistent", 21014843421SMatthew Ahrens fakepropval(s->dds_inconsistent)); 21114843421SMatthew Ahrens } 21214843421SMatthew Ahrens 21314843421SMatthew Ahrens /* On error, returns NULL but does not set python exception. */ 21414843421SMatthew Ahrens static PyObject * 21514843421SMatthew Ahrens ioctl_with_dstnv(int ioc, zfs_cmd_t *zc) 21614843421SMatthew Ahrens { 21714843421SMatthew Ahrens int nvsz = 2048; 21814843421SMatthew Ahrens void *nvbuf; 21914843421SMatthew Ahrens PyObject *pynv = NULL; 22014843421SMatthew Ahrens 22114843421SMatthew Ahrens again: 22214843421SMatthew Ahrens nvbuf = malloc(nvsz); 22314843421SMatthew Ahrens zc->zc_nvlist_dst_size = nvsz; 22414843421SMatthew Ahrens zc->zc_nvlist_dst = (uintptr_t)nvbuf; 22514843421SMatthew Ahrens 22614843421SMatthew Ahrens if (ioctl(zfsdevfd, ioc, zc) == 0) { 22714843421SMatthew Ahrens nvlist_t *nvl; 22814843421SMatthew Ahrens 22914843421SMatthew Ahrens errno = nvlist_unpack(nvbuf, zc->zc_nvlist_dst_size, &nvl, 0); 23014843421SMatthew Ahrens if (errno == 0) { 23114843421SMatthew Ahrens pynv = nvl2py(nvl); 23214843421SMatthew Ahrens nvlist_free(nvl); 23314843421SMatthew Ahrens } 23414843421SMatthew Ahrens } else if (errno == ENOMEM) { 23514843421SMatthew Ahrens free(nvbuf); 23614843421SMatthew Ahrens nvsz = zc->zc_nvlist_dst_size; 23714843421SMatthew Ahrens goto again; 23814843421SMatthew Ahrens } 23914843421SMatthew Ahrens free(nvbuf); 24014843421SMatthew Ahrens return (pynv); 24114843421SMatthew Ahrens } 24214843421SMatthew Ahrens 24314843421SMatthew Ahrens static PyObject * 24414843421SMatthew Ahrens py_next_dataset(PyObject *self, PyObject *args) 24514843421SMatthew Ahrens { 24614843421SMatthew Ahrens int ioc; 24714843421SMatthew Ahrens uint64_t cookie; 24814843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 24914843421SMatthew Ahrens int snaps; 25014843421SMatthew Ahrens char *name; 25114843421SMatthew Ahrens PyObject *nvl; 25214843421SMatthew Ahrens PyObject *ret = NULL; 25314843421SMatthew Ahrens 25414843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "siK", &name, &snaps, &cookie)) 25514843421SMatthew Ahrens return (NULL); 25614843421SMatthew Ahrens 25714843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 25814843421SMatthew Ahrens zc.zc_cookie = cookie; 25914843421SMatthew Ahrens 26014843421SMatthew Ahrens if (snaps) 26114843421SMatthew Ahrens ioc = ZFS_IOC_SNAPSHOT_LIST_NEXT; 26214843421SMatthew Ahrens else 26314843421SMatthew Ahrens ioc = ZFS_IOC_DATASET_LIST_NEXT; 26414843421SMatthew Ahrens 26514843421SMatthew Ahrens nvl = ioctl_with_dstnv(ioc, &zc); 26614843421SMatthew Ahrens if (nvl) { 26714843421SMatthew Ahrens add_ds_props(&zc, nvl); 26814843421SMatthew Ahrens ret = Py_BuildValue("sKO", zc.zc_name, zc.zc_cookie, nvl); 26914843421SMatthew Ahrens Py_DECREF(nvl); 27014843421SMatthew Ahrens } else if (errno == ESRCH) { 27114843421SMatthew Ahrens PyErr_SetNone(PyExc_StopIteration); 27214843421SMatthew Ahrens } else { 27314843421SMatthew Ahrens if (snaps) 27414843421SMatthew Ahrens seterr(_("cannot get snapshots of %s"), name); 27514843421SMatthew Ahrens else 27614843421SMatthew Ahrens seterr(_("cannot get child datasets of %s"), name); 27714843421SMatthew Ahrens } 27814843421SMatthew Ahrens return (ret); 27914843421SMatthew Ahrens } 28014843421SMatthew Ahrens 28114843421SMatthew Ahrens static PyObject * 28214843421SMatthew Ahrens py_dataset_props(PyObject *self, PyObject *args) 28314843421SMatthew Ahrens { 28414843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 28514843421SMatthew Ahrens int snaps; 28614843421SMatthew Ahrens char *name; 28714843421SMatthew Ahrens PyObject *nvl; 28814843421SMatthew Ahrens 28914843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 29014843421SMatthew Ahrens return (NULL); 29114843421SMatthew Ahrens 29214843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 29314843421SMatthew Ahrens 29414843421SMatthew Ahrens nvl = ioctl_with_dstnv(ZFS_IOC_OBJSET_STATS, &zc); 29514843421SMatthew Ahrens if (nvl) { 29614843421SMatthew Ahrens add_ds_props(&zc, nvl); 29714843421SMatthew Ahrens } else { 29814843421SMatthew Ahrens seterr(_("cannot access dataset %s"), name); 29914843421SMatthew Ahrens } 30014843421SMatthew Ahrens return (nvl); 30114843421SMatthew Ahrens } 30214843421SMatthew Ahrens 30314843421SMatthew Ahrens static PyObject * 30414843421SMatthew Ahrens py_get_fsacl(PyObject *self, PyObject *args) 30514843421SMatthew Ahrens { 30614843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 30714843421SMatthew Ahrens char *name; 30814843421SMatthew Ahrens PyObject *nvl; 30914843421SMatthew Ahrens 31014843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 31114843421SMatthew Ahrens return (NULL); 31214843421SMatthew Ahrens 31314843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 31414843421SMatthew Ahrens 31514843421SMatthew Ahrens nvl = ioctl_with_dstnv(ZFS_IOC_GET_FSACL, &zc); 31614843421SMatthew Ahrens if (nvl == NULL) 31714843421SMatthew Ahrens seterr(_("cannot get permissions on %s"), name); 31814843421SMatthew Ahrens 31914843421SMatthew Ahrens return (nvl); 32014843421SMatthew Ahrens } 32114843421SMatthew Ahrens 32214843421SMatthew Ahrens static PyObject * 32314843421SMatthew Ahrens py_set_fsacl(PyObject *self, PyObject *args) 32414843421SMatthew Ahrens { 32514843421SMatthew Ahrens int un; 32614843421SMatthew Ahrens size_t nvsz; 32714843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 32814843421SMatthew Ahrens char *name, *nvbuf; 32914843421SMatthew Ahrens PyObject *dict, *file; 33014843421SMatthew Ahrens nvlist_t *nvl; 33114843421SMatthew Ahrens int err; 33214843421SMatthew Ahrens 33314843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "siO!", &name, &un, 33414843421SMatthew Ahrens &PyDict_Type, &dict)) 33514843421SMatthew Ahrens return (NULL); 33614843421SMatthew Ahrens 33714843421SMatthew Ahrens nvl = dict2nvl(dict); 33814843421SMatthew Ahrens if (nvl == NULL) 33914843421SMatthew Ahrens return (NULL); 34014843421SMatthew Ahrens 34114843421SMatthew Ahrens err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE); 34214843421SMatthew Ahrens assert(err == 0); 34314843421SMatthew Ahrens nvbuf = malloc(nvsz); 34414843421SMatthew Ahrens err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0); 34514843421SMatthew Ahrens assert(err == 0); 34614843421SMatthew Ahrens 34714843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 34814843421SMatthew Ahrens zc.zc_nvlist_src_size = nvsz; 34914843421SMatthew Ahrens zc.zc_nvlist_src = (uintptr_t)nvbuf; 35014843421SMatthew Ahrens zc.zc_perm_action = un; 35114843421SMatthew Ahrens 35214843421SMatthew Ahrens err = ioctl_with_cmdstr(ZFS_IOC_SET_FSACL, &zc); 35314843421SMatthew Ahrens free(nvbuf); 35414843421SMatthew Ahrens if (err) { 35514843421SMatthew Ahrens seterr(_("cannot set permissions on %s"), name); 35614843421SMatthew Ahrens return (NULL); 35714843421SMatthew Ahrens } 35814843421SMatthew Ahrens 35914843421SMatthew Ahrens Py_RETURN_NONE; 36014843421SMatthew Ahrens } 36114843421SMatthew Ahrens 36214843421SMatthew Ahrens static PyObject * 363842727c2SChris Kirby py_get_holds(PyObject *self, PyObject *args) 364842727c2SChris Kirby { 365842727c2SChris Kirby zfs_cmd_t zc = { 0 }; 366842727c2SChris Kirby char *name; 367842727c2SChris Kirby PyObject *nvl; 368842727c2SChris Kirby 369842727c2SChris Kirby if (!PyArg_ParseTuple(args, "s", &name)) 370842727c2SChris Kirby return (NULL); 371842727c2SChris Kirby 372842727c2SChris Kirby (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 373842727c2SChris Kirby 374842727c2SChris Kirby nvl = ioctl_with_dstnv(ZFS_IOC_GET_HOLDS, &zc); 375842727c2SChris Kirby if (nvl == NULL) 376842727c2SChris Kirby seterr(_("cannot get holds for %s"), name); 377842727c2SChris Kirby 378842727c2SChris Kirby return (nvl); 379842727c2SChris Kirby } 380842727c2SChris Kirby 381842727c2SChris Kirby static PyObject * 38214843421SMatthew Ahrens py_userspace_many(PyObject *self, PyObject *args) 38314843421SMatthew Ahrens { 38414843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 38514843421SMatthew Ahrens zfs_userquota_prop_t type; 38614843421SMatthew Ahrens char *name, *propname; 38714843421SMatthew Ahrens int bufsz = 1<<20; 38814843421SMatthew Ahrens void *buf; 38914843421SMatthew Ahrens PyObject *dict, *file; 39014843421SMatthew Ahrens int error; 39114843421SMatthew Ahrens 39214843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "ss", &name, &propname)) 39314843421SMatthew Ahrens return (NULL); 39414843421SMatthew Ahrens 39514843421SMatthew Ahrens for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) 39614843421SMatthew Ahrens if (strcmp(propname, zfs_userquota_prop_prefixes[type]) == 0) 39714843421SMatthew Ahrens break; 39814843421SMatthew Ahrens if (type == ZFS_NUM_USERQUOTA_PROPS) { 39914843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, propname); 40014843421SMatthew Ahrens return (NULL); 40114843421SMatthew Ahrens } 40214843421SMatthew Ahrens 40314843421SMatthew Ahrens dict = PyDict_New(); 40414843421SMatthew Ahrens buf = malloc(bufsz); 40514843421SMatthew Ahrens 40614843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 40714843421SMatthew Ahrens zc.zc_objset_type = type; 40814843421SMatthew Ahrens zc.zc_cookie = 0; 40914843421SMatthew Ahrens 41014843421SMatthew Ahrens while (1) { 41114843421SMatthew Ahrens zfs_useracct_t *zua = buf; 41214843421SMatthew Ahrens 41314843421SMatthew Ahrens zc.zc_nvlist_dst = (uintptr_t)buf; 41414843421SMatthew Ahrens zc.zc_nvlist_dst_size = bufsz; 41514843421SMatthew Ahrens 41614843421SMatthew Ahrens error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_MANY, &zc); 41714843421SMatthew Ahrens if (error || zc.zc_nvlist_dst_size == 0) 41814843421SMatthew Ahrens break; 41914843421SMatthew Ahrens 42014843421SMatthew Ahrens while (zc.zc_nvlist_dst_size > 0) { 42114843421SMatthew Ahrens PyObject *pykey, *pyval; 42214843421SMatthew Ahrens 42314843421SMatthew Ahrens pykey = Py_BuildValue("sI", 42414843421SMatthew Ahrens zua->zu_domain, zua->zu_rid); 42514843421SMatthew Ahrens pyval = Py_BuildValue("K", zua->zu_space); 42614843421SMatthew Ahrens PyDict_SetItem(dict, pykey, pyval); 42714843421SMatthew Ahrens Py_DECREF(pykey); 42814843421SMatthew Ahrens Py_DECREF(pyval); 42914843421SMatthew Ahrens 43014843421SMatthew Ahrens zua++; 43114843421SMatthew Ahrens zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t); 43214843421SMatthew Ahrens } 43314843421SMatthew Ahrens } 43414843421SMatthew Ahrens 43514843421SMatthew Ahrens free(buf); 43614843421SMatthew Ahrens 43714843421SMatthew Ahrens if (error != 0) { 43814843421SMatthew Ahrens Py_DECREF(dict); 43914843421SMatthew Ahrens seterr(_("cannot get %s property on %s"), propname, name); 44014843421SMatthew Ahrens return (NULL); 44114843421SMatthew Ahrens } 44214843421SMatthew Ahrens 44314843421SMatthew Ahrens return (dict); 44414843421SMatthew Ahrens } 44514843421SMatthew Ahrens 44614843421SMatthew Ahrens static PyObject * 44714843421SMatthew Ahrens py_userspace_upgrade(PyObject *self, PyObject *args) 44814843421SMatthew Ahrens { 44914843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 45014843421SMatthew Ahrens char *name; 45114843421SMatthew Ahrens int error; 45214843421SMatthew Ahrens 45314843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 45414843421SMatthew Ahrens return (NULL); 45514843421SMatthew Ahrens 45614843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 45714843421SMatthew Ahrens error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_UPGRADE, &zc); 45814843421SMatthew Ahrens 45914843421SMatthew Ahrens if (error != 0) { 46014843421SMatthew Ahrens seterr(_("cannot initialize user accounting information on %s"), 46114843421SMatthew Ahrens name); 46214843421SMatthew Ahrens return (NULL); 46314843421SMatthew Ahrens } 46414843421SMatthew Ahrens 46514843421SMatthew Ahrens Py_RETURN_NONE; 46614843421SMatthew Ahrens } 46714843421SMatthew Ahrens 46814843421SMatthew Ahrens static PyObject * 46914843421SMatthew Ahrens py_set_cmdstr(PyObject *self, PyObject *args) 47014843421SMatthew Ahrens { 47114843421SMatthew Ahrens char *str; 47214843421SMatthew Ahrens 47314843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &str)) 47414843421SMatthew Ahrens return (NULL); 47514843421SMatthew Ahrens 47614843421SMatthew Ahrens (void) strlcpy(cmdstr, str, sizeof (cmdstr)); 47714843421SMatthew Ahrens 47814843421SMatthew Ahrens Py_RETURN_NONE; 47914843421SMatthew Ahrens } 48014843421SMatthew Ahrens 48114843421SMatthew Ahrens static PyObject * 48214843421SMatthew Ahrens py_get_proptable(PyObject *self, PyObject *args) 48314843421SMatthew Ahrens { 48414843421SMatthew Ahrens zprop_desc_t *t = zfs_prop_get_table(); 48514843421SMatthew Ahrens PyObject *d = PyDict_New(); 48614843421SMatthew Ahrens zfs_prop_t i; 48714843421SMatthew Ahrens 48814843421SMatthew Ahrens for (i = 0; i < ZFS_NUM_PROPS; i++) { 48914843421SMatthew Ahrens zprop_desc_t *p = &t[i]; 49014843421SMatthew Ahrens PyObject *tuple; 49114843421SMatthew Ahrens static const char *typetable[] = 49214843421SMatthew Ahrens {"number", "string", "index"}; 49314843421SMatthew Ahrens static const char *attrtable[] = 49414843421SMatthew Ahrens {"default", "readonly", "inherit", "onetime"}; 49514843421SMatthew Ahrens PyObject *indextable; 49614843421SMatthew Ahrens 49714843421SMatthew Ahrens if (p->pd_proptype == PROP_TYPE_INDEX) { 49814843421SMatthew Ahrens const zprop_index_t *it = p->pd_table; 49914843421SMatthew Ahrens indextable = PyDict_New(); 50014843421SMatthew Ahrens int j; 50114843421SMatthew Ahrens for (j = 0; it[j].pi_name; j++) { 50214843421SMatthew Ahrens PyDict_SetItemString(indextable, 50314843421SMatthew Ahrens it[j].pi_name, 50414843421SMatthew Ahrens Py_BuildValue("K", it[j].pi_value)); 50514843421SMatthew Ahrens } 50614843421SMatthew Ahrens } else { 50714843421SMatthew Ahrens Py_INCREF(Py_None); 50814843421SMatthew Ahrens indextable = Py_None; 50914843421SMatthew Ahrens } 51014843421SMatthew Ahrens 51114843421SMatthew Ahrens tuple = Py_BuildValue("sissKsissiiO", 51214843421SMatthew Ahrens p->pd_name, p->pd_propnum, typetable[p->pd_proptype], 51314843421SMatthew Ahrens p->pd_strdefault, p->pd_numdefault, 51414843421SMatthew Ahrens attrtable[p->pd_attr], p->pd_types, 51514843421SMatthew Ahrens p->pd_values, p->pd_colname, 51614843421SMatthew Ahrens p->pd_rightalign, p->pd_visible, indextable); 51714843421SMatthew Ahrens PyDict_SetItemString(d, p->pd_name, tuple); 51814843421SMatthew Ahrens Py_DECREF(tuple); 51914843421SMatthew Ahrens } 52014843421SMatthew Ahrens 52114843421SMatthew Ahrens return (d); 52214843421SMatthew Ahrens } 52314843421SMatthew Ahrens 52414843421SMatthew Ahrens static PyMethodDef zfsmethods[] = { 52514843421SMatthew Ahrens {"next_dataset", py_next_dataset, METH_VARARGS, 52614843421SMatthew Ahrens "Get next child dataset or snapshot."}, 52714843421SMatthew Ahrens {"get_fsacl", py_get_fsacl, METH_VARARGS, "Get allowed permissions."}, 52814843421SMatthew Ahrens {"set_fsacl", py_set_fsacl, METH_VARARGS, "Set allowed permissions."}, 52914843421SMatthew Ahrens {"userspace_many", py_userspace_many, METH_VARARGS, 53014843421SMatthew Ahrens "Get user space accounting."}, 53114843421SMatthew Ahrens {"userspace_upgrade", py_userspace_upgrade, METH_VARARGS, 53214843421SMatthew Ahrens "Upgrade fs to enable user space accounting."}, 53314843421SMatthew Ahrens {"set_cmdstr", py_set_cmdstr, METH_VARARGS, 53414843421SMatthew Ahrens "Set command string for history logging."}, 53514843421SMatthew Ahrens {"dataset_props", py_dataset_props, METH_VARARGS, 53614843421SMatthew Ahrens "Get dataset properties."}, 53714843421SMatthew Ahrens {"get_proptable", py_get_proptable, METH_NOARGS, 53814843421SMatthew Ahrens "Get property table."}, 539842727c2SChris Kirby {"get_holds", py_get_holds, METH_VARARGS, "Get user holds."}, 54014843421SMatthew Ahrens {NULL, NULL, 0, NULL} 54114843421SMatthew Ahrens }; 54214843421SMatthew Ahrens 543d561bb99SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 544d561bb99SAndy Fiddaman static struct PyModuleDef zfs_module = { 545d561bb99SAndy Fiddaman PyModuleDef_HEAD_INIT, 546d561bb99SAndy Fiddaman "zfs.ioctl", 547d561bb99SAndy Fiddaman NULL, 548d561bb99SAndy Fiddaman -1, 549d561bb99SAndy Fiddaman zfsmethods 550d561bb99SAndy Fiddaman }; 551d561bb99SAndy Fiddaman #endif 552d561bb99SAndy Fiddaman 553d561bb99SAndy Fiddaman static PyObject * 554d561bb99SAndy Fiddaman moduleinit() 55514843421SMatthew Ahrens { 556d561bb99SAndy Fiddaman PyObject *zfs_ioctl, *zfs_util, *devfile; 557d561bb99SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 558d561bb99SAndy Fiddaman zfs_ioctl = PyModule_Create(&zfs_module); 559d561bb99SAndy Fiddaman #else 560d561bb99SAndy Fiddaman zfs_ioctl = Py_InitModule("zfs.ioctl", zfsmethods); 561d561bb99SAndy Fiddaman #endif 562d561bb99SAndy Fiddaman zfs_util = PyImport_ImportModule("zfs.util"); 56314843421SMatthew Ahrens 56414843421SMatthew Ahrens if (zfs_util == NULL) 565d561bb99SAndy Fiddaman return (NULL); 56614843421SMatthew Ahrens 56714843421SMatthew Ahrens ZFSError = PyObject_GetAttrString(zfs_util, "ZFSError"); 56814843421SMatthew Ahrens devfile = PyObject_GetAttrString(zfs_util, "dev"); 56914843421SMatthew Ahrens zfsdevfd = PyObject_AsFileDescriptor(devfile); 57014843421SMatthew Ahrens 57114843421SMatthew Ahrens zfs_prop_init(); 572d561bb99SAndy Fiddaman 573d561bb99SAndy Fiddaman return (zfs_ioctl); 57414843421SMatthew Ahrens } 575d561bb99SAndy Fiddaman 576d561bb99SAndy Fiddaman #if PY_MAJOR_VERSION >= 3 577d561bb99SAndy Fiddaman PyMODINIT_FUNC 578d561bb99SAndy Fiddaman PyInit_ioctl(void) 579d561bb99SAndy Fiddaman { 580d561bb99SAndy Fiddaman return (moduleinit()); 581d561bb99SAndy Fiddaman } 582d561bb99SAndy Fiddaman #else 583d561bb99SAndy Fiddaman PyMODINIT_FUNC 584d561bb99SAndy Fiddaman initioctl(void) 585d561bb99SAndy Fiddaman { 586d561bb99SAndy Fiddaman (void) moduleinit(); 587d561bb99SAndy Fiddaman } 588d561bb99SAndy Fiddaman #endif 589