1*14843421SMatthew Ahrens /* 2*14843421SMatthew Ahrens * CDDL HEADER START 3*14843421SMatthew Ahrens * 4*14843421SMatthew Ahrens * The contents of this file are subject to the terms of the 5*14843421SMatthew Ahrens * Common Development and Distribution License (the "License"). 6*14843421SMatthew Ahrens * You may not use this file except in compliance with the License. 7*14843421SMatthew Ahrens * 8*14843421SMatthew Ahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*14843421SMatthew Ahrens * or http://www.opensolaris.org/os/licensing. 10*14843421SMatthew Ahrens * See the License for the specific language governing permissions 11*14843421SMatthew Ahrens * and limitations under the License. 12*14843421SMatthew Ahrens * 13*14843421SMatthew Ahrens * When distributing Covered Code, include this CDDL HEADER in each 14*14843421SMatthew Ahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*14843421SMatthew Ahrens * If applicable, add the following below this CDDL HEADER, with the 16*14843421SMatthew Ahrens * fields enclosed by brackets "[]" replaced with your own identifying 17*14843421SMatthew Ahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18*14843421SMatthew Ahrens * 19*14843421SMatthew Ahrens * CDDL HEADER END 20*14843421SMatthew Ahrens */ 21*14843421SMatthew Ahrens /* 22*14843421SMatthew Ahrens * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*14843421SMatthew Ahrens * Use is subject to license terms. 24*14843421SMatthew Ahrens */ 25*14843421SMatthew Ahrens 26*14843421SMatthew Ahrens #include <Python.h> 27*14843421SMatthew Ahrens #include <sys/zfs_ioctl.h> 28*14843421SMatthew Ahrens #include <sys/fs/zfs.h> 29*14843421SMatthew Ahrens #include <strings.h> 30*14843421SMatthew Ahrens #include <unistd.h> 31*14843421SMatthew Ahrens #include <libnvpair.h> 32*14843421SMatthew Ahrens #include <idmap.h> 33*14843421SMatthew Ahrens #include <zone.h> 34*14843421SMatthew Ahrens #include <libintl.h> 35*14843421SMatthew Ahrens #include <libzfs.h> 36*14843421SMatthew Ahrens #include "zfs_prop.h" 37*14843421SMatthew Ahrens 38*14843421SMatthew Ahrens static PyObject *ZFSError; 39*14843421SMatthew Ahrens static int zfsdevfd; 40*14843421SMatthew Ahrens 41*14843421SMatthew Ahrens #ifdef __lint 42*14843421SMatthew Ahrens #define dgettext(x, y) y 43*14843421SMatthew Ahrens #endif 44*14843421SMatthew Ahrens 45*14843421SMatthew Ahrens #define _(s) dgettext(TEXT_DOMAIN, s) 46*14843421SMatthew Ahrens 47*14843421SMatthew Ahrens extern int sid_to_id(char *sid, boolean_t user, uid_t *id); 48*14843421SMatthew Ahrens 49*14843421SMatthew Ahrens /*PRINTFLIKE1*/ 50*14843421SMatthew Ahrens static void 51*14843421SMatthew Ahrens seterr(char *fmt, ...) 52*14843421SMatthew Ahrens { 53*14843421SMatthew Ahrens char errstr[1024]; 54*14843421SMatthew Ahrens va_list v; 55*14843421SMatthew Ahrens 56*14843421SMatthew Ahrens va_start(v, fmt); 57*14843421SMatthew Ahrens (void) vsnprintf(errstr, sizeof (errstr), fmt, v); 58*14843421SMatthew Ahrens va_end(v); 59*14843421SMatthew Ahrens 60*14843421SMatthew Ahrens PyErr_SetObject(ZFSError, Py_BuildValue("is", errno, errstr)); 61*14843421SMatthew Ahrens } 62*14843421SMatthew Ahrens 63*14843421SMatthew Ahrens static char cmdstr[HIS_MAX_RECORD_LEN]; 64*14843421SMatthew Ahrens 65*14843421SMatthew Ahrens static int 66*14843421SMatthew Ahrens ioctl_with_cmdstr(int ioc, zfs_cmd_t *zc) 67*14843421SMatthew Ahrens { 68*14843421SMatthew Ahrens int err; 69*14843421SMatthew Ahrens 70*14843421SMatthew Ahrens if (cmdstr[0]) 71*14843421SMatthew Ahrens zc->zc_history = (uint64_t)(uintptr_t)cmdstr; 72*14843421SMatthew Ahrens err = ioctl(zfsdevfd, ioc, zc); 73*14843421SMatthew Ahrens cmdstr[0] = '\0'; 74*14843421SMatthew Ahrens return (err); 75*14843421SMatthew Ahrens } 76*14843421SMatthew Ahrens 77*14843421SMatthew Ahrens static PyObject * 78*14843421SMatthew Ahrens nvl2py(nvlist_t *nvl) 79*14843421SMatthew Ahrens { 80*14843421SMatthew Ahrens PyObject *pyo; 81*14843421SMatthew Ahrens nvpair_t *nvp; 82*14843421SMatthew Ahrens 83*14843421SMatthew Ahrens pyo = PyDict_New(); 84*14843421SMatthew Ahrens 85*14843421SMatthew Ahrens for (nvp = nvlist_next_nvpair(nvl, NULL); nvp; 86*14843421SMatthew Ahrens nvp = nvlist_next_nvpair(nvl, nvp)) { 87*14843421SMatthew Ahrens PyObject *pyval; 88*14843421SMatthew Ahrens char *sval; 89*14843421SMatthew Ahrens uint64_t ival; 90*14843421SMatthew Ahrens boolean_t bval; 91*14843421SMatthew Ahrens nvlist_t *nval; 92*14843421SMatthew Ahrens 93*14843421SMatthew Ahrens switch (nvpair_type(nvp)) { 94*14843421SMatthew Ahrens case DATA_TYPE_STRING: 95*14843421SMatthew Ahrens (void) nvpair_value_string(nvp, &sval); 96*14843421SMatthew Ahrens pyval = Py_BuildValue("s", sval); 97*14843421SMatthew Ahrens break; 98*14843421SMatthew Ahrens 99*14843421SMatthew Ahrens case DATA_TYPE_UINT64: 100*14843421SMatthew Ahrens (void) nvpair_value_uint64(nvp, &ival); 101*14843421SMatthew Ahrens pyval = Py_BuildValue("K", ival); 102*14843421SMatthew Ahrens break; 103*14843421SMatthew Ahrens 104*14843421SMatthew Ahrens case DATA_TYPE_NVLIST: 105*14843421SMatthew Ahrens (void) nvpair_value_nvlist(nvp, &nval); 106*14843421SMatthew Ahrens pyval = nvl2py(nval); 107*14843421SMatthew Ahrens break; 108*14843421SMatthew Ahrens 109*14843421SMatthew Ahrens case DATA_TYPE_BOOLEAN: 110*14843421SMatthew Ahrens Py_INCREF(Py_None); 111*14843421SMatthew Ahrens pyval = Py_None; 112*14843421SMatthew Ahrens break; 113*14843421SMatthew Ahrens 114*14843421SMatthew Ahrens case DATA_TYPE_BOOLEAN_VALUE: 115*14843421SMatthew Ahrens (void) nvpair_value_boolean_value(nvp, &bval); 116*14843421SMatthew Ahrens pyval = Py_BuildValue("i", bval); 117*14843421SMatthew Ahrens break; 118*14843421SMatthew Ahrens 119*14843421SMatthew Ahrens default: 120*14843421SMatthew Ahrens PyErr_SetNone(PyExc_ValueError); 121*14843421SMatthew Ahrens Py_DECREF(pyo); 122*14843421SMatthew Ahrens return (NULL); 123*14843421SMatthew Ahrens } 124*14843421SMatthew Ahrens 125*14843421SMatthew Ahrens PyDict_SetItemString(pyo, nvpair_name(nvp), pyval); 126*14843421SMatthew Ahrens Py_DECREF(pyval); 127*14843421SMatthew Ahrens } 128*14843421SMatthew Ahrens 129*14843421SMatthew Ahrens return (pyo); 130*14843421SMatthew Ahrens } 131*14843421SMatthew Ahrens 132*14843421SMatthew Ahrens static nvlist_t * 133*14843421SMatthew Ahrens dict2nvl(PyObject *d) 134*14843421SMatthew Ahrens { 135*14843421SMatthew Ahrens nvlist_t *nvl; 136*14843421SMatthew Ahrens int err; 137*14843421SMatthew Ahrens PyObject *key, *value; 138*14843421SMatthew Ahrens int pos = 0; 139*14843421SMatthew Ahrens 140*14843421SMatthew Ahrens if (!PyDict_Check(d)) { 141*14843421SMatthew Ahrens PyErr_SetObject(PyExc_ValueError, d); 142*14843421SMatthew Ahrens return (NULL); 143*14843421SMatthew Ahrens } 144*14843421SMatthew Ahrens 145*14843421SMatthew Ahrens err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); 146*14843421SMatthew Ahrens assert(err == 0); 147*14843421SMatthew Ahrens 148*14843421SMatthew Ahrens while (PyDict_Next(d, &pos, &key, &value)) { 149*14843421SMatthew Ahrens char *keystr = PyString_AsString(key); 150*14843421SMatthew Ahrens if (keystr == NULL) { 151*14843421SMatthew Ahrens PyErr_SetObject(PyExc_KeyError, key); 152*14843421SMatthew Ahrens nvlist_free(nvl); 153*14843421SMatthew Ahrens return (NULL); 154*14843421SMatthew Ahrens } 155*14843421SMatthew Ahrens 156*14843421SMatthew Ahrens if (PyDict_Check(value)) { 157*14843421SMatthew Ahrens nvlist_t *valnvl = dict2nvl(value); 158*14843421SMatthew Ahrens err = nvlist_add_nvlist(nvl, keystr, valnvl); 159*14843421SMatthew Ahrens nvlist_free(valnvl); 160*14843421SMatthew Ahrens } else if (value == Py_None) { 161*14843421SMatthew Ahrens err = nvlist_add_boolean(nvl, keystr); 162*14843421SMatthew Ahrens } else if (PyString_Check(value)) { 163*14843421SMatthew Ahrens char *valstr = PyString_AsString(value); 164*14843421SMatthew Ahrens err = nvlist_add_string(nvl, keystr, valstr); 165*14843421SMatthew Ahrens } else if (PyInt_Check(value)) { 166*14843421SMatthew Ahrens uint64_t valint = PyInt_AsUnsignedLongLongMask(value); 167*14843421SMatthew Ahrens err = nvlist_add_uint64(nvl, keystr, valint); 168*14843421SMatthew Ahrens } else if (PyBool_Check(value)) { 169*14843421SMatthew Ahrens boolean_t valbool = value == Py_True ? B_TRUE : B_FALSE; 170*14843421SMatthew Ahrens err = nvlist_add_boolean_value(nvl, keystr, valbool); 171*14843421SMatthew Ahrens } else { 172*14843421SMatthew Ahrens PyErr_SetObject(PyExc_ValueError, value); 173*14843421SMatthew Ahrens nvlist_free(nvl); 174*14843421SMatthew Ahrens return (NULL); 175*14843421SMatthew Ahrens } 176*14843421SMatthew Ahrens assert(err == 0); 177*14843421SMatthew Ahrens } 178*14843421SMatthew Ahrens 179*14843421SMatthew Ahrens return (nvl); 180*14843421SMatthew Ahrens } 181*14843421SMatthew Ahrens 182*14843421SMatthew Ahrens static PyObject * 183*14843421SMatthew Ahrens fakepropval(uint64_t value) 184*14843421SMatthew Ahrens { 185*14843421SMatthew Ahrens PyObject *d = PyDict_New(); 186*14843421SMatthew Ahrens PyDict_SetItemString(d, "value", Py_BuildValue("K", value)); 187*14843421SMatthew Ahrens return (d); 188*14843421SMatthew Ahrens } 189*14843421SMatthew Ahrens 190*14843421SMatthew Ahrens static void 191*14843421SMatthew Ahrens add_ds_props(zfs_cmd_t *zc, PyObject *nvl) 192*14843421SMatthew Ahrens { 193*14843421SMatthew Ahrens dmu_objset_stats_t *s = &zc->zc_objset_stats; 194*14843421SMatthew Ahrens PyDict_SetItemString(nvl, "numclones", 195*14843421SMatthew Ahrens fakepropval(s->dds_num_clones)); 196*14843421SMatthew Ahrens PyDict_SetItemString(nvl, "issnap", 197*14843421SMatthew Ahrens fakepropval(s->dds_is_snapshot)); 198*14843421SMatthew Ahrens PyDict_SetItemString(nvl, "inconsistent", 199*14843421SMatthew Ahrens fakepropval(s->dds_inconsistent)); 200*14843421SMatthew Ahrens } 201*14843421SMatthew Ahrens 202*14843421SMatthew Ahrens /* On error, returns NULL but does not set python exception. */ 203*14843421SMatthew Ahrens static PyObject * 204*14843421SMatthew Ahrens ioctl_with_dstnv(int ioc, zfs_cmd_t *zc) 205*14843421SMatthew Ahrens { 206*14843421SMatthew Ahrens int nvsz = 2048; 207*14843421SMatthew Ahrens void *nvbuf; 208*14843421SMatthew Ahrens PyObject *pynv = NULL; 209*14843421SMatthew Ahrens 210*14843421SMatthew Ahrens again: 211*14843421SMatthew Ahrens nvbuf = malloc(nvsz); 212*14843421SMatthew Ahrens zc->zc_nvlist_dst_size = nvsz; 213*14843421SMatthew Ahrens zc->zc_nvlist_dst = (uintptr_t)nvbuf; 214*14843421SMatthew Ahrens 215*14843421SMatthew Ahrens if (ioctl(zfsdevfd, ioc, zc) == 0) { 216*14843421SMatthew Ahrens nvlist_t *nvl; 217*14843421SMatthew Ahrens 218*14843421SMatthew Ahrens errno = nvlist_unpack(nvbuf, zc->zc_nvlist_dst_size, &nvl, 0); 219*14843421SMatthew Ahrens if (errno == 0) { 220*14843421SMatthew Ahrens pynv = nvl2py(nvl); 221*14843421SMatthew Ahrens nvlist_free(nvl); 222*14843421SMatthew Ahrens } 223*14843421SMatthew Ahrens } else if (errno == ENOMEM) { 224*14843421SMatthew Ahrens free(nvbuf); 225*14843421SMatthew Ahrens nvsz = zc->zc_nvlist_dst_size; 226*14843421SMatthew Ahrens goto again; 227*14843421SMatthew Ahrens } 228*14843421SMatthew Ahrens free(nvbuf); 229*14843421SMatthew Ahrens return (pynv); 230*14843421SMatthew Ahrens } 231*14843421SMatthew Ahrens 232*14843421SMatthew Ahrens static PyObject * 233*14843421SMatthew Ahrens py_next_dataset(PyObject *self, PyObject *args) 234*14843421SMatthew Ahrens { 235*14843421SMatthew Ahrens int ioc; 236*14843421SMatthew Ahrens uint64_t cookie; 237*14843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 238*14843421SMatthew Ahrens int snaps; 239*14843421SMatthew Ahrens char *name; 240*14843421SMatthew Ahrens PyObject *nvl; 241*14843421SMatthew Ahrens PyObject *ret = NULL; 242*14843421SMatthew Ahrens 243*14843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "siK", &name, &snaps, &cookie)) 244*14843421SMatthew Ahrens return (NULL); 245*14843421SMatthew Ahrens 246*14843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 247*14843421SMatthew Ahrens zc.zc_cookie = cookie; 248*14843421SMatthew Ahrens 249*14843421SMatthew Ahrens if (snaps) 250*14843421SMatthew Ahrens ioc = ZFS_IOC_SNAPSHOT_LIST_NEXT; 251*14843421SMatthew Ahrens else 252*14843421SMatthew Ahrens ioc = ZFS_IOC_DATASET_LIST_NEXT; 253*14843421SMatthew Ahrens 254*14843421SMatthew Ahrens nvl = ioctl_with_dstnv(ioc, &zc); 255*14843421SMatthew Ahrens if (nvl) { 256*14843421SMatthew Ahrens add_ds_props(&zc, nvl); 257*14843421SMatthew Ahrens ret = Py_BuildValue("sKO", zc.zc_name, zc.zc_cookie, nvl); 258*14843421SMatthew Ahrens Py_DECREF(nvl); 259*14843421SMatthew Ahrens } else if (errno == ESRCH) { 260*14843421SMatthew Ahrens PyErr_SetNone(PyExc_StopIteration); 261*14843421SMatthew Ahrens } else { 262*14843421SMatthew Ahrens if (snaps) 263*14843421SMatthew Ahrens seterr(_("cannot get snapshots of %s"), name); 264*14843421SMatthew Ahrens else 265*14843421SMatthew Ahrens seterr(_("cannot get child datasets of %s"), name); 266*14843421SMatthew Ahrens } 267*14843421SMatthew Ahrens return (ret); 268*14843421SMatthew Ahrens } 269*14843421SMatthew Ahrens 270*14843421SMatthew Ahrens static PyObject * 271*14843421SMatthew Ahrens py_dataset_props(PyObject *self, PyObject *args) 272*14843421SMatthew Ahrens { 273*14843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 274*14843421SMatthew Ahrens int snaps; 275*14843421SMatthew Ahrens char *name; 276*14843421SMatthew Ahrens PyObject *nvl; 277*14843421SMatthew Ahrens 278*14843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 279*14843421SMatthew Ahrens return (NULL); 280*14843421SMatthew Ahrens 281*14843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 282*14843421SMatthew Ahrens 283*14843421SMatthew Ahrens nvl = ioctl_with_dstnv(ZFS_IOC_OBJSET_STATS, &zc); 284*14843421SMatthew Ahrens if (nvl) { 285*14843421SMatthew Ahrens add_ds_props(&zc, nvl); 286*14843421SMatthew Ahrens } else { 287*14843421SMatthew Ahrens seterr(_("cannot access dataset %s"), name); 288*14843421SMatthew Ahrens } 289*14843421SMatthew Ahrens return (nvl); 290*14843421SMatthew Ahrens } 291*14843421SMatthew Ahrens 292*14843421SMatthew Ahrens static PyObject * 293*14843421SMatthew Ahrens py_get_fsacl(PyObject *self, PyObject *args) 294*14843421SMatthew Ahrens { 295*14843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 296*14843421SMatthew Ahrens char *name; 297*14843421SMatthew Ahrens PyObject *nvl; 298*14843421SMatthew Ahrens 299*14843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 300*14843421SMatthew Ahrens return (NULL); 301*14843421SMatthew Ahrens 302*14843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 303*14843421SMatthew Ahrens 304*14843421SMatthew Ahrens nvl = ioctl_with_dstnv(ZFS_IOC_GET_FSACL, &zc); 305*14843421SMatthew Ahrens if (nvl == NULL) 306*14843421SMatthew Ahrens seterr(_("cannot get permissions on %s"), name); 307*14843421SMatthew Ahrens 308*14843421SMatthew Ahrens return (nvl); 309*14843421SMatthew Ahrens } 310*14843421SMatthew Ahrens 311*14843421SMatthew Ahrens static PyObject * 312*14843421SMatthew Ahrens py_set_fsacl(PyObject *self, PyObject *args) 313*14843421SMatthew Ahrens { 314*14843421SMatthew Ahrens int un; 315*14843421SMatthew Ahrens size_t nvsz; 316*14843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 317*14843421SMatthew Ahrens char *name, *nvbuf; 318*14843421SMatthew Ahrens PyObject *dict, *file; 319*14843421SMatthew Ahrens nvlist_t *nvl; 320*14843421SMatthew Ahrens int err; 321*14843421SMatthew Ahrens 322*14843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "siO!", &name, &un, 323*14843421SMatthew Ahrens &PyDict_Type, &dict)) 324*14843421SMatthew Ahrens return (NULL); 325*14843421SMatthew Ahrens 326*14843421SMatthew Ahrens nvl = dict2nvl(dict); 327*14843421SMatthew Ahrens if (nvl == NULL) 328*14843421SMatthew Ahrens return (NULL); 329*14843421SMatthew Ahrens 330*14843421SMatthew Ahrens err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE); 331*14843421SMatthew Ahrens assert(err == 0); 332*14843421SMatthew Ahrens nvbuf = malloc(nvsz); 333*14843421SMatthew Ahrens err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0); 334*14843421SMatthew Ahrens assert(err == 0); 335*14843421SMatthew Ahrens 336*14843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 337*14843421SMatthew Ahrens zc.zc_nvlist_src_size = nvsz; 338*14843421SMatthew Ahrens zc.zc_nvlist_src = (uintptr_t)nvbuf; 339*14843421SMatthew Ahrens zc.zc_perm_action = un; 340*14843421SMatthew Ahrens 341*14843421SMatthew Ahrens err = ioctl_with_cmdstr(ZFS_IOC_SET_FSACL, &zc); 342*14843421SMatthew Ahrens free(nvbuf); 343*14843421SMatthew Ahrens if (err) { 344*14843421SMatthew Ahrens seterr(_("cannot set permissions on %s"), name); 345*14843421SMatthew Ahrens return (NULL); 346*14843421SMatthew Ahrens } 347*14843421SMatthew Ahrens 348*14843421SMatthew Ahrens Py_RETURN_NONE; 349*14843421SMatthew Ahrens } 350*14843421SMatthew Ahrens 351*14843421SMatthew Ahrens static PyObject * 352*14843421SMatthew Ahrens py_userspace_many(PyObject *self, PyObject *args) 353*14843421SMatthew Ahrens { 354*14843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 355*14843421SMatthew Ahrens zfs_userquota_prop_t type; 356*14843421SMatthew Ahrens char *name, *propname; 357*14843421SMatthew Ahrens int bufsz = 1<<20; 358*14843421SMatthew Ahrens void *buf; 359*14843421SMatthew Ahrens PyObject *dict, *file; 360*14843421SMatthew Ahrens int error; 361*14843421SMatthew Ahrens 362*14843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "ss", &name, &propname)) 363*14843421SMatthew Ahrens return (NULL); 364*14843421SMatthew Ahrens 365*14843421SMatthew Ahrens for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) 366*14843421SMatthew Ahrens if (strcmp(propname, zfs_userquota_prop_prefixes[type]) == 0) 367*14843421SMatthew Ahrens break; 368*14843421SMatthew Ahrens if (type == ZFS_NUM_USERQUOTA_PROPS) { 369*14843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, propname); 370*14843421SMatthew Ahrens return (NULL); 371*14843421SMatthew Ahrens } 372*14843421SMatthew Ahrens 373*14843421SMatthew Ahrens dict = PyDict_New(); 374*14843421SMatthew Ahrens buf = malloc(bufsz); 375*14843421SMatthew Ahrens 376*14843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 377*14843421SMatthew Ahrens zc.zc_objset_type = type; 378*14843421SMatthew Ahrens zc.zc_cookie = 0; 379*14843421SMatthew Ahrens 380*14843421SMatthew Ahrens while (1) { 381*14843421SMatthew Ahrens zfs_useracct_t *zua = buf; 382*14843421SMatthew Ahrens 383*14843421SMatthew Ahrens zc.zc_nvlist_dst = (uintptr_t)buf; 384*14843421SMatthew Ahrens zc.zc_nvlist_dst_size = bufsz; 385*14843421SMatthew Ahrens 386*14843421SMatthew Ahrens error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_MANY, &zc); 387*14843421SMatthew Ahrens if (error || zc.zc_nvlist_dst_size == 0) 388*14843421SMatthew Ahrens break; 389*14843421SMatthew Ahrens 390*14843421SMatthew Ahrens while (zc.zc_nvlist_dst_size > 0) { 391*14843421SMatthew Ahrens PyObject *pykey, *pyval; 392*14843421SMatthew Ahrens 393*14843421SMatthew Ahrens pykey = Py_BuildValue("sI", 394*14843421SMatthew Ahrens zua->zu_domain, zua->zu_rid); 395*14843421SMatthew Ahrens pyval = Py_BuildValue("K", zua->zu_space); 396*14843421SMatthew Ahrens PyDict_SetItem(dict, pykey, pyval); 397*14843421SMatthew Ahrens Py_DECREF(pykey); 398*14843421SMatthew Ahrens Py_DECREF(pyval); 399*14843421SMatthew Ahrens 400*14843421SMatthew Ahrens zua++; 401*14843421SMatthew Ahrens zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t); 402*14843421SMatthew Ahrens } 403*14843421SMatthew Ahrens } 404*14843421SMatthew Ahrens 405*14843421SMatthew Ahrens free(buf); 406*14843421SMatthew Ahrens 407*14843421SMatthew Ahrens if (error != 0) { 408*14843421SMatthew Ahrens Py_DECREF(dict); 409*14843421SMatthew Ahrens seterr(_("cannot get %s property on %s"), propname, name); 410*14843421SMatthew Ahrens return (NULL); 411*14843421SMatthew Ahrens } 412*14843421SMatthew Ahrens 413*14843421SMatthew Ahrens return (dict); 414*14843421SMatthew Ahrens } 415*14843421SMatthew Ahrens 416*14843421SMatthew Ahrens static PyObject * 417*14843421SMatthew Ahrens py_userspace_upgrade(PyObject *self, PyObject *args) 418*14843421SMatthew Ahrens { 419*14843421SMatthew Ahrens zfs_cmd_t zc = { 0 }; 420*14843421SMatthew Ahrens char *name; 421*14843421SMatthew Ahrens int error; 422*14843421SMatthew Ahrens 423*14843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &name)) 424*14843421SMatthew Ahrens return (NULL); 425*14843421SMatthew Ahrens 426*14843421SMatthew Ahrens (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 427*14843421SMatthew Ahrens error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_UPGRADE, &zc); 428*14843421SMatthew Ahrens 429*14843421SMatthew Ahrens if (error != 0) { 430*14843421SMatthew Ahrens seterr(_("cannot initialize user accounting information on %s"), 431*14843421SMatthew Ahrens name); 432*14843421SMatthew Ahrens return (NULL); 433*14843421SMatthew Ahrens } 434*14843421SMatthew Ahrens 435*14843421SMatthew Ahrens Py_RETURN_NONE; 436*14843421SMatthew Ahrens } 437*14843421SMatthew Ahrens 438*14843421SMatthew Ahrens static PyObject * 439*14843421SMatthew Ahrens py_sid_to_id(PyObject *self, PyObject *args) 440*14843421SMatthew Ahrens { 441*14843421SMatthew Ahrens char *sid; 442*14843421SMatthew Ahrens int err, isuser; 443*14843421SMatthew Ahrens uid_t id; 444*14843421SMatthew Ahrens 445*14843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "si", &sid, &isuser)) 446*14843421SMatthew Ahrens return (NULL); 447*14843421SMatthew Ahrens 448*14843421SMatthew Ahrens err = sid_to_id(sid, isuser, &id); 449*14843421SMatthew Ahrens if (err) { 450*14843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, sid); 451*14843421SMatthew Ahrens return (NULL); 452*14843421SMatthew Ahrens } 453*14843421SMatthew Ahrens 454*14843421SMatthew Ahrens return (Py_BuildValue("I", id)); 455*14843421SMatthew Ahrens } 456*14843421SMatthew Ahrens 457*14843421SMatthew Ahrens /* 458*14843421SMatthew Ahrens * Translate the sid string ("S-1-...") to the user@domain name, if 459*14843421SMatthew Ahrens * possible. There should be a better way to do this, but for now we 460*14843421SMatthew Ahrens * just translate to the (possibly ephemeral) uid and then back again. 461*14843421SMatthew Ahrens */ 462*14843421SMatthew Ahrens static PyObject * 463*14843421SMatthew Ahrens py_sid_to_name(PyObject *self, PyObject *args) 464*14843421SMatthew Ahrens { 465*14843421SMatthew Ahrens char *sid; 466*14843421SMatthew Ahrens int err, isuser; 467*14843421SMatthew Ahrens uid_t id; 468*14843421SMatthew Ahrens char *name, *domain; 469*14843421SMatthew Ahrens char buf[256]; 470*14843421SMatthew Ahrens 471*14843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "si", &sid, &isuser)) 472*14843421SMatthew Ahrens return (NULL); 473*14843421SMatthew Ahrens 474*14843421SMatthew Ahrens err = sid_to_id(sid, isuser, &id); 475*14843421SMatthew Ahrens if (err) { 476*14843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, sid); 477*14843421SMatthew Ahrens return (NULL); 478*14843421SMatthew Ahrens } 479*14843421SMatthew Ahrens 480*14843421SMatthew Ahrens if (isuser) { 481*14843421SMatthew Ahrens err = idmap_getwinnamebyuid(id, 482*14843421SMatthew Ahrens IDMAP_REQ_FLG_USE_CACHE, &name, &domain); 483*14843421SMatthew Ahrens } else { 484*14843421SMatthew Ahrens err = idmap_getwinnamebygid(id, 485*14843421SMatthew Ahrens IDMAP_REQ_FLG_USE_CACHE, &name, &domain); 486*14843421SMatthew Ahrens } 487*14843421SMatthew Ahrens if (err != IDMAP_SUCCESS) { 488*14843421SMatthew Ahrens PyErr_SetString(PyExc_KeyError, sid); 489*14843421SMatthew Ahrens return (NULL); 490*14843421SMatthew Ahrens } 491*14843421SMatthew Ahrens (void) snprintf(buf, sizeof (buf), "%s@%s", name, domain); 492*14843421SMatthew Ahrens free(name); 493*14843421SMatthew Ahrens free(domain); 494*14843421SMatthew Ahrens 495*14843421SMatthew Ahrens return (Py_BuildValue("s", buf)); 496*14843421SMatthew Ahrens } 497*14843421SMatthew Ahrens 498*14843421SMatthew Ahrens static PyObject * 499*14843421SMatthew Ahrens py_isglobalzone(PyObject *self, PyObject *args) 500*14843421SMatthew Ahrens { 501*14843421SMatthew Ahrens return (Py_BuildValue("i", getzoneid() == GLOBAL_ZONEID)); 502*14843421SMatthew Ahrens } 503*14843421SMatthew Ahrens 504*14843421SMatthew Ahrens static PyObject * 505*14843421SMatthew Ahrens py_set_cmdstr(PyObject *self, PyObject *args) 506*14843421SMatthew Ahrens { 507*14843421SMatthew Ahrens char *str; 508*14843421SMatthew Ahrens 509*14843421SMatthew Ahrens if (!PyArg_ParseTuple(args, "s", &str)) 510*14843421SMatthew Ahrens return (NULL); 511*14843421SMatthew Ahrens 512*14843421SMatthew Ahrens (void) strlcpy(cmdstr, str, sizeof (cmdstr)); 513*14843421SMatthew Ahrens 514*14843421SMatthew Ahrens Py_RETURN_NONE; 515*14843421SMatthew Ahrens } 516*14843421SMatthew Ahrens 517*14843421SMatthew Ahrens static PyObject * 518*14843421SMatthew Ahrens py_get_proptable(PyObject *self, PyObject *args) 519*14843421SMatthew Ahrens { 520*14843421SMatthew Ahrens zprop_desc_t *t = zfs_prop_get_table(); 521*14843421SMatthew Ahrens PyObject *d = PyDict_New(); 522*14843421SMatthew Ahrens zfs_prop_t i; 523*14843421SMatthew Ahrens 524*14843421SMatthew Ahrens for (i = 0; i < ZFS_NUM_PROPS; i++) { 525*14843421SMatthew Ahrens zprop_desc_t *p = &t[i]; 526*14843421SMatthew Ahrens PyObject *tuple; 527*14843421SMatthew Ahrens static const char *typetable[] = 528*14843421SMatthew Ahrens {"number", "string", "index"}; 529*14843421SMatthew Ahrens static const char *attrtable[] = 530*14843421SMatthew Ahrens {"default", "readonly", "inherit", "onetime"}; 531*14843421SMatthew Ahrens PyObject *indextable; 532*14843421SMatthew Ahrens 533*14843421SMatthew Ahrens if (p->pd_proptype == PROP_TYPE_INDEX) { 534*14843421SMatthew Ahrens const zprop_index_t *it = p->pd_table; 535*14843421SMatthew Ahrens indextable = PyDict_New(); 536*14843421SMatthew Ahrens int j; 537*14843421SMatthew Ahrens for (j = 0; it[j].pi_name; j++) { 538*14843421SMatthew Ahrens PyDict_SetItemString(indextable, 539*14843421SMatthew Ahrens it[j].pi_name, 540*14843421SMatthew Ahrens Py_BuildValue("K", it[j].pi_value)); 541*14843421SMatthew Ahrens } 542*14843421SMatthew Ahrens } else { 543*14843421SMatthew Ahrens Py_INCREF(Py_None); 544*14843421SMatthew Ahrens indextable = Py_None; 545*14843421SMatthew Ahrens } 546*14843421SMatthew Ahrens 547*14843421SMatthew Ahrens tuple = Py_BuildValue("sissKsissiiO", 548*14843421SMatthew Ahrens p->pd_name, p->pd_propnum, typetable[p->pd_proptype], 549*14843421SMatthew Ahrens p->pd_strdefault, p->pd_numdefault, 550*14843421SMatthew Ahrens attrtable[p->pd_attr], p->pd_types, 551*14843421SMatthew Ahrens p->pd_values, p->pd_colname, 552*14843421SMatthew Ahrens p->pd_rightalign, p->pd_visible, indextable); 553*14843421SMatthew Ahrens PyDict_SetItemString(d, p->pd_name, tuple); 554*14843421SMatthew Ahrens Py_DECREF(tuple); 555*14843421SMatthew Ahrens } 556*14843421SMatthew Ahrens 557*14843421SMatthew Ahrens return (d); 558*14843421SMatthew Ahrens } 559*14843421SMatthew Ahrens 560*14843421SMatthew Ahrens static PyMethodDef zfsmethods[] = { 561*14843421SMatthew Ahrens {"next_dataset", py_next_dataset, METH_VARARGS, 562*14843421SMatthew Ahrens "Get next child dataset or snapshot."}, 563*14843421SMatthew Ahrens {"get_fsacl", py_get_fsacl, METH_VARARGS, "Get allowed permissions."}, 564*14843421SMatthew Ahrens {"set_fsacl", py_set_fsacl, METH_VARARGS, "Set allowed permissions."}, 565*14843421SMatthew Ahrens {"userspace_many", py_userspace_many, METH_VARARGS, 566*14843421SMatthew Ahrens "Get user space accounting."}, 567*14843421SMatthew Ahrens {"userspace_upgrade", py_userspace_upgrade, METH_VARARGS, 568*14843421SMatthew Ahrens "Upgrade fs to enable user space accounting."}, 569*14843421SMatthew Ahrens {"set_cmdstr", py_set_cmdstr, METH_VARARGS, 570*14843421SMatthew Ahrens "Set command string for history logging."}, 571*14843421SMatthew Ahrens {"dataset_props", py_dataset_props, METH_VARARGS, 572*14843421SMatthew Ahrens "Get dataset properties."}, 573*14843421SMatthew Ahrens {"get_proptable", py_get_proptable, METH_NOARGS, 574*14843421SMatthew Ahrens "Get property table."}, 575*14843421SMatthew Ahrens /* Below are not really zfs-specific: */ 576*14843421SMatthew Ahrens {"sid_to_id", py_sid_to_id, METH_VARARGS, "Map SID to UID/GID."}, 577*14843421SMatthew Ahrens {"sid_to_name", py_sid_to_name, METH_VARARGS, 578*14843421SMatthew Ahrens "Map SID to name@domain."}, 579*14843421SMatthew Ahrens {"isglobalzone", py_isglobalzone, METH_NOARGS, 580*14843421SMatthew Ahrens "Determine if this is the global zone."}, 581*14843421SMatthew Ahrens {NULL, NULL, 0, NULL} 582*14843421SMatthew Ahrens }; 583*14843421SMatthew Ahrens 584*14843421SMatthew Ahrens void 585*14843421SMatthew Ahrens initioctl(void) 586*14843421SMatthew Ahrens { 587*14843421SMatthew Ahrens PyObject *zfs_ioctl = Py_InitModule("zfs.ioctl", zfsmethods); 588*14843421SMatthew Ahrens PyObject *zfs_util = PyImport_ImportModule("zfs.util"); 589*14843421SMatthew Ahrens PyObject *devfile; 590*14843421SMatthew Ahrens 591*14843421SMatthew Ahrens if (zfs_util == NULL) 592*14843421SMatthew Ahrens return; 593*14843421SMatthew Ahrens 594*14843421SMatthew Ahrens ZFSError = PyObject_GetAttrString(zfs_util, "ZFSError"); 595*14843421SMatthew Ahrens devfile = PyObject_GetAttrString(zfs_util, "dev"); 596*14843421SMatthew Ahrens zfsdevfd = PyObject_AsFileDescriptor(devfile); 597*14843421SMatthew Ahrens 598*14843421SMatthew Ahrens zfs_prop_init(); 599*14843421SMatthew Ahrens } 600