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
seterr(char * fmt,...)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
ioctl_with_cmdstr(int ioc,zfs_cmd_t * zc)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 *
nvl2py(nvlist_t * nvl)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 *
dict2nvl(PyObject * d)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 *
fakepropval(uint64_t value)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
add_ds_props(zfs_cmd_t * zc,PyObject * nvl)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 *
ioctl_with_dstnv(int ioc,zfs_cmd_t * zc)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 *
py_next_dataset(PyObject * self,PyObject * args)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 *
py_dataset_props(PyObject * self,PyObject * args)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 *
py_get_fsacl(PyObject * self,PyObject * args)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 *
py_set_fsacl(PyObject * self,PyObject * args)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 *
py_get_holds(PyObject * self,PyObject * args)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 *
py_userspace_many(PyObject * self,PyObject * args)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 *
py_userspace_upgrade(PyObject * self,PyObject * args)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 *
py_set_cmdstr(PyObject * self,PyObject * args)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 *
py_get_proptable(PyObject * self,PyObject * args)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
initioctl(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