libzfs_dataset.c revision 339158
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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2018, Joyent, Inc. All rights reserved.
25 * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
26 * Copyright (c) 2012 DEY Storage Systems, Inc.  All rights reserved.
27 * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
28 * Copyright (c) 2013 Martin Matuska. All rights reserved.
29 * Copyright (c) 2013 Steven Hartland. All rights reserved.
30 * Copyright (c) 2014 Integros [integros.com]
31 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
32 * Copyright 2017 Nexenta Systems, Inc.
33 * Copyright 2017 RackTop Systems.
34 */
35
36#include <ctype.h>
37#include <errno.h>
38#include <libintl.h>
39#include <math.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <strings.h>
43#include <unistd.h>
44#include <stddef.h>
45#include <zone.h>
46#include <fcntl.h>
47#include <sys/mntent.h>
48#include <sys/mount.h>
49#include <priv.h>
50#include <pwd.h>
51#include <grp.h>
52#include <stddef.h>
53#ifdef illumos
54#include <idmap.h>
55#endif
56
57#include <sys/dnode.h>
58#include <sys/spa.h>
59#include <sys/zap.h>
60#include <sys/misc.h>
61#include <libzfs.h>
62
63#include "zfs_namecheck.h"
64#include "zfs_prop.h"
65#include "libzfs_impl.h"
66#include "zfs_deleg.h"
67
68static int userquota_propname_decode(const char *propname, boolean_t zoned,
69    zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp);
70
71/*
72 * Given a single type (not a mask of types), return the type in a human
73 * readable form.
74 */
75const char *
76zfs_type_to_name(zfs_type_t type)
77{
78	switch (type) {
79	case ZFS_TYPE_FILESYSTEM:
80		return (dgettext(TEXT_DOMAIN, "filesystem"));
81	case ZFS_TYPE_SNAPSHOT:
82		return (dgettext(TEXT_DOMAIN, "snapshot"));
83	case ZFS_TYPE_VOLUME:
84		return (dgettext(TEXT_DOMAIN, "volume"));
85	case ZFS_TYPE_POOL:
86		return (dgettext(TEXT_DOMAIN, "pool"));
87	case ZFS_TYPE_BOOKMARK:
88		return (dgettext(TEXT_DOMAIN, "bookmark"));
89	default:
90		assert(!"unhandled zfs_type_t");
91	}
92
93	return (NULL);
94}
95
96/*
97 * Validate a ZFS path.  This is used even before trying to open the dataset, to
98 * provide a more meaningful error message.  We call zfs_error_aux() to
99 * explain exactly why the name was not valid.
100 */
101int
102zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
103    boolean_t modifying)
104{
105	namecheck_err_t why;
106	char what;
107
108	if (entity_namecheck(path, &why, &what) != 0) {
109		if (hdl != NULL) {
110			switch (why) {
111			case NAME_ERR_TOOLONG:
112				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
113				    "name is too long"));
114				break;
115
116			case NAME_ERR_LEADING_SLASH:
117				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
118				    "leading slash in name"));
119				break;
120
121			case NAME_ERR_EMPTY_COMPONENT:
122				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
123				    "empty component in name"));
124				break;
125
126			case NAME_ERR_TRAILING_SLASH:
127				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
128				    "trailing slash in name"));
129				break;
130
131			case NAME_ERR_INVALCHAR:
132				zfs_error_aux(hdl,
133				    dgettext(TEXT_DOMAIN, "invalid character "
134				    "'%c' in name"), what);
135				break;
136
137			case NAME_ERR_MULTIPLE_DELIMITERS:
138				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
139				    "multiple '@' and/or '#' delimiters in "
140				    "name"));
141				break;
142
143			case NAME_ERR_NOLETTER:
144				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
145				    "pool doesn't begin with a letter"));
146				break;
147
148			case NAME_ERR_RESERVED:
149				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
150				    "name is reserved"));
151				break;
152
153			case NAME_ERR_DISKLIKE:
154				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
155				    "reserved disk name"));
156				break;
157
158			default:
159				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
160				    "(%d) not defined"), why);
161				break;
162			}
163		}
164
165		return (0);
166	}
167
168	if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
169		if (hdl != NULL)
170			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
171			    "snapshot delimiter '@' is not expected here"));
172		return (0);
173	}
174
175	if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) {
176		if (hdl != NULL)
177			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
178			    "missing '@' delimiter in snapshot name"));
179		return (0);
180	}
181
182	if (!(type & ZFS_TYPE_BOOKMARK) && strchr(path, '#') != NULL) {
183		if (hdl != NULL)
184			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
185			    "bookmark delimiter '#' is not expected here"));
186		return (0);
187	}
188
189	if (type == ZFS_TYPE_BOOKMARK && strchr(path, '#') == NULL) {
190		if (hdl != NULL)
191			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
192			    "missing '#' delimiter in bookmark name"));
193		return (0);
194	}
195
196	if (modifying && strchr(path, '%') != NULL) {
197		if (hdl != NULL)
198			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
199			    "invalid character %c in name"), '%');
200		return (0);
201	}
202
203	return (-1);
204}
205
206int
207zfs_name_valid(const char *name, zfs_type_t type)
208{
209	if (type == ZFS_TYPE_POOL)
210		return (zpool_name_valid(NULL, B_FALSE, name));
211	return (zfs_validate_name(NULL, name, type, B_FALSE));
212}
213
214/*
215 * This function takes the raw DSL properties, and filters out the user-defined
216 * properties into a separate nvlist.
217 */
218static nvlist_t *
219process_user_props(zfs_handle_t *zhp, nvlist_t *props)
220{
221	libzfs_handle_t *hdl = zhp->zfs_hdl;
222	nvpair_t *elem;
223	nvlist_t *propval;
224	nvlist_t *nvl;
225
226	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
227		(void) no_memory(hdl);
228		return (NULL);
229	}
230
231	elem = NULL;
232	while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
233		if (!zfs_prop_user(nvpair_name(elem)))
234			continue;
235
236		verify(nvpair_value_nvlist(elem, &propval) == 0);
237		if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) {
238			nvlist_free(nvl);
239			(void) no_memory(hdl);
240			return (NULL);
241		}
242	}
243
244	return (nvl);
245}
246
247static zpool_handle_t *
248zpool_add_handle(zfs_handle_t *zhp, const char *pool_name)
249{
250	libzfs_handle_t *hdl = zhp->zfs_hdl;
251	zpool_handle_t *zph;
252
253	if ((zph = zpool_open_canfail(hdl, pool_name)) != NULL) {
254		if (hdl->libzfs_pool_handles != NULL)
255			zph->zpool_next = hdl->libzfs_pool_handles;
256		hdl->libzfs_pool_handles = zph;
257	}
258	return (zph);
259}
260
261static zpool_handle_t *
262zpool_find_handle(zfs_handle_t *zhp, const char *pool_name, int len)
263{
264	libzfs_handle_t *hdl = zhp->zfs_hdl;
265	zpool_handle_t *zph = hdl->libzfs_pool_handles;
266
267	while ((zph != NULL) &&
268	    (strncmp(pool_name, zpool_get_name(zph), len) != 0))
269		zph = zph->zpool_next;
270	return (zph);
271}
272
273/*
274 * Returns a handle to the pool that contains the provided dataset.
275 * If a handle to that pool already exists then that handle is returned.
276 * Otherwise, a new handle is created and added to the list of handles.
277 */
278static zpool_handle_t *
279zpool_handle(zfs_handle_t *zhp)
280{
281	char *pool_name;
282	int len;
283	zpool_handle_t *zph;
284
285	len = strcspn(zhp->zfs_name, "/@#") + 1;
286	pool_name = zfs_alloc(zhp->zfs_hdl, len);
287	(void) strlcpy(pool_name, zhp->zfs_name, len);
288
289	zph = zpool_find_handle(zhp, pool_name, len);
290	if (zph == NULL)
291		zph = zpool_add_handle(zhp, pool_name);
292
293	free(pool_name);
294	return (zph);
295}
296
297void
298zpool_free_handles(libzfs_handle_t *hdl)
299{
300	zpool_handle_t *next, *zph = hdl->libzfs_pool_handles;
301
302	while (zph != NULL) {
303		next = zph->zpool_next;
304		zpool_close(zph);
305		zph = next;
306	}
307	hdl->libzfs_pool_handles = NULL;
308}
309
310/*
311 * Utility function to gather stats (objset and zpl) for the given object.
312 */
313static int
314get_stats_ioctl(zfs_handle_t *zhp, zfs_cmd_t *zc)
315{
316	libzfs_handle_t *hdl = zhp->zfs_hdl;
317
318	(void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
319
320	while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, zc) != 0) {
321		if (errno == ENOMEM) {
322			if (zcmd_expand_dst_nvlist(hdl, zc) != 0) {
323				return (-1);
324			}
325		} else {
326			return (-1);
327		}
328	}
329	return (0);
330}
331
332/*
333 * Utility function to get the received properties of the given object.
334 */
335static int
336get_recvd_props_ioctl(zfs_handle_t *zhp)
337{
338	libzfs_handle_t *hdl = zhp->zfs_hdl;
339	nvlist_t *recvdprops;
340	zfs_cmd_t zc = { 0 };
341	int err;
342
343	if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
344		return (-1);
345
346	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
347
348	while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_RECVD_PROPS, &zc) != 0) {
349		if (errno == ENOMEM) {
350			if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
351				return (-1);
352			}
353		} else {
354			zcmd_free_nvlists(&zc);
355			return (-1);
356		}
357	}
358
359	err = zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &recvdprops);
360	zcmd_free_nvlists(&zc);
361	if (err != 0)
362		return (-1);
363
364	nvlist_free(zhp->zfs_recvd_props);
365	zhp->zfs_recvd_props = recvdprops;
366
367	return (0);
368}
369
370static int
371put_stats_zhdl(zfs_handle_t *zhp, zfs_cmd_t *zc)
372{
373	nvlist_t *allprops, *userprops;
374
375	zhp->zfs_dmustats = zc->zc_objset_stats; /* structure assignment */
376
377	if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) {
378		return (-1);
379	}
380
381	/*
382	 * XXX Why do we store the user props separately, in addition to
383	 * storing them in zfs_props?
384	 */
385	if ((userprops = process_user_props(zhp, allprops)) == NULL) {
386		nvlist_free(allprops);
387		return (-1);
388	}
389
390	nvlist_free(zhp->zfs_props);
391	nvlist_free(zhp->zfs_user_props);
392
393	zhp->zfs_props = allprops;
394	zhp->zfs_user_props = userprops;
395
396	return (0);
397}
398
399static int
400get_stats(zfs_handle_t *zhp)
401{
402	int rc = 0;
403	zfs_cmd_t zc = { 0 };
404
405	if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
406		return (-1);
407	if (get_stats_ioctl(zhp, &zc) != 0)
408		rc = -1;
409	else if (put_stats_zhdl(zhp, &zc) != 0)
410		rc = -1;
411	zcmd_free_nvlists(&zc);
412	return (rc);
413}
414
415/*
416 * Refresh the properties currently stored in the handle.
417 */
418void
419zfs_refresh_properties(zfs_handle_t *zhp)
420{
421	(void) get_stats(zhp);
422}
423
424/*
425 * Makes a handle from the given dataset name.  Used by zfs_open() and
426 * zfs_iter_* to create child handles on the fly.
427 */
428static int
429make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc)
430{
431	if (put_stats_zhdl(zhp, zc) != 0)
432		return (-1);
433
434	/*
435	 * We've managed to open the dataset and gather statistics.  Determine
436	 * the high-level type.
437	 */
438	if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
439		zhp->zfs_head_type = ZFS_TYPE_VOLUME;
440	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
441		zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM;
442	else
443		abort();
444
445	if (zhp->zfs_dmustats.dds_is_snapshot)
446		zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
447	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
448		zhp->zfs_type = ZFS_TYPE_VOLUME;
449	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
450		zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
451	else
452		abort();	/* we should never see any other types */
453
454	if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL)
455		return (-1);
456
457	return (0);
458}
459
460zfs_handle_t *
461make_dataset_handle(libzfs_handle_t *hdl, const char *path)
462{
463	zfs_cmd_t zc = { 0 };
464
465	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
466
467	if (zhp == NULL)
468		return (NULL);
469
470	zhp->zfs_hdl = hdl;
471	(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
472	if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) {
473		free(zhp);
474		return (NULL);
475	}
476	if (get_stats_ioctl(zhp, &zc) == -1) {
477		zcmd_free_nvlists(&zc);
478		free(zhp);
479		return (NULL);
480	}
481	if (make_dataset_handle_common(zhp, &zc) == -1) {
482		free(zhp);
483		zhp = NULL;
484	}
485	zcmd_free_nvlists(&zc);
486	return (zhp);
487}
488
489zfs_handle_t *
490make_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
491{
492	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
493
494	if (zhp == NULL)
495		return (NULL);
496
497	zhp->zfs_hdl = hdl;
498	(void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name));
499	if (make_dataset_handle_common(zhp, zc) == -1) {
500		free(zhp);
501		return (NULL);
502	}
503	return (zhp);
504}
505
506zfs_handle_t *
507make_dataset_simple_handle_zc(zfs_handle_t *pzhp, zfs_cmd_t *zc)
508{
509	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
510
511	if (zhp == NULL)
512		return (NULL);
513
514	zhp->zfs_hdl = pzhp->zfs_hdl;
515	(void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name));
516	zhp->zfs_head_type = pzhp->zfs_type;
517	zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
518	zhp->zpool_hdl = zpool_handle(zhp);
519	return (zhp);
520}
521
522zfs_handle_t *
523zfs_handle_dup(zfs_handle_t *zhp_orig)
524{
525	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
526
527	if (zhp == NULL)
528		return (NULL);
529
530	zhp->zfs_hdl = zhp_orig->zfs_hdl;
531	zhp->zpool_hdl = zhp_orig->zpool_hdl;
532	(void) strlcpy(zhp->zfs_name, zhp_orig->zfs_name,
533	    sizeof (zhp->zfs_name));
534	zhp->zfs_type = zhp_orig->zfs_type;
535	zhp->zfs_head_type = zhp_orig->zfs_head_type;
536	zhp->zfs_dmustats = zhp_orig->zfs_dmustats;
537	if (zhp_orig->zfs_props != NULL) {
538		if (nvlist_dup(zhp_orig->zfs_props, &zhp->zfs_props, 0) != 0) {
539			(void) no_memory(zhp->zfs_hdl);
540			zfs_close(zhp);
541			return (NULL);
542		}
543	}
544	if (zhp_orig->zfs_user_props != NULL) {
545		if (nvlist_dup(zhp_orig->zfs_user_props,
546		    &zhp->zfs_user_props, 0) != 0) {
547			(void) no_memory(zhp->zfs_hdl);
548			zfs_close(zhp);
549			return (NULL);
550		}
551	}
552	if (zhp_orig->zfs_recvd_props != NULL) {
553		if (nvlist_dup(zhp_orig->zfs_recvd_props,
554		    &zhp->zfs_recvd_props, 0)) {
555			(void) no_memory(zhp->zfs_hdl);
556			zfs_close(zhp);
557			return (NULL);
558		}
559	}
560	zhp->zfs_mntcheck = zhp_orig->zfs_mntcheck;
561	if (zhp_orig->zfs_mntopts != NULL) {
562		zhp->zfs_mntopts = zfs_strdup(zhp_orig->zfs_hdl,
563		    zhp_orig->zfs_mntopts);
564	}
565	zhp->zfs_props_table = zhp_orig->zfs_props_table;
566	return (zhp);
567}
568
569boolean_t
570zfs_bookmark_exists(const char *path)
571{
572	nvlist_t *bmarks;
573	nvlist_t *props;
574	char fsname[ZFS_MAX_DATASET_NAME_LEN];
575	char *bmark_name;
576	char *pound;
577	int err;
578	boolean_t rv;
579
580
581	(void) strlcpy(fsname, path, sizeof (fsname));
582	pound = strchr(fsname, '#');
583	if (pound == NULL)
584		return (B_FALSE);
585
586	*pound = '\0';
587	bmark_name = pound + 1;
588	props = fnvlist_alloc();
589	err = lzc_get_bookmarks(fsname, props, &bmarks);
590	nvlist_free(props);
591	if (err != 0) {
592		nvlist_free(bmarks);
593		return (B_FALSE);
594	}
595
596	rv = nvlist_exists(bmarks, bmark_name);
597	nvlist_free(bmarks);
598	return (rv);
599}
600
601zfs_handle_t *
602make_bookmark_handle(zfs_handle_t *parent, const char *path,
603    nvlist_t *bmark_props)
604{
605	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
606
607	if (zhp == NULL)
608		return (NULL);
609
610	/* Fill in the name. */
611	zhp->zfs_hdl = parent->zfs_hdl;
612	(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
613
614	/* Set the property lists. */
615	if (nvlist_dup(bmark_props, &zhp->zfs_props, 0) != 0) {
616		free(zhp);
617		return (NULL);
618	}
619
620	/* Set the types. */
621	zhp->zfs_head_type = parent->zfs_head_type;
622	zhp->zfs_type = ZFS_TYPE_BOOKMARK;
623
624	if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL) {
625		nvlist_free(zhp->zfs_props);
626		free(zhp);
627		return (NULL);
628	}
629
630	return (zhp);
631}
632
633struct zfs_open_bookmarks_cb_data {
634	const char *path;
635	zfs_handle_t *zhp;
636};
637
638static int
639zfs_open_bookmarks_cb(zfs_handle_t *zhp, void *data)
640{
641	struct zfs_open_bookmarks_cb_data *dp = data;
642
643	/*
644	 * Is it the one we are looking for?
645	 */
646	if (strcmp(dp->path, zfs_get_name(zhp)) == 0) {
647		/*
648		 * We found it.  Save it and let the caller know we are done.
649		 */
650		dp->zhp = zhp;
651		return (EEXIST);
652	}
653
654	/*
655	 * Not found.  Close the handle and ask for another one.
656	 */
657	zfs_close(zhp);
658	return (0);
659}
660
661/*
662 * Opens the given snapshot, bookmark, filesystem, or volume.   The 'types'
663 * argument is a mask of acceptable types.  The function will print an
664 * appropriate error message and return NULL if it can't be opened.
665 */
666zfs_handle_t *
667zfs_open(libzfs_handle_t *hdl, const char *path, int types)
668{
669	zfs_handle_t *zhp;
670	char errbuf[1024];
671	char *bookp;
672
673	(void) snprintf(errbuf, sizeof (errbuf),
674	    dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
675
676	/*
677	 * Validate the name before we even try to open it.
678	 */
679	if (!zfs_validate_name(hdl, path, types, B_FALSE)) {
680		(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
681		return (NULL);
682	}
683
684	/*
685	 * Bookmarks needs to be handled separately.
686	 */
687	bookp = strchr(path, '#');
688	if (bookp == NULL) {
689		/*
690		 * Try to get stats for the dataset, which will tell us if it
691		 * exists.
692		 */
693		errno = 0;
694		if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
695			(void) zfs_standard_error(hdl, errno, errbuf);
696			return (NULL);
697		}
698	} else {
699		char dsname[ZFS_MAX_DATASET_NAME_LEN];
700		zfs_handle_t *pzhp;
701		struct zfs_open_bookmarks_cb_data cb_data = {path, NULL};
702
703		/*
704		 * We need to cut out '#' and everything after '#'
705		 * to get the parent dataset name only.
706		 */
707		assert(bookp - path < sizeof (dsname));
708		(void) strncpy(dsname, path, bookp - path);
709		dsname[bookp - path] = '\0';
710
711		/*
712		 * Create handle for the parent dataset.
713		 */
714		errno = 0;
715		if ((pzhp = make_dataset_handle(hdl, dsname)) == NULL) {
716			(void) zfs_standard_error(hdl, errno, errbuf);
717			return (NULL);
718		}
719
720		/*
721		 * Iterate bookmarks to find the right one.
722		 */
723		errno = 0;
724		if ((zfs_iter_bookmarks(pzhp, zfs_open_bookmarks_cb,
725		    &cb_data) == 0) && (cb_data.zhp == NULL)) {
726			(void) zfs_error(hdl, EZFS_NOENT, errbuf);
727			zfs_close(pzhp);
728			return (NULL);
729		}
730		if (cb_data.zhp == NULL) {
731			(void) zfs_standard_error(hdl, errno, errbuf);
732			zfs_close(pzhp);
733			return (NULL);
734		}
735		zhp = cb_data.zhp;
736
737		/*
738		 * Cleanup.
739		 */
740		zfs_close(pzhp);
741	}
742
743	if (zhp == NULL) {
744		char *at = strchr(path, '@');
745
746		if (at != NULL)
747			*at = '\0';
748		errno = 0;
749		if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
750			(void) zfs_standard_error(hdl, errno, errbuf);
751			return (NULL);
752		}
753		if (at != NULL)
754			*at = '@';
755		(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
756		zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
757	}
758
759	if (!(types & zhp->zfs_type)) {
760		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
761		zfs_close(zhp);
762		return (NULL);
763	}
764
765	return (zhp);
766}
767
768/*
769 * Release a ZFS handle.  Nothing to do but free the associated memory.
770 */
771void
772zfs_close(zfs_handle_t *zhp)
773{
774	if (zhp->zfs_mntopts)
775		free(zhp->zfs_mntopts);
776	nvlist_free(zhp->zfs_props);
777	nvlist_free(zhp->zfs_user_props);
778	nvlist_free(zhp->zfs_recvd_props);
779	free(zhp);
780}
781
782typedef struct mnttab_node {
783	struct mnttab mtn_mt;
784	avl_node_t mtn_node;
785} mnttab_node_t;
786
787static int
788libzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
789{
790	const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1;
791	const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2;
792	int rv;
793
794	rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
795
796	return (AVL_ISIGN(rv));
797}
798
799void
800libzfs_mnttab_init(libzfs_handle_t *hdl)
801{
802	assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0);
803	avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare,
804	    sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node));
805}
806
807void
808libzfs_mnttab_update(libzfs_handle_t *hdl)
809{
810	struct mnttab entry;
811
812	rewind(hdl->libzfs_mnttab);
813	while (getmntent(hdl->libzfs_mnttab, &entry) == 0) {
814		mnttab_node_t *mtn;
815
816		if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
817			continue;
818		mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
819		mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special);
820		mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp);
821		mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype);
822		mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts);
823		avl_add(&hdl->libzfs_mnttab_cache, mtn);
824	}
825}
826
827void
828libzfs_mnttab_fini(libzfs_handle_t *hdl)
829{
830	void *cookie = NULL;
831	mnttab_node_t *mtn;
832
833	while ((mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie))
834	    != NULL) {
835		free(mtn->mtn_mt.mnt_special);
836		free(mtn->mtn_mt.mnt_mountp);
837		free(mtn->mtn_mt.mnt_fstype);
838		free(mtn->mtn_mt.mnt_mntopts);
839		free(mtn);
840	}
841	avl_destroy(&hdl->libzfs_mnttab_cache);
842}
843
844void
845libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable)
846{
847	hdl->libzfs_mnttab_enable = enable;
848}
849
850int
851libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
852    struct mnttab *entry)
853{
854	mnttab_node_t find;
855	mnttab_node_t *mtn;
856
857	if (!hdl->libzfs_mnttab_enable) {
858		struct mnttab srch = { 0 };
859
860		if (avl_numnodes(&hdl->libzfs_mnttab_cache))
861			libzfs_mnttab_fini(hdl);
862		rewind(hdl->libzfs_mnttab);
863		srch.mnt_special = (char *)fsname;
864		srch.mnt_fstype = MNTTYPE_ZFS;
865		if (getmntany(hdl->libzfs_mnttab, entry, &srch) == 0)
866			return (0);
867		else
868			return (ENOENT);
869	}
870
871	if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0)
872		libzfs_mnttab_update(hdl);
873
874	find.mtn_mt.mnt_special = (char *)fsname;
875	mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL);
876	if (mtn) {
877		*entry = mtn->mtn_mt;
878		return (0);
879	}
880	return (ENOENT);
881}
882
883void
884libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,
885    const char *mountp, const char *mntopts)
886{
887	mnttab_node_t *mtn;
888
889	if (avl_numnodes(&hdl->libzfs_mnttab_cache) == 0)
890		return;
891	mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
892	mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special);
893	mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp);
894	mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS);
895	mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts);
896	avl_add(&hdl->libzfs_mnttab_cache, mtn);
897}
898
899void
900libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
901{
902	mnttab_node_t find;
903	mnttab_node_t *ret;
904
905	find.mtn_mt.mnt_special = (char *)fsname;
906	if ((ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL))
907	    != NULL) {
908		avl_remove(&hdl->libzfs_mnttab_cache, ret);
909		free(ret->mtn_mt.mnt_special);
910		free(ret->mtn_mt.mnt_mountp);
911		free(ret->mtn_mt.mnt_fstype);
912		free(ret->mtn_mt.mnt_mntopts);
913		free(ret);
914	}
915}
916
917int
918zfs_spa_version(zfs_handle_t *zhp, int *spa_version)
919{
920	zpool_handle_t *zpool_handle = zhp->zpool_hdl;
921
922	if (zpool_handle == NULL)
923		return (-1);
924
925	*spa_version = zpool_get_prop_int(zpool_handle,
926	    ZPOOL_PROP_VERSION, NULL);
927	return (0);
928}
929
930/*
931 * The choice of reservation property depends on the SPA version.
932 */
933static int
934zfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop)
935{
936	int spa_version;
937
938	if (zfs_spa_version(zhp, &spa_version) < 0)
939		return (-1);
940
941	if (spa_version >= SPA_VERSION_REFRESERVATION)
942		*resv_prop = ZFS_PROP_REFRESERVATION;
943	else
944		*resv_prop = ZFS_PROP_RESERVATION;
945
946	return (0);
947}
948
949/*
950 * Given an nvlist of properties to set, validates that they are correct, and
951 * parses any numeric properties (index, boolean, etc) if they are specified as
952 * strings.
953 */
954nvlist_t *
955zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
956    uint64_t zoned, zfs_handle_t *zhp, zpool_handle_t *zpool_hdl,
957    const char *errbuf)
958{
959	nvpair_t *elem;
960	uint64_t intval;
961	char *strval;
962	zfs_prop_t prop;
963	nvlist_t *ret;
964	int chosen_normal = -1;
965	int chosen_utf = -1;
966
967	if (nvlist_alloc(&ret, NV_UNIQUE_NAME, 0) != 0) {
968		(void) no_memory(hdl);
969		return (NULL);
970	}
971
972	/*
973	 * Make sure this property is valid and applies to this type.
974	 */
975
976	elem = NULL;
977	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
978		const char *propname = nvpair_name(elem);
979
980		prop = zfs_name_to_prop(propname);
981		if (prop == ZPROP_INVAL && zfs_prop_user(propname)) {
982			/*
983			 * This is a user property: make sure it's a
984			 * string, and that it's less than ZAP_MAXNAMELEN.
985			 */
986			if (nvpair_type(elem) != DATA_TYPE_STRING) {
987				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
988				    "'%s' must be a string"), propname);
989				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
990				goto error;
991			}
992
993			if (strlen(nvpair_name(elem)) >= ZAP_MAXNAMELEN) {
994				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
995				    "property name '%s' is too long"),
996				    propname);
997				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
998				goto error;
999			}
1000
1001			(void) nvpair_value_string(elem, &strval);
1002			if (nvlist_add_string(ret, propname, strval) != 0) {
1003				(void) no_memory(hdl);
1004				goto error;
1005			}
1006			continue;
1007		}
1008
1009		/*
1010		 * Currently, only user properties can be modified on
1011		 * snapshots.
1012		 */
1013		if (type == ZFS_TYPE_SNAPSHOT) {
1014			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1015			    "this property can not be modified for snapshots"));
1016			(void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
1017			goto error;
1018		}
1019
1020		if (prop == ZPROP_INVAL && zfs_prop_userquota(propname)) {
1021			zfs_userquota_prop_t uqtype;
1022			char newpropname[128];
1023			char domain[128];
1024			uint64_t rid;
1025			uint64_t valary[3];
1026
1027			if (userquota_propname_decode(propname, zoned,
1028			    &uqtype, domain, sizeof (domain), &rid) != 0) {
1029				zfs_error_aux(hdl,
1030				    dgettext(TEXT_DOMAIN,
1031				    "'%s' has an invalid user/group name"),
1032				    propname);
1033				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1034				goto error;
1035			}
1036
1037			if (uqtype != ZFS_PROP_USERQUOTA &&
1038			    uqtype != ZFS_PROP_GROUPQUOTA) {
1039				zfs_error_aux(hdl,
1040				    dgettext(TEXT_DOMAIN, "'%s' is readonly"),
1041				    propname);
1042				(void) zfs_error(hdl, EZFS_PROPREADONLY,
1043				    errbuf);
1044				goto error;
1045			}
1046
1047			if (nvpair_type(elem) == DATA_TYPE_STRING) {
1048				(void) nvpair_value_string(elem, &strval);
1049				if (strcmp(strval, "none") == 0) {
1050					intval = 0;
1051				} else if (zfs_nicestrtonum(hdl,
1052				    strval, &intval) != 0) {
1053					(void) zfs_error(hdl,
1054					    EZFS_BADPROP, errbuf);
1055					goto error;
1056				}
1057			} else if (nvpair_type(elem) ==
1058			    DATA_TYPE_UINT64) {
1059				(void) nvpair_value_uint64(elem, &intval);
1060				if (intval == 0) {
1061					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1062					    "use 'none' to disable "
1063					    "userquota/groupquota"));
1064					goto error;
1065				}
1066			} else {
1067				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1068				    "'%s' must be a number"), propname);
1069				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1070				goto error;
1071			}
1072
1073			/*
1074			 * Encode the prop name as
1075			 * userquota@<hex-rid>-domain, to make it easy
1076			 * for the kernel to decode.
1077			 */
1078			(void) snprintf(newpropname, sizeof (newpropname),
1079			    "%s%llx-%s", zfs_userquota_prop_prefixes[uqtype],
1080			    (longlong_t)rid, domain);
1081			valary[0] = uqtype;
1082			valary[1] = rid;
1083			valary[2] = intval;
1084			if (nvlist_add_uint64_array(ret, newpropname,
1085			    valary, 3) != 0) {
1086				(void) no_memory(hdl);
1087				goto error;
1088			}
1089			continue;
1090		} else if (prop == ZPROP_INVAL && zfs_prop_written(propname)) {
1091			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1092			    "'%s' is readonly"),
1093			    propname);
1094			(void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
1095			goto error;
1096		}
1097
1098		if (prop == ZPROP_INVAL) {
1099			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1100			    "invalid property '%s'"), propname);
1101			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1102			goto error;
1103		}
1104
1105		if (!zfs_prop_valid_for_type(prop, type)) {
1106			zfs_error_aux(hdl,
1107			    dgettext(TEXT_DOMAIN, "'%s' does not "
1108			    "apply to datasets of this type"), propname);
1109			(void) zfs_error(hdl, EZFS_PROPTYPE, errbuf);
1110			goto error;
1111		}
1112
1113		if (zfs_prop_readonly(prop) &&
1114		    (!zfs_prop_setonce(prop) || zhp != NULL)) {
1115			zfs_error_aux(hdl,
1116			    dgettext(TEXT_DOMAIN, "'%s' is readonly"),
1117			    propname);
1118			(void) zfs_error(hdl, EZFS_PROPREADONLY, errbuf);
1119			goto error;
1120		}
1121
1122		if (zprop_parse_value(hdl, elem, prop, type, ret,
1123		    &strval, &intval, errbuf) != 0)
1124			goto error;
1125
1126		/*
1127		 * Perform some additional checks for specific properties.
1128		 */
1129		switch (prop) {
1130		case ZFS_PROP_VERSION:
1131		{
1132			int version;
1133
1134			if (zhp == NULL)
1135				break;
1136			version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
1137			if (intval < version) {
1138				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1139				    "Can not downgrade; already at version %u"),
1140				    version);
1141				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1142				goto error;
1143			}
1144			break;
1145		}
1146
1147		case ZFS_PROP_VOLBLOCKSIZE:
1148		case ZFS_PROP_RECORDSIZE:
1149		{
1150			int maxbs = SPA_MAXBLOCKSIZE;
1151			if (zpool_hdl != NULL) {
1152				maxbs = zpool_get_prop_int(zpool_hdl,
1153				    ZPOOL_PROP_MAXBLOCKSIZE, NULL);
1154			}
1155			/*
1156			 * Volumes are limited to a volblocksize of 128KB,
1157			 * because they typically service workloads with
1158			 * small random writes, which incur a large performance
1159			 * penalty with large blocks.
1160			 */
1161			if (prop == ZFS_PROP_VOLBLOCKSIZE)
1162				maxbs = SPA_OLD_MAXBLOCKSIZE;
1163			/*
1164			 * The value must be a power of two between
1165			 * SPA_MINBLOCKSIZE and maxbs.
1166			 */
1167			if (intval < SPA_MINBLOCKSIZE ||
1168			    intval > maxbs || !ISP2(intval)) {
1169				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1170				    "'%s' must be power of 2 from 512B "
1171				    "to %uKB"), propname, maxbs >> 10);
1172				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1173				goto error;
1174			}
1175			break;
1176		}
1177		case ZFS_PROP_MLSLABEL:
1178		{
1179#ifdef illumos
1180			/*
1181			 * Verify the mlslabel string and convert to
1182			 * internal hex label string.
1183			 */
1184
1185			m_label_t *new_sl;
1186			char *hex = NULL;	/* internal label string */
1187
1188			/* Default value is already OK. */
1189			if (strcasecmp(strval, ZFS_MLSLABEL_DEFAULT) == 0)
1190				break;
1191
1192			/* Verify the label can be converted to binary form */
1193			if (((new_sl = m_label_alloc(MAC_LABEL)) == NULL) ||
1194			    (str_to_label(strval, &new_sl, MAC_LABEL,
1195			    L_NO_CORRECTION, NULL) == -1)) {
1196				goto badlabel;
1197			}
1198
1199			/* Now translate to hex internal label string */
1200			if (label_to_str(new_sl, &hex, M_INTERNAL,
1201			    DEF_NAMES) != 0) {
1202				if (hex)
1203					free(hex);
1204				goto badlabel;
1205			}
1206			m_label_free(new_sl);
1207
1208			/* If string is already in internal form, we're done. */
1209			if (strcmp(strval, hex) == 0) {
1210				free(hex);
1211				break;
1212			}
1213
1214			/* Replace the label string with the internal form. */
1215			(void) nvlist_remove(ret, zfs_prop_to_name(prop),
1216			    DATA_TYPE_STRING);
1217			verify(nvlist_add_string(ret, zfs_prop_to_name(prop),
1218			    hex) == 0);
1219			free(hex);
1220
1221			break;
1222
1223badlabel:
1224			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1225			    "invalid mlslabel '%s'"), strval);
1226			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1227			m_label_free(new_sl);	/* OK if null */
1228#else	/* !illumos */
1229			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1230			    "mlslabel is not supported on FreeBSD"));
1231			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1232#endif	/* illumos */
1233			goto error;
1234
1235		}
1236
1237		case ZFS_PROP_MOUNTPOINT:
1238		{
1239			namecheck_err_t why;
1240
1241			if (strcmp(strval, ZFS_MOUNTPOINT_NONE) == 0 ||
1242			    strcmp(strval, ZFS_MOUNTPOINT_LEGACY) == 0)
1243				break;
1244
1245			if (mountpoint_namecheck(strval, &why)) {
1246				switch (why) {
1247				case NAME_ERR_LEADING_SLASH:
1248					zfs_error_aux(hdl,
1249					    dgettext(TEXT_DOMAIN,
1250					    "'%s' must be an absolute path, "
1251					    "'none', or 'legacy'"), propname);
1252					break;
1253				case NAME_ERR_TOOLONG:
1254					zfs_error_aux(hdl,
1255					    dgettext(TEXT_DOMAIN,
1256					    "component of '%s' is too long"),
1257					    propname);
1258					break;
1259
1260				default:
1261					zfs_error_aux(hdl,
1262					    dgettext(TEXT_DOMAIN,
1263					    "(%d) not defined"),
1264					    why);
1265					break;
1266				}
1267				(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1268				goto error;
1269			}
1270		}
1271
1272			/*FALLTHRU*/
1273
1274		case ZFS_PROP_SHARESMB:
1275		case ZFS_PROP_SHARENFS:
1276			/*
1277			 * For the mountpoint and sharenfs or sharesmb
1278			 * properties, check if it can be set in a
1279			 * global/non-global zone based on
1280			 * the zoned property value:
1281			 *
1282			 *		global zone	    non-global zone
1283			 * --------------------------------------------------
1284			 * zoned=on	mountpoint (no)	    mountpoint (yes)
1285			 *		sharenfs (no)	    sharenfs (no)
1286			 *		sharesmb (no)	    sharesmb (no)
1287			 *
1288			 * zoned=off	mountpoint (yes)	N/A
1289			 *		sharenfs (yes)
1290			 *		sharesmb (yes)
1291			 */
1292			if (zoned) {
1293				if (getzoneid() == GLOBAL_ZONEID) {
1294					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1295					    "'%s' cannot be set on "
1296					    "dataset in a non-global zone"),
1297					    propname);
1298					(void) zfs_error(hdl, EZFS_ZONED,
1299					    errbuf);
1300					goto error;
1301				} else if (prop == ZFS_PROP_SHARENFS ||
1302				    prop == ZFS_PROP_SHARESMB) {
1303					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1304					    "'%s' cannot be set in "
1305					    "a non-global zone"), propname);
1306					(void) zfs_error(hdl, EZFS_ZONED,
1307					    errbuf);
1308					goto error;
1309				}
1310			} else if (getzoneid() != GLOBAL_ZONEID) {
1311				/*
1312				 * If zoned property is 'off', this must be in
1313				 * a global zone. If not, something is wrong.
1314				 */
1315				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1316				    "'%s' cannot be set while dataset "
1317				    "'zoned' property is set"), propname);
1318				(void) zfs_error(hdl, EZFS_ZONED, errbuf);
1319				goto error;
1320			}
1321
1322			/*
1323			 * At this point, it is legitimate to set the
1324			 * property. Now we want to make sure that the
1325			 * property value is valid if it is sharenfs.
1326			 */
1327			if ((prop == ZFS_PROP_SHARENFS ||
1328			    prop == ZFS_PROP_SHARESMB) &&
1329			    strcmp(strval, "on") != 0 &&
1330			    strcmp(strval, "off") != 0) {
1331				zfs_share_proto_t proto;
1332
1333				if (prop == ZFS_PROP_SHARESMB)
1334					proto = PROTO_SMB;
1335				else
1336					proto = PROTO_NFS;
1337
1338				/*
1339				 * Must be an valid sharing protocol
1340				 * option string so init the libshare
1341				 * in order to enable the parser and
1342				 * then parse the options. We use the
1343				 * control API since we don't care about
1344				 * the current configuration and don't
1345				 * want the overhead of loading it
1346				 * until we actually do something.
1347				 */
1348
1349				if (zfs_init_libshare(hdl,
1350				    SA_INIT_CONTROL_API) != SA_OK) {
1351					/*
1352					 * An error occurred so we can't do
1353					 * anything
1354					 */
1355					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1356					    "'%s' cannot be set: problem "
1357					    "in share initialization"),
1358					    propname);
1359					(void) zfs_error(hdl, EZFS_BADPROP,
1360					    errbuf);
1361					goto error;
1362				}
1363
1364				if (zfs_parse_options(strval, proto) != SA_OK) {
1365					/*
1366					 * There was an error in parsing so
1367					 * deal with it by issuing an error
1368					 * message and leaving after
1369					 * uninitializing the the libshare
1370					 * interface.
1371					 */
1372					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1373					    "'%s' cannot be set to invalid "
1374					    "options"), propname);
1375					(void) zfs_error(hdl, EZFS_BADPROP,
1376					    errbuf);
1377					zfs_uninit_libshare(hdl);
1378					goto error;
1379				}
1380				zfs_uninit_libshare(hdl);
1381			}
1382
1383			break;
1384
1385		case ZFS_PROP_UTF8ONLY:
1386			chosen_utf = (int)intval;
1387			break;
1388
1389		case ZFS_PROP_NORMALIZE:
1390			chosen_normal = (int)intval;
1391			break;
1392
1393		default:
1394			break;
1395		}
1396
1397		/*
1398		 * For changes to existing volumes, we have some additional
1399		 * checks to enforce.
1400		 */
1401		if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
1402			uint64_t volsize = zfs_prop_get_int(zhp,
1403			    ZFS_PROP_VOLSIZE);
1404			uint64_t blocksize = zfs_prop_get_int(zhp,
1405			    ZFS_PROP_VOLBLOCKSIZE);
1406			char buf[64];
1407
1408			switch (prop) {
1409			case ZFS_PROP_RESERVATION:
1410				if (intval > volsize) {
1411					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1412					    "'%s' is greater than current "
1413					    "volume size"), propname);
1414					(void) zfs_error(hdl, EZFS_BADPROP,
1415					    errbuf);
1416					goto error;
1417				}
1418				break;
1419
1420			case ZFS_PROP_REFRESERVATION:
1421				if (intval > volsize && intval != UINT64_MAX) {
1422					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1423					    "'%s' is greater than current "
1424					    "volume size"), propname);
1425					(void) zfs_error(hdl, EZFS_BADPROP,
1426					    errbuf);
1427					goto error;
1428				}
1429				break;
1430
1431			case ZFS_PROP_VOLSIZE:
1432				if (intval % blocksize != 0) {
1433					zfs_nicenum(blocksize, buf,
1434					    sizeof (buf));
1435					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1436					    "'%s' must be a multiple of "
1437					    "volume block size (%s)"),
1438					    propname, buf);
1439					(void) zfs_error(hdl, EZFS_BADPROP,
1440					    errbuf);
1441					goto error;
1442				}
1443
1444				if (intval == 0) {
1445					zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1446					    "'%s' cannot be zero"),
1447					    propname);
1448					(void) zfs_error(hdl, EZFS_BADPROP,
1449					    errbuf);
1450					goto error;
1451				}
1452				break;
1453
1454			default:
1455				break;
1456			}
1457		}
1458	}
1459
1460	/*
1461	 * If normalization was chosen, but no UTF8 choice was made,
1462	 * enforce rejection of non-UTF8 names.
1463	 *
1464	 * If normalization was chosen, but rejecting non-UTF8 names
1465	 * was explicitly not chosen, it is an error.
1466	 */
1467	if (chosen_normal > 0 && chosen_utf < 0) {
1468		if (nvlist_add_uint64(ret,
1469		    zfs_prop_to_name(ZFS_PROP_UTF8ONLY), 1) != 0) {
1470			(void) no_memory(hdl);
1471			goto error;
1472		}
1473	} else if (chosen_normal > 0 && chosen_utf == 0) {
1474		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1475		    "'%s' must be set 'on' if normalization chosen"),
1476		    zfs_prop_to_name(ZFS_PROP_UTF8ONLY));
1477		(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1478		goto error;
1479	}
1480	return (ret);
1481
1482error:
1483	nvlist_free(ret);
1484	return (NULL);
1485}
1486
1487int
1488zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl)
1489{
1490	uint64_t old_volsize;
1491	uint64_t new_volsize;
1492	uint64_t old_reservation;
1493	uint64_t new_reservation;
1494	zfs_prop_t resv_prop;
1495	nvlist_t *props;
1496
1497	/*
1498	 * If this is an existing volume, and someone is setting the volsize,
1499	 * make sure that it matches the reservation, or add it if necessary.
1500	 */
1501	old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
1502	if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
1503		return (-1);
1504	old_reservation = zfs_prop_get_int(zhp, resv_prop);
1505
1506	props = fnvlist_alloc();
1507	fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
1508	    zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
1509
1510	if ((zvol_volsize_to_reservation(old_volsize, props) !=
1511	    old_reservation) || nvlist_exists(nvl,
1512	    zfs_prop_to_name(resv_prop))) {
1513		fnvlist_free(props);
1514		return (0);
1515	}
1516	if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1517	    &new_volsize) != 0) {
1518		fnvlist_free(props);
1519		return (-1);
1520	}
1521	new_reservation = zvol_volsize_to_reservation(new_volsize, props);
1522	fnvlist_free(props);
1523
1524	if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
1525	    new_reservation) != 0) {
1526		(void) no_memory(zhp->zfs_hdl);
1527		return (-1);
1528	}
1529	return (1);
1530}
1531
1532/*
1533 * Helper for 'zfs {set|clone} refreservation=auto'.  Must be called after
1534 * zfs_valid_proplist(), as it is what sets the UINT64_MAX sentinal value.
1535 * Return codes must match zfs_add_synthetic_resv().
1536 */
1537static int
1538zfs_fix_auto_resv(zfs_handle_t *zhp, nvlist_t *nvl)
1539{
1540	uint64_t volsize;
1541	uint64_t resvsize;
1542	zfs_prop_t prop;
1543	nvlist_t *props;
1544
1545	if (!ZFS_IS_VOLUME(zhp)) {
1546		return (0);
1547	}
1548
1549	if (zfs_which_resv_prop(zhp, &prop) != 0) {
1550		return (-1);
1551	}
1552
1553	if (prop != ZFS_PROP_REFRESERVATION) {
1554		return (0);
1555	}
1556
1557	if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(prop), &resvsize) != 0) {
1558		/* No value being set, so it can't be "auto" */
1559		return (0);
1560	}
1561	if (resvsize != UINT64_MAX) {
1562		/* Being set to a value other than "auto" */
1563		return (0);
1564	}
1565
1566	props = fnvlist_alloc();
1567
1568	fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
1569	    zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
1570
1571	if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1572	    &volsize) != 0) {
1573		volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
1574	}
1575
1576	resvsize = zvol_volsize_to_reservation(volsize, props);
1577	fnvlist_free(props);
1578
1579	(void) nvlist_remove_all(nvl, zfs_prop_to_name(prop));
1580	if (nvlist_add_uint64(nvl, zfs_prop_to_name(prop), resvsize) != 0) {
1581		(void) no_memory(zhp->zfs_hdl);
1582		return (-1);
1583	}
1584	return (1);
1585}
1586
1587void
1588zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
1589    char *errbuf)
1590{
1591	switch (err) {
1592
1593	case ENOSPC:
1594		/*
1595		 * For quotas and reservations, ENOSPC indicates
1596		 * something different; setting a quota or reservation
1597		 * doesn't use any disk space.
1598		 */
1599		switch (prop) {
1600		case ZFS_PROP_QUOTA:
1601		case ZFS_PROP_REFQUOTA:
1602			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1603			    "size is less than current used or "
1604			    "reserved space"));
1605			(void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
1606			break;
1607
1608		case ZFS_PROP_RESERVATION:
1609		case ZFS_PROP_REFRESERVATION:
1610			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1611			    "size is greater than available space"));
1612			(void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
1613			break;
1614
1615		default:
1616			(void) zfs_standard_error(hdl, err, errbuf);
1617			break;
1618		}
1619		break;
1620
1621	case EBUSY:
1622		(void) zfs_standard_error(hdl, EBUSY, errbuf);
1623		break;
1624
1625	case EROFS:
1626		(void) zfs_error(hdl, EZFS_DSREADONLY, errbuf);
1627		break;
1628
1629	case E2BIG:
1630		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1631		    "property value too long"));
1632		(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1633		break;
1634
1635	case ENOTSUP:
1636		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1637		    "pool and or dataset must be upgraded to set this "
1638		    "property or value"));
1639		(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
1640		break;
1641
1642	case ERANGE:
1643	case EDOM:
1644		if (prop == ZFS_PROP_COMPRESSION ||
1645		    prop == ZFS_PROP_RECORDSIZE) {
1646			(void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1647			    "property setting is not allowed on "
1648			    "bootable datasets"));
1649			(void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
1650		} else if (prop == ZFS_PROP_CHECKSUM ||
1651		    prop == ZFS_PROP_DEDUP) {
1652			(void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1653			    "property setting is not allowed on "
1654			    "root pools"));
1655			(void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
1656		} else {
1657			(void) zfs_standard_error(hdl, err, errbuf);
1658		}
1659		break;
1660
1661	case EINVAL:
1662		if (prop == ZPROP_INVAL) {
1663			(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
1664		} else {
1665			(void) zfs_standard_error(hdl, err, errbuf);
1666		}
1667		break;
1668
1669	case EOVERFLOW:
1670		/*
1671		 * This platform can't address a volume this big.
1672		 */
1673#ifdef _ILP32
1674		if (prop == ZFS_PROP_VOLSIZE) {
1675			(void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf);
1676			break;
1677		}
1678#endif
1679		/* FALLTHROUGH */
1680	default:
1681		(void) zfs_standard_error(hdl, err, errbuf);
1682	}
1683}
1684
1685/*
1686 * Given a property name and value, set the property for the given dataset.
1687 */
1688int
1689zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
1690{
1691	int ret = -1;
1692	char errbuf[1024];
1693	libzfs_handle_t *hdl = zhp->zfs_hdl;
1694	nvlist_t *nvl = NULL;
1695
1696	(void) snprintf(errbuf, sizeof (errbuf),
1697	    dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1698	    zhp->zfs_name);
1699
1700	if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 ||
1701	    nvlist_add_string(nvl, propname, propval) != 0) {
1702		(void) no_memory(hdl);
1703		goto error;
1704	}
1705
1706	ret = zfs_prop_set_list(zhp, nvl);
1707
1708error:
1709	nvlist_free(nvl);
1710	return (ret);
1711}
1712
1713
1714
1715/*
1716 * Given an nvlist of property names and values, set the properties for the
1717 * given dataset.
1718 */
1719int
1720zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
1721{
1722	zfs_cmd_t zc = { 0 };
1723	int ret = -1;
1724	prop_changelist_t **cls = NULL;
1725	int cl_idx;
1726	char errbuf[1024];
1727	libzfs_handle_t *hdl = zhp->zfs_hdl;
1728	nvlist_t *nvl;
1729	int nvl_len;
1730	int added_resv = 0;
1731
1732	(void) snprintf(errbuf, sizeof (errbuf),
1733	    dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1734	    zhp->zfs_name);
1735
1736	if ((nvl = zfs_valid_proplist(hdl, zhp->zfs_type, props,
1737	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, zhp->zpool_hdl,
1738	    errbuf)) == NULL)
1739		goto error;
1740
1741	/*
1742	 * We have to check for any extra properties which need to be added
1743	 * before computing the length of the nvlist.
1744	 */
1745	for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
1746	    elem != NULL;
1747	    elem = nvlist_next_nvpair(nvl, elem)) {
1748		if (zfs_name_to_prop(nvpair_name(elem)) == ZFS_PROP_VOLSIZE &&
1749		    (added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1) {
1750			goto error;
1751		}
1752	}
1753
1754	if (added_resv != 1 &&
1755	    (added_resv = zfs_fix_auto_resv(zhp, nvl)) == -1) {
1756		goto error;
1757	}
1758
1759	/*
1760	 * Check how many properties we're setting and allocate an array to
1761	 * store changelist pointers for postfix().
1762	 */
1763	nvl_len = 0;
1764	for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
1765	    elem != NULL;
1766	    elem = nvlist_next_nvpair(nvl, elem))
1767		nvl_len++;
1768	if ((cls = calloc(nvl_len, sizeof (prop_changelist_t *))) == NULL)
1769		goto error;
1770
1771	cl_idx = 0;
1772	for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
1773	    elem != NULL;
1774	    elem = nvlist_next_nvpair(nvl, elem)) {
1775
1776		zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
1777
1778		assert(cl_idx < nvl_len);
1779		/*
1780		 * We don't want to unmount & remount the dataset when changing
1781		 * its canmount property to 'on' or 'noauto'.  We only use
1782		 * the changelist logic to unmount when setting canmount=off.
1783		 */
1784		if (prop != ZFS_PROP_CANMOUNT ||
1785		    (fnvpair_value_uint64(elem) == ZFS_CANMOUNT_OFF &&
1786		    zfs_is_mounted(zhp, NULL))) {
1787			cls[cl_idx] = changelist_gather(zhp, prop, 0, 0);
1788			if (cls[cl_idx] == NULL)
1789				goto error;
1790		}
1791
1792		if (prop == ZFS_PROP_MOUNTPOINT &&
1793		    changelist_haszonedchild(cls[cl_idx])) {
1794			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1795			    "child dataset with inherited mountpoint is used "
1796			    "in a non-global zone"));
1797			ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1798			goto error;
1799		}
1800
1801		/* We don't support those properties on FreeBSD. */
1802		switch (prop) {
1803		case ZFS_PROP_DEVICES:
1804		case ZFS_PROP_ISCSIOPTIONS:
1805		case ZFS_PROP_XATTR:
1806		case ZFS_PROP_VSCAN:
1807		case ZFS_PROP_NBMAND:
1808		case ZFS_PROP_MLSLABEL:
1809			(void) snprintf(errbuf, sizeof (errbuf),
1810			    "property '%s' not supported on FreeBSD",
1811			    nvpair_name(elem));
1812			ret = zfs_error(hdl, EZFS_PERM, errbuf);
1813			goto error;
1814		}
1815
1816		if (cls[cl_idx] != NULL &&
1817		    (ret = changelist_prefix(cls[cl_idx])) != 0)
1818			goto error;
1819
1820		cl_idx++;
1821	}
1822	assert(cl_idx == nvl_len);
1823
1824	/*
1825	 * Execute the corresponding ioctl() to set this list of properties.
1826	 */
1827	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1828
1829	if ((ret = zcmd_write_src_nvlist(hdl, &zc, nvl)) != 0 ||
1830	    (ret = zcmd_alloc_dst_nvlist(hdl, &zc, 0)) != 0)
1831		goto error;
1832
1833	ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1834
1835	if (ret != 0) {
1836		/* Get the list of unset properties back and report them. */
1837		nvlist_t *errorprops = NULL;
1838		if (zcmd_read_dst_nvlist(hdl, &zc, &errorprops) != 0)
1839			goto error;
1840		for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
1841		    elem != NULL;
1842		    elem = nvlist_next_nvpair(nvl, elem)) {
1843			zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
1844			zfs_setprop_error(hdl, prop, errno, errbuf);
1845		}
1846		nvlist_free(errorprops);
1847
1848		if (added_resv && errno == ENOSPC) {
1849			/* clean up the volsize property we tried to set */
1850			uint64_t old_volsize = zfs_prop_get_int(zhp,
1851			    ZFS_PROP_VOLSIZE);
1852			nvlist_free(nvl);
1853			nvl = NULL;
1854			zcmd_free_nvlists(&zc);
1855
1856			if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
1857				goto error;
1858			if (nvlist_add_uint64(nvl,
1859			    zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1860			    old_volsize) != 0)
1861				goto error;
1862			if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
1863				goto error;
1864			(void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
1865		}
1866	} else {
1867		for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) {
1868			if (cls[cl_idx] != NULL) {
1869				int clp_err = changelist_postfix(cls[cl_idx]);
1870				if (clp_err != 0)
1871					ret = clp_err;
1872			}
1873		}
1874
1875		/*
1876		 * Refresh the statistics so the new property value
1877		 * is reflected.
1878		 */
1879		if (ret == 0)
1880			(void) get_stats(zhp);
1881	}
1882
1883error:
1884	nvlist_free(nvl);
1885	zcmd_free_nvlists(&zc);
1886	if (cls != NULL) {
1887		for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) {
1888			if (cls[cl_idx] != NULL)
1889				changelist_free(cls[cl_idx]);
1890		}
1891		free(cls);
1892	}
1893	return (ret);
1894}
1895
1896/*
1897 * Given a property, inherit the value from the parent dataset, or if received
1898 * is TRUE, revert to the received value, if any.
1899 */
1900int
1901zfs_prop_inherit(zfs_handle_t *zhp, const char *propname, boolean_t received)
1902{
1903	zfs_cmd_t zc = { 0 };
1904	int ret;
1905	prop_changelist_t *cl;
1906	libzfs_handle_t *hdl = zhp->zfs_hdl;
1907	char errbuf[1024];
1908	zfs_prop_t prop;
1909
1910	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1911	    "cannot inherit %s for '%s'"), propname, zhp->zfs_name);
1912
1913	zc.zc_cookie = received;
1914	if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL) {
1915		/*
1916		 * For user properties, the amount of work we have to do is very
1917		 * small, so just do it here.
1918		 */
1919		if (!zfs_prop_user(propname)) {
1920			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1921			    "invalid property"));
1922			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
1923		}
1924
1925		(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1926		(void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value));
1927
1928		if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc) != 0)
1929			return (zfs_standard_error(hdl, errno, errbuf));
1930
1931		return (0);
1932	}
1933
1934	/*
1935	 * Verify that this property is inheritable.
1936	 */
1937	if (zfs_prop_readonly(prop))
1938		return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf));
1939
1940	if (!zfs_prop_inheritable(prop) && !received)
1941		return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf));
1942
1943	/*
1944	 * Check to see if the value applies to this type
1945	 */
1946	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
1947		return (zfs_error(hdl, EZFS_PROPTYPE, errbuf));
1948
1949	/*
1950	 * Normalize the name, to get rid of shorthand abbreviations.
1951	 */
1952	propname = zfs_prop_to_name(prop);
1953	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1954	(void) strlcpy(zc.zc_value, propname, sizeof (zc.zc_value));
1955
1956	if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID &&
1957	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
1958		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1959		    "dataset is used in a non-global zone"));
1960		return (zfs_error(hdl, EZFS_ZONED, errbuf));
1961	}
1962
1963	/*
1964	 * Determine datasets which will be affected by this change, if any.
1965	 */
1966	if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
1967		return (-1);
1968
1969	if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
1970		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1971		    "child dataset with inherited mountpoint is used "
1972		    "in a non-global zone"));
1973		ret = zfs_error(hdl, EZFS_ZONED, errbuf);
1974		goto error;
1975	}
1976
1977	if ((ret = changelist_prefix(cl)) != 0)
1978		goto error;
1979
1980	if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_INHERIT_PROP, &zc)) != 0) {
1981		return (zfs_standard_error(hdl, errno, errbuf));
1982	} else {
1983
1984		if ((ret = changelist_postfix(cl)) != 0)
1985			goto error;
1986
1987		/*
1988		 * Refresh the statistics so the new property is reflected.
1989		 */
1990		(void) get_stats(zhp);
1991	}
1992
1993error:
1994	changelist_free(cl);
1995	return (ret);
1996}
1997
1998/*
1999 * True DSL properties are stored in an nvlist.  The following two functions
2000 * extract them appropriately.
2001 */
2002static uint64_t
2003getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
2004{
2005	nvlist_t *nv;
2006	uint64_t value;
2007
2008	*source = NULL;
2009	if (nvlist_lookup_nvlist(zhp->zfs_props,
2010	    zfs_prop_to_name(prop), &nv) == 0) {
2011		verify(nvlist_lookup_uint64(nv, ZPROP_VALUE, &value) == 0);
2012		(void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
2013	} else {
2014		verify(!zhp->zfs_props_table ||
2015		    zhp->zfs_props_table[prop] == B_TRUE);
2016		value = zfs_prop_default_numeric(prop);
2017		*source = "";
2018	}
2019
2020	return (value);
2021}
2022
2023static const char *
2024getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
2025{
2026	nvlist_t *nv;
2027	const char *value;
2028
2029	*source = NULL;
2030	if (nvlist_lookup_nvlist(zhp->zfs_props,
2031	    zfs_prop_to_name(prop), &nv) == 0) {
2032		value = fnvlist_lookup_string(nv, ZPROP_VALUE);
2033		(void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
2034	} else {
2035		verify(!zhp->zfs_props_table ||
2036		    zhp->zfs_props_table[prop] == B_TRUE);
2037		value = zfs_prop_default_string(prop);
2038		*source = "";
2039	}
2040
2041	return (value);
2042}
2043
2044static boolean_t
2045zfs_is_recvd_props_mode(zfs_handle_t *zhp)
2046{
2047	return (zhp->zfs_props == zhp->zfs_recvd_props);
2048}
2049
2050static void
2051zfs_set_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
2052{
2053	*cookie = (uint64_t)(uintptr_t)zhp->zfs_props;
2054	zhp->zfs_props = zhp->zfs_recvd_props;
2055}
2056
2057static void
2058zfs_unset_recvd_props_mode(zfs_handle_t *zhp, uint64_t *cookie)
2059{
2060	zhp->zfs_props = (nvlist_t *)(uintptr_t)*cookie;
2061	*cookie = 0;
2062}
2063
2064/*
2065 * Internal function for getting a numeric property.  Both zfs_prop_get() and
2066 * zfs_prop_get_int() are built using this interface.
2067 *
2068 * Certain properties can be overridden using 'mount -o'.  In this case, scan
2069 * the contents of the /etc/mnttab entry, searching for the appropriate options.
2070 * If they differ from the on-disk values, report the current values and mark
2071 * the source "temporary".
2072 */
2073static int
2074get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
2075    char **source, uint64_t *val)
2076{
2077	zfs_cmd_t zc = { 0 };
2078	nvlist_t *zplprops = NULL;
2079	struct mnttab mnt;
2080	char *mntopt_on = NULL;
2081	char *mntopt_off = NULL;
2082	boolean_t received = zfs_is_recvd_props_mode(zhp);
2083
2084	*source = NULL;
2085
2086	switch (prop) {
2087	case ZFS_PROP_ATIME:
2088		mntopt_on = MNTOPT_ATIME;
2089		mntopt_off = MNTOPT_NOATIME;
2090		break;
2091
2092	case ZFS_PROP_DEVICES:
2093		mntopt_on = MNTOPT_DEVICES;
2094		mntopt_off = MNTOPT_NODEVICES;
2095		break;
2096
2097	case ZFS_PROP_EXEC:
2098		mntopt_on = MNTOPT_EXEC;
2099		mntopt_off = MNTOPT_NOEXEC;
2100		break;
2101
2102	case ZFS_PROP_READONLY:
2103		mntopt_on = MNTOPT_RO;
2104		mntopt_off = MNTOPT_RW;
2105		break;
2106
2107	case ZFS_PROP_SETUID:
2108		mntopt_on = MNTOPT_SETUID;
2109		mntopt_off = MNTOPT_NOSETUID;
2110		break;
2111
2112	case ZFS_PROP_XATTR:
2113		mntopt_on = MNTOPT_XATTR;
2114		mntopt_off = MNTOPT_NOXATTR;
2115		break;
2116
2117	case ZFS_PROP_NBMAND:
2118		mntopt_on = MNTOPT_NBMAND;
2119		mntopt_off = MNTOPT_NONBMAND;
2120		break;
2121
2122	default:
2123		break;
2124	}
2125
2126	/*
2127	 * Because looking up the mount options is potentially expensive
2128	 * (iterating over all of /etc/mnttab), we defer its calculation until
2129	 * we're looking up a property which requires its presence.
2130	 */
2131	if (!zhp->zfs_mntcheck &&
2132	    (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) {
2133		libzfs_handle_t *hdl = zhp->zfs_hdl;
2134		struct mnttab entry;
2135
2136		if (libzfs_mnttab_find(hdl, zhp->zfs_name, &entry) == 0) {
2137			zhp->zfs_mntopts = zfs_strdup(hdl,
2138			    entry.mnt_mntopts);
2139			if (zhp->zfs_mntopts == NULL)
2140				return (-1);
2141		}
2142
2143		zhp->zfs_mntcheck = B_TRUE;
2144	}
2145
2146	if (zhp->zfs_mntopts == NULL)
2147		mnt.mnt_mntopts = "";
2148	else
2149		mnt.mnt_mntopts = zhp->zfs_mntopts;
2150
2151	switch (prop) {
2152	case ZFS_PROP_ATIME:
2153	case ZFS_PROP_DEVICES:
2154	case ZFS_PROP_EXEC:
2155	case ZFS_PROP_READONLY:
2156	case ZFS_PROP_SETUID:
2157	case ZFS_PROP_XATTR:
2158	case ZFS_PROP_NBMAND:
2159		*val = getprop_uint64(zhp, prop, source);
2160
2161		if (received)
2162			break;
2163
2164		if (hasmntopt(&mnt, mntopt_on) && !*val) {
2165			*val = B_TRUE;
2166			if (src)
2167				*src = ZPROP_SRC_TEMPORARY;
2168		} else if (hasmntopt(&mnt, mntopt_off) && *val) {
2169			*val = B_FALSE;
2170			if (src)
2171				*src = ZPROP_SRC_TEMPORARY;
2172		}
2173		break;
2174
2175	case ZFS_PROP_CANMOUNT:
2176	case ZFS_PROP_VOLSIZE:
2177	case ZFS_PROP_QUOTA:
2178	case ZFS_PROP_REFQUOTA:
2179	case ZFS_PROP_RESERVATION:
2180	case ZFS_PROP_REFRESERVATION:
2181	case ZFS_PROP_FILESYSTEM_LIMIT:
2182	case ZFS_PROP_SNAPSHOT_LIMIT:
2183	case ZFS_PROP_FILESYSTEM_COUNT:
2184	case ZFS_PROP_SNAPSHOT_COUNT:
2185		*val = getprop_uint64(zhp, prop, source);
2186
2187		if (*source == NULL) {
2188			/* not default, must be local */
2189			*source = zhp->zfs_name;
2190		}
2191		break;
2192
2193	case ZFS_PROP_MOUNTED:
2194		*val = (zhp->zfs_mntopts != NULL);
2195		break;
2196
2197	case ZFS_PROP_NUMCLONES:
2198		*val = zhp->zfs_dmustats.dds_num_clones;
2199		break;
2200
2201	case ZFS_PROP_VERSION:
2202	case ZFS_PROP_NORMALIZE:
2203	case ZFS_PROP_UTF8ONLY:
2204	case ZFS_PROP_CASE:
2205		if (!zfs_prop_valid_for_type(prop, zhp->zfs_head_type) ||
2206		    zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
2207			return (-1);
2208		(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2209		if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_OBJSET_ZPLPROPS, &zc)) {
2210			zcmd_free_nvlists(&zc);
2211			return (-1);
2212		}
2213		if (zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &zplprops) != 0 ||
2214		    nvlist_lookup_uint64(zplprops, zfs_prop_to_name(prop),
2215		    val) != 0) {
2216			zcmd_free_nvlists(&zc);
2217			return (-1);
2218		}
2219		nvlist_free(zplprops);
2220		zcmd_free_nvlists(&zc);
2221		break;
2222
2223	case ZFS_PROP_INCONSISTENT:
2224		*val = zhp->zfs_dmustats.dds_inconsistent;
2225		break;
2226
2227	default:
2228		switch (zfs_prop_get_type(prop)) {
2229		case PROP_TYPE_NUMBER:
2230		case PROP_TYPE_INDEX:
2231			*val = getprop_uint64(zhp, prop, source);
2232			/*
2233			 * If we tried to use a default value for a
2234			 * readonly property, it means that it was not
2235			 * present.  Note this only applies to "truly"
2236			 * readonly properties, not set-once properties
2237			 * like volblocksize.
2238			 */
2239			if (zfs_prop_readonly(prop) &&
2240			    !zfs_prop_setonce(prop) &&
2241			    *source != NULL && (*source)[0] == '\0') {
2242				*source = NULL;
2243				return (-1);
2244			}
2245			break;
2246
2247		case PROP_TYPE_STRING:
2248		default:
2249			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2250			    "cannot get non-numeric property"));
2251			return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP,
2252			    dgettext(TEXT_DOMAIN, "internal error")));
2253		}
2254	}
2255
2256	return (0);
2257}
2258
2259/*
2260 * Calculate the source type, given the raw source string.
2261 */
2262static void
2263get_source(zfs_handle_t *zhp, zprop_source_t *srctype, char *source,
2264    char *statbuf, size_t statlen)
2265{
2266	if (statbuf == NULL || *srctype == ZPROP_SRC_TEMPORARY)
2267		return;
2268
2269	if (source == NULL) {
2270		*srctype = ZPROP_SRC_NONE;
2271	} else if (source[0] == '\0') {
2272		*srctype = ZPROP_SRC_DEFAULT;
2273	} else if (strstr(source, ZPROP_SOURCE_VAL_RECVD) != NULL) {
2274		*srctype = ZPROP_SRC_RECEIVED;
2275	} else {
2276		if (strcmp(source, zhp->zfs_name) == 0) {
2277			*srctype = ZPROP_SRC_LOCAL;
2278		} else {
2279			(void) strlcpy(statbuf, source, statlen);
2280			*srctype = ZPROP_SRC_INHERITED;
2281		}
2282	}
2283
2284}
2285
2286int
2287zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
2288    size_t proplen, boolean_t literal)
2289{
2290	zfs_prop_t prop;
2291	int err = 0;
2292
2293	if (zhp->zfs_recvd_props == NULL)
2294		if (get_recvd_props_ioctl(zhp) != 0)
2295			return (-1);
2296
2297	prop = zfs_name_to_prop(propname);
2298
2299	if (prop != ZPROP_INVAL) {
2300		uint64_t cookie;
2301		if (!nvlist_exists(zhp->zfs_recvd_props, propname))
2302			return (-1);
2303		zfs_set_recvd_props_mode(zhp, &cookie);
2304		err = zfs_prop_get(zhp, prop, propbuf, proplen,
2305		    NULL, NULL, 0, literal);
2306		zfs_unset_recvd_props_mode(zhp, &cookie);
2307	} else {
2308		nvlist_t *propval;
2309		char *recvdval;
2310		if (nvlist_lookup_nvlist(zhp->zfs_recvd_props,
2311		    propname, &propval) != 0)
2312			return (-1);
2313		verify(nvlist_lookup_string(propval, ZPROP_VALUE,
2314		    &recvdval) == 0);
2315		(void) strlcpy(propbuf, recvdval, proplen);
2316	}
2317
2318	return (err == 0 ? 0 : -1);
2319}
2320
2321static int
2322get_clones_string(zfs_handle_t *zhp, char *propbuf, size_t proplen)
2323{
2324	nvlist_t *value;
2325	nvpair_t *pair;
2326
2327	value = zfs_get_clones_nvl(zhp);
2328	if (value == NULL)
2329		return (-1);
2330
2331	propbuf[0] = '\0';
2332	for (pair = nvlist_next_nvpair(value, NULL); pair != NULL;
2333	    pair = nvlist_next_nvpair(value, pair)) {
2334		if (propbuf[0] != '\0')
2335			(void) strlcat(propbuf, ",", proplen);
2336		(void) strlcat(propbuf, nvpair_name(pair), proplen);
2337	}
2338
2339	return (0);
2340}
2341
2342struct get_clones_arg {
2343	uint64_t numclones;
2344	nvlist_t *value;
2345	const char *origin;
2346	char buf[ZFS_MAX_DATASET_NAME_LEN];
2347};
2348
2349int
2350get_clones_cb(zfs_handle_t *zhp, void *arg)
2351{
2352	struct get_clones_arg *gca = arg;
2353
2354	if (gca->numclones == 0) {
2355		zfs_close(zhp);
2356		return (0);
2357	}
2358
2359	if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, gca->buf, sizeof (gca->buf),
2360	    NULL, NULL, 0, B_TRUE) != 0)
2361		goto out;
2362	if (strcmp(gca->buf, gca->origin) == 0) {
2363		fnvlist_add_boolean(gca->value, zfs_get_name(zhp));
2364		gca->numclones--;
2365	}
2366
2367out:
2368	(void) zfs_iter_children(zhp, get_clones_cb, gca);
2369	zfs_close(zhp);
2370	return (0);
2371}
2372
2373nvlist_t *
2374zfs_get_clones_nvl(zfs_handle_t *zhp)
2375{
2376	nvlist_t *nv, *value;
2377
2378	if (nvlist_lookup_nvlist(zhp->zfs_props,
2379	    zfs_prop_to_name(ZFS_PROP_CLONES), &nv) != 0) {
2380		struct get_clones_arg gca;
2381
2382		/*
2383		 * if this is a snapshot, then the kernel wasn't able
2384		 * to get the clones.  Do it by slowly iterating.
2385		 */
2386		if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT)
2387			return (NULL);
2388		if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 0) != 0)
2389			return (NULL);
2390		if (nvlist_alloc(&value, NV_UNIQUE_NAME, 0) != 0) {
2391			nvlist_free(nv);
2392			return (NULL);
2393		}
2394
2395		gca.numclones = zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES);
2396		gca.value = value;
2397		gca.origin = zhp->zfs_name;
2398
2399		if (gca.numclones != 0) {
2400			zfs_handle_t *root;
2401			char pool[ZFS_MAX_DATASET_NAME_LEN];
2402			char *cp = pool;
2403
2404			/* get the pool name */
2405			(void) strlcpy(pool, zhp->zfs_name, sizeof (pool));
2406			(void) strsep(&cp, "/@");
2407			root = zfs_open(zhp->zfs_hdl, pool,
2408			    ZFS_TYPE_FILESYSTEM);
2409
2410			(void) get_clones_cb(root, &gca);
2411		}
2412
2413		if (gca.numclones != 0 ||
2414		    nvlist_add_nvlist(nv, ZPROP_VALUE, value) != 0 ||
2415		    nvlist_add_nvlist(zhp->zfs_props,
2416		    zfs_prop_to_name(ZFS_PROP_CLONES), nv) != 0) {
2417			nvlist_free(nv);
2418			nvlist_free(value);
2419			return (NULL);
2420		}
2421		nvlist_free(nv);
2422		nvlist_free(value);
2423		verify(0 == nvlist_lookup_nvlist(zhp->zfs_props,
2424		    zfs_prop_to_name(ZFS_PROP_CLONES), &nv));
2425	}
2426
2427	verify(nvlist_lookup_nvlist(nv, ZPROP_VALUE, &value) == 0);
2428
2429	return (value);
2430}
2431
2432/*
2433 * Accepts a property and value and checks that the value
2434 * matches the one found by the channel program. If they are
2435 * not equal, print both of them.
2436 */
2437void
2438zcp_check(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t intval,
2439    const char *strval)
2440{
2441	if (!zhp->zfs_hdl->libzfs_prop_debug)
2442		return;
2443	int error;
2444	char *poolname = zhp->zpool_hdl->zpool_name;
2445	const char *program =
2446	    "args = ...\n"
2447	    "ds = args['dataset']\n"
2448	    "prop = args['property']\n"
2449	    "value, setpoint = zfs.get_prop(ds, prop)\n"
2450	    "return {value=value, setpoint=setpoint}\n";
2451	nvlist_t *outnvl;
2452	nvlist_t *retnvl;
2453	nvlist_t *argnvl = fnvlist_alloc();
2454
2455	fnvlist_add_string(argnvl, "dataset", zhp->zfs_name);
2456	fnvlist_add_string(argnvl, "property", zfs_prop_to_name(prop));
2457
2458	error = lzc_channel_program_nosync(poolname, program,
2459	    10 * 1000 * 1000, 10 * 1024 * 1024, argnvl, &outnvl);
2460
2461	if (error == 0) {
2462		retnvl = fnvlist_lookup_nvlist(outnvl, "return");
2463		if (zfs_prop_get_type(prop) == PROP_TYPE_NUMBER) {
2464			int64_t ans;
2465			error = nvlist_lookup_int64(retnvl, "value", &ans);
2466			if (error != 0) {
2467				(void) fprintf(stderr, "zcp check error: %u\n",
2468				    error);
2469				return;
2470			}
2471			if (ans != intval) {
2472				(void) fprintf(stderr,
2473				    "%s: zfs found %lld, but zcp found %lld\n",
2474				    zfs_prop_to_name(prop),
2475				    (longlong_t)intval, (longlong_t)ans);
2476			}
2477		} else {
2478			char *str_ans;
2479			error = nvlist_lookup_string(retnvl, "value", &str_ans);
2480			if (error != 0) {
2481				(void) fprintf(stderr, "zcp check error: %u\n",
2482				    error);
2483				return;
2484			}
2485			if (strcmp(strval, str_ans) != 0) {
2486				(void) fprintf(stderr,
2487				    "%s: zfs found %s, but zcp found %s\n",
2488				    zfs_prop_to_name(prop),
2489				    strval, str_ans);
2490			}
2491		}
2492	} else {
2493		(void) fprintf(stderr,
2494		    "zcp check failed, channel program error: %u\n", error);
2495	}
2496	nvlist_free(argnvl);
2497	nvlist_free(outnvl);
2498}
2499
2500/*
2501 * Retrieve a property from the given object.  If 'literal' is specified, then
2502 * numbers are left as exact values.  Otherwise, numbers are converted to a
2503 * human-readable form.
2504 *
2505 * Returns 0 on success, or -1 on error.
2506 */
2507int
2508zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
2509    zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal)
2510{
2511	char *source = NULL;
2512	uint64_t val;
2513	const char *str;
2514	const char *strval;
2515	boolean_t received = zfs_is_recvd_props_mode(zhp);
2516
2517	/*
2518	 * Check to see if this property applies to our object
2519	 */
2520	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
2521		return (-1);
2522
2523	if (received && zfs_prop_readonly(prop))
2524		return (-1);
2525
2526	if (src)
2527		*src = ZPROP_SRC_NONE;
2528
2529	switch (prop) {
2530	case ZFS_PROP_CREATION:
2531		/*
2532		 * 'creation' is a time_t stored in the statistics.  We convert
2533		 * this into a string unless 'literal' is specified.
2534		 */
2535		{
2536			val = getprop_uint64(zhp, prop, &source);
2537			time_t time = (time_t)val;
2538			struct tm t;
2539
2540			if (literal ||
2541			    localtime_r(&time, &t) == NULL ||
2542			    strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
2543			    &t) == 0)
2544				(void) snprintf(propbuf, proplen, "%llu", val);
2545		}
2546		zcp_check(zhp, prop, val, NULL);
2547		break;
2548
2549	case ZFS_PROP_MOUNTPOINT:
2550		/*
2551		 * Getting the precise mountpoint can be tricky.
2552		 *
2553		 *  - for 'none' or 'legacy', return those values.
2554		 *  - for inherited mountpoints, we want to take everything
2555		 *    after our ancestor and append it to the inherited value.
2556		 *
2557		 * If the pool has an alternate root, we want to prepend that
2558		 * root to any values we return.
2559		 */
2560
2561		str = getprop_string(zhp, prop, &source);
2562
2563		if (str[0] == '/') {
2564			char buf[MAXPATHLEN];
2565			char *root = buf;
2566			const char *relpath;
2567
2568			/*
2569			 * If we inherit the mountpoint, even from a dataset
2570			 * with a received value, the source will be the path of
2571			 * the dataset we inherit from. If source is
2572			 * ZPROP_SOURCE_VAL_RECVD, the received value is not
2573			 * inherited.
2574			 */
2575			if (strcmp(source, ZPROP_SOURCE_VAL_RECVD) == 0) {
2576				relpath = "";
2577			} else {
2578				relpath = zhp->zfs_name + strlen(source);
2579				if (relpath[0] == '/')
2580					relpath++;
2581			}
2582
2583			if ((zpool_get_prop(zhp->zpool_hdl,
2584			    ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL,
2585			    B_FALSE)) || (strcmp(root, "-") == 0))
2586				root[0] = '\0';
2587			/*
2588			 * Special case an alternate root of '/'. This will
2589			 * avoid having multiple leading slashes in the
2590			 * mountpoint path.
2591			 */
2592			if (strcmp(root, "/") == 0)
2593				root++;
2594
2595			/*
2596			 * If the mountpoint is '/' then skip over this
2597			 * if we are obtaining either an alternate root or
2598			 * an inherited mountpoint.
2599			 */
2600			if (str[1] == '\0' && (root[0] != '\0' ||
2601			    relpath[0] != '\0'))
2602				str++;
2603
2604			if (relpath[0] == '\0')
2605				(void) snprintf(propbuf, proplen, "%s%s",
2606				    root, str);
2607			else
2608				(void) snprintf(propbuf, proplen, "%s%s%s%s",
2609				    root, str, relpath[0] == '@' ? "" : "/",
2610				    relpath);
2611		} else {
2612			/* 'legacy' or 'none' */
2613			(void) strlcpy(propbuf, str, proplen);
2614		}
2615		zcp_check(zhp, prop, NULL, propbuf);
2616		break;
2617
2618	case ZFS_PROP_ORIGIN:
2619		str = getprop_string(zhp, prop, &source);
2620		if (str == NULL)
2621			return (-1);
2622		(void) strlcpy(propbuf, str, proplen);
2623		zcp_check(zhp, prop, NULL, str);
2624		break;
2625
2626	case ZFS_PROP_CLONES:
2627		if (get_clones_string(zhp, propbuf, proplen) != 0)
2628			return (-1);
2629		break;
2630
2631	case ZFS_PROP_QUOTA:
2632	case ZFS_PROP_REFQUOTA:
2633	case ZFS_PROP_RESERVATION:
2634	case ZFS_PROP_REFRESERVATION:
2635
2636		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2637			return (-1);
2638		/*
2639		 * If quota or reservation is 0, we translate this into 'none'
2640		 * (unless literal is set), and indicate that it's the default
2641		 * value.  Otherwise, we print the number nicely and indicate
2642		 * that its set locally.
2643		 */
2644		if (val == 0) {
2645			if (literal)
2646				(void) strlcpy(propbuf, "0", proplen);
2647			else
2648				(void) strlcpy(propbuf, "none", proplen);
2649		} else {
2650			if (literal)
2651				(void) snprintf(propbuf, proplen, "%llu",
2652				    (u_longlong_t)val);
2653			else
2654				zfs_nicenum(val, propbuf, proplen);
2655		}
2656		zcp_check(zhp, prop, val, NULL);
2657		break;
2658
2659	case ZFS_PROP_FILESYSTEM_LIMIT:
2660	case ZFS_PROP_SNAPSHOT_LIMIT:
2661	case ZFS_PROP_FILESYSTEM_COUNT:
2662	case ZFS_PROP_SNAPSHOT_COUNT:
2663
2664		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2665			return (-1);
2666
2667		/*
2668		 * If limit is UINT64_MAX, we translate this into 'none' (unless
2669		 * literal is set), and indicate that it's the default value.
2670		 * Otherwise, we print the number nicely and indicate that it's
2671		 * set locally.
2672		 */
2673		if (literal) {
2674			(void) snprintf(propbuf, proplen, "%llu",
2675			    (u_longlong_t)val);
2676		} else if (val == UINT64_MAX) {
2677			(void) strlcpy(propbuf, "none", proplen);
2678		} else {
2679			zfs_nicenum(val, propbuf, proplen);
2680		}
2681
2682		zcp_check(zhp, prop, val, NULL);
2683		break;
2684
2685	case ZFS_PROP_REFRATIO:
2686	case ZFS_PROP_COMPRESSRATIO:
2687		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2688			return (-1);
2689		(void) snprintf(propbuf, proplen, "%llu.%02llux",
2690		    (u_longlong_t)(val / 100),
2691		    (u_longlong_t)(val % 100));
2692		zcp_check(zhp, prop, val, NULL);
2693		break;
2694
2695	case ZFS_PROP_TYPE:
2696		switch (zhp->zfs_type) {
2697		case ZFS_TYPE_FILESYSTEM:
2698			str = "filesystem";
2699			break;
2700		case ZFS_TYPE_VOLUME:
2701			str = "volume";
2702			break;
2703		case ZFS_TYPE_SNAPSHOT:
2704			str = "snapshot";
2705			break;
2706		case ZFS_TYPE_BOOKMARK:
2707			str = "bookmark";
2708			break;
2709		default:
2710			abort();
2711		}
2712		(void) snprintf(propbuf, proplen, "%s", str);
2713		zcp_check(zhp, prop, NULL, propbuf);
2714		break;
2715
2716	case ZFS_PROP_MOUNTED:
2717		/*
2718		 * The 'mounted' property is a pseudo-property that described
2719		 * whether the filesystem is currently mounted.  Even though
2720		 * it's a boolean value, the typical values of "on" and "off"
2721		 * don't make sense, so we translate to "yes" and "no".
2722		 */
2723		if (get_numeric_property(zhp, ZFS_PROP_MOUNTED,
2724		    src, &source, &val) != 0)
2725			return (-1);
2726		if (val)
2727			(void) strlcpy(propbuf, "yes", proplen);
2728		else
2729			(void) strlcpy(propbuf, "no", proplen);
2730		break;
2731
2732	case ZFS_PROP_NAME:
2733		/*
2734		 * The 'name' property is a pseudo-property derived from the
2735		 * dataset name.  It is presented as a real property to simplify
2736		 * consumers.
2737		 */
2738		(void) strlcpy(propbuf, zhp->zfs_name, proplen);
2739		zcp_check(zhp, prop, NULL, propbuf);
2740		break;
2741
2742	case ZFS_PROP_MLSLABEL:
2743		{
2744#ifdef illumos
2745			m_label_t *new_sl = NULL;
2746			char *ascii = NULL;	/* human readable label */
2747
2748			(void) strlcpy(propbuf,
2749			    getprop_string(zhp, prop, &source), proplen);
2750
2751			if (literal || (strcasecmp(propbuf,
2752			    ZFS_MLSLABEL_DEFAULT) == 0))
2753				break;
2754
2755			/*
2756			 * Try to translate the internal hex string to
2757			 * human-readable output.  If there are any
2758			 * problems just use the hex string.
2759			 */
2760
2761			if (str_to_label(propbuf, &new_sl, MAC_LABEL,
2762			    L_NO_CORRECTION, NULL) == -1) {
2763				m_label_free(new_sl);
2764				break;
2765			}
2766
2767			if (label_to_str(new_sl, &ascii, M_LABEL,
2768			    DEF_NAMES) != 0) {
2769				if (ascii)
2770					free(ascii);
2771				m_label_free(new_sl);
2772				break;
2773			}
2774			m_label_free(new_sl);
2775
2776			(void) strlcpy(propbuf, ascii, proplen);
2777			free(ascii);
2778#else	/* !illumos */
2779			propbuf[0] = '\0';
2780#endif	/* illumos */
2781		}
2782		break;
2783
2784	case ZFS_PROP_GUID:
2785	case ZFS_PROP_CREATETXG:
2786		/*
2787		 * GUIDs are stored as numbers, but they are identifiers.
2788		 * We don't want them to be pretty printed, because pretty
2789		 * printing mangles the ID into a truncated and useless value.
2790		 */
2791		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2792			return (-1);
2793		(void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
2794		zcp_check(zhp, prop, val, NULL);
2795		break;
2796
2797	default:
2798		switch (zfs_prop_get_type(prop)) {
2799		case PROP_TYPE_NUMBER:
2800			if (get_numeric_property(zhp, prop, src,
2801			    &source, &val) != 0) {
2802				return (-1);
2803			}
2804
2805			if (literal) {
2806				(void) snprintf(propbuf, proplen, "%llu",
2807				    (u_longlong_t)val);
2808			} else {
2809				zfs_nicenum(val, propbuf, proplen);
2810			}
2811			zcp_check(zhp, prop, val, NULL);
2812			break;
2813
2814		case PROP_TYPE_STRING:
2815			str = getprop_string(zhp, prop, &source);
2816			if (str == NULL)
2817				return (-1);
2818
2819			(void) strlcpy(propbuf, str, proplen);
2820			zcp_check(zhp, prop, NULL, str);
2821			break;
2822
2823		case PROP_TYPE_INDEX:
2824			if (get_numeric_property(zhp, prop, src,
2825			    &source, &val) != 0)
2826				return (-1);
2827			if (zfs_prop_index_to_string(prop, val, &strval) != 0)
2828				return (-1);
2829
2830			(void) strlcpy(propbuf, strval, proplen);
2831			zcp_check(zhp, prop, NULL, strval);
2832			break;
2833
2834		default:
2835			abort();
2836		}
2837	}
2838
2839	get_source(zhp, src, source, statbuf, statlen);
2840
2841	return (0);
2842}
2843
2844/*
2845 * Utility function to get the given numeric property.  Does no validation that
2846 * the given property is the appropriate type; should only be used with
2847 * hard-coded property types.
2848 */
2849uint64_t
2850zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
2851{
2852	char *source;
2853	uint64_t val;
2854
2855	(void) get_numeric_property(zhp, prop, NULL, &source, &val);
2856
2857	return (val);
2858}
2859
2860int
2861zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val)
2862{
2863	char buf[64];
2864
2865	(void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val);
2866	return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf));
2867}
2868
2869/*
2870 * Similar to zfs_prop_get(), but returns the value as an integer.
2871 */
2872int
2873zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
2874    zprop_source_t *src, char *statbuf, size_t statlen)
2875{
2876	char *source;
2877
2878	/*
2879	 * Check to see if this property applies to our object
2880	 */
2881	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) {
2882		return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE,
2883		    dgettext(TEXT_DOMAIN, "cannot get property '%s'"),
2884		    zfs_prop_to_name(prop)));
2885	}
2886
2887	if (src)
2888		*src = ZPROP_SRC_NONE;
2889
2890	if (get_numeric_property(zhp, prop, src, &source, value) != 0)
2891		return (-1);
2892
2893	get_source(zhp, src, source, statbuf, statlen);
2894
2895	return (0);
2896}
2897
2898static int
2899idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
2900    char **domainp, idmap_rid_t *ridp)
2901{
2902#ifdef illumos
2903	idmap_get_handle_t *get_hdl = NULL;
2904	idmap_stat status;
2905	int err = EINVAL;
2906
2907	if (idmap_get_create(&get_hdl) != IDMAP_SUCCESS)
2908		goto out;
2909
2910	if (isuser) {
2911		err = idmap_get_sidbyuid(get_hdl, id,
2912		    IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
2913	} else {
2914		err = idmap_get_sidbygid(get_hdl, id,
2915		    IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
2916	}
2917	if (err == IDMAP_SUCCESS &&
2918	    idmap_get_mappings(get_hdl) == IDMAP_SUCCESS &&
2919	    status == IDMAP_SUCCESS)
2920		err = 0;
2921	else
2922		err = EINVAL;
2923out:
2924	if (get_hdl)
2925		idmap_get_destroy(get_hdl);
2926	return (err);
2927#else	/* !illumos */
2928	assert(!"invalid code path");
2929	return (EINVAL); // silence compiler warning
2930#endif	/* illumos */
2931}
2932
2933/*
2934 * convert the propname into parameters needed by kernel
2935 * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829
2936 * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789
2937 */
2938static int
2939userquota_propname_decode(const char *propname, boolean_t zoned,
2940    zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp)
2941{
2942	zfs_userquota_prop_t type;
2943	char *cp, *end;
2944	char *numericsid = NULL;
2945	boolean_t isuser;
2946
2947	domain[0] = '\0';
2948	*ridp = 0;
2949	/* Figure out the property type ({user|group}{quota|space}) */
2950	for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) {
2951		if (strncmp(propname, zfs_userquota_prop_prefixes[type],
2952		    strlen(zfs_userquota_prop_prefixes[type])) == 0)
2953			break;
2954	}
2955	if (type == ZFS_NUM_USERQUOTA_PROPS)
2956		return (EINVAL);
2957	*typep = type;
2958
2959	isuser = (type == ZFS_PROP_USERQUOTA ||
2960	    type == ZFS_PROP_USERUSED);
2961
2962	cp = strchr(propname, '@') + 1;
2963
2964	if (strchr(cp, '@')) {
2965#ifdef illumos
2966		/*
2967		 * It's a SID name (eg "user@domain") that needs to be
2968		 * turned into S-1-domainID-RID.
2969		 */
2970		int flag = 0;
2971		idmap_stat stat, map_stat;
2972		uid_t pid;
2973		idmap_rid_t rid;
2974		idmap_get_handle_t *gh = NULL;
2975
2976		stat = idmap_get_create(&gh);
2977		if (stat != IDMAP_SUCCESS) {
2978			idmap_get_destroy(gh);
2979			return (ENOMEM);
2980		}
2981		if (zoned && getzoneid() == GLOBAL_ZONEID)
2982			return (ENOENT);
2983		if (isuser) {
2984			stat = idmap_getuidbywinname(cp, NULL, flag, &pid);
2985			if (stat < 0)
2986				return (ENOENT);
2987			stat = idmap_get_sidbyuid(gh, pid, flag, &numericsid,
2988			    &rid, &map_stat);
2989		} else {
2990			stat = idmap_getgidbywinname(cp, NULL, flag, &pid);
2991			if (stat < 0)
2992				return (ENOENT);
2993			stat = idmap_get_sidbygid(gh, pid, flag, &numericsid,
2994			    &rid, &map_stat);
2995		}
2996		if (stat < 0) {
2997			idmap_get_destroy(gh);
2998			return (ENOENT);
2999		}
3000		stat = idmap_get_mappings(gh);
3001		idmap_get_destroy(gh);
3002
3003		if (stat < 0) {
3004			return (ENOENT);
3005		}
3006		if (numericsid == NULL)
3007			return (ENOENT);
3008		cp = numericsid;
3009		*ridp = rid;
3010		/* will be further decoded below */
3011#else	/* !illumos */
3012		return (ENOENT);
3013#endif	/* illumos */
3014	}
3015
3016	if (strncmp(cp, "S-1-", 4) == 0) {
3017		/* It's a numeric SID (eg "S-1-234-567-89") */
3018		(void) strlcpy(domain, cp, domainlen);
3019		errno = 0;
3020		if (*ridp == 0) {
3021			cp = strrchr(domain, '-');
3022			*cp = '\0';
3023			cp++;
3024			*ridp = strtoull(cp, &end, 10);
3025		} else {
3026			end = "";
3027		}
3028		if (numericsid) {
3029			free(numericsid);
3030			numericsid = NULL;
3031		}
3032		if (errno != 0 || *end != '\0')
3033			return (EINVAL);
3034	} else if (!isdigit(*cp)) {
3035		/*
3036		 * It's a user/group name (eg "user") that needs to be
3037		 * turned into a uid/gid
3038		 */
3039		if (zoned && getzoneid() == GLOBAL_ZONEID)
3040			return (ENOENT);
3041		if (isuser) {
3042			struct passwd *pw;
3043			pw = getpwnam(cp);
3044			if (pw == NULL)
3045				return (ENOENT);
3046			*ridp = pw->pw_uid;
3047		} else {
3048			struct group *gr;
3049			gr = getgrnam(cp);
3050			if (gr == NULL)
3051				return (ENOENT);
3052			*ridp = gr->gr_gid;
3053		}
3054	} else {
3055		/* It's a user/group ID (eg "12345"). */
3056		uid_t id = strtoul(cp, &end, 10);
3057		idmap_rid_t rid;
3058		char *mapdomain;
3059
3060		if (*end != '\0')
3061			return (EINVAL);
3062		if (id > MAXUID) {
3063			/* It's an ephemeral ID. */
3064			if (idmap_id_to_numeric_domain_rid(id, isuser,
3065			    &mapdomain, &rid) != 0)
3066				return (ENOENT);
3067			(void) strlcpy(domain, mapdomain, domainlen);
3068			*ridp = rid;
3069		} else {
3070			*ridp = id;
3071		}
3072	}
3073
3074	ASSERT3P(numericsid, ==, NULL);
3075	return (0);
3076}
3077
3078static int
3079zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname,
3080    uint64_t *propvalue, zfs_userquota_prop_t *typep)
3081{
3082	int err;
3083	zfs_cmd_t zc = { 0 };
3084
3085	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3086
3087	err = userquota_propname_decode(propname,
3088	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED),
3089	    typep, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid);
3090	zc.zc_objset_type = *typep;
3091	if (err)
3092		return (err);
3093
3094	err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_USERSPACE_ONE, &zc);
3095	if (err)
3096		return (err);
3097
3098	*propvalue = zc.zc_cookie;
3099	return (0);
3100}
3101
3102int
3103zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname,
3104    uint64_t *propvalue)
3105{
3106	zfs_userquota_prop_t type;
3107
3108	return (zfs_prop_get_userquota_common(zhp, propname, propvalue,
3109	    &type));
3110}
3111
3112int
3113zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
3114    char *propbuf, int proplen, boolean_t literal)
3115{
3116	int err;
3117	uint64_t propvalue;
3118	zfs_userquota_prop_t type;
3119
3120	err = zfs_prop_get_userquota_common(zhp, propname, &propvalue,
3121	    &type);
3122
3123	if (err)
3124		return (err);
3125
3126	if (literal) {
3127		(void) snprintf(propbuf, proplen, "%llu", propvalue);
3128	} else if (propvalue == 0 &&
3129	    (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) {
3130		(void) strlcpy(propbuf, "none", proplen);
3131	} else {
3132		zfs_nicenum(propvalue, propbuf, proplen);
3133	}
3134	return (0);
3135}
3136
3137int
3138zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname,
3139    uint64_t *propvalue)
3140{
3141	int err;
3142	zfs_cmd_t zc = { 0 };
3143	const char *snapname;
3144
3145	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3146
3147	snapname = strchr(propname, '@') + 1;
3148	if (strchr(snapname, '@')) {
3149		(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
3150	} else {
3151		/* snapname is the short name, append it to zhp's fsname */
3152		char *cp;
3153
3154		(void) strlcpy(zc.zc_value, zhp->zfs_name,
3155		    sizeof (zc.zc_value));
3156		cp = strchr(zc.zc_value, '@');
3157		if (cp != NULL)
3158			*cp = '\0';
3159		(void) strlcat(zc.zc_value, "@", sizeof (zc.zc_value));
3160		(void) strlcat(zc.zc_value, snapname, sizeof (zc.zc_value));
3161	}
3162
3163	err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_WRITTEN, &zc);
3164	if (err)
3165		return (err);
3166
3167	*propvalue = zc.zc_cookie;
3168	return (0);
3169}
3170
3171int
3172zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
3173    char *propbuf, int proplen, boolean_t literal)
3174{
3175	int err;
3176	uint64_t propvalue;
3177
3178	err = zfs_prop_get_written_int(zhp, propname, &propvalue);
3179
3180	if (err)
3181		return (err);
3182
3183	if (literal) {
3184		(void) snprintf(propbuf, proplen, "%llu", propvalue);
3185	} else {
3186		zfs_nicenum(propvalue, propbuf, proplen);
3187	}
3188	return (0);
3189}
3190
3191/*
3192 * Returns the name of the given zfs handle.
3193 */
3194const char *
3195zfs_get_name(const zfs_handle_t *zhp)
3196{
3197	return (zhp->zfs_name);
3198}
3199
3200/*
3201 * Returns the name of the parent pool for the given zfs handle.
3202 */
3203const char *
3204zfs_get_pool_name(const zfs_handle_t *zhp)
3205{
3206	return (zhp->zpool_hdl->zpool_name);
3207}
3208
3209/*
3210 * Returns the type of the given zfs handle.
3211 */
3212zfs_type_t
3213zfs_get_type(const zfs_handle_t *zhp)
3214{
3215	return (zhp->zfs_type);
3216}
3217
3218/*
3219 * Is one dataset name a child dataset of another?
3220 *
3221 * Needs to handle these cases:
3222 * Dataset 1	"a/foo"		"a/foo"		"a/foo"		"a/foo"
3223 * Dataset 2	"a/fo"		"a/foobar"	"a/bar/baz"	"a/foo/bar"
3224 * Descendant?	No.		No.		No.		Yes.
3225 */
3226static boolean_t
3227is_descendant(const char *ds1, const char *ds2)
3228{
3229	size_t d1len = strlen(ds1);
3230
3231	/* ds2 can't be a descendant if it's smaller */
3232	if (strlen(ds2) < d1len)
3233		return (B_FALSE);
3234
3235	/* otherwise, compare strings and verify that there's a '/' char */
3236	return (ds2[d1len] == '/' && (strncmp(ds1, ds2, d1len) == 0));
3237}
3238
3239/*
3240 * Given a complete name, return just the portion that refers to the parent.
3241 * Will return -1 if there is no parent (path is just the name of the
3242 * pool).
3243 */
3244static int
3245parent_name(const char *path, char *buf, size_t buflen)
3246{
3247	char *slashp;
3248
3249	(void) strlcpy(buf, path, buflen);
3250
3251	if ((slashp = strrchr(buf, '/')) == NULL)
3252		return (-1);
3253	*slashp = '\0';
3254
3255	return (0);
3256}
3257
3258/*
3259 * If accept_ancestor is false, then check to make sure that the given path has
3260 * a parent, and that it exists.  If accept_ancestor is true, then find the
3261 * closest existing ancestor for the given path.  In prefixlen return the
3262 * length of already existing prefix of the given path.  We also fetch the
3263 * 'zoned' property, which is used to validate property settings when creating
3264 * new datasets.
3265 */
3266static int
3267check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned,
3268    boolean_t accept_ancestor, int *prefixlen)
3269{
3270	zfs_cmd_t zc = { 0 };
3271	char parent[ZFS_MAX_DATASET_NAME_LEN];
3272	char *slash;
3273	zfs_handle_t *zhp;
3274	char errbuf[1024];
3275	uint64_t is_zoned;
3276
3277	(void) snprintf(errbuf, sizeof (errbuf),
3278	    dgettext(TEXT_DOMAIN, "cannot create '%s'"), path);
3279
3280	/* get parent, and check to see if this is just a pool */
3281	if (parent_name(path, parent, sizeof (parent)) != 0) {
3282		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3283		    "missing dataset name"));
3284		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3285	}
3286
3287	/* check to see if the pool exists */
3288	if ((slash = strchr(parent, '/')) == NULL)
3289		slash = parent + strlen(parent);
3290	(void) strncpy(zc.zc_name, parent, slash - parent);
3291	zc.zc_name[slash - parent] = '\0';
3292	if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 &&
3293	    errno == ENOENT) {
3294		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3295		    "no such pool '%s'"), zc.zc_name);
3296		return (zfs_error(hdl, EZFS_NOENT, errbuf));
3297	}
3298
3299	/* check to see if the parent dataset exists */
3300	while ((zhp = make_dataset_handle(hdl, parent)) == NULL) {
3301		if (errno == ENOENT && accept_ancestor) {
3302			/*
3303			 * Go deeper to find an ancestor, give up on top level.
3304			 */
3305			if (parent_name(parent, parent, sizeof (parent)) != 0) {
3306				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3307				    "no such pool '%s'"), zc.zc_name);
3308				return (zfs_error(hdl, EZFS_NOENT, errbuf));
3309			}
3310		} else if (errno == ENOENT) {
3311			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3312			    "parent does not exist"));
3313			return (zfs_error(hdl, EZFS_NOENT, errbuf));
3314		} else
3315			return (zfs_standard_error(hdl, errno, errbuf));
3316	}
3317
3318	is_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
3319	if (zoned != NULL)
3320		*zoned = is_zoned;
3321
3322	/* we are in a non-global zone, but parent is in the global zone */
3323	if (getzoneid() != GLOBAL_ZONEID && !is_zoned) {
3324		(void) zfs_standard_error(hdl, EPERM, errbuf);
3325		zfs_close(zhp);
3326		return (-1);
3327	}
3328
3329	/* make sure parent is a filesystem */
3330	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
3331		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3332		    "parent is not a filesystem"));
3333		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
3334		zfs_close(zhp);
3335		return (-1);
3336	}
3337
3338	zfs_close(zhp);
3339	if (prefixlen != NULL)
3340		*prefixlen = strlen(parent);
3341	return (0);
3342}
3343
3344/*
3345 * Finds whether the dataset of the given type(s) exists.
3346 */
3347boolean_t
3348zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types)
3349{
3350	zfs_handle_t *zhp;
3351
3352	if (!zfs_validate_name(hdl, path, types, B_FALSE))
3353		return (B_FALSE);
3354
3355	/*
3356	 * Try to get stats for the dataset, which will tell us if it exists.
3357	 */
3358	if ((zhp = make_dataset_handle(hdl, path)) != NULL) {
3359		int ds_type = zhp->zfs_type;
3360
3361		zfs_close(zhp);
3362		if (types & ds_type)
3363			return (B_TRUE);
3364	}
3365	return (B_FALSE);
3366}
3367
3368/*
3369 * Given a path to 'target', create all the ancestors between
3370 * the prefixlen portion of the path, and the target itself.
3371 * Fail if the initial prefixlen-ancestor does not already exist.
3372 */
3373int
3374create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
3375{
3376	zfs_handle_t *h;
3377	char *cp;
3378	const char *opname;
3379
3380	/* make sure prefix exists */
3381	cp = target + prefixlen;
3382	if (*cp != '/') {
3383		assert(strchr(cp, '/') == NULL);
3384		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
3385	} else {
3386		*cp = '\0';
3387		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
3388		*cp = '/';
3389	}
3390	if (h == NULL)
3391		return (-1);
3392	zfs_close(h);
3393
3394	/*
3395	 * Attempt to create, mount, and share any ancestor filesystems,
3396	 * up to the prefixlen-long one.
3397	 */
3398	for (cp = target + prefixlen + 1;
3399	    (cp = strchr(cp, '/')) != NULL; *cp = '/', cp++) {
3400
3401		*cp = '\0';
3402
3403		h = make_dataset_handle(hdl, target);
3404		if (h) {
3405			/* it already exists, nothing to do here */
3406			zfs_close(h);
3407			continue;
3408		}
3409
3410		if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
3411		    NULL) != 0) {
3412			opname = dgettext(TEXT_DOMAIN, "create");
3413			goto ancestorerr;
3414		}
3415
3416		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
3417		if (h == NULL) {
3418			opname = dgettext(TEXT_DOMAIN, "open");
3419			goto ancestorerr;
3420		}
3421
3422		if (zfs_mount(h, NULL, 0) != 0) {
3423			opname = dgettext(TEXT_DOMAIN, "mount");
3424			goto ancestorerr;
3425		}
3426
3427		if (zfs_share(h) != 0) {
3428			opname = dgettext(TEXT_DOMAIN, "share");
3429			goto ancestorerr;
3430		}
3431
3432		zfs_close(h);
3433	}
3434
3435	return (0);
3436
3437ancestorerr:
3438	zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3439	    "failed to %s ancestor '%s'"), opname, target);
3440	return (-1);
3441}
3442
3443/*
3444 * Creates non-existing ancestors of the given path.
3445 */
3446int
3447zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
3448{
3449	int prefix;
3450	char *path_copy;
3451	char errbuf[1024];
3452	int rc = 0;
3453
3454	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3455	    "cannot create '%s'"), path);
3456
3457	/*
3458	 * Check that we are not passing the nesting limit
3459	 * before we start creating any ancestors.
3460	 */
3461	if (dataset_nestcheck(path) != 0) {
3462		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3463		    "maximum name nesting depth exceeded"));
3464		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3465	}
3466
3467	if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
3468		return (-1);
3469
3470	if ((path_copy = strdup(path)) != NULL) {
3471		rc = create_parents(hdl, path_copy, prefix);
3472		free(path_copy);
3473	}
3474	if (path_copy == NULL || rc != 0)
3475		return (-1);
3476
3477	return (0);
3478}
3479
3480/*
3481 * Create a new filesystem or volume.
3482 */
3483int
3484zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
3485    nvlist_t *props)
3486{
3487	int ret;
3488	uint64_t size = 0;
3489	uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
3490	char errbuf[1024];
3491	uint64_t zoned;
3492	enum lzc_dataset_type ost;
3493	zpool_handle_t *zpool_handle;
3494
3495	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3496	    "cannot create '%s'"), path);
3497
3498	/* validate the path, taking care to note the extended error message */
3499	if (!zfs_validate_name(hdl, path, type, B_TRUE))
3500		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3501
3502	if (dataset_nestcheck(path) != 0) {
3503		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3504		    "maximum name nesting depth exceeded"));
3505		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3506	}
3507
3508	/* validate parents exist */
3509	if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0)
3510		return (-1);
3511
3512	/*
3513	 * The failure modes when creating a dataset of a different type over
3514	 * one that already exists is a little strange.  In particular, if you
3515	 * try to create a dataset on top of an existing dataset, the ioctl()
3516	 * will return ENOENT, not EEXIST.  To prevent this from happening, we
3517	 * first try to see if the dataset exists.
3518	 */
3519	if (zfs_dataset_exists(hdl, path, ZFS_TYPE_DATASET)) {
3520		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3521		    "dataset already exists"));
3522		return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3523	}
3524
3525	if (type == ZFS_TYPE_VOLUME)
3526		ost = LZC_DATSET_TYPE_ZVOL;
3527	else
3528		ost = LZC_DATSET_TYPE_ZFS;
3529
3530	/* open zpool handle for prop validation */
3531	char pool_path[ZFS_MAX_DATASET_NAME_LEN];
3532	(void) strlcpy(pool_path, path, sizeof (pool_path));
3533
3534	/* truncate pool_path at first slash */
3535	char *p = strchr(pool_path, '/');
3536	if (p != NULL)
3537		*p = '\0';
3538
3539	if ((zpool_handle = zpool_open(hdl, pool_path)) == NULL)
3540		return (-1);
3541
3542	if (props && (props = zfs_valid_proplist(hdl, type, props,
3543	    zoned, NULL, zpool_handle, errbuf)) == 0) {
3544		zpool_close(zpool_handle);
3545		return (-1);
3546	}
3547	zpool_close(zpool_handle);
3548
3549	if (type == ZFS_TYPE_VOLUME) {
3550		/*
3551		 * If we are creating a volume, the size and block size must
3552		 * satisfy a few restraints.  First, the blocksize must be a
3553		 * valid block size between SPA_{MIN,MAX}BLOCKSIZE.  Second, the
3554		 * volsize must be a multiple of the block size, and cannot be
3555		 * zero.
3556		 */
3557		if (props == NULL || nvlist_lookup_uint64(props,
3558		    zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) {
3559			nvlist_free(props);
3560			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3561			    "missing volume size"));
3562			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3563		}
3564
3565		if ((ret = nvlist_lookup_uint64(props,
3566		    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
3567		    &blocksize)) != 0) {
3568			if (ret == ENOENT) {
3569				blocksize = zfs_prop_default_numeric(
3570				    ZFS_PROP_VOLBLOCKSIZE);
3571			} else {
3572				nvlist_free(props);
3573				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3574				    "missing volume block size"));
3575				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3576			}
3577		}
3578
3579		if (size == 0) {
3580			nvlist_free(props);
3581			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3582			    "volume size cannot be zero"));
3583			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3584		}
3585
3586		if (size % blocksize != 0) {
3587			nvlist_free(props);
3588			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3589			    "volume size must be a multiple of volume block "
3590			    "size"));
3591			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3592		}
3593	}
3594
3595	/* create the dataset */
3596	ret = lzc_create(path, ost, props);
3597	nvlist_free(props);
3598
3599	/* check for failure */
3600	if (ret != 0) {
3601		char parent[ZFS_MAX_DATASET_NAME_LEN];
3602		(void) parent_name(path, parent, sizeof (parent));
3603
3604		switch (errno) {
3605		case ENOENT:
3606			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3607			    "no such parent '%s'"), parent);
3608			return (zfs_error(hdl, EZFS_NOENT, errbuf));
3609
3610		case EINVAL:
3611			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3612			    "parent '%s' is not a filesystem"), parent);
3613			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3614
3615		case ENOTSUP:
3616			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3617			    "pool must be upgraded to set this "
3618			    "property or value"));
3619			return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
3620		case ERANGE:
3621			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3622			    "invalid property value(s) specified"));
3623			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3624#ifdef _ILP32
3625		case EOVERFLOW:
3626			/*
3627			 * This platform can't address a volume this big.
3628			 */
3629			if (type == ZFS_TYPE_VOLUME)
3630				return (zfs_error(hdl, EZFS_VOLTOOBIG,
3631				    errbuf));
3632#endif
3633			/* FALLTHROUGH */
3634		default:
3635			return (zfs_standard_error(hdl, errno, errbuf));
3636		}
3637	}
3638
3639	return (0);
3640}
3641
3642/*
3643 * Destroys the given dataset.  The caller must make sure that the filesystem
3644 * isn't mounted, and that there are no active dependents. If the file system
3645 * does not exist this function does nothing.
3646 */
3647int
3648zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
3649{
3650	zfs_cmd_t zc = { 0 };
3651
3652	if (zhp->zfs_type == ZFS_TYPE_BOOKMARK) {
3653		nvlist_t *nv = fnvlist_alloc();
3654		fnvlist_add_boolean(nv, zhp->zfs_name);
3655		int error = lzc_destroy_bookmarks(nv, NULL);
3656		fnvlist_free(nv);
3657		if (error != 0) {
3658			return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3659			    dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
3660			    zhp->zfs_name));
3661		}
3662		return (0);
3663	}
3664
3665	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3666
3667	if (ZFS_IS_VOLUME(zhp)) {
3668		zc.zc_objset_type = DMU_OST_ZVOL;
3669	} else {
3670		zc.zc_objset_type = DMU_OST_ZFS;
3671	}
3672
3673	zc.zc_defer_destroy = defer;
3674	if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0 &&
3675	    errno != ENOENT) {
3676		return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3677		    dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
3678		    zhp->zfs_name));
3679	}
3680
3681	remove_mountpoint(zhp);
3682
3683	return (0);
3684}
3685
3686struct destroydata {
3687	nvlist_t *nvl;
3688	const char *snapname;
3689};
3690
3691static int
3692zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
3693{
3694	struct destroydata *dd = arg;
3695	char name[ZFS_MAX_DATASET_NAME_LEN];
3696	int rv = 0;
3697
3698	(void) snprintf(name, sizeof (name),
3699	    "%s@%s", zhp->zfs_name, dd->snapname);
3700
3701	if (lzc_exists(name))
3702		verify(nvlist_add_boolean(dd->nvl, name) == 0);
3703
3704	rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, dd);
3705	zfs_close(zhp);
3706	return (rv);
3707}
3708
3709/*
3710 * Destroys all snapshots with the given name in zhp & descendants.
3711 */
3712int
3713zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
3714{
3715	int ret;
3716	struct destroydata dd = { 0 };
3717
3718	dd.snapname = snapname;
3719	verify(nvlist_alloc(&dd.nvl, NV_UNIQUE_NAME, 0) == 0);
3720	(void) zfs_check_snap_cb(zfs_handle_dup(zhp), &dd);
3721
3722	if (nvlist_empty(dd.nvl)) {
3723		ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
3724		    dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
3725		    zhp->zfs_name, snapname);
3726	} else {
3727		ret = zfs_destroy_snaps_nvl(zhp->zfs_hdl, dd.nvl, defer);
3728	}
3729	nvlist_free(dd.nvl);
3730	return (ret);
3731}
3732
3733/*
3734 * Destroys all the snapshots named in the nvlist.
3735 */
3736int
3737zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer)
3738{
3739	int ret;
3740	nvlist_t *errlist = NULL;
3741
3742	ret = lzc_destroy_snaps(snaps, defer, &errlist);
3743
3744	if (ret == 0) {
3745		nvlist_free(errlist);
3746		return (0);
3747	}
3748
3749	if (nvlist_empty(errlist)) {
3750		char errbuf[1024];
3751		(void) snprintf(errbuf, sizeof (errbuf),
3752		    dgettext(TEXT_DOMAIN, "cannot destroy snapshots"));
3753
3754		ret = zfs_standard_error(hdl, ret, errbuf);
3755	}
3756	for (nvpair_t *pair = nvlist_next_nvpair(errlist, NULL);
3757	    pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) {
3758		char errbuf[1024];
3759		(void) snprintf(errbuf, sizeof (errbuf),
3760		    dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"),
3761		    nvpair_name(pair));
3762
3763		switch (fnvpair_value_int32(pair)) {
3764		case EEXIST:
3765			zfs_error_aux(hdl,
3766			    dgettext(TEXT_DOMAIN, "snapshot is cloned"));
3767			ret = zfs_error(hdl, EZFS_EXISTS, errbuf);
3768			break;
3769		default:
3770			ret = zfs_standard_error(hdl, errno, errbuf);
3771			break;
3772		}
3773	}
3774
3775	nvlist_free(errlist);
3776	return (ret);
3777}
3778
3779/*
3780 * Clones the given dataset.  The target must be of the same type as the source.
3781 */
3782int
3783zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
3784{
3785	char parent[ZFS_MAX_DATASET_NAME_LEN];
3786	int ret;
3787	char errbuf[1024];
3788	libzfs_handle_t *hdl = zhp->zfs_hdl;
3789	uint64_t zoned;
3790
3791	assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
3792
3793	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3794	    "cannot create '%s'"), target);
3795
3796	/* validate the target/clone name */
3797	if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
3798		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3799
3800	/* validate parents exist */
3801	if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
3802		return (-1);
3803
3804	(void) parent_name(target, parent, sizeof (parent));
3805
3806	/* do the clone */
3807
3808	if (props) {
3809		zfs_type_t type;
3810
3811		if (ZFS_IS_VOLUME(zhp)) {
3812			type = ZFS_TYPE_VOLUME;
3813		} else {
3814			type = ZFS_TYPE_FILESYSTEM;
3815		}
3816		if ((props = zfs_valid_proplist(hdl, type, props, zoned,
3817		    zhp, zhp->zpool_hdl, errbuf)) == NULL)
3818			return (-1);
3819		if (zfs_fix_auto_resv(zhp, props) == -1) {
3820			nvlist_free(props);
3821			return (-1);
3822		}
3823	}
3824
3825	ret = lzc_clone(target, zhp->zfs_name, props);
3826	nvlist_free(props);
3827
3828	if (ret != 0) {
3829		switch (errno) {
3830
3831		case ENOENT:
3832			/*
3833			 * The parent doesn't exist.  We should have caught this
3834			 * above, but there may a race condition that has since
3835			 * destroyed the parent.
3836			 *
3837			 * At this point, we don't know whether it's the source
3838			 * that doesn't exist anymore, or whether the target
3839			 * dataset doesn't exist.
3840			 */
3841			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3842			    "no such parent '%s'"), parent);
3843			return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
3844
3845		case EXDEV:
3846			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3847			    "source and target pools differ"));
3848			return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET,
3849			    errbuf));
3850
3851		default:
3852			return (zfs_standard_error(zhp->zfs_hdl, errno,
3853			    errbuf));
3854		}
3855	}
3856
3857	return (ret);
3858}
3859
3860/*
3861 * Promotes the given clone fs to be the clone parent.
3862 */
3863int
3864zfs_promote(zfs_handle_t *zhp)
3865{
3866	libzfs_handle_t *hdl = zhp->zfs_hdl;
3867	char snapname[ZFS_MAX_DATASET_NAME_LEN];
3868	int ret;
3869	char errbuf[1024];
3870
3871	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3872	    "cannot promote '%s'"), zhp->zfs_name);
3873
3874	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
3875		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3876		    "snapshots can not be promoted"));
3877		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3878	}
3879
3880	if (zhp->zfs_dmustats.dds_origin[0] == '\0') {
3881		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3882		    "not a cloned filesystem"));
3883		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3884	}
3885
3886	if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE))
3887		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3888
3889	ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname));
3890
3891	if (ret != 0) {
3892		switch (ret) {
3893		case EEXIST:
3894			/* There is a conflicting snapshot name. */
3895			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3896			    "conflicting snapshot '%s' from parent '%s'"),
3897			    snapname, zhp->zfs_dmustats.dds_origin);
3898			return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3899
3900		default:
3901			return (zfs_standard_error(hdl, ret, errbuf));
3902		}
3903	}
3904	return (ret);
3905}
3906
3907typedef struct snapdata {
3908	nvlist_t *sd_nvl;
3909	const char *sd_snapname;
3910} snapdata_t;
3911
3912static int
3913zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
3914{
3915	snapdata_t *sd = arg;
3916	char name[ZFS_MAX_DATASET_NAME_LEN];
3917	int rv = 0;
3918
3919	if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) == 0) {
3920		(void) snprintf(name, sizeof (name),
3921		    "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
3922
3923		fnvlist_add_boolean(sd->sd_nvl, name);
3924
3925		rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
3926	}
3927	zfs_close(zhp);
3928
3929	return (rv);
3930}
3931
3932int
3933zfs_remap_indirects(libzfs_handle_t *hdl, const char *fs)
3934{
3935	int err;
3936	char errbuf[1024];
3937
3938	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3939	    "cannot remap dataset '%s'"), fs);
3940
3941	err = lzc_remap(fs);
3942
3943	if (err != 0) {
3944		switch (err) {
3945		case ENOTSUP:
3946			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3947			    "pool must be upgraded"));
3948			(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
3949			break;
3950		case EINVAL:
3951			(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
3952			break;
3953		default:
3954			(void) zfs_standard_error(hdl, err, errbuf);
3955			break;
3956		}
3957	}
3958
3959	return (err);
3960}
3961
3962/*
3963 * Creates snapshots.  The keys in the snaps nvlist are the snapshots to be
3964 * created.
3965 */
3966int
3967zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
3968{
3969	int ret;
3970	char errbuf[1024];
3971	nvpair_t *elem;
3972	nvlist_t *errors;
3973
3974	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3975	    "cannot create snapshots "));
3976
3977	elem = NULL;
3978	while ((elem = nvlist_next_nvpair(snaps, elem)) != NULL) {
3979		const char *snapname = nvpair_name(elem);
3980
3981		/* validate the target name */
3982		if (!zfs_validate_name(hdl, snapname, ZFS_TYPE_SNAPSHOT,
3983		    B_TRUE)) {
3984			(void) snprintf(errbuf, sizeof (errbuf),
3985			    dgettext(TEXT_DOMAIN,
3986			    "cannot create snapshot '%s'"), snapname);
3987			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3988		}
3989	}
3990
3991	/*
3992	 * get pool handle for prop validation. assumes all snaps are in the
3993	 * same pool, as does lzc_snapshot (below).
3994	 */
3995	char pool[ZFS_MAX_DATASET_NAME_LEN];
3996	elem = nvlist_next_nvpair(snaps, NULL);
3997	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
3998	pool[strcspn(pool, "/@")] = '\0';
3999	zpool_handle_t *zpool_hdl = zpool_open(hdl, pool);
4000
4001	if (props != NULL &&
4002	    (props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
4003	    props, B_FALSE, NULL, zpool_hdl, errbuf)) == NULL) {
4004		zpool_close(zpool_hdl);
4005		return (-1);
4006	}
4007	zpool_close(zpool_hdl);
4008
4009	ret = lzc_snapshot(snaps, props, &errors);
4010
4011	if (ret != 0) {
4012		boolean_t printed = B_FALSE;
4013		for (elem = nvlist_next_nvpair(errors, NULL);
4014		    elem != NULL;
4015		    elem = nvlist_next_nvpair(errors, elem)) {
4016			(void) snprintf(errbuf, sizeof (errbuf),
4017			    dgettext(TEXT_DOMAIN,
4018			    "cannot create snapshot '%s'"), nvpair_name(elem));
4019			(void) zfs_standard_error(hdl,
4020			    fnvpair_value_int32(elem), errbuf);
4021			printed = B_TRUE;
4022		}
4023		if (!printed) {
4024			switch (ret) {
4025			case EXDEV:
4026				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4027				    "multiple snapshots of same "
4028				    "fs not allowed"));
4029				(void) zfs_error(hdl, EZFS_EXISTS, errbuf);
4030
4031				break;
4032			default:
4033				(void) zfs_standard_error(hdl, ret, errbuf);
4034			}
4035		}
4036	}
4037
4038	nvlist_free(props);
4039	nvlist_free(errors);
4040	return (ret);
4041}
4042
4043int
4044zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
4045    nvlist_t *props)
4046{
4047	int ret;
4048	snapdata_t sd = { 0 };
4049	char fsname[ZFS_MAX_DATASET_NAME_LEN];
4050	char *cp;
4051	zfs_handle_t *zhp;
4052	char errbuf[1024];
4053
4054	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4055	    "cannot snapshot %s"), path);
4056
4057	if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
4058		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4059
4060	(void) strlcpy(fsname, path, sizeof (fsname));
4061	cp = strchr(fsname, '@');
4062	*cp = '\0';
4063	sd.sd_snapname = cp + 1;
4064
4065	if ((zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM |
4066	    ZFS_TYPE_VOLUME)) == NULL) {
4067		return (-1);
4068	}
4069
4070	verify(nvlist_alloc(&sd.sd_nvl, NV_UNIQUE_NAME, 0) == 0);
4071	if (recursive) {
4072		(void) zfs_snapshot_cb(zfs_handle_dup(zhp), &sd);
4073	} else {
4074		fnvlist_add_boolean(sd.sd_nvl, path);
4075	}
4076
4077	ret = zfs_snapshot_nvl(hdl, sd.sd_nvl, props);
4078	nvlist_free(sd.sd_nvl);
4079	zfs_close(zhp);
4080	return (ret);
4081}
4082
4083/*
4084 * Destroy any more recent snapshots.  We invoke this callback on any dependents
4085 * of the snapshot first.  If the 'cb_dependent' member is non-zero, then this
4086 * is a dependent and we should just destroy it without checking the transaction
4087 * group.
4088 */
4089typedef struct rollback_data {
4090	const char	*cb_target;		/* the snapshot */
4091	uint64_t	cb_create;		/* creation time reference */
4092	boolean_t	cb_error;
4093	boolean_t	cb_force;
4094} rollback_data_t;
4095
4096static int
4097rollback_destroy_dependent(zfs_handle_t *zhp, void *data)
4098{
4099	rollback_data_t *cbp = data;
4100	prop_changelist_t *clp;
4101
4102	/* We must destroy this clone; first unmount it */
4103	clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
4104	    cbp->cb_force ? MS_FORCE: 0);
4105	if (clp == NULL || changelist_prefix(clp) != 0) {
4106		cbp->cb_error = B_TRUE;
4107		zfs_close(zhp);
4108		return (0);
4109	}
4110	if (zfs_destroy(zhp, B_FALSE) != 0)
4111		cbp->cb_error = B_TRUE;
4112	else
4113		changelist_remove(clp, zhp->zfs_name);
4114	(void) changelist_postfix(clp);
4115	changelist_free(clp);
4116
4117	zfs_close(zhp);
4118	return (0);
4119}
4120
4121static int
4122rollback_destroy(zfs_handle_t *zhp, void *data)
4123{
4124	rollback_data_t *cbp = data;
4125
4126	if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > cbp->cb_create) {
4127		cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
4128		    rollback_destroy_dependent, cbp);
4129
4130		cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
4131	}
4132
4133	zfs_close(zhp);
4134	return (0);
4135}
4136
4137/*
4138 * Given a dataset, rollback to a specific snapshot, discarding any
4139 * data changes since then and making it the active dataset.
4140 *
4141 * Any snapshots and bookmarks more recent than the target are
4142 * destroyed, along with their dependents (i.e. clones).
4143 */
4144int
4145zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
4146{
4147	rollback_data_t cb = { 0 };
4148	int err;
4149	boolean_t restore_resv = 0;
4150	uint64_t old_volsize = 0, new_volsize;
4151	zfs_prop_t resv_prop;
4152
4153	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
4154	    zhp->zfs_type == ZFS_TYPE_VOLUME);
4155
4156	/*
4157	 * Destroy all recent snapshots and their dependents.
4158	 */
4159	cb.cb_force = force;
4160	cb.cb_target = snap->zfs_name;
4161	cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
4162	(void) zfs_iter_snapshots(zhp, B_FALSE, rollback_destroy, &cb);
4163	(void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
4164
4165	if (cb.cb_error)
4166		return (-1);
4167
4168	/*
4169	 * Now that we have verified that the snapshot is the latest,
4170	 * rollback to the given snapshot.
4171	 */
4172
4173	if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
4174		if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
4175			return (-1);
4176		old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
4177		restore_resv =
4178		    (old_volsize == zfs_prop_get_int(zhp, resv_prop));
4179	}
4180
4181	/*
4182	 * Pass both the filesystem and the wanted snapshot names,
4183	 * we would get an error back if the snapshot is destroyed or
4184	 * a new snapshot is created before this request is processed.
4185	 */
4186	err = lzc_rollback_to(zhp->zfs_name, snap->zfs_name);
4187	if (err != 0) {
4188		char errbuf[1024];
4189
4190		(void) snprintf(errbuf, sizeof (errbuf),
4191		    dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
4192		    zhp->zfs_name);
4193		switch (err) {
4194		case EEXIST:
4195			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
4196			    "there is a snapshot or bookmark more recent "
4197			    "than '%s'"), snap->zfs_name);
4198			(void) zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf);
4199			break;
4200		case ESRCH:
4201			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
4202			    "'%s' is not found among snapshots of '%s'"),
4203			    snap->zfs_name, zhp->zfs_name);
4204			(void) zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf);
4205			break;
4206		case EINVAL:
4207			(void) zfs_error(zhp->zfs_hdl, EZFS_BADTYPE, errbuf);
4208			break;
4209		default:
4210			(void) zfs_standard_error(zhp->zfs_hdl, err, errbuf);
4211		}
4212		return (err);
4213	}
4214
4215	/*
4216	 * For volumes, if the pre-rollback volsize matched the pre-
4217	 * rollback reservation and the volsize has changed then set
4218	 * the reservation property to the post-rollback volsize.
4219	 * Make a new handle since the rollback closed the dataset.
4220	 */
4221	if ((zhp->zfs_type == ZFS_TYPE_VOLUME) &&
4222	    (zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name))) {
4223		if (restore_resv) {
4224			new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
4225			if (old_volsize != new_volsize)
4226				err = zfs_prop_set_int(zhp, resv_prop,
4227				    new_volsize);
4228		}
4229		zfs_close(zhp);
4230	}
4231	return (err);
4232}
4233
4234/*
4235 * Renames the given dataset.
4236 */
4237int
4238zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
4239    renameflags_t flags)
4240{
4241	int ret = 0;
4242	zfs_cmd_t zc = { 0 };
4243	char *delim;
4244	prop_changelist_t *cl = NULL;
4245	zfs_handle_t *zhrp = NULL;
4246	char *parentname = NULL;
4247	char parent[ZFS_MAX_DATASET_NAME_LEN];
4248	char property[ZFS_MAXPROPLEN];
4249	libzfs_handle_t *hdl = zhp->zfs_hdl;
4250	char errbuf[1024];
4251
4252	/* if we have the same exact name, just return success */
4253	if (strcmp(zhp->zfs_name, target) == 0)
4254		return (0);
4255
4256	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4257	    "cannot rename to '%s'"), target);
4258
4259	if (source != NULL) {
4260		/*
4261		 * This is recursive snapshots rename, put snapshot name
4262		 * (that might not exist) into zfs_name.
4263		 */
4264		assert(flags.recurse);
4265
4266		(void) strlcat(zhp->zfs_name, "@", sizeof(zhp->zfs_name));
4267		(void) strlcat(zhp->zfs_name, source, sizeof(zhp->zfs_name));
4268		zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
4269	}
4270
4271	/* make sure source name is valid */
4272	if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE))
4273		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4274
4275	/*
4276	 * Make sure the target name is valid
4277	 */
4278	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
4279		if ((strchr(target, '@') == NULL) ||
4280		    *target == '@') {
4281			/*
4282			 * Snapshot target name is abbreviated,
4283			 * reconstruct full dataset name
4284			 */
4285			(void) strlcpy(parent, zhp->zfs_name,
4286			    sizeof (parent));
4287			delim = strchr(parent, '@');
4288			if (strchr(target, '@') == NULL)
4289				*(++delim) = '\0';
4290			else
4291				*delim = '\0';
4292			(void) strlcat(parent, target, sizeof (parent));
4293			target = parent;
4294		} else {
4295			/*
4296			 * Make sure we're renaming within the same dataset.
4297			 */
4298			delim = strchr(target, '@');
4299			if (strncmp(zhp->zfs_name, target, delim - target)
4300			    != 0 || zhp->zfs_name[delim - target] != '@') {
4301				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4302				    "snapshots must be part of same "
4303				    "dataset"));
4304				return (zfs_error(hdl, EZFS_CROSSTARGET,
4305				    errbuf));
4306			}
4307		}
4308
4309		if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
4310			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4311	} else {
4312		if (flags.recurse) {
4313			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4314			    "recursive rename must be a snapshot"));
4315			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4316		}
4317
4318		if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
4319			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4320
4321		/* validate parents */
4322		if (check_parents(hdl, target, NULL, B_FALSE, NULL) != 0)
4323			return (-1);
4324
4325		/* make sure we're in the same pool */
4326		verify((delim = strchr(target, '/')) != NULL);
4327		if (strncmp(zhp->zfs_name, target, delim - target) != 0 ||
4328		    zhp->zfs_name[delim - target] != '/') {
4329			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4330			    "datasets must be within same pool"));
4331			return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
4332		}
4333
4334		/* new name cannot be a child of the current dataset name */
4335		if (is_descendant(zhp->zfs_name, target)) {
4336			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4337			    "New dataset name cannot be a descendant of "
4338			    "current dataset name"));
4339			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4340		}
4341	}
4342
4343	(void) snprintf(errbuf, sizeof (errbuf),
4344	    dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name);
4345
4346	if (getzoneid() == GLOBAL_ZONEID &&
4347	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
4348		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4349		    "dataset is used in a non-global zone"));
4350		return (zfs_error(hdl, EZFS_ZONED, errbuf));
4351	}
4352
4353	/*
4354	 * Avoid unmounting file systems with mountpoint property set to
4355	 * 'legacy' or 'none' even if -u option is not given.
4356	 */
4357	if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
4358	    !flags.recurse && !flags.nounmount &&
4359	    zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, property,
4360	    sizeof (property), NULL, NULL, 0, B_FALSE) == 0 &&
4361	    (strcmp(property, "legacy") == 0 ||
4362	     strcmp(property, "none") == 0)) {
4363		flags.nounmount = B_TRUE;
4364	}
4365	if (flags.recurse) {
4366
4367		parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
4368		if (parentname == NULL) {
4369			ret = -1;
4370			goto error;
4371		}
4372		delim = strchr(parentname, '@');
4373		*delim = '\0';
4374		zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_DATASET);
4375		if (zhrp == NULL) {
4376			ret = -1;
4377			goto error;
4378		}
4379	} else if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT) {
4380		if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
4381		    flags.nounmount ? CL_GATHER_DONT_UNMOUNT : 0,
4382		    flags.forceunmount ? MS_FORCE : 0)) == NULL) {
4383			return (-1);
4384		}
4385
4386		if (changelist_haszonedchild(cl)) {
4387			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4388			    "child dataset with inherited mountpoint is used "
4389			    "in a non-global zone"));
4390			(void) zfs_error(hdl, EZFS_ZONED, errbuf);
4391			ret = -1;
4392			goto error;
4393		}
4394
4395		if ((ret = changelist_prefix(cl)) != 0)
4396			goto error;
4397	}
4398
4399	if (ZFS_IS_VOLUME(zhp))
4400		zc.zc_objset_type = DMU_OST_ZVOL;
4401	else
4402		zc.zc_objset_type = DMU_OST_ZFS;
4403
4404	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4405	(void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
4406
4407	zc.zc_cookie = flags.recurse ? 1 : 0;
4408	if (flags.nounmount)
4409		zc.zc_cookie |= 2;
4410
4411	if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
4412		/*
4413		 * if it was recursive, the one that actually failed will
4414		 * be in zc.zc_name
4415		 */
4416		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4417		    "cannot rename '%s'"), zc.zc_name);
4418
4419		if (flags.recurse && errno == EEXIST) {
4420			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4421			    "a child dataset already has a snapshot "
4422			    "with the new name"));
4423			(void) zfs_error(hdl, EZFS_EXISTS, errbuf);
4424		} else {
4425			(void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
4426		}
4427
4428		/*
4429		 * On failure, we still want to remount any filesystems that
4430		 * were previously mounted, so we don't alter the system state.
4431		 */
4432		if (cl != NULL)
4433			(void) changelist_postfix(cl);
4434	} else {
4435		if (cl != NULL) {
4436			changelist_rename(cl, zfs_get_name(zhp), target);
4437			ret = changelist_postfix(cl);
4438		}
4439	}
4440
4441error:
4442	if (parentname != NULL) {
4443		free(parentname);
4444	}
4445	if (zhrp != NULL) {
4446		zfs_close(zhrp);
4447	}
4448	if (cl != NULL) {
4449		changelist_free(cl);
4450	}
4451	return (ret);
4452}
4453
4454nvlist_t *
4455zfs_get_user_props(zfs_handle_t *zhp)
4456{
4457	return (zhp->zfs_user_props);
4458}
4459
4460nvlist_t *
4461zfs_get_recvd_props(zfs_handle_t *zhp)
4462{
4463	if (zhp->zfs_recvd_props == NULL)
4464		if (get_recvd_props_ioctl(zhp) != 0)
4465			return (NULL);
4466	return (zhp->zfs_recvd_props);
4467}
4468
4469/*
4470 * This function is used by 'zfs list' to determine the exact set of columns to
4471 * display, and their maximum widths.  This does two main things:
4472 *
4473 *      - If this is a list of all properties, then expand the list to include
4474 *        all native properties, and set a flag so that for each dataset we look
4475 *        for new unique user properties and add them to the list.
4476 *
4477 *      - For non fixed-width properties, keep track of the maximum width seen
4478 *        so that we can size the column appropriately. If the user has
4479 *        requested received property values, we also need to compute the width
4480 *        of the RECEIVED column.
4481 */
4482int
4483zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received,
4484    boolean_t literal)
4485{
4486	libzfs_handle_t *hdl = zhp->zfs_hdl;
4487	zprop_list_t *entry;
4488	zprop_list_t **last, **start;
4489	nvlist_t *userprops, *propval;
4490	nvpair_t *elem;
4491	char *strval;
4492	char buf[ZFS_MAXPROPLEN];
4493
4494	if (zprop_expand_list(hdl, plp, ZFS_TYPE_DATASET) != 0)
4495		return (-1);
4496
4497	userprops = zfs_get_user_props(zhp);
4498
4499	entry = *plp;
4500	if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) {
4501		/*
4502		 * Go through and add any user properties as necessary.  We
4503		 * start by incrementing our list pointer to the first
4504		 * non-native property.
4505		 */
4506		start = plp;
4507		while (*start != NULL) {
4508			if ((*start)->pl_prop == ZPROP_INVAL)
4509				break;
4510			start = &(*start)->pl_next;
4511		}
4512
4513		elem = NULL;
4514		while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) {
4515			/*
4516			 * See if we've already found this property in our list.
4517			 */
4518			for (last = start; *last != NULL;
4519			    last = &(*last)->pl_next) {
4520				if (strcmp((*last)->pl_user_prop,
4521				    nvpair_name(elem)) == 0)
4522					break;
4523			}
4524
4525			if (*last == NULL) {
4526				if ((entry = zfs_alloc(hdl,
4527				    sizeof (zprop_list_t))) == NULL ||
4528				    ((entry->pl_user_prop = zfs_strdup(hdl,
4529				    nvpair_name(elem)))) == NULL) {
4530					free(entry);
4531					return (-1);
4532				}
4533
4534				entry->pl_prop = ZPROP_INVAL;
4535				entry->pl_width = strlen(nvpair_name(elem));
4536				entry->pl_all = B_TRUE;
4537				*last = entry;
4538			}
4539		}
4540	}
4541
4542	/*
4543	 * Now go through and check the width of any non-fixed columns
4544	 */
4545	for (entry = *plp; entry != NULL; entry = entry->pl_next) {
4546		if (entry->pl_fixed && !literal)
4547			continue;
4548
4549		if (entry->pl_prop != ZPROP_INVAL) {
4550			if (zfs_prop_get(zhp, entry->pl_prop,
4551			    buf, sizeof (buf), NULL, NULL, 0, literal) == 0) {
4552				if (strlen(buf) > entry->pl_width)
4553					entry->pl_width = strlen(buf);
4554			}
4555			if (received && zfs_prop_get_recvd(zhp,
4556			    zfs_prop_to_name(entry->pl_prop),
4557			    buf, sizeof (buf), literal) == 0)
4558				if (strlen(buf) > entry->pl_recvd_width)
4559					entry->pl_recvd_width = strlen(buf);
4560		} else {
4561			if (nvlist_lookup_nvlist(userprops, entry->pl_user_prop,
4562			    &propval) == 0) {
4563				verify(nvlist_lookup_string(propval,
4564				    ZPROP_VALUE, &strval) == 0);
4565				if (strlen(strval) > entry->pl_width)
4566					entry->pl_width = strlen(strval);
4567			}
4568			if (received && zfs_prop_get_recvd(zhp,
4569			    entry->pl_user_prop,
4570			    buf, sizeof (buf), literal) == 0)
4571				if (strlen(buf) > entry->pl_recvd_width)
4572					entry->pl_recvd_width = strlen(buf);
4573		}
4574	}
4575
4576	return (0);
4577}
4578
4579int
4580zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path,
4581    char *resource, void *export, void *sharetab,
4582    int sharemax, zfs_share_op_t operation)
4583{
4584	zfs_cmd_t zc = { 0 };
4585	int error;
4586
4587	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
4588	(void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
4589	if (resource)
4590		(void) strlcpy(zc.zc_string, resource, sizeof (zc.zc_string));
4591	zc.zc_share.z_sharedata = (uint64_t)(uintptr_t)sharetab;
4592	zc.zc_share.z_exportdata = (uint64_t)(uintptr_t)export;
4593	zc.zc_share.z_sharetype = operation;
4594	zc.zc_share.z_sharemax = sharemax;
4595	error = ioctl(hdl->libzfs_fd, ZFS_IOC_SHARE, &zc);
4596	return (error);
4597}
4598
4599void
4600zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props)
4601{
4602	nvpair_t *curr;
4603
4604	/*
4605	 * Keep a reference to the props-table against which we prune the
4606	 * properties.
4607	 */
4608	zhp->zfs_props_table = props;
4609
4610	curr = nvlist_next_nvpair(zhp->zfs_props, NULL);
4611
4612	while (curr) {
4613		zfs_prop_t zfs_prop = zfs_name_to_prop(nvpair_name(curr));
4614		nvpair_t *next = nvlist_next_nvpair(zhp->zfs_props, curr);
4615
4616		/*
4617		 * User properties will result in ZPROP_INVAL, and since we
4618		 * only know how to prune standard ZFS properties, we always
4619		 * leave these in the list.  This can also happen if we
4620		 * encounter an unknown DSL property (when running older
4621		 * software, for example).
4622		 */
4623		if (zfs_prop != ZPROP_INVAL && props[zfs_prop] == B_FALSE)
4624			(void) nvlist_remove(zhp->zfs_props,
4625			    nvpair_name(curr), nvpair_type(curr));
4626		curr = next;
4627	}
4628}
4629
4630#ifdef illumos
4631static int
4632zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path,
4633    zfs_smb_acl_op_t cmd, char *resource1, char *resource2)
4634{
4635	zfs_cmd_t zc = { 0 };
4636	nvlist_t *nvlist = NULL;
4637	int error;
4638
4639	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
4640	(void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
4641	zc.zc_cookie = (uint64_t)cmd;
4642
4643	if (cmd == ZFS_SMB_ACL_RENAME) {
4644		if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) {
4645			(void) no_memory(hdl);
4646			return (0);
4647		}
4648	}
4649
4650	switch (cmd) {
4651	case ZFS_SMB_ACL_ADD:
4652	case ZFS_SMB_ACL_REMOVE:
4653		(void) strlcpy(zc.zc_string, resource1, sizeof (zc.zc_string));
4654		break;
4655	case ZFS_SMB_ACL_RENAME:
4656		if (nvlist_add_string(nvlist, ZFS_SMB_ACL_SRC,
4657		    resource1) != 0) {
4658				(void) no_memory(hdl);
4659				return (-1);
4660		}
4661		if (nvlist_add_string(nvlist, ZFS_SMB_ACL_TARGET,
4662		    resource2) != 0) {
4663				(void) no_memory(hdl);
4664				return (-1);
4665		}
4666		if (zcmd_write_src_nvlist(hdl, &zc, nvlist) != 0) {
4667			nvlist_free(nvlist);
4668			return (-1);
4669		}
4670		break;
4671	case ZFS_SMB_ACL_PURGE:
4672		break;
4673	default:
4674		return (-1);
4675	}
4676	error = ioctl(hdl->libzfs_fd, ZFS_IOC_SMB_ACL, &zc);
4677	nvlist_free(nvlist);
4678	return (error);
4679}
4680
4681int
4682zfs_smb_acl_add(libzfs_handle_t *hdl, char *dataset,
4683    char *path, char *resource)
4684{
4685	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_ADD,
4686	    resource, NULL));
4687}
4688
4689int
4690zfs_smb_acl_remove(libzfs_handle_t *hdl, char *dataset,
4691    char *path, char *resource)
4692{
4693	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_REMOVE,
4694	    resource, NULL));
4695}
4696
4697int
4698zfs_smb_acl_purge(libzfs_handle_t *hdl, char *dataset, char *path)
4699{
4700	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_PURGE,
4701	    NULL, NULL));
4702}
4703
4704int
4705zfs_smb_acl_rename(libzfs_handle_t *hdl, char *dataset, char *path,
4706    char *oldname, char *newname)
4707{
4708	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME,
4709	    oldname, newname));
4710}
4711#endif	/* illumos */
4712
4713int
4714zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
4715    zfs_userspace_cb_t func, void *arg)
4716{
4717	zfs_cmd_t zc = { 0 };
4718	zfs_useracct_t buf[100];
4719	libzfs_handle_t *hdl = zhp->zfs_hdl;
4720	int ret;
4721
4722	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4723
4724	zc.zc_objset_type = type;
4725	zc.zc_nvlist_dst = (uintptr_t)buf;
4726
4727	for (;;) {
4728		zfs_useracct_t *zua = buf;
4729
4730		zc.zc_nvlist_dst_size = sizeof (buf);
4731		if (zfs_ioctl(hdl, ZFS_IOC_USERSPACE_MANY, &zc) != 0) {
4732			char errbuf[1024];
4733
4734			(void) snprintf(errbuf, sizeof (errbuf),
4735			    dgettext(TEXT_DOMAIN,
4736			    "cannot get used/quota for %s"), zc.zc_name);
4737			return (zfs_standard_error_fmt(hdl, errno, errbuf));
4738		}
4739		if (zc.zc_nvlist_dst_size == 0)
4740			break;
4741
4742		while (zc.zc_nvlist_dst_size > 0) {
4743			if ((ret = func(arg, zua->zu_domain, zua->zu_rid,
4744			    zua->zu_space)) != 0)
4745				return (ret);
4746			zua++;
4747			zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t);
4748		}
4749	}
4750
4751	return (0);
4752}
4753
4754struct holdarg {
4755	nvlist_t *nvl;
4756	const char *snapname;
4757	const char *tag;
4758	boolean_t recursive;
4759	int error;
4760};
4761
4762static int
4763zfs_hold_one(zfs_handle_t *zhp, void *arg)
4764{
4765	struct holdarg *ha = arg;
4766	char name[ZFS_MAX_DATASET_NAME_LEN];
4767	int rv = 0;
4768
4769	(void) snprintf(name, sizeof (name),
4770	    "%s@%s", zhp->zfs_name, ha->snapname);
4771
4772	if (lzc_exists(name))
4773		fnvlist_add_string(ha->nvl, name, ha->tag);
4774
4775	if (ha->recursive)
4776		rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha);
4777	zfs_close(zhp);
4778	return (rv);
4779}
4780
4781int
4782zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
4783    boolean_t recursive, int cleanup_fd)
4784{
4785	int ret;
4786	struct holdarg ha;
4787
4788	ha.nvl = fnvlist_alloc();
4789	ha.snapname = snapname;
4790	ha.tag = tag;
4791	ha.recursive = recursive;
4792	(void) zfs_hold_one(zfs_handle_dup(zhp), &ha);
4793
4794	if (nvlist_empty(ha.nvl)) {
4795		char errbuf[1024];
4796
4797		fnvlist_free(ha.nvl);
4798		ret = ENOENT;
4799		(void) snprintf(errbuf, sizeof (errbuf),
4800		    dgettext(TEXT_DOMAIN,
4801		    "cannot hold snapshot '%s@%s'"),
4802		    zhp->zfs_name, snapname);
4803		(void) zfs_standard_error(zhp->zfs_hdl, ret, errbuf);
4804		return (ret);
4805	}
4806
4807	ret = zfs_hold_nvl(zhp, cleanup_fd, ha.nvl);
4808	fnvlist_free(ha.nvl);
4809
4810	return (ret);
4811}
4812
4813int
4814zfs_hold_nvl(zfs_handle_t *zhp, int cleanup_fd, nvlist_t *holds)
4815{
4816	int ret;
4817	nvlist_t *errors;
4818	libzfs_handle_t *hdl = zhp->zfs_hdl;
4819	char errbuf[1024];
4820	nvpair_t *elem;
4821
4822	errors = NULL;
4823	ret = lzc_hold(holds, cleanup_fd, &errors);
4824
4825	if (ret == 0) {
4826		/* There may be errors even in the success case. */
4827		fnvlist_free(errors);
4828		return (0);
4829	}
4830
4831	if (nvlist_empty(errors)) {
4832		/* no hold-specific errors */
4833		(void) snprintf(errbuf, sizeof (errbuf),
4834		    dgettext(TEXT_DOMAIN, "cannot hold"));
4835		switch (ret) {
4836		case ENOTSUP:
4837			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4838			    "pool must be upgraded"));
4839			(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
4840			break;
4841		case EINVAL:
4842			(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4843			break;
4844		default:
4845			(void) zfs_standard_error(hdl, ret, errbuf);
4846		}
4847	}
4848
4849	for (elem = nvlist_next_nvpair(errors, NULL);
4850	    elem != NULL;
4851	    elem = nvlist_next_nvpair(errors, elem)) {
4852		(void) snprintf(errbuf, sizeof (errbuf),
4853		    dgettext(TEXT_DOMAIN,
4854		    "cannot hold snapshot '%s'"), nvpair_name(elem));
4855		switch (fnvpair_value_int32(elem)) {
4856		case E2BIG:
4857			/*
4858			 * Temporary tags wind up having the ds object id
4859			 * prepended. So even if we passed the length check
4860			 * above, it's still possible for the tag to wind
4861			 * up being slightly too long.
4862			 */
4863			(void) zfs_error(hdl, EZFS_TAGTOOLONG, errbuf);
4864			break;
4865		case EINVAL:
4866			(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4867			break;
4868		case EEXIST:
4869			(void) zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf);
4870			break;
4871		default:
4872			(void) zfs_standard_error(hdl,
4873			    fnvpair_value_int32(elem), errbuf);
4874		}
4875	}
4876
4877	fnvlist_free(errors);
4878	return (ret);
4879}
4880
4881static int
4882zfs_release_one(zfs_handle_t *zhp, void *arg)
4883{
4884	struct holdarg *ha = arg;
4885	char name[ZFS_MAX_DATASET_NAME_LEN];
4886	int rv = 0;
4887	nvlist_t *existing_holds;
4888
4889	(void) snprintf(name, sizeof (name),
4890	    "%s@%s", zhp->zfs_name, ha->snapname);
4891
4892	if (lzc_get_holds(name, &existing_holds) != 0) {
4893		ha->error = ENOENT;
4894	} else if (!nvlist_exists(existing_holds, ha->tag)) {
4895		ha->error = ESRCH;
4896	} else {
4897		nvlist_t *torelease = fnvlist_alloc();
4898		fnvlist_add_boolean(torelease, ha->tag);
4899		fnvlist_add_nvlist(ha->nvl, name, torelease);
4900		fnvlist_free(torelease);
4901	}
4902
4903	if (ha->recursive)
4904		rv = zfs_iter_filesystems(zhp, zfs_release_one, ha);
4905	zfs_close(zhp);
4906	return (rv);
4907}
4908
4909int
4910zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
4911    boolean_t recursive)
4912{
4913	int ret;
4914	struct holdarg ha;
4915	nvlist_t *errors = NULL;
4916	nvpair_t *elem;
4917	libzfs_handle_t *hdl = zhp->zfs_hdl;
4918	char errbuf[1024];
4919
4920	ha.nvl = fnvlist_alloc();
4921	ha.snapname = snapname;
4922	ha.tag = tag;
4923	ha.recursive = recursive;
4924	ha.error = 0;
4925	(void) zfs_release_one(zfs_handle_dup(zhp), &ha);
4926
4927	if (nvlist_empty(ha.nvl)) {
4928		fnvlist_free(ha.nvl);
4929		ret = ha.error;
4930		(void) snprintf(errbuf, sizeof (errbuf),
4931		    dgettext(TEXT_DOMAIN,
4932		    "cannot release hold from snapshot '%s@%s'"),
4933		    zhp->zfs_name, snapname);
4934		if (ret == ESRCH) {
4935			(void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
4936		} else {
4937			(void) zfs_standard_error(hdl, ret, errbuf);
4938		}
4939		return (ret);
4940	}
4941
4942	ret = lzc_release(ha.nvl, &errors);
4943	fnvlist_free(ha.nvl);
4944
4945	if (ret == 0) {
4946		/* There may be errors even in the success case. */
4947		fnvlist_free(errors);
4948		return (0);
4949	}
4950
4951	if (nvlist_empty(errors)) {
4952		/* no hold-specific errors */
4953		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4954		    "cannot release"));
4955		switch (errno) {
4956		case ENOTSUP:
4957			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4958			    "pool must be upgraded"));
4959			(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
4960			break;
4961		default:
4962			(void) zfs_standard_error_fmt(hdl, errno, errbuf);
4963		}
4964	}
4965
4966	for (elem = nvlist_next_nvpair(errors, NULL);
4967	    elem != NULL;
4968	    elem = nvlist_next_nvpair(errors, elem)) {
4969		(void) snprintf(errbuf, sizeof (errbuf),
4970		    dgettext(TEXT_DOMAIN,
4971		    "cannot release hold from snapshot '%s'"),
4972		    nvpair_name(elem));
4973		switch (fnvpair_value_int32(elem)) {
4974		case ESRCH:
4975			(void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
4976			break;
4977		case EINVAL:
4978			(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4979			break;
4980		default:
4981			(void) zfs_standard_error_fmt(hdl,
4982			    fnvpair_value_int32(elem), errbuf);
4983		}
4984	}
4985
4986	fnvlist_free(errors);
4987	return (ret);
4988}
4989
4990int
4991zfs_get_fsacl(zfs_handle_t *zhp, nvlist_t **nvl)
4992{
4993	zfs_cmd_t zc = { 0 };
4994	libzfs_handle_t *hdl = zhp->zfs_hdl;
4995	int nvsz = 2048;
4996	void *nvbuf;
4997	int err = 0;
4998	char errbuf[1024];
4999
5000	assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
5001	    zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
5002
5003tryagain:
5004
5005	nvbuf = malloc(nvsz);
5006	if (nvbuf == NULL) {
5007		err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
5008		goto out;
5009	}
5010
5011	zc.zc_nvlist_dst_size = nvsz;
5012	zc.zc_nvlist_dst = (uintptr_t)nvbuf;
5013
5014	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
5015
5016	if (ioctl(hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) {
5017		(void) snprintf(errbuf, sizeof (errbuf),
5018		    dgettext(TEXT_DOMAIN, "cannot get permissions on '%s'"),
5019		    zc.zc_name);
5020		switch (errno) {
5021		case ENOMEM:
5022			free(nvbuf);
5023			nvsz = zc.zc_nvlist_dst_size;
5024			goto tryagain;
5025
5026		case ENOTSUP:
5027			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5028			    "pool must be upgraded"));
5029			err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
5030			break;
5031		case EINVAL:
5032			err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
5033			break;
5034		case ENOENT:
5035			err = zfs_error(hdl, EZFS_NOENT, errbuf);
5036			break;
5037		default:
5038			err = zfs_standard_error_fmt(hdl, errno, errbuf);
5039			break;
5040		}
5041	} else {
5042		/* success */
5043		int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
5044		if (rc) {
5045			(void) snprintf(errbuf, sizeof (errbuf), dgettext(
5046			    TEXT_DOMAIN, "cannot get permissions on '%s'"),
5047			    zc.zc_name);
5048			err = zfs_standard_error_fmt(hdl, rc, errbuf);
5049		}
5050	}
5051
5052	free(nvbuf);
5053out:
5054	return (err);
5055}
5056
5057int
5058zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl)
5059{
5060	zfs_cmd_t zc = { 0 };
5061	libzfs_handle_t *hdl = zhp->zfs_hdl;
5062	char *nvbuf;
5063	char errbuf[1024];
5064	size_t nvsz;
5065	int err;
5066
5067	assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
5068	    zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
5069
5070	err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE);
5071	assert(err == 0);
5072
5073	nvbuf = malloc(nvsz);
5074
5075	err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0);
5076	assert(err == 0);
5077
5078	zc.zc_nvlist_src_size = nvsz;
5079	zc.zc_nvlist_src = (uintptr_t)nvbuf;
5080	zc.zc_perm_action = un;
5081
5082	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
5083
5084	if (zfs_ioctl(hdl, ZFS_IOC_SET_FSACL, &zc) != 0) {
5085		(void) snprintf(errbuf, sizeof (errbuf),
5086		    dgettext(TEXT_DOMAIN, "cannot set permissions on '%s'"),
5087		    zc.zc_name);
5088		switch (errno) {
5089		case ENOTSUP:
5090			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5091			    "pool must be upgraded"));
5092			err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
5093			break;
5094		case EINVAL:
5095			err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
5096			break;
5097		case ENOENT:
5098			err = zfs_error(hdl, EZFS_NOENT, errbuf);
5099			break;
5100		default:
5101			err = zfs_standard_error_fmt(hdl, errno, errbuf);
5102			break;
5103		}
5104	}
5105
5106	free(nvbuf);
5107
5108	return (err);
5109}
5110
5111int
5112zfs_get_holds(zfs_handle_t *zhp, nvlist_t **nvl)
5113{
5114	int err;
5115	char errbuf[1024];
5116
5117	err = lzc_get_holds(zhp->zfs_name, nvl);
5118
5119	if (err != 0) {
5120		libzfs_handle_t *hdl = zhp->zfs_hdl;
5121
5122		(void) snprintf(errbuf, sizeof (errbuf),
5123		    dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
5124		    zhp->zfs_name);
5125		switch (err) {
5126		case ENOTSUP:
5127			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5128			    "pool must be upgraded"));
5129			err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
5130			break;
5131		case EINVAL:
5132			err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
5133			break;
5134		case ENOENT:
5135			err = zfs_error(hdl, EZFS_NOENT, errbuf);
5136			break;
5137		default:
5138			err = zfs_standard_error_fmt(hdl, errno, errbuf);
5139			break;
5140		}
5141	}
5142
5143	return (err);
5144}
5145
5146/*
5147 * Convert the zvol's volume size to an appropriate reservation.
5148 * Note: If this routine is updated, it is necessary to update the ZFS test
5149 * suite's shell version in reservation.kshlib.
5150 */
5151uint64_t
5152zvol_volsize_to_reservation(uint64_t volsize, nvlist_t *props)
5153{
5154	uint64_t numdb;
5155	uint64_t nblocks, volblocksize;
5156	int ncopies;
5157	char *strval;
5158
5159	if (nvlist_lookup_string(props,
5160	    zfs_prop_to_name(ZFS_PROP_COPIES), &strval) == 0)
5161		ncopies = atoi(strval);
5162	else
5163		ncopies = 1;
5164	if (nvlist_lookup_uint64(props,
5165	    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
5166	    &volblocksize) != 0)
5167		volblocksize = ZVOL_DEFAULT_BLOCKSIZE;
5168	nblocks = volsize/volblocksize;
5169	/* start with metadnode L0-L6 */
5170	numdb = 7;
5171	/* calculate number of indirects */
5172	while (nblocks > 1) {
5173		nblocks += DNODES_PER_LEVEL - 1;
5174		nblocks /= DNODES_PER_LEVEL;
5175		numdb += nblocks;
5176	}
5177	numdb *= MIN(SPA_DVAS_PER_BP, ncopies + 1);
5178	volsize *= ncopies;
5179	/*
5180	 * this is exactly DN_MAX_INDBLKSHIFT when metadata isn't
5181	 * compressed, but in practice they compress down to about
5182	 * 1100 bytes
5183	 */
5184	numdb *= 1ULL << DN_MAX_INDBLKSHIFT;
5185	volsize += numdb;
5186	return (volsize);
5187}
5188
5189/*
5190 * Attach/detach the given filesystem to/from the given jail.
5191 */
5192int
5193zfs_jail(zfs_handle_t *zhp, int jailid, int attach)
5194{
5195	libzfs_handle_t *hdl = zhp->zfs_hdl;
5196	zfs_cmd_t zc = { 0 };
5197	char errbuf[1024];
5198	unsigned long cmd;
5199	int ret;
5200
5201	if (attach) {
5202		(void) snprintf(errbuf, sizeof (errbuf),
5203		    dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name);
5204	} else {
5205		(void) snprintf(errbuf, sizeof (errbuf),
5206		    dgettext(TEXT_DOMAIN, "cannot unjail '%s'"), zhp->zfs_name);
5207	}
5208
5209	switch (zhp->zfs_type) {
5210	case ZFS_TYPE_VOLUME:
5211		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5212		    "volumes can not be jailed"));
5213		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
5214	case ZFS_TYPE_SNAPSHOT:
5215		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
5216		    "snapshots can not be jailed"));
5217		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
5218	}
5219	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
5220
5221	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
5222	zc.zc_objset_type = DMU_OST_ZFS;
5223	zc.zc_jailid = jailid;
5224
5225	cmd = attach ? ZFS_IOC_JAIL : ZFS_IOC_UNJAIL;
5226	if ((ret = ioctl(hdl->libzfs_fd, cmd, &zc)) != 0)
5227		zfs_standard_error(hdl, errno, errbuf);
5228
5229	return (ret);
5230}
5231