19396SMatthew.Ahrens@Sun.COM /* 29396SMatthew.Ahrens@Sun.COM * CDDL HEADER START 39396SMatthew.Ahrens@Sun.COM * 49396SMatthew.Ahrens@Sun.COM * The contents of this file are subject to the terms of the 59396SMatthew.Ahrens@Sun.COM * Common Development and Distribution License (the "License"). 69396SMatthew.Ahrens@Sun.COM * You may not use this file except in compliance with the License. 79396SMatthew.Ahrens@Sun.COM * 89396SMatthew.Ahrens@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99396SMatthew.Ahrens@Sun.COM * or http://www.opensolaris.org/os/licensing. 109396SMatthew.Ahrens@Sun.COM * See the License for the specific language governing permissions 119396SMatthew.Ahrens@Sun.COM * and limitations under the License. 129396SMatthew.Ahrens@Sun.COM * 139396SMatthew.Ahrens@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 149396SMatthew.Ahrens@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159396SMatthew.Ahrens@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 169396SMatthew.Ahrens@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 179396SMatthew.Ahrens@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 189396SMatthew.Ahrens@Sun.COM * 199396SMatthew.Ahrens@Sun.COM * CDDL HEADER END 209396SMatthew.Ahrens@Sun.COM */ 219396SMatthew.Ahrens@Sun.COM /* 22*11821SSam.Falkner@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 239396SMatthew.Ahrens@Sun.COM * Use is subject to license terms. 249396SMatthew.Ahrens@Sun.COM */ 259396SMatthew.Ahrens@Sun.COM 269396SMatthew.Ahrens@Sun.COM #include <Python.h> 279396SMatthew.Ahrens@Sun.COM #include <sys/zfs_ioctl.h> 289396SMatthew.Ahrens@Sun.COM #include <sys/fs/zfs.h> 299396SMatthew.Ahrens@Sun.COM #include <strings.h> 309396SMatthew.Ahrens@Sun.COM #include <unistd.h> 319396SMatthew.Ahrens@Sun.COM #include <libnvpair.h> 329396SMatthew.Ahrens@Sun.COM #include <libintl.h> 339396SMatthew.Ahrens@Sun.COM #include <libzfs.h> 349396SMatthew.Ahrens@Sun.COM #include "zfs_prop.h" 359396SMatthew.Ahrens@Sun.COM 369396SMatthew.Ahrens@Sun.COM static PyObject *ZFSError; 379396SMatthew.Ahrens@Sun.COM static int zfsdevfd; 389396SMatthew.Ahrens@Sun.COM 399396SMatthew.Ahrens@Sun.COM #ifdef __lint 409396SMatthew.Ahrens@Sun.COM #define dgettext(x, y) y 419396SMatthew.Ahrens@Sun.COM #endif 429396SMatthew.Ahrens@Sun.COM 439396SMatthew.Ahrens@Sun.COM #define _(s) dgettext(TEXT_DOMAIN, s) 449396SMatthew.Ahrens@Sun.COM 459396SMatthew.Ahrens@Sun.COM /*PRINTFLIKE1*/ 469396SMatthew.Ahrens@Sun.COM static void 479396SMatthew.Ahrens@Sun.COM seterr(char *fmt, ...) 489396SMatthew.Ahrens@Sun.COM { 499396SMatthew.Ahrens@Sun.COM char errstr[1024]; 509396SMatthew.Ahrens@Sun.COM va_list v; 519396SMatthew.Ahrens@Sun.COM 529396SMatthew.Ahrens@Sun.COM va_start(v, fmt); 539396SMatthew.Ahrens@Sun.COM (void) vsnprintf(errstr, sizeof (errstr), fmt, v); 549396SMatthew.Ahrens@Sun.COM va_end(v); 559396SMatthew.Ahrens@Sun.COM 569396SMatthew.Ahrens@Sun.COM PyErr_SetObject(ZFSError, Py_BuildValue("is", errno, errstr)); 579396SMatthew.Ahrens@Sun.COM } 589396SMatthew.Ahrens@Sun.COM 599396SMatthew.Ahrens@Sun.COM static char cmdstr[HIS_MAX_RECORD_LEN]; 609396SMatthew.Ahrens@Sun.COM 619396SMatthew.Ahrens@Sun.COM static int 629396SMatthew.Ahrens@Sun.COM ioctl_with_cmdstr(int ioc, zfs_cmd_t *zc) 639396SMatthew.Ahrens@Sun.COM { 649396SMatthew.Ahrens@Sun.COM int err; 659396SMatthew.Ahrens@Sun.COM 669396SMatthew.Ahrens@Sun.COM if (cmdstr[0]) 679396SMatthew.Ahrens@Sun.COM zc->zc_history = (uint64_t)(uintptr_t)cmdstr; 689396SMatthew.Ahrens@Sun.COM err = ioctl(zfsdevfd, ioc, zc); 699396SMatthew.Ahrens@Sun.COM cmdstr[0] = '\0'; 709396SMatthew.Ahrens@Sun.COM return (err); 719396SMatthew.Ahrens@Sun.COM } 729396SMatthew.Ahrens@Sun.COM 739396SMatthew.Ahrens@Sun.COM static PyObject * 749396SMatthew.Ahrens@Sun.COM nvl2py(nvlist_t *nvl) 759396SMatthew.Ahrens@Sun.COM { 769396SMatthew.Ahrens@Sun.COM PyObject *pyo; 779396SMatthew.Ahrens@Sun.COM nvpair_t *nvp; 789396SMatthew.Ahrens@Sun.COM 799396SMatthew.Ahrens@Sun.COM pyo = PyDict_New(); 809396SMatthew.Ahrens@Sun.COM 819396SMatthew.Ahrens@Sun.COM for (nvp = nvlist_next_nvpair(nvl, NULL); nvp; 829396SMatthew.Ahrens@Sun.COM nvp = nvlist_next_nvpair(nvl, nvp)) { 839396SMatthew.Ahrens@Sun.COM PyObject *pyval; 849396SMatthew.Ahrens@Sun.COM char *sval; 859396SMatthew.Ahrens@Sun.COM uint64_t ival; 869396SMatthew.Ahrens@Sun.COM boolean_t bval; 879396SMatthew.Ahrens@Sun.COM nvlist_t *nval; 889396SMatthew.Ahrens@Sun.COM 899396SMatthew.Ahrens@Sun.COM switch (nvpair_type(nvp)) { 909396SMatthew.Ahrens@Sun.COM case DATA_TYPE_STRING: 919396SMatthew.Ahrens@Sun.COM (void) nvpair_value_string(nvp, &sval); 929396SMatthew.Ahrens@Sun.COM pyval = Py_BuildValue("s", sval); 939396SMatthew.Ahrens@Sun.COM break; 949396SMatthew.Ahrens@Sun.COM 959396SMatthew.Ahrens@Sun.COM case DATA_TYPE_UINT64: 969396SMatthew.Ahrens@Sun.COM (void) nvpair_value_uint64(nvp, &ival); 979396SMatthew.Ahrens@Sun.COM pyval = Py_BuildValue("K", ival); 989396SMatthew.Ahrens@Sun.COM break; 999396SMatthew.Ahrens@Sun.COM 1009396SMatthew.Ahrens@Sun.COM case DATA_TYPE_NVLIST: 1019396SMatthew.Ahrens@Sun.COM (void) nvpair_value_nvlist(nvp, &nval); 1029396SMatthew.Ahrens@Sun.COM pyval = nvl2py(nval); 1039396SMatthew.Ahrens@Sun.COM break; 1049396SMatthew.Ahrens@Sun.COM 1059396SMatthew.Ahrens@Sun.COM case DATA_TYPE_BOOLEAN: 1069396SMatthew.Ahrens@Sun.COM Py_INCREF(Py_None); 1079396SMatthew.Ahrens@Sun.COM pyval = Py_None; 1089396SMatthew.Ahrens@Sun.COM break; 1099396SMatthew.Ahrens@Sun.COM 1109396SMatthew.Ahrens@Sun.COM case DATA_TYPE_BOOLEAN_VALUE: 1119396SMatthew.Ahrens@Sun.COM (void) nvpair_value_boolean_value(nvp, &bval); 1129396SMatthew.Ahrens@Sun.COM pyval = Py_BuildValue("i", bval); 1139396SMatthew.Ahrens@Sun.COM break; 1149396SMatthew.Ahrens@Sun.COM 1159396SMatthew.Ahrens@Sun.COM default: 1169396SMatthew.Ahrens@Sun.COM PyErr_SetNone(PyExc_ValueError); 1179396SMatthew.Ahrens@Sun.COM Py_DECREF(pyo); 1189396SMatthew.Ahrens@Sun.COM return (NULL); 1199396SMatthew.Ahrens@Sun.COM } 1209396SMatthew.Ahrens@Sun.COM 1219396SMatthew.Ahrens@Sun.COM PyDict_SetItemString(pyo, nvpair_name(nvp), pyval); 1229396SMatthew.Ahrens@Sun.COM Py_DECREF(pyval); 1239396SMatthew.Ahrens@Sun.COM } 1249396SMatthew.Ahrens@Sun.COM 1259396SMatthew.Ahrens@Sun.COM return (pyo); 1269396SMatthew.Ahrens@Sun.COM } 1279396SMatthew.Ahrens@Sun.COM 1289396SMatthew.Ahrens@Sun.COM static nvlist_t * 1299396SMatthew.Ahrens@Sun.COM dict2nvl(PyObject *d) 1309396SMatthew.Ahrens@Sun.COM { 1319396SMatthew.Ahrens@Sun.COM nvlist_t *nvl; 1329396SMatthew.Ahrens@Sun.COM int err; 1339396SMatthew.Ahrens@Sun.COM PyObject *key, *value; 1349396SMatthew.Ahrens@Sun.COM int pos = 0; 1359396SMatthew.Ahrens@Sun.COM 1369396SMatthew.Ahrens@Sun.COM if (!PyDict_Check(d)) { 1379396SMatthew.Ahrens@Sun.COM PyErr_SetObject(PyExc_ValueError, d); 1389396SMatthew.Ahrens@Sun.COM return (NULL); 1399396SMatthew.Ahrens@Sun.COM } 1409396SMatthew.Ahrens@Sun.COM 1419396SMatthew.Ahrens@Sun.COM err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0); 1429396SMatthew.Ahrens@Sun.COM assert(err == 0); 1439396SMatthew.Ahrens@Sun.COM 1449396SMatthew.Ahrens@Sun.COM while (PyDict_Next(d, &pos, &key, &value)) { 1459396SMatthew.Ahrens@Sun.COM char *keystr = PyString_AsString(key); 1469396SMatthew.Ahrens@Sun.COM if (keystr == NULL) { 1479396SMatthew.Ahrens@Sun.COM PyErr_SetObject(PyExc_KeyError, key); 1489396SMatthew.Ahrens@Sun.COM nvlist_free(nvl); 1499396SMatthew.Ahrens@Sun.COM return (NULL); 1509396SMatthew.Ahrens@Sun.COM } 1519396SMatthew.Ahrens@Sun.COM 1529396SMatthew.Ahrens@Sun.COM if (PyDict_Check(value)) { 1539396SMatthew.Ahrens@Sun.COM nvlist_t *valnvl = dict2nvl(value); 1549396SMatthew.Ahrens@Sun.COM err = nvlist_add_nvlist(nvl, keystr, valnvl); 1559396SMatthew.Ahrens@Sun.COM nvlist_free(valnvl); 1569396SMatthew.Ahrens@Sun.COM } else if (value == Py_None) { 1579396SMatthew.Ahrens@Sun.COM err = nvlist_add_boolean(nvl, keystr); 1589396SMatthew.Ahrens@Sun.COM } else if (PyString_Check(value)) { 1599396SMatthew.Ahrens@Sun.COM char *valstr = PyString_AsString(value); 1609396SMatthew.Ahrens@Sun.COM err = nvlist_add_string(nvl, keystr, valstr); 1619396SMatthew.Ahrens@Sun.COM } else if (PyInt_Check(value)) { 1629396SMatthew.Ahrens@Sun.COM uint64_t valint = PyInt_AsUnsignedLongLongMask(value); 1639396SMatthew.Ahrens@Sun.COM err = nvlist_add_uint64(nvl, keystr, valint); 1649396SMatthew.Ahrens@Sun.COM } else if (PyBool_Check(value)) { 1659396SMatthew.Ahrens@Sun.COM boolean_t valbool = value == Py_True ? B_TRUE : B_FALSE; 1669396SMatthew.Ahrens@Sun.COM err = nvlist_add_boolean_value(nvl, keystr, valbool); 1679396SMatthew.Ahrens@Sun.COM } else { 1689396SMatthew.Ahrens@Sun.COM PyErr_SetObject(PyExc_ValueError, value); 1699396SMatthew.Ahrens@Sun.COM nvlist_free(nvl); 1709396SMatthew.Ahrens@Sun.COM return (NULL); 1719396SMatthew.Ahrens@Sun.COM } 1729396SMatthew.Ahrens@Sun.COM assert(err == 0); 1739396SMatthew.Ahrens@Sun.COM } 1749396SMatthew.Ahrens@Sun.COM 1759396SMatthew.Ahrens@Sun.COM return (nvl); 1769396SMatthew.Ahrens@Sun.COM } 1779396SMatthew.Ahrens@Sun.COM 1789396SMatthew.Ahrens@Sun.COM static PyObject * 1799396SMatthew.Ahrens@Sun.COM fakepropval(uint64_t value) 1809396SMatthew.Ahrens@Sun.COM { 1819396SMatthew.Ahrens@Sun.COM PyObject *d = PyDict_New(); 1829396SMatthew.Ahrens@Sun.COM PyDict_SetItemString(d, "value", Py_BuildValue("K", value)); 1839396SMatthew.Ahrens@Sun.COM return (d); 1849396SMatthew.Ahrens@Sun.COM } 1859396SMatthew.Ahrens@Sun.COM 1869396SMatthew.Ahrens@Sun.COM static void 1879396SMatthew.Ahrens@Sun.COM add_ds_props(zfs_cmd_t *zc, PyObject *nvl) 1889396SMatthew.Ahrens@Sun.COM { 1899396SMatthew.Ahrens@Sun.COM dmu_objset_stats_t *s = &zc->zc_objset_stats; 1909396SMatthew.Ahrens@Sun.COM PyDict_SetItemString(nvl, "numclones", 1919396SMatthew.Ahrens@Sun.COM fakepropval(s->dds_num_clones)); 1929396SMatthew.Ahrens@Sun.COM PyDict_SetItemString(nvl, "issnap", 1939396SMatthew.Ahrens@Sun.COM fakepropval(s->dds_is_snapshot)); 1949396SMatthew.Ahrens@Sun.COM PyDict_SetItemString(nvl, "inconsistent", 1959396SMatthew.Ahrens@Sun.COM fakepropval(s->dds_inconsistent)); 1969396SMatthew.Ahrens@Sun.COM } 1979396SMatthew.Ahrens@Sun.COM 1989396SMatthew.Ahrens@Sun.COM /* On error, returns NULL but does not set python exception. */ 1999396SMatthew.Ahrens@Sun.COM static PyObject * 2009396SMatthew.Ahrens@Sun.COM ioctl_with_dstnv(int ioc, zfs_cmd_t *zc) 2019396SMatthew.Ahrens@Sun.COM { 2029396SMatthew.Ahrens@Sun.COM int nvsz = 2048; 2039396SMatthew.Ahrens@Sun.COM void *nvbuf; 2049396SMatthew.Ahrens@Sun.COM PyObject *pynv = NULL; 2059396SMatthew.Ahrens@Sun.COM 2069396SMatthew.Ahrens@Sun.COM again: 2079396SMatthew.Ahrens@Sun.COM nvbuf = malloc(nvsz); 2089396SMatthew.Ahrens@Sun.COM zc->zc_nvlist_dst_size = nvsz; 2099396SMatthew.Ahrens@Sun.COM zc->zc_nvlist_dst = (uintptr_t)nvbuf; 2109396SMatthew.Ahrens@Sun.COM 2119396SMatthew.Ahrens@Sun.COM if (ioctl(zfsdevfd, ioc, zc) == 0) { 2129396SMatthew.Ahrens@Sun.COM nvlist_t *nvl; 2139396SMatthew.Ahrens@Sun.COM 2149396SMatthew.Ahrens@Sun.COM errno = nvlist_unpack(nvbuf, zc->zc_nvlist_dst_size, &nvl, 0); 2159396SMatthew.Ahrens@Sun.COM if (errno == 0) { 2169396SMatthew.Ahrens@Sun.COM pynv = nvl2py(nvl); 2179396SMatthew.Ahrens@Sun.COM nvlist_free(nvl); 2189396SMatthew.Ahrens@Sun.COM } 2199396SMatthew.Ahrens@Sun.COM } else if (errno == ENOMEM) { 2209396SMatthew.Ahrens@Sun.COM free(nvbuf); 2219396SMatthew.Ahrens@Sun.COM nvsz = zc->zc_nvlist_dst_size; 2229396SMatthew.Ahrens@Sun.COM goto again; 2239396SMatthew.Ahrens@Sun.COM } 2249396SMatthew.Ahrens@Sun.COM free(nvbuf); 2259396SMatthew.Ahrens@Sun.COM return (pynv); 2269396SMatthew.Ahrens@Sun.COM } 2279396SMatthew.Ahrens@Sun.COM 2289396SMatthew.Ahrens@Sun.COM static PyObject * 2299396SMatthew.Ahrens@Sun.COM py_next_dataset(PyObject *self, PyObject *args) 2309396SMatthew.Ahrens@Sun.COM { 2319396SMatthew.Ahrens@Sun.COM int ioc; 2329396SMatthew.Ahrens@Sun.COM uint64_t cookie; 2339396SMatthew.Ahrens@Sun.COM zfs_cmd_t zc = { 0 }; 2349396SMatthew.Ahrens@Sun.COM int snaps; 2359396SMatthew.Ahrens@Sun.COM char *name; 2369396SMatthew.Ahrens@Sun.COM PyObject *nvl; 2379396SMatthew.Ahrens@Sun.COM PyObject *ret = NULL; 2389396SMatthew.Ahrens@Sun.COM 2399396SMatthew.Ahrens@Sun.COM if (!PyArg_ParseTuple(args, "siK", &name, &snaps, &cookie)) 2409396SMatthew.Ahrens@Sun.COM return (NULL); 2419396SMatthew.Ahrens@Sun.COM 2429396SMatthew.Ahrens@Sun.COM (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 2439396SMatthew.Ahrens@Sun.COM zc.zc_cookie = cookie; 2449396SMatthew.Ahrens@Sun.COM 2459396SMatthew.Ahrens@Sun.COM if (snaps) 2469396SMatthew.Ahrens@Sun.COM ioc = ZFS_IOC_SNAPSHOT_LIST_NEXT; 2479396SMatthew.Ahrens@Sun.COM else 2489396SMatthew.Ahrens@Sun.COM ioc = ZFS_IOC_DATASET_LIST_NEXT; 2499396SMatthew.Ahrens@Sun.COM 2509396SMatthew.Ahrens@Sun.COM nvl = ioctl_with_dstnv(ioc, &zc); 2519396SMatthew.Ahrens@Sun.COM if (nvl) { 2529396SMatthew.Ahrens@Sun.COM add_ds_props(&zc, nvl); 2539396SMatthew.Ahrens@Sun.COM ret = Py_BuildValue("sKO", zc.zc_name, zc.zc_cookie, nvl); 2549396SMatthew.Ahrens@Sun.COM Py_DECREF(nvl); 2559396SMatthew.Ahrens@Sun.COM } else if (errno == ESRCH) { 2569396SMatthew.Ahrens@Sun.COM PyErr_SetNone(PyExc_StopIteration); 2579396SMatthew.Ahrens@Sun.COM } else { 2589396SMatthew.Ahrens@Sun.COM if (snaps) 2599396SMatthew.Ahrens@Sun.COM seterr(_("cannot get snapshots of %s"), name); 2609396SMatthew.Ahrens@Sun.COM else 2619396SMatthew.Ahrens@Sun.COM seterr(_("cannot get child datasets of %s"), name); 2629396SMatthew.Ahrens@Sun.COM } 2639396SMatthew.Ahrens@Sun.COM return (ret); 2649396SMatthew.Ahrens@Sun.COM } 2659396SMatthew.Ahrens@Sun.COM 2669396SMatthew.Ahrens@Sun.COM static PyObject * 2679396SMatthew.Ahrens@Sun.COM py_dataset_props(PyObject *self, PyObject *args) 2689396SMatthew.Ahrens@Sun.COM { 2699396SMatthew.Ahrens@Sun.COM zfs_cmd_t zc = { 0 }; 2709396SMatthew.Ahrens@Sun.COM int snaps; 2719396SMatthew.Ahrens@Sun.COM char *name; 2729396SMatthew.Ahrens@Sun.COM PyObject *nvl; 2739396SMatthew.Ahrens@Sun.COM 2749396SMatthew.Ahrens@Sun.COM if (!PyArg_ParseTuple(args, "s", &name)) 2759396SMatthew.Ahrens@Sun.COM return (NULL); 2769396SMatthew.Ahrens@Sun.COM 2779396SMatthew.Ahrens@Sun.COM (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 2789396SMatthew.Ahrens@Sun.COM 2799396SMatthew.Ahrens@Sun.COM nvl = ioctl_with_dstnv(ZFS_IOC_OBJSET_STATS, &zc); 2809396SMatthew.Ahrens@Sun.COM if (nvl) { 2819396SMatthew.Ahrens@Sun.COM add_ds_props(&zc, nvl); 2829396SMatthew.Ahrens@Sun.COM } else { 2839396SMatthew.Ahrens@Sun.COM seterr(_("cannot access dataset %s"), name); 2849396SMatthew.Ahrens@Sun.COM } 2859396SMatthew.Ahrens@Sun.COM return (nvl); 2869396SMatthew.Ahrens@Sun.COM } 2879396SMatthew.Ahrens@Sun.COM 2889396SMatthew.Ahrens@Sun.COM static PyObject * 2899396SMatthew.Ahrens@Sun.COM py_get_fsacl(PyObject *self, PyObject *args) 2909396SMatthew.Ahrens@Sun.COM { 2919396SMatthew.Ahrens@Sun.COM zfs_cmd_t zc = { 0 }; 2929396SMatthew.Ahrens@Sun.COM char *name; 2939396SMatthew.Ahrens@Sun.COM PyObject *nvl; 2949396SMatthew.Ahrens@Sun.COM 2959396SMatthew.Ahrens@Sun.COM if (!PyArg_ParseTuple(args, "s", &name)) 2969396SMatthew.Ahrens@Sun.COM return (NULL); 2979396SMatthew.Ahrens@Sun.COM 2989396SMatthew.Ahrens@Sun.COM (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 2999396SMatthew.Ahrens@Sun.COM 3009396SMatthew.Ahrens@Sun.COM nvl = ioctl_with_dstnv(ZFS_IOC_GET_FSACL, &zc); 3019396SMatthew.Ahrens@Sun.COM if (nvl == NULL) 3029396SMatthew.Ahrens@Sun.COM seterr(_("cannot get permissions on %s"), name); 3039396SMatthew.Ahrens@Sun.COM 3049396SMatthew.Ahrens@Sun.COM return (nvl); 3059396SMatthew.Ahrens@Sun.COM } 3069396SMatthew.Ahrens@Sun.COM 3079396SMatthew.Ahrens@Sun.COM static PyObject * 3089396SMatthew.Ahrens@Sun.COM py_set_fsacl(PyObject *self, PyObject *args) 3099396SMatthew.Ahrens@Sun.COM { 3109396SMatthew.Ahrens@Sun.COM int un; 3119396SMatthew.Ahrens@Sun.COM size_t nvsz; 3129396SMatthew.Ahrens@Sun.COM zfs_cmd_t zc = { 0 }; 3139396SMatthew.Ahrens@Sun.COM char *name, *nvbuf; 3149396SMatthew.Ahrens@Sun.COM PyObject *dict, *file; 3159396SMatthew.Ahrens@Sun.COM nvlist_t *nvl; 3169396SMatthew.Ahrens@Sun.COM int err; 3179396SMatthew.Ahrens@Sun.COM 3189396SMatthew.Ahrens@Sun.COM if (!PyArg_ParseTuple(args, "siO!", &name, &un, 3199396SMatthew.Ahrens@Sun.COM &PyDict_Type, &dict)) 3209396SMatthew.Ahrens@Sun.COM return (NULL); 3219396SMatthew.Ahrens@Sun.COM 3229396SMatthew.Ahrens@Sun.COM nvl = dict2nvl(dict); 3239396SMatthew.Ahrens@Sun.COM if (nvl == NULL) 3249396SMatthew.Ahrens@Sun.COM return (NULL); 3259396SMatthew.Ahrens@Sun.COM 3269396SMatthew.Ahrens@Sun.COM err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE); 3279396SMatthew.Ahrens@Sun.COM assert(err == 0); 3289396SMatthew.Ahrens@Sun.COM nvbuf = malloc(nvsz); 3299396SMatthew.Ahrens@Sun.COM err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0); 3309396SMatthew.Ahrens@Sun.COM assert(err == 0); 3319396SMatthew.Ahrens@Sun.COM 3329396SMatthew.Ahrens@Sun.COM (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 3339396SMatthew.Ahrens@Sun.COM zc.zc_nvlist_src_size = nvsz; 3349396SMatthew.Ahrens@Sun.COM zc.zc_nvlist_src = (uintptr_t)nvbuf; 3359396SMatthew.Ahrens@Sun.COM zc.zc_perm_action = un; 3369396SMatthew.Ahrens@Sun.COM 3379396SMatthew.Ahrens@Sun.COM err = ioctl_with_cmdstr(ZFS_IOC_SET_FSACL, &zc); 3389396SMatthew.Ahrens@Sun.COM free(nvbuf); 3399396SMatthew.Ahrens@Sun.COM if (err) { 3409396SMatthew.Ahrens@Sun.COM seterr(_("cannot set permissions on %s"), name); 3419396SMatthew.Ahrens@Sun.COM return (NULL); 3429396SMatthew.Ahrens@Sun.COM } 3439396SMatthew.Ahrens@Sun.COM 3449396SMatthew.Ahrens@Sun.COM Py_RETURN_NONE; 3459396SMatthew.Ahrens@Sun.COM } 3469396SMatthew.Ahrens@Sun.COM 3479396SMatthew.Ahrens@Sun.COM static PyObject * 34810242Schris.kirby@sun.com py_get_holds(PyObject *self, PyObject *args) 34910242Schris.kirby@sun.com { 35010242Schris.kirby@sun.com zfs_cmd_t zc = { 0 }; 35110242Schris.kirby@sun.com char *name; 35210242Schris.kirby@sun.com PyObject *nvl; 35310242Schris.kirby@sun.com 35410242Schris.kirby@sun.com if (!PyArg_ParseTuple(args, "s", &name)) 35510242Schris.kirby@sun.com return (NULL); 35610242Schris.kirby@sun.com 35710242Schris.kirby@sun.com (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 35810242Schris.kirby@sun.com 35910242Schris.kirby@sun.com nvl = ioctl_with_dstnv(ZFS_IOC_GET_HOLDS, &zc); 36010242Schris.kirby@sun.com if (nvl == NULL) 36110242Schris.kirby@sun.com seterr(_("cannot get holds for %s"), name); 36210242Schris.kirby@sun.com 36310242Schris.kirby@sun.com return (nvl); 36410242Schris.kirby@sun.com } 36510242Schris.kirby@sun.com 36610242Schris.kirby@sun.com static PyObject * 3679396SMatthew.Ahrens@Sun.COM py_userspace_many(PyObject *self, PyObject *args) 3689396SMatthew.Ahrens@Sun.COM { 3699396SMatthew.Ahrens@Sun.COM zfs_cmd_t zc = { 0 }; 3709396SMatthew.Ahrens@Sun.COM zfs_userquota_prop_t type; 3719396SMatthew.Ahrens@Sun.COM char *name, *propname; 3729396SMatthew.Ahrens@Sun.COM int bufsz = 1<<20; 3739396SMatthew.Ahrens@Sun.COM void *buf; 3749396SMatthew.Ahrens@Sun.COM PyObject *dict, *file; 3759396SMatthew.Ahrens@Sun.COM int error; 3769396SMatthew.Ahrens@Sun.COM 3779396SMatthew.Ahrens@Sun.COM if (!PyArg_ParseTuple(args, "ss", &name, &propname)) 3789396SMatthew.Ahrens@Sun.COM return (NULL); 3799396SMatthew.Ahrens@Sun.COM 3809396SMatthew.Ahrens@Sun.COM for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) 3819396SMatthew.Ahrens@Sun.COM if (strcmp(propname, zfs_userquota_prop_prefixes[type]) == 0) 3829396SMatthew.Ahrens@Sun.COM break; 3839396SMatthew.Ahrens@Sun.COM if (type == ZFS_NUM_USERQUOTA_PROPS) { 3849396SMatthew.Ahrens@Sun.COM PyErr_SetString(PyExc_KeyError, propname); 3859396SMatthew.Ahrens@Sun.COM return (NULL); 3869396SMatthew.Ahrens@Sun.COM } 3879396SMatthew.Ahrens@Sun.COM 3889396SMatthew.Ahrens@Sun.COM dict = PyDict_New(); 3899396SMatthew.Ahrens@Sun.COM buf = malloc(bufsz); 3909396SMatthew.Ahrens@Sun.COM 3919396SMatthew.Ahrens@Sun.COM (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 3929396SMatthew.Ahrens@Sun.COM zc.zc_objset_type = type; 3939396SMatthew.Ahrens@Sun.COM zc.zc_cookie = 0; 3949396SMatthew.Ahrens@Sun.COM 3959396SMatthew.Ahrens@Sun.COM while (1) { 3969396SMatthew.Ahrens@Sun.COM zfs_useracct_t *zua = buf; 3979396SMatthew.Ahrens@Sun.COM 3989396SMatthew.Ahrens@Sun.COM zc.zc_nvlist_dst = (uintptr_t)buf; 3999396SMatthew.Ahrens@Sun.COM zc.zc_nvlist_dst_size = bufsz; 4009396SMatthew.Ahrens@Sun.COM 4019396SMatthew.Ahrens@Sun.COM error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_MANY, &zc); 4029396SMatthew.Ahrens@Sun.COM if (error || zc.zc_nvlist_dst_size == 0) 4039396SMatthew.Ahrens@Sun.COM break; 4049396SMatthew.Ahrens@Sun.COM 4059396SMatthew.Ahrens@Sun.COM while (zc.zc_nvlist_dst_size > 0) { 4069396SMatthew.Ahrens@Sun.COM PyObject *pykey, *pyval; 4079396SMatthew.Ahrens@Sun.COM 4089396SMatthew.Ahrens@Sun.COM pykey = Py_BuildValue("sI", 4099396SMatthew.Ahrens@Sun.COM zua->zu_domain, zua->zu_rid); 4109396SMatthew.Ahrens@Sun.COM pyval = Py_BuildValue("K", zua->zu_space); 4119396SMatthew.Ahrens@Sun.COM PyDict_SetItem(dict, pykey, pyval); 4129396SMatthew.Ahrens@Sun.COM Py_DECREF(pykey); 4139396SMatthew.Ahrens@Sun.COM Py_DECREF(pyval); 4149396SMatthew.Ahrens@Sun.COM 4159396SMatthew.Ahrens@Sun.COM zua++; 4169396SMatthew.Ahrens@Sun.COM zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t); 4179396SMatthew.Ahrens@Sun.COM } 4189396SMatthew.Ahrens@Sun.COM } 4199396SMatthew.Ahrens@Sun.COM 4209396SMatthew.Ahrens@Sun.COM free(buf); 4219396SMatthew.Ahrens@Sun.COM 4229396SMatthew.Ahrens@Sun.COM if (error != 0) { 4239396SMatthew.Ahrens@Sun.COM Py_DECREF(dict); 4249396SMatthew.Ahrens@Sun.COM seterr(_("cannot get %s property on %s"), propname, name); 4259396SMatthew.Ahrens@Sun.COM return (NULL); 4269396SMatthew.Ahrens@Sun.COM } 4279396SMatthew.Ahrens@Sun.COM 4289396SMatthew.Ahrens@Sun.COM return (dict); 4299396SMatthew.Ahrens@Sun.COM } 4309396SMatthew.Ahrens@Sun.COM 4319396SMatthew.Ahrens@Sun.COM static PyObject * 4329396SMatthew.Ahrens@Sun.COM py_userspace_upgrade(PyObject *self, PyObject *args) 4339396SMatthew.Ahrens@Sun.COM { 4349396SMatthew.Ahrens@Sun.COM zfs_cmd_t zc = { 0 }; 4359396SMatthew.Ahrens@Sun.COM char *name; 4369396SMatthew.Ahrens@Sun.COM int error; 4379396SMatthew.Ahrens@Sun.COM 4389396SMatthew.Ahrens@Sun.COM if (!PyArg_ParseTuple(args, "s", &name)) 4399396SMatthew.Ahrens@Sun.COM return (NULL); 4409396SMatthew.Ahrens@Sun.COM 4419396SMatthew.Ahrens@Sun.COM (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name)); 4429396SMatthew.Ahrens@Sun.COM error = ioctl(zfsdevfd, ZFS_IOC_USERSPACE_UPGRADE, &zc); 4439396SMatthew.Ahrens@Sun.COM 4449396SMatthew.Ahrens@Sun.COM if (error != 0) { 4459396SMatthew.Ahrens@Sun.COM seterr(_("cannot initialize user accounting information on %s"), 4469396SMatthew.Ahrens@Sun.COM name); 4479396SMatthew.Ahrens@Sun.COM return (NULL); 4489396SMatthew.Ahrens@Sun.COM } 4499396SMatthew.Ahrens@Sun.COM 4509396SMatthew.Ahrens@Sun.COM Py_RETURN_NONE; 4519396SMatthew.Ahrens@Sun.COM } 4529396SMatthew.Ahrens@Sun.COM 4539396SMatthew.Ahrens@Sun.COM static PyObject * 4549396SMatthew.Ahrens@Sun.COM py_set_cmdstr(PyObject *self, PyObject *args) 4559396SMatthew.Ahrens@Sun.COM { 4569396SMatthew.Ahrens@Sun.COM char *str; 4579396SMatthew.Ahrens@Sun.COM 4589396SMatthew.Ahrens@Sun.COM if (!PyArg_ParseTuple(args, "s", &str)) 4599396SMatthew.Ahrens@Sun.COM return (NULL); 4609396SMatthew.Ahrens@Sun.COM 4619396SMatthew.Ahrens@Sun.COM (void) strlcpy(cmdstr, str, sizeof (cmdstr)); 4629396SMatthew.Ahrens@Sun.COM 4639396SMatthew.Ahrens@Sun.COM Py_RETURN_NONE; 4649396SMatthew.Ahrens@Sun.COM } 4659396SMatthew.Ahrens@Sun.COM 4669396SMatthew.Ahrens@Sun.COM static PyObject * 4679396SMatthew.Ahrens@Sun.COM py_get_proptable(PyObject *self, PyObject *args) 4689396SMatthew.Ahrens@Sun.COM { 4699396SMatthew.Ahrens@Sun.COM zprop_desc_t *t = zfs_prop_get_table(); 4709396SMatthew.Ahrens@Sun.COM PyObject *d = PyDict_New(); 4719396SMatthew.Ahrens@Sun.COM zfs_prop_t i; 4729396SMatthew.Ahrens@Sun.COM 4739396SMatthew.Ahrens@Sun.COM for (i = 0; i < ZFS_NUM_PROPS; i++) { 4749396SMatthew.Ahrens@Sun.COM zprop_desc_t *p = &t[i]; 4759396SMatthew.Ahrens@Sun.COM PyObject *tuple; 4769396SMatthew.Ahrens@Sun.COM static const char *typetable[] = 4779396SMatthew.Ahrens@Sun.COM {"number", "string", "index"}; 4789396SMatthew.Ahrens@Sun.COM static const char *attrtable[] = 4799396SMatthew.Ahrens@Sun.COM {"default", "readonly", "inherit", "onetime"}; 4809396SMatthew.Ahrens@Sun.COM PyObject *indextable; 4819396SMatthew.Ahrens@Sun.COM 4829396SMatthew.Ahrens@Sun.COM if (p->pd_proptype == PROP_TYPE_INDEX) { 4839396SMatthew.Ahrens@Sun.COM const zprop_index_t *it = p->pd_table; 4849396SMatthew.Ahrens@Sun.COM indextable = PyDict_New(); 4859396SMatthew.Ahrens@Sun.COM int j; 4869396SMatthew.Ahrens@Sun.COM for (j = 0; it[j].pi_name; j++) { 4879396SMatthew.Ahrens@Sun.COM PyDict_SetItemString(indextable, 4889396SMatthew.Ahrens@Sun.COM it[j].pi_name, 4899396SMatthew.Ahrens@Sun.COM Py_BuildValue("K", it[j].pi_value)); 4909396SMatthew.Ahrens@Sun.COM } 4919396SMatthew.Ahrens@Sun.COM } else { 4929396SMatthew.Ahrens@Sun.COM Py_INCREF(Py_None); 4939396SMatthew.Ahrens@Sun.COM indextable = Py_None; 4949396SMatthew.Ahrens@Sun.COM } 4959396SMatthew.Ahrens@Sun.COM 4969396SMatthew.Ahrens@Sun.COM tuple = Py_BuildValue("sissKsissiiO", 4979396SMatthew.Ahrens@Sun.COM p->pd_name, p->pd_propnum, typetable[p->pd_proptype], 4989396SMatthew.Ahrens@Sun.COM p->pd_strdefault, p->pd_numdefault, 4999396SMatthew.Ahrens@Sun.COM attrtable[p->pd_attr], p->pd_types, 5009396SMatthew.Ahrens@Sun.COM p->pd_values, p->pd_colname, 5019396SMatthew.Ahrens@Sun.COM p->pd_rightalign, p->pd_visible, indextable); 5029396SMatthew.Ahrens@Sun.COM PyDict_SetItemString(d, p->pd_name, tuple); 5039396SMatthew.Ahrens@Sun.COM Py_DECREF(tuple); 5049396SMatthew.Ahrens@Sun.COM } 5059396SMatthew.Ahrens@Sun.COM 5069396SMatthew.Ahrens@Sun.COM return (d); 5079396SMatthew.Ahrens@Sun.COM } 5089396SMatthew.Ahrens@Sun.COM 5099396SMatthew.Ahrens@Sun.COM static PyMethodDef zfsmethods[] = { 5109396SMatthew.Ahrens@Sun.COM {"next_dataset", py_next_dataset, METH_VARARGS, 5119396SMatthew.Ahrens@Sun.COM "Get next child dataset or snapshot."}, 5129396SMatthew.Ahrens@Sun.COM {"get_fsacl", py_get_fsacl, METH_VARARGS, "Get allowed permissions."}, 5139396SMatthew.Ahrens@Sun.COM {"set_fsacl", py_set_fsacl, METH_VARARGS, "Set allowed permissions."}, 5149396SMatthew.Ahrens@Sun.COM {"userspace_many", py_userspace_many, METH_VARARGS, 5159396SMatthew.Ahrens@Sun.COM "Get user space accounting."}, 5169396SMatthew.Ahrens@Sun.COM {"userspace_upgrade", py_userspace_upgrade, METH_VARARGS, 5179396SMatthew.Ahrens@Sun.COM "Upgrade fs to enable user space accounting."}, 5189396SMatthew.Ahrens@Sun.COM {"set_cmdstr", py_set_cmdstr, METH_VARARGS, 5199396SMatthew.Ahrens@Sun.COM "Set command string for history logging."}, 5209396SMatthew.Ahrens@Sun.COM {"dataset_props", py_dataset_props, METH_VARARGS, 5219396SMatthew.Ahrens@Sun.COM "Get dataset properties."}, 5229396SMatthew.Ahrens@Sun.COM {"get_proptable", py_get_proptable, METH_NOARGS, 5239396SMatthew.Ahrens@Sun.COM "Get property table."}, 52410242Schris.kirby@sun.com {"get_holds", py_get_holds, METH_VARARGS, "Get user holds."}, 5259396SMatthew.Ahrens@Sun.COM {NULL, NULL, 0, NULL} 5269396SMatthew.Ahrens@Sun.COM }; 5279396SMatthew.Ahrens@Sun.COM 5289396SMatthew.Ahrens@Sun.COM void 5299396SMatthew.Ahrens@Sun.COM initioctl(void) 5309396SMatthew.Ahrens@Sun.COM { 5319396SMatthew.Ahrens@Sun.COM PyObject *zfs_ioctl = Py_InitModule("zfs.ioctl", zfsmethods); 5329396SMatthew.Ahrens@Sun.COM PyObject *zfs_util = PyImport_ImportModule("zfs.util"); 5339396SMatthew.Ahrens@Sun.COM PyObject *devfile; 5349396SMatthew.Ahrens@Sun.COM 5359396SMatthew.Ahrens@Sun.COM if (zfs_util == NULL) 5369396SMatthew.Ahrens@Sun.COM return; 5379396SMatthew.Ahrens@Sun.COM 5389396SMatthew.Ahrens@Sun.COM ZFSError = PyObject_GetAttrString(zfs_util, "ZFSError"); 5399396SMatthew.Ahrens@Sun.COM devfile = PyObject_GetAttrString(zfs_util, "dev"); 5409396SMatthew.Ahrens@Sun.COM zfsdevfd = PyObject_AsFileDescriptor(devfile); 5419396SMatthew.Ahrens@Sun.COM 5429396SMatthew.Ahrens@Sun.COM zfs_prop_init(); 5439396SMatthew.Ahrens@Sun.COM } 544