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 /* 29fa9e4066Sahrens * Master property table. 30fa9e4066Sahrens * 31fa9e4066Sahrens * This table keeps track of all the properties supported by ZFS, and their 32fa9e4066Sahrens * various attributes. Not all of these are needed by the kernel, and several 33fa9e4066Sahrens * are only used by a single libzfs client. But having them here centralizes 34fa9e4066Sahrens * all property information in one location. 35fa9e4066Sahrens * 36fa9e4066Sahrens * name The human-readable string representing this property 37fa9e4066Sahrens * proptype Basic type (string, boolean, number) 38fa9e4066Sahrens * default Default value for the property. Sadly, C only allows 39fa9e4066Sahrens * you to initialize the first member of a union, so we 40fa9e4066Sahrens * have two default members for each property. 41fa9e4066Sahrens * attr Attributes (readonly, inheritable) for the property 42fa9e4066Sahrens * types Valid dataset types to which this applies 43fa9e4066Sahrens * values String describing acceptable values for the property 44fa9e4066Sahrens * colname The column header for 'zfs list' 45fa9e4066Sahrens * colfmt The column formatting for 'zfs list' 46fa9e4066Sahrens * 47fa9e4066Sahrens * This table must match the order of property types in libzfs.h. 48fa9e4066Sahrens */ 49fa9e4066Sahrens 50fa9e4066Sahrens #include <sys/zio.h> 51fa9e4066Sahrens #include <sys/spa.h> 52fa9e4066Sahrens #include <sys/zfs_acl.h> 53fa9e4066Sahrens #include <sys/zfs_ioctl.h> 54e7437265Sahrens #include <sys/zfs_znode.h> 55fa9e4066Sahrens 56fa9e4066Sahrens #include "zfs_prop.h" 57ecd6cf80Smarks #include "zfs_deleg.h" 58fa9e4066Sahrens 59fa9e4066Sahrens #if defined(_KERNEL) 60fa9e4066Sahrens #include <sys/systm.h> 61*d3c8f894Stimf #include <util/qsort.h> 62fa9e4066Sahrens #else 63fa9e4066Sahrens #include <stdlib.h> 64fa9e4066Sahrens #include <string.h> 65fa9e4066Sahrens #include <ctype.h> 66fa9e4066Sahrens #endif 67fa9e4066Sahrens 68fa9e4066Sahrens typedef enum { 69fa9e4066Sahrens prop_default, 70fa9e4066Sahrens prop_readonly, 71fa9e4066Sahrens prop_inherit 72fa9e4066Sahrens } prop_attr_t; 73fa9e4066Sahrens 74fa9e4066Sahrens typedef struct { 75fa9e4066Sahrens const char *pd_name; 76fa9e4066Sahrens zfs_proptype_t pd_proptype; 77fa9e4066Sahrens uint64_t pd_numdefault; 78fa9e4066Sahrens const char *pd_strdefault; 79fa9e4066Sahrens prop_attr_t pd_attr; 80fa9e4066Sahrens int pd_types; 81fa9e4066Sahrens const char *pd_values; 82fa9e4066Sahrens const char *pd_colname; 83e9dbad6fSeschrock boolean_t pd_rightalign; 8466e2aaccSgw25295 boolean_t pd_visible; 85ecd6cf80Smarks const char *pd_perm; 86fa9e4066Sahrens } prop_desc_t; 87fa9e4066Sahrens 8866e2aaccSgw25295 static prop_desc_t zfs_prop_table[] = { 89fa9e4066Sahrens { "type", prop_type_string, 0, NULL, prop_readonly, 9066e2aaccSgw25295 ZFS_TYPE_ANY, "filesystem | volume | snapshot", "TYPE", B_TRUE, 91ecd6cf80Smarks B_TRUE, ZFS_DELEG_PERM_NONE }, 92fa9e4066Sahrens { "creation", prop_type_number, 0, NULL, prop_readonly, 93ecd6cf80Smarks ZFS_TYPE_ANY, "<date>", "CREATION", B_FALSE, B_TRUE, 94ecd6cf80Smarks ZFS_DELEG_PERM_NONE }, 95fa9e4066Sahrens { "used", prop_type_number, 0, NULL, prop_readonly, 96ecd6cf80Smarks ZFS_TYPE_ANY, "<size>", "USED", B_TRUE, B_TRUE, 97ecd6cf80Smarks ZFS_DELEG_PERM_NONE }, 98fa9e4066Sahrens { "available", prop_type_number, 0, NULL, prop_readonly, 9966e2aaccSgw25295 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>", "AVAIL", B_TRUE, 100ecd6cf80Smarks B_TRUE, ZFS_DELEG_PERM_NONE }, 101fa9e4066Sahrens { "referenced", prop_type_number, 0, NULL, prop_readonly, 1024f75c27eSeschrock ZFS_TYPE_ANY, 103ecd6cf80Smarks "<size>", "REFER", B_TRUE, B_TRUE, ZFS_DELEG_PERM_NONE }, 104fa9e4066Sahrens { "compressratio", prop_type_number, 0, NULL, prop_readonly, 10566e2aaccSgw25295 ZFS_TYPE_ANY, "<1.00x or higher if compressed>", "RATIO", B_TRUE, 106ecd6cf80Smarks B_TRUE, ZFS_DELEG_PERM_NONE }, 107fa9e4066Sahrens { "mounted", prop_type_boolean, 0, NULL, prop_readonly, 108ecd6cf80Smarks ZFS_TYPE_FILESYSTEM, "yes | no | -", "MOUNTED", B_TRUE, B_TRUE, 109ecd6cf80Smarks ZFS_DELEG_PERM_NONE }, 110fa9e4066Sahrens { "origin", prop_type_string, 0, NULL, prop_readonly, 111101f5531Slling ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<snapshot>", "ORIGIN", 112ecd6cf80Smarks B_FALSE, B_TRUE, ZFS_DELEG_PERM_NONE }, 113fa9e4066Sahrens { "quota", prop_type_number, 0, NULL, prop_default, 114ecd6cf80Smarks ZFS_TYPE_FILESYSTEM, "<size> | none", "QUOTA", B_TRUE, B_TRUE, 115ecd6cf80Smarks ZFS_DELEG_PERM_QUOTA }, 116fa9e4066Sahrens { "reservation", prop_type_number, 0, NULL, prop_default, 117fa9e4066Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 118ecd6cf80Smarks "<size> | none", "RESERV", B_TRUE, B_TRUE, 119ecd6cf80Smarks ZFS_DELEG_PERM_RESERVATION }, 120fa9e4066Sahrens { "volsize", prop_type_number, 0, NULL, prop_default, 121ecd6cf80Smarks ZFS_TYPE_VOLUME, "<size>", "VOLSIZE", B_TRUE, B_TRUE, 122ecd6cf80Smarks ZFS_DELEG_PERM_VOLSIZE }, 1234f75c27eSeschrock { "volblocksize", prop_type_number, 8192, NULL, prop_readonly, 12466e2aaccSgw25295 ZFS_TYPE_VOLUME, "512 to 128k, power of 2", "VOLBLOCK", B_TRUE, 125ecd6cf80Smarks B_TRUE, ZFS_DELEG_PERM_NONE }, 126fa9e4066Sahrens { "recordsize", prop_type_number, SPA_MAXBLOCKSIZE, NULL, 127fa9e4066Sahrens prop_inherit, 1284f75c27eSeschrock ZFS_TYPE_FILESYSTEM, 129ecd6cf80Smarks "512 to 128k, power of 2", "RECSIZE", B_TRUE, B_TRUE, 130ecd6cf80Smarks ZFS_DELEG_PERM_RECORDSIZE }, 131fa9e4066Sahrens { "mountpoint", prop_type_string, 0, "/", prop_inherit, 132fa9e4066Sahrens ZFS_TYPE_FILESYSTEM, 133ecd6cf80Smarks "<path> | legacy | none", "MOUNTPOINT", B_FALSE, B_TRUE, 134ecd6cf80Smarks ZFS_DELEG_PERM_MOUNTPOINT }, 135fa9e4066Sahrens { "sharenfs", prop_type_string, 0, "off", prop_inherit, 136fa9e4066Sahrens ZFS_TYPE_FILESYSTEM, 137ecd6cf80Smarks "on | off | share(1M) options", "SHARENFS", B_FALSE, B_TRUE, 138ecd6cf80Smarks ZFS_DELEG_PERM_SHARENFS }, 139101f5531Slling { "checksum", prop_type_index, ZIO_CHECKSUM_DEFAULT, "on", 1404f75c27eSeschrock prop_inherit, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 14166e2aaccSgw25295 "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM", B_TRUE, 142ecd6cf80Smarks B_TRUE, ZFS_DELEG_PERM_CHECKSUM }, 143101f5531Slling { "compression", prop_type_index, ZIO_COMPRESS_DEFAULT, "off", 1444f75c27eSeschrock prop_inherit, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 145ecd6cf80Smarks "on | off | lzjb | gzip | gzip-[1-9]", "COMPRESS", B_TRUE, B_TRUE, 146ecd6cf80Smarks ZFS_DELEG_PERM_COMPRESSION }, 147fa9e4066Sahrens { "atime", prop_type_boolean, 1, NULL, prop_inherit, 148fa9e4066Sahrens ZFS_TYPE_FILESYSTEM, 149ecd6cf80Smarks "on | off", "ATIME", B_TRUE, B_TRUE, ZFS_DELEG_PERM_ATIME }, 150fa9e4066Sahrens { "devices", prop_type_boolean, 1, NULL, prop_inherit, 15112054bfcSnd150628 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, 152ecd6cf80Smarks "on | off", "DEVICES", B_TRUE, B_TRUE, ZFS_DELEG_PERM_DEVICES }, 153fa9e4066Sahrens { "exec", prop_type_boolean, 1, NULL, prop_inherit, 15412054bfcSnd150628 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, 155ecd6cf80Smarks "on | off", "EXEC", B_TRUE, B_TRUE, ZFS_DELEG_PERM_EXEC }, 156fa9e4066Sahrens { "setuid", prop_type_boolean, 1, NULL, prop_inherit, 15712054bfcSnd150628 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "SETUID", 158ecd6cf80Smarks B_TRUE, B_TRUE, ZFS_DELEG_PERM_SETUID }, 159fa9e4066Sahrens { "readonly", prop_type_boolean, 0, NULL, prop_inherit, 1604f75c27eSeschrock ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 161ecd6cf80Smarks "on | off", "RDONLY", B_TRUE, B_TRUE, ZFS_DELEG_PERM_READONLY }, 162fa9e4066Sahrens { "zoned", prop_type_boolean, 0, NULL, prop_inherit, 1634f75c27eSeschrock ZFS_TYPE_FILESYSTEM, 164ecd6cf80Smarks "on | off", "ZONED", B_TRUE, B_TRUE, ZFS_DELEG_PERM_ZONED }, 165906d120cSlling { "snapdir", prop_type_index, ZFS_SNAPDIR_HIDDEN, "hidden", 166a0965f35Sbonwick prop_inherit, 167fa9e4066Sahrens ZFS_TYPE_FILESYSTEM, 168ecd6cf80Smarks "hidden | visible", "SNAPDIR", B_TRUE, B_TRUE, 169ecd6cf80Smarks ZFS_DELEG_PERM_SNAPDIR }, 170e9dbad6fSeschrock { "aclmode", prop_type_index, ZFS_ACL_GROUPMASK, "groupmask", 171e9dbad6fSeschrock prop_inherit, ZFS_TYPE_FILESYSTEM, 172ecd6cf80Smarks "discard | groupmask | passthrough", "ACLMODE", B_TRUE, 173ecd6cf80Smarks B_TRUE, ZFS_DELEG_PERM_ACLMODE }, 174e9dbad6fSeschrock { "aclinherit", prop_type_index, ZFS_ACL_SECURE, "secure", 175e9dbad6fSeschrock prop_inherit, ZFS_TYPE_FILESYSTEM, 17666e2aaccSgw25295 "discard | noallow | secure | passthrough", "ACLINHERIT", B_TRUE, 177ecd6cf80Smarks B_TRUE, ZFS_DELEG_PERM_ACLINHERIT }, 17866e2aaccSgw25295 { "createtxg", prop_type_number, 0, NULL, prop_readonly, 179ecd6cf80Smarks ZFS_TYPE_ANY, NULL, NULL, B_FALSE, B_FALSE, ZFS_DELEG_PERM_NONE }, 18066e2aaccSgw25295 { "name", prop_type_string, 0, NULL, prop_readonly, 181ecd6cf80Smarks ZFS_TYPE_ANY, NULL, "NAME", B_FALSE, B_FALSE, ZFS_DELEG_PERM_NONE }, 182e9dbad6fSeschrock { "canmount", prop_type_boolean, 1, NULL, prop_default, 183fa9e4066Sahrens ZFS_TYPE_FILESYSTEM, 184ecd6cf80Smarks "on | off", "CANMOUNT", B_TRUE, B_TRUE, ZFS_DELEG_PERM_CANMOUNT }, 18566e2aaccSgw25295 { "shareiscsi", prop_type_string, 0, "off", prop_inherit, 18666e2aaccSgw25295 ZFS_TYPE_ANY, 187ecd6cf80Smarks "on | off | type=<type>", "SHAREISCSI", B_FALSE, B_TRUE, 188ecd6cf80Smarks ZFS_DELEG_PERM_SHAREISCSI }, 18966e2aaccSgw25295 { "iscsioptions", prop_type_string, 0, NULL, prop_inherit, 190ecd6cf80Smarks ZFS_TYPE_VOLUME, NULL, "ISCSIOPTIONS", B_FALSE, B_FALSE, 191ecd6cf80Smarks ZFS_DELEG_PERM_NONE }, 1927b55fa8eSck153898 { "xattr", prop_type_boolean, 1, NULL, prop_inherit, 1937b55fa8eSck153898 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, 194ecd6cf80Smarks "on | off", "XATTR", B_TRUE, B_TRUE, ZFS_DELEG_PERM_XATTR }, 19539c23413Seschrock { "numclones", prop_type_number, 0, NULL, prop_readonly, 196ecd6cf80Smarks ZFS_TYPE_SNAPSHOT, NULL, NULL, B_FALSE, B_FALSE, 197ecd6cf80Smarks ZFS_DELEG_PERM_NONE }, 198d0ad202dSahrens { "copies", prop_type_index, 1, "1", prop_inherit, 199d0ad202dSahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 200ecd6cf80Smarks "1 | 2 | 3", "COPIES", B_TRUE, B_TRUE, ZFS_DELEG_PERM_COPIES }, 201b1b8ab34Slling { "bootfs", prop_type_string, 0, NULL, prop_default, 202ecd6cf80Smarks ZFS_TYPE_POOL, "<filesystem>", "BOOTFS", B_FALSE, 203ecd6cf80Smarks B_TRUE, ZFS_DELEG_PERM_NONE }, 2043d7072f8Seschrock { "autoreplace", prop_type_boolean, 0, NULL, prop_default, 205ecd6cf80Smarks ZFS_TYPE_POOL, "on | off", "REPLACE", B_FALSE, B_TRUE, 206ecd6cf80Smarks ZFS_DELEG_PERM_NONE }, 207ecd6cf80Smarks { "delegation", prop_type_boolean, 1, NULL, prop_default, 208ecd6cf80Smarks ZFS_TYPE_POOL, "on | off", "DELEGATION", B_TRUE, 209e7437265Sahrens B_TRUE, ZFS_DELEG_PERM_NONE }, 210e7437265Sahrens { "version", prop_type_index, 0, NULL, prop_default, 211e7437265Sahrens ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "1 | 2 | current", 212e7437265Sahrens "VERSION", B_TRUE, B_TRUE, ZFS_DELEG_PERM_VERSION }, 213fa9e4066Sahrens }; 214fa9e4066Sahrens 21566e2aaccSgw25295 #define ZFS_PROP_COUNT ((sizeof (zfs_prop_table))/(sizeof (prop_desc_t))) 21666e2aaccSgw25295 217b1b8ab34Slling /* 218b1b8ab34Slling * Returns TRUE if the property applies to the given dataset types. 219b1b8ab34Slling */ 220b1b8ab34Slling int 221b1b8ab34Slling zfs_prop_valid_for_type(zfs_prop_t prop, int types) 222b1b8ab34Slling { 223b1b8ab34Slling return ((zfs_prop_table[prop].pd_types & types) != 0); 224b1b8ab34Slling } 225b1b8ab34Slling 226b1b8ab34Slling /* 227b1b8ab34Slling * Determine if the specified property is visible or not. 228b1b8ab34Slling */ 229b1b8ab34Slling boolean_t 230b1b8ab34Slling zfs_prop_is_visible(zfs_prop_t prop) 231b1b8ab34Slling { 232b1b8ab34Slling if (prop < 0) 233b1b8ab34Slling return (B_FALSE); 234b1b8ab34Slling 235b1b8ab34Slling return (zfs_prop_table[prop].pd_visible); 236b1b8ab34Slling } 237b1b8ab34Slling 238b1b8ab34Slling /* 239*d3c8f894Stimf * A comparison function we can use to order indexes into the 240*d3c8f894Stimf * zfs_prop_table[] 241*d3c8f894Stimf */ 242*d3c8f894Stimf static int 243*d3c8f894Stimf zfs_prop_compare(const void *p1, const void *p2) 244*d3c8f894Stimf { 245*d3c8f894Stimf int i, j; 246*d3c8f894Stimf prop_attr_t iattr, jattr; 247*d3c8f894Stimf 248*d3c8f894Stimf i = *((int *)p1); 249*d3c8f894Stimf j = *((int *)p2); 250*d3c8f894Stimf 251*d3c8f894Stimf iattr = zfs_prop_table[i].pd_attr; 252*d3c8f894Stimf jattr = zfs_prop_table[j].pd_attr; 253*d3c8f894Stimf 254*d3c8f894Stimf /* first, sort by whether the property is readonly or not */ 255*d3c8f894Stimf if (iattr != prop_readonly && 256*d3c8f894Stimf jattr == prop_readonly) 257*d3c8f894Stimf return (1); 258*d3c8f894Stimf if (iattr == prop_readonly && 259*d3c8f894Stimf jattr != prop_readonly) 260*d3c8f894Stimf return (-1); 261*d3c8f894Stimf 262*d3c8f894Stimf /* otherwise, sort by the property name */ 263*d3c8f894Stimf return (strcmp(zfs_prop_table[i].pd_name, 264*d3c8f894Stimf zfs_prop_table[j].pd_name)); 265*d3c8f894Stimf } 266*d3c8f894Stimf 267*d3c8f894Stimf /* 268b1b8ab34Slling * Iterate over all properties, calling back into the specified function 269b1b8ab34Slling * for each property. We will continue to iterate until we either 270b1b8ab34Slling * reach the end or the callback function something other than 271b1b8ab34Slling * ZFS_PROP_CONT. 272b1b8ab34Slling */ 273b1b8ab34Slling zfs_prop_t 274b1b8ab34Slling zfs_prop_iter_common(zfs_prop_f func, void *cb, zfs_type_t type, 275*d3c8f894Stimf boolean_t show_all, boolean_t ordered) 276b1b8ab34Slling { 277b1b8ab34Slling int i; 278*d3c8f894Stimf int order[ZFS_PROP_COUNT]; 279*d3c8f894Stimf 280*d3c8f894Stimf for (int j = 0; j < ZFS_PROP_COUNT; j++) { 281*d3c8f894Stimf order[j] = j; 282*d3c8f894Stimf } 283*d3c8f894Stimf 284*d3c8f894Stimf 285*d3c8f894Stimf if (ordered) { 286*d3c8f894Stimf qsort((void *)order, ZFS_PROP_COUNT, sizeof (zfs_prop_t), 287*d3c8f894Stimf zfs_prop_compare); 288*d3c8f894Stimf } 289b1b8ab34Slling 290b1b8ab34Slling for (i = 0; i < ZFS_PROP_COUNT; i++) { 291*d3c8f894Stimf if (zfs_prop_valid_for_type(order[i], type) && 292*d3c8f894Stimf (zfs_prop_is_visible(order[i]) || show_all)) { 293*d3c8f894Stimf if (func(order[i], cb) != ZFS_PROP_CONT) 294*d3c8f894Stimf return (order[i]); 295b1b8ab34Slling } 296b1b8ab34Slling } 297b1b8ab34Slling return (ZFS_PROP_CONT); 298b1b8ab34Slling } 299b1b8ab34Slling 300b1b8ab34Slling zfs_prop_t 301b1b8ab34Slling zfs_prop_iter(zfs_prop_f func, void *cb, boolean_t show_all) 302b1b8ab34Slling { 303*d3c8f894Stimf return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, show_all, 304*d3c8f894Stimf B_FALSE)); 305*d3c8f894Stimf } 306*d3c8f894Stimf 307*d3c8f894Stimf zfs_prop_t 308*d3c8f894Stimf zfs_prop_iter_ordered(zfs_prop_f func, void *cb, boolean_t show_all) 309*d3c8f894Stimf { 310*d3c8f894Stimf return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, show_all, 311*d3c8f894Stimf B_TRUE)); 312b1b8ab34Slling } 313b1b8ab34Slling 314b1b8ab34Slling zpool_prop_t 315b1b8ab34Slling zpool_prop_iter(zpool_prop_f func, void *cb, boolean_t show_all) 316b1b8ab34Slling { 317*d3c8f894Stimf return (zfs_prop_iter_common(func, cb, ZFS_TYPE_POOL, show_all, 318*d3c8f894Stimf B_FALSE)); 319b1b8ab34Slling } 320b1b8ab34Slling 321fa9e4066Sahrens zfs_proptype_t 322fa9e4066Sahrens zfs_prop_get_type(zfs_prop_t prop) 323fa9e4066Sahrens { 324fa9e4066Sahrens return (zfs_prop_table[prop].pd_proptype); 325fa9e4066Sahrens } 326fa9e4066Sahrens 3273d7072f8Seschrock zfs_proptype_t 3283d7072f8Seschrock zpool_prop_get_type(zfs_prop_t prop) 3293d7072f8Seschrock { 3303d7072f8Seschrock return (zfs_prop_table[prop].pd_proptype); 3313d7072f8Seschrock } 3323d7072f8Seschrock 333e9dbad6fSeschrock static boolean_t 334e9dbad6fSeschrock propname_match(const char *p, zfs_prop_t prop, size_t len) 3355c709891Seschrock { 3365c709891Seschrock const char *propname = zfs_prop_table[prop].pd_name; 3375c709891Seschrock #ifndef _KERNEL 3385c709891Seschrock const char *colname = zfs_prop_table[prop].pd_colname; 3395c709891Seschrock int c; 3405c709891Seschrock #endif 3415c709891Seschrock 3423bb79becSeschrock #ifndef _KERNEL 3433bb79becSeschrock if (colname == NULL) 344e9dbad6fSeschrock return (B_FALSE); 3453bb79becSeschrock #endif 3463bb79becSeschrock 3475c709891Seschrock if (len == strlen(propname) && 3485c709891Seschrock strncmp(p, propname, len) == 0) 349e9dbad6fSeschrock return (B_TRUE); 3505c709891Seschrock 3515c709891Seschrock #ifndef _KERNEL 3523bb79becSeschrock if (len != strlen(colname)) 353e9dbad6fSeschrock return (B_FALSE); 3545c709891Seschrock 3555c709891Seschrock for (c = 0; c < len; c++) 3565c709891Seschrock if (p[c] != tolower(colname[c])) 3575c709891Seschrock break; 3585c709891Seschrock 3595c709891Seschrock return (colname[c] == '\0'); 3605c709891Seschrock #else 361e9dbad6fSeschrock return (B_FALSE); 3625c709891Seschrock #endif 3635c709891Seschrock } 3645c709891Seschrock 36566e2aaccSgw25295 zfs_prop_t 36666e2aaccSgw25295 zfs_name_to_prop_cb(zfs_prop_t prop, void *cb_data) 36766e2aaccSgw25295 { 36866e2aaccSgw25295 const char *propname = cb_data; 36966e2aaccSgw25295 370ecd6cf80Smarks if (propname_match(propname, prop, strlen(propname))) { 37166e2aaccSgw25295 return (prop); 372ecd6cf80Smarks } 37366e2aaccSgw25295 37466e2aaccSgw25295 return (ZFS_PROP_CONT); 37566e2aaccSgw25295 } 3765c709891Seschrock 377fa9e4066Sahrens /* 378b1b8ab34Slling * Given a property name and its type, returns the corresponding property ID. 379b1b8ab34Slling */ 380b1b8ab34Slling zfs_prop_t 381b1b8ab34Slling zfs_name_to_prop_common(const char *propname, zfs_type_t type) 382b1b8ab34Slling { 383b1b8ab34Slling zfs_prop_t prop; 384b1b8ab34Slling 385b1b8ab34Slling prop = zfs_prop_iter_common(zfs_name_to_prop_cb, (void *)propname, 386*d3c8f894Stimf type, B_TRUE, B_FALSE); 387b1b8ab34Slling return (prop == ZFS_PROP_CONT ? ZFS_PROP_INVAL : prop); 388b1b8ab34Slling } 389b1b8ab34Slling 390b1b8ab34Slling /* 391b1b8ab34Slling * Given a zfs dataset property name, returns the corresponding property ID. 392fa9e4066Sahrens */ 393fa9e4066Sahrens zfs_prop_t 394fa9e4066Sahrens zfs_name_to_prop(const char *propname) 395fa9e4066Sahrens { 396b1b8ab34Slling return (zfs_name_to_prop_common(propname, ZFS_TYPE_ANY)); 397b1b8ab34Slling } 398fa9e4066Sahrens 399b1b8ab34Slling /* 400b1b8ab34Slling * Given a pool property name, returns the corresponding property ID. 401b1b8ab34Slling */ 402b1b8ab34Slling zpool_prop_t 403b1b8ab34Slling zpool_name_to_prop(const char *propname) 404b1b8ab34Slling { 405b1b8ab34Slling return (zfs_name_to_prop_common(propname, ZFS_TYPE_POOL)); 406fa9e4066Sahrens } 407fa9e4066Sahrens 408ecd6cf80Smarks const char * 409ecd6cf80Smarks zfs_prop_perm(zfs_prop_t prop) 410ecd6cf80Smarks { 411ecd6cf80Smarks return (zfs_prop_table[prop].pd_perm); 412ecd6cf80Smarks } 413ecd6cf80Smarks 414fa9e4066Sahrens /* 415e9dbad6fSeschrock * For user property names, we allow all lowercase alphanumeric characters, plus 416e9dbad6fSeschrock * a few useful punctuation characters. 417e9dbad6fSeschrock */ 418e9dbad6fSeschrock static int 419e9dbad6fSeschrock valid_char(char c) 420e9dbad6fSeschrock { 421e9dbad6fSeschrock return ((c >= 'a' && c <= 'z') || 422e9dbad6fSeschrock (c >= '0' && c <= '9') || 423e9dbad6fSeschrock c == '-' || c == '_' || c == '.' || c == ':'); 424e9dbad6fSeschrock } 425e9dbad6fSeschrock 426e9dbad6fSeschrock /* 427e9dbad6fSeschrock * Returns true if this is a valid user-defined property (one with a ':'). 428e9dbad6fSeschrock */ 429e9dbad6fSeschrock boolean_t 430e9dbad6fSeschrock zfs_prop_user(const char *name) 431e9dbad6fSeschrock { 432e9dbad6fSeschrock int i; 433e9dbad6fSeschrock char c; 434e9dbad6fSeschrock boolean_t foundsep = B_FALSE; 435e9dbad6fSeschrock 436e9dbad6fSeschrock for (i = 0; i < strlen(name); i++) { 437e9dbad6fSeschrock c = name[i]; 438e9dbad6fSeschrock if (!valid_char(c)) 439e9dbad6fSeschrock return (B_FALSE); 440e9dbad6fSeschrock if (c == ':') 441e9dbad6fSeschrock foundsep = B_TRUE; 442e9dbad6fSeschrock } 443e9dbad6fSeschrock 444e9dbad6fSeschrock if (!foundsep) 445e9dbad6fSeschrock return (B_FALSE); 446e9dbad6fSeschrock 447e9dbad6fSeschrock return (B_TRUE); 448e9dbad6fSeschrock } 449e9dbad6fSeschrock 450e9dbad6fSeschrock /* 451fa9e4066Sahrens * Return the default value for the given property. 452fa9e4066Sahrens */ 4537f7322feSeschrock const char * 4547f7322feSeschrock zfs_prop_default_string(zfs_prop_t prop) 455fa9e4066Sahrens { 4567f7322feSeschrock return (zfs_prop_table[prop].pd_strdefault); 457fa9e4066Sahrens } 458fa9e4066Sahrens 4593d7072f8Seschrock const char * 4603d7072f8Seschrock zpool_prop_default_string(zpool_prop_t prop) 4613d7072f8Seschrock { 4623d7072f8Seschrock return (zfs_prop_table[prop].pd_strdefault); 4633d7072f8Seschrock } 4643d7072f8Seschrock 465fa9e4066Sahrens uint64_t 466fa9e4066Sahrens zfs_prop_default_numeric(zfs_prop_t prop) 467fa9e4066Sahrens { 468fa9e4066Sahrens return (zfs_prop_table[prop].pd_numdefault); 469fa9e4066Sahrens } 470fa9e4066Sahrens 4713d7072f8Seschrock uint64_t 4723d7072f8Seschrock zpool_prop_default_numeric(zpool_prop_t prop) 4733d7072f8Seschrock { 4743d7072f8Seschrock return (zfs_prop_table[prop].pd_numdefault); 4753d7072f8Seschrock } 4763d7072f8Seschrock 477fa9e4066Sahrens /* 478fa9e4066Sahrens * Returns TRUE if the property is readonly. 479fa9e4066Sahrens */ 480fa9e4066Sahrens int 481fa9e4066Sahrens zfs_prop_readonly(zfs_prop_t prop) 482fa9e4066Sahrens { 483fa9e4066Sahrens return (zfs_prop_table[prop].pd_attr == prop_readonly); 484fa9e4066Sahrens } 485fa9e4066Sahrens 486fa9e4066Sahrens /* 487b1b8ab34Slling * Given a dataset property ID, returns the corresponding name. 4883d7072f8Seschrock * Assuming the zfs dataset property ID is valid. 489fa9e4066Sahrens */ 490fa9e4066Sahrens const char * 491fa9e4066Sahrens zfs_prop_to_name(zfs_prop_t prop) 492fa9e4066Sahrens { 493fa9e4066Sahrens return (zfs_prop_table[prop].pd_name); 494fa9e4066Sahrens } 495fa9e4066Sahrens 496fa9e4066Sahrens /* 497b1b8ab34Slling * Given a pool property ID, returns the corresponding name. 4983d7072f8Seschrock * Assuming the pool property ID is valid. 499b1b8ab34Slling */ 500b1b8ab34Slling const char * 501b1b8ab34Slling zpool_prop_to_name(zpool_prop_t prop) 502b1b8ab34Slling { 503b1b8ab34Slling return (zfs_prop_table[prop].pd_name); 504b1b8ab34Slling } 505b1b8ab34Slling 506b1b8ab34Slling /* 507fa9e4066Sahrens * Returns TRUE if the property is inheritable. 508fa9e4066Sahrens */ 509fa9e4066Sahrens int 510fa9e4066Sahrens zfs_prop_inheritable(zfs_prop_t prop) 511fa9e4066Sahrens { 512fa9e4066Sahrens return (zfs_prop_table[prop].pd_attr == prop_inherit); 513fa9e4066Sahrens } 514fa9e4066Sahrens 515e9dbad6fSeschrock typedef struct zfs_index { 516e9dbad6fSeschrock const char *name; 517e9dbad6fSeschrock uint64_t index; 518e9dbad6fSeschrock } zfs_index_t; 519e9dbad6fSeschrock 520e9dbad6fSeschrock static zfs_index_t checksum_table[] = { 521e9dbad6fSeschrock { "on", ZIO_CHECKSUM_ON }, 522e9dbad6fSeschrock { "off", ZIO_CHECKSUM_OFF }, 523e9dbad6fSeschrock { "fletcher2", ZIO_CHECKSUM_FLETCHER_2 }, 524e9dbad6fSeschrock { "fletcher4", ZIO_CHECKSUM_FLETCHER_4 }, 525e9dbad6fSeschrock { "sha256", ZIO_CHECKSUM_SHA256 }, 526e9dbad6fSeschrock { NULL } 527e9dbad6fSeschrock }; 528e9dbad6fSeschrock 529e9dbad6fSeschrock static zfs_index_t compress_table[] = { 530e9dbad6fSeschrock { "on", ZIO_COMPRESS_ON }, 531e9dbad6fSeschrock { "off", ZIO_COMPRESS_OFF }, 532e9dbad6fSeschrock { "lzjb", ZIO_COMPRESS_LZJB }, 533c9431fa1Sahl { "gzip", ZIO_COMPRESS_GZIP_6 }, /* the default gzip level */ 534c9431fa1Sahl { "gzip-1", ZIO_COMPRESS_GZIP_1 }, 535c9431fa1Sahl { "gzip-2", ZIO_COMPRESS_GZIP_2 }, 536c9431fa1Sahl { "gzip-3", ZIO_COMPRESS_GZIP_3 }, 537c9431fa1Sahl { "gzip-4", ZIO_COMPRESS_GZIP_4 }, 538c9431fa1Sahl { "gzip-5", ZIO_COMPRESS_GZIP_5 }, 539c9431fa1Sahl { "gzip-6", ZIO_COMPRESS_GZIP_6 }, 540c9431fa1Sahl { "gzip-7", ZIO_COMPRESS_GZIP_7 }, 541c9431fa1Sahl { "gzip-8", ZIO_COMPRESS_GZIP_8 }, 542c9431fa1Sahl { "gzip-9", ZIO_COMPRESS_GZIP_9 }, 543e9dbad6fSeschrock { NULL } 544e9dbad6fSeschrock }; 545e9dbad6fSeschrock 546e9dbad6fSeschrock static zfs_index_t snapdir_table[] = { 547e9dbad6fSeschrock { "hidden", ZFS_SNAPDIR_HIDDEN }, 548e9dbad6fSeschrock { "visible", ZFS_SNAPDIR_VISIBLE }, 549e9dbad6fSeschrock { NULL } 550e9dbad6fSeschrock }; 551e9dbad6fSeschrock 552e9dbad6fSeschrock static zfs_index_t acl_mode_table[] = { 553e9dbad6fSeschrock { "discard", ZFS_ACL_DISCARD }, 554e9dbad6fSeschrock { "groupmask", ZFS_ACL_GROUPMASK }, 555e9dbad6fSeschrock { "passthrough", ZFS_ACL_PASSTHROUGH }, 556e9dbad6fSeschrock { NULL } 557e9dbad6fSeschrock }; 558e9dbad6fSeschrock 559e9dbad6fSeschrock static zfs_index_t acl_inherit_table[] = { 560e9dbad6fSeschrock { "discard", ZFS_ACL_DISCARD }, 561e9dbad6fSeschrock { "noallow", ZFS_ACL_NOALLOW }, 562e9dbad6fSeschrock { "secure", ZFS_ACL_SECURE }, 563e9dbad6fSeschrock { "passthrough", ZFS_ACL_PASSTHROUGH }, 564e9dbad6fSeschrock { NULL } 565e9dbad6fSeschrock }; 566e9dbad6fSeschrock 567d0ad202dSahrens static zfs_index_t copies_table[] = { 568d0ad202dSahrens { "1", 1 }, 569d0ad202dSahrens { "2", 2 }, 570d0ad202dSahrens { "3", 3 }, 571d0ad202dSahrens { NULL } 572d0ad202dSahrens }; 573d0ad202dSahrens 574e7437265Sahrens static zfs_index_t version_table[] = { 575e7437265Sahrens { "1", 1 }, 576e7437265Sahrens { "2", 2 }, 577e7437265Sahrens { "current", ZPL_VERSION }, 578e7437265Sahrens { NULL } 579e7437265Sahrens }; 580e7437265Sahrens 581e9dbad6fSeschrock static zfs_index_t * 582e9dbad6fSeschrock zfs_prop_index_table(zfs_prop_t prop) 583e9dbad6fSeschrock { 584e9dbad6fSeschrock switch (prop) { 585e9dbad6fSeschrock case ZFS_PROP_CHECKSUM: 586e9dbad6fSeschrock return (checksum_table); 587e9dbad6fSeschrock case ZFS_PROP_COMPRESSION: 588e9dbad6fSeschrock return (compress_table); 589e9dbad6fSeschrock case ZFS_PROP_SNAPDIR: 590e9dbad6fSeschrock return (snapdir_table); 591e9dbad6fSeschrock case ZFS_PROP_ACLMODE: 592e9dbad6fSeschrock return (acl_mode_table); 593e9dbad6fSeschrock case ZFS_PROP_ACLINHERIT: 594e9dbad6fSeschrock return (acl_inherit_table); 595d0ad202dSahrens case ZFS_PROP_COPIES: 596d0ad202dSahrens return (copies_table); 597e7437265Sahrens case ZFS_PROP_VERSION: 598e7437265Sahrens return (version_table); 599e9dbad6fSeschrock default: 600e9dbad6fSeschrock return (NULL); 601e9dbad6fSeschrock } 602e9dbad6fSeschrock } 603e9dbad6fSeschrock 604e9dbad6fSeschrock /* 605e9dbad6fSeschrock * Tables of index types, plus functions to convert between the user view 606e9dbad6fSeschrock * (strings) and internal representation (uint64_t). 607e9dbad6fSeschrock */ 608e9dbad6fSeschrock int 609e9dbad6fSeschrock zfs_prop_string_to_index(zfs_prop_t prop, const char *string, uint64_t *index) 610e9dbad6fSeschrock { 611e9dbad6fSeschrock zfs_index_t *table; 612e9dbad6fSeschrock int i; 613e9dbad6fSeschrock 614e9dbad6fSeschrock if ((table = zfs_prop_index_table(prop)) == NULL) 615e9dbad6fSeschrock return (-1); 616e9dbad6fSeschrock 617e9dbad6fSeschrock for (i = 0; table[i].name != NULL; i++) { 618e9dbad6fSeschrock if (strcmp(string, table[i].name) == 0) { 619e9dbad6fSeschrock *index = table[i].index; 620e9dbad6fSeschrock return (0); 621e9dbad6fSeschrock } 622e9dbad6fSeschrock } 623e9dbad6fSeschrock 624e9dbad6fSeschrock return (-1); 625e9dbad6fSeschrock } 626e9dbad6fSeschrock 627e9dbad6fSeschrock int 628e9dbad6fSeschrock zfs_prop_index_to_string(zfs_prop_t prop, uint64_t index, const char **string) 629e9dbad6fSeschrock { 630e9dbad6fSeschrock zfs_index_t *table; 631e9dbad6fSeschrock int i; 632e9dbad6fSeschrock 633e9dbad6fSeschrock if ((table = zfs_prop_index_table(prop)) == NULL) 634e9dbad6fSeschrock return (-1); 635e9dbad6fSeschrock 636e9dbad6fSeschrock for (i = 0; table[i].name != NULL; i++) { 637e9dbad6fSeschrock if (table[i].index == index) { 638e9dbad6fSeschrock *string = table[i].name; 639e9dbad6fSeschrock return (0); 640e9dbad6fSeschrock } 641e9dbad6fSeschrock } 642e9dbad6fSeschrock 643e9dbad6fSeschrock return (-1); 644e9dbad6fSeschrock } 645e9dbad6fSeschrock 646acd76fe5Seschrock #ifndef _KERNEL 647acd76fe5Seschrock 648fa9e4066Sahrens /* 649fa9e4066Sahrens * Returns a string describing the set of acceptable values for the given 650b1b8ab34Slling * zfs property, or NULL if it cannot be set. 651fa9e4066Sahrens */ 652fa9e4066Sahrens const char * 653fa9e4066Sahrens zfs_prop_values(zfs_prop_t prop) 654fa9e4066Sahrens { 655b1b8ab34Slling if (zfs_prop_table[prop].pd_types == ZFS_TYPE_POOL) 656b1b8ab34Slling return (NULL); 657b1b8ab34Slling 658b1b8ab34Slling return (zfs_prop_table[prop].pd_values); 659b1b8ab34Slling } 660b1b8ab34Slling 661b1b8ab34Slling /* 662b1b8ab34Slling * Returns a string describing the set of acceptable values for the given 663b1b8ab34Slling * zpool property, or NULL if it cannot be set. 664b1b8ab34Slling */ 665b1b8ab34Slling const char * 666b1b8ab34Slling zpool_prop_values(zfs_prop_t prop) 667b1b8ab34Slling { 668b1b8ab34Slling if (zfs_prop_table[prop].pd_types != ZFS_TYPE_POOL) 669b1b8ab34Slling return (NULL); 670b1b8ab34Slling 671fa9e4066Sahrens return (zfs_prop_table[prop].pd_values); 672fa9e4066Sahrens } 673fa9e4066Sahrens 674fa9e4066Sahrens /* 675fa9e4066Sahrens * Returns TRUE if this property is a string type. Note that index types 676fa9e4066Sahrens * (compression, checksum) are treated as strings in userland, even though they 677fa9e4066Sahrens * are stored numerically on disk. 678fa9e4066Sahrens */ 679fa9e4066Sahrens int 680fa9e4066Sahrens zfs_prop_is_string(zfs_prop_t prop) 681fa9e4066Sahrens { 682fa9e4066Sahrens return (zfs_prop_table[prop].pd_proptype == prop_type_string || 683fa9e4066Sahrens zfs_prop_table[prop].pd_proptype == prop_type_index); 684fa9e4066Sahrens } 685fa9e4066Sahrens 686fa9e4066Sahrens /* 687fa9e4066Sahrens * Returns the column header for the given property. Used only in 688fa9e4066Sahrens * 'zfs list -o', but centralized here with the other property information. 689fa9e4066Sahrens */ 690fa9e4066Sahrens const char * 691fa9e4066Sahrens zfs_prop_column_name(zfs_prop_t prop) 692fa9e4066Sahrens { 693fa9e4066Sahrens return (zfs_prop_table[prop].pd_colname); 694fa9e4066Sahrens } 695fa9e4066Sahrens 696fa9e4066Sahrens /* 697e9dbad6fSeschrock * Returns whether the given property should be displayed right-justified for 698e9dbad6fSeschrock * 'zfs list'. 699fa9e4066Sahrens */ 700e9dbad6fSeschrock boolean_t 701e9dbad6fSeschrock zfs_prop_align_right(zfs_prop_t prop) 702fa9e4066Sahrens { 703e9dbad6fSeschrock return (zfs_prop_table[prop].pd_rightalign); 704fa9e4066Sahrens } 705fa9e4066Sahrens 706fa9e4066Sahrens /* 707e9dbad6fSeschrock * Determines the minimum width for the column, and indicates whether it's fixed 708e9dbad6fSeschrock * or not. Only string columns are non-fixed. 709fa9e4066Sahrens */ 710e9dbad6fSeschrock size_t 711e9dbad6fSeschrock zfs_prop_width(zfs_prop_t prop, boolean_t *fixed) 712fa9e4066Sahrens { 713e9dbad6fSeschrock prop_desc_t *pd = &zfs_prop_table[prop]; 714e9dbad6fSeschrock zfs_index_t *idx; 715e9dbad6fSeschrock size_t ret; 716fa9e4066Sahrens int i; 717fa9e4066Sahrens 718e9dbad6fSeschrock *fixed = B_TRUE; 719fa9e4066Sahrens 72007ba0419Seschrock /* 721e9dbad6fSeschrock * Start with the width of the column name. 72207ba0419Seschrock */ 723e9dbad6fSeschrock ret = strlen(pd->pd_colname); 724fa9e4066Sahrens 725e9dbad6fSeschrock /* 726e9dbad6fSeschrock * For fixed-width values, make sure the width is large enough to hold 727e9dbad6fSeschrock * any possible value. 728e9dbad6fSeschrock */ 729e9dbad6fSeschrock switch (pd->pd_proptype) { 730e9dbad6fSeschrock case prop_type_number: 731e9dbad6fSeschrock /* 732e9dbad6fSeschrock * The maximum length of a human-readable number is 5 characters 733e9dbad6fSeschrock * ("20.4M", for example). 734e9dbad6fSeschrock */ 735e9dbad6fSeschrock if (ret < 5) 736e9dbad6fSeschrock ret = 5; 737e9dbad6fSeschrock /* 738e9dbad6fSeschrock * 'creation' is handled specially because it's a number 739e9dbad6fSeschrock * internally, but displayed as a date string. 740e9dbad6fSeschrock */ 741e9dbad6fSeschrock if (prop == ZFS_PROP_CREATION) 742e9dbad6fSeschrock *fixed = B_FALSE; 743e9dbad6fSeschrock break; 744e9dbad6fSeschrock case prop_type_boolean: 745e9dbad6fSeschrock /* 746e9dbad6fSeschrock * The maximum length of a boolean value is 3 characters, for 747e9dbad6fSeschrock * "off". 748e9dbad6fSeschrock */ 749e9dbad6fSeschrock if (ret < 3) 750e9dbad6fSeschrock ret = 3; 751e9dbad6fSeschrock break; 752e9dbad6fSeschrock case prop_type_index: 753e9dbad6fSeschrock idx = zfs_prop_index_table(prop); 754e9dbad6fSeschrock for (i = 0; idx[i].name != NULL; i++) { 755e9dbad6fSeschrock if (strlen(idx[i].name) > ret) 756e9dbad6fSeschrock ret = strlen(idx[i].name); 757fa9e4066Sahrens } 758e9dbad6fSeschrock break; 759fa9e4066Sahrens 760e9dbad6fSeschrock case prop_type_string: 761e9dbad6fSeschrock *fixed = B_FALSE; 76207ba0419Seschrock break; 76307ba0419Seschrock } 76407ba0419Seschrock 765e9dbad6fSeschrock return (ret); 766fa9e4066Sahrens } 767fa9e4066Sahrens 768fa9e4066Sahrens #endif 769