]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / cddl / contrib / opensolaris / common / zfs / zfs_prop.c
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 /*
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         boolean_t       pd_rightalign;
81         boolean_t       pd_visible;
82 } prop_desc_t;
83
84 static prop_desc_t zfs_prop_table[] = {
85         { "type",       prop_type_string,       0,      NULL,   prop_readonly,
86             ZFS_TYPE_ANY, "filesystem | volume | snapshot", "TYPE", B_TRUE,
87             B_TRUE },
88         { "creation",   prop_type_number,       0,      NULL,   prop_readonly,
89             ZFS_TYPE_ANY, "<date>", "CREATION", B_FALSE, B_TRUE },
90         { "used",       prop_type_number,       0,      NULL,   prop_readonly,
91             ZFS_TYPE_ANY, "<size>",     "USED", B_TRUE, B_TRUE },
92         { "available",  prop_type_number,       0,      NULL,   prop_readonly,
93             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>", "AVAIL", B_TRUE,
94             B_TRUE },
95         { "referenced", prop_type_number,       0,      NULL,   prop_readonly,
96             ZFS_TYPE_ANY,
97             "<size>", "REFER", B_TRUE, B_TRUE },
98         { "compressratio", prop_type_number,    0,      NULL,   prop_readonly,
99             ZFS_TYPE_ANY, "<1.00x or higher if compressed>", "RATIO", B_TRUE,
100             B_TRUE },
101         { "mounted",    prop_type_boolean,      0,      NULL,   prop_readonly,
102             ZFS_TYPE_FILESYSTEM, "yes | no | -", "MOUNTED", B_TRUE, B_TRUE },
103         { "origin",     prop_type_string,       0,      NULL,   prop_readonly,
104             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<snapshot>", "ORIGIN",
105             B_FALSE, B_TRUE },
106         { "quota",      prop_type_number,       0,      NULL,   prop_default,
107             ZFS_TYPE_FILESYSTEM, "<size> | none", "QUOTA", B_TRUE, B_TRUE },
108         { "reservation", prop_type_number,      0,      NULL,   prop_default,
109             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
110             "<size> | none", "RESERV", B_TRUE, B_TRUE },
111         { "volsize",    prop_type_number,       0,      NULL,   prop_default,
112             ZFS_TYPE_VOLUME, "<size>", "VOLSIZE", B_TRUE, B_TRUE },
113         { "volblocksize", prop_type_number,     8192,   NULL,   prop_readonly,
114             ZFS_TYPE_VOLUME, "512 to 128k, power of 2", "VOLBLOCK", B_TRUE,
115             B_TRUE },
116         { "recordsize", prop_type_number,       SPA_MAXBLOCKSIZE,       NULL,
117             prop_inherit,
118             ZFS_TYPE_FILESYSTEM,
119             "512 to 128k, power of 2", "RECSIZE", B_TRUE, B_TRUE },
120         { "mountpoint", prop_type_string,       0,      "/",    prop_inherit,
121             ZFS_TYPE_FILESYSTEM,
122             "<path> | legacy | none", "MOUNTPOINT", B_FALSE, B_TRUE },
123         { "sharenfs",   prop_type_string,       0,      "off",  prop_inherit,
124             ZFS_TYPE_FILESYSTEM,
125             "on | off | exports(5) options", "SHARENFS", B_FALSE, B_TRUE },
126         { "checksum",   prop_type_index,        ZIO_CHECKSUM_DEFAULT,   "on",
127             prop_inherit,       ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
128             "on | off | fletcher2 | fletcher4 | sha256", "CHECKSUM", B_TRUE,
129             B_TRUE },
130         { "compression", prop_type_index,       ZIO_COMPRESS_DEFAULT,   "off",
131             prop_inherit,       ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
132             "on | off | lzjb | gzip | gzip-[1-9]", "COMPRESS", B_TRUE, B_TRUE },
133         { "atime",      prop_type_boolean,      1,      NULL,   prop_inherit,
134             ZFS_TYPE_FILESYSTEM,
135             "on | off", "ATIME", B_TRUE, B_TRUE },
136         { "devices",    prop_type_boolean,      1,      NULL,   prop_inherit,
137             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT,
138             "on | off", "DEVICES", B_TRUE, B_TRUE },
139         { "exec",       prop_type_boolean,      1,      NULL,   prop_inherit,
140             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT,
141             "on | off", "EXEC", B_TRUE, B_TRUE },
142         { "setuid",     prop_type_boolean,      1,      NULL,   prop_inherit,
143             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off", "SETUID",
144             B_TRUE, B_TRUE },
145         { "readonly",   prop_type_boolean,      0,      NULL,   prop_inherit,
146             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
147             "on | off", "RDONLY", B_TRUE, B_TRUE },
148         { "jailed",     prop_type_boolean,      0,      NULL,   prop_inherit,
149             ZFS_TYPE_FILESYSTEM,
150             "on | off", "JAILED", B_TRUE, B_TRUE },
151         { "snapdir",    prop_type_index,        ZFS_SNAPDIR_HIDDEN, "hidden",
152             prop_inherit,
153             ZFS_TYPE_FILESYSTEM,
154             "hidden | visible", "SNAPDIR", B_TRUE, B_TRUE },
155         { "aclmode", prop_type_index,   ZFS_ACL_GROUPMASK, "groupmask",
156             prop_inherit, ZFS_TYPE_FILESYSTEM,
157             "discard | groupmask | passthrough", "ACLMODE", B_TRUE, B_TRUE },
158         { "aclinherit", prop_type_index,        ZFS_ACL_SECURE, "secure",
159             prop_inherit, ZFS_TYPE_FILESYSTEM,
160             "discard | noallow | secure | passthrough", "ACLINHERIT", B_TRUE,
161             B_TRUE },
162         { "createtxg",  prop_type_number,       0,      NULL,   prop_readonly,
163             ZFS_TYPE_ANY, NULL, NULL, B_FALSE, B_FALSE },
164         { "name",       prop_type_string,       0,      NULL,   prop_readonly,
165             ZFS_TYPE_ANY, NULL, "NAME", B_FALSE, B_FALSE },
166         { "canmount",   prop_type_boolean,      1,      NULL,   prop_default,
167             ZFS_TYPE_FILESYSTEM,
168             "on | off", "CANMOUNT", B_TRUE, B_TRUE },
169         { "shareiscsi", prop_type_string,       0,      "off",  prop_inherit,
170             ZFS_TYPE_ANY,
171             "on | off | type=<type>", "SHAREISCSI", B_FALSE, B_TRUE },
172         { "iscsioptions", prop_type_string,     0,      NULL,   prop_inherit,
173             ZFS_TYPE_VOLUME, NULL, "ISCSIOPTIONS", B_FALSE, B_FALSE },
174         { "xattr",      prop_type_boolean,      1,      NULL,   prop_inherit,
175             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT,
176             "on | off", "XATTR", B_TRUE, B_TRUE },
177         { "numclones", prop_type_number,        0,      NULL,   prop_readonly,
178             ZFS_TYPE_SNAPSHOT, NULL, NULL, B_FALSE, B_FALSE },
179         { "copies",     prop_type_index,        1,      "1",    prop_inherit,
180             ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
181             "1 | 2 | 3", "COPIES", B_TRUE, B_TRUE },
182         { "bootfs", prop_type_string,   0,      NULL,   prop_default,
183             ZFS_TYPE_POOL, "<filesystem>", "BOOTFS", B_FALSE, B_TRUE },
184 };
185
186 #define ZFS_PROP_COUNT  ((sizeof (zfs_prop_table))/(sizeof (prop_desc_t)))
187
188 /*
189  * Returns TRUE if the property applies to the given dataset types.
190  */
191 int
192 zfs_prop_valid_for_type(zfs_prop_t prop, int types)
193 {
194         return ((zfs_prop_table[prop].pd_types & types) != 0);
195 }
196
197 /*
198  * Determine if the specified property is visible or not.
199  */
200 boolean_t
201 zfs_prop_is_visible(zfs_prop_t prop)
202 {
203         if (prop < 0)
204                 return (B_FALSE);
205
206         return (zfs_prop_table[prop].pd_visible);
207 }
208
209 /*
210  * Iterate over all properties, calling back into the specified function
211  * for each property. We will continue to iterate until we either
212  * reach the end or the callback function something other than
213  * ZFS_PROP_CONT.
214  */
215 zfs_prop_t
216 zfs_prop_iter_common(zfs_prop_f func, void *cb, zfs_type_t type,
217     boolean_t show_all)
218 {
219         int i;
220
221         for (i = 0; i < ZFS_PROP_COUNT; i++) {
222                 if (zfs_prop_valid_for_type(i, type) &&
223                     (zfs_prop_is_visible(i) || show_all)) {
224                         if (func(i, cb) != ZFS_PROP_CONT)
225                                 return (i);
226                 }
227         }
228         return (ZFS_PROP_CONT);
229 }
230
231 zfs_prop_t
232 zfs_prop_iter(zfs_prop_f func, void *cb, boolean_t show_all)
233 {
234         return (zfs_prop_iter_common(func, cb, ZFS_TYPE_ANY, show_all));
235 }
236
237 zpool_prop_t
238 zpool_prop_iter(zpool_prop_f func, void *cb, boolean_t show_all)
239 {
240         return (zfs_prop_iter_common(func, cb, ZFS_TYPE_POOL, show_all));
241 }
242
243 zfs_proptype_t
244 zfs_prop_get_type(zfs_prop_t prop)
245 {
246         return (zfs_prop_table[prop].pd_proptype);
247 }
248
249 static boolean_t
250 propname_match(const char *p, zfs_prop_t prop, size_t len)
251 {
252         const char *propname = zfs_prop_table[prop].pd_name;
253 #ifndef _KERNEL
254         const char *colname = zfs_prop_table[prop].pd_colname;
255         int c;
256 #endif
257
258 #ifndef _KERNEL
259         if (colname == NULL)
260                 return (B_FALSE);
261 #endif
262
263         if (len == strlen(propname) &&
264             strncmp(p, propname, len) == 0)
265                 return (B_TRUE);
266
267 #ifndef _KERNEL
268         if (len != strlen(colname))
269                 return (B_FALSE);
270
271         for (c = 0; c < len; c++)
272                 if (p[c] != tolower(colname[c]))
273                         break;
274
275         return (colname[c] == '\0');
276 #else
277         return (B_FALSE);
278 #endif
279 }
280
281 zfs_prop_t
282 zfs_name_to_prop_cb(zfs_prop_t prop, void *cb_data)
283 {
284         const char *propname = cb_data;
285
286         if (propname_match(propname, prop, strlen(propname)))
287                 return (prop);
288
289         return (ZFS_PROP_CONT);
290 }
291
292 /*
293  * Given a property name and its type, returns the corresponding property ID.
294  */
295 zfs_prop_t
296 zfs_name_to_prop_common(const char *propname, zfs_type_t type)
297 {
298         zfs_prop_t prop;
299
300         prop = zfs_prop_iter_common(zfs_name_to_prop_cb, (void *)propname,
301             type, B_TRUE);
302         return (prop == ZFS_PROP_CONT ? ZFS_PROP_INVAL : prop);
303 }
304
305 /*
306  * Given a zfs dataset property name, returns the corresponding property ID.
307  */
308 zfs_prop_t
309 zfs_name_to_prop(const char *propname)
310 {
311         return (zfs_name_to_prop_common(propname, ZFS_TYPE_ANY));
312 }
313
314 /*
315  * Given a pool property name, returns the corresponding property ID.
316  */
317 zpool_prop_t
318 zpool_name_to_prop(const char *propname)
319 {
320         return (zfs_name_to_prop_common(propname, ZFS_TYPE_POOL));
321 }
322
323 /*
324  * For user property names, we allow all lowercase alphanumeric characters, plus
325  * a few useful punctuation characters.
326  */
327 static int
328 valid_char(char c)
329 {
330         return ((c >= 'a' && c <= 'z') ||
331             (c >= '0' && c <= '9') ||
332             c == '-' || c == '_' || c == '.' || c == ':');
333 }
334
335 /*
336  * Returns true if this is a valid user-defined property (one with a ':').
337  */
338 boolean_t
339 zfs_prop_user(const char *name)
340 {
341         int i;
342         char c;
343         boolean_t foundsep = B_FALSE;
344
345         for (i = 0; i < strlen(name); i++) {
346                 c = name[i];
347                 if (!valid_char(c))
348                         return (B_FALSE);
349                 if (c == ':')
350                         foundsep = B_TRUE;
351         }
352
353         if (!foundsep)
354                 return (B_FALSE);
355
356         return (B_TRUE);
357 }
358
359 /*
360  * Return the default value for the given property.
361  */
362 const char *
363 zfs_prop_default_string(zfs_prop_t prop)
364 {
365         return (zfs_prop_table[prop].pd_strdefault);
366 }
367
368 uint64_t
369 zfs_prop_default_numeric(zfs_prop_t prop)
370 {
371         return (zfs_prop_table[prop].pd_numdefault);
372 }
373
374 /*
375  * Returns TRUE if the property is readonly.
376  */
377 int
378 zfs_prop_readonly(zfs_prop_t prop)
379 {
380         return (zfs_prop_table[prop].pd_attr == prop_readonly);
381 }
382
383 /*
384  * Given a dataset property ID, returns the corresponding name.
385  * Assuming the zfs dataset propety ID is valid.
386  */
387 const char *
388 zfs_prop_to_name(zfs_prop_t prop)
389 {
390         return (zfs_prop_table[prop].pd_name);
391 }
392
393 /*
394  * Given a pool property ID, returns the corresponding name.
395  * Assuming the pool propety ID is valid.
396  */
397 const char *
398 zpool_prop_to_name(zpool_prop_t prop)
399 {
400         return (zfs_prop_table[prop].pd_name);
401 }
402
403 /*
404  * Returns TRUE if the property is inheritable.
405  */
406 int
407 zfs_prop_inheritable(zfs_prop_t prop)
408 {
409         return (zfs_prop_table[prop].pd_attr == prop_inherit);
410 }
411
412 typedef struct zfs_index {
413         const char *name;
414         uint64_t index;
415 } zfs_index_t;
416
417 static zfs_index_t checksum_table[] = {
418         { "on",         ZIO_CHECKSUM_ON },
419         { "off",        ZIO_CHECKSUM_OFF },
420         { "fletcher2",  ZIO_CHECKSUM_FLETCHER_2 },
421         { "fletcher4",  ZIO_CHECKSUM_FLETCHER_4 },
422         { "sha256",     ZIO_CHECKSUM_SHA256 },
423         { NULL }
424 };
425
426 static zfs_index_t compress_table[] = {
427         { "on",         ZIO_COMPRESS_ON },
428         { "off",        ZIO_COMPRESS_OFF },
429         { "lzjb",       ZIO_COMPRESS_LZJB },
430         { "gzip",       ZIO_COMPRESS_GZIP_6 },  /* the default gzip level */
431         { "gzip-1",     ZIO_COMPRESS_GZIP_1 },
432         { "gzip-2",     ZIO_COMPRESS_GZIP_2 },
433         { "gzip-3",     ZIO_COMPRESS_GZIP_3 },
434         { "gzip-4",     ZIO_COMPRESS_GZIP_4 },
435         { "gzip-5",     ZIO_COMPRESS_GZIP_5 },
436         { "gzip-6",     ZIO_COMPRESS_GZIP_6 },
437         { "gzip-7",     ZIO_COMPRESS_GZIP_7 },
438         { "gzip-8",     ZIO_COMPRESS_GZIP_8 },
439         { "gzip-9",     ZIO_COMPRESS_GZIP_9 },
440         { NULL }
441 };
442
443 static zfs_index_t snapdir_table[] = {
444         { "hidden",     ZFS_SNAPDIR_HIDDEN },
445         { "visible",    ZFS_SNAPDIR_VISIBLE },
446         { NULL }
447 };
448
449 static zfs_index_t acl_mode_table[] = {
450         { "discard",    ZFS_ACL_DISCARD },
451         { "groupmask",  ZFS_ACL_GROUPMASK },
452         { "passthrough", ZFS_ACL_PASSTHROUGH },
453         { NULL }
454 };
455
456 static zfs_index_t acl_inherit_table[] = {
457         { "discard",    ZFS_ACL_DISCARD },
458         { "noallow",    ZFS_ACL_NOALLOW },
459         { "secure",     ZFS_ACL_SECURE },
460         { "passthrough", ZFS_ACL_PASSTHROUGH },
461         { NULL }
462 };
463
464 static zfs_index_t copies_table[] = {
465         { "1",  1 },
466         { "2",  2 },
467         { "3",  3 },
468         { NULL }
469 };
470
471 static zfs_index_t *
472 zfs_prop_index_table(zfs_prop_t prop)
473 {
474         switch (prop) {
475         case ZFS_PROP_CHECKSUM:
476                 return (checksum_table);
477         case ZFS_PROP_COMPRESSION:
478                 return (compress_table);
479         case ZFS_PROP_SNAPDIR:
480                 return (snapdir_table);
481         case ZFS_PROP_ACLMODE:
482                 return (acl_mode_table);
483         case ZFS_PROP_ACLINHERIT:
484                 return (acl_inherit_table);
485         case ZFS_PROP_COPIES:
486                 return (copies_table);
487         default:
488                 return (NULL);
489         }
490 }
491
492
493 /*
494  * Tables of index types, plus functions to convert between the user view
495  * (strings) and internal representation (uint64_t).
496  */
497 int
498 zfs_prop_string_to_index(zfs_prop_t prop, const char *string, uint64_t *index)
499 {
500         zfs_index_t *table;
501         int i;
502
503         if ((table = zfs_prop_index_table(prop)) == NULL)
504                 return (-1);
505
506         for (i = 0; table[i].name != NULL; i++) {
507                 if (strcmp(string, table[i].name) == 0) {
508                         *index = table[i].index;
509                         return (0);
510                 }
511         }
512
513         return (-1);
514 }
515
516 int
517 zfs_prop_index_to_string(zfs_prop_t prop, uint64_t index, const char **string)
518 {
519         zfs_index_t *table;
520         int i;
521
522         if ((table = zfs_prop_index_table(prop)) == NULL)
523                 return (-1);
524
525         for (i = 0; table[i].name != NULL; i++) {
526                 if (table[i].index == index) {
527                         *string = table[i].name;
528                         return (0);
529                 }
530         }
531
532         return (-1);
533 }
534
535 #ifndef _KERNEL
536
537 /*
538  * Returns a string describing the set of acceptable values for the given
539  * zfs property, or NULL if it cannot be set.
540  */
541 const char *
542 zfs_prop_values(zfs_prop_t prop)
543 {
544         if (zfs_prop_table[prop].pd_types == ZFS_TYPE_POOL)
545                 return (NULL);
546
547         return (zfs_prop_table[prop].pd_values);
548 }
549
550 /*
551  * Returns a string describing the set of acceptable values for the given
552  * zpool property, or NULL if it cannot be set.
553  */
554 const char *
555 zpool_prop_values(zfs_prop_t prop)
556 {
557         if (zfs_prop_table[prop].pd_types != ZFS_TYPE_POOL)
558                 return (NULL);
559
560         return (zfs_prop_table[prop].pd_values);
561 }
562
563 /*
564  * Returns TRUE if this property is a string type.  Note that index types
565  * (compression, checksum) are treated as strings in userland, even though they
566  * are stored numerically on disk.
567  */
568 int
569 zfs_prop_is_string(zfs_prop_t prop)
570 {
571         return (zfs_prop_table[prop].pd_proptype == prop_type_string ||
572             zfs_prop_table[prop].pd_proptype == prop_type_index);
573 }
574
575 /*
576  * Returns the column header for the given property.  Used only in
577  * 'zfs list -o', but centralized here with the other property information.
578  */
579 const char *
580 zfs_prop_column_name(zfs_prop_t prop)
581 {
582         return (zfs_prop_table[prop].pd_colname);
583 }
584
585 /*
586  * Returns whether the given property should be displayed right-justified for
587  * 'zfs list'.
588  */
589 boolean_t
590 zfs_prop_align_right(zfs_prop_t prop)
591 {
592         return (zfs_prop_table[prop].pd_rightalign);
593 }
594
595 /*
596  * Determines the minimum width for the column, and indicates whether it's fixed
597  * or not.  Only string columns are non-fixed.
598  */
599 size_t
600 zfs_prop_width(zfs_prop_t prop, boolean_t *fixed)
601 {
602         prop_desc_t *pd = &zfs_prop_table[prop];
603         zfs_index_t *idx;
604         size_t ret;
605         int i;
606
607         *fixed = B_TRUE;
608
609         /*
610          * Start with the width of the column name.
611          */
612         ret = strlen(pd->pd_colname);
613
614         /*
615          * For fixed-width values, make sure the width is large enough to hold
616          * any possible value.
617          */
618         switch (pd->pd_proptype) {
619         case prop_type_number:
620                 /*
621                  * The maximum length of a human-readable number is 5 characters
622                  * ("20.4M", for example).
623                  */
624                 if (ret < 5)
625                         ret = 5;
626                 /*
627                  * 'creation' is handled specially because it's a number
628                  * internally, but displayed as a date string.
629                  */
630                 if (prop == ZFS_PROP_CREATION)
631                         *fixed = B_FALSE;
632                 break;
633         case prop_type_boolean:
634                 /*
635                  * The maximum length of a boolean value is 3 characters, for
636                  * "off".
637                  */
638                 if (ret < 3)
639                         ret = 3;
640                 break;
641         case prop_type_index:
642                 idx = zfs_prop_index_table(prop);
643                 for (i = 0; idx[i].name != NULL; i++) {
644                         if (strlen(idx[i].name) > ret)
645                                 ret = strlen(idx[i].name);
646                 }
647                 break;
648
649         case prop_type_string:
650                 *fixed = B_FALSE;
651                 break;
652         }
653
654         return (ret);
655 }
656
657 #endif