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