xref: /titanic_52/usr/src/lib/libzfs/common/libzfs_dataset.c (revision 3b862e9a9ce59d5dbf0177b9eb293109fde6bf36)
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 2009 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/mount.h>
42 #include <sys/avl.h>
43 #include <priv.h>
44 #include <pwd.h>
45 #include <grp.h>
46 #include <stddef.h>
47 #include <ucred.h>
48 #include <idmap.h>
49 #include <aclutils.h>
50 #include <directory.h>
51 
52 #include <sys/spa.h>
53 #include <sys/zap.h>
54 #include <libzfs.h>
55 
56 #include "zfs_namecheck.h"
57 #include "zfs_prop.h"
58 #include "libzfs_impl.h"
59 #include "zfs_deleg.h"
60 
61 static int zvol_create_link_common(libzfs_handle_t *, const char *, int);
62 static int userquota_propname_decode(const char *propname, boolean_t zoned,
63     zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp);
64 
65 /*
66  * Given a single type (not a mask of types), return the type in a human
67  * readable form.
68  */
69 const char *
70 zfs_type_to_name(zfs_type_t type)
71 {
72 	switch (type) {
73 	case ZFS_TYPE_FILESYSTEM:
74 		return (dgettext(TEXT_DOMAIN, "filesystem"));
75 	case ZFS_TYPE_SNAPSHOT:
76 		return (dgettext(TEXT_DOMAIN, "snapshot"));
77 	case ZFS_TYPE_VOLUME:
78 		return (dgettext(TEXT_DOMAIN, "volume"));
79 	}
80 
81 	return (NULL);
82 }
83 
84 /*
85  * Given a path and mask of ZFS types, return a string describing this dataset.
86  * This is used when we fail to open a dataset and we cannot get an exact type.
87  * We guess what the type would have been based on the path and the mask of
88  * acceptable types.
89  */
90 static const char *
91 path_to_str(const char *path, int types)
92 {
93 	/*
94 	 * When given a single type, always report the exact type.
95 	 */
96 	if (types == ZFS_TYPE_SNAPSHOT)
97 		return (dgettext(TEXT_DOMAIN, "snapshot"));
98 	if (types == ZFS_TYPE_FILESYSTEM)
99 		return (dgettext(TEXT_DOMAIN, "filesystem"));
100 	if (types == ZFS_TYPE_VOLUME)
101 		return (dgettext(TEXT_DOMAIN, "volume"));
102 
103 	/*
104 	 * The user is requesting more than one type of dataset.  If this is the
105 	 * case, consult the path itself.  If we're looking for a snapshot, and
106 	 * a '@' is found, then report it as "snapshot".  Otherwise, remove the
107 	 * snapshot attribute and try again.
108 	 */
109 	if (types & ZFS_TYPE_SNAPSHOT) {
110 		if (strchr(path, '@') != NULL)
111 			return (dgettext(TEXT_DOMAIN, "snapshot"));
112 		return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT));
113 	}
114 
115 	/*
116 	 * The user has requested either filesystems or volumes.
117 	 * We have no way of knowing a priori what type this would be, so always
118 	 * report it as "filesystem" or "volume", our two primitive types.
119 	 */
120 	if (types & ZFS_TYPE_FILESYSTEM)
121 		return (dgettext(TEXT_DOMAIN, "filesystem"));
122 
123 	assert(types & ZFS_TYPE_VOLUME);
124 	return (dgettext(TEXT_DOMAIN, "volume"));
125 }
126 
127 /*
128  * Validate a ZFS path.  This is used even before trying to open the dataset, to
129  * provide a more meaningful error message.  We call zfs_error_aux() to
130  * explain exactly why the name was not valid.
131  */
132 static int
133 zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
134     boolean_t modifying)
135 {
136 	namecheck_err_t why;
137 	char what;
138 
139 	if (dataset_namecheck(path, &why, &what) != 0) {
140 		if (hdl != NULL) {
141 			switch (why) {
142 			case NAME_ERR_TOOLONG:
143 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
144 				    "name is too long"));
145 				break;
146 
147 			case NAME_ERR_LEADING_SLASH:
148 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
149 				    "leading slash in name"));
150 				break;
151 
152 			case NAME_ERR_EMPTY_COMPONENT:
153 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
154 				    "empty component in name"));
155 				break;
156 
157 			case NAME_ERR_TRAILING_SLASH:
158 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
159 				    "trailing slash in name"));
160 				break;
161 
162 			case NAME_ERR_INVALCHAR:
163 				zfs_error_aux(hdl,
164 				    dgettext(TEXT_DOMAIN, "invalid character "
165 				    "'%c' in name"), what);
166 				break;
167 
168 			case NAME_ERR_MULTIPLE_AT:
169 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
170 				    "multiple '@' delimiters in name"));
171 				break;
172 
173 			case NAME_ERR_NOLETTER:
174 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
175 				    "pool doesn't begin with a letter"));
176 				break;
177 
178 			case NAME_ERR_RESERVED:
179 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
180 				    "name is reserved"));
181 				break;
182 
183 			case NAME_ERR_DISKLIKE:
184 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
185 				    "reserved disk name"));
186 				break;
187 			}
188 		}
189 
190 		return (0);
191 	}
192 
193 	if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
194 		if (hdl != NULL)
195 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
196 			    "snapshot delimiter '@' in filesystem name"));
197 		return (0);
198 	}
199 
200 	if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) {
201 		if (hdl != NULL)
202 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
203 			    "missing '@' delimiter in snapshot name"));
204 		return (0);
205 	}
206 
207 	if (modifying && strchr(path, '%') != NULL) {
208 		if (hdl != NULL)
209 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
210 			    "invalid character %c in name"), '%');
211 		return (0);
212 	}
213 
214 	return (-1);
215 }
216 
217 int
218 zfs_name_valid(const char *name, zfs_type_t type)
219 {
220 	if (type == ZFS_TYPE_POOL)
221 		return (zpool_name_valid(NULL, B_FALSE, name));
222 	return (zfs_validate_name(NULL, name, type, B_FALSE));
223 }
224 
225 /*
226  * This function takes the raw DSL properties, and filters out the user-defined
227  * properties into a separate nvlist.
228  */
229 static nvlist_t *
230 process_user_props(zfs_handle_t *zhp, nvlist_t *props)
231 {
232 	libzfs_handle_t *hdl = zhp->zfs_hdl;
233 	nvpair_t *elem;
234 	nvlist_t *propval;
235 	nvlist_t *nvl;
236 
237 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
238 		(void) no_memory(hdl);
239 		return (NULL);
240 	}
241 
242 	elem = NULL;
243 	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
244 		if (!zfs_prop_user(nvpair_name(elem)))
245 			continue;
246 
247 		verify(nvpair_value_nvlist(elem, &propval) == 0);
248 		if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) {
249 			nvlist_free(nvl);
250 			(void) no_memory(hdl);
251 			return (NULL);
252 		}
253 	}
254 
255 	return (nvl);
256 }
257 
258 static zpool_handle_t *
259 zpool_add_handle(zfs_handle_t *zhp, const char *pool_name)
260 {
261 	libzfs_handle_t *hdl = zhp->zfs_hdl;
262 	zpool_handle_t *zph;
263 
264 	if ((zph = zpool_open_canfail(hdl, pool_name)) != NULL) {
265 		if (hdl->libzfs_pool_handles != NULL)
266 			zph->zpool_next = hdl->libzfs_pool_handles;
267 		hdl->libzfs_pool_handles = zph;
268 	}
269 	return (zph);
270 }
271 
272 static zpool_handle_t *
273 zpool_find_handle(zfs_handle_t *zhp, const char *pool_name, int len)
274 {
275 	libzfs_handle_t *hdl = zhp->zfs_hdl;
276 	zpool_handle_t *zph = hdl->libzfs_pool_handles;
277 
278 	while ((zph != NULL) &&
279 	    (strncmp(pool_name, zpool_get_name(zph), len) != 0))
280 		zph = zph->zpool_next;
281 	return (zph);
282 }
283 
284 /*
285  * Returns a handle to the pool that contains the provided dataset.
286  * If a handle to that pool already exists then that handle is returned.
287  * Otherwise, a new handle is created and added to the list of handles.
288  */
289 static zpool_handle_t *
290 zpool_handle(zfs_handle_t *zhp)
291 {
292 	char *pool_name;
293 	int len;
294 	zpool_handle_t *zph;
295 
296 	len = strcspn(zhp->zfs_name, "/@") + 1;
297 	pool_name = zfs_alloc(zhp->zfs_hdl, len);
298 	(void) strlcpy(pool_name, zhp->zfs_name, len);
299 
300 	zph = zpool_find_handle(zhp, pool_name, len);
301 	if (zph == NULL)
302 		zph = zpool_add_handle(zhp, pool_name);
303 
304 	free(pool_name);
305 	return (zph);
306 }
307 
308 void
309 zpool_free_handles(libzfs_handle_t *hdl)
310 {
311 	zpool_handle_t *next, *zph = hdl->libzfs_pool_handles;
312 
313 	while (zph != NULL) {
314 		next = zph->zpool_next;
315 		zpool_close(zph);
316 		zph = next;
317 	}
318 	hdl->libzfs_pool_handles = NULL;
319 }
320 
321 /*
322  * Utility function to gather stats (objset and zpl) for the given object.
323  */
324 static int
325 get_stats_ioctl(zfs_handle_t *zhp, zfs_cmd_t *zc)
326 {
327 	libzfs_handle_t *hdl = zhp->zfs_hdl;
328 
329 	(void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
330 
331 	while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, zc) != 0) {
332 		if (errno == ENOMEM) {
333 			if (zcmd_expand_dst_nvlist(hdl, zc) != 0) {
334 				return (-1);
335 			}
336 		} else {
337 			return (-1);
338 		}
339 	}
340 	return (0);
341 }
342 
343 static int
344 put_stats_zhdl(zfs_handle_t *zhp, zfs_cmd_t *zc)
345 {
346 	nvlist_t *allprops, *userprops;
347 
348 	zhp->zfs_dmustats = zc->zc_objset_stats; /* structure assignment */
349 
350 	if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) {
351 		return (-1);
352 	}
353 
354 	/*
355 	 * XXX Why do we store the user props separately, in addition to
356 	 * storing them in zfs_props?
357 	 */
358 	if ((userprops = process_user_props(zhp, allprops)) == NULL) {
359 		nvlist_free(allprops);
360 		return (-1);
361 	}
362 
363 	nvlist_free(zhp->zfs_props);
364 	nvlist_free(zhp->zfs_user_props);
365 
366 	zhp->zfs_props = allprops;
367 	zhp->zfs_user_props = userprops;
368 
369 	return (0);
370 }
371 
372 static int
373 get_stats(zfs_handle_t *zhp)
374 {
375 	int rc = 0;
376 	zfs_cmd_t zc = { 0 };
377 
378 	if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
379 		return (-1);
380 	if (get_stats_ioctl(zhp, &zc) != 0)
381 		rc = -1;
382 	else if (put_stats_zhdl(zhp, &zc) != 0)
383 		rc = -1;
384 	zcmd_free_nvlists(&zc);
385 	return (rc);
386 }
387 
388 /*
389  * Refresh the properties currently stored in the handle.
390  */
391 void
392 zfs_refresh_properties(zfs_handle_t *zhp)
393 {
394 	(void) get_stats(zhp);
395 }
396 
397 /*
398  * Makes a handle from the given dataset name.  Used by zfs_open() and
399  * zfs_iter_* to create child handles on the fly.
400  */
401 static int
402 make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc)
403 {
404 	if (put_stats_zhdl(zhp, zc) != 0)
405 		return (-1);
406 
407 	/*
408 	 * We've managed to open the dataset and gather statistics.  Determine
409 	 * the high-level type.
410 	 */
411 	if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
412 		zhp->zfs_head_type = ZFS_TYPE_VOLUME;
413 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
414 		zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM;
415 	else
416 		abort();
417 
418 	if (zhp->zfs_dmustats.dds_is_snapshot)
419 		zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
420 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
421 		zhp->zfs_type = ZFS_TYPE_VOLUME;
422 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
423 		zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
424 	else
425 		abort();	/* we should never see any other types */
426 
427 	zhp->zpool_hdl = zpool_handle(zhp);
428 	return (0);
429 }
430 
431 zfs_handle_t *
432 make_dataset_handle(libzfs_handle_t *hdl, const char *path)
433 {
434 	zfs_cmd_t zc = { 0 };
435 
436 	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
437 
438 	if (zhp == NULL)
439 		return (NULL);
440 
441 	zhp->zfs_hdl = hdl;
442 	(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
443 	if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) {
444 		free(zhp);
445 		return (NULL);
446 	}
447 	if (get_stats_ioctl(zhp, &zc) == -1) {
448 		zcmd_free_nvlists(&zc);
449 		free(zhp);
450 		return (NULL);
451 	}
452 	if (make_dataset_handle_common(zhp, &zc) == -1) {
453 		free(zhp);
454 		zhp = NULL;
455 	}
456 	zcmd_free_nvlists(&zc);
457 	return (zhp);
458 }
459 
460 static zfs_handle_t *
461 make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
462 {
463 	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
464 
465 	if (zhp == NULL)
466 		return (NULL);
467 
468 	zhp->zfs_hdl = hdl;
469 	(void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name));
470 	if (make_dataset_handle_common(zhp, zc) == -1) {
471 		free(zhp);
472 		return (NULL);
473 	}
474 	return (zhp);
475 }
476 
477 /*
478  * Opens the given snapshot, filesystem, or volume.   The 'types'
479  * argument is a mask of acceptable types.  The function will print an
480  * appropriate error message and return NULL if it can't be opened.
481  */
482 zfs_handle_t *
483 zfs_open(libzfs_handle_t *hdl, const char *path, int types)
484 {
485 	zfs_handle_t *zhp;
486 	char errbuf[1024];
487 
488 	(void) snprintf(errbuf, sizeof (errbuf),
489 	    dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
490 
491 	/*
492 	 * Validate the name before we even try to open it.
493 	 */
494 	if (!zfs_validate_name(hdl, path, ZFS_TYPE_DATASET, B_FALSE)) {
495 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
496 		    "invalid dataset name"));
497 		(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
498 		return (NULL);
499 	}
500 
501 	/*
502 	 * Try to get stats for the dataset, which will tell us if it exists.
503 	 */
504 	errno = 0;
505 	if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
506 		(void) zfs_standard_error(hdl, errno, errbuf);
507 		return (NULL);
508 	}
509 
510 	if (!(types & zhp->zfs_type)) {
511 		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
512 		zfs_close(zhp);
513 		return (NULL);
514 	}
515 
516 	return (zhp);
517 }
518 
519 /*
520  * Release a ZFS handle.  Nothing to do but free the associated memory.
521  */
522 void
523 zfs_close(zfs_handle_t *zhp)
524 {
525 	if (zhp->zfs_mntopts)
526 		free(zhp->zfs_mntopts);
527 	nvlist_free(zhp->zfs_props);
528 	nvlist_free(zhp->zfs_user_props);
529 	free(zhp);
530 }
531 
532 typedef struct mnttab_node {
533 	struct mnttab mtn_mt;
534 	avl_node_t mtn_node;
535 } mnttab_node_t;
536 
537 static int
538 libzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
539 {
540 	const mnttab_node_t *mtn1 = arg1;
541 	const mnttab_node_t *mtn2 = arg2;
542 	int rv;
543 
544 	rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
545 
546 	if (rv == 0)
547 		return (0);
548 	return (rv > 0 ? 1 : -1);
549 }
550 
551 void
552 libzfs_mnttab_init(libzfs_handle_t *hdl)
553 {
554 	assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0);
555 	avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare,
556 	    sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node));
557 }
558 
559 void
560 libzfs_mnttab_update(libzfs_handle_t *hdl)
561 {
562 	struct mnttab entry;
563 
564 	rewind(hdl->libzfs_mnttab);
565 	while (getmntent(hdl->libzfs_mnttab, &entry) == 0) {
566 		mnttab_node_t *mtn;
567 
568 		if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
569 			continue;
570 		mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
571 		mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special);
572 		mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp);
573 		mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype);
574 		mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts);
575 		avl_add(&hdl->libzfs_mnttab_cache, mtn);
576 	}
577 }
578 
579 void
580 libzfs_mnttab_fini(libzfs_handle_t *hdl)
581 {
582 	void *cookie = NULL;
583 	mnttab_node_t *mtn;
584 
585 	while (mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie)) {
586 		free(mtn->mtn_mt.mnt_special);
587 		free(mtn->mtn_mt.mnt_mountp);
588 		free(mtn->mtn_mt.mnt_fstype);
589 		free(mtn->mtn_mt.mnt_mntopts);
590 		free(mtn);
591 	}
592 	avl_destroy(&hdl->libzfs_mnttab_cache);
593 }
594 
595 void
596 libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable)
597 {
598 	hdl->libzfs_mnttab_enable = enable;
599 }
600 
601 int
602 libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
603     struct mnttab *entry)
604 {
605 	mnttab_node_t find;
606 	mnttab_node_t *mtn;
607 
608 	if (!hdl->libzfs_mnttab_enable) {
609 		struct mnttab srch = { 0 };
610 
611 		if (avl_numnodes(&hdl->libzfs_mnttab_cache))
612 			libzfs_mnttab_fini(hdl);
613 		rewind(hdl->libzfs_mnttab);
614 		srch.mnt_special = (char *)fsname;
615 		srch.mnt_fstype = MNTTYPE_ZFS;
616 		if (getmntany(hdl->libzfs_mnttab, entry, &srch) == 0)
617 			return (0);
618 		else
619 			return (ENOENT);
620 	}
621 
622 	if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0)
623 		libzfs_mnttab_update(hdl);
624 
625 	find.mtn_mt.mnt_special = (char *)fsname;
626 	mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL);
627 	if (mtn) {
628 		*entry = mtn->mtn_mt;
629 		return (0);
630 	}
631 	return (ENOENT);
632 }
633 
634 void
635 libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,
636     const char *mountp, const char *mntopts)
637 {
638 	mnttab_node_t *mtn;
639 
640 	if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0)
641 		return;
642 	mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
643 	mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special);
644 	mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp);
645 	mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS);
646 	mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts);
647 	avl_add(&hdl->libzfs_mnttab_cache, mtn);
648 }
649 
650 void
651 libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
652 {
653 	mnttab_node_t find;
654 	mnttab_node_t *ret;
655 
656 	find.mtn_mt.mnt_special = (char *)fsname;
657 	if (ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL)) {
658 		avl_remove(&hdl->libzfs_mnttab_cache, ret);
659 		free(ret->mtn_mt.mnt_special);
660 		free(ret->mtn_mt.mnt_mountp);
661 		free(ret->mtn_mt.mnt_fstype);
662 		free(ret->mtn_mt.mnt_mntopts);
663 		free(ret);
664 	}
665 }
666 
667 int
668 zfs_spa_version(zfs_handle_t *zhp, int *spa_version)
669 {
670 	zpool_handle_t *zpool_handle = zhp->zpool_hdl;
671 
672 	if (zpool_handle == NULL)
673 		return (-1);
674 
675 	*spa_version = zpool_get_prop_int(zpool_handle,
676 	    ZPOOL_PROP_VERSION, NULL);
677 	return (0);
678 }
679 
680 /*
681  * The choice of reservation property depends on the SPA version.
682  */
683 static int
684 zfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop)
685 {
686 	int spa_version;
687 
688 	if (zfs_spa_version(zhp, &spa_version) < 0)
689 		return (-1);
690 
691 	if (spa_version >= SPA_VERSION_REFRESERVATION)
692 		*resv_prop = ZFS_PROP_REFRESERVATION;
693 	else
694 		*resv_prop = ZFS_PROP_RESERVATION;
695 
696 	return (0);
697 }
698 
699 /*
700  * Given an nvlist of properties to set, validates that they are correct, and
701  * parses any numeric properties (index, boolean, etc) if they are specified as
702  * strings.
703  */
704 nvlist_t *
705 zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
706     uint64_t zoned, zfs_handle_t *zhp, const char *errbuf)
707 {
708 	nvpair_t *elem;
709 	uint64_t intval;
710 	char *strval;
711 	zfs_prop_t prop;
712 	nvlist_t *ret;
713 	int chosen_normal = -1;
714 	int chosen_utf = -1;
715 
716 	if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) {
717 		(void) no_memory(hdl);
718 		return (NULL);
719 	}
720 
721 	/*
722 	 * Make sure this property is valid and applies to this type.
723 	 */
724 
725 	elem = NULL;
726 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
727 		const char *propname = nvpair_name(elem);
728 
729 		prop = zfs_name_to_prop(propname);
730 		if (prop == ZPROP_INVAL && zfs_prop_user(propname)) {
731 			/*
732 			 * This is a user property: make sure it's a
733 			 * string, and that it's less than ZAP_MAXNAMELEN.
734 			 */
735 			if (nvpair_type(elem) != DATA_TYPE_STRING) {
736 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
737 				    "'%s' must be a string"), propname);
738 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
739 				goto error;
740 			}
741 
742 			if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
743 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
744 				    "property name '%s' is too long"),
745 				    propname);
746 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
747 				goto error;
748 			}
749 
750 			(void) nvpair_value_string(elem, &strval);
751 			if (nvlist_add_string(ret, propname, strval) != 0) {
752 				(void) no_memory(hdl);
753 				goto error;
754 			}
755 			continue;
756 		}
757 
758 		/*
759 		 * Currently, only user properties can be modified on
760 		 * snapshots.
761 		 */
762 		if (type == ZFS_TYPE_SNAPSHOT) {
763 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
764 			    "this property can not be modified for snapshots"));
765 			(void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
766 			goto error;
767 		}
768 
769 		if (prop == ZPROP_INVAL && zfs_prop_userquota(propname)) {
770 			zfs_userquota_prop_t uqtype;
771 			char newpropname[128];
772 			char domain[128];
773 			uint64_t rid;
774 			uint64_t valary[3];
775 
776 			if (userquota_propname_decode(propname, zoned,
777 			    &uqtype, domain, sizeof (domain), &rid) != 0) {
778 				zfs_error_aux(hdl,
779 				    dgettext(TEXT_DOMAIN,
780 				    "'%s' has an invalid user/group name"),
781 				    propname);
782 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
783 				goto error;
784 			}
785 
786 			if (uqtype != ZFS_PROP_USERQUOTA &&
787 			    uqtype != ZFS_PROP_GROUPQUOTA) {
788 				zfs_error_aux(hdl,
789 				    dgettext(TEXT_DOMAIN, "'%s' is readonly"),
790 				    propname);
791 				(void) zfs_error(hdl, EZFS_PROPREADONLY,
792 				    errbuf);
793 				goto error;
794 			}
795 
796 			if (nvpair_type(elem) == DATA_TYPE_STRING) {
797 				(void) nvpair_value_string(elem, &strval);
798 				if (strcmp(strval, "none") == 0) {
799 					intval = 0;
800 				} else if (zfs_nicestrtonum(hdl,
801 				    strval, &intval) != 0) {
802 					(void) zfs_error(hdl,
803 					    EZFS_BADPROP, errbuf);
804 					goto error;
805 				}
806 			} else if (nvpair_type(elem) ==
807 			    DATA_TYPE_UINT64) {
808 				(void) nvpair_value_uint64(elem, &intval);
809 				if (intval == 0) {
810 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
811 					    "use 'none' to disable "
812 					    "userquota/groupquota"));
813 					goto error;
814 				}
815 			} else {
816 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
817 				    "'%s' must be a number"), propname);
818 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
819 				goto error;
820 			}
821 
822 			(void) snprintf(newpropname, sizeof (newpropname),
823 			    "%s%s", zfs_userquota_prop_prefixes[uqtype],
824 			    domain);
825 			valary[0] = uqtype;
826 			valary[1] = rid;
827 			valary[2] = intval;
828 			if (nvlist_add_uint64_array(ret, newpropname,
829 			    valary, 3) != 0) {
830 				(void) no_memory(hdl);
831 				goto error;
832 			}
833 			continue;
834 		}
835 
836 		if (prop == ZPROP_INVAL) {
837 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
838 			    "invalid property '%s'"), propname);
839 			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
840 			goto error;
841 		}
842 
843 		if (!zfs_prop_valid_for_type(prop, type)) {
844 			zfs_error_aux(hdl,
845 			    dgettext(TEXT_DOMAIN, "'%s' does not "
846 			    "apply to datasets of this type"), propname);
847 			(void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
848 			goto error;
849 		}
850 
851 		if (zfs_prop_readonly(prop) &&
852 		    (!zfs_prop_setonce(prop) || zhp != NULL)) {
853 			zfs_error_aux(hdl,
854 			    dgettext(TEXT_DOMAIN, "'%s' is readonly"),
855 			    propname);
856 			(void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
857 			goto error;
858 		}
859 
860 		if (zprop_parse_value(hdl, elem, prop, type, ret,
861 		    &strval, &intval, errbuf) != 0)
862 			goto error;
863 
864 		/*
865 		 * Perform some additional checks for specific properties.
866 		 */
867 		switch (prop) {
868 		case ZFS_PROP_VERSION:
869 		{
870 			int version;
871 
872 			if (zhp == NULL)
873 				break;
874 			version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
875 			if (intval < version) {
876 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
877 				    "Can not downgrade; already at version %u"),
878 				    version);
879 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
880 				goto error;
881 			}
882 			break;
883 		}
884 
885 		case ZFS_PROP_RECORDSIZE:
886 		case ZFS_PROP_VOLBLOCKSIZE:
887 			/* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */
888 			if (intval < SPA_MINBLOCKSIZE ||
889 			    intval > SPA_MAXBLOCKSIZE || !ISP2(intval)) {
890 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
891 				    "'%s' must be power of 2 from %u "
892 				    "to %uk"), propname,
893 				    (uint_t)SPA_MINBLOCKSIZE,
894 				    (uint_t)SPA_MAXBLOCKSIZE >> 10);
895 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
896 				goto error;
897 			}
898 			break;
899 
900 		case ZFS_PROP_SHAREISCSI:
901 			if (strcmp(strval, "off") != 0 &&
902 			    strcmp(strval, "on") != 0 &&
903 			    strcmp(strval, "type=disk") != 0) {
904 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
905 				    "'%s' must be 'on', 'off', or 'type=disk'"),
906 				    propname);
907 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
908 				goto error;
909 			}
910 
911 			break;
912 
913 		case ZFS_PROP_MOUNTPOINT:
914 		{
915 			namecheck_err_t why;
916 
917 			if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 ||
918 			    strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0)
919 				break;
920 
921 			if (mountpoint_namecheck(strval, &why)) {
922 				switch (why) {
923 				case NAME_ERR_LEADING_SLASH:
924 					zfs_error_aux(hdl,
925 					    dgettext(TEXT_DOMAIN,
926 					    "'%s' must be an absolute path, "
927 					    "'none', or 'legacy'"), propname);
928 					break;
929 				case NAME_ERR_TOOLONG:
930 					zfs_error_aux(hdl,
931 					    dgettext(TEXT_DOMAIN,
932 					    "component of '%s' is too long"),
933 					    propname);
934 					break;
935 				}
936 				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
937 				goto error;
938 			}
939 		}
940 
941 			/*FALLTHRU*/
942 
943 		case ZFS_PROP_SHARESMB:
944 		case ZFS_PROP_SHARENFS:
945 			/*
946 			 * For the mountpoint and sharenfs or sharesmb
947 			 * properties, check if it can be set in a
948 			 * global/non-global zone based on
949 			 * the zoned property value:
950 			 *
951 			 *		global zone	    non-global zone
952 			 * --------------------------------------------------
953 			 * zoned=on	mountpoint (no)	    mountpoint (yes)
954 			 *		sharenfs (no)	    sharenfs (no)
955 			 *		sharesmb (no)	    sharesmb (no)
956 			 *
957 			 * zoned=off	mountpoint (yes)	N/A
958 			 *		sharenfs (yes)
959 			 *		sharesmb (yes)
960 			 */
961 			if (zoned) {
962 				if (getzoneid() == GLOBAL_ZONEID) {
963 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
964 					    "'%s' cannot be set on "
965 					    "dataset in a non-global zone"),
966 					    propname);
967 					(void) zfs_error(hdl, EZFS_ZONED,
968 					    errbuf);
969 					goto error;
970 				} else if (prop == ZFS_PROP_SHARENFS ||
971 				    prop == ZFS_PROP_SHARESMB) {
972 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
973 					    "'%s' cannot be set in "
974 					    "a non-global zone"), propname);
975 					(void) zfs_error(hdl, EZFS_ZONED,
976 					    errbuf);
977 					goto error;
978 				}
979 			} else if (getzoneid() != GLOBAL_ZONEID) {
980 				/*
981 				 * If zoned property is 'off', this must be in
982 				 * a global zone. If not, something is wrong.
983 				 */
984 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
985 				    "'%s' cannot be set while dataset "
986 				    "'zoned' property is set"), propname);
987 				(void) zfs_error(hdl, EZFS_ZONED, errbuf);
988 				goto error;
989 			}
990 
991 			/*
992 			 * At this point, it is legitimate to set the
993 			 * property. Now we want to make sure that the
994 			 * property value is valid if it is sharenfs.
995 			 */
996 			if ((prop == ZFS_PROP_SHARENFS ||
997 			    prop == ZFS_PROP_SHARESMB) &&
998 			    strcmp(strval, "on") != 0 &&
999 			    strcmp(strval, "off") != 0) {
1000 				zfs_share_proto_t proto;
1001 
1002 				if (prop == ZFS_PROP_SHARESMB)
1003 					proto = PROTO_SMB;
1004 				else
1005 					proto = PROTO_NFS;
1006 
1007 				/*
1008 				 * Must be an valid sharing protocol
1009 				 * option string so init the libshare
1010 				 * in order to enable the parser and
1011 				 * then parse the options. We use the
1012 				 * control API since we don't care about
1013 				 * the current configuration and don't
1014 				 * want the overhead of loading it
1015 				 * until we actually do something.
1016 				 */
1017 
1018 				if (zfs_init_libshare(hdl,
1019 				    SA_INIT_CONTROL_API) != SA_OK) {
1020 					/*
1021 					 * An error occurred so we can't do
1022 					 * anything
1023 					 */
1024 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1025 					    "'%s' cannot be set: problem "
1026 					    "in share initialization"),
1027 					    propname);
1028 					(void) zfs_error(hdl, EZFS_BADPROP,
1029 					    errbuf);
1030 					goto error;
1031 				}
1032 
1033 				if (zfs_parse_options(strval, proto) != SA_OK) {
1034 					/*
1035 					 * There was an error in parsing so
1036 					 * deal with it by issuing an error
1037 					 * message and leaving after
1038 					 * uninitializing the the libshare
1039 					 * interface.
1040 					 */
1041 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1042 					    "'%s' cannot be set to invalid "
1043 					    "options"), propname);
1044 					(void) zfs_error(hdl, EZFS_BADPROP,
1045 					    errbuf);
1046 					zfs_uninit_libshare(hdl);
1047 					goto error;
1048 				}
1049 				zfs_uninit_libshare(hdl);
1050 			}
1051 
1052 			break;
1053 		case ZFS_PROP_UTF8ONLY:
1054 			chosen_utf = (int)intval;
1055 			break;
1056 		case ZFS_PROP_NORMALIZE:
1057 			chosen_normal = (int)intval;
1058 			break;
1059 		}
1060 
1061 		/*
1062 		 * For changes to existing volumes, we have some additional
1063 		 * checks to enforce.
1064 		 */
1065 		if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
1066 			uint64_t volsize = zfs_prop_get_int(zhp,
1067 			    ZFS_PROP_VOLSIZE);
1068 			uint64_t blocksize = zfs_prop_get_int(zhp,
1069 			    ZFS_PROP_VOLBLOCKSIZE);
1070 			char buf[64];
1071 
1072 			switch (prop) {
1073 			case ZFS_PROP_RESERVATION:
1074 			case ZFS_PROP_REFRESERVATION:
1075 				if (intval > volsize) {
1076 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1077 					    "'%s' is greater than current "
1078 					    "volume size"), propname);
1079 					(void) zfs_error(hdl, EZFS_BADPROP,
1080 					    errbuf);
1081 					goto error;
1082 				}
1083 				break;
1084 
1085 			case ZFS_PROP_VOLSIZE:
1086 				if (intval % blocksize != 0) {
1087 					zfs_nicenum(blocksize, buf,
1088 					    sizeof (buf));
1089 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1090 					    "'%s' must be a multiple of "
1091 					    "volume block size (%s)"),
1092 					    propname, buf);
1093 					(void) zfs_error(hdl, EZFS_BADPROP,
1094 					    errbuf);
1095 					goto error;
1096 				}
1097 
1098 				if (intval == 0) {
1099 					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1100 					    "'%s' cannot be zero"),
1101 					    propname);
1102 					(void) zfs_error(hdl, EZFS_BADPROP,
1103 					    errbuf);
1104 					goto error;
1105 				}
1106 				break;
1107 			}
1108 		}
1109 	}
1110 
1111 	/*
1112 	 * If normalization was chosen, but no UTF8 choice was made,
1113 	 * enforce rejection of non-UTF8 names.
1114 	 *
1115 	 * If normalization was chosen, but rejecting non-UTF8 names
1116 	 * was explicitly not chosen, it is an error.
1117 	 */
1118 	if (chosen_normal > 0 && chosen_utf < 0) {
1119 		if (nvlist_add_uint64(ret,
1120 		    zfs_prop_to_name(ZFS_PROP_UTF8ONLY), 1) != 0) {
1121 			(void) no_memory(hdl);
1122 			goto error;
1123 		}
1124 	} else if (chosen_normal > 0 && chosen_utf == 0) {
1125 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1126 		    "'%s' must be set 'on' if normalization chosen"),
1127 		    zfs_prop_to_name(ZFS_PROP_UTF8ONLY));
1128 		(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1129 		goto error;
1130 	}
1131 
1132 	/*
1133 	 * If this is an existing volume, and someone is setting the volsize,
1134 	 * make sure that it matches the reservation, or add it if necessary.
1135 	 */
1136 	if (zhp != NULL && type == ZFS_TYPE_VOLUME &&
1137 	    nvlist_lookup_uint64(ret, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1138 	    &intval) == 0) {
1139 		uint64_t old_volsize = zfs_prop_get_int(zhp,
1140 		    ZFS_PROP_VOLSIZE);
1141 		uint64_t old_reservation;
1142 		uint64_t new_reservation;
1143 		zfs_prop_t resv_prop;
1144 
1145 		if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
1146 			goto error;
1147 		old_reservation = zfs_prop_get_int(zhp, resv_prop);
1148 
1149 		if (old_volsize == old_reservation &&
1150 		    nvlist_lookup_uint64(ret, zfs_prop_to_name(resv_prop),
1151 		    &new_reservation) != 0) {
1152 			if (nvlist_add_uint64(ret,
1153 			    zfs_prop_to_name(resv_prop), intval) != 0) {
1154 				(void) no_memory(hdl);
1155 				goto error;
1156 			}
1157 		}
1158 	}
1159 	return (ret);
1160 
1161 error:
1162 	nvlist_free(ret);
1163 	return (NULL);
1164 }
1165 
1166 /*
1167  * Given a property name and value, set the property for the given dataset.
1168  */
1169 int
1170 zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
1171 {
1172 	zfs_cmd_t zc = { 0 };
1173 	int ret = -1;
1174 	prop_changelist_t *cl = NULL;
1175 	char errbuf[1024];
1176 	libzfs_handle_t *hdl = zhp->zfs_hdl;
1177 	nvlist_t *nvl = NULL, *realprops;
1178 	zfs_prop_t prop;
1179 	boolean_t do_prefix;
1180 	uint64_t idx;
1181 
1182 	(void) snprintf(errbuf, sizeof (errbuf),
1183 	    dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1184 	    zhp->zfs_name);
1185 
1186 	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
1187 	    nvlist_add_string(nvl, propname, propval) != 0) {
1188 		(void) no_memory(hdl);
1189 		goto error;
1190 	}
1191 
1192 	if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl,
1193 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
1194 		goto error;
1195 
1196 	nvlist_free(nvl);
1197 	nvl = realprops;
1198 
1199 	prop = zfs_name_to_prop(propname);
1200 
1201 	if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
1202 		goto error;
1203 
1204 	if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
1205 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1206 		    "child dataset with inherited mountpoint is used "
1207 		    "in a non-global zone"));
1208 		ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1209 		goto error;
1210 	}
1211 
1212 	/*
1213 	 * If the dataset's canmount property is being set to noauto,
1214 	 * then we want to prevent unmounting & remounting it.
1215 	 */
1216 	do_prefix = !((prop == ZFS_PROP_CANMOUNT) &&
1217 	    (zprop_string_to_index(prop, propval, &idx,
1218 	    ZFS_TYPE_DATASET) == 0) && (idx == ZFS_CANMOUNT_NOAUTO));
1219 
1220 	if (do_prefix && (ret = changelist_prefix(cl)) != 0)
1221 		goto error;
1222 
1223 	/*
1224 	 * Execute the corresponding ioctl() to set this property.
1225 	 */
1226 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1227 
1228 	if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
1229 		goto error;
1230 
1231 	ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1232 
1233 	if (ret != 0) {
1234 		switch (errno) {
1235 
1236 		case ENOSPC:
1237 			/*
1238 			 * For quotas and reservations, ENOSPC indicates
1239 			 * something different; setting a quota or reservation
1240 			 * doesn't use any disk space.
1241 			 */
1242 			switch (prop) {
1243 			case ZFS_PROP_QUOTA:
1244 			case ZFS_PROP_REFQUOTA:
1245 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1246 				    "size is less than current used or "
1247 				    "reserved space"));
1248 				(void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
1249 				break;
1250 
1251 			case ZFS_PROP_RESERVATION:
1252 			case ZFS_PROP_REFRESERVATION:
1253 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1254 				    "size is greater than available space"));
1255 				(void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
1256 				break;
1257 
1258 			default:
1259 				(void) zfs_standard_error(hdl, errno, errbuf);
1260 				break;
1261 			}
1262 			break;
1263 
1264 		case EBUSY:
1265 			if (prop == ZFS_PROP_VOLBLOCKSIZE)
1266 				(void) zfs_error(hdl, EZFS_VOLHASDATA, errbuf);
1267 			else
1268 				(void) zfs_standard_error(hdl, EBUSY, errbuf);
1269 			break;
1270 
1271 		case EROFS:
1272 			(void) zfs_error(hdl, EZFS_DSREADONLY, errbuf);
1273 			break;
1274 
1275 		case ENOTSUP:
1276 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1277 			    "pool and or dataset must be upgraded to set this "
1278 			    "property or value"));
1279 			(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
1280 			break;
1281 
1282 		case ERANGE:
1283 			if (prop == ZFS_PROP_COMPRESSION) {
1284 				(void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1285 				    "property setting is not allowed on "
1286 				    "bootable datasets"));
1287 				(void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
1288 			} else {
1289 				(void) zfs_standard_error(hdl, errno, errbuf);
1290 			}
1291 			break;
1292 
1293 		case EOVERFLOW:
1294 			/*
1295 			 * This platform can't address a volume this big.
1296 			 */
1297 #ifdef _ILP32
1298 			if (prop == ZFS_PROP_VOLSIZE) {
1299 				(void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf);
1300 				break;
1301 			}
1302 #endif
1303 			/* FALLTHROUGH */
1304 		default:
1305 			(void) zfs_standard_error(hdl, errno, errbuf);
1306 		}
1307 	} else {
1308 		if (do_prefix)
1309 			ret = changelist_postfix(cl);
1310 
1311 		/*
1312 		 * Refresh the statistics so the new property value
1313 		 * is reflected.
1314 		 */
1315 		if (ret == 0)
1316 			(void) get_stats(zhp);
1317 	}
1318 
1319 error:
1320 	nvlist_free(nvl);
1321 	zcmd_free_nvlists(&zc);
1322 	if (cl)
1323 		changelist_free(cl);
1324 	return (ret);
1325 }
1326 
1327 /*
1328  * Given a property, inherit the value from the parent dataset.
1329  */
1330 int
1331 zfs_prop_inherit(zfs_handle_t *zhp, const char *propname)
1332 {
1333 	zfs_cmd_t zc = { 0 };
1334 	int ret;
1335 	prop_changelist_t *cl;
1336 	libzfs_handle_t *hdl = zhp->zfs_hdl;
1337 	char errbuf[1024];
1338 	zfs_prop_t prop;
1339 
1340 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1341 	    "cannot inherit %s for '%s'"), propname, zhp->zfs_name);
1342 
1343 	if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
1344 		/*
1345 		 * For user properties, the amount of work we have to do is very
1346 		 * small, so just do it here.
1347 		 */
1348 		if (!zfs_prop_user(propname)) {
1349 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1350 			    "invalid property"));
1351 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
1352 		}
1353 
1354 		(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1355 		(void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value));
1356 
1357 		if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0)
1358 			return (zfs_standard_error(hdl, errno, errbuf));
1359 
1360 		return (0);
1361 	}
1362 
1363 	/*
1364 	 * Verify that this property is inheritable.
1365 	 */
1366 	if (zfs_prop_readonly(prop))
1367 		return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf));
1368 
1369 	if (!zfs_prop_inheritable(prop))
1370 		return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf));
1371 
1372 	/*
1373 	 * Check to see if the value applies to this type
1374 	 */
1375 	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
1376 		return (zfs_error(hdl, EZFS_PROPTYPE, errbuf));
1377 
1378 	/*
1379 	 * Normalize the name, to get rid of shorthand abbrevations.
1380 	 */
1381 	propname = zfs_prop_to_name(prop);
1382 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1383 	(void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value));
1384 
1385 	if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID &&
1386 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
1387 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1388 		    "dataset is used in a non-global zone"));
1389 		return (zfs_error(hdl, EZFS_ZONED, errbuf));
1390 	}
1391 
1392 	/*
1393 	 * Determine datasets which will be affected by this change, if any.
1394 	 */
1395 	if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
1396 		return (-1);
1397 
1398 	if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
1399 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1400 		    "child dataset with inherited mountpoint is used "
1401 		    "in a non-global zone"));
1402 		ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1403 		goto error;
1404 	}
1405 
1406 	if ((ret = changelist_prefix(cl)) != 0)
1407 		goto error;
1408 
1409 	if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc)) != 0) {
1410 		return (zfs_standard_error(hdl, errno, errbuf));
1411 	} else {
1412 
1413 		if ((ret = changelist_postfix(cl)) != 0)
1414 			goto error;
1415 
1416 		/*
1417 		 * Refresh the statistics so the new property is reflected.
1418 		 */
1419 		(void) get_stats(zhp);
1420 	}
1421 
1422 error:
1423 	changelist_free(cl);
1424 	return (ret);
1425 }
1426 
1427 /*
1428  * True DSL properties are stored in an nvlist.  The following two functions
1429  * extract them appropriately.
1430  */
1431 static uint64_t
1432 getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
1433 {
1434 	nvlist_t *nv;
1435 	uint64_t value;
1436 
1437 	*source = NULL;
1438 	if (nvlist_lookup_nvlist(zhp->zfs_props,
1439 	    zfs_prop_to_name(prop), &nv) == 0) {
1440 		verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0);
1441 		(void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
1442 	} else {
1443 		verify(!zhp->zfs_props_table ||
1444 		    zhp->zfs_props_table[prop] == B_TRUE);
1445 		value = zfs_prop_default_numeric(prop);
1446 		*source = "";
1447 	}
1448 
1449 	return (value);
1450 }
1451 
1452 static char *
1453 getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
1454 {
1455 	nvlist_t *nv;
1456 	char *value;
1457 
1458 	*source = NULL;
1459 	if (nvlist_lookup_nvlist(zhp->zfs_props,
1460 	    zfs_prop_to_name(prop), &nv) == 0) {
1461 		verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
1462 		(void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
1463 	} else {
1464 		verify(!zhp->zfs_props_table ||
1465 		    zhp->zfs_props_table[prop] == B_TRUE);
1466 		if ((value = (char *)zfs_prop_default_string(prop)) == NULL)
1467 			value = "";
1468 		*source = "";
1469 	}
1470 
1471 	return (value);
1472 }
1473 
1474 /*
1475  * Internal function for getting a numeric property.  Both zfs_prop_get() and
1476  * zfs_prop_get_int() are built using this interface.
1477  *
1478  * Certain properties can be overridden using 'mount -o'.  In this case, scan
1479  * the contents of the /etc/mnttab entry, searching for the appropriate options.
1480  * If they differ from the on-disk values, report the current values and mark
1481  * the source "temporary".
1482  */
1483 static int
1484 get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
1485     char **source, uint64_t *val)
1486 {
1487 	zfs_cmd_t zc = { 0 };
1488 	nvlist_t *zplprops = NULL;
1489 	struct mnttab mnt;
1490 	char *mntopt_on = NULL;
1491 	char *mntopt_off = NULL;
1492 
1493 	*source = NULL;
1494 
1495 	switch (prop) {
1496 	case ZFS_PROP_ATIME:
1497 		mntopt_on = MNTOPT_ATIME;
1498 		mntopt_off = MNTOPT_NOATIME;
1499 		break;
1500 
1501 	case ZFS_PROP_DEVICES:
1502 		mntopt_on = MNTOPT_DEVICES;
1503 		mntopt_off = MNTOPT_NODEVICES;
1504 		break;
1505 
1506 	case ZFS_PROP_EXEC:
1507 		mntopt_on = MNTOPT_EXEC;
1508 		mntopt_off = MNTOPT_NOEXEC;
1509 		break;
1510 
1511 	case ZFS_PROP_READONLY:
1512 		mntopt_on = MNTOPT_RO;
1513 		mntopt_off = MNTOPT_RW;
1514 		break;
1515 
1516 	case ZFS_PROP_SETUID:
1517 		mntopt_on = MNTOPT_SETUID;
1518 		mntopt_off = MNTOPT_NOSETUID;
1519 		break;
1520 
1521 	case ZFS_PROP_XATTR:
1522 		mntopt_on = MNTOPT_XATTR;
1523 		mntopt_off = MNTOPT_NOXATTR;
1524 		break;
1525 
1526 	case ZFS_PROP_NBMAND:
1527 		mntopt_on = MNTOPT_NBMAND;
1528 		mntopt_off = MNTOPT_NONBMAND;
1529 		break;
1530 	}
1531 
1532 	/*
1533 	 * Because looking up the mount options is potentially expensive
1534 	 * (iterating over all of /etc/mnttab), we defer its calculation until
1535 	 * we're looking up a property which requires its presence.
1536 	 */
1537 	if (!zhp->zfs_mntcheck &&
1538 	    (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) {
1539 		libzfs_handle_t *hdl = zhp->zfs_hdl;
1540 		struct mnttab entry;
1541 
1542 		if (libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0) {
1543 			zhp->zfs_mntopts = zfs_strdup(hdl,
1544 			    entry.mnt_mntopts);
1545 			if (zhp->zfs_mntopts == NULL)
1546 				return (-1);
1547 		}
1548 
1549 		zhp->zfs_mntcheck = B_TRUE;
1550 	}
1551 
1552 	if (zhp->zfs_mntopts == NULL)
1553 		mnt.mnt_mntopts = "";
1554 	else
1555 		mnt.mnt_mntopts = zhp->zfs_mntopts;
1556 
1557 	switch (prop) {
1558 	case ZFS_PROP_ATIME:
1559 	case ZFS_PROP_DEVICES:
1560 	case ZFS_PROP_EXEC:
1561 	case ZFS_PROP_READONLY:
1562 	case ZFS_PROP_SETUID:
1563 	case ZFS_PROP_XATTR:
1564 	case ZFS_PROP_NBMAND:
1565 		*val = getprop_uint64(zhp, prop, source);
1566 
1567 		if (hasmntopt(&mnt, mntopt_on) && !*val) {
1568 			*val = B_TRUE;
1569 			if (src)
1570 				*src = ZPROP_SRC_TEMPORARY;
1571 		} else if (hasmntopt(&mnt, mntopt_off) && *val) {
1572 			*val = B_FALSE;
1573 			if (src)
1574 				*src = ZPROP_SRC_TEMPORARY;
1575 		}
1576 		break;
1577 
1578 	case ZFS_PROP_CANMOUNT:
1579 		*val = getprop_uint64(zhp, prop, source);
1580 		if (*val != ZFS_CANMOUNT_ON)
1581 			*source = zhp->zfs_name;
1582 		else
1583 			*source = "";	/* default */
1584 		break;
1585 
1586 	case ZFS_PROP_QUOTA:
1587 	case ZFS_PROP_REFQUOTA:
1588 	case ZFS_PROP_RESERVATION:
1589 	case ZFS_PROP_REFRESERVATION:
1590 		*val = getprop_uint64(zhp, prop, source);
1591 		if (*val == 0)
1592 			*source = "";	/* default */
1593 		else
1594 			*source = zhp->zfs_name;
1595 		break;
1596 
1597 	case ZFS_PROP_MOUNTED:
1598 		*val = (zhp->zfs_mntopts != NULL);
1599 		break;
1600 
1601 	case ZFS_PROP_NUMCLONES:
1602 		*val = zhp->zfs_dmustats.dds_num_clones;
1603 		break;
1604 
1605 	case ZFS_PROP_VERSION:
1606 	case ZFS_PROP_NORMALIZE:
1607 	case ZFS_PROP_UTF8ONLY:
1608 	case ZFS_PROP_CASE:
1609 		if (!zfs_prop_valid_for_type(prop, zhp->zfs_head_type) ||
1610 		    zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
1611 			return (-1);
1612 		(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1613 		if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_ZPLPROPS, &zc)) {
1614 			zcmd_free_nvlists(&zc);
1615 			return (-1);
1616 		}
1617 		if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &zplprops) != 0 ||
1618 		    nvlist_lookup_uint64(zplprops, zfs_prop_to_name(prop),
1619 		    val) != 0) {
1620 			zcmd_free_nvlists(&zc);
1621 			return (-1);
1622 		}
1623 		if (zplprops)
1624 			nvlist_free(zplprops);
1625 		zcmd_free_nvlists(&zc);
1626 		break;
1627 
1628 	default:
1629 		switch (zfs_prop_get_type(prop)) {
1630 		case PROP_TYPE_NUMBER:
1631 		case PROP_TYPE_INDEX:
1632 			*val = getprop_uint64(zhp, prop, source);
1633 			/*
1634 			 * If we tried to use a default value for a
1635 			 * readonly property, it means that it was not
1636 			 * present; return an error.
1637 			 */
1638 			if (zfs_prop_readonly(prop) &&
1639 			    *source && (*source)[0] == '\0') {
1640 				return (-1);
1641 			}
1642 			break;
1643 
1644 		case PROP_TYPE_STRING:
1645 		default:
1646 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
1647 			    "cannot get non-numeric property"));
1648 			return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP,
1649 			    dgettext(TEXT_DOMAIN, "internal error")));
1650 		}
1651 	}
1652 
1653 	return (0);
1654 }
1655 
1656 /*
1657  * Calculate the source type, given the raw source string.
1658  */
1659 static void
1660 get_source(zfs_handle_t *zhp, zprop_source_t *srctype, char *source,
1661     char *statbuf, size_t statlen)
1662 {
1663 	if (statbuf == NULL || *srctype == ZPROP_SRC_TEMPORARY)
1664 		return;
1665 
1666 	if (source == NULL) {
1667 		*srctype = ZPROP_SRC_NONE;
1668 	} else if (source[0] == '\0') {
1669 		*srctype = ZPROP_SRC_DEFAULT;
1670 	} else {
1671 		if (strcmp(source, zhp->zfs_name) == 0) {
1672 			*srctype = ZPROP_SRC_LOCAL;
1673 		} else {
1674 			(void) strlcpy(statbuf, source, statlen);
1675 			*srctype = ZPROP_SRC_INHERITED;
1676 		}
1677 	}
1678 
1679 }
1680 
1681 /*
1682  * Retrieve a property from the given object.  If 'literal' is specified, then
1683  * numbers are left as exact values.  Otherwise, numbers are converted to a
1684  * human-readable form.
1685  *
1686  * Returns 0 on success, or -1 on error.
1687  */
1688 int
1689 zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
1690     zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal)
1691 {
1692 	char *source = NULL;
1693 	uint64_t val;
1694 	char *str;
1695 	const char *strval;
1696 
1697 	/*
1698 	 * Check to see if this property applies to our object
1699 	 */
1700 	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
1701 		return (-1);
1702 
1703 	if (src)
1704 		*src = ZPROP_SRC_NONE;
1705 
1706 	switch (prop) {
1707 	case ZFS_PROP_CREATION:
1708 		/*
1709 		 * 'creation' is a time_t stored in the statistics.  We convert
1710 		 * this into a string unless 'literal' is specified.
1711 		 */
1712 		{
1713 			val = getprop_uint64(zhp, prop, &source);
1714 			time_t time = (time_t)val;
1715 			struct tm t;
1716 
1717 			if (literal ||
1718 			    localtime_r(&time, &t) == NULL ||
1719 			    strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
1720 			    &t) == 0)
1721 				(void) snprintf(propbuf, proplen, "%llu", val);
1722 		}
1723 		break;
1724 
1725 	case ZFS_PROP_MOUNTPOINT:
1726 		/*
1727 		 * Getting the precise mountpoint can be tricky.
1728 		 *
1729 		 *  - for 'none' or 'legacy', return those values.
1730 		 *  - for inherited mountpoints, we want to take everything
1731 		 *    after our ancestor and append it to the inherited value.
1732 		 *
1733 		 * If the pool has an alternate root, we want to prepend that
1734 		 * root to any values we return.
1735 		 */
1736 
1737 		str = getprop_string(zhp, prop, &source);
1738 
1739 		if (str[0] == '/') {
1740 			char buf[MAXPATHLEN];
1741 			char *root = buf;
1742 			const char *relpath = zhp->zfs_name + strlen(source);
1743 
1744 			if (relpath[0] == '/')
1745 				relpath++;
1746 
1747 			if ((zpool_get_prop(zhp->zpool_hdl,
1748 			    ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) ||
1749 			    (strcmp(root, "-") == 0))
1750 				root[0] = '\0';
1751 			/*
1752 			 * Special case an alternate root of '/'. This will
1753 			 * avoid having multiple leading slashes in the
1754 			 * mountpoint path.
1755 			 */
1756 			if (strcmp(root, "/") == 0)
1757 				root++;
1758 
1759 			/*
1760 			 * If the mountpoint is '/' then skip over this
1761 			 * if we are obtaining either an alternate root or
1762 			 * an inherited mountpoint.
1763 			 */
1764 			if (str[1] == '\0' && (root[0] != '\0' ||
1765 			    relpath[0] != '\0'))
1766 				str++;
1767 
1768 			if (relpath[0] == '\0')
1769 				(void) snprintf(propbuf, proplen, "%s%s",
1770 				    root, str);
1771 			else
1772 				(void) snprintf(propbuf, proplen, "%s%s%s%s",
1773 				    root, str, relpath[0] == '@' ? "" : "/",
1774 				    relpath);
1775 		} else {
1776 			/* 'legacy' or 'none' */
1777 			(void) strlcpy(propbuf, str, proplen);
1778 		}
1779 
1780 		break;
1781 
1782 	case ZFS_PROP_ORIGIN:
1783 		(void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
1784 		    proplen);
1785 		/*
1786 		 * If there is no parent at all, return failure to indicate that
1787 		 * it doesn't apply to this dataset.
1788 		 */
1789 		if (propbuf[0] == '\0')
1790 			return (-1);
1791 		break;
1792 
1793 	case ZFS_PROP_QUOTA:
1794 	case ZFS_PROP_REFQUOTA:
1795 	case ZFS_PROP_RESERVATION:
1796 	case ZFS_PROP_REFRESERVATION:
1797 
1798 		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
1799 			return (-1);
1800 
1801 		/*
1802 		 * If quota or reservation is 0, we translate this into 'none'
1803 		 * (unless literal is set), and indicate that it's the default
1804 		 * value.  Otherwise, we print the number nicely and indicate
1805 		 * that its set locally.
1806 		 */
1807 		if (val == 0) {
1808 			if (literal)
1809 				(void) strlcpy(propbuf, "0", proplen);
1810 			else
1811 				(void) strlcpy(propbuf, "none", proplen);
1812 		} else {
1813 			if (literal)
1814 				(void) snprintf(propbuf, proplen, "%llu",
1815 				    (u_longlong_t)val);
1816 			else
1817 				zfs_nicenum(val, propbuf, proplen);
1818 		}
1819 		break;
1820 
1821 	case ZFS_PROP_COMPRESSRATIO:
1822 		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
1823 			return (-1);
1824 		(void) snprintf(propbuf, proplen, "%lld.%02lldx", (longlong_t)
1825 		    val / 100, (longlong_t)val % 100);
1826 		break;
1827 
1828 	case ZFS_PROP_TYPE:
1829 		switch (zhp->zfs_type) {
1830 		case ZFS_TYPE_FILESYSTEM:
1831 			str = "filesystem";
1832 			break;
1833 		case ZFS_TYPE_VOLUME:
1834 			str = "volume";
1835 			break;
1836 		case ZFS_TYPE_SNAPSHOT:
1837 			str = "snapshot";
1838 			break;
1839 		default:
1840 			abort();
1841 		}
1842 		(void) snprintf(propbuf, proplen, "%s", str);
1843 		break;
1844 
1845 	case ZFS_PROP_MOUNTED:
1846 		/*
1847 		 * The 'mounted' property is a pseudo-property that described
1848 		 * whether the filesystem is currently mounted.  Even though
1849 		 * it's a boolean value, the typical values of "on" and "off"
1850 		 * don't make sense, so we translate to "yes" and "no".
1851 		 */
1852 		if (get_numeric_property(zhp, ZFS_PROP_MOUNTED,
1853 		    src, &source, &val) != 0)
1854 			return (-1);
1855 		if (val)
1856 			(void) strlcpy(propbuf, "yes", proplen);
1857 		else
1858 			(void) strlcpy(propbuf, "no", proplen);
1859 		break;
1860 
1861 	case ZFS_PROP_NAME:
1862 		/*
1863 		 * The 'name' property is a pseudo-property derived from the
1864 		 * dataset name.  It is presented as a real property to simplify
1865 		 * consumers.
1866 		 */
1867 		(void) strlcpy(propbuf, zhp->zfs_name, proplen);
1868 		break;
1869 
1870 	default:
1871 		switch (zfs_prop_get_type(prop)) {
1872 		case PROP_TYPE_NUMBER:
1873 			if (get_numeric_property(zhp, prop, src,
1874 			    &source, &val) != 0)
1875 				return (-1);
1876 			if (literal)
1877 				(void) snprintf(propbuf, proplen, "%llu",
1878 				    (u_longlong_t)val);
1879 			else
1880 				zfs_nicenum(val, propbuf, proplen);
1881 			break;
1882 
1883 		case PROP_TYPE_STRING:
1884 			(void) strlcpy(propbuf,
1885 			    getprop_string(zhp, prop, &source), proplen);
1886 			break;
1887 
1888 		case PROP_TYPE_INDEX:
1889 			if (get_numeric_property(zhp, prop, src,
1890 			    &source, &val) != 0)
1891 				return (-1);
1892 			if (zfs_prop_index_to_string(prop, val, &strval) != 0)
1893 				return (-1);
1894 			(void) strlcpy(propbuf, strval, proplen);
1895 			break;
1896 
1897 		default:
1898 			abort();
1899 		}
1900 	}
1901 
1902 	get_source(zhp, src, source, statbuf, statlen);
1903 
1904 	return (0);
1905 }
1906 
1907 /*
1908  * Utility function to get the given numeric property.  Does no validation that
1909  * the given property is the appropriate type; should only be used with
1910  * hard-coded property types.
1911  */
1912 uint64_t
1913 zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
1914 {
1915 	char *source;
1916 	uint64_t val;
1917 
1918 	(void) get_numeric_property(zhp, prop, NULL, &source, &val);
1919 
1920 	return (val);
1921 }
1922 
1923 int
1924 zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val)
1925 {
1926 	char buf[64];
1927 
1928 	(void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val);
1929 	return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf));
1930 }
1931 
1932 /*
1933  * Similar to zfs_prop_get(), but returns the value as an integer.
1934  */
1935 int
1936 zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
1937     zprop_source_t *src, char *statbuf, size_t statlen)
1938 {
1939 	char *source;
1940 
1941 	/*
1942 	 * Check to see if this property applies to our object
1943 	 */
1944 	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) {
1945 		return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE,
1946 		    dgettext(TEXT_DOMAIN, "cannot get property '%s'"),
1947 		    zfs_prop_to_name(prop)));
1948 	}
1949 
1950 	if (src)
1951 		*src = ZPROP_SRC_NONE;
1952 
1953 	if (get_numeric_property(zhp, prop, src, &source, value) != 0)
1954 		return (-1);
1955 
1956 	get_source(zhp, src, source, statbuf, statlen);
1957 
1958 	return (0);
1959 }
1960 
1961 static int
1962 idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
1963     char **domainp, idmap_rid_t *ridp)
1964 {
1965 	idmap_handle_t *idmap_hdl = NULL;
1966 	idmap_get_handle_t *get_hdl = NULL;
1967 	idmap_stat status;
1968 	int err = EINVAL;
1969 
1970 	if (idmap_init(&idmap_hdl) != IDMAP_SUCCESS)
1971 		goto out;
1972 	if (idmap_get_create(idmap_hdl, &get_hdl) != IDMAP_SUCCESS)
1973 		goto out;
1974 
1975 	if (isuser) {
1976 		err = idmap_get_sidbyuid(get_hdl, id,
1977 		    IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
1978 	} else {
1979 		err = idmap_get_sidbygid(get_hdl, id,
1980 		    IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
1981 	}
1982 	if (err == IDMAP_SUCCESS &&
1983 	    idmap_get_mappings(get_hdl) == IDMAP_SUCCESS &&
1984 	    status == IDMAP_SUCCESS)
1985 		err = 0;
1986 	else
1987 		err = EINVAL;
1988 out:
1989 	if (get_hdl)
1990 		idmap_get_destroy(get_hdl);
1991 	if (idmap_hdl)
1992 		(void) idmap_fini(idmap_hdl);
1993 	return (err);
1994 }
1995 
1996 /*
1997  * convert the propname into parameters needed by kernel
1998  * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829
1999  * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789
2000  */
2001 static int
2002 userquota_propname_decode(const char *propname, boolean_t zoned,
2003     zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp)
2004 {
2005 	zfs_userquota_prop_t type;
2006 	char *cp, *end;
2007 	char *numericsid = NULL;
2008 	boolean_t isuser;
2009 
2010 	domain[0] = '\0';
2011 
2012 	/* Figure out the property type ({user|group}{quota|space}) */
2013 	for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) {
2014 		if (strncmp(propname, zfs_userquota_prop_prefixes[type],
2015 		    strlen(zfs_userquota_prop_prefixes[type])) == 0)
2016 			break;
2017 	}
2018 	if (type == ZFS_NUM_USERQUOTA_PROPS)
2019 		return (EINVAL);
2020 	*typep = type;
2021 
2022 	isuser = (type == ZFS_PROP_USERQUOTA ||
2023 	    type == ZFS_PROP_USERUSED);
2024 
2025 	cp = strchr(propname, '@') + 1;
2026 
2027 	if (strchr(cp, '@')) {
2028 		/*
2029 		 * It's a SID name (eg "user@domain") that needs to be
2030 		 * turned into S-1-domainID-RID.
2031 		 */
2032 		directory_error_t e;
2033 		if (zoned && getzoneid() == GLOBAL_ZONEID)
2034 			return (ENOENT);
2035 		if (isuser) {
2036 			e = directory_sid_from_user_name(NULL,
2037 			    cp, &numericsid);
2038 		} else {
2039 			e = directory_sid_from_group_name(NULL,
2040 			    cp, &numericsid);
2041 		}
2042 		if (e != NULL) {
2043 			directory_error_free(e);
2044 			return (ENOENT);
2045 		}
2046 		if (numericsid == NULL)
2047 			return (ENOENT);
2048 		cp = numericsid;
2049 		/* will be further decoded below */
2050 	}
2051 
2052 	if (strncmp(cp, "S-1-", 4) == 0) {
2053 		/* It's a numeric SID (eg "S-1-234-567-89") */
2054 		(void) strlcpy(domain, cp, domainlen);
2055 		cp = strrchr(domain, '-');
2056 		*cp = '\0';
2057 		cp++;
2058 
2059 		errno = 0;
2060 		*ridp = strtoull(cp, &end, 10);
2061 		if (numericsid) {
2062 			free(numericsid);
2063 			numericsid = NULL;
2064 		}
2065 		if (errno != 0 || *end != '\0')
2066 			return (EINVAL);
2067 	} else if (!isdigit(*cp)) {
2068 		/*
2069 		 * It's a user/group name (eg "user") that needs to be
2070 		 * turned into a uid/gid
2071 		 */
2072 		if (zoned && getzoneid() == GLOBAL_ZONEID)
2073 			return (ENOENT);
2074 		if (isuser) {
2075 			struct passwd *pw;
2076 			pw = getpwnam(cp);
2077 			if (pw == NULL)
2078 				return (ENOENT);
2079 			*ridp = pw->pw_uid;
2080 		} else {
2081 			struct group *gr;
2082 			gr = getgrnam(cp);
2083 			if (gr == NULL)
2084 				return (ENOENT);
2085 			*ridp = gr->gr_gid;
2086 		}
2087 	} else {
2088 		/* It's a user/group ID (eg "12345"). */
2089 		uid_t id = strtoul(cp, &end, 10);
2090 		idmap_rid_t rid;
2091 		char *mapdomain;
2092 
2093 		if (*end != '\0')
2094 			return (EINVAL);
2095 		if (id > MAXUID) {
2096 			/* It's an ephemeral ID. */
2097 			if (idmap_id_to_numeric_domain_rid(id, isuser,
2098 			    &mapdomain, &rid) != 0)
2099 				return (ENOENT);
2100 			(void) strlcpy(domain, mapdomain, domainlen);
2101 			*ridp = rid;
2102 		} else {
2103 			*ridp = id;
2104 		}
2105 	}
2106 
2107 	ASSERT3P(numericsid, ==, NULL);
2108 	return (0);
2109 }
2110 
2111 static int
2112 zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname,
2113     uint64_t *propvalue, zfs_userquota_prop_t *typep)
2114 {
2115 	int err;
2116 	zfs_cmd_t zc = { 0 };
2117 
2118 	(void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2119 
2120 	err = userquota_propname_decode(propname,
2121 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED),
2122 	    typep, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid);
2123 	zc.zc_objset_type = *typep;
2124 	if (err)
2125 		return (err);
2126 
2127 	err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_USERSPACE_ONE, &zc);
2128 	if (err)
2129 		return (err);
2130 
2131 	*propvalue = zc.zc_cookie;
2132 	return (0);
2133 }
2134 
2135 int
2136 zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname,
2137     uint64_t *propvalue)
2138 {
2139 	zfs_userquota_prop_t type;
2140 
2141 	return (zfs_prop_get_userquota_common(zhp, propname, propvalue,
2142 	    &type));
2143 }
2144 
2145 int
2146 zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
2147     char *propbuf, int proplen, boolean_t literal)
2148 {
2149 	int err;
2150 	uint64_t propvalue;
2151 	zfs_userquota_prop_t type;
2152 
2153 	err = zfs_prop_get_userquota_common(zhp, propname, &propvalue,
2154 	    &type);
2155 
2156 	if (err)
2157 		return (err);
2158 
2159 	if (literal) {
2160 		(void) snprintf(propbuf, proplen, "%llu", propvalue);
2161 	} else if (propvalue == 0 &&
2162 	    (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) {
2163 		(void) strlcpy(propbuf, "none", proplen);
2164 	} else {
2165 		zfs_nicenum(propvalue, propbuf, proplen);
2166 	}
2167 	return (0);
2168 }
2169 
2170 /*
2171  * Returns the name of the given zfs handle.
2172  */
2173 const char *
2174 zfs_get_name(const zfs_handle_t *zhp)
2175 {
2176 	return (zhp->zfs_name);
2177 }
2178 
2179 /*
2180  * Returns the type of the given zfs handle.
2181  */
2182 zfs_type_t
2183 zfs_get_type(const zfs_handle_t *zhp)
2184 {
2185 	return (zhp->zfs_type);
2186 }
2187 
2188 static int
2189 zfs_do_list_ioctl(zfs_handle_t *zhp, int arg, zfs_cmd_t *zc)
2190 {
2191 	int rc;
2192 	uint64_t	orig_cookie;
2193 
2194 	orig_cookie = zc->zc_cookie;
2195 top:
2196 	(void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
2197 	rc = ioctl(zhp->zfs_hdl->libzfs_fd, arg, zc);
2198 
2199 	if (rc == -1) {
2200 		switch (errno) {
2201 		case ENOMEM:
2202 			/* expand nvlist memory and try again */
2203 			if (zcmd_expand_dst_nvlist(zhp->zfs_hdl, zc) != 0) {
2204 				zcmd_free_nvlists(zc);
2205 				return (-1);
2206 			}
2207 			zc->zc_cookie = orig_cookie;
2208 			goto top;
2209 		/*
2210 		 * An errno value of ESRCH indicates normal completion.
2211 		 * If ENOENT is returned, then the underlying dataset
2212 		 * has been removed since we obtained the handle.
2213 		 */
2214 		case ESRCH:
2215 		case ENOENT:
2216 			rc = 1;
2217 			break;
2218 		default:
2219 			rc = zfs_standard_error(zhp->zfs_hdl, errno,
2220 			    dgettext(TEXT_DOMAIN,
2221 			    "cannot iterate filesystems"));
2222 			break;
2223 		}
2224 	}
2225 	return (rc);
2226 }
2227 
2228 /*
2229  * Iterate over all child filesystems
2230  */
2231 int
2232 zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
2233 {
2234 	zfs_cmd_t zc = { 0 };
2235 	zfs_handle_t *nzhp;
2236 	int ret;
2237 
2238 	if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM)
2239 		return (0);
2240 
2241 	if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
2242 		return (-1);
2243 
2244 	while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_DATASET_LIST_NEXT,
2245 	    &zc)) == 0) {
2246 		/*
2247 		 * Silently ignore errors, as the only plausible explanation is
2248 		 * that the pool has since been removed.
2249 		 */
2250 		if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
2251 		    &zc)) == NULL) {
2252 			continue;
2253 		}
2254 
2255 		if ((ret = func(nzhp, data)) != 0) {
2256 			zcmd_free_nvlists(&zc);
2257 			return (ret);
2258 		}
2259 	}
2260 	zcmd_free_nvlists(&zc);
2261 	return ((ret < 0) ? ret : 0);
2262 }
2263 
2264 /*
2265  * Iterate over all snapshots
2266  */
2267 int
2268 zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
2269 {
2270 	zfs_cmd_t zc = { 0 };
2271 	zfs_handle_t *nzhp;
2272 	int ret;
2273 
2274 	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT)
2275 		return (0);
2276 
2277 	if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
2278 		return (-1);
2279 	while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT,
2280 	    &zc)) == 0) {
2281 
2282 		if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl,
2283 		    &zc)) == NULL) {
2284 			continue;
2285 		}
2286 
2287 		if ((ret = func(nzhp, data)) != 0) {
2288 			zcmd_free_nvlists(&zc);
2289 			return (ret);
2290 		}
2291 	}
2292 	zcmd_free_nvlists(&zc);
2293 	return ((ret < 0) ? ret : 0);
2294 }
2295 
2296 /*
2297  * Iterate over all children, snapshots and filesystems
2298  */
2299 int
2300 zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
2301 {
2302 	int ret;
2303 
2304 	if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0)
2305 		return (ret);
2306 
2307 	return (zfs_iter_snapshots(zhp, func, data));
2308 }
2309 
2310 /*
2311  * Given a complete name, return just the portion that refers to the parent.
2312  * Can return NULL if this is a pool.
2313  */
2314 static int
2315 parent_name(const char *path, char *buf, size_t buflen)
2316 {
2317 	char *loc;
2318 
2319 	if ((loc = strrchr(path, '/')) == NULL)
2320 		return (-1);
2321 
2322 	(void) strncpy(buf, path, MIN(buflen, loc - path));
2323 	buf[loc - path] = '\0';
2324 
2325 	return (0);
2326 }
2327 
2328 /*
2329  * If accept_ancestor is false, then check to make sure that the given path has
2330  * a parent, and that it exists.  If accept_ancestor is true, then find the
2331  * closest existing ancestor for the given path.  In prefixlen return the
2332  * length of already existing prefix of the given path.  We also fetch the
2333  * 'zoned' property, which is used to validate property settings when creating
2334  * new datasets.
2335  */
2336 static int
2337 check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned,
2338     boolean_t accept_ancestor, int *prefixlen)
2339 {
2340 	zfs_cmd_t zc = { 0 };
2341 	char parent[ZFS_MAXNAMELEN];
2342 	char *slash;
2343 	zfs_handle_t *zhp;
2344 	char errbuf[1024];
2345 
2346 	(void) snprintf(errbuf, sizeof (errbuf),
2347 	    dgettext(TEXT_DOMAIN, "cannot create '%s'"), path);
2348 
2349 	/* get parent, and check to see if this is just a pool */
2350 	if (parent_name(path, parent, sizeof (parent)) != 0) {
2351 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2352 		    "missing dataset name"));
2353 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2354 	}
2355 
2356 	/* check to see if the pool exists */
2357 	if ((slash = strchr(parent, '/')) == NULL)
2358 		slash = parent + strlen(parent);
2359 	(void) strncpy(zc.zc_name, parent, slash - parent);
2360 	zc.zc_name[slash - parent] = '\0';
2361 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 &&
2362 	    errno == ENOENT) {
2363 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2364 		    "no such pool '%s'"), zc.zc_name);
2365 		return (zfs_error(hdl, EZFS_NOENT, errbuf));
2366 	}
2367 
2368 	/* check to see if the parent dataset exists */
2369 	while ((zhp = make_dataset_handle(hdl, parent)) == NULL) {
2370 		if (errno == ENOENT && accept_ancestor) {
2371 			/*
2372 			 * Go deeper to find an ancestor, give up on top level.
2373 			 */
2374 			if (parent_name(parent, parent, sizeof (parent)) != 0) {
2375 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2376 				    "no such pool '%s'"), zc.zc_name);
2377 				return (zfs_error(hdl, EZFS_NOENT, errbuf));
2378 			}
2379 		} else if (errno == ENOENT) {
2380 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2381 			    "parent does not exist"));
2382 			return (zfs_error(hdl, EZFS_NOENT, errbuf));
2383 		} else
2384 			return (zfs_standard_error(hdl, errno, errbuf));
2385 	}
2386 
2387 	*zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
2388 	/* we are in a non-global zone, but parent is in the global zone */
2389 	if (getzoneid() != GLOBAL_ZONEID && !(*zoned)) {
2390 		(void) zfs_standard_error(hdl, EPERM, errbuf);
2391 		zfs_close(zhp);
2392 		return (-1);
2393 	}
2394 
2395 	/* make sure parent is a filesystem */
2396 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
2397 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2398 		    "parent is not a filesystem"));
2399 		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
2400 		zfs_close(zhp);
2401 		return (-1);
2402 	}
2403 
2404 	zfs_close(zhp);
2405 	if (prefixlen != NULL)
2406 		*prefixlen = strlen(parent);
2407 	return (0);
2408 }
2409 
2410 /*
2411  * Finds whether the dataset of the given type(s) exists.
2412  */
2413 boolean_t
2414 zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types)
2415 {
2416 	zfs_handle_t *zhp;
2417 
2418 	if (!zfs_validate_name(hdl, path, types, B_FALSE))
2419 		return (B_FALSE);
2420 
2421 	/*
2422 	 * Try to get stats for the dataset, which will tell us if it exists.
2423 	 */
2424 	if ((zhp = make_dataset_handle(hdl, path)) != NULL) {
2425 		int ds_type = zhp->zfs_type;
2426 
2427 		zfs_close(zhp);
2428 		if (types & ds_type)
2429 			return (B_TRUE);
2430 	}
2431 	return (B_FALSE);
2432 }
2433 
2434 /*
2435  * Given a path to 'target', create all the ancestors between
2436  * the prefixlen portion of the path, and the target itself.
2437  * Fail if the initial prefixlen-ancestor does not already exist.
2438  */
2439 int
2440 create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
2441 {
2442 	zfs_handle_t *h;
2443 	char *cp;
2444 	const char *opname;
2445 
2446 	/* make sure prefix exists */
2447 	cp = target + prefixlen;
2448 	if (*cp != '/') {
2449 		assert(strchr(cp, '/') == NULL);
2450 		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2451 	} else {
2452 		*cp = '\0';
2453 		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2454 		*cp = '/';
2455 	}
2456 	if (h == NULL)
2457 		return (-1);
2458 	zfs_close(h);
2459 
2460 	/*
2461 	 * Attempt to create, mount, and share any ancestor filesystems,
2462 	 * up to the prefixlen-long one.
2463 	 */
2464 	for (cp = target + prefixlen + 1;
2465 	    cp = strchr(cp, '/'); *cp = '/', cp++) {
2466 		char *logstr;
2467 
2468 		*cp = '\0';
2469 
2470 		h = make_dataset_handle(hdl, target);
2471 		if (h) {
2472 			/* it already exists, nothing to do here */
2473 			zfs_close(h);
2474 			continue;
2475 		}
2476 
2477 		logstr = hdl->libzfs_log_str;
2478 		hdl->libzfs_log_str = NULL;
2479 		if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
2480 		    NULL) != 0) {
2481 			hdl->libzfs_log_str = logstr;
2482 			opname = dgettext(TEXT_DOMAIN, "create");
2483 			goto ancestorerr;
2484 		}
2485 
2486 		hdl->libzfs_log_str = logstr;
2487 		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
2488 		if (h == NULL) {
2489 			opname = dgettext(TEXT_DOMAIN, "open");
2490 			goto ancestorerr;
2491 		}
2492 
2493 		if (zfs_mount(h, NULL, 0) != 0) {
2494 			opname = dgettext(TEXT_DOMAIN, "mount");
2495 			goto ancestorerr;
2496 		}
2497 
2498 		if (zfs_share(h) != 0) {
2499 			opname = dgettext(TEXT_DOMAIN, "share");
2500 			goto ancestorerr;
2501 		}
2502 
2503 		zfs_close(h);
2504 	}
2505 
2506 	return (0);
2507 
2508 ancestorerr:
2509 	zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2510 	    "failed to %s ancestor '%s'"), opname, target);
2511 	return (-1);
2512 }
2513 
2514 /*
2515  * Creates non-existing ancestors of the given path.
2516  */
2517 int
2518 zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
2519 {
2520 	int prefix;
2521 	uint64_t zoned;
2522 	char *path_copy;
2523 	int rc;
2524 
2525 	if (check_parents(hdl, path, &zoned, B_TRUE, &prefix) != 0)
2526 		return (-1);
2527 
2528 	if ((path_copy = strdup(path)) != NULL) {
2529 		rc = create_parents(hdl, path_copy, prefix);
2530 		free(path_copy);
2531 	}
2532 	if (path_copy == NULL || rc != 0)
2533 		return (-1);
2534 
2535 	return (0);
2536 }
2537 
2538 /*
2539  * Create a new filesystem or volume.
2540  */
2541 int
2542 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
2543     nvlist_t *props)
2544 {
2545 	zfs_cmd_t zc = { 0 };
2546 	int ret;
2547 	uint64_t size = 0;
2548 	uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
2549 	char errbuf[1024];
2550 	uint64_t zoned;
2551 
2552 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2553 	    "cannot create '%s'"), path);
2554 
2555 	/* validate the path, taking care to note the extended error message */
2556 	if (!zfs_validate_name(hdl, path, type, B_TRUE))
2557 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2558 
2559 	/* validate parents exist */
2560 	if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0)
2561 		return (-1);
2562 
2563 	/*
2564 	 * The failure modes when creating a dataset of a different type over
2565 	 * one that already exists is a little strange.  In particular, if you
2566 	 * try to create a dataset on top of an existing dataset, the ioctl()
2567 	 * will return ENOENT, not EEXIST.  To prevent this from happening, we
2568 	 * first try to see if the dataset exists.
2569 	 */
2570 	(void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name));
2571 	if (zfs_dataset_exists(hdl, zc.zc_name, ZFS_TYPE_DATASET)) {
2572 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2573 		    "dataset already exists"));
2574 		return (zfs_error(hdl, EZFS_EXISTS, errbuf));
2575 	}
2576 
2577 	if (type == ZFS_TYPE_VOLUME)
2578 		zc.zc_objset_type = DMU_OST_ZVOL;
2579 	else
2580 		zc.zc_objset_type = DMU_OST_ZFS;
2581 
2582 	if (props && (props = zfs_valid_proplist(hdl, type, props,
2583 	    zoned, NULL, errbuf)) == 0)
2584 		return (-1);
2585 
2586 	if (type == ZFS_TYPE_VOLUME) {
2587 		/*
2588 		 * If we are creating a volume, the size and block size must
2589 		 * satisfy a few restraints.  First, the blocksize must be a
2590 		 * valid block size between SPA_{MIN,MAX}BLOCKSIZE.  Second, the
2591 		 * volsize must be a multiple of the block size, and cannot be
2592 		 * zero.
2593 		 */
2594 		if (props == NULL || nvlist_lookup_uint64(props,
2595 		    zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) {
2596 			nvlist_free(props);
2597 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2598 			    "missing volume size"));
2599 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
2600 		}
2601 
2602 		if ((ret = nvlist_lookup_uint64(props,
2603 		    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
2604 		    &blocksize)) != 0) {
2605 			if (ret == ENOENT) {
2606 				blocksize = zfs_prop_default_numeric(
2607 				    ZFS_PROP_VOLBLOCKSIZE);
2608 			} else {
2609 				nvlist_free(props);
2610 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2611 				    "missing volume block size"));
2612 				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
2613 			}
2614 		}
2615 
2616 		if (size == 0) {
2617 			nvlist_free(props);
2618 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2619 			    "volume size cannot be zero"));
2620 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
2621 		}
2622 
2623 		if (size % blocksize != 0) {
2624 			nvlist_free(props);
2625 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2626 			    "volume size must be a multiple of volume block "
2627 			    "size"));
2628 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
2629 		}
2630 	}
2631 
2632 	if (props && zcmd_write_src_nvlist(hdl, &zc, props) != 0)
2633 		return (-1);
2634 	nvlist_free(props);
2635 
2636 	/* create the dataset */
2637 	ret = zfs_ioctl(hdl, ZFS_IOC_CREATE, &zc);
2638 
2639 	if (ret == 0 && type == ZFS_TYPE_VOLUME) {
2640 		ret = zvol_create_link(hdl, path);
2641 		if (ret) {
2642 			(void) zfs_standard_error(hdl, errno,
2643 			    dgettext(TEXT_DOMAIN,
2644 			    "Volume successfully created, but device links "
2645 			    "were not created"));
2646 			zcmd_free_nvlists(&zc);
2647 			return (-1);
2648 		}
2649 	}
2650 
2651 	zcmd_free_nvlists(&zc);
2652 
2653 	/* check for failure */
2654 	if (ret != 0) {
2655 		char parent[ZFS_MAXNAMELEN];
2656 		(void) parent_name(path, parent, sizeof (parent));
2657 
2658 		switch (errno) {
2659 		case ENOENT:
2660 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2661 			    "no such parent '%s'"), parent);
2662 			return (zfs_error(hdl, EZFS_NOENT, errbuf));
2663 
2664 		case EINVAL:
2665 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2666 			    "parent '%s' is not a filesystem"), parent);
2667 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
2668 
2669 		case EDOM:
2670 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2671 			    "volume block size must be power of 2 from "
2672 			    "%u to %uk"),
2673 			    (uint_t)SPA_MINBLOCKSIZE,
2674 			    (uint_t)SPA_MAXBLOCKSIZE >> 10);
2675 
2676 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
2677 
2678 		case ENOTSUP:
2679 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2680 			    "pool must be upgraded to set this "
2681 			    "property or value"));
2682 			return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
2683 #ifdef _ILP32
2684 		case EOVERFLOW:
2685 			/*
2686 			 * This platform can't address a volume this big.
2687 			 */
2688 			if (type == ZFS_TYPE_VOLUME)
2689 				return (zfs_error(hdl, EZFS_VOLTOOBIG,
2690 				    errbuf));
2691 #endif
2692 			/* FALLTHROUGH */
2693 		default:
2694 			return (zfs_standard_error(hdl, errno, errbuf));
2695 		}
2696 	}
2697 
2698 	return (0);
2699 }
2700 
2701 /*
2702  * Destroys the given dataset.  The caller must make sure that the filesystem
2703  * isn't mounted, and that there are no active dependents.
2704  */
2705 int
2706 zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
2707 {
2708 	zfs_cmd_t zc = { 0 };
2709 
2710 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2711 
2712 	if (ZFS_IS_VOLUME(zhp)) {
2713 		/*
2714 		 * If user doesn't have permissions to unshare volume, then
2715 		 * abort the request.  This would only happen for a
2716 		 * non-privileged user.
2717 		 */
2718 		if (zfs_unshare_iscsi(zhp) != 0) {
2719 			return (-1);
2720 		}
2721 
2722 		if (zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0)
2723 			return (-1);
2724 
2725 		zc.zc_objset_type = DMU_OST_ZVOL;
2726 	} else {
2727 		zc.zc_objset_type = DMU_OST_ZFS;
2728 	}
2729 
2730 	zc.zc_defer_destroy = defer;
2731 	if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0) {
2732 		return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
2733 		    dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
2734 		    zhp->zfs_name));
2735 	}
2736 
2737 	remove_mountpoint(zhp);
2738 
2739 	return (0);
2740 }
2741 
2742 struct destroydata {
2743 	char *snapname;
2744 	boolean_t gotone;
2745 	boolean_t closezhp;
2746 };
2747 
2748 static int
2749 zfs_remove_link_cb(zfs_handle_t *zhp, void *arg)
2750 {
2751 	struct destroydata *dd = arg;
2752 	zfs_handle_t *szhp;
2753 	char name[ZFS_MAXNAMELEN];
2754 	boolean_t closezhp = dd->closezhp;
2755 	int rv;
2756 
2757 	(void) strlcpy(name, zhp->zfs_name, sizeof (name));
2758 	(void) strlcat(name, "@", sizeof (name));
2759 	(void) strlcat(name, dd->snapname, sizeof (name));
2760 
2761 	szhp = make_dataset_handle(zhp->zfs_hdl, name);
2762 	if (szhp) {
2763 		dd->gotone = B_TRUE;
2764 		zfs_close(szhp);
2765 	}
2766 
2767 	if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
2768 		(void) zvol_remove_link(zhp->zfs_hdl, name);
2769 		/*
2770 		 * NB: this is simply a best-effort.  We don't want to
2771 		 * return an error, because then we wouldn't visit all
2772 		 * the volumes.
2773 		 */
2774 	}
2775 
2776 	dd->closezhp = B_TRUE;
2777 	rv = zfs_iter_filesystems(zhp, zfs_remove_link_cb, arg);
2778 	if (closezhp)
2779 		zfs_close(zhp);
2780 	return (rv);
2781 }
2782 
2783 /*
2784  * Destroys all snapshots with the given name in zhp & descendants.
2785  */
2786 int
2787 zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
2788 {
2789 	zfs_cmd_t zc = { 0 };
2790 	int ret;
2791 	struct destroydata dd = { 0 };
2792 
2793 	dd.snapname = snapname;
2794 	(void) zfs_remove_link_cb(zhp, &dd);
2795 
2796 	if (!dd.gotone) {
2797 		return (zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
2798 		    dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
2799 		    zhp->zfs_name, snapname));
2800 	}
2801 
2802 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2803 	(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
2804 	zc.zc_defer_destroy = defer;
2805 
2806 	ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY_SNAPS, &zc);
2807 	if (ret != 0) {
2808 		char errbuf[1024];
2809 
2810 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2811 		    "cannot destroy '%s@%s'"), zc.zc_name, snapname);
2812 
2813 		switch (errno) {
2814 		case EEXIST:
2815 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2816 			    "snapshot is cloned"));
2817 			return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf));
2818 
2819 		default:
2820 			return (zfs_standard_error(zhp->zfs_hdl, errno,
2821 			    errbuf));
2822 		}
2823 	}
2824 
2825 	return (0);
2826 }
2827 
2828 /*
2829  * Clones the given dataset.  The target must be of the same type as the source.
2830  */
2831 int
2832 zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
2833 {
2834 	zfs_cmd_t zc = { 0 };
2835 	char parent[ZFS_MAXNAMELEN];
2836 	int ret;
2837 	char errbuf[1024];
2838 	libzfs_handle_t *hdl = zhp->zfs_hdl;
2839 	zfs_type_t type;
2840 	uint64_t zoned;
2841 
2842 	assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
2843 
2844 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2845 	    "cannot create '%s'"), target);
2846 
2847 	/* validate the target name */
2848 	if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
2849 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2850 
2851 	/* validate parents exist */
2852 	if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
2853 		return (-1);
2854 
2855 	(void) parent_name(target, parent, sizeof (parent));
2856 
2857 	/* do the clone */
2858 	if (ZFS_IS_VOLUME(zhp)) {
2859 		zc.zc_objset_type = DMU_OST_ZVOL;
2860 		type = ZFS_TYPE_VOLUME;
2861 	} else {
2862 		zc.zc_objset_type = DMU_OST_ZFS;
2863 		type = ZFS_TYPE_FILESYSTEM;
2864 	}
2865 
2866 	if (props) {
2867 		if ((props = zfs_valid_proplist(hdl, type, props, zoned,
2868 		    zhp, errbuf)) == NULL)
2869 			return (-1);
2870 
2871 		if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
2872 			nvlist_free(props);
2873 			return (-1);
2874 		}
2875 
2876 		nvlist_free(props);
2877 	}
2878 
2879 	(void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name));
2880 	(void) strlcpy(zc.zc_value, zhp->zfs_name, sizeof (zc.zc_value));
2881 	ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_CREATE, &zc);
2882 
2883 	zcmd_free_nvlists(&zc);
2884 
2885 	if (ret != 0) {
2886 		switch (errno) {
2887 
2888 		case ENOENT:
2889 			/*
2890 			 * The parent doesn't exist.  We should have caught this
2891 			 * above, but there may a race condition that has since
2892 			 * destroyed the parent.
2893 			 *
2894 			 * At this point, we don't know whether it's the source
2895 			 * that doesn't exist anymore, or whether the target
2896 			 * dataset doesn't exist.
2897 			 */
2898 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2899 			    "no such parent '%s'"), parent);
2900 			return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
2901 
2902 		case EXDEV:
2903 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2904 			    "source and target pools differ"));
2905 			return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET,
2906 			    errbuf));
2907 
2908 		default:
2909 			return (zfs_standard_error(zhp->zfs_hdl, errno,
2910 			    errbuf));
2911 		}
2912 	} else if (ZFS_IS_VOLUME(zhp)) {
2913 		ret = zvol_create_link(zhp->zfs_hdl, target);
2914 	}
2915 
2916 	return (ret);
2917 }
2918 
2919 typedef struct promote_data {
2920 	char cb_mountpoint[MAXPATHLEN];
2921 	const char *cb_target;
2922 	const char *cb_errbuf;
2923 	uint64_t cb_pivot_txg;
2924 } promote_data_t;
2925 
2926 static int
2927 promote_snap_cb(zfs_handle_t *zhp, void *data)
2928 {
2929 	promote_data_t *pd = data;
2930 	zfs_handle_t *szhp;
2931 	char snapname[MAXPATHLEN];
2932 	int rv = 0;
2933 
2934 	/* We don't care about snapshots after the pivot point */
2935 	if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > pd->cb_pivot_txg) {
2936 		zfs_close(zhp);
2937 		return (0);
2938 	}
2939 
2940 	/* Remove the device link if it's a zvol. */
2941 	if (ZFS_IS_VOLUME(zhp))
2942 		(void) zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name);
2943 
2944 	/* Check for conflicting names */
2945 	(void) strlcpy(snapname, pd->cb_target, sizeof (snapname));
2946 	(void) strlcat(snapname, strchr(zhp->zfs_name, '@'), sizeof (snapname));
2947 	szhp = make_dataset_handle(zhp->zfs_hdl, snapname);
2948 	if (szhp != NULL) {
2949 		zfs_close(szhp);
2950 		zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2951 		    "snapshot name '%s' from origin \n"
2952 		    "conflicts with '%s' from target"),
2953 		    zhp->zfs_name, snapname);
2954 		rv = zfs_error(zhp->zfs_hdl, EZFS_EXISTS, pd->cb_errbuf);
2955 	}
2956 	zfs_close(zhp);
2957 	return (rv);
2958 }
2959 
2960 static int
2961 promote_snap_done_cb(zfs_handle_t *zhp, void *data)
2962 {
2963 	promote_data_t *pd = data;
2964 
2965 	/* We don't care about snapshots after the pivot point */
2966 	if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) <= pd->cb_pivot_txg) {
2967 		/* Create the device link if it's a zvol. */
2968 		if (ZFS_IS_VOLUME(zhp))
2969 			(void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
2970 	}
2971 
2972 	zfs_close(zhp);
2973 	return (0);
2974 }
2975 
2976 /*
2977  * Promotes the given clone fs to be the clone parent.
2978  */
2979 int
2980 zfs_promote(zfs_handle_t *zhp)
2981 {
2982 	libzfs_handle_t *hdl = zhp->zfs_hdl;
2983 	zfs_cmd_t zc = { 0 };
2984 	char parent[MAXPATHLEN];
2985 	char *cp;
2986 	int ret;
2987 	zfs_handle_t *pzhp;
2988 	promote_data_t pd;
2989 	char errbuf[1024];
2990 
2991 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2992 	    "cannot promote '%s'"), zhp->zfs_name);
2993 
2994 	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
2995 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2996 		    "snapshots can not be promoted"));
2997 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
2998 	}
2999 
3000 	(void) strlcpy(parent, zhp->zfs_dmustats.dds_origin, sizeof (parent));
3001 	if (parent[0] == '\0') {
3002 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3003 		    "not a cloned filesystem"));
3004 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3005 	}
3006 	cp = strchr(parent, '@');
3007 	*cp = '\0';
3008 
3009 	/* Walk the snapshots we will be moving */
3010 	pzhp = zfs_open(hdl, zhp->zfs_dmustats.dds_origin, ZFS_TYPE_SNAPSHOT);
3011 	if (pzhp == NULL)
3012 		return (-1);
3013 	pd.cb_pivot_txg = zfs_prop_get_int(pzhp, ZFS_PROP_CREATETXG);
3014 	zfs_close(pzhp);
3015 	pd.cb_target = zhp->zfs_name;
3016 	pd.cb_errbuf = errbuf;
3017 	pzhp = zfs_open(hdl, parent, ZFS_TYPE_DATASET);
3018 	if (pzhp == NULL)
3019 		return (-1);
3020 	(void) zfs_prop_get(pzhp, ZFS_PROP_MOUNTPOINT, pd.cb_mountpoint,
3021 	    sizeof (pd.cb_mountpoint), NULL, NULL, 0, FALSE);
3022 	ret = zfs_iter_snapshots(pzhp, promote_snap_cb, &pd);
3023 	if (ret != 0) {
3024 		zfs_close(pzhp);
3025 		return (-1);
3026 	}
3027 
3028 	/* issue the ioctl */
3029 	(void) strlcpy(zc.zc_value, zhp->zfs_dmustats.dds_origin,
3030 	    sizeof (zc.zc_value));
3031 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3032 	ret = zfs_ioctl(hdl, ZFS_IOC_PROMOTE, &zc);
3033 
3034 	if (ret != 0) {
3035 		int save_errno = errno;
3036 
3037 		(void) zfs_iter_snapshots(pzhp, promote_snap_done_cb, &pd);
3038 		zfs_close(pzhp);
3039 
3040 		switch (save_errno) {
3041 		case EEXIST:
3042 			/*
3043 			 * There is a conflicting snapshot name.  We
3044 			 * should have caught this above, but they could
3045 			 * have renamed something in the mean time.
3046 			 */
3047 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3048 			    "conflicting snapshot name from parent '%s'"),
3049 			    parent);
3050 			return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3051 
3052 		default:
3053 			return (zfs_standard_error(hdl, save_errno, errbuf));
3054 		}
3055 	} else {
3056 		(void) zfs_iter_snapshots(zhp, promote_snap_done_cb, &pd);
3057 	}
3058 
3059 	zfs_close(pzhp);
3060 	return (ret);
3061 }
3062 
3063 struct createdata {
3064 	const char *cd_snapname;
3065 	int cd_ifexists;
3066 };
3067 
3068 static int
3069 zfs_create_link_cb(zfs_handle_t *zhp, void *arg)
3070 {
3071 	struct createdata *cd = arg;
3072 	int ret;
3073 
3074 	if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
3075 		char name[MAXPATHLEN];
3076 
3077 		(void) strlcpy(name, zhp->zfs_name, sizeof (name));
3078 		(void) strlcat(name, "@", sizeof (name));
3079 		(void) strlcat(name, cd->cd_snapname, sizeof (name));
3080 		(void) zvol_create_link_common(zhp->zfs_hdl, name,
3081 		    cd->cd_ifexists);
3082 		/*
3083 		 * NB: this is simply a best-effort.  We don't want to
3084 		 * return an error, because then we wouldn't visit all
3085 		 * the volumes.
3086 		 */
3087 	}
3088 
3089 	ret = zfs_iter_filesystems(zhp, zfs_create_link_cb, cd);
3090 
3091 	zfs_close(zhp);
3092 
3093 	return (ret);
3094 }
3095 
3096 /*
3097  * Takes a snapshot of the given dataset.
3098  */
3099 int
3100 zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
3101     nvlist_t *props)
3102 {
3103 	const char *delim;
3104 	char parent[ZFS_MAXNAMELEN];
3105 	zfs_handle_t *zhp;
3106 	zfs_cmd_t zc = { 0 };
3107 	int ret;
3108 	char errbuf[1024];
3109 
3110 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3111 	    "cannot snapshot '%s'"), path);
3112 
3113 	/* validate the target name */
3114 	if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
3115 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3116 
3117 	if (props) {
3118 		if ((props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
3119 		    props, B_FALSE, NULL, errbuf)) == NULL)
3120 			return (-1);
3121 
3122 		if (zcmd_write_src_nvlist(hdl, &zc, props) != 0) {
3123 			nvlist_free(props);
3124 			return (-1);
3125 		}
3126 
3127 		nvlist_free(props);
3128 	}
3129 
3130 	/* make sure the parent exists and is of the appropriate type */
3131 	delim = strchr(path, '@');
3132 	(void) strncpy(parent, path, delim - path);
3133 	parent[delim - path] = '\0';
3134 
3135 	if ((zhp = zfs_open(hdl, parent, ZFS_TYPE_FILESYSTEM |
3136 	    ZFS_TYPE_VOLUME)) == NULL) {
3137 		zcmd_free_nvlists(&zc);
3138 		return (-1);
3139 	}
3140 
3141 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3142 	(void) strlcpy(zc.zc_value, delim+1, sizeof (zc.zc_value));
3143 	if (ZFS_IS_VOLUME(zhp))
3144 		zc.zc_objset_type = DMU_OST_ZVOL;
3145 	else
3146 		zc.zc_objset_type = DMU_OST_ZFS;
3147 	zc.zc_cookie = recursive;
3148 	ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_SNAPSHOT, &zc);
3149 
3150 	zcmd_free_nvlists(&zc);
3151 
3152 	/*
3153 	 * if it was recursive, the one that actually failed will be in
3154 	 * zc.zc_name.
3155 	 */
3156 	if (ret != 0)
3157 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3158 		    "cannot create snapshot '%s@%s'"), zc.zc_name, zc.zc_value);
3159 
3160 	if (ret == 0 && recursive) {
3161 		struct createdata cd;
3162 
3163 		cd.cd_snapname = delim + 1;
3164 		cd.cd_ifexists = B_FALSE;
3165 		(void) zfs_iter_filesystems(zhp, zfs_create_link_cb, &cd);
3166 	}
3167 	if (ret == 0 && zhp->zfs_type == ZFS_TYPE_VOLUME) {
3168 		ret = zvol_create_link(zhp->zfs_hdl, path);
3169 		if (ret != 0) {
3170 			(void) zfs_standard_error(hdl, errno,
3171 			    dgettext(TEXT_DOMAIN,
3172 			    "Volume successfully snapshotted, but device links "
3173 			    "were not created"));
3174 			zfs_close(zhp);
3175 			return (-1);
3176 		}
3177 	}
3178 
3179 	if (ret != 0)
3180 		(void) zfs_standard_error(hdl, errno, errbuf);
3181 
3182 	zfs_close(zhp);
3183 
3184 	return (ret);
3185 }
3186 
3187 /*
3188  * Destroy any more recent snapshots.  We invoke this callback on any dependents
3189  * of the snapshot first.  If the 'cb_dependent' member is non-zero, then this
3190  * is a dependent and we should just destroy it without checking the transaction
3191  * group.
3192  */
3193 typedef struct rollback_data {
3194 	const char	*cb_target;		/* the snapshot */
3195 	uint64_t	cb_create;		/* creation time reference */
3196 	boolean_t	cb_error;
3197 	boolean_t	cb_dependent;
3198 	boolean_t	cb_force;
3199 } rollback_data_t;
3200 
3201 static int
3202 rollback_destroy(zfs_handle_t *zhp, void *data)
3203 {
3204 	rollback_data_t *cbp = data;
3205 
3206 	if (!cbp->cb_dependent) {
3207 		if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 &&
3208 		    zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
3209 		    zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
3210 		    cbp->cb_create) {
3211 			char *logstr;
3212 
3213 			cbp->cb_dependent = B_TRUE;
3214 			cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
3215 			    rollback_destroy, cbp);
3216 			cbp->cb_dependent = B_FALSE;
3217 
3218 			logstr = zhp->zfs_hdl->libzfs_log_str;
3219 			zhp->zfs_hdl->libzfs_log_str = NULL;
3220 			cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
3221 			zhp->zfs_hdl->libzfs_log_str = logstr;
3222 		}
3223 	} else {
3224 		/* We must destroy this clone; first unmount it */
3225 		prop_changelist_t *clp;
3226 
3227 		clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
3228 		    cbp->cb_force ? MS_FORCE: 0);
3229 		if (clp == NULL || changelist_prefix(clp) != 0) {
3230 			cbp->cb_error = B_TRUE;
3231 			zfs_close(zhp);
3232 			return (0);
3233 		}
3234 		if (zfs_destroy(zhp, B_FALSE) != 0)
3235 			cbp->cb_error = B_TRUE;
3236 		else
3237 			changelist_remove(clp, zhp->zfs_name);
3238 		(void) changelist_postfix(clp);
3239 		changelist_free(clp);
3240 	}
3241 
3242 	zfs_close(zhp);
3243 	return (0);
3244 }
3245 
3246 /*
3247  * Given a dataset, rollback to a specific snapshot, discarding any
3248  * data changes since then and making it the active dataset.
3249  *
3250  * Any snapshots more recent than the target are destroyed, along with
3251  * their dependents.
3252  */
3253 int
3254 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
3255 {
3256 	rollback_data_t cb = { 0 };
3257 	int err;
3258 	zfs_cmd_t zc = { 0 };
3259 	boolean_t restore_resv = 0;
3260 	uint64_t old_volsize, new_volsize;
3261 	zfs_prop_t resv_prop;
3262 
3263 	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
3264 	    zhp->zfs_type == ZFS_TYPE_VOLUME);
3265 
3266 	/*
3267 	 * Destroy all recent snapshots and its dependends.
3268 	 */
3269 	cb.cb_force = force;
3270 	cb.cb_target = snap->zfs_name;
3271 	cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
3272 	(void) zfs_iter_children(zhp, rollback_destroy, &cb);
3273 
3274 	if (cb.cb_error)
3275 		return (-1);
3276 
3277 	/*
3278 	 * Now that we have verified that the snapshot is the latest,
3279 	 * rollback to the given snapshot.
3280 	 */
3281 
3282 	if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
3283 		if (zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0)
3284 			return (-1);
3285 		if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
3286 			return (-1);
3287 		old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3288 		restore_resv =
3289 		    (old_volsize == zfs_prop_get_int(zhp, resv_prop));
3290 	}
3291 
3292 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3293 
3294 	if (ZFS_IS_VOLUME(zhp))
3295 		zc.zc_objset_type = DMU_OST_ZVOL;
3296 	else
3297 		zc.zc_objset_type = DMU_OST_ZFS;
3298 
3299 	/*
3300 	 * We rely on zfs_iter_children() to verify that there are no
3301 	 * newer snapshots for the given dataset.  Therefore, we can
3302 	 * simply pass the name on to the ioctl() call.  There is still
3303 	 * an unlikely race condition where the user has taken a
3304 	 * snapshot since we verified that this was the most recent.
3305 	 *
3306 	 */
3307 	if ((err = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_ROLLBACK, &zc)) != 0) {
3308 		(void) zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3309 		    dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
3310 		    zhp->zfs_name);
3311 		return (err);
3312 	}
3313 
3314 	/*
3315 	 * For volumes, if the pre-rollback volsize matched the pre-
3316 	 * rollback reservation and the volsize has changed then set
3317 	 * the reservation property to the post-rollback volsize.
3318 	 * Make a new handle since the rollback closed the dataset.
3319 	 */
3320 	if ((zhp->zfs_type == ZFS_TYPE_VOLUME) &&
3321 	    (zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name))) {
3322 		if (err = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name)) {
3323 			zfs_close(zhp);
3324 			return (err);
3325 		}
3326 		if (restore_resv) {
3327 			new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3328 			if (old_volsize != new_volsize)
3329 				err = zfs_prop_set_int(zhp, resv_prop,
3330 				    new_volsize);
3331 		}
3332 		zfs_close(zhp);
3333 	}
3334 	return (err);
3335 }
3336 
3337 /*
3338  * Iterate over all dependents for a given dataset.  This includes both
3339  * hierarchical dependents (children) and data dependents (snapshots and
3340  * clones).  The bulk of the processing occurs in get_dependents() in
3341  * libzfs_graph.c.
3342  */
3343 int
3344 zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion,
3345     zfs_iter_f func, void *data)
3346 {
3347 	char **dependents;
3348 	size_t count;
3349 	int i;
3350 	zfs_handle_t *child;
3351 	int ret = 0;
3352 
3353 	if (get_dependents(zhp->zfs_hdl, allowrecursion, zhp->zfs_name,
3354 	    &dependents, &count) != 0)
3355 		return (-1);
3356 
3357 	for (i = 0; i < count; i++) {
3358 		if ((child = make_dataset_handle(zhp->zfs_hdl,
3359 		    dependents[i])) == NULL)
3360 			continue;
3361 
3362 		if ((ret = func(child, data)) != 0)
3363 			break;
3364 	}
3365 
3366 	for (i = 0; i < count; i++)
3367 		free(dependents[i]);
3368 	free(dependents);
3369 
3370 	return (ret);
3371 }
3372 
3373 /*
3374  * Renames the given dataset.
3375  */
3376 int
3377 zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
3378 {
3379 	int ret;
3380 	zfs_cmd_t zc = { 0 };
3381 	char *delim;
3382 	prop_changelist_t *cl = NULL;
3383 	zfs_handle_t *zhrp = NULL;
3384 	char *parentname = NULL;
3385 	char parent[ZFS_MAXNAMELEN];
3386 	libzfs_handle_t *hdl = zhp->zfs_hdl;
3387 	char errbuf[1024];
3388 
3389 	/* if we have the same exact name, just return success */
3390 	if (strcmp(zhp->zfs_name, target) == 0)
3391 		return (0);
3392 
3393 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3394 	    "cannot rename to '%s'"), target);
3395 
3396 	/*
3397 	 * Make sure the target name is valid
3398 	 */
3399 	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
3400 		if ((strchr(target, '@') == NULL) ||
3401 		    *target == '@') {
3402 			/*
3403 			 * Snapshot target name is abbreviated,
3404 			 * reconstruct full dataset name
3405 			 */
3406 			(void) strlcpy(parent, zhp->zfs_name,
3407 			    sizeof (parent));
3408 			delim = strchr(parent, '@');
3409 			if (strchr(target, '@') == NULL)
3410 				*(++delim) = '\0';
3411 			else
3412 				*delim = '\0';
3413 			(void) strlcat(parent, target, sizeof (parent));
3414 			target = parent;
3415 		} else {
3416 			/*
3417 			 * Make sure we're renaming within the same dataset.
3418 			 */
3419 			delim = strchr(target, '@');
3420 			if (strncmp(zhp->zfs_name, target, delim - target)
3421 			    != 0 || zhp->zfs_name[delim - target] != '@') {
3422 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3423 				    "snapshots must be part of same "
3424 				    "dataset"));
3425 				return (zfs_error(hdl, EZFS_CROSSTARGET,
3426 				    errbuf));
3427 			}
3428 		}
3429 		if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
3430 			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3431 	} else {
3432 		if (recursive) {
3433 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3434 			    "recursive rename must be a snapshot"));
3435 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3436 		}
3437 
3438 		if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
3439 			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3440 		uint64_t unused;
3441 
3442 		/* validate parents */
3443 		if (check_parents(hdl, target, &unused, B_FALSE, NULL) != 0)
3444 			return (-1);
3445 
3446 		(void) parent_name(target, parent, sizeof (parent));
3447 
3448 		/* make sure we're in the same pool */
3449 		verify((delim = strchr(target, '/')) != NULL);
3450 		if (strncmp(zhp->zfs_name, target, delim - target) != 0 ||
3451 		    zhp->zfs_name[delim - target] != '/') {
3452 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3453 			    "datasets must be within same pool"));
3454 			return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
3455 		}
3456 
3457 		/* new name cannot be a child of the current dataset name */
3458 		if (strncmp(parent, zhp->zfs_name,
3459 		    strlen(zhp->zfs_name)) == 0) {
3460 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3461 			    "New dataset name cannot be a descendent of "
3462 			    "current dataset name"));
3463 			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3464 		}
3465 	}
3466 
3467 	(void) snprintf(errbuf, sizeof (errbuf),
3468 	    dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name);
3469 
3470 	if (getzoneid() == GLOBAL_ZONEID &&
3471 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
3472 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3473 		    "dataset is used in a non-global zone"));
3474 		return (zfs_error(hdl, EZFS_ZONED, errbuf));
3475 	}
3476 
3477 	if (recursive) {
3478 		struct destroydata dd;
3479 
3480 		parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
3481 		if (parentname == NULL) {
3482 			ret = -1;
3483 			goto error;
3484 		}
3485 		delim = strchr(parentname, '@');
3486 		*delim = '\0';
3487 		zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_DATASET);
3488 		if (zhrp == NULL) {
3489 			ret = -1;
3490 			goto error;
3491 		}
3492 
3493 		dd.snapname = delim + 1;
3494 		dd.gotone = B_FALSE;
3495 		dd.closezhp = B_TRUE;
3496 
3497 		/* We remove any zvol links prior to renaming them */
3498 		ret = zfs_iter_filesystems(zhrp, zfs_remove_link_cb, &dd);
3499 		if (ret) {
3500 			goto error;
3501 		}
3502 	} else {
3503 		if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0)) == NULL)
3504 			return (-1);
3505 
3506 		if (changelist_haszonedchild(cl)) {
3507 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3508 			    "child dataset with inherited mountpoint is used "
3509 			    "in a non-global zone"));
3510 			(void) zfs_error(hdl, EZFS_ZONED, errbuf);
3511 			goto error;
3512 		}
3513 
3514 		if ((ret = changelist_prefix(cl)) != 0)
3515 			goto error;
3516 	}
3517 
3518 	if (ZFS_IS_VOLUME(zhp))
3519 		zc.zc_objset_type = DMU_OST_ZVOL;
3520 	else
3521 		zc.zc_objset_type = DMU_OST_ZFS;
3522 
3523 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3524 	(void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
3525 
3526 	zc.zc_cookie = recursive;
3527 
3528 	if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
3529 		/*
3530 		 * if it was recursive, the one that actually failed will
3531 		 * be in zc.zc_name
3532 		 */
3533 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3534 		    "cannot rename '%s'"), zc.zc_name);
3535 
3536 		if (recursive && errno == EEXIST) {
3537 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3538 			    "a child dataset already has a snapshot "
3539 			    "with the new name"));
3540 			(void) zfs_error(hdl, EZFS_EXISTS, errbuf);
3541 		} else {
3542 			(void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
3543 		}
3544 
3545 		/*
3546 		 * On failure, we still want to remount any filesystems that
3547 		 * were previously mounted, so we don't alter the system state.
3548 		 */
3549 		if (recursive) {
3550 			struct createdata cd;
3551 
3552 			/* only create links for datasets that had existed */
3553 			cd.cd_snapname = delim + 1;
3554 			cd.cd_ifexists = B_TRUE;
3555 			(void) zfs_iter_filesystems(zhrp, zfs_create_link_cb,
3556 			    &cd);
3557 		} else {
3558 			(void) changelist_postfix(cl);
3559 		}
3560 	} else {
3561 		if (recursive) {
3562 			struct createdata cd;
3563 
3564 			/* only create links for datasets that had existed */
3565 			cd.cd_snapname = strchr(target, '@') + 1;
3566 			cd.cd_ifexists = B_TRUE;
3567 			ret = zfs_iter_filesystems(zhrp, zfs_create_link_cb,
3568 			    &cd);
3569 		} else {
3570 			changelist_rename(cl, zfs_get_name(zhp), target);
3571 			ret = changelist_postfix(cl);
3572 		}
3573 	}
3574 
3575 error:
3576 	if (parentname) {
3577 		free(parentname);
3578 	}
3579 	if (zhrp) {
3580 		zfs_close(zhrp);
3581 	}
3582 	if (cl) {
3583 		changelist_free(cl);
3584 	}
3585 	return (ret);
3586 }
3587 
3588 /*
3589  * Given a zvol dataset, issue the ioctl to create the appropriate minor node,
3590  * poke devfsadm to create the /dev link, and then wait for the link to appear.
3591  */
3592 int
3593 zvol_create_link(libzfs_handle_t *hdl, const char *dataset)
3594 {
3595 	return (zvol_create_link_common(hdl, dataset, B_FALSE));
3596 }
3597 
3598 static int
3599 zvol_create_link_common(libzfs_handle_t *hdl, const char *dataset, int ifexists)
3600 {
3601 	zfs_cmd_t zc = { 0 };
3602 	di_devlink_handle_t dhdl;
3603 	priv_set_t *priv_effective;
3604 	int privileged;
3605 
3606 	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
3607 
3608 	/*
3609 	 * Issue the appropriate ioctl.
3610 	 */
3611 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_CREATE_MINOR, &zc) != 0) {
3612 		switch (errno) {
3613 		case EEXIST:
3614 			/*
3615 			 * Silently ignore the case where the link already
3616 			 * exists.  This allows 'zfs volinit' to be run multiple
3617 			 * times without errors.
3618 			 */
3619 			return (0);
3620 
3621 		case ENOENT:
3622 			/*
3623 			 * Dataset does not exist in the kernel.  If we
3624 			 * don't care (see zfs_rename), then ignore the
3625 			 * error quietly.
3626 			 */
3627 			if (ifexists) {
3628 				return (0);
3629 			}
3630 
3631 			/* FALLTHROUGH */
3632 
3633 		default:
3634 			return (zfs_standard_error_fmt(hdl, errno,
3635 			    dgettext(TEXT_DOMAIN, "cannot create device links "
3636 			    "for '%s'"), dataset));
3637 		}
3638 	}
3639 
3640 	/*
3641 	 * If privileged call devfsadm and wait for the links to
3642 	 * magically appear.
3643 	 * Otherwise, print out an informational message.
3644 	 */
3645 
3646 	priv_effective = priv_allocset();
3647 	(void) getppriv(PRIV_EFFECTIVE, priv_effective);
3648 	privileged = (priv_isfullset(priv_effective) == B_TRUE);
3649 	priv_freeset(priv_effective);
3650 
3651 	if (privileged) {
3652 		if ((dhdl = di_devlink_init(ZFS_DRIVER,
3653 		    DI_MAKE_LINK)) == NULL) {
3654 			zfs_error_aux(hdl, strerror(errno));
3655 			(void) zfs_error_fmt(hdl, errno,
3656 			    dgettext(TEXT_DOMAIN, "cannot create device links "
3657 			    "for '%s'"), dataset);
3658 			(void) ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc);
3659 			return (-1);
3660 		} else {
3661 			(void) di_devlink_fini(&dhdl);
3662 		}
3663 	} else {
3664 		char pathname[MAXPATHLEN];
3665 		struct stat64 statbuf;
3666 		int i;
3667 
3668 #define	MAX_WAIT	10
3669 
3670 		/*
3671 		 * This is the poor mans way of waiting for the link
3672 		 * to show up.  If after 10 seconds we still don't
3673 		 * have it, then print out a message.
3674 		 */
3675 		(void) snprintf(pathname, sizeof (pathname), "/dev/zvol/dsk/%s",
3676 		    dataset);
3677 
3678 		for (i = 0; i != MAX_WAIT; i++) {
3679 			if (stat64(pathname, &statbuf) == 0)
3680 				break;
3681 			(void) sleep(1);
3682 		}
3683 		if (i == MAX_WAIT)
3684 			(void) printf(gettext("%s may not be immediately "
3685 			    "available\n"), pathname);
3686 	}
3687 
3688 	return (0);
3689 }
3690 
3691 /*
3692  * Remove a minor node for the given zvol and the associated /dev links.
3693  */
3694 int
3695 zvol_remove_link(libzfs_handle_t *hdl, const char *dataset)
3696 {
3697 	zfs_cmd_t zc = { 0 };
3698 
3699 	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
3700 
3701 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc) != 0) {
3702 		switch (errno) {
3703 		case ENXIO:
3704 			/*
3705 			 * Silently ignore the case where the link no longer
3706 			 * exists, so that 'zfs volfini' can be run multiple
3707 			 * times without errors.
3708 			 */
3709 			return (0);
3710 
3711 		default:
3712 			return (zfs_standard_error_fmt(hdl, errno,
3713 			    dgettext(TEXT_DOMAIN, "cannot remove device "
3714 			    "links for '%s'"), dataset));
3715 		}
3716 	}
3717 
3718 	return (0);
3719 }
3720 
3721 nvlist_t *
3722 zfs_get_user_props(zfs_handle_t *zhp)
3723 {
3724 	return (zhp->zfs_user_props);
3725 }
3726 
3727 /*
3728  * This function is used by 'zfs list' to determine the exact set of columns to
3729  * display, and their maximum widths.  This does two main things:
3730  *
3731  *      - If this is a list of all properties, then expand the list to include
3732  *        all native properties, and set a flag so that for each dataset we look
3733  *        for new unique user properties and add them to the list.
3734  *
3735  *      - For non fixed-width properties, keep track of the maximum width seen
3736  *        so that we can size the column appropriately.
3737  */
3738 int
3739 zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp)
3740 {
3741 	libzfs_handle_t *hdl = zhp->zfs_hdl;
3742 	zprop_list_t *entry;
3743 	zprop_list_t **last, **start;
3744 	nvlist_t *userprops, *propval;
3745 	nvpair_t *elem;
3746 	char *strval;
3747 	char buf[ZFS_MAXPROPLEN];
3748 
3749 	if (zprop_expand_list(hdl, plp, ZFS_TYPE_DATASET) != 0)
3750 		return (-1);
3751 
3752 	userprops = zfs_get_user_props(zhp);
3753 
3754 	entry = *plp;
3755 	if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) {
3756 		/*
3757 		 * Go through and add any user properties as necessary.  We
3758 		 * start by incrementing our list pointer to the first
3759 		 * non-native property.
3760 		 */
3761 		start = plp;
3762 		while (*start != NULL) {
3763 			if ((*start)->pl_prop == ZPROP_INVAL)
3764 				break;
3765 			start = &(*start)->pl_next;
3766 		}
3767 
3768 		elem = NULL;
3769 		while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) {
3770 			/*
3771 			 * See if we've already found this property in our list.
3772 			 */
3773 			for (last = start; *last != NULL;
3774 			    last = &(*last)->pl_next) {
3775 				if (strcmp((*last)->pl_user_prop,
3776 				    nvpair_name(elem)) == 0)
3777 					break;
3778 			}
3779 
3780 			if (*last == NULL) {
3781 				if ((entry = zfs_alloc(hdl,
3782 				    sizeof (zprop_list_t))) == NULL ||
3783 				    ((entry->pl_user_prop = zfs_strdup(hdl,
3784 				    nvpair_name(elem)))) == NULL) {
3785 					free(entry);
3786 					return (-1);
3787 				}
3788 
3789 				entry->pl_prop = ZPROP_INVAL;
3790 				entry->pl_width = strlen(nvpair_name(elem));
3791 				entry->pl_all = B_TRUE;
3792 				*last = entry;
3793 			}
3794 		}
3795 	}
3796 
3797 	/*
3798 	 * Now go through and check the width of any non-fixed columns
3799 	 */
3800 	for (entry = *plp; entry != NULL; entry = entry->pl_next) {
3801 		if (entry->pl_fixed)
3802 			continue;
3803 
3804 		if (entry->pl_prop != ZPROP_INVAL) {
3805 			if (zfs_prop_get(zhp, entry->pl_prop,
3806 			    buf, sizeof (buf), NULL, NULL, 0, B_FALSE) == 0) {
3807 				if (strlen(buf) > entry->pl_width)
3808 					entry->pl_width = strlen(buf);
3809 			}
3810 		} else if (nvlist_lookup_nvlist(userprops,
3811 		    entry->pl_user_prop, &propval)  == 0) {
3812 			verify(nvlist_lookup_string(propval,
3813 			    ZPROP_VALUE, &strval) == 0);
3814 			if (strlen(strval) > entry->pl_width)
3815 				entry->pl_width = strlen(strval);
3816 		}
3817 	}
3818 
3819 	return (0);
3820 }
3821 
3822 int
3823 zfs_iscsi_perm_check(libzfs_handle_t *hdl, char *dataset, ucred_t *cred)
3824 {
3825 	zfs_cmd_t zc = { 0 };
3826 	nvlist_t *nvp;
3827 	gid_t gid;
3828 	uid_t uid;
3829 	const gid_t *groups;
3830 	int group_cnt;
3831 	int error;
3832 
3833 	if (nvlist_alloc(&nvp, NV_UNIQUE_NAME, 0) != 0)
3834 		return (no_memory(hdl));
3835 
3836 	uid = ucred_geteuid(cred);
3837 	gid = ucred_getegid(cred);
3838 	group_cnt = ucred_getgroups(cred, &groups);
3839 
3840 	if (uid == (uid_t)-1 || gid == (uid_t)-1 || group_cnt == (uid_t)-1)
3841 		return (1);
3842 
3843 	if (nvlist_add_uint32(nvp, ZFS_DELEG_PERM_UID, uid) != 0) {
3844 		nvlist_free(nvp);
3845 		return (1);
3846 	}
3847 
3848 	if (nvlist_add_uint32(nvp, ZFS_DELEG_PERM_GID, gid) != 0) {
3849 		nvlist_free(nvp);
3850 		return (1);
3851 	}
3852 
3853 	if (nvlist_add_uint32_array(nvp,
3854 	    ZFS_DELEG_PERM_GROUPS, (uint32_t *)groups, group_cnt) != 0) {
3855 		nvlist_free(nvp);
3856 		return (1);
3857 	}
3858 	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
3859 
3860 	if (zcmd_write_src_nvlist(hdl, &zc, nvp))
3861 		return (-1);
3862 
3863 	error = ioctl(hdl->libzfs_fd, ZFS_IOC_ISCSI_PERM_CHECK, &zc);
3864 	nvlist_free(nvp);
3865 	return (error);
3866 }
3867 
3868 int
3869 zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path,
3870     char *resource, void *export, void *sharetab,
3871     int sharemax, zfs_share_op_t operation)
3872 {
3873 	zfs_cmd_t zc = { 0 };
3874 	int error;
3875 
3876 	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
3877 	(void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
3878 	if (resource)
3879 		(void) strlcpy(zc.zc_string, resource, sizeof (zc.zc_string));
3880 	zc.zc_share.z_sharedata = (uint64_t)(uintptr_t)sharetab;
3881 	zc.zc_share.z_exportdata = (uint64_t)(uintptr_t)export;
3882 	zc.zc_share.z_sharetype = operation;
3883 	zc.zc_share.z_sharemax = sharemax;
3884 	error = ioctl(hdl->libzfs_fd, ZFS_IOC_SHARE, &zc);
3885 	return (error);
3886 }
3887 
3888 void
3889 zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props)
3890 {
3891 	nvpair_t *curr;
3892 
3893 	/*
3894 	 * Keep a reference to the props-table against which we prune the
3895 	 * properties.
3896 	 */
3897 	zhp->zfs_props_table = props;
3898 
3899 	curr = nvlist_next_nvpair(zhp->zfs_props, NULL);
3900 
3901 	while (curr) {
3902 		zfs_prop_t zfs_prop = zfs_name_to_prop(nvpair_name(curr));
3903 		nvpair_t *next = nvlist_next_nvpair(zhp->zfs_props, curr);
3904 
3905 		/*
3906 		 * We leave user:props in the nvlist, so there will be
3907 		 * some ZPROP_INVAL.  To be extra safe, don't prune
3908 		 * those.
3909 		 */
3910 		if (zfs_prop != ZPROP_INVAL && props[zfs_prop] == B_FALSE)
3911 			(void) nvlist_remove(zhp->zfs_props,
3912 			    nvpair_name(curr), nvpair_type(curr));
3913 		curr = next;
3914 	}
3915 }
3916 
3917 static int
3918 zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path,
3919     zfs_smb_acl_op_t cmd, char *resource1, char *resource2)
3920 {
3921 	zfs_cmd_t zc = { 0 };
3922 	nvlist_t *nvlist = NULL;
3923 	int error;
3924 
3925 	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
3926 	(void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
3927 	zc.zc_cookie = (uint64_t)cmd;
3928 
3929 	if (cmd == ZFS_SMB_ACL_RENAME) {
3930 		if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) {
3931 			(void) no_memory(hdl);
3932 			return (NULL);
3933 		}
3934 	}
3935 
3936 	switch (cmd) {
3937 	case ZFS_SMB_ACL_ADD:
3938 	case ZFS_SMB_ACL_REMOVE:
3939 		(void) strlcpy(zc.zc_string, resource1, sizeof (zc.zc_string));
3940 		break;
3941 	case ZFS_SMB_ACL_RENAME:
3942 		if (nvlist_add_string(nvlist, ZFS_SMB_ACL_SRC,
3943 		    resource1) != 0) {
3944 				(void) no_memory(hdl);
3945 				return (-1);
3946 		}
3947 		if (nvlist_add_string(nvlist, ZFS_SMB_ACL_TARGET,
3948 		    resource2) != 0) {
3949 				(void) no_memory(hdl);
3950 				return (-1);
3951 		}
3952 		if (zcmd_write_src_nvlist(hdl, &zc, nvlist) != 0) {
3953 			nvlist_free(nvlist);
3954 			return (-1);
3955 		}
3956 		break;
3957 	case ZFS_SMB_ACL_PURGE:
3958 		break;
3959 	default:
3960 		return (-1);
3961 	}
3962 	error = ioctl(hdl->libzfs_fd, ZFS_IOC_SMB_ACL, &zc);
3963 	if (nvlist)
3964 		nvlist_free(nvlist);
3965 	return (error);
3966 }
3967 
3968 int
3969 zfs_smb_acl_add(libzfs_handle_t *hdl, char *dataset,
3970     char *path, char *resource)
3971 {
3972 	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_ADD,
3973 	    resource, NULL));
3974 }
3975 
3976 int
3977 zfs_smb_acl_remove(libzfs_handle_t *hdl, char *dataset,
3978     char *path, char *resource)
3979 {
3980 	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_REMOVE,
3981 	    resource, NULL));
3982 }
3983 
3984 int
3985 zfs_smb_acl_purge(libzfs_handle_t *hdl, char *dataset, char *path)
3986 {
3987 	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_PURGE,
3988 	    NULL, NULL));
3989 }
3990 
3991 int
3992 zfs_smb_acl_rename(libzfs_handle_t *hdl, char *dataset, char *path,
3993     char *oldname, char *newname)
3994 {
3995 	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME,
3996 	    oldname, newname));
3997 }
3998 
3999 int
4000 zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
4001     zfs_userspace_cb_t func, void *arg)
4002 {
4003 	zfs_cmd_t zc = { 0 };
4004 	int error;
4005 	zfs_useracct_t buf[100];
4006 
4007 	(void) strncpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4008 
4009 	zc.zc_objset_type = type;
4010 	zc.zc_nvlist_dst = (uintptr_t)buf;
4011 
4012 	/* CONSTCOND */
4013 	while (1) {
4014 		zfs_useracct_t *zua = buf;
4015 
4016 		zc.zc_nvlist_dst_size = sizeof (buf);
4017 		error = ioctl(zhp->zfs_hdl->libzfs_fd,
4018 		    ZFS_IOC_USERSPACE_MANY, &zc);
4019 		if (error || zc.zc_nvlist_dst_size == 0)
4020 			break;
4021 
4022 		while (zc.zc_nvlist_dst_size > 0) {
4023 			error = func(arg, zua->zu_domain, zua->zu_rid,
4024 			    zua->zu_space);
4025 			if (error != 0)
4026 				return (error);
4027 			zua++;
4028 			zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t);
4029 		}
4030 	}
4031 
4032 	return (error);
4033 }
4034 
4035 int
4036 zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
4037     boolean_t recursive, boolean_t temphold)
4038 {
4039 	zfs_cmd_t zc = { 0 };
4040 	libzfs_handle_t *hdl = zhp->zfs_hdl;
4041 
4042 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4043 	(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
4044 	if (strlcpy(zc.zc_string, tag, sizeof (zc.zc_string))
4045 	    >= sizeof (zc.zc_string))
4046 		return (zfs_error(hdl, EZFS_TAGTOOLONG, tag));
4047 	zc.zc_cookie = recursive;
4048 	zc.zc_temphold = temphold;
4049 
4050 	if (zfs_ioctl(hdl, ZFS_IOC_HOLD, &zc) != 0) {
4051 		char errbuf[ZFS_MAXNAMELEN+32];
4052 
4053 		/*
4054 		 * if it was recursive, the one that actually failed will be in
4055 		 * zc.zc_name.
4056 		 */
4057 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4058 		    "cannot hold '%s@%s'"), zc.zc_name, snapname);
4059 		switch (errno) {
4060 		case ENOTSUP:
4061 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4062 			    "pool must be upgraded"));
4063 			return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
4064 		case EINVAL:
4065 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4066 		case EEXIST:
4067 			return (zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf));
4068 		default:
4069 			return (zfs_standard_error_fmt(hdl, errno, errbuf));
4070 		}
4071 	}
4072 
4073 	return (0);
4074 }
4075 
4076 struct hold_range_arg {
4077 	zfs_handle_t	*origin;
4078 	const char	*fromsnap;
4079 	const char	*tosnap;
4080 	char		lastsnapheld[ZFS_MAXNAMELEN];
4081 	const char	*tag;
4082 	boolean_t	temphold;
4083 	boolean_t	seento;
4084 	boolean_t	seenfrom;
4085 	boolean_t	holding;
4086 };
4087 
4088 static int
4089 zfs_hold_range_one(zfs_handle_t *zhp, void *arg)
4090 {
4091 	struct hold_range_arg *hra = arg;
4092 	const char *thissnap;
4093 	int error;
4094 
4095 	thissnap = strchr(zfs_get_name(zhp), '@') + 1;
4096 
4097 	if (hra->fromsnap && !hra->seenfrom &&
4098 	    strcmp(hra->fromsnap, thissnap) == 0)
4099 		hra->seenfrom = B_TRUE;
4100 
4101 	/* snap is older or newer than the desired range, ignore it */
4102 	if (hra->seento || !hra->seenfrom) {
4103 		zfs_close(zhp);
4104 		return (0);
4105 	}
4106 
4107 	if (hra->holding) {
4108 		error = zfs_hold(hra->origin, thissnap, hra->tag, B_FALSE,
4109 		    hra->temphold);
4110 		if (error == 0) {
4111 			(void) strlcpy(hra->lastsnapheld, zfs_get_name(zhp),
4112 			    sizeof (hra->lastsnapheld));
4113 		}
4114 	} else {
4115 		error = zfs_release(hra->origin, thissnap, hra->tag, B_FALSE);
4116 	}
4117 
4118 	if (!hra->seento && strcmp(hra->tosnap, thissnap) == 0)
4119 		hra->seento = B_TRUE;
4120 
4121 	zfs_close(zhp);
4122 	return (error);
4123 }
4124 
4125 /*
4126  * Add a user hold on the set of snapshots starting with fromsnap up to
4127  * and including tosnap. If we're unable to to acquire a particular hold,
4128  * undo any holds up to that point.
4129  */
4130 int
4131 zfs_hold_range(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
4132     const char *tag, boolean_t temphold)
4133 {
4134 	struct hold_range_arg arg = { 0 };
4135 	int error;
4136 
4137 	arg.origin = zhp;
4138 	arg.fromsnap = fromsnap;
4139 	arg.tosnap = tosnap;
4140 	arg.tag = tag;
4141 	arg.temphold = temphold;
4142 	arg.holding = B_TRUE;
4143 
4144 	error = zfs_iter_snapshots_sorted(zhp, zfs_hold_range_one, &arg);
4145 
4146 	/*
4147 	 * Make sure we either hold the entire range or none.
4148 	 */
4149 	if (error && arg.lastsnapheld[0] != '\0') {
4150 		(void) zfs_release_range(zhp, fromsnap,
4151 		    (const char *)arg.lastsnapheld, tag);
4152 	}
4153 	return (error);
4154 }
4155 
4156 int
4157 zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
4158     boolean_t recursive)
4159 {
4160 	zfs_cmd_t zc = { 0 };
4161 	libzfs_handle_t *hdl = zhp->zfs_hdl;
4162 
4163 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4164 	(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
4165 	if (strlcpy(zc.zc_string, tag, sizeof (zc.zc_string))
4166 	    >= sizeof (zc.zc_string))
4167 		return (zfs_error(hdl, EZFS_TAGTOOLONG, tag));
4168 	zc.zc_cookie = recursive;
4169 
4170 	if (zfs_ioctl(hdl, ZFS_IOC_RELEASE, &zc) != 0) {
4171 		char errbuf[ZFS_MAXNAMELEN+32];
4172 
4173 		/*
4174 		 * if it was recursive, the one that actually failed will be in
4175 		 * zc.zc_name.
4176 		 */
4177 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4178 		    "cannot release '%s@%s'"), zc.zc_name, snapname);
4179 		switch (errno) {
4180 		case ESRCH:
4181 			return (zfs_error(hdl, EZFS_REFTAG_RELE, errbuf));
4182 		case ENOTSUP:
4183 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4184 			    "pool must be upgraded"));
4185 			return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
4186 		case EINVAL:
4187 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4188 		default:
4189 			return (zfs_standard_error_fmt(hdl, errno, errbuf));
4190 		}
4191 	}
4192 
4193 	return (0);
4194 }
4195 
4196 /*
4197  * Release a user hold from the set of snapshots starting with fromsnap
4198  * up to and including tosnap.
4199  */
4200 int
4201 zfs_release_range(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
4202     const char *tag)
4203 {
4204 	struct hold_range_arg arg = { 0 };
4205 
4206 	arg.origin = zhp;
4207 	arg.fromsnap = fromsnap;
4208 	arg.tosnap = tosnap;
4209 	arg.tag = tag;
4210 
4211 	return (zfs_iter_snapshots_sorted(zhp, zfs_hold_range_one, &arg));
4212 }
4213