| 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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. | 
| 23 |  * Copyright (c) 2011, 2014 by Delphix. All rights reserved. | 
| 24 |  * Copyright (c) 2013 by Saso Kiselkov. All rights reserved. | 
| 25 |  * Copyright (c) 2013, Joyent, Inc. All rights reserved. | 
| 26 |  * Copyright (c) 2014 Integros [integros.com] | 
| 27 |  */ | 
| 28 |  | 
| 29 | /* Portions Copyright 2010 Robert Milkowski */ | 
| 30 |  | 
| 31 | #include <sys/zio.h> | 
| 32 | #include <sys/spa.h> | 
| 33 | #include <sys/u8_textprep.h> | 
| 34 | #include <sys/zfs_acl.h> | 
| 35 | #include <sys/zfs_ioctl.h> | 
| 36 | #include <sys/zfs_znode.h> | 
| 37 |  | 
| 38 | #include "zfs_prop.h" | 
| 39 | #include "zfs_deleg.h" | 
| 40 |  | 
| 41 | #if defined(_KERNEL) | 
| 42 | #include <sys/systm.h> | 
| 43 | #else | 
| 44 | #include <stdlib.h> | 
| 45 | #include <string.h> | 
| 46 | #include <ctype.h> | 
| 47 | #endif | 
| 48 |  | 
| 49 | static zprop_desc_t zfs_prop_table[ZFS_NUM_PROPS]; | 
| 50 |  | 
| 51 | /* Note this is indexed by zfs_userquota_prop_t, keep the order the same */ | 
| 52 | const char *zfs_userquota_prop_prefixes[] = { | 
| 53 | 	"userused@" , | 
| 54 | 	"userquota@" , | 
| 55 | 	"groupused@" , | 
| 56 | 	"groupquota@"  | 
| 57 | }; | 
| 58 |  | 
| 59 | zprop_desc_t * | 
| 60 | zfs_prop_get_table(void) | 
| 61 | { | 
| 62 | 	return (zfs_prop_table); | 
| 63 | } | 
| 64 |  | 
| 65 | void | 
| 66 | zfs_prop_init(void) | 
| 67 | { | 
| 68 | 	static zprop_index_t checksum_table[] = { | 
| 69 | 		{ "on" ,		ZIO_CHECKSUM_ON }, | 
| 70 | 		{ "off" ,	ZIO_CHECKSUM_OFF }, | 
| 71 | 		{ "fletcher2" ,	ZIO_CHECKSUM_FLETCHER_2 }, | 
| 72 | 		{ "fletcher4" ,	ZIO_CHECKSUM_FLETCHER_4 }, | 
| 73 | 		{ "sha256" ,	ZIO_CHECKSUM_SHA256 }, | 
| 74 | 		{ "noparity" ,	ZIO_CHECKSUM_NOPARITY }, | 
| 75 | #ifndef __NetBSD__ | 
| 76 | 		{ "sha512" ,	ZIO_CHECKSUM_SHA512 }, | 
| 77 | 		{ "skein" ,	ZIO_CHECKSUM_SKEIN }, | 
| 78 | #endif | 
| 79 | #ifdef illumos | 
| 80 | 		{ "edonr" ,	ZIO_CHECKSUM_EDONR }, | 
| 81 | #endif | 
| 82 | 		{ NULL } | 
| 83 | 	}; | 
| 84 |  | 
| 85 | 	static zprop_index_t dedup_table[] = { | 
| 86 | 		{ "on" ,		ZIO_CHECKSUM_ON }, | 
| 87 | 		{ "off" ,	ZIO_CHECKSUM_OFF }, | 
| 88 | 		{ "verify" ,	ZIO_CHECKSUM_ON | ZIO_CHECKSUM_VERIFY }, | 
| 89 | 		{ "sha256" ,	ZIO_CHECKSUM_SHA256 }, | 
| 90 | 		{ "sha256,verify" , | 
| 91 | 				ZIO_CHECKSUM_SHA256 | ZIO_CHECKSUM_VERIFY }, | 
| 92 | #ifndef __NetBSD__ | 
| 93 | 		{ "sha512" ,	ZIO_CHECKSUM_SHA512 }, | 
| 94 | 		{ "sha512,verify" , | 
| 95 | 				ZIO_CHECKSUM_SHA512 | ZIO_CHECKSUM_VERIFY }, | 
| 96 | 		{ "skein" ,	ZIO_CHECKSUM_SKEIN }, | 
| 97 | 		{ "skein,verify" , | 
| 98 | 				ZIO_CHECKSUM_SKEIN | ZIO_CHECKSUM_VERIFY }, | 
| 99 | #endif | 
| 100 | #ifdef illumos | 
| 101 | 		{ "edonr,verify" , | 
| 102 | 				ZIO_CHECKSUM_EDONR | ZIO_CHECKSUM_VERIFY }, | 
| 103 | #endif | 
| 104 | 		{ NULL } | 
| 105 | 	}; | 
| 106 |  | 
| 107 | 	static zprop_index_t compress_table[] = { | 
| 108 | 		{ "on" ,		ZIO_COMPRESS_ON }, | 
| 109 | 		{ "off" ,	ZIO_COMPRESS_OFF }, | 
| 110 | 		{ "lzjb" ,	ZIO_COMPRESS_LZJB }, | 
| 111 | 		{ "gzip" ,	ZIO_COMPRESS_GZIP_6 },	/* gzip default */ | 
| 112 | 		{ "gzip-1" ,	ZIO_COMPRESS_GZIP_1 }, | 
| 113 | 		{ "gzip-2" ,	ZIO_COMPRESS_GZIP_2 }, | 
| 114 | 		{ "gzip-3" ,	ZIO_COMPRESS_GZIP_3 }, | 
| 115 | 		{ "gzip-4" ,	ZIO_COMPRESS_GZIP_4 }, | 
| 116 | 		{ "gzip-5" ,	ZIO_COMPRESS_GZIP_5 }, | 
| 117 | 		{ "gzip-6" ,	ZIO_COMPRESS_GZIP_6 }, | 
| 118 | 		{ "gzip-7" ,	ZIO_COMPRESS_GZIP_7 }, | 
| 119 | 		{ "gzip-8" ,	ZIO_COMPRESS_GZIP_8 }, | 
| 120 | 		{ "gzip-9" ,	ZIO_COMPRESS_GZIP_9 }, | 
| 121 | 		{ "zle" ,	ZIO_COMPRESS_ZLE }, | 
| 122 | 		{ "lz4" ,	ZIO_COMPRESS_LZ4 }, | 
| 123 | 		{ NULL } | 
| 124 | 	}; | 
| 125 |  | 
| 126 | 	static zprop_index_t snapdir_table[] = { | 
| 127 | 		{ "hidden" ,	ZFS_SNAPDIR_HIDDEN }, | 
| 128 | 		{ "visible" ,	ZFS_SNAPDIR_VISIBLE }, | 
| 129 | 		{ NULL } | 
| 130 | 	}; | 
| 131 |  | 
| 132 | 	static zprop_index_t acl_mode_table[] = { | 
| 133 | 		{ "discard" ,	ZFS_ACL_DISCARD }, | 
| 134 | 		{ "groupmask" ,	ZFS_ACL_GROUPMASK }, | 
| 135 | 		{ "passthrough" , ZFS_ACL_PASSTHROUGH }, | 
| 136 | 		{ "restricted" , ZFS_ACL_RESTRICTED }, | 
| 137 | 		{ NULL } | 
| 138 | 	}; | 
| 139 |  | 
| 140 | 	static zprop_index_t acl_inherit_table[] = { | 
| 141 | 		{ "discard" ,	ZFS_ACL_DISCARD }, | 
| 142 | 		{ "noallow" ,	ZFS_ACL_NOALLOW }, | 
| 143 | 		{ "restricted" ,	ZFS_ACL_RESTRICTED }, | 
| 144 | 		{ "passthrough" , ZFS_ACL_PASSTHROUGH }, | 
| 145 | 		{ "secure" ,	ZFS_ACL_RESTRICTED }, /* bkwrd compatability */ | 
| 146 | 		{ "passthrough-x" , ZFS_ACL_PASSTHROUGH_X }, | 
| 147 | 		{ NULL } | 
| 148 | 	}; | 
| 149 |  | 
| 150 | 	static zprop_index_t case_table[] = { | 
| 151 | 		{ "sensitive" ,		ZFS_CASE_SENSITIVE }, | 
| 152 | 		{ "insensitive" ,	ZFS_CASE_INSENSITIVE }, | 
| 153 | 		{ "mixed" ,		ZFS_CASE_MIXED }, | 
| 154 | 		{ NULL } | 
| 155 | 	}; | 
| 156 |  | 
| 157 | 	static zprop_index_t copies_table[] = { | 
| 158 | 		{ "1" ,		1 }, | 
| 159 | 		{ "2" ,		2 }, | 
| 160 | 		{ "3" ,		3 }, | 
| 161 | 		{ NULL } | 
| 162 | 	}; | 
| 163 |  | 
| 164 | 	/* | 
| 165 | 	 * Use the unique flags we have to send to u8_strcmp() and/or | 
| 166 | 	 * u8_textprep() to represent the various normalization property | 
| 167 | 	 * values. | 
| 168 | 	 */ | 
| 169 | 	static zprop_index_t normalize_table[] = { | 
| 170 | 		{ "none" ,	0 }, | 
| 171 | 		{ "formD" ,	U8_TEXTPREP_NFD }, | 
| 172 | 		{ "formKC" ,	U8_TEXTPREP_NFKC }, | 
| 173 | 		{ "formC" ,	U8_TEXTPREP_NFC }, | 
| 174 | 		{ "formKD" ,	U8_TEXTPREP_NFKD }, | 
| 175 | 		{ NULL } | 
| 176 | 	}; | 
| 177 |  | 
| 178 | 	static zprop_index_t version_table[] = { | 
| 179 | 		{ "1" ,		1 }, | 
| 180 | 		{ "2" ,		2 }, | 
| 181 | 		{ "3" ,		3 }, | 
| 182 | 		{ "4" ,		4 }, | 
| 183 | 		{ "5" ,		5 }, | 
| 184 | 		{ "current" ,	ZPL_VERSION }, | 
| 185 | 		{ NULL } | 
| 186 | 	}; | 
| 187 |  | 
| 188 | 	static zprop_index_t boolean_table[] = { | 
| 189 | 		{ "off" ,	0 }, | 
| 190 | 		{ "on" ,		1 }, | 
| 191 | 		{ NULL } | 
| 192 | 	}; | 
| 193 |  | 
| 194 | 	static zprop_index_t logbias_table[] = { | 
| 195 | 		{ "latency" ,	ZFS_LOGBIAS_LATENCY }, | 
| 196 | 		{ "throughput" ,	ZFS_LOGBIAS_THROUGHPUT }, | 
| 197 | 		{ NULL } | 
| 198 | 	}; | 
| 199 |  | 
| 200 | 	static zprop_index_t canmount_table[] = { | 
| 201 | 		{ "off" ,	ZFS_CANMOUNT_OFF }, | 
| 202 | 		{ "on" ,		ZFS_CANMOUNT_ON }, | 
| 203 | 		{ "noauto" ,	ZFS_CANMOUNT_NOAUTO }, | 
| 204 | 		{ NULL } | 
| 205 | 	}; | 
| 206 |  | 
| 207 | 	static zprop_index_t cache_table[] = { | 
| 208 | 		{ "none" ,	ZFS_CACHE_NONE }, | 
| 209 | 		{ "metadata" ,	ZFS_CACHE_METADATA }, | 
| 210 | 		{ "all" ,	ZFS_CACHE_ALL }, | 
| 211 | 		{ NULL } | 
| 212 | 	}; | 
| 213 |  | 
| 214 | 	static zprop_index_t sync_table[] = { | 
| 215 | 		{ "standard" ,	ZFS_SYNC_STANDARD }, | 
| 216 | 		{ "always" ,	ZFS_SYNC_ALWAYS }, | 
| 217 | 		{ "disabled" ,	ZFS_SYNC_DISABLED }, | 
| 218 | 		{ NULL } | 
| 219 | 	}; | 
| 220 |  | 
| 221 | 	static zprop_index_t volmode_table[] = { | 
| 222 | 		{ "default" ,	ZFS_VOLMODE_DEFAULT }, | 
| 223 | 		{ "geom" ,	ZFS_VOLMODE_GEOM }, | 
| 224 | 		{ "dev" ,	ZFS_VOLMODE_DEV }, | 
| 225 | 		{ "none" ,	ZFS_VOLMODE_NONE }, | 
| 226 | 		{ NULL } | 
| 227 | 	}; | 
| 228 |  | 
| 229 | 	static zprop_index_t redundant_metadata_table[] = { | 
| 230 | 		{ "all" ,	ZFS_REDUNDANT_METADATA_ALL }, | 
| 231 | 		{ "most" ,	ZFS_REDUNDANT_METADATA_MOST }, | 
| 232 | 		{ NULL } | 
| 233 | 	}; | 
| 234 |  | 
| 235 | 	/* inherit index properties */ | 
| 236 | 	zprop_register_index(ZFS_PROP_REDUNDANT_METADATA, "redundant_metadata" , | 
| 237 | 	    ZFS_REDUNDANT_METADATA_ALL, | 
| 238 | 	    PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 239 | 	    "all | most" , "REDUND_MD" , | 
| 240 | 	    redundant_metadata_table); | 
| 241 | 	zprop_register_index(ZFS_PROP_SYNC, "sync" , ZFS_SYNC_STANDARD, | 
| 242 | 	    PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 243 | 	    "standard | always | disabled" , "SYNC" , | 
| 244 | 	    sync_table); | 
| 245 | 	zprop_register_index(ZFS_PROP_CHECKSUM, "checksum" , | 
| 246 | 	    ZIO_CHECKSUM_DEFAULT, PROP_INHERIT, ZFS_TYPE_FILESYSTEM | | 
| 247 | 	    ZFS_TYPE_VOLUME, | 
| 248 | 	    "on | off | fletcher2 | fletcher4 | sha256 | sha512 | "  | 
| 249 | 	    "skein | edonr" , "CHECKSUM" , checksum_table); | 
| 250 | 	zprop_register_index(ZFS_PROP_DEDUP, "dedup" , ZIO_CHECKSUM_OFF, | 
| 251 | 	    PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 252 | 	    "on | off | verify | sha256[,verify], sha512[,verify], "  | 
| 253 | 	    "skein[,verify], edonr,verify" , "DEDUP" , dedup_table); | 
| 254 | 	zprop_register_index(ZFS_PROP_COMPRESSION, "compression" , | 
| 255 | 	    ZIO_COMPRESS_DEFAULT, PROP_INHERIT, | 
| 256 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 257 | 	    "on | off | lzjb | gzip | gzip-[1-9] | zle | lz4" , | 
| 258 | 	    "COMPRESS" , compress_table); | 
| 259 | 	zprop_register_index(ZFS_PROP_SNAPDIR, "snapdir" , ZFS_SNAPDIR_HIDDEN, | 
| 260 | 	    PROP_INHERIT, ZFS_TYPE_FILESYSTEM, | 
| 261 | 	    "hidden | visible" , "SNAPDIR" , snapdir_table); | 
| 262 | 	zprop_register_index(ZFS_PROP_ACLMODE, "aclmode" , ZFS_ACL_DISCARD, | 
| 263 | 	    PROP_INHERIT, ZFS_TYPE_FILESYSTEM, | 
| 264 | 	    "discard | groupmask | passthrough | restricted" , "ACLMODE" , | 
| 265 | 	    acl_mode_table); | 
| 266 | 	zprop_register_index(ZFS_PROP_ACLINHERIT, "aclinherit" , | 
| 267 | 	    ZFS_ACL_RESTRICTED, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, | 
| 268 | 	    "discard | noallow | restricted | passthrough | passthrough-x" , | 
| 269 | 	    "ACLINHERIT" , acl_inherit_table); | 
| 270 | 	zprop_register_index(ZFS_PROP_COPIES, "copies" , 1, PROP_INHERIT, | 
| 271 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 272 | 	    "1 | 2 | 3" , "COPIES" , copies_table); | 
| 273 | 	zprop_register_index(ZFS_PROP_PRIMARYCACHE, "primarycache" , | 
| 274 | 	    ZFS_CACHE_ALL, PROP_INHERIT, | 
| 275 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME, | 
| 276 | 	    "all | none | metadata" , "PRIMARYCACHE" , cache_table); | 
| 277 | 	zprop_register_index(ZFS_PROP_SECONDARYCACHE, "secondarycache" , | 
| 278 | 	    ZFS_CACHE_ALL, PROP_INHERIT, | 
| 279 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME, | 
| 280 | 	    "all | none | metadata" , "SECONDARYCACHE" , cache_table); | 
| 281 | 	zprop_register_index(ZFS_PROP_LOGBIAS, "logbias" , ZFS_LOGBIAS_LATENCY, | 
| 282 | 	    PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 283 | 	    "latency | throughput" , "LOGBIAS" , logbias_table); | 
| 284 | 	zprop_register_index(ZFS_PROP_VOLMODE, "volmode" , | 
| 285 | 	    ZFS_VOLMODE_DEFAULT, PROP_INHERIT, | 
| 286 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT | ZFS_TYPE_VOLUME, | 
| 287 | 	    "default | geom | dev | none" , "VOLMODE" , volmode_table); | 
| 288 |  | 
| 289 | 	/* inherit index (boolean) properties */ | 
| 290 | 	zprop_register_index(ZFS_PROP_ATIME, "atime" , 1, PROP_INHERIT, | 
| 291 | 	    ZFS_TYPE_FILESYSTEM, "on | off" , "ATIME" , boolean_table); | 
| 292 | 	zprop_register_index(ZFS_PROP_DEVICES, "devices" , 1, PROP_INHERIT, | 
| 293 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off" , "DEVICES" , | 
| 294 | 	    boolean_table); | 
| 295 | 	zprop_register_index(ZFS_PROP_EXEC, "exec" , 1, PROP_INHERIT, | 
| 296 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off" , "EXEC" , | 
| 297 | 	    boolean_table); | 
| 298 | 	zprop_register_index(ZFS_PROP_SETUID, "setuid" , 1, PROP_INHERIT, | 
| 299 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off" , "SETUID" , | 
| 300 | 	    boolean_table); | 
| 301 | 	zprop_register_index(ZFS_PROP_READONLY, "readonly" , 0, PROP_INHERIT, | 
| 302 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "on | off" , "RDONLY" , | 
| 303 | 	    boolean_table); | 
| 304 | 	zprop_register_index(ZFS_PROP_ZONED, "jailed" , 0, PROP_INHERIT, | 
| 305 | 	    ZFS_TYPE_FILESYSTEM, "on | off" , "JAILED" , boolean_table); | 
| 306 | 	zprop_register_index(ZFS_PROP_XATTR, "xattr" , 1, PROP_INHERIT, | 
| 307 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off" , "XATTR" , | 
| 308 | 	    boolean_table); | 
| 309 | 	zprop_register_index(ZFS_PROP_VSCAN, "vscan" , 0, PROP_INHERIT, | 
| 310 | 	    ZFS_TYPE_FILESYSTEM, "on | off" , "VSCAN" , | 
| 311 | 	    boolean_table); | 
| 312 | 	zprop_register_index(ZFS_PROP_NBMAND, "nbmand" , 0, PROP_INHERIT, | 
| 313 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, "on | off" , "NBMAND" , | 
| 314 | 	    boolean_table); | 
| 315 |  | 
| 316 | 	/* default index properties */ | 
| 317 | 	zprop_register_index(ZFS_PROP_VERSION, "version" , 0, PROP_DEFAULT, | 
| 318 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, | 
| 319 | 	    "1 | 2 | 3 | 4 | 5 | current" , "VERSION" , version_table); | 
| 320 | 	zprop_register_index(ZFS_PROP_CANMOUNT, "canmount" , ZFS_CANMOUNT_ON, | 
| 321 | 	    PROP_DEFAULT, ZFS_TYPE_FILESYSTEM, "on | off | noauto" , | 
| 322 | 	    "CANMOUNT" , canmount_table); | 
| 323 |  | 
| 324 | 	/* readonly index (boolean) properties */ | 
| 325 | 	zprop_register_index(ZFS_PROP_MOUNTED, "mounted" , 0, PROP_READONLY, | 
| 326 | 	    ZFS_TYPE_FILESYSTEM, "yes | no" , "MOUNTED" , boolean_table); | 
| 327 | 	zprop_register_index(ZFS_PROP_DEFER_DESTROY, "defer_destroy" , 0, | 
| 328 | 	    PROP_READONLY, ZFS_TYPE_SNAPSHOT, "yes | no" , "DEFER_DESTROY" , | 
| 329 | 	    boolean_table); | 
| 330 |  | 
| 331 | 	/* set once index properties */ | 
| 332 | 	zprop_register_index(ZFS_PROP_NORMALIZE, "normalization" , 0, | 
| 333 | 	    PROP_ONETIME, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, | 
| 334 | 	    "none | formC | formD | formKC | formKD" , "NORMALIZATION" , | 
| 335 | 	    normalize_table); | 
| 336 | 	zprop_register_index(ZFS_PROP_CASE, "casesensitivity" , | 
| 337 | 	    ZFS_CASE_SENSITIVE, PROP_ONETIME, ZFS_TYPE_FILESYSTEM | | 
| 338 | 	    ZFS_TYPE_SNAPSHOT, | 
| 339 | 	    "sensitive | insensitive | mixed" , "CASE" , case_table); | 
| 340 |  | 
| 341 | 	/* set once index (boolean) properties */ | 
| 342 | 	zprop_register_index(ZFS_PROP_UTF8ONLY, "utf8only" , 0, PROP_ONETIME, | 
| 343 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT, | 
| 344 | 	    "on | off" , "UTF8ONLY" , boolean_table); | 
| 345 |  | 
| 346 | 	/* string properties */ | 
| 347 | 	zprop_register_string(ZFS_PROP_ORIGIN, "origin" , NULL, PROP_READONLY, | 
| 348 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<snapshot>" , "ORIGIN" ); | 
| 349 | 	zprop_register_string(ZFS_PROP_CLONES, "clones" , NULL, PROP_READONLY, | 
| 350 | 	    ZFS_TYPE_SNAPSHOT, "<dataset>[,...]" , "CLONES" ); | 
| 351 | 	zprop_register_string(ZFS_PROP_MOUNTPOINT, "mountpoint" , "/" , | 
| 352 | 	    PROP_INHERIT, ZFS_TYPE_FILESYSTEM, "<path> | legacy | none" , | 
| 353 | 	    "MOUNTPOINT" ); | 
| 354 | 	zprop_register_string(ZFS_PROP_SHARENFS, "sharenfs" , "off" , | 
| 355 | 	    PROP_INHERIT, ZFS_TYPE_FILESYSTEM, "on | off | share(1M) options" , | 
| 356 | 	    "SHARENFS" ); | 
| 357 | 	zprop_register_string(ZFS_PROP_TYPE, "type" , NULL, PROP_READONLY, | 
| 358 | 	    ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, | 
| 359 | 	    "filesystem | volume | snapshot | bookmark" , "TYPE" ); | 
| 360 | 	zprop_register_string(ZFS_PROP_SHARESMB, "sharesmb" , "off" , | 
| 361 | 	    PROP_INHERIT, ZFS_TYPE_FILESYSTEM, | 
| 362 | 	    "on | off | sharemgr(1M) options" , "SHARESMB" ); | 
| 363 | 	zprop_register_string(ZFS_PROP_MLSLABEL, "mlslabel" , | 
| 364 | 	    ZFS_MLSLABEL_DEFAULT, PROP_INHERIT, ZFS_TYPE_DATASET, | 
| 365 | 	    "<sensitivity label>" , "MLSLABEL" ); | 
| 366 | 	zprop_register_string(ZFS_PROP_RECEIVE_RESUME_TOKEN, | 
| 367 | 	    "receive_resume_token" , | 
| 368 | 	    NULL, PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 369 | 	    "<string token>" , "RESUMETOK" ); | 
| 370 |  | 
| 371 | 	/* readonly number properties */ | 
| 372 | 	zprop_register_number(ZFS_PROP_USED, "used" , 0, PROP_READONLY, | 
| 373 | 	    ZFS_TYPE_DATASET, "<size>" , "USED" ); | 
| 374 | 	zprop_register_number(ZFS_PROP_AVAILABLE, "available" , 0, PROP_READONLY, | 
| 375 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>" , "AVAIL" ); | 
| 376 | 	zprop_register_number(ZFS_PROP_REFERENCED, "referenced" , 0, | 
| 377 | 	    PROP_READONLY, ZFS_TYPE_DATASET, "<size>" , "REFER" ); | 
| 378 | 	zprop_register_number(ZFS_PROP_COMPRESSRATIO, "compressratio" , 0, | 
| 379 | 	    PROP_READONLY, ZFS_TYPE_DATASET, | 
| 380 | 	    "<1.00x or higher if compressed>" , "RATIO" ); | 
| 381 | 	zprop_register_number(ZFS_PROP_REFRATIO, "refcompressratio" , 0, | 
| 382 | 	    PROP_READONLY, ZFS_TYPE_DATASET, | 
| 383 | 	    "<1.00x or higher if compressed>" , "REFRATIO" ); | 
| 384 | 	zprop_register_number(ZFS_PROP_VOLBLOCKSIZE, "volblocksize" , | 
| 385 | 	    ZVOL_DEFAULT_BLOCKSIZE, PROP_ONETIME, | 
| 386 | 	    ZFS_TYPE_VOLUME, "512 to 128k, power of 2" ,	"VOLBLOCK" ); | 
| 387 | 	zprop_register_number(ZFS_PROP_USEDSNAP, "usedbysnapshots" , 0, | 
| 388 | 	    PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>" , | 
| 389 | 	    "USEDSNAP" ); | 
| 390 | 	zprop_register_number(ZFS_PROP_USEDDS, "usedbydataset" , 0, | 
| 391 | 	    PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>" , | 
| 392 | 	    "USEDDS" ); | 
| 393 | 	zprop_register_number(ZFS_PROP_USEDCHILD, "usedbychildren" , 0, | 
| 394 | 	    PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>" , | 
| 395 | 	    "USEDCHILD" ); | 
| 396 | 	zprop_register_number(ZFS_PROP_USEDREFRESERV, "usedbyrefreservation" , 0, | 
| 397 | 	    PROP_READONLY, | 
| 398 | 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<size>" , "USEDREFRESERV" ); | 
| 399 | 	zprop_register_number(ZFS_PROP_USERREFS, "userrefs" , 0, PROP_READONLY, | 
| 400 | 	    ZFS_TYPE_SNAPSHOT, "<count>" , "USERREFS" ); | 
| 401 | 	zprop_register_number(ZFS_PROP_WRITTEN, "written" , 0, PROP_READONLY, | 
| 402 | 	    ZFS_TYPE_DATASET, "<size>" , "WRITTEN" ); | 
| 403 | 	zprop_register_number(ZFS_PROP_LOGICALUSED, "logicalused" , 0, | 
| 404 | 	    PROP_READONLY, ZFS_TYPE_DATASET, "<size>" , "LUSED" ); | 
| 405 | 	zprop_register_number(ZFS_PROP_LOGICALREFERENCED, "logicalreferenced" , | 
| 406 | 	    0, PROP_READONLY, ZFS_TYPE_DATASET, "<size>" , "LREFER" ); | 
| 407 |  | 
| 408 | 	/* default number properties */ | 
| 409 | 	zprop_register_number(ZFS_PROP_QUOTA, "quota" , 0, PROP_DEFAULT, | 
| 410 | 	    ZFS_TYPE_FILESYSTEM, "<size> | none" , "QUOTA" ); | 
| 411 | 	zprop_register_number(ZFS_PROP_RESERVATION, "reservation" , 0, | 
| 412 | 	    PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 413 | 	    "<size> | none" , "RESERV" ); | 
| 414 | 	zprop_register_number(ZFS_PROP_VOLSIZE, "volsize" , 0, PROP_DEFAULT, | 
| 415 | 	    ZFS_TYPE_VOLUME, "<size>" , "VOLSIZE" ); | 
| 416 | 	zprop_register_number(ZFS_PROP_REFQUOTA, "refquota" , 0, PROP_DEFAULT, | 
| 417 | 	    ZFS_TYPE_FILESYSTEM, "<size> | none" , "REFQUOTA" ); | 
| 418 | 	zprop_register_number(ZFS_PROP_REFRESERVATION, "refreservation" , 0, | 
| 419 | 	    PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 420 | 	    "<size> | none" , "REFRESERV" ); | 
| 421 | 	zprop_register_number(ZFS_PROP_FILESYSTEM_LIMIT, "filesystem_limit" , | 
| 422 | 	    UINT64_MAX, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM, | 
| 423 | 	    "<count> | none" , "FSLIMIT" ); | 
| 424 | 	zprop_register_number(ZFS_PROP_SNAPSHOT_LIMIT, "snapshot_limit" , | 
| 425 | 	    UINT64_MAX, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 426 | 	    "<count> | none" , "SSLIMIT" ); | 
| 427 | 	zprop_register_number(ZFS_PROP_FILESYSTEM_COUNT, "filesystem_count" , | 
| 428 | 	    UINT64_MAX, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM, | 
| 429 | 	    "<count>" , "FSCOUNT" ); | 
| 430 | 	zprop_register_number(ZFS_PROP_SNAPSHOT_COUNT, "snapshot_count" , | 
| 431 | 	    UINT64_MAX, PROP_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, | 
| 432 | 	    "<count>" , "SSCOUNT" ); | 
| 433 |  | 
| 434 | 	/* inherit number properties */ | 
| 435 | 	zprop_register_number(ZFS_PROP_RECORDSIZE, "recordsize" , | 
| 436 | 	    SPA_OLD_MAXBLOCKSIZE, PROP_INHERIT, | 
| 437 | 	    ZFS_TYPE_FILESYSTEM, "512 to 1M, power of 2" , "RECSIZE" ); | 
| 438 |  | 
| 439 | 	/* hidden properties */ | 
| 440 | 	zprop_register_hidden(ZFS_PROP_CREATETXG, "createtxg" , PROP_TYPE_NUMBER, | 
| 441 | 	    PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "CREATETXG" ); | 
| 442 | 	zprop_register_hidden(ZFS_PROP_NUMCLONES, "numclones" , PROP_TYPE_NUMBER, | 
| 443 | 	    PROP_READONLY, ZFS_TYPE_SNAPSHOT, "NUMCLONES" ); | 
| 444 | 	zprop_register_hidden(ZFS_PROP_NAME, "name" , PROP_TYPE_STRING, | 
| 445 | 	    PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "NAME" ); | 
| 446 | 	zprop_register_hidden(ZFS_PROP_ISCSIOPTIONS, "iscsioptions" , | 
| 447 | 	    PROP_TYPE_STRING, PROP_INHERIT, ZFS_TYPE_VOLUME, "ISCSIOPTIONS" ); | 
| 448 | 	zprop_register_hidden(ZFS_PROP_STMF_SHAREINFO, "stmf_sbd_lu" , | 
| 449 | 	    PROP_TYPE_STRING, PROP_INHERIT, ZFS_TYPE_VOLUME, | 
| 450 | 	    "STMF_SBD_LU" ); | 
| 451 | 	zprop_register_hidden(ZFS_PROP_GUID, "guid" , PROP_TYPE_NUMBER, | 
| 452 | 	    PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "GUID" ); | 
| 453 | 	zprop_register_hidden(ZFS_PROP_USERACCOUNTING, "useraccounting" , | 
| 454 | 	    PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_DATASET, | 
| 455 | 	    "USERACCOUNTING" ); | 
| 456 | 	zprop_register_hidden(ZFS_PROP_UNIQUE, "unique" , PROP_TYPE_NUMBER, | 
| 457 | 	    PROP_READONLY, ZFS_TYPE_DATASET, "UNIQUE" ); | 
| 458 | 	zprop_register_hidden(ZFS_PROP_OBJSETID, "objsetid" , PROP_TYPE_NUMBER, | 
| 459 | 	    PROP_READONLY, ZFS_TYPE_DATASET, "OBJSETID" ); | 
| 460 | 	zprop_register_hidden(ZFS_PROP_INCONSISTENT, "inconsistent" , | 
| 461 | 	    PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_DATASET, "INCONSISTENT" ); | 
| 462 | 	zprop_register_hidden(ZFS_PROP_PREV_SNAP, "prevsnap" , PROP_TYPE_STRING, | 
| 463 | 	    PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "PREVSNAP" ); | 
| 464 |  | 
| 465 | 	/* oddball properties */ | 
| 466 | 	zprop_register_impl(ZFS_PROP_CREATION, "creation" , PROP_TYPE_NUMBER, 0, | 
| 467 | 	    NULL, PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, | 
| 468 | 	    "<date>" , "CREATION" , B_FALSE, B_TRUE, NULL); | 
| 469 | } | 
| 470 |  | 
| 471 | boolean_t | 
| 472 | zfs_prop_delegatable(zfs_prop_t prop) | 
| 473 | { | 
| 474 | 	zprop_desc_t *pd = &zfs_prop_table[prop]; | 
| 475 |  | 
| 476 | 	/* The mlslabel property is never delegatable. */ | 
| 477 | 	if (prop == ZFS_PROP_MLSLABEL) | 
| 478 | 		return (B_FALSE); | 
| 479 |  | 
| 480 | 	return (pd->pd_attr != PROP_READONLY); | 
| 481 | } | 
| 482 |  | 
| 483 | /* | 
| 484 |  * Given a zfs dataset property name, returns the corresponding property ID. | 
| 485 |  */ | 
| 486 | zfs_prop_t | 
| 487 | zfs_name_to_prop(const char *propname) | 
| 488 | { | 
| 489 | 	return (zprop_name_to_prop(propname, ZFS_TYPE_DATASET)); | 
| 490 | } | 
| 491 |  | 
| 492 | /* | 
| 493 |  * For user property names, we allow all lowercase alphanumeric characters, plus | 
| 494 |  * a few useful punctuation characters. | 
| 495 |  */ | 
| 496 | static int | 
| 497 | valid_char(char c) | 
| 498 | { | 
| 499 | 	return ((c >= 'a' && c <= 'z') || | 
| 500 | 	    (c >= '0' && c <= '9') || | 
| 501 | 	    c == '-' || c == '_' || c == '.' || c == ':'); | 
| 502 | } | 
| 503 |  | 
| 504 | /* | 
| 505 |  * Returns true if this is a valid user-defined property (one with a ':'). | 
| 506 |  */ | 
| 507 | boolean_t | 
| 508 | zfs_prop_user(const char *name) | 
| 509 | { | 
| 510 | 	int i; | 
| 511 | 	char c; | 
| 512 | 	boolean_t foundsep = B_FALSE; | 
| 513 |  | 
| 514 | 	for (i = 0; i < strlen(name); i++) { | 
| 515 | 		c = name[i]; | 
| 516 | 		if (!valid_char(c)) | 
| 517 | 			return (B_FALSE); | 
| 518 | 		if (c == ':') | 
| 519 | 			foundsep = B_TRUE; | 
| 520 | 	} | 
| 521 |  | 
| 522 | 	if (!foundsep) | 
| 523 | 		return (B_FALSE); | 
| 524 |  | 
| 525 | 	return (B_TRUE); | 
| 526 | } | 
| 527 |  | 
| 528 | /* | 
| 529 |  * Returns true if this is a valid userspace-type property (one with a '@'). | 
| 530 |  * Note that after the @, any character is valid (eg, another @, for SID | 
| 531 |  * user@domain). | 
| 532 |  */ | 
| 533 | boolean_t | 
| 534 | zfs_prop_userquota(const char *name) | 
| 535 | { | 
| 536 | 	zfs_userquota_prop_t prop; | 
| 537 |  | 
| 538 | 	for (prop = 0; prop < ZFS_NUM_USERQUOTA_PROPS; prop++) { | 
| 539 | 		if (strncmp(name, zfs_userquota_prop_prefixes[prop], | 
| 540 | 		    strlen(zfs_userquota_prop_prefixes[prop])) == 0) { | 
| 541 | 			return (B_TRUE); | 
| 542 | 		} | 
| 543 | 	} | 
| 544 |  | 
| 545 | 	return (B_FALSE); | 
| 546 | } | 
| 547 |  | 
| 548 | /* | 
| 549 |  * Returns true if this is a valid written@ property. | 
| 550 |  * Note that after the @, any character is valid (eg, another @, for | 
| 551 |  * written@pool/fs@origin). | 
| 552 |  */ | 
| 553 | boolean_t | 
| 554 | zfs_prop_written(const char *name) | 
| 555 | { | 
| 556 | 	static const char *prefix = "written@" ; | 
| 557 | 	return (strncmp(name, prefix, strlen(prefix)) == 0); | 
| 558 | } | 
| 559 |  | 
| 560 | /* | 
| 561 |  * Tables of index types, plus functions to convert between the user view | 
| 562 |  * (strings) and internal representation (uint64_t). | 
| 563 |  */ | 
| 564 | int | 
| 565 | zfs_prop_string_to_index(zfs_prop_t prop, const char *string, uint64_t *index) | 
| 566 | { | 
| 567 | 	return (zprop_string_to_index(prop, string, index, ZFS_TYPE_DATASET)); | 
| 568 | } | 
| 569 |  | 
| 570 | int | 
| 571 | zfs_prop_index_to_string(zfs_prop_t prop, uint64_t index, const char **string) | 
| 572 | { | 
| 573 | 	return (zprop_index_to_string(prop, index, string, ZFS_TYPE_DATASET)); | 
| 574 | } | 
| 575 |  | 
| 576 | uint64_t | 
| 577 | zfs_prop_random_value(zfs_prop_t prop, uint64_t seed) | 
| 578 | { | 
| 579 | 	return (zprop_random_value(prop, seed, ZFS_TYPE_DATASET)); | 
| 580 | } | 
| 581 |  | 
| 582 | /* | 
| 583 |  * Returns TRUE if the property applies to any of the given dataset types. | 
| 584 |  */ | 
| 585 | boolean_t | 
| 586 | zfs_prop_valid_for_type(int prop, zfs_type_t types) | 
| 587 | { | 
| 588 | 	return (zprop_valid_for_type(prop, types)); | 
| 589 | } | 
| 590 |  | 
| 591 | zprop_type_t | 
| 592 | zfs_prop_get_type(zfs_prop_t prop) | 
| 593 | { | 
| 594 | 	return (zfs_prop_table[prop].pd_proptype); | 
| 595 | } | 
| 596 |  | 
| 597 | /* | 
| 598 |  * Returns TRUE if the property is readonly. | 
| 599 |  */ | 
| 600 | boolean_t | 
| 601 | zfs_prop_readonly(zfs_prop_t prop) | 
| 602 | { | 
| 603 | 	return (zfs_prop_table[prop].pd_attr == PROP_READONLY || | 
| 604 | 	    zfs_prop_table[prop].pd_attr == PROP_ONETIME); | 
| 605 | } | 
| 606 |  | 
| 607 | /* | 
| 608 |  * Returns TRUE if the property is only allowed to be set once. | 
| 609 |  */ | 
| 610 | boolean_t | 
| 611 | zfs_prop_setonce(zfs_prop_t prop) | 
| 612 | { | 
| 613 | 	return (zfs_prop_table[prop].pd_attr == PROP_ONETIME); | 
| 614 | } | 
| 615 |  | 
| 616 | const char * | 
| 617 | zfs_prop_default_string(zfs_prop_t prop) | 
| 618 | { | 
| 619 | 	return (zfs_prop_table[prop].pd_strdefault); | 
| 620 | } | 
| 621 |  | 
| 622 | uint64_t | 
| 623 | zfs_prop_default_numeric(zfs_prop_t prop) | 
| 624 | { | 
| 625 | 	return (zfs_prop_table[prop].pd_numdefault); | 
| 626 | } | 
| 627 |  | 
| 628 | /* | 
| 629 |  * Given a dataset property ID, returns the corresponding name. | 
| 630 |  * Assuming the zfs dataset property ID is valid. | 
| 631 |  */ | 
| 632 | const char * | 
| 633 | zfs_prop_to_name(zfs_prop_t prop) | 
| 634 | { | 
| 635 | 	return (zfs_prop_table[prop].pd_name); | 
| 636 | } | 
| 637 |  | 
| 638 | /* | 
| 639 |  * Returns TRUE if the property is inheritable. | 
| 640 |  */ | 
| 641 | boolean_t | 
| 642 | zfs_prop_inheritable(zfs_prop_t prop) | 
| 643 | { | 
| 644 | 	return (zfs_prop_table[prop].pd_attr == PROP_INHERIT || | 
| 645 | 	    zfs_prop_table[prop].pd_attr == PROP_ONETIME); | 
| 646 | } | 
| 647 |  | 
| 648 | #ifndef _KERNEL | 
| 649 |  | 
| 650 | /* | 
| 651 |  * Returns a string describing the set of acceptable values for the given | 
| 652 |  * zfs property, or NULL if it cannot be set. | 
| 653 |  */ | 
| 654 | const char * | 
| 655 | zfs_prop_values(zfs_prop_t prop) | 
| 656 | { | 
| 657 | 	return (zfs_prop_table[prop].pd_values); | 
| 658 | } | 
| 659 |  | 
| 660 | /* | 
| 661 |  * Returns TRUE if this property is a string type.  Note that index types | 
| 662 |  * (compression, checksum) are treated as strings in userland, even though they | 
| 663 |  * are stored numerically on disk. | 
| 664 |  */ | 
| 665 | int | 
| 666 | zfs_prop_is_string(zfs_prop_t prop) | 
| 667 | { | 
| 668 | 	return (zfs_prop_table[prop].pd_proptype == PROP_TYPE_STRING || | 
| 669 | 	    zfs_prop_table[prop].pd_proptype == PROP_TYPE_INDEX); | 
| 670 | } | 
| 671 |  | 
| 672 | /* | 
| 673 |  * Returns the column header for the given property.  Used only in | 
| 674 |  * 'zfs list -o', but centralized here with the other property information. | 
| 675 |  */ | 
| 676 | const char * | 
| 677 | zfs_prop_column_name(zfs_prop_t prop) | 
| 678 | { | 
| 679 | 	return (zfs_prop_table[prop].pd_colname); | 
| 680 | } | 
| 681 |  | 
| 682 | /* | 
| 683 |  * Returns whether the given property should be displayed right-justified for | 
| 684 |  * 'zfs list'. | 
| 685 |  */ | 
| 686 | boolean_t | 
| 687 | zfs_prop_align_right(zfs_prop_t prop) | 
| 688 | { | 
| 689 | 	return (zfs_prop_table[prop].pd_rightalign); | 
| 690 | } | 
| 691 |  | 
| 692 | #endif | 
| 693 |  |