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 /* 2214843421SMatthew Ahrens * Copyright 2009 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 <idmap.h> 3314843421SMatthew Ahrens #include <zone.h> 3414843421SMatthew Ahrens #include <libintl.h> 3514843421SMatthew Ahrens #include <libzfs.h> 36*3b12c289SMatthew Ahrens #include <directory.h> 3714843421SMatthew Ahrens #include "zfs_prop.h" 3814843421SMatthew Ahrens 3914843421SMatthew Ahrens static PyObject *ZFSError; 4014843421SMatthew Ahrens static int zfsdevfd; 4114843421SMatthew Ahrens 4214843421SMatthew Ahrens #ifdef __lint 4314843421SMatthew Ahrens #define dgettext(x, y) y 4414843421SMatthew Ahrens #endif 4514843421SMatthew Ahrens 4614843421SMatthew Ahrens #define _(s) dgettext(TEXT_DOMAIN, s) 4714843421SMatthew Ahrens 4814843421SMatthew Ahrens extern int sid_to_id(char *sid, boolean_t user, uid_t *id); 4914843421SMatthew Ahrens 5014843421SMatthew Ahrens /*PRINTFLIKE1*/ 5114843421SMatthew Ahrens static void 5214843421SMatthew Ahrens seterr(char *fmt, ...) 5314843421SMatthew Ahrens { 5414843421SMatthew Ahrens char errstr[1024]; 5514843421SMatthew Ahrens va_list v; 5614843421SMatthew Ahrens 5714843421SMatthew Ahrens va_start(v, fmt); 5814843421SMatthew Ahrens (void) vsnprintf(errstr, sizeof (errstr), fmt, v); 5914843421SMatthew Ahrens va_end(v); 6014843421SMatthew Ahrens 6114843421SMatthew Ahrens PyErr_SetObject(ZFSError, Py_BuildValue("is", errno, errstr)); 6214843421SMatthew Ahrens } 6314843421SMatthew Ahrens 6414843421SMatthew Ahrens static char cmdstr[HIS_MAX_RECORD_LEN]; 6514843421SMatthew Ahrens 6614843421SMatthew Ahrens static int 6714843421SMatthew Ahrens ioctl_with_cmdstr(int ioc, zfs_cmd_t *zc) 6814843421SMatthew Ahrens { 6914843421SMatthew Ahrens int err; 7014843421SMatthew Ahrens 7114843421SMatthew Ahrens if (cmdstr[0]) 7214843421SMatthew Ahrens zc->zc_history = (uint64_t)(uintptr_t)cmdstr; 7314843421SMatthew Ahrens err = ioctl(zfsdevfd, ioc, zc); 7414843421SMatthew Ahrens cmdstr[0] = '\0'; 7514843421SMatthew Ahrens return (err); 7614843421SMatthew Ahrens } 7714843421SMatthew Ahrens 7814843421SMatthew Ahrens static PyObject * 7914843421SMatthew Ahrens nvl2py(nvlist_t *nvl) 8014843421SMatthew Ahrens { 8114843421SMatthew Ahrens PyObject *pyo; 8214843421SMatthew Ahrens nvpair_t *nvp; 8314843421SMatthew Ahrens 8414843421SMatthew Ahrens pyo = PyDict_New(); 8514843421SMatthew Ahrens 8614843421SMatthew Ahrens for (nvp = nvlist_next_nvpair(nvl, NULL); nvp; 8714843421SMatthew Ahrens nvp = nvlist_next_nvpair(nvl, nvp)) { 8814843421SMatthew Ahrens PyObject *pyval; 8914843421SMatthew Ahrens char *sval; 9014843421SMatthew Ahrens uint64_t ival; 9114843421SMatthew Ahrens boolean_t bval; 9214843421SMatthew Ahrens nvlist_t *nval; 9314843421SMatthew Ahrens 9414843421SMatthew Ahrens switch (nvpair_type(nvp)) { 9514843421SMatthew Ahrens case DATA_TYPE_STRING: 9614843421SMatthew Ahrens (void) nvpair_value_string(nvp, &sval); 9714843421SMatthew Ahrens pyval = Py_BuildValue("s", sval); 9814843421SMatthew Ahrens break; 9914843421SMatthew Ahrens 10014843421SMatthew Ahrens case DATA_TYPE_UINT64: 10114843421SMatthew Ahrens (void) nvpair_value_uint64(nvp, &ival); 10214843421SMatthew Ahrens pyval = Py_BuildValue("K", ival); 10314843421SMatthew Ahrens break; 10414843421SMatthew Ahrens 10514843421SMatthew Ahrens case DATA_TYPE_NVLIST: 10614843421SMatthew Ahrens (void) nvpair_value_nvlist(nvp, &nval); 10714843421SMatthew Ahrens pyval = nvl2py(nval); 10814843421SMatthew Ahrens break; 10914843421SMatthew Ahrens 11014843421SMatthew Ahrens case DATA_TYPE_BOOLEAN: 11114843421SMatthew Ahrens Py_INCREF(Py_None); 11214843421SMatthew Ahrens pyval = Py_None; 11314843421SMatthew Ahrens break; 11414843421SMatthew Ahrens 11514843421SMatthew Ahrens case DATA_TYPE_BOOLEAN_VALUE: 11614843421SMatthew Ahrens (void) nvpair_value_boolean_value(nvp, &bval); 11714843421SMatthew Ahrens pyval = Py_BuildValue("i", bval); 11814843421SMatthew Ahrens break; 11914843421SMatthew Ahrens 12014843421SMatthew Ahrens default: 12114843421SMatthew Ahrens PyErr_SetNone(PyExc_ValueError); 12214843421SMatthew Ahrens Py_DECREF(pyo); 12314843421SMatthew Ahrens return (NULL); 12414843421SMatthew Ahrens } 12514843421SMatthew Ahrens 12614843421SMatthew Ahrens PyDict_SetItemString(pyo, nvpair_name(nvp), pyval); 12714843421SMatthew Ahrens Py_DECREF(pyval); 12814843421SMatthew Ahrens } 12914843421SMatthew Ahrens 13014843421SMatthew Ahrens return (pyo); 13114843421SMatthew Ahrens } 13214843421SMatthew Ahrens 13314843421SMatthew Ahrens static nvlist_t * 13414843421SMatthew Ahrens dict2nvl(PyObject *d) 13514843421SMatthew Ahrens { 13614843421SMatthew Ahrens nvlist_t *nvl; 13714843421SMatthew Ahrens int err; 13814843421SMatthew Ahrens PyObject *key, *value; 13914843421SMatthew Ahrens int pos = 0; 14014843421SMatthew Ahrens 14114843421SMatthew Ahrens if (!PyDict_Check(d)) { 14214843421SMatthew Ahrens PyErr_SetObject(PyExc_ValueError, d); 14314843421SMatthew Ahrens return (NULL); 14414843421SMatthew Ahrens } 14514843421SMatthew Ahrens 14614843421SMatthew Ahrens err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); 14714843421SMatthew Ahrens assert(err == 0); 14814843421SMatthew Ahrens 14914843421SMatthew Ahrens while (PyDict_Next(d, &pos, &key, &value)) { 15014843421SMatthew Ahrens char *keystr = PyString_AsString(key); 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); 16314843421SMatthew Ahrens } else if (PyString_Check(value)) { 16414843421SMatthew Ahrens char *valstr = PyString_AsString(value); 16514843421SMatthew Ahrens err = nvlist_add_string(nvl, keystr, valstr); 16614843421SMatthew Ahrens } else if (PyInt_Check(value)) { 16714843421SMatthew Ahrens uint64_t valint = PyInt_AsUnsignedLongLongMask(value); 16814843421SMatthew Ahrens err = nvlist_add_uint64(nvl, keystr, valint); 16914843421SMatthew Ahrens } else if (PyBool_Check(value)) { 17014843421SMatthew Ahrens boolean_t valbool = value == Py_True ? B_TRUE : B_FALSE; 17114843421SMatthew Ahrens err = nvlist_add_boolean_value(nvl, keystr, valbool); 17214843421SMatthew Ahrens } else { 17314843421SMatthew Ahrens PyErr_SetObject(PyExc_ValueError, value); 17414843421SMatthew Ahrens nvlist_free(nvl); 17514843421SMatthew Ahrens return (NULL); 17614843421SMatthew Ahrens } 17714843421SMatthew Ahrens assert(err == 0); 17814843421SMatthew Ahrens } 17914843421SMatthew Ahrens 18014843421SMatthew Ahrens return (nvl); 18114843421SMatthew Ahrens } 18214843421SMatthew Ahrens 18314843421SMatthew Ahrens static PyObject * 18414843421SMatthew Ahrens fakepropval(uint64_t value) 18514843421SMatthew Ahrens { 18614843421SMatthew Ahrens PyObject *d = PyDict_New(); 18714843421SMatthew Ahrens PyDict_SetItemString(d, "value", Py_BuildValue("K", value)); 18814843421SMatthew Ahrens return (d); 18914843421SMatthew Ahrens } 19014843421SMatthew Ahrens 19114843421SMatthew Ahrens static void 19214843421SMatthew Ahrens add_ds_props(zfs_cmd_t *zc, PyObject *nvl) 19314843421SMatthew Ahrens { 19414843421SMatthew Ahrens dmu_objset_stats_t *s = &zc->zc_objset_stats; 19514843421SMatthew Ahrens PyDict_SetItemString(nvl, "numclones", 19614843421SMatthew Ahrens fakepropval(s->dds_num_clones)); 19714843421SMatthew Ahrens PyDict_SetItemString(nvl, "issnap", 19814843421SMatthew Ahrens fakepropval(s->dds_is_snapshot)); 19914843421SMatthew Ahrens PyDict_SetItemString(nvl, "inconsistent", 20014843421SMatthew Ahrens fakepropval(s->dds_inconsistent)); 20114843421SMatthew Ahrens } 20214843421SMatthew Ahrens 20314843421SMatthew Ahrens /* On error, returns NULL but does not set python exception. */ 20414843421SMatthew Ahrens static PyObject * 20514843421SMatthew Ahrens ioctl_with_dstnv(int ioc, zfs_cmd_t *zc) 20614843421SMatthew Ahrens { 20714843421SMatthew Ahrens int nvsz = 2048; 20814843421SMatthew Ahrens void *nvbuf; 20914843421SMatthew Ahrens PyObject *pynv = NULL; 21014843421SMatthew Ahrens 21114843421SMatthew Ahrens again: 21214843421SMatthew Ahrens nvbuf = malloc(nvsz); 21314843421SMatthew Ahrens zc->zc_nvlist_dst_size = nvsz; 21414843421SMatthew Ahrens zc->zc_nvlist_dst = (uintptr_t)nvbuf; 21514843421SMatthew Ahrens 21614843421SMatthew Ahrens if (ioctl(zfsdevfd, ioc, zc) == 0) { 21714843421SMatthew Ahrens nvlist_t *nvl; 21814843421SMatthew Ahrens 21914843421SMatthew Ahrens errno = nvlist_unpack(nvbuf, zc->zc_nvlist_dst_size, &nvl, 0); 22014843421SMatthew Ahrens if (errno == 0) { 22114843421SMatthew Ahrens pynv = nvl2py(nvl); 22214843421SMatthew Ahrens nvlist_free(nvl); 22314843421SMatthew Ahrens } 22414843421SMatthew Ahrens } else if (errno == ENOMEM) { 22514843421SMatthew Ahrens free(nvbuf); 22614843421SMatthew Ahrens nvsz = zc->zc_nvlist_dst_size; 22714843421SMatthew Ahrens goto again; 22814843421SMatthew Ahrens } 22914843421SMatthew Ahrens free(nvbuf); 23014843421SMatthew Ahrens return (pynv); 23114843421SMatthew Ahrens } 23214843421SMatthew Ahrens 23314843421SMatthew Ahrens static PyObject * 23414843421SMatthew Ahrens py_next_dataset(PyObject *self, PyObject *args) 23514843421SMatthew Ahrens { 23614843421SMatthew Ahrens int ioc; 23714843421SMatthew Ahrens uint64_t cookie; 23814843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 23914843421SMatthew Ahrens int snaps; 24014843421SMatthew Ahrens char *name; 24114843421SMatthew Ahrens PyObject *nvl; 24214843421SMatthew Ahrens PyObject *ret = NULL; 24314843421SMatthew Ahrens 24414843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "siK", &name, &snaps, &cookie)) 24514843421SMatthew Ahrens return (NULL); 24614843421SMatthew Ahrens 24714843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 24814843421SMatthew Ahrens zc.zc_cookie = cookie; 24914843421SMatthew Ahrens 25014843421SMatthew Ahrens if (snaps) 25114843421SMatthew Ahrens ioc = ZFS_IOC_SNAPSHOT_LIST_NEXT; 25214843421SMatthew Ahrens else 25314843421SMatthew Ahrens ioc = ZFS_IOC_DATASET_LIST_NEXT; 25414843421SMatthew Ahrens 25514843421SMatthew Ahrens nvl = ioctl_with_dstnv(ioc, &zc); 25614843421SMatthew Ahrens if (nvl) { 25714843421SMatthew Ahrens add_ds_props(&zc, nvl); 25814843421SMatthew Ahrens ret = Py_BuildValue("sKO", zc.zc_name, zc.zc_cookie, nvl); 25914843421SMatthew Ahrens Py_DECREF(nvl); 26014843421SMatthew Ahrens } else if (errno == ESRCH) { 26114843421SMatthew Ahrens PyErr_SetNone(PyExc_StopIteration); 26214843421SMatthew Ahrens } else { 26314843421SMatthew Ahrens if (snaps) 26414843421SMatthew Ahrens seterr(_("cannot get snapshots of %s"), name); 26514843421SMatthew Ahrens else 26614843421SMatthew Ahrens seterr(_("cannot get child datasets of %s"), name); 26714843421SMatthew Ahrens } 26814843421SMatthew Ahrens return (ret); 26914843421SMatthew Ahrens } 27014843421SMatthew Ahrens 27114843421SMatthew Ahrens static PyObject * 27214843421SMatthew Ahrens py_dataset_props(PyObject *self, PyObject *args) 27314843421SMatthew Ahrens { 27414843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 27514843421SMatthew Ahrens int snaps; 27614843421SMatthew Ahrens char *name; 27714843421SMatthew Ahrens PyObject *nvl; 27814843421SMatthew Ahrens 27914843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 28014843421SMatthew Ahrens return (NULL); 28114843421SMatthew Ahrens 28214843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 28314843421SMatthew Ahrens 28414843421SMatthew Ahrens nvl = ioctl_with_dstnv(ZFS_IOC_OBJSET_STATS, &zc); 28514843421SMatthew Ahrens if (nvl) { 28614843421SMatthew Ahrens add_ds_props(&zc, nvl); 28714843421SMatthew Ahrens } else { 28814843421SMatthew Ahrens seterr(_("cannot access dataset %s"), name); 28914843421SMatthew Ahrens } 29014843421SMatthew Ahrens return (nvl); 29114843421SMatthew Ahrens } 29214843421SMatthew Ahrens 29314843421SMatthew Ahrens static PyObject * 29414843421SMatthew Ahrens py_get_fsacl(PyObject *self, PyObject *args) 29514843421SMatthew Ahrens { 29614843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 29714843421SMatthew Ahrens char *name; 29814843421SMatthew Ahrens PyObject *nvl; 29914843421SMatthew Ahrens 30014843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 30114843421SMatthew Ahrens return (NULL); 30214843421SMatthew Ahrens 30314843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 30414843421SMatthew Ahrens 30514843421SMatthew Ahrens nvl = ioctl_with_dstnv(ZFS_IOC_GET_FSACL, &zc); 30614843421SMatthew Ahrens if (nvl == NULL) 30714843421SMatthew Ahrens seterr(_("cannot get permissions on %s"), name); 30814843421SMatthew Ahrens 30914843421SMatthew Ahrens return (nvl); 31014843421SMatthew Ahrens } 31114843421SMatthew Ahrens 31214843421SMatthew Ahrens static PyObject * 31314843421SMatthew Ahrens py_set_fsacl(PyObject *self, PyObject *args) 31414843421SMatthew Ahrens { 31514843421SMatthew Ahrens int un; 31614843421SMatthew Ahrens size_t nvsz; 31714843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 31814843421SMatthew Ahrens char *name, *nvbuf; 31914843421SMatthew Ahrens PyObject *dict, *file; 32014843421SMatthew Ahrens nvlist_t *nvl; 32114843421SMatthew Ahrens int err; 32214843421SMatthew Ahrens 32314843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "siO!", &name, &un, 32414843421SMatthew Ahrens &PyDict_Type, &dict)) 32514843421SMatthew Ahrens return (NULL); 32614843421SMatthew Ahrens 32714843421SMatthew Ahrens nvl = dict2nvl(dict); 32814843421SMatthew Ahrens if (nvl == NULL) 32914843421SMatthew Ahrens return (NULL); 33014843421SMatthew Ahrens 33114843421SMatthew Ahrens err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE); 33214843421SMatthew Ahrens assert(err == 0); 33314843421SMatthew Ahrens nvbuf = malloc(nvsz); 33414843421SMatthew Ahrens err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0); 33514843421SMatthew Ahrens assert(err == 0); 33614843421SMatthew Ahrens 33714843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 33814843421SMatthew Ahrens zc.zc_nvlist_src_size = nvsz; 33914843421SMatthew Ahrens zc.zc_nvlist_src = (uintptr_t)nvbuf; 34014843421SMatthew Ahrens zc.zc_perm_action = un; 34114843421SMatthew Ahrens 34214843421SMatthew Ahrens err = ioctl_with_cmdstr(ZFS_IOC_SET_FSACL, &zc); 34314843421SMatthew Ahrens free(nvbuf); 34414843421SMatthew Ahrens if (err) { 34514843421SMatthew Ahrens seterr(_("cannot set permissions on %s"), name); 34614843421SMatthew Ahrens return (NULL); 34714843421SMatthew Ahrens } 34814843421SMatthew Ahrens 34914843421SMatthew Ahrens Py_RETURN_NONE; 35014843421SMatthew Ahrens } 35114843421SMatthew Ahrens 35214843421SMatthew Ahrens static PyObject * 35314843421SMatthew Ahrens py_userspace_many(PyObject *self, PyObject *args) 35414843421SMatthew Ahrens { 35514843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 35614843421SMatthew Ahrens zfs_userquota_prop_t type; 35714843421SMatthew Ahrens char *name, *propname; 35814843421SMatthew Ahrens int bufsz = 1<<20; 35914843421SMatthew Ahrens void *buf; 36014843421SMatthew Ahrens PyObject *dict, *file; 36114843421SMatthew Ahrens int error; 36214843421SMatthew Ahrens 36314843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "ss", &name, &propname)) 36414843421SMatthew Ahrens return (NULL); 36514843421SMatthew Ahrens 36614843421SMatthew Ahrens for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) 36714843421SMatthew Ahrens if (strcmp(propname, zfs_userquota_prop_prefixes[type]) == 0) 36814843421SMatthew Ahrens break; 36914843421SMatthew Ahrens if (type == ZFS_NUM_USERQUOTA_PROPS) { 37014843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, propname); 37114843421SMatthew Ahrens return (NULL); 37214843421SMatthew Ahrens } 37314843421SMatthew Ahrens 37414843421SMatthew Ahrens dict = PyDict_New(); 37514843421SMatthew Ahrens buf = malloc(bufsz); 37614843421SMatthew Ahrens 37714843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 37814843421SMatthew Ahrens zc.zc_objset_type = type; 37914843421SMatthew Ahrens zc.zc_cookie = 0; 38014843421SMatthew Ahrens 38114843421SMatthew Ahrens while (1) { 38214843421SMatthew Ahrens zfs_useracct_t *zua = buf; 38314843421SMatthew Ahrens 38414843421SMatthew Ahrens zc.zc_nvlist_dst = (uintptr_t)buf; 38514843421SMatthew Ahrens zc.zc_nvlist_dst_size = bufsz; 38614843421SMatthew Ahrens 38714843421SMatthew Ahrens error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_MANY, &zc); 38814843421SMatthew Ahrens if (error || zc.zc_nvlist_dst_size == 0) 38914843421SMatthew Ahrens break; 39014843421SMatthew Ahrens 39114843421SMatthew Ahrens while (zc.zc_nvlist_dst_size > 0) { 39214843421SMatthew Ahrens PyObject *pykey, *pyval; 39314843421SMatthew Ahrens 39414843421SMatthew Ahrens pykey = Py_BuildValue("sI", 39514843421SMatthew Ahrens zua->zu_domain, zua->zu_rid); 39614843421SMatthew Ahrens pyval = Py_BuildValue("K", zua->zu_space); 39714843421SMatthew Ahrens PyDict_SetItem(dict, pykey, pyval); 39814843421SMatthew Ahrens Py_DECREF(pykey); 39914843421SMatthew Ahrens Py_DECREF(pyval); 40014843421SMatthew Ahrens 40114843421SMatthew Ahrens zua++; 40214843421SMatthew Ahrens zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t); 40314843421SMatthew Ahrens } 40414843421SMatthew Ahrens } 40514843421SMatthew Ahrens 40614843421SMatthew Ahrens free(buf); 40714843421SMatthew Ahrens 40814843421SMatthew Ahrens if (error != 0) { 40914843421SMatthew Ahrens Py_DECREF(dict); 41014843421SMatthew Ahrens seterr(_("cannot get %s property on %s"), propname, name); 41114843421SMatthew Ahrens return (NULL); 41214843421SMatthew Ahrens } 41314843421SMatthew Ahrens 41414843421SMatthew Ahrens return (dict); 41514843421SMatthew Ahrens } 41614843421SMatthew Ahrens 41714843421SMatthew Ahrens static PyObject * 41814843421SMatthew Ahrens py_userspace_upgrade(PyObject *self, PyObject *args) 41914843421SMatthew Ahrens { 42014843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 42114843421SMatthew Ahrens char *name; 42214843421SMatthew Ahrens int error; 42314843421SMatthew Ahrens 42414843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 42514843421SMatthew Ahrens return (NULL); 42614843421SMatthew Ahrens 42714843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 42814843421SMatthew Ahrens error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_UPGRADE, &zc); 42914843421SMatthew Ahrens 43014843421SMatthew Ahrens if (error != 0) { 43114843421SMatthew Ahrens seterr(_("cannot initialize user accounting information on %s"), 43214843421SMatthew Ahrens name); 43314843421SMatthew Ahrens return (NULL); 43414843421SMatthew Ahrens } 43514843421SMatthew Ahrens 43614843421SMatthew Ahrens Py_RETURN_NONE; 43714843421SMatthew Ahrens } 43814843421SMatthew Ahrens 43914843421SMatthew Ahrens static PyObject * 44014843421SMatthew Ahrens py_sid_to_id(PyObject *self, PyObject *args) 44114843421SMatthew Ahrens { 44214843421SMatthew Ahrens char *sid; 44314843421SMatthew Ahrens int err, isuser; 44414843421SMatthew Ahrens uid_t id; 44514843421SMatthew Ahrens 44614843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "si", &sid, &isuser)) 44714843421SMatthew Ahrens return (NULL); 44814843421SMatthew Ahrens 44914843421SMatthew Ahrens err = sid_to_id(sid, isuser, &id); 45014843421SMatthew Ahrens if (err) { 45114843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, sid); 45214843421SMatthew Ahrens return (NULL); 45314843421SMatthew Ahrens } 45414843421SMatthew Ahrens 45514843421SMatthew Ahrens return (Py_BuildValue("I", id)); 45614843421SMatthew Ahrens } 45714843421SMatthew Ahrens 45814843421SMatthew Ahrens /* 45914843421SMatthew Ahrens * Translate the sid string ("S-1-...") to the user@domain name, if 460*3b12c289SMatthew Ahrens * possible. 46114843421SMatthew Ahrens */ 46214843421SMatthew Ahrens static PyObject * 46314843421SMatthew Ahrens py_sid_to_name(PyObject *self, PyObject *args) 46414843421SMatthew Ahrens { 465*3b12c289SMatthew Ahrens int isuser; 466*3b12c289SMatthew Ahrens char *name, *sid; 467*3b12c289SMatthew Ahrens directory_error_t e; 468*3b12c289SMatthew Ahrens uint64_t classes; 469*3b12c289SMatthew Ahrens PyObject *ret; 47014843421SMatthew Ahrens 47114843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "si", &sid, &isuser)) 47214843421SMatthew Ahrens return (NULL); 473*3b12c289SMatthew Ahrens e = directory_name_from_sid(NULL, sid, &name, &classes); 474*3b12c289SMatthew Ahrens if (e != NULL) { 475*3b12c289SMatthew Ahrens directory_error_free(e); 47614843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, sid); 47714843421SMatthew Ahrens return (NULL); 47814843421SMatthew Ahrens } 479*3b12c289SMatthew Ahrens if (name == NULL) { 480*3b12c289SMatthew Ahrens PyErr_SetString(PyExc_KeyError, sid); 481*3b12c289SMatthew Ahrens return (NULL); 482*3b12c289SMatthew Ahrens } 48314843421SMatthew Ahrens if (isuser) { 484*3b12c289SMatthew Ahrens if (!(classes & DIRECTORY_CLASS_USER)) { 485*3b12c289SMatthew Ahrens free(name); 48614843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, sid); 48714843421SMatthew Ahrens return (NULL); 48814843421SMatthew Ahrens } 489*3b12c289SMatthew Ahrens } else { 490*3b12c289SMatthew Ahrens if (!(classes & DIRECTORY_CLASS_GROUP)) { 49114843421SMatthew Ahrens free(name); 492*3b12c289SMatthew Ahrens PyErr_SetString(PyExc_KeyError, sid); 493*3b12c289SMatthew Ahrens return (NULL); 494*3b12c289SMatthew Ahrens } 495*3b12c289SMatthew Ahrens } 49614843421SMatthew Ahrens 497*3b12c289SMatthew Ahrens ret = PyString_FromString(name); 498*3b12c289SMatthew Ahrens free(name); 499*3b12c289SMatthew Ahrens return (ret); 50014843421SMatthew Ahrens } 50114843421SMatthew Ahrens 50214843421SMatthew Ahrens static PyObject * 50314843421SMatthew Ahrens py_isglobalzone(PyObject *self, PyObject *args) 50414843421SMatthew Ahrens { 50514843421SMatthew Ahrens return (Py_BuildValue("i", getzoneid() == GLOBAL_ZONEID)); 50614843421SMatthew Ahrens } 50714843421SMatthew Ahrens 50814843421SMatthew Ahrens static PyObject * 50914843421SMatthew Ahrens py_set_cmdstr(PyObject *self, PyObject *args) 51014843421SMatthew Ahrens { 51114843421SMatthew Ahrens char *str; 51214843421SMatthew Ahrens 51314843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &str)) 51414843421SMatthew Ahrens return (NULL); 51514843421SMatthew Ahrens 51614843421SMatthew Ahrens (void) strlcpy(cmdstr, str, sizeof (cmdstr)); 51714843421SMatthew Ahrens 51814843421SMatthew Ahrens Py_RETURN_NONE; 51914843421SMatthew Ahrens } 52014843421SMatthew Ahrens 52114843421SMatthew Ahrens static PyObject * 52214843421SMatthew Ahrens py_get_proptable(PyObject *self, PyObject *args) 52314843421SMatthew Ahrens { 52414843421SMatthew Ahrens zprop_desc_t *t = zfs_prop_get_table(); 52514843421SMatthew Ahrens PyObject *d = PyDict_New(); 52614843421SMatthew Ahrens zfs_prop_t i; 52714843421SMatthew Ahrens 52814843421SMatthew Ahrens for (i = 0; i < ZFS_NUM_PROPS; i++) { 52914843421SMatthew Ahrens zprop_desc_t *p = &t[i]; 53014843421SMatthew Ahrens PyObject *tuple; 53114843421SMatthew Ahrens static const char *typetable[] = 53214843421SMatthew Ahrens {"number", "string", "index"}; 53314843421SMatthew Ahrens static const char *attrtable[] = 53414843421SMatthew Ahrens {"default", "readonly", "inherit", "onetime"}; 53514843421SMatthew Ahrens PyObject *indextable; 53614843421SMatthew Ahrens 53714843421SMatthew Ahrens if (p->pd_proptype == PROP_TYPE_INDEX) { 53814843421SMatthew Ahrens const zprop_index_t *it = p->pd_table; 53914843421SMatthew Ahrens indextable = PyDict_New(); 54014843421SMatthew Ahrens int j; 54114843421SMatthew Ahrens for (j = 0; it[j].pi_name; j++) { 54214843421SMatthew Ahrens PyDict_SetItemString(indextable, 54314843421SMatthew Ahrens it[j].pi_name, 54414843421SMatthew Ahrens Py_BuildValue("K", it[j].pi_value)); 54514843421SMatthew Ahrens } 54614843421SMatthew Ahrens } else { 54714843421SMatthew Ahrens Py_INCREF(Py_None); 54814843421SMatthew Ahrens indextable = Py_None; 54914843421SMatthew Ahrens } 55014843421SMatthew Ahrens 55114843421SMatthew Ahrens tuple = Py_BuildValue("sissKsissiiO", 55214843421SMatthew Ahrens p->pd_name, p->pd_propnum, typetable[p->pd_proptype], 55314843421SMatthew Ahrens p->pd_strdefault, p->pd_numdefault, 55414843421SMatthew Ahrens attrtable[p->pd_attr], p->pd_types, 55514843421SMatthew Ahrens p->pd_values, p->pd_colname, 55614843421SMatthew Ahrens p->pd_rightalign, p->pd_visible, indextable); 55714843421SMatthew Ahrens PyDict_SetItemString(d, p->pd_name, tuple); 55814843421SMatthew Ahrens Py_DECREF(tuple); 55914843421SMatthew Ahrens } 56014843421SMatthew Ahrens 56114843421SMatthew Ahrens return (d); 56214843421SMatthew Ahrens } 56314843421SMatthew Ahrens 56414843421SMatthew Ahrens static PyMethodDef zfsmethods[] = { 56514843421SMatthew Ahrens {"next_dataset", py_next_dataset, METH_VARARGS, 56614843421SMatthew Ahrens "Get next child dataset or snapshot."}, 56714843421SMatthew Ahrens {"get_fsacl", py_get_fsacl, METH_VARARGS, "Get allowed permissions."}, 56814843421SMatthew Ahrens {"set_fsacl", py_set_fsacl, METH_VARARGS, "Set allowed permissions."}, 56914843421SMatthew Ahrens {"userspace_many", py_userspace_many, METH_VARARGS, 57014843421SMatthew Ahrens "Get user space accounting."}, 57114843421SMatthew Ahrens {"userspace_upgrade", py_userspace_upgrade, METH_VARARGS, 57214843421SMatthew Ahrens "Upgrade fs to enable user space accounting."}, 57314843421SMatthew Ahrens {"set_cmdstr", py_set_cmdstr, METH_VARARGS, 57414843421SMatthew Ahrens "Set command string for history logging."}, 57514843421SMatthew Ahrens {"dataset_props", py_dataset_props, METH_VARARGS, 57614843421SMatthew Ahrens "Get dataset properties."}, 57714843421SMatthew Ahrens {"get_proptable", py_get_proptable, METH_NOARGS, 57814843421SMatthew Ahrens "Get property table."}, 57914843421SMatthew Ahrens /* Below are not really zfs-specific: */ 58014843421SMatthew Ahrens {"sid_to_id", py_sid_to_id, METH_VARARGS, "Map SID to UID/GID."}, 58114843421SMatthew Ahrens {"sid_to_name", py_sid_to_name, METH_VARARGS, 58214843421SMatthew Ahrens "Map SID to name@domain."}, 58314843421SMatthew Ahrens {"isglobalzone", py_isglobalzone, METH_NOARGS, 58414843421SMatthew Ahrens "Determine if this is the global zone."}, 58514843421SMatthew Ahrens {NULL, NULL, 0, NULL} 58614843421SMatthew Ahrens }; 58714843421SMatthew Ahrens 58814843421SMatthew Ahrens void 58914843421SMatthew Ahrens initioctl(void) 59014843421SMatthew Ahrens { 59114843421SMatthew Ahrens PyObject *zfs_ioctl = Py_InitModule("zfs.ioctl", zfsmethods); 59214843421SMatthew Ahrens PyObject *zfs_util = PyImport_ImportModule("zfs.util"); 59314843421SMatthew Ahrens PyObject *devfile; 59414843421SMatthew Ahrens 59514843421SMatthew Ahrens if (zfs_util == NULL) 59614843421SMatthew Ahrens return; 59714843421SMatthew Ahrens 59814843421SMatthew Ahrens ZFSError = PyObject_GetAttrString(zfs_util, "ZFSError"); 59914843421SMatthew Ahrens devfile = PyObject_GetAttrString(zfs_util, "dev"); 60014843421SMatthew Ahrens zfsdevfd = PyObject_AsFileDescriptor(devfile); 60114843421SMatthew Ahrens 60214843421SMatthew Ahrens zfs_prop_init(); 60314843421SMatthew Ahrens } 604