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 /* 22*e4d060fbSSam Falkner * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2314843421SMatthew Ahrens * Use is subject to license terms. 2414843421SMatthew Ahrens */ 2514843421SMatthew Ahrens 2614843421SMatthew Ahrens #include <Python.h> 2714843421SMatthew Ahrens #include <sys/zfs_ioctl.h> 2814843421SMatthew Ahrens #include <sys/fs/zfs.h> 2914843421SMatthew Ahrens #include <strings.h> 3014843421SMatthew Ahrens #include <unistd.h> 3114843421SMatthew Ahrens #include <libnvpair.h> 3214843421SMatthew Ahrens #include <libintl.h> 3314843421SMatthew Ahrens #include <libzfs.h> 3414843421SMatthew Ahrens #include "zfs_prop.h" 3514843421SMatthew Ahrens 3614843421SMatthew Ahrens static PyObject *ZFSError; 3714843421SMatthew Ahrens static int zfsdevfd; 3814843421SMatthew Ahrens 3914843421SMatthew Ahrens #ifdef __lint 4014843421SMatthew Ahrens #define dgettext(x, y) y 4114843421SMatthew Ahrens #endif 4214843421SMatthew Ahrens 4314843421SMatthew Ahrens #define _(s) dgettext(TEXT_DOMAIN, s) 4414843421SMatthew Ahrens 4514843421SMatthew Ahrens /*PRINTFLIKE1*/ 4614843421SMatthew Ahrens static void 4714843421SMatthew Ahrens seterr(char *fmt, ...) 4814843421SMatthew Ahrens { 4914843421SMatthew Ahrens char errstr[1024]; 5014843421SMatthew Ahrens va_list v; 5114843421SMatthew Ahrens 5214843421SMatthew Ahrens va_start(v, fmt); 5314843421SMatthew Ahrens (void) vsnprintf(errstr, sizeof (errstr), fmt, v); 5414843421SMatthew Ahrens va_end(v); 5514843421SMatthew Ahrens 5614843421SMatthew Ahrens PyErr_SetObject(ZFSError, Py_BuildValue("is", errno, errstr)); 5714843421SMatthew Ahrens } 5814843421SMatthew Ahrens 5914843421SMatthew Ahrens static char cmdstr[HIS_MAX_RECORD_LEN]; 6014843421SMatthew Ahrens 6114843421SMatthew Ahrens static int 6214843421SMatthew Ahrens ioctl_with_cmdstr(int ioc, zfs_cmd_t *zc) 6314843421SMatthew Ahrens { 6414843421SMatthew Ahrens int err; 6514843421SMatthew Ahrens 6614843421SMatthew Ahrens if (cmdstr[0]) 6714843421SMatthew Ahrens zc->zc_history = (uint64_t)(uintptr_t)cmdstr; 6814843421SMatthew Ahrens err = ioctl(zfsdevfd, ioc, zc); 6914843421SMatthew Ahrens cmdstr[0] = '\0'; 7014843421SMatthew Ahrens return (err); 7114843421SMatthew Ahrens } 7214843421SMatthew Ahrens 7314843421SMatthew Ahrens static PyObject * 7414843421SMatthew Ahrens nvl2py(nvlist_t *nvl) 7514843421SMatthew Ahrens { 7614843421SMatthew Ahrens PyObject *pyo; 7714843421SMatthew Ahrens nvpair_t *nvp; 7814843421SMatthew Ahrens 7914843421SMatthew Ahrens pyo = PyDict_New(); 8014843421SMatthew Ahrens 8114843421SMatthew Ahrens for (nvp = nvlist_next_nvpair(nvl, NULL); nvp; 8214843421SMatthew Ahrens nvp = nvlist_next_nvpair(nvl, nvp)) { 8314843421SMatthew Ahrens PyObject *pyval; 8414843421SMatthew Ahrens char *sval; 8514843421SMatthew Ahrens uint64_t ival; 8614843421SMatthew Ahrens boolean_t bval; 8714843421SMatthew Ahrens nvlist_t *nval; 8814843421SMatthew Ahrens 8914843421SMatthew Ahrens switch (nvpair_type(nvp)) { 9014843421SMatthew Ahrens case DATA_TYPE_STRING: 9114843421SMatthew Ahrens (void) nvpair_value_string(nvp, &sval); 9214843421SMatthew Ahrens pyval = Py_BuildValue("s", sval); 9314843421SMatthew Ahrens break; 9414843421SMatthew Ahrens 9514843421SMatthew Ahrens case DATA_TYPE_UINT64: 9614843421SMatthew Ahrens (void) nvpair_value_uint64(nvp, &ival); 9714843421SMatthew Ahrens pyval = Py_BuildValue("K", ival); 9814843421SMatthew Ahrens break; 9914843421SMatthew Ahrens 10014843421SMatthew Ahrens case DATA_TYPE_NVLIST: 10114843421SMatthew Ahrens (void) nvpair_value_nvlist(nvp, &nval); 10214843421SMatthew Ahrens pyval = nvl2py(nval); 10314843421SMatthew Ahrens break; 10414843421SMatthew Ahrens 10514843421SMatthew Ahrens case DATA_TYPE_BOOLEAN: 10614843421SMatthew Ahrens Py_INCREF(Py_None); 10714843421SMatthew Ahrens pyval = Py_None; 10814843421SMatthew Ahrens break; 10914843421SMatthew Ahrens 11014843421SMatthew Ahrens case DATA_TYPE_BOOLEAN_VALUE: 11114843421SMatthew Ahrens (void) nvpair_value_boolean_value(nvp, &bval); 11214843421SMatthew Ahrens pyval = Py_BuildValue("i", bval); 11314843421SMatthew Ahrens break; 11414843421SMatthew Ahrens 11514843421SMatthew Ahrens default: 11614843421SMatthew Ahrens PyErr_SetNone(PyExc_ValueError); 11714843421SMatthew Ahrens Py_DECREF(pyo); 11814843421SMatthew Ahrens return (NULL); 11914843421SMatthew Ahrens } 12014843421SMatthew Ahrens 12114843421SMatthew Ahrens PyDict_SetItemString(pyo, nvpair_name(nvp), pyval); 12214843421SMatthew Ahrens Py_DECREF(pyval); 12314843421SMatthew Ahrens } 12414843421SMatthew Ahrens 12514843421SMatthew Ahrens return (pyo); 12614843421SMatthew Ahrens } 12714843421SMatthew Ahrens 12814843421SMatthew Ahrens static nvlist_t * 12914843421SMatthew Ahrens dict2nvl(PyObject *d) 13014843421SMatthew Ahrens { 13114843421SMatthew Ahrens nvlist_t *nvl; 13214843421SMatthew Ahrens int err; 13314843421SMatthew Ahrens PyObject *key, *value; 13414843421SMatthew Ahrens int pos = 0; 13514843421SMatthew Ahrens 13614843421SMatthew Ahrens if (!PyDict_Check(d)) { 13714843421SMatthew Ahrens PyErr_SetObject(PyExc_ValueError, d); 13814843421SMatthew Ahrens return (NULL); 13914843421SMatthew Ahrens } 14014843421SMatthew Ahrens 14114843421SMatthew Ahrens err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); 14214843421SMatthew Ahrens assert(err == 0); 14314843421SMatthew Ahrens 14414843421SMatthew Ahrens while (PyDict_Next(d, &pos, &key, &value)) { 14514843421SMatthew Ahrens char *keystr = PyString_AsString(key); 14614843421SMatthew Ahrens if (keystr == NULL) { 14714843421SMatthew Ahrens PyErr_SetObject(PyExc_KeyError, key); 14814843421SMatthew Ahrens nvlist_free(nvl); 14914843421SMatthew Ahrens return (NULL); 15014843421SMatthew Ahrens } 15114843421SMatthew Ahrens 15214843421SMatthew Ahrens if (PyDict_Check(value)) { 15314843421SMatthew Ahrens nvlist_t *valnvl = dict2nvl(value); 15414843421SMatthew Ahrens err = nvlist_add_nvlist(nvl, keystr, valnvl); 15514843421SMatthew Ahrens nvlist_free(valnvl); 15614843421SMatthew Ahrens } else if (value == Py_None) { 15714843421SMatthew Ahrens err = nvlist_add_boolean(nvl, keystr); 15814843421SMatthew Ahrens } else if (PyString_Check(value)) { 15914843421SMatthew Ahrens char *valstr = PyString_AsString(value); 16014843421SMatthew Ahrens err = nvlist_add_string(nvl, keystr, valstr); 16114843421SMatthew Ahrens } else if (PyInt_Check(value)) { 16214843421SMatthew Ahrens uint64_t valint = PyInt_AsUnsignedLongLongMask(value); 16314843421SMatthew Ahrens err = nvlist_add_uint64(nvl, keystr, valint); 16414843421SMatthew Ahrens } else if (PyBool_Check(value)) { 16514843421SMatthew Ahrens boolean_t valbool = value == Py_True ? B_TRUE : B_FALSE; 16614843421SMatthew Ahrens err = nvlist_add_boolean_value(nvl, keystr, valbool); 16714843421SMatthew Ahrens } else { 16814843421SMatthew Ahrens PyErr_SetObject(PyExc_ValueError, value); 16914843421SMatthew Ahrens nvlist_free(nvl); 17014843421SMatthew Ahrens return (NULL); 17114843421SMatthew Ahrens } 17214843421SMatthew Ahrens assert(err == 0); 17314843421SMatthew Ahrens } 17414843421SMatthew Ahrens 17514843421SMatthew Ahrens return (nvl); 17614843421SMatthew Ahrens } 17714843421SMatthew Ahrens 17814843421SMatthew Ahrens static PyObject * 17914843421SMatthew Ahrens fakepropval(uint64_t value) 18014843421SMatthew Ahrens { 18114843421SMatthew Ahrens PyObject *d = PyDict_New(); 18214843421SMatthew Ahrens PyDict_SetItemString(d, "value", Py_BuildValue("K", value)); 18314843421SMatthew Ahrens return (d); 18414843421SMatthew Ahrens } 18514843421SMatthew Ahrens 18614843421SMatthew Ahrens static void 18714843421SMatthew Ahrens add_ds_props(zfs_cmd_t *zc, PyObject *nvl) 18814843421SMatthew Ahrens { 18914843421SMatthew Ahrens dmu_objset_stats_t *s = &zc->zc_objset_stats; 19014843421SMatthew Ahrens PyDict_SetItemString(nvl, "numclones", 19114843421SMatthew Ahrens fakepropval(s->dds_num_clones)); 19214843421SMatthew Ahrens PyDict_SetItemString(nvl, "issnap", 19314843421SMatthew Ahrens fakepropval(s->dds_is_snapshot)); 19414843421SMatthew Ahrens PyDict_SetItemString(nvl, "inconsistent", 19514843421SMatthew Ahrens fakepropval(s->dds_inconsistent)); 19614843421SMatthew Ahrens } 19714843421SMatthew Ahrens 19814843421SMatthew Ahrens /* On error, returns NULL but does not set python exception. */ 19914843421SMatthew Ahrens static PyObject * 20014843421SMatthew Ahrens ioctl_with_dstnv(int ioc, zfs_cmd_t *zc) 20114843421SMatthew Ahrens { 20214843421SMatthew Ahrens int nvsz = 2048; 20314843421SMatthew Ahrens void *nvbuf; 20414843421SMatthew Ahrens PyObject *pynv = NULL; 20514843421SMatthew Ahrens 20614843421SMatthew Ahrens again: 20714843421SMatthew Ahrens nvbuf = malloc(nvsz); 20814843421SMatthew Ahrens zc->zc_nvlist_dst_size = nvsz; 20914843421SMatthew Ahrens zc->zc_nvlist_dst = (uintptr_t)nvbuf; 21014843421SMatthew Ahrens 21114843421SMatthew Ahrens if (ioctl(zfsdevfd, ioc, zc) == 0) { 21214843421SMatthew Ahrens nvlist_t *nvl; 21314843421SMatthew Ahrens 21414843421SMatthew Ahrens errno = nvlist_unpack(nvbuf, zc->zc_nvlist_dst_size, &nvl, 0); 21514843421SMatthew Ahrens if (errno == 0) { 21614843421SMatthew Ahrens pynv = nvl2py(nvl); 21714843421SMatthew Ahrens nvlist_free(nvl); 21814843421SMatthew Ahrens } 21914843421SMatthew Ahrens } else if (errno == ENOMEM) { 22014843421SMatthew Ahrens free(nvbuf); 22114843421SMatthew Ahrens nvsz = zc->zc_nvlist_dst_size; 22214843421SMatthew Ahrens goto again; 22314843421SMatthew Ahrens } 22414843421SMatthew Ahrens free(nvbuf); 22514843421SMatthew Ahrens return (pynv); 22614843421SMatthew Ahrens } 22714843421SMatthew Ahrens 22814843421SMatthew Ahrens static PyObject * 22914843421SMatthew Ahrens py_next_dataset(PyObject *self, PyObject *args) 23014843421SMatthew Ahrens { 23114843421SMatthew Ahrens int ioc; 23214843421SMatthew Ahrens uint64_t cookie; 23314843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 23414843421SMatthew Ahrens int snaps; 23514843421SMatthew Ahrens char *name; 23614843421SMatthew Ahrens PyObject *nvl; 23714843421SMatthew Ahrens PyObject *ret = NULL; 23814843421SMatthew Ahrens 23914843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "siK", &name, &snaps, &cookie)) 24014843421SMatthew Ahrens return (NULL); 24114843421SMatthew Ahrens 24214843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 24314843421SMatthew Ahrens zc.zc_cookie = cookie; 24414843421SMatthew Ahrens 24514843421SMatthew Ahrens if (snaps) 24614843421SMatthew Ahrens ioc = ZFS_IOC_SNAPSHOT_LIST_NEXT; 24714843421SMatthew Ahrens else 24814843421SMatthew Ahrens ioc = ZFS_IOC_DATASET_LIST_NEXT; 24914843421SMatthew Ahrens 25014843421SMatthew Ahrens nvl = ioctl_with_dstnv(ioc, &zc); 25114843421SMatthew Ahrens if (nvl) { 25214843421SMatthew Ahrens add_ds_props(&zc, nvl); 25314843421SMatthew Ahrens ret = Py_BuildValue("sKO", zc.zc_name, zc.zc_cookie, nvl); 25414843421SMatthew Ahrens Py_DECREF(nvl); 25514843421SMatthew Ahrens } else if (errno == ESRCH) { 25614843421SMatthew Ahrens PyErr_SetNone(PyExc_StopIteration); 25714843421SMatthew Ahrens } else { 25814843421SMatthew Ahrens if (snaps) 25914843421SMatthew Ahrens seterr(_("cannot get snapshots of %s"), name); 26014843421SMatthew Ahrens else 26114843421SMatthew Ahrens seterr(_("cannot get child datasets of %s"), name); 26214843421SMatthew Ahrens } 26314843421SMatthew Ahrens return (ret); 26414843421SMatthew Ahrens } 26514843421SMatthew Ahrens 26614843421SMatthew Ahrens static PyObject * 26714843421SMatthew Ahrens py_dataset_props(PyObject *self, PyObject *args) 26814843421SMatthew Ahrens { 26914843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 27014843421SMatthew Ahrens int snaps; 27114843421SMatthew Ahrens char *name; 27214843421SMatthew Ahrens PyObject *nvl; 27314843421SMatthew Ahrens 27414843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 27514843421SMatthew Ahrens return (NULL); 27614843421SMatthew Ahrens 27714843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 27814843421SMatthew Ahrens 27914843421SMatthew Ahrens nvl = ioctl_with_dstnv(ZFS_IOC_OBJSET_STATS, &zc); 28014843421SMatthew Ahrens if (nvl) { 28114843421SMatthew Ahrens add_ds_props(&zc, nvl); 28214843421SMatthew Ahrens } else { 28314843421SMatthew Ahrens seterr(_("cannot access dataset %s"), name); 28414843421SMatthew Ahrens } 28514843421SMatthew Ahrens return (nvl); 28614843421SMatthew Ahrens } 28714843421SMatthew Ahrens 28814843421SMatthew Ahrens static PyObject * 28914843421SMatthew Ahrens py_get_fsacl(PyObject *self, PyObject *args) 29014843421SMatthew Ahrens { 29114843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 29214843421SMatthew Ahrens char *name; 29314843421SMatthew Ahrens PyObject *nvl; 29414843421SMatthew Ahrens 29514843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 29614843421SMatthew Ahrens return (NULL); 29714843421SMatthew Ahrens 29814843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 29914843421SMatthew Ahrens 30014843421SMatthew Ahrens nvl = ioctl_with_dstnv(ZFS_IOC_GET_FSACL, &zc); 30114843421SMatthew Ahrens if (nvl == NULL) 30214843421SMatthew Ahrens seterr(_("cannot get permissions on %s"), name); 30314843421SMatthew Ahrens 30414843421SMatthew Ahrens return (nvl); 30514843421SMatthew Ahrens } 30614843421SMatthew Ahrens 30714843421SMatthew Ahrens static PyObject * 30814843421SMatthew Ahrens py_set_fsacl(PyObject *self, PyObject *args) 30914843421SMatthew Ahrens { 31014843421SMatthew Ahrens int un; 31114843421SMatthew Ahrens size_t nvsz; 31214843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 31314843421SMatthew Ahrens char *name, *nvbuf; 31414843421SMatthew Ahrens PyObject *dict, *file; 31514843421SMatthew Ahrens nvlist_t *nvl; 31614843421SMatthew Ahrens int err; 31714843421SMatthew Ahrens 31814843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "siO!", &name, &un, 31914843421SMatthew Ahrens &PyDict_Type, &dict)) 32014843421SMatthew Ahrens return (NULL); 32114843421SMatthew Ahrens 32214843421SMatthew Ahrens nvl = dict2nvl(dict); 32314843421SMatthew Ahrens if (nvl == NULL) 32414843421SMatthew Ahrens return (NULL); 32514843421SMatthew Ahrens 32614843421SMatthew Ahrens err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE); 32714843421SMatthew Ahrens assert(err == 0); 32814843421SMatthew Ahrens nvbuf = malloc(nvsz); 32914843421SMatthew Ahrens err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0); 33014843421SMatthew Ahrens assert(err == 0); 33114843421SMatthew Ahrens 33214843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 33314843421SMatthew Ahrens zc.zc_nvlist_src_size = nvsz; 33414843421SMatthew Ahrens zc.zc_nvlist_src = (uintptr_t)nvbuf; 33514843421SMatthew Ahrens zc.zc_perm_action = un; 33614843421SMatthew Ahrens 33714843421SMatthew Ahrens err = ioctl_with_cmdstr(ZFS_IOC_SET_FSACL, &zc); 33814843421SMatthew Ahrens free(nvbuf); 33914843421SMatthew Ahrens if (err) { 34014843421SMatthew Ahrens seterr(_("cannot set permissions on %s"), name); 34114843421SMatthew Ahrens return (NULL); 34214843421SMatthew Ahrens } 34314843421SMatthew Ahrens 34414843421SMatthew Ahrens Py_RETURN_NONE; 34514843421SMatthew Ahrens } 34614843421SMatthew Ahrens 34714843421SMatthew Ahrens static PyObject * 348842727c2SChris Kirby py_get_holds(PyObject *self, PyObject *args) 349842727c2SChris Kirby { 350842727c2SChris Kirby zfs_cmd_t zc = { 0 }; 351842727c2SChris Kirby char *name; 352842727c2SChris Kirby PyObject *nvl; 353842727c2SChris Kirby 354842727c2SChris Kirby if (!PyArg_ParseTuple(args, "s", &name)) 355842727c2SChris Kirby return (NULL); 356842727c2SChris Kirby 357842727c2SChris Kirby (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 358842727c2SChris Kirby 359842727c2SChris Kirby nvl = ioctl_with_dstnv(ZFS_IOC_GET_HOLDS, &zc); 360842727c2SChris Kirby if (nvl == NULL) 361842727c2SChris Kirby seterr(_("cannot get holds for %s"), name); 362842727c2SChris Kirby 363842727c2SChris Kirby return (nvl); 364842727c2SChris Kirby } 365842727c2SChris Kirby 366842727c2SChris Kirby static PyObject * 36714843421SMatthew Ahrens py_userspace_many(PyObject *self, PyObject *args) 36814843421SMatthew Ahrens { 36914843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 37014843421SMatthew Ahrens zfs_userquota_prop_t type; 37114843421SMatthew Ahrens char *name, *propname; 37214843421SMatthew Ahrens int bufsz = 1<<20; 37314843421SMatthew Ahrens void *buf; 37414843421SMatthew Ahrens PyObject *dict, *file; 37514843421SMatthew Ahrens int error; 37614843421SMatthew Ahrens 37714843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "ss", &name, &propname)) 37814843421SMatthew Ahrens return (NULL); 37914843421SMatthew Ahrens 38014843421SMatthew Ahrens for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) 38114843421SMatthew Ahrens if (strcmp(propname, zfs_userquota_prop_prefixes[type]) == 0) 38214843421SMatthew Ahrens break; 38314843421SMatthew Ahrens if (type == ZFS_NUM_USERQUOTA_PROPS) { 38414843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, propname); 38514843421SMatthew Ahrens return (NULL); 38614843421SMatthew Ahrens } 38714843421SMatthew Ahrens 38814843421SMatthew Ahrens dict = PyDict_New(); 38914843421SMatthew Ahrens buf = malloc(bufsz); 39014843421SMatthew Ahrens 39114843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 39214843421SMatthew Ahrens zc.zc_objset_type = type; 39314843421SMatthew Ahrens zc.zc_cookie = 0; 39414843421SMatthew Ahrens 39514843421SMatthew Ahrens while (1) { 39614843421SMatthew Ahrens zfs_useracct_t *zua = buf; 39714843421SMatthew Ahrens 39814843421SMatthew Ahrens zc.zc_nvlist_dst = (uintptr_t)buf; 39914843421SMatthew Ahrens zc.zc_nvlist_dst_size = bufsz; 40014843421SMatthew Ahrens 40114843421SMatthew Ahrens error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_MANY, &zc); 40214843421SMatthew Ahrens if (error || zc.zc_nvlist_dst_size == 0) 40314843421SMatthew Ahrens break; 40414843421SMatthew Ahrens 40514843421SMatthew Ahrens while (zc.zc_nvlist_dst_size > 0) { 40614843421SMatthew Ahrens PyObject *pykey, *pyval; 40714843421SMatthew Ahrens 40814843421SMatthew Ahrens pykey = Py_BuildValue("sI", 40914843421SMatthew Ahrens zua->zu_domain, zua->zu_rid); 41014843421SMatthew Ahrens pyval = Py_BuildValue("K", zua->zu_space); 41114843421SMatthew Ahrens PyDict_SetItem(dict, pykey, pyval); 41214843421SMatthew Ahrens Py_DECREF(pykey); 41314843421SMatthew Ahrens Py_DECREF(pyval); 41414843421SMatthew Ahrens 41514843421SMatthew Ahrens zua++; 41614843421SMatthew Ahrens zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t); 41714843421SMatthew Ahrens } 41814843421SMatthew Ahrens } 41914843421SMatthew Ahrens 42014843421SMatthew Ahrens free(buf); 42114843421SMatthew Ahrens 42214843421SMatthew Ahrens if (error != 0) { 42314843421SMatthew Ahrens Py_DECREF(dict); 42414843421SMatthew Ahrens seterr(_("cannot get %s property on %s"), propname, name); 42514843421SMatthew Ahrens return (NULL); 42614843421SMatthew Ahrens } 42714843421SMatthew Ahrens 42814843421SMatthew Ahrens return (dict); 42914843421SMatthew Ahrens } 43014843421SMatthew Ahrens 43114843421SMatthew Ahrens static PyObject * 43214843421SMatthew Ahrens py_userspace_upgrade(PyObject *self, PyObject *args) 43314843421SMatthew Ahrens { 43414843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 43514843421SMatthew Ahrens char *name; 43614843421SMatthew Ahrens int error; 43714843421SMatthew Ahrens 43814843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 43914843421SMatthew Ahrens return (NULL); 44014843421SMatthew Ahrens 44114843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 44214843421SMatthew Ahrens error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_UPGRADE, &zc); 44314843421SMatthew Ahrens 44414843421SMatthew Ahrens if (error != 0) { 44514843421SMatthew Ahrens seterr(_("cannot initialize user accounting information on %s"), 44614843421SMatthew Ahrens name); 44714843421SMatthew Ahrens return (NULL); 44814843421SMatthew Ahrens } 44914843421SMatthew Ahrens 45014843421SMatthew Ahrens Py_RETURN_NONE; 45114843421SMatthew Ahrens } 45214843421SMatthew Ahrens 45314843421SMatthew Ahrens static PyObject * 45414843421SMatthew Ahrens py_set_cmdstr(PyObject *self, PyObject *args) 45514843421SMatthew Ahrens { 45614843421SMatthew Ahrens char *str; 45714843421SMatthew Ahrens 45814843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &str)) 45914843421SMatthew Ahrens return (NULL); 46014843421SMatthew Ahrens 46114843421SMatthew Ahrens (void) strlcpy(cmdstr, str, sizeof (cmdstr)); 46214843421SMatthew Ahrens 46314843421SMatthew Ahrens Py_RETURN_NONE; 46414843421SMatthew Ahrens } 46514843421SMatthew Ahrens 46614843421SMatthew Ahrens static PyObject * 46714843421SMatthew Ahrens py_get_proptable(PyObject *self, PyObject *args) 46814843421SMatthew Ahrens { 46914843421SMatthew Ahrens zprop_desc_t *t = zfs_prop_get_table(); 47014843421SMatthew Ahrens PyObject *d = PyDict_New(); 47114843421SMatthew Ahrens zfs_prop_t i; 47214843421SMatthew Ahrens 47314843421SMatthew Ahrens for (i = 0; i < ZFS_NUM_PROPS; i++) { 47414843421SMatthew Ahrens zprop_desc_t *p = &t[i]; 47514843421SMatthew Ahrens PyObject *tuple; 47614843421SMatthew Ahrens static const char *typetable[] = 47714843421SMatthew Ahrens {"number", "string", "index"}; 47814843421SMatthew Ahrens static const char *attrtable[] = 47914843421SMatthew Ahrens {"default", "readonly", "inherit", "onetime"}; 48014843421SMatthew Ahrens PyObject *indextable; 48114843421SMatthew Ahrens 48214843421SMatthew Ahrens if (p->pd_proptype == PROP_TYPE_INDEX) { 48314843421SMatthew Ahrens const zprop_index_t *it = p->pd_table; 48414843421SMatthew Ahrens indextable = PyDict_New(); 48514843421SMatthew Ahrens int j; 48614843421SMatthew Ahrens for (j = 0; it[j].pi_name; j++) { 48714843421SMatthew Ahrens PyDict_SetItemString(indextable, 48814843421SMatthew Ahrens it[j].pi_name, 48914843421SMatthew Ahrens Py_BuildValue("K", it[j].pi_value)); 49014843421SMatthew Ahrens } 49114843421SMatthew Ahrens } else { 49214843421SMatthew Ahrens Py_INCREF(Py_None); 49314843421SMatthew Ahrens indextable = Py_None; 49414843421SMatthew Ahrens } 49514843421SMatthew Ahrens 49614843421SMatthew Ahrens tuple = Py_BuildValue("sissKsissiiO", 49714843421SMatthew Ahrens p->pd_name, p->pd_propnum, typetable[p->pd_proptype], 49814843421SMatthew Ahrens p->pd_strdefault, p->pd_numdefault, 49914843421SMatthew Ahrens attrtable[p->pd_attr], p->pd_types, 50014843421SMatthew Ahrens p->pd_values, p->pd_colname, 50114843421SMatthew Ahrens p->pd_rightalign, p->pd_visible, indextable); 50214843421SMatthew Ahrens PyDict_SetItemString(d, p->pd_name, tuple); 50314843421SMatthew Ahrens Py_DECREF(tuple); 50414843421SMatthew Ahrens } 50514843421SMatthew Ahrens 50614843421SMatthew Ahrens return (d); 50714843421SMatthew Ahrens } 50814843421SMatthew Ahrens 50914843421SMatthew Ahrens static PyMethodDef zfsmethods[] = { 51014843421SMatthew Ahrens {"next_dataset", py_next_dataset, METH_VARARGS, 51114843421SMatthew Ahrens "Get next child dataset or snapshot."}, 51214843421SMatthew Ahrens {"get_fsacl", py_get_fsacl, METH_VARARGS, "Get allowed permissions."}, 51314843421SMatthew Ahrens {"set_fsacl", py_set_fsacl, METH_VARARGS, "Set allowed permissions."}, 51414843421SMatthew Ahrens {"userspace_many", py_userspace_many, METH_VARARGS, 51514843421SMatthew Ahrens "Get user space accounting."}, 51614843421SMatthew Ahrens {"userspace_upgrade", py_userspace_upgrade, METH_VARARGS, 51714843421SMatthew Ahrens "Upgrade fs to enable user space accounting."}, 51814843421SMatthew Ahrens {"set_cmdstr", py_set_cmdstr, METH_VARARGS, 51914843421SMatthew Ahrens "Set command string for history logging."}, 52014843421SMatthew Ahrens {"dataset_props", py_dataset_props, METH_VARARGS, 52114843421SMatthew Ahrens "Get dataset properties."}, 52214843421SMatthew Ahrens {"get_proptable", py_get_proptable, METH_NOARGS, 52314843421SMatthew Ahrens "Get property table."}, 524842727c2SChris Kirby {"get_holds", py_get_holds, METH_VARARGS, "Get user holds."}, 52514843421SMatthew Ahrens {NULL, NULL, 0, NULL} 52614843421SMatthew Ahrens }; 52714843421SMatthew Ahrens 52814843421SMatthew Ahrens void 52914843421SMatthew Ahrens initioctl(void) 53014843421SMatthew Ahrens { 53114843421SMatthew Ahrens PyObject *zfs_ioctl = Py_InitModule("zfs.ioctl", zfsmethods); 53214843421SMatthew Ahrens PyObject *zfs_util = PyImport_ImportModule("zfs.util"); 53314843421SMatthew Ahrens PyObject *devfile; 53414843421SMatthew Ahrens 53514843421SMatthew Ahrens if (zfs_util == NULL) 53614843421SMatthew Ahrens return; 53714843421SMatthew Ahrens 53814843421SMatthew Ahrens ZFSError = PyObject_GetAttrString(zfs_util, "ZFSError"); 53914843421SMatthew Ahrens devfile = PyObject_GetAttrString(zfs_util, "dev"); 54014843421SMatthew Ahrens zfsdevfd = PyObject_AsFileDescriptor(devfile); 54114843421SMatthew Ahrens 54214843421SMatthew Ahrens zfs_prop_init(); 54314843421SMatthew Ahrens } 544