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