Home | History | Annotate | Download | only in common
      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 /*
     23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include <assert.h>
     28 #include <ctype.h>
     29 #include <errno.h>
     30 #include <libdevinfo.h>
     31 #include <libintl.h>
     32 #include <math.h>
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <strings.h>
     36 #include <unistd.h>
     37 #include <stddef.h>
     38 #include <zone.h>
     39 #include <fcntl.h>
     40 #include <sys/mntent.h>
     41 #include <sys/mnttab.h>
     42 #include <sys/mount.h>
     43 #include <sys/avl.h>
     44 #include <priv.h>
     45 #include <pwd.h>
     46 #include <grp.h>
     47 #include <stddef.h>
     48 #include <ucred.h>
     49 
     50 #include <sys/spa.h>
     51 #include <sys/zap.h>
     52 #include <libzfs.h>
     53 
     54 #include "zfs_namecheck.h"
     55 #include "zfs_prop.h"
     56 #include "libzfs_impl.h"
     57 #include "zfs_deleg.h"
     58 
     59 static int zvol_create_link_common(libzfs_handle_t *, const char *, int);
     60 
     61 /*
     62  * Given a single type (not a mask of types), return the type in a human
     63  * readable form.
     64  */
     65 const char *
     66 zfs_type_to_name(zfs_type_t type)
     67 {
     68 	switch (type) {
     69 	case ZFS_TYPE_FILESYSTEM:
     70 		return (dgettext(TEXT_DOMAIN, "filesystem"));
     71 	case ZFS_TYPE_SNAPSHOT:
     72 		return (dgettext(TEXT_DOMAIN, "snapshot"));
     73 	case ZFS_TYPE_VOLUME:
     74 		return (dgettext(TEXT_DOMAIN, "volume"));
     75 	}
     76 
     77 	return (NULL);
     78 }
     79 
     80 /*
     81  * Given a path and mask of ZFS types, return a string describing this dataset.
     82  * This is used when we fail to open a dataset and we cannot get an exact type.
     83  * We guess what the type would have been based on the path and the mask of
     84  * acceptable types.
     85  */
     86 static const char *
     87 path_to_str(const char *path, int types)
     88 {
     89 	/*
     90 	 * When given a single type, always report the exact type.
     91 	 */
     92 	if (types == ZFS_TYPE_SNAPSHOT)
     93 		return (dgettext(TEXT_DOMAIN, "snapshot"));
     94 	if (types == ZFS_TYPE_FILESYSTEM)
     95 		return (dgettext(TEXT_DOMAIN, "filesystem"));
     96 	if (types == ZFS_TYPE_VOLUME)
     97 		return (dgettext(TEXT_DOMAIN, "volume"));
     98 
     99 	/*
    100 	 * The user is requesting more than one type of dataset.  If this is the
    101 	 * case, consult the path itself.  If we're looking for a snapshot, and
    102 	 * a '@' is found, then report it as "snapshot".  Otherwise, remove the
    103 	 * snapshot attribute and try again.
    104 	 */
    105 	if (types & ZFS_TYPE_SNAPSHOT) {
    106 		if (strchr(path, '@') != NULL)
    107 			return (dgettext(TEXT_DOMAIN, "snapshot"));
    108 		return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT));
    109 	}
    110 
    111 
    112 	/*
    113 	 * The user has requested either filesystems or volumes.
    114 	 * We have no way of knowing a priori what type this would be, so always
    115 	 * report it as "filesystem" or "volume", our two primitive types.
    116 	 */
    117 	if (types & ZFS_TYPE_FILESYSTEM)
    118 		return (dgettext(TEXT_DOMAIN, "filesystem"));
    119 
    120 	assert(types & ZFS_TYPE_VOLUME);
    121 	return (dgettext(TEXT_DOMAIN, "volume"));
    122 }
    123 
    124 /*
    125  * Validate a ZFS path.  This is used even before trying to open the dataset, to
    126  * provide a more meaningful error message.  We place a more useful message in
    127  * 'buf' detailing exactly why the name was not valid.
    128  */
    129 static int
    130 zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
    131     boolean_t modifying)
    132 {
    133 	namecheck_err_t why;
    134 	char what;
    135 
    136 	if (dataset_namecheck(path, &why, &what) != 0) {
    137 		if (hdl != NULL) {
    138 			switch (why) {
    139 			case NAME_ERR_TOOLONG:
    140 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    141 				    "name is too long"));
    142 				break;
    143 
    144 			case NAME_ERR_LEADING_SLASH:
    145 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    146 				    "leading slash in name"));
    147 				break;
    148 
    149 			case NAME_ERR_EMPTY_COMPONENT:
    150 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    151 				    "empty component in name"));
    152 				break;
    153 
    154 			case NAME_ERR_TRAILING_SLASH:
    155 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    156 				    "trailing slash in name"));
    157 				break;
    158 
    159 			case NAME_ERR_INVALCHAR:
    160 				zfs_error_aux(hdl,
    161 				    dgettext(TEXT_DOMAIN, "invalid character "
    162 				    "'%c' in name"), what);
    163 				break;
    164 
    165 			case NAME_ERR_MULTIPLE_AT:
    166 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    167 				    "multiple '@' delimiters in name"));
    168 				break;
    169 
    170 			case NAME_ERR_NOLETTER:
    171 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    172 				    "pool doesn't begin with a letter"));
    173 				break;
    174 
    175 			case NAME_ERR_RESERVED:
    176 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    177 				    "name is reserved"));
    178 				break;
    179 
    180 			case NAME_ERR_DISKLIKE:
    181 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    182 				    "reserved disk name"));
    183 				break;
    184 			}
    185 		}
    186 
    187 		return (0);
    188 	}
    189 
    190 	if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
    191 		if (hdl != NULL)
    192 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    193 			    "snapshot delimiter '@' in filesystem name"));
    194 		return (0);
    195 	}
    196 
    197 	if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) {
    198 		if (hdl != NULL)
    199 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    200 			    "missing '@' delimiter in snapshot name"));
    201 		return (0);
    202 	}
    203 
    204 	if (modifying && strchr(path, '%') != NULL) {
    205 		if (hdl != NULL)
    206 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    207 			    "invalid character %c in name"), '%');
    208 		return (0);
    209 	}
    210 
    211 	return (-1);
    212 }
    213 
    214 int
    215 zfs_name_valid(const char *name, zfs_type_t type)
    216 {
    217 	if (type == ZFS_TYPE_POOL)
    218 		return (zpool_name_valid(NULL, B_FALSE, name));
    219 	return (zfs_validate_name(NULL, name, type, B_FALSE));
    220 }
    221 
    222 /*
    223  * This function takes the raw DSL properties, and filters out the user-defined
    224  * properties into a separate nvlist.
    225  */
    226 static nvlist_t *
    227 process_user_props(zfs_handle_t *zhp, nvlist_t *props)
    228 {
    229 	libzfs_handle_t *hdl = zhp->zfs_hdl;
    230 	nvpair_t *elem;
    231 	nvlist_t *propval;
    232 	nvlist_t *nvl;
    233 
    234 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
    235 		(void) no_memory(hdl);
    236 		return (NULL);
    237 	}
    238 
    239 	elem = NULL;
    240 	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
    241 		if (!zfs_prop_user(nvpair_name(elem)))
    242 			continue;
    243 
    244 		verify(nvpair_value_nvlist(elem, &propval) == 0);
    245 		if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) {
    246 			nvlist_free(nvl);
    247 			(void) no_memory(hdl);
    248 			return (NULL);
    249 		}
    250 	}
    251 
    252 	return (nvl);
    253 }
    254 
    255 static zpool_handle_t *
    256 zpool_add_handle(zfs_handle_t *zhp, const char *pool_name)
    257 {
    258 	libzfs_handle_t *hdl = zhp->zfs_hdl;
    259 	zpool_handle_t *zph;
    260 
    261 	if ((zph = zpool_open_canfail(hdl, pool_name)) != NULL) {
    262 		if (hdl->libzfs_pool_handles != NULL)
    263 			zph->zpool_next = hdl->libzfs_pool_handles;
    264 		hdl->libzfs_pool_handles = zph;
    265 	}
    266 	return (zph);
    267 }
    268 
    269 static zpool_handle_t *
    270 zpool_find_handle(zfs_handle_t *zhp, const char *pool_name, int len)
    271 {
    272 	libzfs_handle_t *hdl = zhp->zfs_hdl;
    273 	zpool_handle_t *zph = hdl->libzfs_pool_handles;
    274 
    275 	while ((zph != NULL) &&
    276 	    (strncmp(pool_name, zpool_get_name(zph), len) != 0))
    277 		zph = zph->zpool_next;
    278 	return (zph);
    279 }
    280 
    281 /*
    282  * Returns a handle to the pool that contains the provided dataset.
    283  * If a handle to that pool already exists then that handle is returned.
    284  * Otherwise, a new handle is created and added to the list of handles.
    285  */
    286 static zpool_handle_t *
    287 zpool_handle(zfs_handle_t *zhp)
    288 {
    289 	char *pool_name;
    290 	int len;
    291 	zpool_handle_t *zph;
    292 
    293 	len = strcspn(zhp->zfs_name, "/@") + 1;
    294 	pool_name = zfs_alloc(zhp->zfs_hdl, len);
    295 	(void) strlcpy(pool_name, zhp->zfs_name, len);
    296 
    297 	zph = zpool_find_handle(zhp, pool_name, len);
    298 	if (zph == NULL)
    299 		zph = zpool_add_handle(zhp, pool_name);
    300 
    301 	free(pool_name);
    302 	return (zph);
    303 }
    304 
    305 void
    306 zpool_free_handles(libzfs_handle_t *hdl)
    307 {
    308 	zpool_handle_t *next, *zph = hdl->libzfs_pool_handles;
    309 
    310 	while (zph != NULL) {
    311 		next = zph->zpool_next;
    312 		zpool_close(zph);
    313 		zph = next;
    314 	}
    315 	hdl->libzfs_pool_handles = NULL;
    316 }
    317 
    318 /*
    319  * Utility function to gather stats (objset and zpl) for the given object.
    320  */
    321 static int
    322 get_stats(zfs_handle_t *zhp)
    323 {
    324 	zfs_cmd_t zc = { 0 };
    325 	libzfs_handle_t *hdl = zhp->zfs_hdl;
    326 	nvlist_t *allprops, *userprops;
    327 
    328 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
    329 
    330 	if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
    331 		return (-1);
    332 
    333 	while (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) {
    334 		if (errno == ENOMEM) {
    335 			if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
    336 				zcmd_free_nvlists(&zc);
    337 				return (-1);
    338 			}
    339 		} else {
    340 			zcmd_free_nvlists(&zc);
    341 			return (-1);
    342 		}
    343 	}
    344 
    345 	zhp->zfs_dmustats = zc.zc_objset_stats; /* structure assignment */
    346 
    347 	if (zcmd_read_dst_nvlist(hdl, &zc, &allprops) != 0) {
    348 		zcmd_free_nvlists(&zc);
    349 		return (-1);
    350 	}
    351 
    352 	zcmd_free_nvlists(&zc);
    353 
    354 	if ((userprops = process_user_props(zhp, allprops)) == NULL) {
    355 		nvlist_free(allprops);
    356 		return (-1);
    357 	}
    358 
    359 	nvlist_free(zhp->zfs_props);
    360 	nvlist_free(zhp->zfs_user_props);
    361 
    362 	zhp->zfs_props = allprops;
    363 	zhp->zfs_user_props = userprops;
    364 
    365 	return (0);
    366 }
    367 
    368 /*
    369  * Refresh the properties currently stored in the handle.
    370  */
    371 void
    372 zfs_refresh_properties(zfs_handle_t *zhp)
    373 {
    374 	(void) get_stats(zhp);
    375 }
    376 
    377 /*
    378  * Makes a handle from the given dataset name.  Used by zfs_open() and
    379  * zfs_iter_* to create child handles on the fly.
    380  */
    381 zfs_handle_t *
    382 make_dataset_handle(libzfs_handle_t *hdl, const char *path)
    383 {
    384 	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
    385 	char *logstr;
    386 
    387 	if (zhp == NULL)
    388 		return (NULL);
    389 
    390 	zhp->zfs_hdl = hdl;
    391 
    392 	/*
    393 	 * Preserve history log string.
    394 	 * any changes performed here will be
    395 	 * logged as an internal event.
    396 	 */
    397 	logstr = zhp->zfs_hdl->libzfs_log_str;
    398 	zhp->zfs_hdl->libzfs_log_str = NULL;
    399 top:
    400 	(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
    401 
    402 	if (get_stats(zhp) != 0) {
    403 		zhp->zfs_hdl->libzfs_log_str = logstr;
    404 		free(zhp);
    405 		return (NULL);
    406 	}
    407 
    408 	if (zhp->zfs_dmustats.dds_inconsistent) {
    409 		zfs_cmd_t zc = { 0 };
    410 
    411 		/*
    412 		 * If it is dds_inconsistent, then we've caught it in
    413 		 * the middle of a 'zfs receive' or 'zfs destroy', and
    414 		 * it is inconsistent from the ZPL's point of view, so
    415 		 * can't be mounted.  However, it could also be that we
    416 		 * have crashed in the middle of one of those
    417 		 * operations, in which case we need to get rid of the
    418 		 * inconsistent state.  We do that by either rolling
    419 		 * back to the previous snapshot (which will fail if
    420 		 * there is none), or destroying the filesystem.  Note
    421 		 * that if we are still in the middle of an active
    422 		 * 'receive' or 'destroy', then the rollback and destroy
    423 		 * will fail with EBUSY and we will drive on as usual.
    424 		 */
    425 
    426 		(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
    427 
    428 		if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL) {
    429 			(void) zvol_remove_link(hdl, zhp->zfs_name);
    430 			zc.zc_objset_type = DMU_OST_ZVOL;
    431 		} else {
    432 			zc.zc_objset_type = DMU_OST_ZFS;
    433 		}
    434 
    435 		/*
    436 		 * If we can successfully destroy it, pretend that it
    437 		 * never existed.
    438 		 */
    439 		if (ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) == 0) {
    440 			zhp->zfs_hdl->libzfs_log_str = logstr;
    441 			free(zhp);
    442 			errno = ENOENT;
    443 			return (NULL);
    444 		}
    445 		/* If we can successfully roll it back, reget the stats */
    446 		if (ioctl(hdl->libzfs_fd, ZFS_IOC_ROLLBACK, &zc) == 0)
    447 			goto top;
    448 	}
    449 
    450 	/*
    451 	 * We've managed to open the dataset and gather statistics.  Determine
    452 	 * the high-level type.
    453 	 */
    454 	if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
    455 		zhp->zfs_head_type = ZFS_TYPE_VOLUME;
    456 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
    457 		zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM;
    458 	else
    459 		abort();
    460 
    461 	if (zhp->zfs_dmustats.dds_is_snapshot)
    462 		zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
    463 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
    464 		zhp->zfs_type = ZFS_TYPE_VOLUME;
    465 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
    466 		zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
    467 	else
    468 		abort();	/* we should never see any other types */
    469 
    470 	zhp->zfs_hdl->libzfs_log_str = logstr;
    471 	zhp->zpool_hdl = zpool_handle(zhp);
    472 	return (zhp);
    473 }
    474 
    475 /*
    476  * Opens the given snapshot, filesystem, or volume.   The 'types'
    477  * argument is a mask of acceptable types.  The function will print an
    478  * appropriate error message and return NULL if it can't be opened.
    479  */
    480 zfs_handle_t *
    481 zfs_open(libzfs_handle_t *hdl, const char *path, int types)
    482 {
    483 	zfs_handle_t *zhp;
    484 	char errbuf[1024];
    485 
    486 	(void) snprintf(errbuf, sizeof (errbuf),
    487 	    dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
    488 
    489 	/*
    490 	 * Validate the name before we even try to open it.
    491 	 */
    492 	if (!zfs_validate_name(hdl, path, ZFS_TYPE_DATASET, B_FALSE)) {
    493 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    494 		    "invalid dataset name"));
    495 		(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
    496 		return (NULL);
    497 	}
    498 
    499 	/*
    500 	 * Try to get stats for the dataset, which will tell us if it exists.
    501 	 */
    502 	errno = 0;
    503 	if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
    504 		(void) zfs_standard_error(hdl, errno, errbuf);
    505 		return (NULL);
    506 	}
    507 
    508 	if (!(types & zhp->zfs_type)) {
    509 		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
    510 		zfs_close(zhp);
    511 		return (NULL);
    512 	}
    513 
    514 	return (zhp);
    515 }
    516 
    517 /*
    518  * Release a ZFS handle.  Nothing to do but free the associated memory.
    519  */
    520 void
    521 zfs_close(zfs_handle_t *zhp)
    522 {
    523 	if (zhp->zfs_mntopts)
    524 		free(zhp->zfs_mntopts);
    525 	nvlist_free(zhp->zfs_props);
    526 	nvlist_free(zhp->zfs_user_props);
    527 	free(zhp);
    528 }
    529 
    530 int
    531 zfs_spa_version(zfs_handle_t *zhp, int *spa_version)
    532 {
    533 	zpool_handle_t *zpool_handle = zhp->zpool_hdl;
    534 
    535 	if (zpool_handle == NULL)
    536 		return (-1);
    537 
    538 	*spa_version = zpool_get_prop_int(zpool_handle,
    539 	    ZPOOL_PROP_VERSION, NULL);
    540 	return (0);
    541 }
    542 
    543 /*
    544  * The choice of reservation property depends on the SPA version.
    545  */
    546 static int
    547 zfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop)
    548 {
    549 	int spa_version;
    550 
    551 	if (zfs_spa_version(zhp, &spa_version) < 0)
    552 		return (-1);
    553 
    554 	if (spa_version >= SPA_VERSION_REFRESERVATION)
    555 		*resv_prop = ZFS_PROP_REFRESERVATION;
    556 	else
    557 		*resv_prop = ZFS_PROP_RESERVATION;
    558 
    559 	return (0);
    560 }
    561 
    562 /*
    563  * Given an nvlist of properties to set, validates that they are correct, and
    564  * parses any numeric properties (index, boolean, etc) if they are specified as
    565  * strings.
    566  */
    567 nvlist_t *
    568 zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
    569     uint64_t zoned, zfs_handle_t *zhp, const char *errbuf)
    570 {
    571 	nvpair_t *elem;
    572 	uint64_t intval;
    573 	char *strval;
    574 	zfs_prop_t prop;
    575 	nvlist_t *ret;
    576 	int chosen_normal = -1;
    577 	int chosen_utf = -1;
    578 
    579 	if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) {
    580 		(void) no_memory(hdl);
    581 		return (NULL);
    582 	}
    583 
    584 	elem = NULL;
    585 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
    586 		const char *propname = nvpair_name(elem);
    587 
    588 		/*
    589 		 * Make sure this property is valid and applies to this type.
    590 		 */
    591 		if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
    592 			if (!zfs_prop_user(propname)) {
    593 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    594 				    "invalid property '%s'"), propname);
    595 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
    596 				goto error;
    597 			}
    598 
    599 			/*
    600 			 * If this is a user property, make sure it's a
    601 			 * string, and that it's less than ZAP_MAXNAMELEN.
    602 			 */
    603 			if (nvpair_type(elem) != DATA_TYPE_STRING) {
    604 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    605 				    "'%s' must be a string"), propname);
    606 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
    607 				goto error;
    608 			}
    609 
    610 			if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
    611 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    612 				    "property name '%s' is too long"),
    613 				    propname);
    614 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
    615 				goto error;
    616 			}
    617 
    618 			(void) nvpair_value_string(elem, &strval);
    619 			if (nvlist_add_string(ret, propname, strval) != 0) {
    620 				(void) no_memory(hdl);
    621 				goto error;
    622 			}
    623 			continue;
    624 		}
    625 
    626 		if (type == ZFS_TYPE_SNAPSHOT) {
    627 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    628 			    "this property can not be modified for snapshots"));
    629 			(void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
    630 			goto error;
    631 		}
    632 
    633 		if (!zfs_prop_valid_for_type(prop, type)) {
    634 			zfs_error_aux(hdl,
    635 			    dgettext(TEXT_DOMAIN, "'%s' does not "
    636 			    "apply to datasets of this type"), propname);
    637 			(void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
    638 			goto error;
    639 		}
    640 
    641 		if (zfs_prop_readonly(prop) &&
    642 		    (!zfs_prop_setonce(prop) || zhp != NULL)) {
    643 			zfs_error_aux(hdl,
    644 			    dgettext(TEXT_DOMAIN, "'%s' is readonly"),
    645 			    propname);
    646 			(void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
    647 			goto error;
    648 		}
    649 
    650 		if (zprop_parse_value(hdl, elem, prop, type, ret,
    651 		    &strval, &intval, errbuf) != 0)
    652 			goto error;
    653 
    654 		/*
    655 		 * Perform some additional checks for specific properties.
    656 		 */
    657 		switch (prop) {
    658 		case ZFS_PROP_VERSION:
    659 		{
    660 			int version;
    661 
    662 			if (zhp == NULL)
    663 				break;
    664 			version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
    665 			if (intval < version) {
    666 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    667 				    "Can not downgrade; already at version %u"),
    668 				    version);
    669 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
    670 				goto error;
    671 			}
    672 			break;
    673 		}
    674 
    675 		case ZFS_PROP_RECORDSIZE:
    676 		case ZFS_PROP_VOLBLOCKSIZE:
    677 			/* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */
    678 			if (intval < SPA_MINBLOCKSIZE ||
    679 			    intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) {
    680 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    681 				    "'%s' must be power of 2 from %u "
    682 				    "to %uk"), propname,
    683 				    (uint_t)SPA_MINBLOCKSIZE,
    684 				    (uint_t)SPA_MAXBLOCKSIZE >> 10);
    685 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
    686 				goto error;
    687 			}
    688 			break;
    689 
    690 		case ZFS_PROP_SHAREISCSI:
    691 			if (strcmp(strval, "off") != 0 &&
    692 			    strcmp(strval, "on") != 0 &&
    693 			    strcmp(strval, "type=disk") != 0) {
    694 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    695 				    "'%s' must be 'on', 'off', or 'type=disk'"),
    696 				    propname);
    697 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
    698 				goto error;
    699 			}
    700 
    701 			break;
    702 
    703 		case ZFS_PROP_MOUNTPOINT:
    704 		{
    705 			namecheck_err_t why;
    706 
    707 			if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 ||
    708 			    strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0)
    709 				break;
    710 
    711 			if (mountpoint_namecheck(strval, &why)) {
    712 				switch (why) {
    713 				case NAME_ERR_LEADING_SLASH:
    714 					zfs_error_aux(hdl,
    715 					    dgettext(TEXT_DOMAIN,
    716 					    "'%s' must be an absolute path, "
    717 					    "'none', or 'legacy'"), propname);
    718 					break;
    719 				case NAME_ERR_TOOLONG:
    720 					zfs_error_aux(hdl,
    721 					    dgettext(TEXT_DOMAIN,
    722 					    "component of '%s' is too long"),
    723 					    propname);
    724 					break;
    725 				}
    726 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
    727 				goto error;
    728 			}
    729 		}
    730 
    731 			/*FALLTHRU*/
    732 
    733 		case ZFS_PROP_SHARESMB:
    734 		case ZFS_PROP_SHARENFS:
    735 			/*
    736 			 * For the mountpoint and sharenfs or sharesmb
    737 			 * properties, check if it can be set in a
    738 			 * global/non-global zone based on
    739 			 * the zoned property value:
    740 			 *
    741 			 *		global zone	    non-global zone
    742 			 * --------------------------------------------------
    743 			 * zoned=on	mountpoint (no)	    mountpoint (yes)
    744 			 *		sharenfs (no)	    sharenfs (no)
    745 			 *		sharesmb (no)	    sharesmb (no)
    746 			 *
    747 			 * zoned=off	mountpoint (yes)	N/A
    748 			 *		sharenfs (yes)
    749 			 *		sharesmb (yes)
    750 			 */
    751 			if (zoned) {
    752 				if (getzoneid() == GLOBAL_ZONEID) {
    753 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    754 					    "'%s' cannot be set on "
    755 					    "dataset in a non-global zone"),
    756 					    propname);
    757 					(void) zfs_error(hdl, EZFS_ZONED,
    758 					    errbuf);
    759 					goto error;
    760 				} else if (prop == ZFS_PROP_SHARENFS ||
    761 				    prop == ZFS_PROP_SHARESMB) {
    762 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    763 					    "'%s' cannot be set in "
    764 					    "a non-global zone"), propname);
    765 					(void) zfs_error(hdl, EZFS_ZONED,
    766 					    errbuf);
    767 					goto error;
    768 				}
    769 			} else if (getzoneid() != GLOBAL_ZONEID) {
    770 				/*
    771 				 * If zoned property is 'off', this must be in
    772 				 * a globle zone. If not, something is wrong.
    773 				 */
    774 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    775 				    "'%s' cannot be set while dataset "
    776 				    "'zoned' property is set"), propname);
    777 				(void) zfs_error(hdl, EZFS_ZONED, errbuf);
    778 				goto error;
    779 			}
    780 
    781 			/*
    782 			 * At this point, it is legitimate to set the
    783 			 * property. Now we want to make sure that the
    784 			 * property value is valid if it is sharenfs.
    785 			 */
    786 			if ((prop == ZFS_PROP_SHARENFS ||
    787 			    prop == ZFS_PROP_SHARESMB) &&
    788 			    strcmp(strval, "on") != 0 &&
    789 			    strcmp(strval, "off") != 0) {
    790 				zfs_share_proto_t proto;
    791 
    792 				if (prop == ZFS_PROP_SHARESMB)
    793 					proto = PROTO_SMB;
    794 				else
    795 					proto = PROTO_NFS;
    796 
    797 				/*
    798 				 * Must be an valid sharing protocol
    799 				 * option string so init the libshare
    800 				 * in order to enable the parser and
    801 				 * then parse the options. We use the
    802 				 * control API since we don't care about
    803 				 * the current configuration and don't
    804 				 * want the overhead of loading it
    805 				 * until we actually do something.
    806 				 */
    807 
    808 				if (zfs_init_libshare(hdl,
    809 				    SA_INIT_CONTROL_API) != SA_OK) {
    810 					/*
    811 					 * An error occurred so we can't do
    812 					 * anything
    813 					 */
    814 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    815 					    "'%s' cannot be set: problem "
    816 					    "in share initialization"),
    817 					    propname);
    818 					(void) zfs_error(hdl, EZFS_BADPROP,
    819 					    errbuf);
    820 					goto error;
    821 				}
    822 
    823 				if (zfs_parse_options(strval, proto) != SA_OK) {
    824 					/*
    825 					 * There was an error in parsing so
    826 					 * deal with it by issuing an error
    827 					 * message and leaving after
    828 					 * uninitializing the the libshare
    829 					 * interface.
    830 					 */
    831 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    832 					    "'%s' cannot be set to invalid "
    833 					    "options"), propname);
    834 					(void) zfs_error(hdl, EZFS_BADPROP,
    835 					    errbuf);
    836 					zfs_uninit_libshare(hdl);
    837 					goto error;
    838 				}
    839 				zfs_uninit_libshare(hdl);
    840 			}
    841 
    842 			break;
    843 		case ZFS_PROP_UTF8ONLY:
    844 			chosen_utf = (int)intval;
    845 			break;
    846 		case ZFS_PROP_NORMALIZE:
    847 			chosen_normal = (int)intval;
    848 			break;
    849 		}
    850 
    851 		/*
    852 		 * For changes to existing volumes, we have some additional
    853 		 * checks to enforce.
    854 		 */
    855 		if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
    856 			uint64_t volsize = zfs_prop_get_int(zhp,
    857 			    ZFS_PROP_VOLSIZE);
    858 			uint64_t blocksize = zfs_prop_get_int(zhp,
    859 			    ZFS_PROP_VOLBLOCKSIZE);
    860 			char buf[64];
    861 
    862 			switch (prop) {
    863 			case ZFS_PROP_RESERVATION:
    864 			case ZFS_PROP_REFRESERVATION:
    865 				if (intval > volsize) {
    866 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    867 					    "'%s' is greater than current "
    868 					    "volume size"), propname);
    869 					(void) zfs_error(hdl, EZFS_BADPROP,
    870 					    errbuf);
    871 					goto error;
    872 				}
    873 				break;
    874 
    875 			case ZFS_PROP_VOLSIZE:
    876 				if (intval % blocksize != 0) {
    877 					zfs_nicenum(blocksize, buf,
    878 					    sizeof (buf));
    879 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    880 					    "'%s' must be a multiple of "
    881 					    "volume block size (%s)"),
    882 					    propname, buf);
    883 					(void) zfs_error(hdl, EZFS_BADPROP,
    884 					    errbuf);
    885 					goto error;
    886 				}
    887 
    888 				if (intval == 0) {
    889 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    890 					    "'%s' cannot be zero"),
    891 					    propname);
    892 					(void) zfs_error(hdl, EZFS_BADPROP,
    893 					    errbuf);
    894 					goto error;
    895 				}
    896 				break;
    897 			}
    898 		}
    899 	}
    900 
    901 	/*
    902 	 * If normalization was chosen, but no UTF8 choice was made,
    903 	 * enforce rejection of non-UTF8 names.
    904 	 *
    905 	 * If normalization was chosen, but rejecting non-UTF8 names
    906 	 * was explicitly not chosen, it is an error.
    907 	 */
    908 	if (chosen_normal > 0 && chosen_utf < 0) {
    909 		if (nvlist_add_uint64(ret,
    910 		    zfs_prop_to_name(ZFS_PROP_UTF8ONLY), 1) != 0) {
    911 			(void) no_memory(hdl);
    912 			goto error;
    913 		}
    914 	} else if (chosen_normal > 0 && chosen_utf == 0) {
    915 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
    916 		    "'%s' must be set 'on' if normalization chosen"),
    917 		    zfs_prop_to_name(ZFS_PROP_UTF8ONLY));
    918 		(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
    919 		goto error;
    920 	}
    921 
    922 	/*
    923 	 * If this is an existing volume, and someone is setting the volsize,
    924 	 * make sure that it matches the reservation, or add it if necessary.
    925 	 */
    926 	if (zhp != NULL && type == ZFS_TYPE_VOLUME &&
    927 	    nvlist_lookup_uint64(ret, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
    928 	    &intval) == 0) {
    929 		uint64_t old_volsize = zfs_prop_get_int(zhp,
    930 		    ZFS_PROP_VOLSIZE);
    931 		uint64_t old_reservation;
    932 		uint64_t new_reservation;
    933 		zfs_prop_t resv_prop;
    934 
    935 		if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
    936 			goto error;
    937 		old_reservation = zfs_prop_get_int(zhp, resv_prop);
    938 
    939 		if (old_volsize == old_reservation &&
    940 		    nvlist_lookup_uint64(ret, zfs_prop_to_name(resv_prop),
    941 		    &new_reservation) != 0) {
    942 			if (nvlist_add_uint64(ret,
    943 			    zfs_prop_to_name(resv_prop), intval) != 0) {
    944 				(void) no_memory(hdl);
    945 				goto error;
    946 			}
    947 		}
    948 	}
    949 	return (ret);
    950 
    951 error:
    952 	nvlist_free(ret);
    953 	return (NULL);
    954 }
    955 
    956 static int
    957 zfs_get_perm_who(const char *who, zfs_deleg_who_type_t *who_type,
    958     uint64_t *ret_who)
    959 {
    960 	struct passwd *pwd;
    961 	struct group *grp;
    962 	uid_t id;
    963 
    964 	if (*who_type == ZFS_DELEG_EVERYONE || *who_type == ZFS_DELEG_CREATE ||
    965 	    *who_type == ZFS_DELEG_NAMED_SET) {
    966 		*ret_who = -1;
    967 		return (0);
    968 	}
    969 	if (who == NULL && !(*who_type == ZFS_DELEG_EVERYONE))
    970 		return (EZFS_BADWHO);
    971 
    972 	if (*who_type == ZFS_DELEG_WHO_UNKNOWN &&
    973 	    strcmp(who, "everyone") == 0) {
    974 		*ret_who = -1;
    975 		*who_type = ZFS_DELEG_EVERYONE;
    976 		return (0);
    977 	}
    978 
    979 	pwd = getpwnam(who);
    980 	grp = getgrnam(who);
    981 
    982 	if ((*who_type == ZFS_DELEG_USER) && pwd) {
    983 		*ret_who = pwd->pw_uid;
    984 	} else if ((*who_type == ZFS_DELEG_GROUP) && grp) {
    985 		*ret_who = grp->gr_gid;
    986 	} else if (pwd) {
    987 		*ret_who = pwd->pw_uid;
    988 		*who_type = ZFS_DELEG_USER;
    989 	} else if (grp) {
    990 		*ret_who = grp->gr_gid;
    991 		*who_type = ZFS_DELEG_GROUP;
    992 	} else {
    993 		char *end;
    994 
    995 		id = strtol(who, &end, 10);
    996 		if (errno != 0 || *end != '\0') {
    997 			return (EZFS_BADWHO);
    998 		} else {
    999 			*ret_who = id;
   1000 			if (*who_type == ZFS_DELEG_WHO_UNKNOWN)
   1001 				*who_type = ZFS_DELEG_USER;
   1002 		}
   1003 	}
   1004 
   1005 	return (0);
   1006 }
   1007 
   1008 static void
   1009 zfs_perms_add_to_nvlist(nvlist_t *who_nvp, char *name, nvlist_t *perms_nvp)
   1010 {
   1011 	if (perms_nvp != NULL) {
   1012 		verify(nvlist_add_nvlist(who_nvp,
   1013 		    name, perms_nvp) == 0);
   1014 	} else {
   1015 		verify(nvlist_add_boolean(who_nvp, name) == 0);
   1016 	}
   1017 }
   1018 
   1019 static void
   1020 helper(zfs_deleg_who_type_t who_type, uint64_t whoid, char *whostr,
   1021     zfs_deleg_inherit_t inherit, nvlist_t *who_nvp, nvlist_t *perms_nvp,
   1022     nvlist_t *sets_nvp)
   1023 {
   1024 	boolean_t do_perms, do_sets;
   1025 	char name[ZFS_MAX_DELEG_NAME];
   1026 
   1027 	do_perms = (nvlist_next_nvpair(perms_nvp, NULL) != NULL);
   1028 	do_sets = (nvlist_next_nvpair(sets_nvp, NULL) != NULL);
   1029 
   1030 	if (!do_perms && !do_sets)
   1031 		do_perms = do_sets = B_TRUE;
   1032 
   1033 	if (do_perms) {
   1034 		zfs_deleg_whokey(name, who_type, inherit,
   1035 		    (who_type == ZFS_DELEG_NAMED_SET) ?
   1036 		    whostr : (void *)&whoid);
   1037 		zfs_perms_add_to_nvlist(who_nvp, name, perms_nvp);
   1038 	}
   1039 	if (do_sets) {
   1040 		zfs_deleg_whokey(name, toupper(who_type), inherit,
   1041 		    (who_type == ZFS_DELEG_NAMED_SET) ?
   1042 		    whostr : (void *)&whoid);
   1043 		zfs_perms_add_to_nvlist(who_nvp, name, sets_nvp);
   1044 	}
   1045 }
   1046 
   1047 static void
   1048 zfs_perms_add_who_nvlist(nvlist_t *who_nvp, uint64_t whoid, void *whostr,
   1049     nvlist_t *perms_nvp, nvlist_t *sets_nvp,
   1050     zfs_deleg_who_type_t who_type, zfs_deleg_inherit_t inherit)
   1051 {
   1052 	if (who_type == ZFS_DELEG_NAMED_SET || who_type == ZFS_DELEG_CREATE) {
   1053 		helper(who_type, whoid, whostr, 0,
   1054 		    who_nvp, perms_nvp, sets_nvp);
   1055 	} else {
   1056 		if (inherit & ZFS_DELEG_PERM_LOCAL) {
   1057 			helper(who_type, whoid, whostr, ZFS_DELEG_LOCAL,
   1058 			    who_nvp, perms_nvp, sets_nvp);
   1059 		}
   1060 		if (inherit & ZFS_DELEG_PERM_DESCENDENT) {
   1061 			helper(who_type, whoid, whostr, ZFS_DELEG_DESCENDENT,
   1062 			    who_nvp, perms_nvp, sets_nvp);
   1063 		}
   1064 	}
   1065 }
   1066 
   1067 /*
   1068  * Construct nvlist to pass down to kernel for setting/removing permissions.
   1069  *
   1070  * The nvlist is constructed as a series of nvpairs with an optional embedded
   1071  * nvlist of permissions to remove or set.  The topmost nvpairs are the actual
   1072  * base attribute named stored in the dsl.
   1073  * Arguments:
   1074  *
   1075  * whostr:   is a comma separated list of users, groups, or a single set name.
   1076  *           whostr may be null for everyone or create perms.
   1077  * who_type: is the type of entry in whostr.  Typically this will be
   1078  *           ZFS_DELEG_WHO_UNKNOWN.
   1079  * perms:    common separated list of permissions.  May be null if user
   1080  *           is requested to remove permissions by who.
   1081  * inherit:  Specifies the inheritance of the permissions.  Will be either
   1082  *           ZFS_DELEG_PERM_LOCAL and/or  ZFS_DELEG_PERM_DESCENDENT.
   1083  * nvp       The constructed nvlist to pass to zfs_perm_set().
   1084  *           The output nvp will look something like this.
   1085  *              ul$1234 -> {create ; destroy }
   1086  *              Ul$1234 -> { @myset }
   1087  *              s-$@myset - { snapshot; checksum; compression }
   1088  */
   1089 int
   1090 zfs_build_perms(zfs_handle_t *zhp, char *whostr, char *perms,
   1091     zfs_deleg_who_type_t who_type, zfs_deleg_inherit_t inherit, nvlist_t **nvp)
   1092 {
   1093 	nvlist_t *who_nvp;
   1094 	nvlist_t *perms_nvp = NULL;
   1095 	nvlist_t *sets_nvp = NULL;
   1096 	char errbuf[1024];
   1097 	char *who_tok, *perm;
   1098 	int error;
   1099 
   1100 	*nvp = NULL;
   1101 
   1102 	if (perms) {
   1103 		if ((error = nvlist_alloc(&perms_nvp,
   1104 		    NV_UNIQUE_NAME, 0)) != 0) {
   1105 			return (1);
   1106 		}