xref: /illumos-gate/usr/src/common/zfs/zfs_prop.c (revision 91ebeef555ce7f899b6270a3c2df47b51f7ad59a)
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