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