1fa9e4066Sahrens /* 2fa9e4066Sahrens * CDDL HEADER START 3fa9e4066Sahrens * 4fa9e4066Sahrens * The contents of this file are subject to the terms of the 5906d120cSlling * Common Development and Distribution License (the "License"). 6906d120cSlling * You may not use this file except in compliance with the License. 7fa9e4066Sahrens * 8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing. 10fa9e4066Sahrens * See the License for the specific language governing permissions 11fa9e4066Sahrens * and limitations under the License. 12fa9e4066Sahrens * 13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the 16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18fa9e4066Sahrens * 19fa9e4066Sahrens * CDDL HEADER END 20fa9e4066Sahrens */ 21fa9e4066Sahrens /* 2239c23413Seschrock * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23fa9e4066Sahrens * Use is subject to license terms. 24fa9e4066Sahrens */ 25fa9e4066Sahrens 26fa9e4066Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27fa9e4066Sahrens 28fa9e4066Sahrens #include <sys/zio.h> 29fa9e4066Sahrens #include <sys/spa.h> 30fa9e4066Sahrens #include <sys/zfs_acl.h> 31fa9e4066Sahrens #include <sys/zfs_ioctl.h> 32e7437265Sahrens #include <sys/zfs_znode.h> 33fa9e4066Sahrens 34fa9e4066Sahrens #include "zfs_prop.h" 35ecd6cf80Smarks #include "zfs_deleg.h" 36fa9e4066Sahrens 37fa9e4066Sahrens #if defined(_KERNEL) 38fa9e4066Sahrens #include <sys/systm.h> 39d3c8f894Stimf #include <util/qsort.h> 40fa9e4066Sahrens #else 41fa9e4066Sahrens #include <stdlib.h> 42fa9e4066Sahrens #include <string.h> 43fa9e4066Sahrens #include <ctype.h> 44fa9e4066Sahrens #endif 45fa9e4066Sahrens 46fa9e4066Sahrens typedef enum { 4791ebeef5Sahrens PROP_DEFAULT, 4891ebeef5Sahrens PROP_READONLY, 4991ebeef5Sahrens PROP_INHERIT 50fa9e4066Sahrens } prop_attr_t; 51fa9e4066Sahrens 5291ebeef5Sahrens typedef struct zfs_index { 5391ebeef5Sahrens const char *name; 5491ebeef5Sahrens uint64_t index; 5591ebeef5Sahrens } zfs_index_t; 5691ebeef5Sahrens 57fa9e4066Sahrens typedef struct { 5891ebeef5Sahrens const char *pd_name; /* human-readable property name */ 5991ebeef5Sahrens zfs_proptype_t pd_proptype; /* string, boolean, index, number */ 6091ebeef5Sahrens const char *pd_strdefault; /* default for strings */ 6191ebeef5Sahrens uint64_t pd_numdefault; /* for boolean / index / number */ 6291ebeef5Sahrens prop_attr_t pd_attr; /* default, readonly, inherit */ 6391ebeef5Sahrens int pd_types; /* bitfield of valid dataset types */ 6491ebeef5Sahrens /* fs | vol | snap; or pool */ 6591ebeef5Sahrens const char *pd_values; /* string telling acceptable values */ 6691ebeef5Sahrens const char *pd_colname; /* column header for "zfs list" */ 6791ebeef5Sahrens boolean_t pd_rightalign; /* column alignment for "zfs list" */ 6891ebeef5Sahrens boolean_t pd_visible; /* do we list this property with the */ 6991ebeef5Sahrens /* "zfs get" help message */ 7091ebeef5Sahrens const zfs_index_t *pd_table; /* for index properties, a table */ 7191ebeef5Sahrens /* defining the possible values */ 72fa9e4066Sahrens } prop_desc_t; 73fa9e4066Sahrens 7491ebeef5Sahrens static prop_desc_t zfs_prop_table[ZFS_NUM_PROPS]; 7591ebeef5Sahrens 7691ebeef5Sahrens static void 7791ebeef5Sahrens register_impl(zfs_prop_t prop, const char *name, zfs_proptype_t type, 7891ebeef5Sahrens uint64_t numdefault, const char *strdefault, prop_attr_t attr, 7991ebeef5Sahrens int objset_types, const char *values, const char *colname, 8091ebeef5Sahrens boolean_t rightalign, boolean_t visible, const zfs_index_t *table) 8191ebeef5Sahrens { 8291ebeef5Sahrens prop_desc_t *pd = &zfs_prop_table[prop]; 8391ebeef5Sahrens 8491ebeef5Sahrens ASSERT(pd->pd_name == NULL || pd->pd_name == name); 8591ebeef5Sahrens 8691ebeef5Sahrens pd->pd_name = name; 8791ebeef5Sahrens pd->pd_proptype = type; 8891ebeef5Sahrens pd->pd_numdefault = numdefault; 8991ebeef5Sahrens pd->pd_strdefault = strdefault; 9091ebeef5Sahrens pd->pd_attr = attr; 9191ebeef5Sahrens pd->pd_types = objset_types; 9291ebeef5Sahrens pd->pd_values = values; 9391ebeef5Sahrens pd->pd_colname = colname; 9491ebeef5Sahrens pd->pd_rightalign = rightalign; 9591ebeef5Sahrens pd->pd_visible = visible; 9691ebeef5Sahrens pd->pd_table = table; 9791ebeef5Sahrens } 9891ebeef5Sahrens 9991ebeef5Sahrens static void 10091ebeef5Sahrens register_string(zfs_prop_t prop, const char *name, const char *def, 10191ebeef5Sahrens prop_attr_t attr, int objset_types, const char *values, 10291ebeef5Sahrens const char *colname) 10391ebeef5Sahrens { 10491ebeef5Sahrens register_impl(prop, name, PROP_TYPE_STRING, 0, def, attr, 10591ebeef5Sahrens objset_types, values, colname, B_FALSE, B_TRUE, NULL); 10691ebeef5Sahrens 10791ebeef5Sahrens } 10891ebeef5Sahrens 10991ebeef5Sahrens static void 11091ebeef5Sahrens register_number(zfs_prop_t prop, const char *name, uint64_t def, 11191ebeef5Sahrens prop_attr_t attr, int objset_types, const char *values, const char *colname) 11291ebeef5Sahrens { 11391ebeef5Sahrens register_impl(prop, name, PROP_TYPE_NUMBER, def, NULL, attr, 11491ebeef5Sahrens objset_types, values, colname, B_TRUE, B_TRUE, NULL); 11591ebeef5Sahrens } 11691ebeef5Sahrens 11791ebeef5Sahrens static void 11891ebeef5Sahrens register_index(zfs_prop_t prop, const char *name, uint64_t def, 119*e45ce728Sahrens prop_attr_t attr, int objset_types, const char *values, const char *colname, 12091ebeef5Sahrens const zfs_index_t *table) 12191ebeef5Sahrens { 122*e45ce728Sahrens register_impl(prop, name, PROP_TYPE_INDEX, def, NULL, attr, 12391ebeef5Sahrens objset_types, values, colname, B_TRUE, B_TRUE, table); 12491ebeef5Sahrens } 12591ebeef5Sahrens 12691ebeef5Sahrens static void 12791ebeef5Sahrens register_hidden(zfs_prop_t prop, const char *name, zfs_proptype_t type, 12891ebeef5Sahrens prop_attr_t attr, int objset_types, const char *colname) 12991ebeef5Sahrens { 13091ebeef5Sahrens register_impl(prop, name, type, 0, NULL, attr, 13191ebeef5Sahrens objset_types, NULL, colname, B_FALSE, B_FALSE, NULL); 13291ebeef5Sahrens } 13391ebeef5Sahrens 13491ebeef5Sahrens void 13591ebeef5Sahrens zfs_prop_init(void) 13691ebeef5Sahrens { 13791ebeef5Sahrens static zfs_index_t checksum_table[] = { 13891ebeef5Sahrens { "on", ZIO_CHECKSUM_ON }, 13991ebeef5Sahrens { "off", ZIO_CHECKSUM_OFF }, 14091ebeef5Sahrens { "fletcher2", ZIO_CHECKSUM_FLETCHER_2 }, 14191ebeef5Sahrens { "fletcher4", ZIO_CHECKSUM_FLETCHER_4 }, 14291ebeef5Sahrens { "sha256", ZIO_CHECKSUM_SHA256 }, 14391ebeef5Sahrens { NULL } 14491ebeef5Sahrens }; 14591ebeef5Sahrens 14691ebeef5Sahrens static zfs_index_t compress_table[] = { 14791ebeef5Sahrens { "on", ZIO_COMPRESS_ON }, 14891ebeef5Sahrens { "off", ZIO_COMPRESS_OFF }, 14991ebeef5Sahrens { "lzjb", ZIO_COMPRESS_LZJB }, 15091ebeef5Sahrens { "gzip", ZIO_COMPRESS_GZIP_6 }, /* gzip default */ 15191ebeef5Sahrens { "gzip-1", ZIO_COMPRESS_GZIP_1 }, 15291ebeef5Sahrens { "gzip-2", ZIO_COMPRESS_GZIP_2 }, 15391ebeef5Sahrens { "gzip-3", ZIO_COMPRESS_GZIP_3 }, 15491ebeef5Sahrens { "gzip-4", ZIO_COMPRESS_GZIP_4 }, 15591ebeef5Sahrens { "gzip-5", ZIO_COMPRESS_GZIP_5 }, 15691ebeef5Sahrens { "gzip-6", ZIO_COMPRESS_GZIP_6 }, 15791ebeef5Sahrens { "gzip-7", ZIO_COMPRESS_GZIP_7 }, 15891ebeef5Sahrens { "gzip-8", ZIO_COMPRESS_GZIP_8 }, 15991ebeef5Sahrens { "gzip-9", ZIO_COMPRESS_GZIP_9 }, 16091ebeef5Sahrens { NULL } 16191ebeef5Sahrens }; 16291ebeef5Sahrens 16391ebeef5Sahrens static zfs_index_t snapdir_table[] = { 16491ebeef5Sahrens { "hidden", ZFS_SNAPDIR_HIDDEN }, 16591ebeef5Sahrens { "visible", ZFS_SNAPDIR_VISIBLE }, 16691ebeef5Sahrens { NULL } 16791ebeef5Sahrens }; 16891ebeef5Sahrens 16991ebeef5Sahrens static zfs_index_t acl_mode_table[] = { 17091ebeef5Sahrens { "discard", ZFS_ACL_DISCARD }, 17191ebeef5Sahrens { "groupmask", ZFS_ACL_GROUPMASK }, 17291ebeef5Sahrens { "passthrough", ZFS_ACL_PASSTHROUGH }, 17391ebeef5Sahrens { NULL } 17491ebeef5Sahrens }; 17591ebeef5Sahrens 17691ebeef5Sahrens static zfs_index_t acl_inherit_table[] = { 17791ebeef5Sahrens { "discard", ZFS_ACL_DISCARD }, 17891ebeef5Sahrens { "noallow", ZFS_ACL_NOALLOW }, 17991ebeef5Sahrens { "secure", ZFS_ACL_SECURE }, 18091ebeef5Sahrens { "passthrough", ZFS_ACL_PASSTHROUGH }, 18191ebeef5Sahrens { NULL } 18291ebeef5Sahrens }; 18391ebeef5Sahrens 18491ebeef5Sahrens static zfs_index_t copies_table[] = { 18591ebeef5Sahrens { "1", 1 }, 18691ebeef5Sahrens { "2", 2 }, 18791ebeef5Sahrens { "3", 3 }, 18891ebeef5Sahrens { NULL } 18991ebeef5Sahrens }; 19091ebeef5Sahrens 19191ebeef5Sahrens static zfs_index_t version_table[] = { 19291ebeef5Sahrens { "1", 1 }, 19391ebeef5Sahrens { "2", 2 }, 19491ebeef5Sahrens { "current", ZPL_VERSION }, 19591ebeef5Sahrens { NULL } 19691ebeef5Sahrens }; 19791ebeef5Sahrens 198*e45ce728Sahrens static zfs_index_t boolean_table[] = { 199*e45ce728Sahrens { "off", 0 }, 200*e45ce728Sahrens { "on", 1 }, 201*e45ce728Sahrens { NULL } 202*e45ce728Sahrens }; 203*e45ce728Sahrens 20491ebeef5Sahrens /* inherit index properties */ 20591ebeef5Sahrens register_index(ZFS_PROP_CHECKSUM, "checksum", ZIO_CHECKSUM_DEFAULT, 206*e45ce728Sahrens PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 20791ebeef5Sahrens "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM", 20891ebeef5Sahrens checksum_table); 20991ebeef5Sahrens register_index(ZFS_PROP_COMPRESSION, "compression", 210*e45ce728Sahrens ZIO_COMPRESS_DEFAULT, PROP_INHERIT, 211*e45ce728Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 21291ebeef5Sahrens "on | off | lzjb | gzip | gzip-[1-9]", "COMPRESS", compress_table); 21391ebeef5Sahrens register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN, 214*e45ce728Sahrens PROP_INHERIT, ZFS_TYPE_FILESYSTEM, 215*e45ce728Sahrens "hidden | visible", "SNAPDIR", snapdir_table); 21691ebeef5Sahrens register_index(ZFS_PROP_ACLMODE, "aclmode", ZFS_ACL_GROUPMASK, 217*e45ce728Sahrens PROP_INHERIT, ZFS_TYPE_FILESYSTEM, 218*e45ce728Sahrens "discard | groupmask | passthrough", "ACLMODE", 21991ebeef5Sahrens acl_mode_table); 22091ebeef5Sahrens register_index(ZFS_PROP_ACLINHERIT, "aclinherit", ZFS_ACL_SECURE, 221*e45ce728Sahrens PROP_INHERIT, ZFS_TYPE_FILESYSTEM, 22291ebeef5Sahrens "discard | noallow | secure | passthrough", "ACLINHERIT", 22391ebeef5Sahrens acl_inherit_table); 22491ebeef5Sahrens register_index(ZFS_PROP_COPIES, "copies", 1, 225*e45ce728Sahrens PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 22691ebeef5Sahrens "1 | 2 | 3", "COPIES", copies_table); 227*e45ce728Sahrens 228*e45ce728Sahrens /* inherit index (boolean) properties */ 229*e45ce728Sahrens register_index(ZFS_PROP_ATIME, "atime", 1, PROP_INHERIT, 230*e45ce728Sahrens ZFS_TYPE_FILESYSTEM, "on | off", "ATIME", boolean_table); 231*e45ce728Sahrens register_index(ZFS_PROP_DEVICES, "devices", 1, PROP_INHERIT, 232*e45ce728Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "DEVICES", 233*e45ce728Sahrens boolean_table); 234*e45ce728Sahrens register_index(ZFS_PROP_EXEC, "exec", 1, PROP_INHERIT, 235*e45ce728Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "EXEC", 236*e45ce728Sahrens boolean_table); 237*e45ce728Sahrens register_index(ZFS_PROP_SETUID, "setuid", 1, PROP_INHERIT, 238*e45ce728Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "SETUID", 239*e45ce728Sahrens boolean_table); 240*e45ce728Sahrens register_index(ZFS_PROP_READONLY, "readonly", 0, PROP_INHERIT, 241*e45ce728Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "on | off", "RDONLY", 242*e45ce728Sahrens boolean_table); 243*e45ce728Sahrens register_index(ZFS_PROP_ZONED, "zoned", 0, PROP_INHERIT, 244*e45ce728Sahrens ZFS_TYPE_FILESYSTEM, "on | off", "ZONED", boolean_table); 245*e45ce728Sahrens register_index(ZFS_PROP_XATTR, "xattr", 1, PROP_INHERIT, 246*e45ce728Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "XATTR", 247*e45ce728Sahrens boolean_table); 248*e45ce728Sahrens 249*e45ce728Sahrens /* default index properties */ 250*e45ce728Sahrens register_index(ZFS_PROP_VERSION, "version", 0, PROP_DEFAULT, 2517b55fa8eSck ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, 25291ebeef5Sahrens "1 | 2 | current", "VERSION", version_table); 25391ebeef5Sahrens 254*e45ce728Sahrens /* default index (boolean) properties */ 255*e45ce728Sahrens register_index(ZFS_PROP_CANMOUNT, "canmount", 1, PROP_DEFAULT, 256*e45ce728Sahrens ZFS_TYPE_FILESYSTEM, "on | off", "CANMOUNT", boolean_table); 257*e45ce728Sahrens register_index(ZPOOL_PROP_DELEGATION, "delegation", 1, PROP_DEFAULT, 258*e45ce728Sahrens ZFS_TYPE_POOL, "on | off", "DELEGATION", boolean_table); 259*e45ce728Sahrens register_index(ZPOOL_PROP_AUTOREPLACE, "autoreplace", 0, PROP_DEFAULT, 260*e45ce728Sahrens ZFS_TYPE_POOL, "on | off", "REPLACE", boolean_table); 261*e45ce728Sahrens 262*e45ce728Sahrens /* readonly index (boolean) properties */ 263*e45ce728Sahrens register_index(ZFS_PROP_MOUNTED, "mounted", 0, PROP_READONLY, 264*e45ce728Sahrens ZFS_TYPE_FILESYSTEM, "yes | no | -", "MOUNTED", boolean_table); 265*e45ce728Sahrens 26691ebeef5Sahrens /* string properties */ 26791ebeef5Sahrens register_string(ZFS_PROP_ORIGIN, "origin", NULL, PROP_READONLY, 26891ebeef5Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<snapshot>", "ORIGIN"); 26991ebeef5Sahrens register_string(ZPOOL_PROP_BOOTFS, "bootfs", NULL, PROP_DEFAULT, 27091ebeef5Sahrens ZFS_TYPE_POOL, "<filesystem>", "BOOTFS"); 27191ebeef5Sahrens register_string(ZFS_PROP_MOUNTPOINT, "mountpoint", "/", PROP_INHERIT, 27291ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "<path> | legacy | none", "MOUNTPOINT"); 27391ebeef5Sahrens register_string(ZFS_PROP_SHARENFS, "sharenfs", "off", PROP_INHERIT, 27491ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "on | off | share(1M) options", "SHARENFS"); 27591ebeef5Sahrens register_string(ZFS_PROP_SHAREISCSI, "shareiscsi", "off", PROP_INHERIT, 27691ebeef5Sahrens ZFS_TYPE_ANY, "on | off | type=<type>", "SHAREISCSI"); 27791ebeef5Sahrens register_string(ZFS_PROP_TYPE, "type", NULL, PROP_READONLY, 27891ebeef5Sahrens ZFS_TYPE_ANY, "filesystem | volume | snapshot", "TYPE"); 27991ebeef5Sahrens 28091ebeef5Sahrens /* readonly number properties */ 28191ebeef5Sahrens register_number(ZFS_PROP_USED, "used", 0, PROP_READONLY, 28291ebeef5Sahrens ZFS_TYPE_ANY, "<size>", "USED"); 28391ebeef5Sahrens register_number(ZFS_PROP_AVAILABLE, "available", 0, PROP_READONLY, 284d0ad202dSahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 28591ebeef5Sahrens "<size>", "AVAIL"); 28691ebeef5Sahrens register_number(ZFS_PROP_REFERENCED, "referenced", 0, PROP_READONLY, 28791ebeef5Sahrens ZFS_TYPE_ANY, "<size>", "REFER"); 28891ebeef5Sahrens register_number(ZFS_PROP_COMPRESSRATIO, "compressratio", 0, 28991ebeef5Sahrens PROP_READONLY, ZFS_TYPE_ANY, 29091ebeef5Sahrens "<1.00x or higher if compressed>", "RATIO"); 29191ebeef5Sahrens register_number(ZFS_PROP_VOLBLOCKSIZE, "volblocksize", 8192, 29291ebeef5Sahrens PROP_READONLY, 29391ebeef5Sahrens ZFS_TYPE_VOLUME, "512 to 128k, power of 2", "VOLBLOCK"); 29491ebeef5Sahrens 29591ebeef5Sahrens /* default number properties */ 29691ebeef5Sahrens register_number(ZFS_PROP_QUOTA, "quota", 0, PROP_DEFAULT, 29791ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "<size> | none", "QUOTA"); 29891ebeef5Sahrens register_number(ZFS_PROP_RESERVATION, "reservation", 0, PROP_DEFAULT, 29991ebeef5Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size> | none", "RESERV"); 30091ebeef5Sahrens register_number(ZFS_PROP_VOLSIZE, "volsize", 0, PROP_DEFAULT, 30191ebeef5Sahrens ZFS_TYPE_VOLUME, "<size>", "VOLSIZE"); 30291ebeef5Sahrens 30391ebeef5Sahrens /* inherit number properties */ 30491ebeef5Sahrens register_number(ZFS_PROP_RECORDSIZE, "recordsize", SPA_MAXBLOCKSIZE, 30591ebeef5Sahrens PROP_INHERIT, 30691ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "512 to 128k, power of 2", "RECSIZE"); 30791ebeef5Sahrens 30891ebeef5Sahrens /* hidden properties */ 30991ebeef5Sahrens register_hidden(ZFS_PROP_CREATETXG, "createtxg", PROP_TYPE_NUMBER, 31091ebeef5Sahrens PROP_READONLY, ZFS_TYPE_ANY, NULL); 31191ebeef5Sahrens register_hidden(ZFS_PROP_NUMCLONES, "numclones", PROP_TYPE_NUMBER, 31291ebeef5Sahrens PROP_READONLY, ZFS_TYPE_SNAPSHOT, NULL); 31391ebeef5Sahrens register_hidden(ZFS_PROP_NAME, "name", PROP_TYPE_STRING, 31491ebeef5Sahrens PROP_READONLY, ZFS_TYPE_ANY, "NAME"); 31591ebeef5Sahrens register_hidden(ZFS_PROP_ISCSIOPTIONS, "iscsioptions", PROP_TYPE_STRING, 31691ebeef5Sahrens PROP_INHERIT, ZFS_TYPE_VOLUME, "ISCSIOPTIONS"); 31791ebeef5Sahrens register_hidden(ZPOOL_PROP_NAME, "zpoolname", PROP_TYPE_STRING, 31891ebeef5Sahrens PROP_READONLY, ZFS_TYPE_POOL, NULL); 31991ebeef5Sahrens 32091ebeef5Sahrens /* oddball properties */ 32191ebeef5Sahrens register_impl(ZFS_PROP_CREATION, "creation", PROP_TYPE_NUMBER, 0, NULL, 32291ebeef5Sahrens PROP_READONLY, ZFS_TYPE_ANY, 32391ebeef5Sahrens "<date>", "CREATION", B_FALSE, B_TRUE, NULL); 32491ebeef5Sahrens } 32591ebeef5Sahrens 32666e2aaccSgw 327b1b8ab34Slling /* 32891ebeef5Sahrens * Returns TRUE if the property applies to any of the given dataset types. 329b1b8ab34Slling */ 330b1b8ab34Slling int 331b1b8ab34Slling zfs_prop_valid_for_type(zfs_prop_t prop, int types) 332b1b8ab34Slling { 333b1b8ab34Slling return ((zfs_prop_table[prop].pd_types & types) != 0); 334b1b8ab34Slling } 335b1b8ab34Slling 336b1b8ab34Slling /* 337b1b8ab34Slling * Determine if the specified property is visible or not. 338b1b8ab34Slling */ 339b1b8ab34Slling boolean_t 340b1b8ab34Slling zfs_prop_is_visible(zfs_prop_t prop) 341b1b8ab34Slling { 342b1b8ab34Slling if (prop < 0) 343b1b8ab34Slling return (B_FALSE); 344b1b8ab34Slling 345b1b8ab34Slling return (zfs_prop_table[prop].pd_visible); 346b1b8ab34Slling } 347b1b8ab34Slling 348d3c8f894Stimf /* 349d3c8f894Stimf * A comparison function we can use to order indexes into the 350d3c8f894Stimf * zfs_prop_table[] 351d3c8f894Stimf */ 352d3c8f894Stimf static int 35391ebeef5Sahrens zfs_prop_compare(const void *arg1, const void *arg2) 354d3c8f894Stimf { 35591ebeef5Sahrens const zfs_prop_t *p1 = arg1; 35691ebeef5Sahrens const zfs_prop_t *p2 = arg2; 35791ebeef5Sahrens boolean_t p1ro, p2ro; 358d3c8f894Stimf 35991ebeef5Sahrens p1ro = (zfs_prop_table[*p1].pd_attr == PROP_READONLY); 36091ebeef5Sahrens p2ro = (zfs_prop_table[*p2].pd_attr == PROP_READONLY); 361d3c8f894Stimf 36291ebeef5Sahrens if (p1ro == p2ro) { 36391ebeef5Sahrens return (strcmp(zfs_prop_table[*p1].pd_name, 36491ebeef5Sahrens zfs_prop_table[*p2].pd_name)); 36591ebeef5Sahrens } 366d3c8f894Stimf 36791ebeef5Sahrens return (p1ro ? -1 : 1); 368d3c8f894Stimf } 369d3c8f894Stimf 370b1b8ab34Slling /* 371b1b8ab34Slling * Iterate over all properties, calling back into the specified function 372b1b8ab34Slling * for each property. We will continue to iterate until we either 373b1b8ab34Slling * reach the end or the callback function something other than 374b1b8ab34Slling * ZFS_PROP_CONT. 375b1b8ab34Slling */ 376b1b8ab34Slling zfs_prop_t 377b1b8ab34Slling zfs_prop_iter_common(zfs_prop_f func, void *cb, zfs_type_t type, 378d3c8f894Stimf boolean_t show_all, boolean_t ordered) 379b1b8ab34Slling { 380b1b8ab34Slling int i; 38191ebeef5Sahrens zfs_prop_t order[ZFS_NUM_PROPS]; 382d3c8f894Stimf 38391ebeef5Sahrens for (int j = 0; j < ZFS_NUM_PROPS; j++) 384d3c8f894Stimf order[j] = j; 385d3c8f894Stimf 386d3c8f894Stimf 387d3c8f894Stimf if (ordered) { 38891ebeef5Sahrens qsort((void *)order, ZFS_NUM_PROPS, sizeof (zfs_prop_t), 389d3c8f894Stimf zfs_prop_compare); 390d3c8f894Stimf } 391b1b8ab34Slling 39291ebeef5Sahrens for (i = 0; i < ZFS_NUM_PROPS; i++) { 393d3c8f894Stimf if (zfs_prop_valid_for_type(order[i], type) && 394d3c8f894Stimf (zfs_prop_is_visible(order[i]) || show_all)) { 395d3c8f894Stimf if (func(order[i], cb) != ZFS_PROP_CONT) 396d3c8f894Stimf return (order[i]); 397b1b8ab34Slling } 398b1b8ab34Slling } 399b1b8ab34Slling return (ZFS_PROP_CONT); 400b1b8ab34Slling } 401b1b8ab34Slling 402b1b8ab34Slling zfs_prop_t 40391ebeef5Sahrens zfs_prop_iter(zfs_prop_f func, void *cb) 404b1b8ab34Slling { 40591ebeef5Sahrens return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, B_FALSE, B_FALSE)); 406d3c8f894Stimf } 407d3c8f894Stimf 408d3c8f894Stimf zfs_prop_t 40991ebeef5Sahrens zfs_prop_iter_ordered(zfs_prop_f func, void *cb) 410d3c8f894Stimf { 41191ebeef5Sahrens return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, B_FALSE, B_TRUE)); 412b1b8ab34Slling } 413b1b8ab34Slling 414b1b8ab34Slling zpool_prop_t 41591ebeef5Sahrens zpool_prop_iter(zpool_prop_f func, void *cb) 416b1b8ab34Slling { 41791ebeef5Sahrens return (zfs_prop_iter_common(func, cb, ZFS_TYPE_POOL, B_FALSE, 418d3c8f894Stimf B_FALSE)); 419b1b8ab34Slling } 420b1b8ab34Slling 421fa9e4066Sahrens zfs_proptype_t 422fa9e4066Sahrens zfs_prop_get_type(zfs_prop_t prop) 423fa9e4066Sahrens { 424fa9e4066Sahrens return (zfs_prop_table[prop].pd_proptype); 425fa9e4066Sahrens } 426fa9e4066Sahrens 4273d7072f8Seschrock zfs_proptype_t 4283d7072f8Seschrock zpool_prop_get_type(zfs_prop_t prop) 4293d7072f8Seschrock { 4303d7072f8Seschrock return (zfs_prop_table[prop].pd_proptype); 4313d7072f8Seschrock } 4323d7072f8Seschrock 433e9dbad6fSeschrock static boolean_t 434e9dbad6fSeschrock propname_match(const char *p, zfs_prop_t prop, size_t len) 4355c709891Seschrock { 4365c709891Seschrock const char *propname = zfs_prop_table[prop].pd_name; 4375c709891Seschrock #ifndef _KERNEL 4385c709891Seschrock const char *colname = zfs_prop_table[prop].pd_colname; 4395c709891Seschrock int c; 4405c709891Seschrock 4413bb79becSeschrock if (colname == NULL) 442e9dbad6fSeschrock return (B_FALSE); 4433bb79becSeschrock #endif 4443bb79becSeschrock 4455c709891Seschrock if (len == strlen(propname) && 4465c709891Seschrock strncmp(p, propname, len) == 0) 447e9dbad6fSeschrock return (B_TRUE); 4485c709891Seschrock 4495c709891Seschrock #ifndef _KERNEL 4503bb79becSeschrock if (len != strlen(colname)) 451e9dbad6fSeschrock return (B_FALSE); 4525c709891Seschrock 4535c709891Seschrock for (c = 0; c < len; c++) 4545c709891Seschrock if (p[c] != tolower(colname[c])) 4555c709891Seschrock break; 4565c709891Seschrock 4575c709891Seschrock return (colname[c] == '\0'); 4585c709891Seschrock #else 459e9dbad6fSeschrock return (B_FALSE); 4605c709891Seschrock #endif 4615c709891Seschrock } 4625c709891Seschrock 46366e2aaccSgw zfs_prop_t 46466e2aaccSgw zfs_name_to_prop_cb(zfs_prop_t prop, void *cb_data) 46566e2aaccSgw { 46666e2aaccSgw const char *propname = cb_data; 46766e2aaccSgw 46891ebeef5Sahrens if (propname_match(propname, prop, strlen(propname))) 46966e2aaccSgw return (prop); 47066e2aaccSgw 47166e2aaccSgw return (ZFS_PROP_CONT); 47266e2aaccSgw } 4735c709891Seschrock 474fa9e4066Sahrens /* 475b1b8ab34Slling * Given a property name and its type, returns the corresponding property ID. 476fa9e4066Sahrens */ 477fa9e4066Sahrens zfs_prop_t 478b1b8ab34Slling zfs_name_to_prop_common(const char *propname, zfs_type_t type) 479fa9e4066Sahrens { 48066e2aaccSgw zfs_prop_t prop; 481fa9e4066Sahrens 482b1b8ab34Slling prop = zfs_prop_iter_common(zfs_name_to_prop_cb, (void *)propname, 483d3c8f894Stimf type, B_TRUE, B_FALSE); 48466e2aaccSgw return (prop == ZFS_PROP_CONT ? ZFS_PROP_INVAL : prop); 485fa9e4066Sahrens } 486fa9e4066Sahrens 487b1b8ab34Slling /* 488b1b8ab34Slling * Given a zfs dataset property name, returns the corresponding property ID. 489b1b8ab34Slling */ 490b1b8ab34Slling zfs_prop_t 491b1b8ab34Slling zfs_name_to_prop(const char *propname) 492b1b8ab34Slling { 493b1b8ab34Slling return (zfs_name_to_prop_common(propname, ZFS_TYPE_ANY)); 494b1b8ab34Slling } 495b1b8ab34Slling 496b1b8ab34Slling /* 497b1b8ab34Slling * Given a pool property name, returns the corresponding property ID. 498b1b8ab34Slling */ 499b1b8ab34Slling zpool_prop_t 500b1b8ab34Slling zpool_name_to_prop(const char *propname) 501b1b8ab34Slling { 502b1b8ab34Slling return (zfs_name_to_prop_common(propname, ZFS_TYPE_POOL)); 503b1b8ab34Slling } 504b1b8ab34Slling 50591ebeef5Sahrens boolean_t 50691ebeef5Sahrens zfs_prop_delegatable(zfs_prop_t prop) 507ecd6cf80Smarks { 50891ebeef5Sahrens prop_desc_t *pd = &zfs_prop_table[prop]; 50991ebeef5Sahrens return (pd->pd_attr != PROP_READONLY && pd->pd_types != ZFS_TYPE_POOL); 510ecd6cf80Smarks } 511ecd6cf80Smarks 512e9dbad6fSeschrock /* 513e9dbad6fSeschrock * For user property names, we allow all lowercase alphanumeric characters, plus 514e9dbad6fSeschrock * a few useful punctuation characters. 515e9dbad6fSeschrock */ 516e9dbad6fSeschrock static int 517e9dbad6fSeschrock valid_char(char c) 518e9dbad6fSeschrock { 519e9dbad6fSeschrock return ((c >= 'a' && c <= 'z') || 520e9dbad6fSeschrock (c >= '0' && c <= '9') || 521e9dbad6fSeschrock c == '-' || c == '_' || c == '.' || c == ':'); 522e9dbad6fSeschrock } 523e9dbad6fSeschrock 524e9dbad6fSeschrock /* 525e9dbad6fSeschrock * Returns true if this is a valid user-defined property (one with a ':'). 526e9dbad6fSeschrock */ 527e9dbad6fSeschrock boolean_t 528e9dbad6fSeschrock zfs_prop_user(const char *name) 529e9dbad6fSeschrock { 530e9dbad6fSeschrock int i; 531e9dbad6fSeschrock char c; 532e9dbad6fSeschrock boolean_t foundsep = B_FALSE; 533e9dbad6fSeschrock 534e9dbad6fSeschrock for (i = 0; i < strlen(name); i++) { 535e9dbad6fSeschrock c = name[i]; 536e9dbad6fSeschrock if (!valid_char(c)) 537e9dbad6fSeschrock return (B_FALSE); 538e9dbad6fSeschrock if (c == ':') 539e9dbad6fSeschrock foundsep = B_TRUE; 540e9dbad6fSeschrock } 541e9dbad6fSeschrock 542e9dbad6fSeschrock if (!foundsep) 543e9dbad6fSeschrock return (B_FALSE); 544e9dbad6fSeschrock 545e9dbad6fSeschrock return (B_TRUE); 546e9dbad6fSeschrock } 547e9dbad6fSeschrock 548fa9e4066Sahrens /* 549fa9e4066Sahrens * Return the default value for the given property. 550fa9e4066Sahrens */ 5517f7322feSeschrock const char * 5527f7322feSeschrock zfs_prop_default_string(zfs_prop_t prop) 553fa9e4066Sahrens { 5547f7322feSeschrock return (zfs_prop_table[prop].pd_strdefault); 555fa9e4066Sahrens } 556fa9e4066Sahrens 5573d7072f8Seschrock const char * 5583d7072f8Seschrock zpool_prop_default_string(zpool_prop_t prop) 5593d7072f8Seschrock { 5603d7072f8Seschrock return (zfs_prop_table[prop].pd_strdefault); 5613d7072f8Seschrock } 5623d7072f8Seschrock 563fa9e4066Sahrens uint64_t 564fa9e4066Sahrens zfs_prop_default_numeric(zfs_prop_t prop) 565fa9e4066Sahrens { 566fa9e4066Sahrens return (zfs_prop_table[prop].pd_numdefault); 567fa9e4066Sahrens } 568fa9e4066Sahrens 5693d7072f8Seschrock uint64_t 5703d7072f8Seschrock zpool_prop_default_numeric(zpool_prop_t prop) 5713d7072f8Seschrock { 5723d7072f8Seschrock return (zfs_prop_table[prop].pd_numdefault); 5733d7072f8Seschrock } 5743d7072f8Seschrock 575fa9e4066Sahrens /* 576fa9e4066Sahrens * Returns TRUE if the property is readonly. 577fa9e4066Sahrens */ 578fa9e4066Sahrens int 579fa9e4066Sahrens zfs_prop_readonly(zfs_prop_t prop) 580fa9e4066Sahrens { 58191ebeef5Sahrens return (zfs_prop_table[prop].pd_attr == PROP_READONLY); 582fa9e4066Sahrens } 583fa9e4066Sahrens 584fa9e4066Sahrens /* 585b1b8ab34Slling * Given a dataset property ID, returns the corresponding name. 5863d7072f8Seschrock * Assuming the zfs dataset property ID is valid. 587fa9e4066Sahrens */ 588fa9e4066Sahrens const char * 589fa9e4066Sahrens zfs_prop_to_name(zfs_prop_t prop) 590fa9e4066Sahrens { 591fa9e4066Sahrens return (zfs_prop_table[prop].pd_name); 592fa9e4066Sahrens } 593fa9e4066Sahrens 594b1b8ab34Slling /* 595b1b8ab34Slling * Given a pool property ID, returns the corresponding name. 5963d7072f8Seschrock * Assuming the pool property ID is valid. 597b1b8ab34Slling */ 598b1b8ab34Slling const char * 599b1b8ab34Slling zpool_prop_to_name(zpool_prop_t prop) 600b1b8ab34Slling { 601b1b8ab34Slling return (zfs_prop_table[prop].pd_name); 602b1b8ab34Slling } 603b1b8ab34Slling 604fa9e4066Sahrens /* 605fa9e4066Sahrens * Returns TRUE if the property is inheritable. 606fa9e4066Sahrens */ 607fa9e4066Sahrens int 608fa9e4066Sahrens zfs_prop_inheritable(zfs_prop_t prop) 609fa9e4066Sahrens { 61091ebeef5Sahrens return (zfs_prop_table[prop].pd_attr == PROP_INHERIT); 611e9dbad6fSeschrock } 612e9dbad6fSeschrock 613e9dbad6fSeschrock /* 614e9dbad6fSeschrock * Tables of index types, plus functions to convert between the user view 615e9dbad6fSeschrock * (strings) and internal representation (uint64_t). 616e9dbad6fSeschrock */ 617e9dbad6fSeschrock int 618e9dbad6fSeschrock zfs_prop_string_to_index(zfs_prop_t prop, const char *string, uint64_t *index) 619e9dbad6fSeschrock { 62091ebeef5Sahrens const zfs_index_t *table; 621e9dbad6fSeschrock int i; 622e9dbad6fSeschrock 62391ebeef5Sahrens if ((table = zfs_prop_table[prop].pd_table) == NULL) 624e9dbad6fSeschrock return (-1); 625e9dbad6fSeschrock 626e9dbad6fSeschrock for (i = 0; table[i].name != NULL; i++) { 627e9dbad6fSeschrock if (strcmp(string, table[i].name) == 0) { 628e9dbad6fSeschrock *index = table[i].index; 629e9dbad6fSeschrock return (0); 630e9dbad6fSeschrock } 631e9dbad6fSeschrock } 632e9dbad6fSeschrock 633e9dbad6fSeschrock return (-1); 634e9dbad6fSeschrock } 635e9dbad6fSeschrock 636e9dbad6fSeschrock int 637e9dbad6fSeschrock zfs_prop_index_to_string(zfs_prop_t prop, uint64_t index, const char **string) 638e9dbad6fSeschrock { 63991ebeef5Sahrens const zfs_index_t *table; 640e9dbad6fSeschrock int i; 641e9dbad6fSeschrock 64291ebeef5Sahrens if ((table = zfs_prop_table[prop].pd_table) == NULL) 643e9dbad6fSeschrock return (-1); 644e9dbad6fSeschrock 645e9dbad6fSeschrock for (i = 0; table[i].name != NULL; i++) { 646e9dbad6fSeschrock if (table[i].index == index) { 647e9dbad6fSeschrock *string = table[i].name; 648e9dbad6fSeschrock return (0); 649e9dbad6fSeschrock } 650e9dbad6fSeschrock } 651e9dbad6fSeschrock 652e9dbad6fSeschrock return (-1); 653e9dbad6fSeschrock } 654e9dbad6fSeschrock 655acd76fe5Seschrock #ifndef _KERNEL 656acd76fe5Seschrock 657fa9e4066Sahrens /* 658b1b8ab34Slling * Returns a string describing the set of acceptable values for the given 659b1b8ab34Slling * zfs property, or NULL if it cannot be set. 660fa9e4066Sahrens */ 661b1b8ab34Slling const char * 662b1b8ab34Slling zfs_prop_values(zfs_prop_t prop) 663fa9e4066Sahrens { 664b1b8ab34Slling if (zfs_prop_table[prop].pd_types == ZFS_TYPE_POOL) 665b1b8ab34Slling return (NULL); 666b1b8ab34Slling 667b1b8ab34Slling return (zfs_prop_table[prop].pd_values); 668fa9e4066Sahrens } 669fa9e4066Sahrens 670fa9e4066Sahrens /* 671fa9e4066Sahrens * Returns a string describing the set of acceptable values for the given 672b1b8ab34Slling * zpool property, or NULL if it cannot be set. 673fa9e4066Sahrens */ 674fa9e4066Sahrens const char * 675b1b8ab34Slling zpool_prop_values(zfs_prop_t prop) 676fa9e4066Sahrens { 677b1b8ab34Slling if (zfs_prop_table[prop].pd_types != ZFS_TYPE_POOL) 678b1b8ab34Slling return (NULL); 679b1b8ab34Slling 680fa9e4066Sahrens return (zfs_prop_table[prop].pd_values); 681fa9e4066Sahrens } 682fa9e4066Sahrens 683fa9e4066Sahrens /* 684fa9e4066Sahrens * Returns TRUE if this property is a string type. Note that index types 685fa9e4066Sahrens * (compression, checksum) are treated as strings in userland, even though they 686fa9e4066Sahrens * are stored numerically on disk. 687fa9e4066Sahrens */ 688fa9e4066Sahrens int 689fa9e4066Sahrens zfs_prop_is_string(zfs_prop_t prop) 690fa9e4066Sahrens { 69191ebeef5Sahrens return (zfs_prop_table[prop].pd_proptype == PROP_TYPE_STRING || 69291ebeef5Sahrens zfs_prop_table[prop].pd_proptype == PROP_TYPE_INDEX); 693fa9e4066Sahrens } 694fa9e4066Sahrens 695fa9e4066Sahrens /* 696fa9e4066Sahrens * Returns the column header for the given property. Used only in 697fa9e4066Sahrens * 'zfs list -o', but centralized here with the other property information. 698fa9e4066Sahrens */ 699fa9e4066Sahrens const char * 700fa9e4066Sahrens zfs_prop_column_name(zfs_prop_t prop) 701fa9e4066Sahrens { 702fa9e4066Sahrens return (zfs_prop_table[prop].pd_colname); 703fa9e4066Sahrens } 704fa9e4066Sahrens 705fa9e4066Sahrens /* 706e9dbad6fSeschrock * Returns whether the given property should be displayed right-justified for 707e9dbad6fSeschrock * 'zfs list'. 708fa9e4066Sahrens */ 709e9dbad6fSeschrock boolean_t 710e9dbad6fSeschrock zfs_prop_align_right(zfs_prop_t prop) 711fa9e4066Sahrens { 712e9dbad6fSeschrock return (zfs_prop_table[prop].pd_rightalign); 713fa9e4066Sahrens } 714fa9e4066Sahrens 715fa9e4066Sahrens /* 716e9dbad6fSeschrock * Determines the minimum width for the column, and indicates whether it's fixed 717e9dbad6fSeschrock * or not. Only string columns are non-fixed. 718fa9e4066Sahrens */ 719e9dbad6fSeschrock size_t 720e9dbad6fSeschrock zfs_prop_width(zfs_prop_t prop, boolean_t *fixed) 721fa9e4066Sahrens { 722e9dbad6fSeschrock prop_desc_t *pd = &zfs_prop_table[prop]; 72391ebeef5Sahrens const zfs_index_t *idx; 724e9dbad6fSeschrock size_t ret; 725fa9e4066Sahrens int i; 726fa9e4066Sahrens 727e9dbad6fSeschrock *fixed = B_TRUE; 728fa9e4066Sahrens 72907ba0419Seschrock /* 730e9dbad6fSeschrock * Start with the width of the column name. 73107ba0419Seschrock */ 732e9dbad6fSeschrock ret = strlen(pd->pd_colname); 733fa9e4066Sahrens 73407ba0419Seschrock /* 735e9dbad6fSeschrock * For fixed-width values, make sure the width is large enough to hold 736e9dbad6fSeschrock * any possible value. 73707ba0419Seschrock */ 738e9dbad6fSeschrock switch (pd->pd_proptype) { 73991ebeef5Sahrens case PROP_TYPE_NUMBER: 74007ba0419Seschrock /* 741e9dbad6fSeschrock * The maximum length of a human-readable number is 5 characters 742e9dbad6fSeschrock * ("20.4M", for example). 74307ba0419Seschrock */ 744e9dbad6fSeschrock if (ret < 5) 745e9dbad6fSeschrock ret = 5; 74607ba0419Seschrock /* 747e9dbad6fSeschrock * 'creation' is handled specially because it's a number 748e9dbad6fSeschrock * internally, but displayed as a date string. 74907ba0419Seschrock */ 750e9dbad6fSeschrock if (prop == ZFS_PROP_CREATION) 751e9dbad6fSeschrock *fixed = B_FALSE; 752e9dbad6fSeschrock break; 75391ebeef5Sahrens case PROP_TYPE_INDEX: 75491ebeef5Sahrens idx = zfs_prop_table[prop].pd_table; 755e9dbad6fSeschrock for (i = 0; idx[i].name != NULL; i++) { 756e9dbad6fSeschrock if (strlen(idx[i].name) > ret) 757e9dbad6fSeschrock ret = strlen(idx[i].name); 75807ba0419Seschrock } 759e9dbad6fSeschrock break; 76007ba0419Seschrock 76191ebeef5Sahrens case PROP_TYPE_STRING: 762e9dbad6fSeschrock *fixed = B_FALSE; 763e9dbad6fSeschrock break; 76407ba0419Seschrock } 765fa9e4066Sahrens 766e9dbad6fSeschrock return (ret); 767fa9e4066Sahrens } 768fa9e4066Sahrens 769fa9e4066Sahrens #endif 770