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