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 { 47*91ebeef5Sahrens PROP_DEFAULT, 48*91ebeef5Sahrens PROP_READONLY, 49*91ebeef5Sahrens PROP_INHERIT 50fa9e4066Sahrens } prop_attr_t; 51fa9e4066Sahrens 52*91ebeef5Sahrens typedef struct zfs_index { 53*91ebeef5Sahrens const char *name; 54*91ebeef5Sahrens uint64_t index; 55*91ebeef5Sahrens } zfs_index_t; 56*91ebeef5Sahrens 57fa9e4066Sahrens typedef struct { 58*91ebeef5Sahrens const char *pd_name; /* human-readable property name */ 59*91ebeef5Sahrens zfs_proptype_t pd_proptype; /* string, boolean, index, number */ 60*91ebeef5Sahrens const char *pd_strdefault; /* default for strings */ 61*91ebeef5Sahrens uint64_t pd_numdefault; /* for boolean / index / number */ 62*91ebeef5Sahrens prop_attr_t pd_attr; /* default, readonly, inherit */ 63*91ebeef5Sahrens int pd_types; /* bitfield of valid dataset types */ 64*91ebeef5Sahrens /* fs | vol | snap; or pool */ 65*91ebeef5Sahrens const char *pd_values; /* string telling acceptable values */ 66*91ebeef5Sahrens const char *pd_colname; /* column header for "zfs list" */ 67*91ebeef5Sahrens boolean_t pd_rightalign; /* column alignment for "zfs list" */ 68*91ebeef5Sahrens boolean_t pd_visible; /* do we list this property with the */ 69*91ebeef5Sahrens /* "zfs get" help message */ 70*91ebeef5Sahrens const zfs_index_t *pd_table; /* for index properties, a table */ 71*91ebeef5Sahrens /* defining the possible values */ 72fa9e4066Sahrens } prop_desc_t; 73fa9e4066Sahrens 74*91ebeef5Sahrens static prop_desc_t zfs_prop_table[ZFS_NUM_PROPS]; 75*91ebeef5Sahrens 76*91ebeef5Sahrens static void 77*91ebeef5Sahrens register_impl(zfs_prop_t prop, const char *name, zfs_proptype_t type, 78*91ebeef5Sahrens uint64_t numdefault, const char *strdefault, prop_attr_t attr, 79*91ebeef5Sahrens int objset_types, const char *values, const char *colname, 80*91ebeef5Sahrens boolean_t rightalign, boolean_t visible, const zfs_index_t *table) 81*91ebeef5Sahrens { 82*91ebeef5Sahrens prop_desc_t *pd = &zfs_prop_table[prop]; 83*91ebeef5Sahrens 84*91ebeef5Sahrens ASSERT(pd->pd_name == NULL || pd->pd_name == name); 85*91ebeef5Sahrens 86*91ebeef5Sahrens pd->pd_name = name; 87*91ebeef5Sahrens pd->pd_proptype = type; 88*91ebeef5Sahrens pd->pd_numdefault = numdefault; 89*91ebeef5Sahrens pd->pd_strdefault = strdefault; 90*91ebeef5Sahrens pd->pd_attr = attr; 91*91ebeef5Sahrens pd->pd_types = objset_types; 92*91ebeef5Sahrens pd->pd_values = values; 93*91ebeef5Sahrens pd->pd_colname = colname; 94*91ebeef5Sahrens pd->pd_rightalign = rightalign; 95*91ebeef5Sahrens pd->pd_visible = visible; 96*91ebeef5Sahrens pd->pd_table = table; 97*91ebeef5Sahrens } 98*91ebeef5Sahrens 99*91ebeef5Sahrens static void 100*91ebeef5Sahrens register_string(zfs_prop_t prop, const char *name, const char *def, 101*91ebeef5Sahrens prop_attr_t attr, int objset_types, const char *values, 102*91ebeef5Sahrens const char *colname) 103*91ebeef5Sahrens { 104*91ebeef5Sahrens register_impl(prop, name, PROP_TYPE_STRING, 0, def, attr, 105*91ebeef5Sahrens objset_types, values, colname, B_FALSE, B_TRUE, NULL); 106*91ebeef5Sahrens 107*91ebeef5Sahrens } 108*91ebeef5Sahrens 109*91ebeef5Sahrens static void 110*91ebeef5Sahrens register_number(zfs_prop_t prop, const char *name, uint64_t def, 111*91ebeef5Sahrens prop_attr_t attr, int objset_types, const char *values, const char *colname) 112*91ebeef5Sahrens { 113*91ebeef5Sahrens register_impl(prop, name, PROP_TYPE_NUMBER, def, NULL, attr, 114*91ebeef5Sahrens objset_types, values, colname, B_TRUE, B_TRUE, NULL); 115*91ebeef5Sahrens } 116*91ebeef5Sahrens 117*91ebeef5Sahrens static void 118*91ebeef5Sahrens register_boolean(zfs_prop_t prop, const char *name, uint64_t def, 119*91ebeef5Sahrens prop_attr_t attr, int objset_types, const char *values, const char *colname) 120*91ebeef5Sahrens { 121*91ebeef5Sahrens register_impl(prop, name, PROP_TYPE_BOOLEAN, def, NULL, attr, 122*91ebeef5Sahrens objset_types, values, colname, B_TRUE, B_TRUE, NULL); 123*91ebeef5Sahrens } 124*91ebeef5Sahrens 125*91ebeef5Sahrens static void 126*91ebeef5Sahrens register_index(zfs_prop_t prop, const char *name, uint64_t def, 127*91ebeef5Sahrens int objset_types, const char *values, const char *colname, 128*91ebeef5Sahrens const zfs_index_t *table) 129*91ebeef5Sahrens { 130*91ebeef5Sahrens register_impl(prop, name, PROP_TYPE_INDEX, def, NULL, PROP_INHERIT, 131*91ebeef5Sahrens objset_types, values, colname, B_TRUE, B_TRUE, table); 132*91ebeef5Sahrens } 133*91ebeef5Sahrens 134*91ebeef5Sahrens static void 135*91ebeef5Sahrens register_hidden(zfs_prop_t prop, const char *name, zfs_proptype_t type, 136*91ebeef5Sahrens prop_attr_t attr, int objset_types, const char *colname) 137*91ebeef5Sahrens { 138*91ebeef5Sahrens register_impl(prop, name, type, 0, NULL, attr, 139*91ebeef5Sahrens objset_types, NULL, colname, B_FALSE, B_FALSE, NULL); 140*91ebeef5Sahrens } 141*91ebeef5Sahrens 142*91ebeef5Sahrens void 143*91ebeef5Sahrens zfs_prop_init(void) 144*91ebeef5Sahrens { 145*91ebeef5Sahrens static zfs_index_t checksum_table[] = { 146*91ebeef5Sahrens { "on", ZIO_CHECKSUM_ON }, 147*91ebeef5Sahrens { "off", ZIO_CHECKSUM_OFF }, 148*91ebeef5Sahrens { "fletcher2", ZIO_CHECKSUM_FLETCHER_2 }, 149*91ebeef5Sahrens { "fletcher4", ZIO_CHECKSUM_FLETCHER_4 }, 150*91ebeef5Sahrens { "sha256", ZIO_CHECKSUM_SHA256 }, 151*91ebeef5Sahrens { NULL } 152*91ebeef5Sahrens }; 153*91ebeef5Sahrens 154*91ebeef5Sahrens static zfs_index_t compress_table[] = { 155*91ebeef5Sahrens { "on", ZIO_COMPRESS_ON }, 156*91ebeef5Sahrens { "off", ZIO_COMPRESS_OFF }, 157*91ebeef5Sahrens { "lzjb", ZIO_COMPRESS_LZJB }, 158*91ebeef5Sahrens { "gzip", ZIO_COMPRESS_GZIP_6 }, /* gzip default */ 159*91ebeef5Sahrens { "gzip-1", ZIO_COMPRESS_GZIP_1 }, 160*91ebeef5Sahrens { "gzip-2", ZIO_COMPRESS_GZIP_2 }, 161*91ebeef5Sahrens { "gzip-3", ZIO_COMPRESS_GZIP_3 }, 162*91ebeef5Sahrens { "gzip-4", ZIO_COMPRESS_GZIP_4 }, 163*91ebeef5Sahrens { "gzip-5", ZIO_COMPRESS_GZIP_5 }, 164*91ebeef5Sahrens { "gzip-6", ZIO_COMPRESS_GZIP_6 }, 165*91ebeef5Sahrens { "gzip-7", ZIO_COMPRESS_GZIP_7 }, 166*91ebeef5Sahrens { "gzip-8", ZIO_COMPRESS_GZIP_8 }, 167*91ebeef5Sahrens { "gzip-9", ZIO_COMPRESS_GZIP_9 }, 168*91ebeef5Sahrens { NULL } 169*91ebeef5Sahrens }; 170*91ebeef5Sahrens 171*91ebeef5Sahrens static zfs_index_t snapdir_table[] = { 172*91ebeef5Sahrens { "hidden", ZFS_SNAPDIR_HIDDEN }, 173*91ebeef5Sahrens { "visible", ZFS_SNAPDIR_VISIBLE }, 174*91ebeef5Sahrens { NULL } 175*91ebeef5Sahrens }; 176*91ebeef5Sahrens 177*91ebeef5Sahrens static zfs_index_t acl_mode_table[] = { 178*91ebeef5Sahrens { "discard", ZFS_ACL_DISCARD }, 179*91ebeef5Sahrens { "groupmask", ZFS_ACL_GROUPMASK }, 180*91ebeef5Sahrens { "passthrough", ZFS_ACL_PASSTHROUGH }, 181*91ebeef5Sahrens { NULL } 182*91ebeef5Sahrens }; 183*91ebeef5Sahrens 184*91ebeef5Sahrens static zfs_index_t acl_inherit_table[] = { 185*91ebeef5Sahrens { "discard", ZFS_ACL_DISCARD }, 186*91ebeef5Sahrens { "noallow", ZFS_ACL_NOALLOW }, 187*91ebeef5Sahrens { "secure", ZFS_ACL_SECURE }, 188*91ebeef5Sahrens { "passthrough", ZFS_ACL_PASSTHROUGH }, 189*91ebeef5Sahrens { NULL } 190*91ebeef5Sahrens }; 191*91ebeef5Sahrens 192*91ebeef5Sahrens static zfs_index_t copies_table[] = { 193*91ebeef5Sahrens { "1", 1 }, 194*91ebeef5Sahrens { "2", 2 }, 195*91ebeef5Sahrens { "3", 3 }, 196*91ebeef5Sahrens { NULL } 197*91ebeef5Sahrens }; 198*91ebeef5Sahrens 199*91ebeef5Sahrens static zfs_index_t version_table[] = { 200*91ebeef5Sahrens { "1", 1 }, 201*91ebeef5Sahrens { "2", 2 }, 202*91ebeef5Sahrens { "current", ZPL_VERSION }, 203*91ebeef5Sahrens { NULL } 204*91ebeef5Sahrens }; 205*91ebeef5Sahrens 206*91ebeef5Sahrens /* inherit index properties */ 207*91ebeef5Sahrens register_index(ZFS_PROP_CHECKSUM, "checksum", ZIO_CHECKSUM_DEFAULT, 208fa9e4066Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 209*91ebeef5Sahrens "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM", 210*91ebeef5Sahrens checksum_table); 211*91ebeef5Sahrens register_index(ZFS_PROP_COMPRESSION, "compression", 212*91ebeef5Sahrens ZIO_COMPRESS_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 213*91ebeef5Sahrens "on | off | lzjb | gzip | gzip-[1-9]", "COMPRESS", compress_table); 214*91ebeef5Sahrens register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN, 215*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "hidden | visible", "SNAPDIR", snapdir_table); 216*91ebeef5Sahrens register_index(ZFS_PROP_ACLMODE, "aclmode", ZFS_ACL_GROUPMASK, 217*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "discard | groupmask | passthrough", "ACLMODE", 218*91ebeef5Sahrens acl_mode_table); 219*91ebeef5Sahrens register_index(ZFS_PROP_ACLINHERIT, "aclinherit", ZFS_ACL_SECURE, 220fa9e4066Sahrens ZFS_TYPE_FILESYSTEM, 221*91ebeef5Sahrens "discard | noallow | secure | passthrough", "ACLINHERIT", 222*91ebeef5Sahrens acl_inherit_table); 223*91ebeef5Sahrens register_index(ZFS_PROP_COPIES, "copies", 1, 2244f75c27eSeschrock ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 225*91ebeef5Sahrens "1 | 2 | 3", "COPIES", copies_table); 226*91ebeef5Sahrens register_index(ZFS_PROP_VERSION, "version", 0, 2277b55fa8eSck ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, 228*91ebeef5Sahrens "1 | 2 | current", "VERSION", version_table); 229*91ebeef5Sahrens 230*91ebeef5Sahrens /* string properties */ 231*91ebeef5Sahrens register_string(ZFS_PROP_ORIGIN, "origin", NULL, PROP_READONLY, 232*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<snapshot>", "ORIGIN"); 233*91ebeef5Sahrens register_string(ZPOOL_PROP_BOOTFS, "bootfs", NULL, PROP_DEFAULT, 234*91ebeef5Sahrens ZFS_TYPE_POOL, "<filesystem>", "BOOTFS"); 235*91ebeef5Sahrens register_string(ZFS_PROP_MOUNTPOINT, "mountpoint", "/", PROP_INHERIT, 236*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "<path> | legacy | none", "MOUNTPOINT"); 237*91ebeef5Sahrens register_string(ZFS_PROP_SHARENFS, "sharenfs", "off", PROP_INHERIT, 238*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "on | off | share(1M) options", "SHARENFS"); 239*91ebeef5Sahrens register_string(ZFS_PROP_SHAREISCSI, "shareiscsi", "off", PROP_INHERIT, 240*91ebeef5Sahrens ZFS_TYPE_ANY, "on | off | type=<type>", "SHAREISCSI"); 241*91ebeef5Sahrens register_string(ZFS_PROP_TYPE, "type", NULL, PROP_READONLY, 242*91ebeef5Sahrens ZFS_TYPE_ANY, "filesystem | volume | snapshot", "TYPE"); 243*91ebeef5Sahrens 244*91ebeef5Sahrens /* readonly number properties */ 245*91ebeef5Sahrens register_number(ZFS_PROP_USED, "used", 0, PROP_READONLY, 246*91ebeef5Sahrens ZFS_TYPE_ANY, "<size>", "USED"); 247*91ebeef5Sahrens register_number(ZFS_PROP_AVAILABLE, "available", 0, PROP_READONLY, 248d0ad202dSahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 249*91ebeef5Sahrens "<size>", "AVAIL"); 250*91ebeef5Sahrens register_number(ZFS_PROP_REFERENCED, "referenced", 0, PROP_READONLY, 251*91ebeef5Sahrens ZFS_TYPE_ANY, "<size>", "REFER"); 252*91ebeef5Sahrens register_number(ZFS_PROP_COMPRESSRATIO, "compressratio", 0, 253*91ebeef5Sahrens PROP_READONLY, ZFS_TYPE_ANY, 254*91ebeef5Sahrens "<1.00x or higher if compressed>", "RATIO"); 255*91ebeef5Sahrens register_number(ZFS_PROP_VOLBLOCKSIZE, "volblocksize", 8192, 256*91ebeef5Sahrens PROP_READONLY, 257*91ebeef5Sahrens ZFS_TYPE_VOLUME, "512 to 128k, power of 2", "VOLBLOCK"); 258*91ebeef5Sahrens 259*91ebeef5Sahrens /* default number properties */ 260*91ebeef5Sahrens register_number(ZFS_PROP_QUOTA, "quota", 0, PROP_DEFAULT, 261*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "<size> | none", "QUOTA"); 262*91ebeef5Sahrens register_number(ZFS_PROP_RESERVATION, "reservation", 0, PROP_DEFAULT, 263*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size> | none", "RESERV"); 264*91ebeef5Sahrens register_number(ZFS_PROP_VOLSIZE, "volsize", 0, PROP_DEFAULT, 265*91ebeef5Sahrens ZFS_TYPE_VOLUME, "<size>", "VOLSIZE"); 266*91ebeef5Sahrens 267*91ebeef5Sahrens /* inherit number properties */ 268*91ebeef5Sahrens register_number(ZFS_PROP_RECORDSIZE, "recordsize", SPA_MAXBLOCKSIZE, 269*91ebeef5Sahrens PROP_INHERIT, 270*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "512 to 128k, power of 2", "RECSIZE"); 271*91ebeef5Sahrens 272*91ebeef5Sahrens /* readonly boolean properties */ 273*91ebeef5Sahrens register_boolean(ZFS_PROP_MOUNTED, "mounted", 0, PROP_READONLY, 274*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "yes | no | -", "MOUNTED"); 275*91ebeef5Sahrens 276*91ebeef5Sahrens /* default boolean properties */ 277*91ebeef5Sahrens register_boolean(ZFS_PROP_CANMOUNT, "canmount", 1, PROP_DEFAULT, 278*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "on | off", "CANMOUNT"); 279*91ebeef5Sahrens register_boolean(ZPOOL_PROP_DELEGATION, "delegation", 1, PROP_DEFAULT, 280*91ebeef5Sahrens ZFS_TYPE_POOL, "on | off", "DELEGATION"); 281*91ebeef5Sahrens register_boolean(ZPOOL_PROP_AUTOREPLACE, "autoreplace", 0, PROP_DEFAULT, 282*91ebeef5Sahrens ZFS_TYPE_POOL, "on | off", "REPLACE"); 283*91ebeef5Sahrens 284*91ebeef5Sahrens /* inherit boolean properties */ 285*91ebeef5Sahrens register_boolean(ZFS_PROP_ATIME, "atime", 1, PROP_INHERIT, 286*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "on | off", "ATIME"); 287*91ebeef5Sahrens register_boolean(ZFS_PROP_DEVICES, "devices", 1, PROP_INHERIT, 288*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "DEVICES"); 289*91ebeef5Sahrens register_boolean(ZFS_PROP_EXEC, "exec", 1, PROP_INHERIT, 290*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "EXEC"); 291*91ebeef5Sahrens register_boolean(ZFS_PROP_SETUID, "setuid", 1, PROP_INHERIT, 292*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "SETUID"); 293*91ebeef5Sahrens register_boolean(ZFS_PROP_READONLY, "readonly", 0, PROP_INHERIT, 294*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "on | off", "RDONLY"); 295*91ebeef5Sahrens register_boolean(ZFS_PROP_ZONED, "zoned", 0, PROP_INHERIT, 296*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM, "on | off", "ZONED"); 297*91ebeef5Sahrens register_boolean(ZFS_PROP_XATTR, "xattr", 1, PROP_INHERIT, 298*91ebeef5Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "XATTR"); 299*91ebeef5Sahrens 300*91ebeef5Sahrens /* hidden properties */ 301*91ebeef5Sahrens register_hidden(ZFS_PROP_CREATETXG, "createtxg", PROP_TYPE_NUMBER, 302*91ebeef5Sahrens PROP_READONLY, ZFS_TYPE_ANY, NULL); 303*91ebeef5Sahrens register_hidden(ZFS_PROP_NUMCLONES, "numclones", PROP_TYPE_NUMBER, 304*91ebeef5Sahrens PROP_READONLY, ZFS_TYPE_SNAPSHOT, NULL); 305*91ebeef5Sahrens register_hidden(ZFS_PROP_NAME, "name", PROP_TYPE_STRING, 306*91ebeef5Sahrens PROP_READONLY, ZFS_TYPE_ANY, "NAME"); 307*91ebeef5Sahrens register_hidden(ZFS_PROP_ISCSIOPTIONS, "iscsioptions", PROP_TYPE_STRING, 308*91ebeef5Sahrens PROP_INHERIT, ZFS_TYPE_VOLUME, "ISCSIOPTIONS"); 309*91ebeef5Sahrens register_hidden(ZPOOL_PROP_NAME, "zpoolname", PROP_TYPE_STRING, 310*91ebeef5Sahrens PROP_READONLY, ZFS_TYPE_POOL, NULL); 311*91ebeef5Sahrens 312*91ebeef5Sahrens /* oddball properties */ 313*91ebeef5Sahrens register_impl(ZFS_PROP_CREATION, "creation", PROP_TYPE_NUMBER, 0, NULL, 314*91ebeef5Sahrens PROP_READONLY, ZFS_TYPE_ANY, 315*91ebeef5Sahrens "<date>", "CREATION", B_FALSE, B_TRUE, NULL); 316*91ebeef5Sahrens } 317*91ebeef5Sahrens 31866e2aaccSgw 319b1b8ab34Slling /* 320*91ebeef5Sahrens * Returns TRUE if the property applies to any of the given dataset types. 321b1b8ab34Slling */ 322b1b8ab34Slling int 323b1b8ab34Slling zfs_prop_valid_for_type(zfs_prop_t prop, int types) 324b1b8ab34Slling { 325b1b8ab34Slling return ((zfs_prop_table[prop].pd_types & types) != 0); 326b1b8ab34Slling } 327b1b8ab34Slling 328b1b8ab34Slling /* 329b1b8ab34Slling * Determine if the specified property is visible or not. 330b1b8ab34Slling */ 331b1b8ab34Slling boolean_t 332b1b8ab34Slling zfs_prop_is_visible(zfs_prop_t prop) 333b1b8ab34Slling { 334b1b8ab34Slling if (prop < 0) 335b1b8ab34Slling return (B_FALSE); 336b1b8ab34Slling 337b1b8ab34Slling return (zfs_prop_table[prop].pd_visible); 338b1b8ab34Slling } 339b1b8ab34Slling 340d3c8f894Stimf /* 341d3c8f894Stimf * A comparison function we can use to order indexes into the 342d3c8f894Stimf * zfs_prop_table[] 343d3c8f894Stimf */ 344d3c8f894Stimf static int 345*91ebeef5Sahrens zfs_prop_compare(const void *arg1, const void *arg2) 346d3c8f894Stimf { 347*91ebeef5Sahrens const zfs_prop_t *p1 = arg1; 348*91ebeef5Sahrens const zfs_prop_t *p2 = arg2; 349*91ebeef5Sahrens boolean_t p1ro, p2ro; 350d3c8f894Stimf 351*91ebeef5Sahrens p1ro = (zfs_prop_table[*p1].pd_attr == PROP_READONLY); 352*91ebeef5Sahrens p2ro = (zfs_prop_table[*p2].pd_attr == PROP_READONLY); 353d3c8f894Stimf 354*91ebeef5Sahrens if (p1ro == p2ro) { 355*91ebeef5Sahrens return (strcmp(zfs_prop_table[*p1].pd_name, 356*91ebeef5Sahrens zfs_prop_table[*p2].pd_name)); 357*91ebeef5Sahrens } 358d3c8f894Stimf 359*91ebeef5Sahrens return (p1ro ? -1 : 1); 360d3c8f894Stimf } 361d3c8f894Stimf 362b1b8ab34Slling /* 363b1b8ab34Slling * Iterate over all properties, calling back into the specified function 364b1b8ab34Slling * for each property. We will continue to iterate until we either 365b1b8ab34Slling * reach the end or the callback function something other than 366b1b8ab34Slling * ZFS_PROP_CONT. 367b1b8ab34Slling */ 368b1b8ab34Slling zfs_prop_t 369b1b8ab34Slling zfs_prop_iter_common(zfs_prop_f func, void *cb, zfs_type_t type, 370d3c8f894Stimf boolean_t show_all, boolean_t ordered) 371b1b8ab34Slling { 372b1b8ab34Slling int i; 373*91ebeef5Sahrens zfs_prop_t order[ZFS_NUM_PROPS]; 374d3c8f894Stimf 375*91ebeef5Sahrens for (int j = 0; j < ZFS_NUM_PROPS; j++) 376d3c8f894Stimf order[j] = j; 377d3c8f894Stimf 378d3c8f894Stimf 379d3c8f894Stimf if (ordered) { 380*91ebeef5Sahrens qsort((void *)order, ZFS_NUM_PROPS, sizeof (zfs_prop_t), 381d3c8f894Stimf zfs_prop_compare); 382d3c8f894Stimf } 383b1b8ab34Slling 384*91ebeef5Sahrens for (i = 0; i < ZFS_NUM_PROPS; i++) { 385d3c8f894Stimf if (zfs_prop_valid_for_type(order[i], type) && 386d3c8f894Stimf (zfs_prop_is_visible(order[i]) || show_all)) { 387d3c8f894Stimf if (func(order[i], cb) != ZFS_PROP_CONT) 388d3c8f894Stimf return (order[i]); 389b1b8ab34Slling } 390b1b8ab34Slling } 391b1b8ab34Slling return (ZFS_PROP_CONT); 392b1b8ab34Slling } 393b1b8ab34Slling 394b1b8ab34Slling zfs_prop_t 395*91ebeef5Sahrens zfs_prop_iter(zfs_prop_f func, void *cb) 396b1b8ab34Slling { 397*91ebeef5Sahrens return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, B_FALSE, B_FALSE)); 398d3c8f894Stimf } 399d3c8f894Stimf 400d3c8f894Stimf zfs_prop_t 401*91ebeef5Sahrens zfs_prop_iter_ordered(zfs_prop_f func, void *cb) 402d3c8f894Stimf { 403*91ebeef5Sahrens return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, B_FALSE, B_TRUE)); 404b1b8ab34Slling } 405b1b8ab34Slling 406b1b8ab34Slling zpool_prop_t 407*91ebeef5Sahrens zpool_prop_iter(zpool_prop_f func, void *cb) 408b1b8ab34Slling { 409*91ebeef5Sahrens return (zfs_prop_iter_common(func, cb, ZFS_TYPE_POOL, B_FALSE, 410d3c8f894Stimf B_FALSE)); 411b1b8ab34Slling } 412b1b8ab34Slling 413fa9e4066Sahrens zfs_proptype_t 414fa9e4066Sahrens zfs_prop_get_type(zfs_prop_t prop) 415fa9e4066Sahrens { 416fa9e4066Sahrens return (zfs_prop_table[prop].pd_proptype); 417fa9e4066Sahrens } 418fa9e4066Sahrens 4193d7072f8Seschrock zfs_proptype_t 4203d7072f8Seschrock zpool_prop_get_type(zfs_prop_t prop) 4213d7072f8Seschrock { 4223d7072f8Seschrock return (zfs_prop_table[prop].pd_proptype); 4233d7072f8Seschrock } 4243d7072f8Seschrock 425e9dbad6fSeschrock static boolean_t 426e9dbad6fSeschrock propname_match(const char *p, zfs_prop_t prop, size_t len) 4275c709891Seschrock { 4285c709891Seschrock const char *propname = zfs_prop_table[prop].pd_name; 4295c709891Seschrock #ifndef _KERNEL 4305c709891Seschrock const char *colname = zfs_prop_table[prop].pd_colname; 4315c709891Seschrock int c; 4325c709891Seschrock 4333bb79becSeschrock if (colname == NULL) 434e9dbad6fSeschrock return (B_FALSE); 4353bb79becSeschrock #endif 4363bb79becSeschrock 4375c709891Seschrock if (len == strlen(propname) && 4385c709891Seschrock strncmp(p, propname, len) == 0) 439e9dbad6fSeschrock return (B_TRUE); 4405c709891Seschrock 4415c709891Seschrock #ifndef _KERNEL 4423bb79becSeschrock if (len != strlen(colname)) 443e9dbad6fSeschrock return (B_FALSE); 4445c709891Seschrock 4455c709891Seschrock for (c = 0; c < len; c++) 4465c709891Seschrock if (p[c] != tolower(colname[c])) 4475c709891Seschrock break; 4485c709891Seschrock 4495c709891Seschrock return (colname[c] == '\0'); 4505c709891Seschrock #else 451e9dbad6fSeschrock return (B_FALSE); 4525c709891Seschrock #endif 4535c709891Seschrock } 4545c709891Seschrock 45566e2aaccSgw zfs_prop_t 45666e2aaccSgw zfs_name_to_prop_cb(zfs_prop_t prop, void *cb_data) 45766e2aaccSgw { 45866e2aaccSgw const char *propname = cb_data; 45966e2aaccSgw 460*91ebeef5Sahrens if (propname_match(propname, prop, strlen(propname))) 46166e2aaccSgw return (prop); 46266e2aaccSgw 46366e2aaccSgw return (ZFS_PROP_CONT); 46466e2aaccSgw } 4655c709891Seschrock 466fa9e4066Sahrens /* 467b1b8ab34Slling * Given a property name and its type, returns the corresponding property ID. 468fa9e4066Sahrens */ 469fa9e4066Sahrens zfs_prop_t 470b1b8ab34Slling zfs_name_to_prop_common(const char *propname, zfs_type_t type) 471fa9e4066Sahrens { 47266e2aaccSgw zfs_prop_t prop; 473fa9e4066Sahrens 474b1b8ab34Slling prop = zfs_prop_iter_common(zfs_name_to_prop_cb, (void *)propname, 475d3c8f894Stimf type, B_TRUE, B_FALSE); 47666e2aaccSgw return (prop == ZFS_PROP_CONT ? ZFS_PROP_INVAL : prop); 477fa9e4066Sahrens } 478fa9e4066Sahrens 479b1b8ab34Slling /* 480b1b8ab34Slling * Given a zfs dataset property name, returns the corresponding property ID. 481b1b8ab34Slling */ 482b1b8ab34Slling zfs_prop_t 483b1b8ab34Slling zfs_name_to_prop(const char *propname) 484b1b8ab34Slling { 485b1b8ab34Slling return (zfs_name_to_prop_common(propname, ZFS_TYPE_ANY)); 486b1b8ab34Slling } 487b1b8ab34Slling 488b1b8ab34Slling /* 489b1b8ab34Slling * Given a pool property name, returns the corresponding property ID. 490b1b8ab34Slling */ 491b1b8ab34Slling zpool_prop_t 492b1b8ab34Slling zpool_name_to_prop(const char *propname) 493b1b8ab34Slling { 494b1b8ab34Slling return (zfs_name_to_prop_common(propname, ZFS_TYPE_POOL)); 495b1b8ab34Slling } 496b1b8ab34Slling 497*91ebeef5Sahrens boolean_t 498*91ebeef5Sahrens zfs_prop_delegatable(zfs_prop_t prop) 499ecd6cf80Smarks { 500*91ebeef5Sahrens prop_desc_t *pd = &zfs_prop_table[prop]; 501*91ebeef5Sahrens return (pd->pd_attr != PROP_READONLY && pd->pd_types != ZFS_TYPE_POOL); 502ecd6cf80Smarks } 503ecd6cf80Smarks 504e9dbad6fSeschrock /* 505e9dbad6fSeschrock * For user property names, we allow all lowercase alphanumeric characters, plus 506e9dbad6fSeschrock * a few useful punctuation characters. 507e9dbad6fSeschrock */ 508e9dbad6fSeschrock static int 509e9dbad6fSeschrock valid_char(char c) 510e9dbad6fSeschrock { 511e9dbad6fSeschrock return ((c >= 'a' && c <= 'z') || 512e9dbad6fSeschrock (c >= '0' && c <= '9') || 513e9dbad6fSeschrock c == '-' || c == '_' || c == '.' || c == ':'); 514e9dbad6fSeschrock } 515e9dbad6fSeschrock 516e9dbad6fSeschrock /* 517e9dbad6fSeschrock * Returns true if this is a valid user-defined property (one with a ':'). 518e9dbad6fSeschrock */ 519e9dbad6fSeschrock boolean_t 520e9dbad6fSeschrock zfs_prop_user(const char *name) 521e9dbad6fSeschrock { 522e9dbad6fSeschrock int i; 523e9dbad6fSeschrock char c; 524e9dbad6fSeschrock boolean_t foundsep = B_FALSE; 525e9dbad6fSeschrock 526e9dbad6fSeschrock for (i = 0; i < strlen(name); i++) { 527e9dbad6fSeschrock c = name[i]; 528e9dbad6fSeschrock if (!valid_char(c)) 529e9dbad6fSeschrock return (B_FALSE); 530e9dbad6fSeschrock if (c == ':') 531e9dbad6fSeschrock foundsep = B_TRUE; 532e9dbad6fSeschrock } 533e9dbad6fSeschrock 534e9dbad6fSeschrock if (!foundsep) 535e9dbad6fSeschrock return (B_FALSE); 536e9dbad6fSeschrock 537e9dbad6fSeschrock return (B_TRUE); 538e9dbad6fSeschrock } 539e9dbad6fSeschrock 540fa9e4066Sahrens /* 541fa9e4066Sahrens * Return the default value for the given property. 542fa9e4066Sahrens */ 5437f7322feSeschrock const char * 5447f7322feSeschrock zfs_prop_default_string(zfs_prop_t prop) 545fa9e4066Sahrens { 5467f7322feSeschrock return (zfs_prop_table[prop].pd_strdefault); 547fa9e4066Sahrens } 548fa9e4066Sahrens 5493d7072f8Seschrock const char * 5503d7072f8Seschrock zpool_prop_default_string(zpool_prop_t prop) 5513d7072f8Seschrock { 5523d7072f8Seschrock return (zfs_prop_table[prop].pd_strdefault); 5533d7072f8Seschrock } 5543d7072f8Seschrock 555fa9e4066Sahrens uint64_t 556fa9e4066Sahrens zfs_prop_default_numeric(zfs_prop_t prop) 557fa9e4066Sahrens { 558fa9e4066Sahrens return (zfs_prop_table[prop].pd_numdefault); 559fa9e4066Sahrens } 560fa9e4066Sahrens 5613d7072f8Seschrock uint64_t 5623d7072f8Seschrock zpool_prop_default_numeric(zpool_prop_t prop) 5633d7072f8Seschrock { 5643d7072f8Seschrock return (zfs_prop_table[prop].pd_numdefault); 5653d7072f8Seschrock } 5663d7072f8Seschrock 567fa9e4066Sahrens /* 568fa9e4066Sahrens * Returns TRUE if the property is readonly. 569fa9e4066Sahrens */ 570fa9e4066Sahrens int 571fa9e4066Sahrens zfs_prop_readonly(zfs_prop_t prop) 572fa9e4066Sahrens { 573*91ebeef5Sahrens return (zfs_prop_table[prop].pd_attr == PROP_READONLY); 574fa9e4066Sahrens } 575fa9e4066Sahrens 576fa9e4066Sahrens /* 577b1b8ab34Slling * Given a dataset property ID, returns the corresponding name. 5783d7072f8Seschrock * Assuming the zfs dataset property ID is valid. 579fa9e4066Sahrens */ 580fa9e4066Sahrens const char * 581fa9e4066Sahrens zfs_prop_to_name(zfs_prop_t prop) 582fa9e4066Sahrens { 583fa9e4066Sahrens return (zfs_prop_table[prop].pd_name); 584fa9e4066Sahrens } 585fa9e4066Sahrens 586b1b8ab34Slling /* 587b1b8ab34Slling * Given a pool property ID, returns the corresponding name. 5883d7072f8Seschrock * Assuming the pool property ID is valid. 589b1b8ab34Slling */ 590b1b8ab34Slling const char * 591b1b8ab34Slling zpool_prop_to_name(zpool_prop_t prop) 592b1b8ab34Slling { 593b1b8ab34Slling return (zfs_prop_table[prop].pd_name); 594b1b8ab34Slling } 595b1b8ab34Slling 596fa9e4066Sahrens /* 597fa9e4066Sahrens * Returns TRUE if the property is inheritable. 598fa9e4066Sahrens */ 599fa9e4066Sahrens int 600fa9e4066Sahrens zfs_prop_inheritable(zfs_prop_t prop) 601fa9e4066Sahrens { 602*91ebeef5Sahrens return (zfs_prop_table[prop].pd_attr == PROP_INHERIT); 603e9dbad6fSeschrock } 604e9dbad6fSeschrock 605e9dbad6fSeschrock /* 606e9dbad6fSeschrock * Tables of index types, plus functions to convert between the user view 607e9dbad6fSeschrock * (strings) and internal representation (uint64_t). 608e9dbad6fSeschrock */ 609e9dbad6fSeschrock int 610e9dbad6fSeschrock zfs_prop_string_to_index(zfs_prop_t prop, const char *string, uint64_t *index) 611e9dbad6fSeschrock { 612*91ebeef5Sahrens const zfs_index_t *table; 613e9dbad6fSeschrock int i; 614e9dbad6fSeschrock 615*91ebeef5Sahrens if ((table = zfs_prop_table[prop].pd_table) == NULL) 616e9dbad6fSeschrock return (-1); 617e9dbad6fSeschrock 618e9dbad6fSeschrock for (i = 0; table[i].name != NULL; i++) { 619e9dbad6fSeschrock if (strcmp(string, table[i].name) == 0) { 620e9dbad6fSeschrock *index = table[i].index; 621e9dbad6fSeschrock return (0); 622e9dbad6fSeschrock } 623e9dbad6fSeschrock } 624e9dbad6fSeschrock 625e9dbad6fSeschrock return (-1); 626e9dbad6fSeschrock } 627e9dbad6fSeschrock 628e9dbad6fSeschrock int 629e9dbad6fSeschrock zfs_prop_index_to_string(zfs_prop_t prop, uint64_t index, const char **string) 630e9dbad6fSeschrock { 631*91ebeef5Sahrens const zfs_index_t *table; 632e9dbad6fSeschrock int i; 633e9dbad6fSeschrock 634*91ebeef5Sahrens if ((table = zfs_prop_table[prop].pd_table) == NULL) 635e9dbad6fSeschrock return (-1); 636e9dbad6fSeschrock 637e9dbad6fSeschrock for (i = 0; table[i].name != NULL; i++) { 638e9dbad6fSeschrock if (table[i].index == index) { 639e9dbad6fSeschrock *string = table[i].name; 640e9dbad6fSeschrock return (0); 641e9dbad6fSeschrock } 642e9dbad6fSeschrock } 643e9dbad6fSeschrock 644e9dbad6fSeschrock return (-1); 645e9dbad6fSeschrock } 646e9dbad6fSeschrock 647acd76fe5Seschrock #ifndef _KERNEL 648acd76fe5Seschrock 649fa9e4066Sahrens /* 650b1b8ab34Slling * Returns a string describing the set of acceptable values for the given 651b1b8ab34Slling * zfs property, or NULL if it cannot be set. 652fa9e4066Sahrens */ 653b1b8ab34Slling const char * 654b1b8ab34Slling zfs_prop_values(zfs_prop_t prop) 655fa9e4066Sahrens { 656b1b8ab34Slling if (zfs_prop_table[prop].pd_types == ZFS_TYPE_POOL) 657b1b8ab34Slling return (NULL); 658b1b8ab34Slling 659b1b8ab34Slling return (zfs_prop_table[prop].pd_values); 660fa9e4066Sahrens } 661fa9e4066Sahrens 662fa9e4066Sahrens /* 663fa9e4066Sahrens * Returns a string describing the set of acceptable values for the given 664b1b8ab34Slling * zpool property, or NULL if it cannot be set. 665fa9e4066Sahrens */ 666fa9e4066Sahrens const char * 667b1b8ab34Slling zpool_prop_values(zfs_prop_t prop) 668fa9e4066Sahrens { 669b1b8ab34Slling if (zfs_prop_table[prop].pd_types != ZFS_TYPE_POOL) 670b1b8ab34Slling return (NULL); 671b1b8ab34Slling 672fa9e4066Sahrens return (zfs_prop_table[prop].pd_values); 673fa9e4066Sahrens } 674fa9e4066Sahrens 675fa9e4066Sahrens /* 676fa9e4066Sahrens * Returns TRUE if this property is a string type. Note that index types 677fa9e4066Sahrens * (compression, checksum) are treated as strings in userland, even though they 678fa9e4066Sahrens * are stored numerically on disk. 679fa9e4066Sahrens */ 680fa9e4066Sahrens int 681fa9e4066Sahrens zfs_prop_is_string(zfs_prop_t prop) 682fa9e4066Sahrens { 683*91ebeef5Sahrens return (zfs_prop_table[prop].pd_proptype == PROP_TYPE_STRING || 684*91ebeef5Sahrens zfs_prop_table[prop].pd_proptype == PROP_TYPE_INDEX); 685fa9e4066Sahrens } 686fa9e4066Sahrens 687fa9e4066Sahrens /* 688fa9e4066Sahrens * Returns the column header for the given property. Used only in 689fa9e4066Sahrens * 'zfs list -o', but centralized here with the other property information. 690fa9e4066Sahrens */ 691fa9e4066Sahrens const char * 692fa9e4066Sahrens zfs_prop_column_name(zfs_prop_t prop) 693fa9e4066Sahrens { 694fa9e4066Sahrens return (zfs_prop_table[prop].pd_colname); 695fa9e4066Sahrens } 696fa9e4066Sahrens 697fa9e4066Sahrens /* 698e9dbad6fSeschrock * Returns whether the given property should be displayed right-justified for 699e9dbad6fSeschrock * 'zfs list'. 700fa9e4066Sahrens */ 701e9dbad6fSeschrock boolean_t 702e9dbad6fSeschrock zfs_prop_align_right(zfs_prop_t prop) 703fa9e4066Sahrens { 704e9dbad6fSeschrock return (zfs_prop_table[prop].pd_rightalign); 705fa9e4066Sahrens } 706fa9e4066Sahrens 707fa9e4066Sahrens /* 708e9dbad6fSeschrock * Determines the minimum width for the column, and indicates whether it's fixed 709e9dbad6fSeschrock * or not. Only string columns are non-fixed. 710fa9e4066Sahrens */ 711e9dbad6fSeschrock size_t 712e9dbad6fSeschrock zfs_prop_width(zfs_prop_t prop, boolean_t *fixed) 713fa9e4066Sahrens { 714e9dbad6fSeschrock prop_desc_t *pd = &zfs_prop_table[prop]; 715*91ebeef5Sahrens const zfs_index_t *idx; 716e9dbad6fSeschrock size_t ret; 717fa9e4066Sahrens int i; 718fa9e4066Sahrens 719e9dbad6fSeschrock *fixed = B_TRUE; 720fa9e4066Sahrens 72107ba0419Seschrock /* 722e9dbad6fSeschrock * Start with the width of the column name. 72307ba0419Seschrock */ 724e9dbad6fSeschrock ret = strlen(pd->pd_colname); 725fa9e4066Sahrens 72607ba0419Seschrock /* 727e9dbad6fSeschrock * For fixed-width values, make sure the width is large enough to hold 728e9dbad6fSeschrock * any possible value. 72907ba0419Seschrock */ 730e9dbad6fSeschrock switch (pd->pd_proptype) { 731*91ebeef5Sahrens case PROP_TYPE_NUMBER: 73207ba0419Seschrock /* 733e9dbad6fSeschrock * The maximum length of a human-readable number is 5 characters 734e9dbad6fSeschrock * ("20.4M", for example). 73507ba0419Seschrock */ 736e9dbad6fSeschrock if (ret < 5) 737e9dbad6fSeschrock ret = 5; 73807ba0419Seschrock /* 739e9dbad6fSeschrock * 'creation' is handled specially because it's a number 740e9dbad6fSeschrock * internally, but displayed as a date string. 74107ba0419Seschrock */ 742e9dbad6fSeschrock if (prop == ZFS_PROP_CREATION) 743e9dbad6fSeschrock *fixed = B_FALSE; 744e9dbad6fSeschrock break; 745*91ebeef5Sahrens case PROP_TYPE_BOOLEAN: 74607ba0419Seschrock /* 747e9dbad6fSeschrock * The maximum length of a boolean value is 3 characters, for 748e9dbad6fSeschrock * "off". 74907ba0419Seschrock */ 750e9dbad6fSeschrock if (ret < 3) 751e9dbad6fSeschrock ret = 3; 752e9dbad6fSeschrock break; 753*91ebeef5Sahrens case PROP_TYPE_INDEX: 754*91ebeef5Sahrens 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 761*91ebeef5Sahrens case PROP_TYPE_STRING: 762e9dbad6fSeschrock *fixed = B_FALSE; 763e9dbad6fSeschrock break; 76407ba0419Seschrock } 765fa9e4066Sahrens 766e9dbad6fSeschrock return (ret); 767fa9e4066Sahrens } 768fa9e4066Sahrens 769fa9e4066Sahrens #endif 770