1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * Master property table. 30 * 31 * This table keeps track of all the properties supported by ZFS, and their 32 * various attributes. Not all of these are needed by the kernel, and several 33 * are only used by a single libzfs client. But having them here centralizes 34 * all property information in one location. 35 * 36 * name The human-readable string representing this property 37 * proptype Basic type (string, boolean, number) 38 * default Default value for the property. Sadly, C only allows 39 * you to initialize the first member of a union, so we 40 * have two default members for each property. 41 * attr Attributes (readonly, inheritable) for the property 42 * types Valid dataset types to which this applies 43 * values String describing acceptable values for the property 44 * colname The column header for 'zfs list' 45 * colfmt The column formatting for 'zfs list' 46 * 47 * This table must match the order of property types in libzfs.h. 48 */ 49 50 #include <sys/zio.h> 51 #include <sys/spa.h> 52 #include <sys/zfs_acl.h> 53 #include <sys/zfs_ioctl.h> 54 55 #include "zfs_prop.h" 56 57 #if defined(_KERNEL) 58 #include <sys/systm.h> 59 #else 60 #include <stdlib.h> 61 #include <string.h> 62 #include <ctype.h> 63 #endif 64 65 typedef enum { 66 prop_default, 67 prop_readonly, 68 prop_inherit 69 } prop_attr_t; 70 71 typedef struct { 72 const char *pd_name; 73 zfs_proptype_t pd_proptype; 74 uint64_t pd_numdefault; 75 const char *pd_strdefault; 76 prop_attr_t pd_attr; 77 int pd_types; 78 const char *pd_values; 79 const char *pd_colname; 80 const char *pd_colfmt; 81 } prop_desc_t; 82 83 static prop_desc_t zfs_prop_table[ZFS_NPROP_ALL] = { 84 { "type", prop_type_string, 0, NULL, prop_readonly, 85 ZFS_TYPE_ANY, "filesystem | volume | snapshot", "TYPE", "%10s" }, 86 { "creation", prop_type_number, 0, NULL, prop_readonly, 87 ZFS_TYPE_ANY, "<date>", "CREATION", "%-20s" }, 88 { "used", prop_type_number, 0, NULL, prop_readonly, 89 ZFS_TYPE_ANY, "<size>", "USED", "%5s" }, 90 { "available", prop_type_number, 0, NULL, prop_readonly, 91 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>", "AVAIL", "%5s" }, 92 { "referenced", prop_type_number, 0, NULL, prop_readonly, 93 ZFS_TYPE_ANY, 94 "<size>", "REFER", "%5s" }, 95 { "compressratio", prop_type_number, 0, NULL, prop_readonly, 96 ZFS_TYPE_ANY, "<1.00x or higher if compressed>", "RATIO", "%5s" }, 97 { "mounted", prop_type_boolean, 0, NULL, prop_readonly, 98 ZFS_TYPE_FILESYSTEM, "yes | no | -", "MOUNTED", "%7s" }, 99 { "origin", prop_type_string, 0, NULL, prop_readonly, 100 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<snapshot>", "ORIGIN", 101 "%-20s" }, 102 { "quota", prop_type_number, 0, NULL, prop_default, 103 ZFS_TYPE_FILESYSTEM, "<size> | none", "QUOTA", "%5s" }, 104 { "reservation", prop_type_number, 0, NULL, prop_default, 105 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 106 "<size> | none", "RESERV", "%6s" }, 107 { "volsize", prop_type_number, 0, NULL, prop_default, 108 ZFS_TYPE_VOLUME, "<size>", "VOLSIZE", "%7s" }, 109 { "volblocksize", prop_type_number, 8192, NULL, prop_readonly, 110 ZFS_TYPE_VOLUME, "512 to 128k, power of 2", "VOLBLOCK", "%8s" }, 111 { "recordsize", prop_type_number, SPA_MAXBLOCKSIZE, NULL, 112 prop_inherit, 113 ZFS_TYPE_FILESYSTEM, 114 "512 to 128k, power of 2", "RECSIZE", "%7s" }, 115 { "mountpoint", prop_type_string, 0, "/", prop_inherit, 116 ZFS_TYPE_FILESYSTEM, 117 "<path> | legacy | none", "MOUNTPOINT", "%-20s" }, 118 { "sharenfs", prop_type_string, 0, "off", prop_inherit, 119 ZFS_TYPE_FILESYSTEM, 120 "on | off | share(1M) options", "SHARENFS", "%-15s" }, 121 { "checksum", prop_type_index, ZIO_CHECKSUM_DEFAULT, "on", 122 prop_inherit, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 123 "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM", "%10s" }, 124 { "compression", prop_type_index, ZIO_COMPRESS_DEFAULT, "off", 125 prop_inherit, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 126 "on | off | lzjb", "COMPRESS", "%8s" }, 127 { "atime", prop_type_boolean, 1, NULL, prop_inherit, 128 ZFS_TYPE_FILESYSTEM, 129 "on | off", "ATIME", "%5s" }, 130 { "devices", prop_type_boolean, 1, NULL, prop_inherit, 131 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, 132 "on | off", "DEVICES", "%7s" }, 133 { "exec", prop_type_boolean, 1, NULL, prop_inherit, 134 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, 135 "on | off", "EXEC", "%4s" }, 136 { "setuid", prop_type_boolean, 1, NULL, prop_inherit, 137 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "SETUID", 138 "%6s" }, 139 { "readonly", prop_type_boolean, 0, NULL, prop_inherit, 140 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, 141 "on | off", "RDONLY", "%6s" }, 142 { "zoned", prop_type_boolean, 0, NULL, prop_inherit, 143 ZFS_TYPE_FILESYSTEM, 144 "on | off", "ZONED", "%5s" }, 145 { "snapdir", prop_type_index, ZFS_SNAPDIR_HIDDEN, "hidden", 146 prop_inherit, 147 ZFS_TYPE_FILESYSTEM, 148 "hidden | visible", "SNAPDIR", "%7s" }, 149 { "aclmode", prop_type_index, GROUPMASK, "groupmask", prop_inherit, 150 ZFS_TYPE_FILESYSTEM, 151 "discard | groupmask | passthrough", "ACLMODE", "%11s" }, 152 { "aclinherit", prop_type_index, SECURE, "secure", prop_inherit, 153 ZFS_TYPE_FILESYSTEM, 154 "discard | noallow | secure | passthrough", "ACLINHERIT", "%11s" }, 155 { "createtxg", prop_type_number, 0, NULL, prop_readonly, 156 ZFS_TYPE_ANY, NULL, NULL, NULL}, 157 { "name", prop_type_string, 0, NULL, prop_readonly, 158 ZFS_TYPE_ANY, 159 NULL, "NAME", "%-20s" }, 160 }; 161 162 zfs_proptype_t 163 zfs_prop_get_type(zfs_prop_t prop) 164 { 165 return (zfs_prop_table[prop].pd_proptype); 166 } 167 168 static int 169 propname_match(const char *p, int prop, size_t len) 170 { 171 const char *propname = zfs_prop_table[prop].pd_name; 172 #ifndef _KERNEL 173 const char *colname = zfs_prop_table[prop].pd_colname; 174 int c; 175 #endif 176 177 #ifndef _KERNEL 178 if (colname == NULL) 179 return (0); 180 #endif 181 182 if (len == strlen(propname) && 183 strncmp(p, propname, len) == 0) 184 return (1); 185 186 #ifndef _KERNEL 187 if (len != strlen(colname)) 188 return (0); 189 190 for (c = 0; c < len; c++) 191 if (p[c] != tolower(colname[c])) 192 break; 193 194 return (colname[c] == '\0'); 195 #else 196 return (0); 197 #endif 198 } 199 200 201 /* 202 * Given a property name, returns the corresponding property ID. 203 */ 204 zfs_prop_t 205 zfs_name_to_prop(const char *propname) 206 { 207 int i; 208 209 for (i = 0; i < ZFS_NPROP_ALL; i++) { 210 if (propname_match(propname, i, strlen(propname))) 211 return (i); 212 } 213 214 return (ZFS_PROP_INVAL); 215 } 216 217 /* 218 * Return the default value for the given property. 219 */ 220 const char * 221 zfs_prop_default_string(zfs_prop_t prop) 222 { 223 return (zfs_prop_table[prop].pd_strdefault); 224 } 225 226 uint64_t 227 zfs_prop_default_numeric(zfs_prop_t prop) 228 { 229 return (zfs_prop_table[prop].pd_numdefault); 230 } 231 232 /* 233 * Returns TRUE if the property is readonly. 234 */ 235 int 236 zfs_prop_readonly(zfs_prop_t prop) 237 { 238 return (zfs_prop_table[prop].pd_attr == prop_readonly); 239 } 240 241 #ifndef _KERNEL 242 /* 243 * Given a property ID, returns the corresponding name. 244 */ 245 const char * 246 zfs_prop_to_name(zfs_prop_t prop) 247 { 248 return (zfs_prop_table[prop].pd_name); 249 } 250 251 /* 252 * Returns TRUE if the property is inheritable. 253 */ 254 int 255 zfs_prop_inheritable(zfs_prop_t prop) 256 { 257 return (zfs_prop_table[prop].pd_attr == prop_inherit); 258 } 259 260 /* 261 * Returns TRUE if the property applies to the given dataset types. 262 */ 263 int 264 zfs_prop_valid_for_type(zfs_prop_t prop, int types) 265 { 266 return ((zfs_prop_table[prop].pd_types & types) != 0); 267 } 268 269 /* 270 * Returns a string describing the set of acceptable values for the given 271 * property, or NULL if it cannot be set. 272 */ 273 const char * 274 zfs_prop_values(zfs_prop_t prop) 275 { 276 return (zfs_prop_table[prop].pd_values); 277 } 278 279 /* 280 * Returns TRUE if this property is a string type. Note that index types 281 * (compression, checksum) are treated as strings in userland, even though they 282 * are stored numerically on disk. 283 */ 284 int 285 zfs_prop_is_string(zfs_prop_t prop) 286 { 287 return (zfs_prop_table[prop].pd_proptype == prop_type_string || 288 zfs_prop_table[prop].pd_proptype == prop_type_index); 289 } 290 291 /* 292 * Returns the column header for the given property. Used only in 293 * 'zfs list -o', but centralized here with the other property information. 294 */ 295 const char * 296 zfs_prop_column_name(zfs_prop_t prop) 297 { 298 return (zfs_prop_table[prop].pd_colname); 299 } 300 301 /* 302 * Returns the column formatting for the given property. Used only in 303 * 'zfs list -o', but centralized here with the other property information. 304 */ 305 const char * 306 zfs_prop_column_format(zfs_prop_t prop) 307 { 308 return (zfs_prop_table[prop].pd_colfmt); 309 } 310 311 /* 312 * Given a comma-separated list of fields, fills in the specified array with a 313 * list of properties. The keyword "all" can be used to specify all properties. 314 * The 'count' parameter returns the number of matching properties placed into 315 * the list. The 'props' parameter must point to an array of at least 316 * ZFS_NPROP_ALL elements. 317 */ 318 int 319 zfs_get_proplist(char *fields, zfs_prop_t *props, int max, 320 int *count, char **badopt) 321 { 322 int i; 323 size_t len; 324 char *s, *p; 325 326 *count = 0; 327 328 /* 329 * Check for the special value "all", which indicates all properties 330 * should be displayed. 331 */ 332 if (strcmp(fields, "all") == 0) { 333 if (max < ZFS_NPROP_VISIBLE) 334 return (EOVERFLOW); 335 336 for (i = 0; i < ZFS_NPROP_VISIBLE; i++) 337 props[i] = i; 338 *count = ZFS_NPROP_VISIBLE; 339 return (0); 340 } 341 342 /* 343 * It would be nice to use getsubopt() here, but the inclusion of column 344 * aliases makes this more effort than it's worth. 345 */ 346 s = fields; 347 while (*s != '\0') { 348 if ((p = strchr(s, ',')) == NULL) { 349 len = strlen(s); 350 p = s + len; 351 } else { 352 len = p - s; 353 } 354 355 /* 356 * Check for empty options. 357 */ 358 if (len == 0) { 359 *badopt = ""; 360 return (EINVAL); 361 } 362 363 /* 364 * Check all regular property names. 365 */ 366 for (i = 0; i < ZFS_NPROP_ALL; i++) { 367 if (propname_match(s, i, len)) 368 break; 369 } 370 371 /* 372 * If no column is specified, then return failure, setting 373 * 'badopt' to point to the invalid option. 374 */ 375 if (i == ZFS_NPROP_ALL) { 376 s[len] = '\0'; 377 *badopt = s; 378 return (EINVAL); 379 } 380 381 /* 382 * If the user specified too many options (by using the same one 383 * multiple times). return an error with 'badopt' set to NULL to 384 * indicate this condition. 385 */ 386 if (*count == max) 387 return (EOVERFLOW); 388 389 props[*count] = i; 390 *count += 1; 391 392 s = p; 393 if (*s == ',') 394 s++; 395 } 396 397 /* 398 * If no fields were specified, return an error. 399 */ 400 if (*count == 0) { 401 *badopt = ""; 402 return (EINVAL); 403 } 404 405 return (0); 406 } 407 408 #endif 409