libzfs_dataset.c revision 323757
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, 2015 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			}
2170			break;
2171
2172		case PROP_TYPE_STRING:
2173		default:
2174			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2175			    "cannot get non-numeric property"));
2176			return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP,
2177			    dgettext(TEXT_DOMAIN, "internal error")));
2178		}
2179	}
2180
2181	return (0);
2182}
2183
2184/*
2185 * Calculate the source type, given the raw source string.
2186 */
2187static void
2188get_source(zfs_handle_t *zhp, zprop_source_t *srctype, char *source,
2189    char *statbuf, size_t statlen)
2190{
2191	if (statbuf == NULL || *srctype == ZPROP_SRC_TEMPORARY)
2192		return;
2193
2194	if (source == NULL) {
2195		*srctype = ZPROP_SRC_NONE;
2196	} else if (source[0] == '\0') {
2197		*srctype = ZPROP_SRC_DEFAULT;
2198	} else if (strstr(source, ZPROP_SOURCE_VAL_RECVD) != NULL) {
2199		*srctype = ZPROP_SRC_RECEIVED;
2200	} else {
2201		if (strcmp(source, zhp->zfs_name) == 0) {
2202			*srctype = ZPROP_SRC_LOCAL;
2203		} else {
2204			(void) strlcpy(statbuf, source, statlen);
2205			*srctype = ZPROP_SRC_INHERITED;
2206		}
2207	}
2208
2209}
2210
2211int
2212zfs_prop_get_recvd(zfs_handle_t *zhp, const char *propname, char *propbuf,
2213    size_t proplen, boolean_t literal)
2214{
2215	zfs_prop_t prop;
2216	int err = 0;
2217
2218	if (zhp->zfs_recvd_props == NULL)
2219		if (get_recvd_props_ioctl(zhp) != 0)
2220			return (-1);
2221
2222	prop = zfs_name_to_prop(propname);
2223
2224	if (prop != ZPROP_INVAL) {
2225		uint64_t cookie;
2226		if (!nvlist_exists(zhp->zfs_recvd_props, propname))
2227			return (-1);
2228		zfs_set_recvd_props_mode(zhp, &cookie);
2229		err = zfs_prop_get(zhp, prop, propbuf, proplen,
2230		    NULL, NULL, 0, literal);
2231		zfs_unset_recvd_props_mode(zhp, &cookie);
2232	} else {
2233		nvlist_t *propval;
2234		char *recvdval;
2235		if (nvlist_lookup_nvlist(zhp->zfs_recvd_props,
2236		    propname, &propval) != 0)
2237			return (-1);
2238		verify(nvlist_lookup_string(propval, ZPROP_VALUE,
2239		    &recvdval) == 0);
2240		(void) strlcpy(propbuf, recvdval, proplen);
2241	}
2242
2243	return (err == 0 ? 0 : -1);
2244}
2245
2246static int
2247get_clones_string(zfs_handle_t *zhp, char *propbuf, size_t proplen)
2248{
2249	nvlist_t *value;
2250	nvpair_t *pair;
2251
2252	value = zfs_get_clones_nvl(zhp);
2253	if (value == NULL)
2254		return (-1);
2255
2256	propbuf[0] = '\0';
2257	for (pair = nvlist_next_nvpair(value, NULL); pair != NULL;
2258	    pair = nvlist_next_nvpair(value, pair)) {
2259		if (propbuf[0] != '\0')
2260			(void) strlcat(propbuf, ",", proplen);
2261		(void) strlcat(propbuf, nvpair_name(pair), proplen);
2262	}
2263
2264	return (0);
2265}
2266
2267struct get_clones_arg {
2268	uint64_t numclones;
2269	nvlist_t *value;
2270	const char *origin;
2271	char buf[ZFS_MAX_DATASET_NAME_LEN];
2272};
2273
2274int
2275get_clones_cb(zfs_handle_t *zhp, void *arg)
2276{
2277	struct get_clones_arg *gca = arg;
2278
2279	if (gca->numclones == 0) {
2280		zfs_close(zhp);
2281		return (0);
2282	}
2283
2284	if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, gca->buf, sizeof (gca->buf),
2285	    NULL, NULL, 0, B_TRUE) != 0)
2286		goto out;
2287	if (strcmp(gca->buf, gca->origin) == 0) {
2288		fnvlist_add_boolean(gca->value, zfs_get_name(zhp));
2289		gca->numclones--;
2290	}
2291
2292out:
2293	(void) zfs_iter_children(zhp, get_clones_cb, gca);
2294	zfs_close(zhp);
2295	return (0);
2296}
2297
2298nvlist_t *
2299zfs_get_clones_nvl(zfs_handle_t *zhp)
2300{
2301	nvlist_t *nv, *value;
2302
2303	if (nvlist_lookup_nvlist(zhp->zfs_props,
2304	    zfs_prop_to_name(ZFS_PROP_CLONES), &nv) != 0) {
2305		struct get_clones_arg gca;
2306
2307		/*
2308		 * if this is a snapshot, then the kernel wasn't able
2309		 * to get the clones.  Do it by slowly iterating.
2310		 */
2311		if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT)
2312			return (NULL);
2313		if (nvlist_alloc(&nv, NV_UNIQUE_NAME, 0) != 0)
2314			return (NULL);
2315		if (nvlist_alloc(&value, NV_UNIQUE_NAME, 0) != 0) {
2316			nvlist_free(nv);
2317			return (NULL);
2318		}
2319
2320		gca.numclones = zfs_prop_get_int(zhp, ZFS_PROP_NUMCLONES);
2321		gca.value = value;
2322		gca.origin = zhp->zfs_name;
2323
2324		if (gca.numclones != 0) {
2325			zfs_handle_t *root;
2326			char pool[ZFS_MAX_DATASET_NAME_LEN];
2327			char *cp = pool;
2328
2329			/* get the pool name */
2330			(void) strlcpy(pool, zhp->zfs_name, sizeof (pool));
2331			(void) strsep(&cp, "/@");
2332			root = zfs_open(zhp->zfs_hdl, pool,
2333			    ZFS_TYPE_FILESYSTEM);
2334
2335			(void) get_clones_cb(root, &gca);
2336		}
2337
2338		if (gca.numclones != 0 ||
2339		    nvlist_add_nvlist(nv, ZPROP_VALUE, value) != 0 ||
2340		    nvlist_add_nvlist(zhp->zfs_props,
2341		    zfs_prop_to_name(ZFS_PROP_CLONES), nv) != 0) {
2342			nvlist_free(nv);
2343			nvlist_free(value);
2344			return (NULL);
2345		}
2346		nvlist_free(nv);
2347		nvlist_free(value);
2348		verify(0 == nvlist_lookup_nvlist(zhp->zfs_props,
2349		    zfs_prop_to_name(ZFS_PROP_CLONES), &nv));
2350	}
2351
2352	verify(nvlist_lookup_nvlist(nv, ZPROP_VALUE, &value) == 0);
2353
2354	return (value);
2355}
2356
2357/*
2358 * Retrieve a property from the given object.  If 'literal' is specified, then
2359 * numbers are left as exact values.  Otherwise, numbers are converted to a
2360 * human-readable form.
2361 *
2362 * Returns 0 on success, or -1 on error.
2363 */
2364int
2365zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
2366    zprop_source_t *src, char *statbuf, size_t statlen, boolean_t literal)
2367{
2368	char *source = NULL;
2369	uint64_t val;
2370	const char *str;
2371	const char *strval;
2372	boolean_t received = zfs_is_recvd_props_mode(zhp);
2373
2374	/*
2375	 * Check to see if this property applies to our object
2376	 */
2377	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
2378		return (-1);
2379
2380	if (received && zfs_prop_readonly(prop))
2381		return (-1);
2382
2383	if (src)
2384		*src = ZPROP_SRC_NONE;
2385
2386	switch (prop) {
2387	case ZFS_PROP_CREATION:
2388		/*
2389		 * 'creation' is a time_t stored in the statistics.  We convert
2390		 * this into a string unless 'literal' is specified.
2391		 */
2392		{
2393			val = getprop_uint64(zhp, prop, &source);
2394			time_t time = (time_t)val;
2395			struct tm t;
2396
2397			if (literal ||
2398			    localtime_r(&time, &t) == NULL ||
2399			    strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
2400			    &t) == 0)
2401				(void) snprintf(propbuf, proplen, "%llu", val);
2402		}
2403		break;
2404
2405	case ZFS_PROP_MOUNTPOINT:
2406		/*
2407		 * Getting the precise mountpoint can be tricky.
2408		 *
2409		 *  - for 'none' or 'legacy', return those values.
2410		 *  - for inherited mountpoints, we want to take everything
2411		 *    after our ancestor and append it to the inherited value.
2412		 *
2413		 * If the pool has an alternate root, we want to prepend that
2414		 * root to any values we return.
2415		 */
2416
2417		str = getprop_string(zhp, prop, &source);
2418
2419		if (str[0] == '/') {
2420			char buf[MAXPATHLEN];
2421			char *root = buf;
2422			const char *relpath;
2423
2424			/*
2425			 * If we inherit the mountpoint, even from a dataset
2426			 * with a received value, the source will be the path of
2427			 * the dataset we inherit from. If source is
2428			 * ZPROP_SOURCE_VAL_RECVD, the received value is not
2429			 * inherited.
2430			 */
2431			if (strcmp(source, ZPROP_SOURCE_VAL_RECVD) == 0) {
2432				relpath = "";
2433			} else {
2434				relpath = zhp->zfs_name + strlen(source);
2435				if (relpath[0] == '/')
2436					relpath++;
2437			}
2438
2439			if ((zpool_get_prop(zhp->zpool_hdl,
2440			    ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL,
2441			    B_FALSE)) || (strcmp(root, "-") == 0))
2442				root[0] = '\0';
2443			/*
2444			 * Special case an alternate root of '/'. This will
2445			 * avoid having multiple leading slashes in the
2446			 * mountpoint path.
2447			 */
2448			if (strcmp(root, "/") == 0)
2449				root++;
2450
2451			/*
2452			 * If the mountpoint is '/' then skip over this
2453			 * if we are obtaining either an alternate root or
2454			 * an inherited mountpoint.
2455			 */
2456			if (str[1] == '\0' && (root[0] != '\0' ||
2457			    relpath[0] != '\0'))
2458				str++;
2459
2460			if (relpath[0] == '\0')
2461				(void) snprintf(propbuf, proplen, "%s%s",
2462				    root, str);
2463			else
2464				(void) snprintf(propbuf, proplen, "%s%s%s%s",
2465				    root, str, relpath[0] == '@' ? "" : "/",
2466				    relpath);
2467		} else {
2468			/* 'legacy' or 'none' */
2469			(void) strlcpy(propbuf, str, proplen);
2470		}
2471
2472		break;
2473
2474	case ZFS_PROP_ORIGIN:
2475		str = getprop_string(zhp, prop, &source);
2476		if (str == NULL)
2477			return (-1);
2478		(void) strlcpy(propbuf, str, proplen);
2479		break;
2480
2481	case ZFS_PROP_CLONES:
2482		if (get_clones_string(zhp, propbuf, proplen) != 0)
2483			return (-1);
2484		break;
2485
2486	case ZFS_PROP_QUOTA:
2487	case ZFS_PROP_REFQUOTA:
2488	case ZFS_PROP_RESERVATION:
2489	case ZFS_PROP_REFRESERVATION:
2490
2491		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2492			return (-1);
2493
2494		/*
2495		 * If quota or reservation is 0, we translate this into 'none'
2496		 * (unless literal is set), and indicate that it's the default
2497		 * value.  Otherwise, we print the number nicely and indicate
2498		 * that its set locally.
2499		 */
2500		if (val == 0) {
2501			if (literal)
2502				(void) strlcpy(propbuf, "0", proplen);
2503			else
2504				(void) strlcpy(propbuf, "none", proplen);
2505		} else {
2506			if (literal)
2507				(void) snprintf(propbuf, proplen, "%llu",
2508				    (u_longlong_t)val);
2509			else
2510				zfs_nicenum(val, propbuf, proplen);
2511		}
2512		break;
2513
2514	case ZFS_PROP_FILESYSTEM_LIMIT:
2515	case ZFS_PROP_SNAPSHOT_LIMIT:
2516	case ZFS_PROP_FILESYSTEM_COUNT:
2517	case ZFS_PROP_SNAPSHOT_COUNT:
2518
2519		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2520			return (-1);
2521
2522		/*
2523		 * If limit is UINT64_MAX, we translate this into 'none' (unless
2524		 * literal is set), and indicate that it's the default value.
2525		 * Otherwise, we print the number nicely and indicate that it's
2526		 * set locally.
2527		 */
2528		if (literal) {
2529			(void) snprintf(propbuf, proplen, "%llu",
2530			    (u_longlong_t)val);
2531		} else if (val == UINT64_MAX) {
2532			(void) strlcpy(propbuf, "none", proplen);
2533		} else {
2534			zfs_nicenum(val, propbuf, proplen);
2535		}
2536		break;
2537
2538	case ZFS_PROP_REFRATIO:
2539	case ZFS_PROP_COMPRESSRATIO:
2540		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2541			return (-1);
2542		(void) snprintf(propbuf, proplen, "%llu.%02llux",
2543		    (u_longlong_t)(val / 100),
2544		    (u_longlong_t)(val % 100));
2545		break;
2546
2547	case ZFS_PROP_TYPE:
2548		switch (zhp->zfs_type) {
2549		case ZFS_TYPE_FILESYSTEM:
2550			str = "filesystem";
2551			break;
2552		case ZFS_TYPE_VOLUME:
2553			str = "volume";
2554			break;
2555		case ZFS_TYPE_SNAPSHOT:
2556			str = "snapshot";
2557			break;
2558		case ZFS_TYPE_BOOKMARK:
2559			str = "bookmark";
2560			break;
2561		default:
2562			abort();
2563		}
2564		(void) snprintf(propbuf, proplen, "%s", str);
2565		break;
2566
2567	case ZFS_PROP_MOUNTED:
2568		/*
2569		 * The 'mounted' property is a pseudo-property that described
2570		 * whether the filesystem is currently mounted.  Even though
2571		 * it's a boolean value, the typical values of "on" and "off"
2572		 * don't make sense, so we translate to "yes" and "no".
2573		 */
2574		if (get_numeric_property(zhp, ZFS_PROP_MOUNTED,
2575		    src, &source, &val) != 0)
2576			return (-1);
2577		if (val)
2578			(void) strlcpy(propbuf, "yes", proplen);
2579		else
2580			(void) strlcpy(propbuf, "no", proplen);
2581		break;
2582
2583	case ZFS_PROP_NAME:
2584		/*
2585		 * The 'name' property is a pseudo-property derived from the
2586		 * dataset name.  It is presented as a real property to simplify
2587		 * consumers.
2588		 */
2589		(void) strlcpy(propbuf, zhp->zfs_name, proplen);
2590		break;
2591
2592	case ZFS_PROP_MLSLABEL:
2593		{
2594#ifdef illumos
2595			m_label_t *new_sl = NULL;
2596			char *ascii = NULL;	/* human readable label */
2597
2598			(void) strlcpy(propbuf,
2599			    getprop_string(zhp, prop, &source), proplen);
2600
2601			if (literal || (strcasecmp(propbuf,
2602			    ZFS_MLSLABEL_DEFAULT) == 0))
2603				break;
2604
2605			/*
2606			 * Try to translate the internal hex string to
2607			 * human-readable output.  If there are any
2608			 * problems just use the hex string.
2609			 */
2610
2611			if (str_to_label(propbuf, &new_sl, MAC_LABEL,
2612			    L_NO_CORRECTION, NULL) == -1) {
2613				m_label_free(new_sl);
2614				break;
2615			}
2616
2617			if (label_to_str(new_sl, &ascii, M_LABEL,
2618			    DEF_NAMES) != 0) {
2619				if (ascii)
2620					free(ascii);
2621				m_label_free(new_sl);
2622				break;
2623			}
2624			m_label_free(new_sl);
2625
2626			(void) strlcpy(propbuf, ascii, proplen);
2627			free(ascii);
2628#else	/* !illumos */
2629			propbuf[0] = '\0';
2630#endif	/* illumos */
2631		}
2632		break;
2633
2634	case ZFS_PROP_GUID:
2635		/*
2636		 * GUIDs are stored as numbers, but they are identifiers.
2637		 * We don't want them to be pretty printed, because pretty
2638		 * printing mangles the ID into a truncated and useless value.
2639		 */
2640		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
2641			return (-1);
2642		(void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
2643		break;
2644
2645	default:
2646		switch (zfs_prop_get_type(prop)) {
2647		case PROP_TYPE_NUMBER:
2648			if (get_numeric_property(zhp, prop, src,
2649			    &source, &val) != 0)
2650				return (-1);
2651			if (literal)
2652				(void) snprintf(propbuf, proplen, "%llu",
2653				    (u_longlong_t)val);
2654			else
2655				zfs_nicenum(val, propbuf, proplen);
2656			break;
2657
2658		case PROP_TYPE_STRING:
2659			str = getprop_string(zhp, prop, &source);
2660			if (str == NULL)
2661				return (-1);
2662			(void) strlcpy(propbuf, str, proplen);
2663			break;
2664
2665		case PROP_TYPE_INDEX:
2666			if (get_numeric_property(zhp, prop, src,
2667			    &source, &val) != 0)
2668				return (-1);
2669			if (zfs_prop_index_to_string(prop, val, &strval) != 0)
2670				return (-1);
2671			(void) strlcpy(propbuf, strval, proplen);
2672			break;
2673
2674		default:
2675			abort();
2676		}
2677	}
2678
2679	get_source(zhp, src, source, statbuf, statlen);
2680
2681	return (0);
2682}
2683
2684/*
2685 * Utility function to get the given numeric property.  Does no validation that
2686 * the given property is the appropriate type; should only be used with
2687 * hard-coded property types.
2688 */
2689uint64_t
2690zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
2691{
2692	char *source;
2693	uint64_t val;
2694
2695	(void) get_numeric_property(zhp, prop, NULL, &source, &val);
2696
2697	return (val);
2698}
2699
2700int
2701zfs_prop_set_int(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t val)
2702{
2703	char buf[64];
2704
2705	(void) snprintf(buf, sizeof (buf), "%llu", (longlong_t)val);
2706	return (zfs_prop_set(zhp, zfs_prop_to_name(prop), buf));
2707}
2708
2709/*
2710 * Similar to zfs_prop_get(), but returns the value as an integer.
2711 */
2712int
2713zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
2714    zprop_source_t *src, char *statbuf, size_t statlen)
2715{
2716	char *source;
2717
2718	/*
2719	 * Check to see if this property applies to our object
2720	 */
2721	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type)) {
2722		return (zfs_error_fmt(zhp->zfs_hdl, EZFS_PROPTYPE,
2723		    dgettext(TEXT_DOMAIN, "cannot get property '%s'"),
2724		    zfs_prop_to_name(prop)));
2725	}
2726
2727	if (src)
2728		*src = ZPROP_SRC_NONE;
2729
2730	if (get_numeric_property(zhp, prop, src, &source, value) != 0)
2731		return (-1);
2732
2733	get_source(zhp, src, source, statbuf, statlen);
2734
2735	return (0);
2736}
2737
2738static int
2739idmap_id_to_numeric_domain_rid(uid_t id, boolean_t isuser,
2740    char **domainp, idmap_rid_t *ridp)
2741{
2742#ifdef illumos
2743	idmap_get_handle_t *get_hdl = NULL;
2744	idmap_stat status;
2745	int err = EINVAL;
2746
2747	if (idmap_get_create(&get_hdl) != IDMAP_SUCCESS)
2748		goto out;
2749
2750	if (isuser) {
2751		err = idmap_get_sidbyuid(get_hdl, id,
2752		    IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
2753	} else {
2754		err = idmap_get_sidbygid(get_hdl, id,
2755		    IDMAP_REQ_FLG_USE_CACHE, domainp, ridp, &status);
2756	}
2757	if (err == IDMAP_SUCCESS &&
2758	    idmap_get_mappings(get_hdl) == IDMAP_SUCCESS &&
2759	    status == IDMAP_SUCCESS)
2760		err = 0;
2761	else
2762		err = EINVAL;
2763out:
2764	if (get_hdl)
2765		idmap_get_destroy(get_hdl);
2766	return (err);
2767#else	/* !illumos */
2768	assert(!"invalid code path");
2769	return (EINVAL); // silence compiler warning
2770#endif	/* illumos */
2771}
2772
2773/*
2774 * convert the propname into parameters needed by kernel
2775 * Eg: userquota@ahrens -> ZFS_PROP_USERQUOTA, "", 126829
2776 * Eg: userused@matt@domain -> ZFS_PROP_USERUSED, "S-1-123-456", 789
2777 */
2778static int
2779userquota_propname_decode(const char *propname, boolean_t zoned,
2780    zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp)
2781{
2782	zfs_userquota_prop_t type;
2783	char *cp, *end;
2784	char *numericsid = NULL;
2785	boolean_t isuser;
2786
2787	domain[0] = '\0';
2788	*ridp = 0;
2789	/* Figure out the property type ({user|group}{quota|space}) */
2790	for (type = 0; type < ZFS_NUM_USERQUOTA_PROPS; type++) {
2791		if (strncmp(propname, zfs_userquota_prop_prefixes[type],
2792		    strlen(zfs_userquota_prop_prefixes[type])) == 0)
2793			break;
2794	}
2795	if (type == ZFS_NUM_USERQUOTA_PROPS)
2796		return (EINVAL);
2797	*typep = type;
2798
2799	isuser = (type == ZFS_PROP_USERQUOTA ||
2800	    type == ZFS_PROP_USERUSED);
2801
2802	cp = strchr(propname, '@') + 1;
2803
2804	if (strchr(cp, '@')) {
2805#ifdef illumos
2806		/*
2807		 * It's a SID name (eg "user@domain") that needs to be
2808		 * turned into S-1-domainID-RID.
2809		 */
2810		int flag = 0;
2811		idmap_stat stat, map_stat;
2812		uid_t pid;
2813		idmap_rid_t rid;
2814		idmap_get_handle_t *gh = NULL;
2815
2816		stat = idmap_get_create(&gh);
2817		if (stat != IDMAP_SUCCESS) {
2818			idmap_get_destroy(gh);
2819			return (ENOMEM);
2820		}
2821		if (zoned && getzoneid() == GLOBAL_ZONEID)
2822			return (ENOENT);
2823		if (isuser) {
2824			stat = idmap_getuidbywinname(cp, NULL, flag, &pid);
2825			if (stat < 0)
2826				return (ENOENT);
2827			stat = idmap_get_sidbyuid(gh, pid, flag, &numericsid,
2828			    &rid, &map_stat);
2829		} else {
2830			stat = idmap_getgidbywinname(cp, NULL, flag, &pid);
2831			if (stat < 0)
2832				return (ENOENT);
2833			stat = idmap_get_sidbygid(gh, pid, flag, &numericsid,
2834			    &rid, &map_stat);
2835		}
2836		if (stat < 0) {
2837			idmap_get_destroy(gh);
2838			return (ENOENT);
2839		}
2840		stat = idmap_get_mappings(gh);
2841		idmap_get_destroy(gh);
2842
2843		if (stat < 0) {
2844			return (ENOENT);
2845		}
2846		if (numericsid == NULL)
2847			return (ENOENT);
2848		cp = numericsid;
2849		*ridp = rid;
2850		/* will be further decoded below */
2851#else	/* !illumos */
2852		return (ENOENT);
2853#endif	/* illumos */
2854	}
2855
2856	if (strncmp(cp, "S-1-", 4) == 0) {
2857		/* It's a numeric SID (eg "S-1-234-567-89") */
2858		(void) strlcpy(domain, cp, domainlen);
2859		errno = 0;
2860		if (*ridp == 0) {
2861			cp = strrchr(domain, '-');
2862			*cp = '\0';
2863			cp++;
2864			*ridp = strtoull(cp, &end, 10);
2865		} else {
2866			end = "";
2867		}
2868		if (numericsid) {
2869			free(numericsid);
2870			numericsid = NULL;
2871		}
2872		if (errno != 0 || *end != '\0')
2873			return (EINVAL);
2874	} else if (!isdigit(*cp)) {
2875		/*
2876		 * It's a user/group name (eg "user") that needs to be
2877		 * turned into a uid/gid
2878		 */
2879		if (zoned && getzoneid() == GLOBAL_ZONEID)
2880			return (ENOENT);
2881		if (isuser) {
2882			struct passwd *pw;
2883			pw = getpwnam(cp);
2884			if (pw == NULL)
2885				return (ENOENT);
2886			*ridp = pw->pw_uid;
2887		} else {
2888			struct group *gr;
2889			gr = getgrnam(cp);
2890			if (gr == NULL)
2891				return (ENOENT);
2892			*ridp = gr->gr_gid;
2893		}
2894	} else {
2895		/* It's a user/group ID (eg "12345"). */
2896		uid_t id = strtoul(cp, &end, 10);
2897		idmap_rid_t rid;
2898		char *mapdomain;
2899
2900		if (*end != '\0')
2901			return (EINVAL);
2902		if (id > MAXUID) {
2903			/* It's an ephemeral ID. */
2904			if (idmap_id_to_numeric_domain_rid(id, isuser,
2905			    &mapdomain, &rid) != 0)
2906				return (ENOENT);
2907			(void) strlcpy(domain, mapdomain, domainlen);
2908			*ridp = rid;
2909		} else {
2910			*ridp = id;
2911		}
2912	}
2913
2914	ASSERT3P(numericsid, ==, NULL);
2915	return (0);
2916}
2917
2918static int
2919zfs_prop_get_userquota_common(zfs_handle_t *zhp, const char *propname,
2920    uint64_t *propvalue, zfs_userquota_prop_t *typep)
2921{
2922	int err;
2923	zfs_cmd_t zc = { 0 };
2924
2925	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2926
2927	err = userquota_propname_decode(propname,
2928	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED),
2929	    typep, zc.zc_value, sizeof (zc.zc_value), &zc.zc_guid);
2930	zc.zc_objset_type = *typep;
2931	if (err)
2932		return (err);
2933
2934	err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_USERSPACE_ONE, &zc);
2935	if (err)
2936		return (err);
2937
2938	*propvalue = zc.zc_cookie;
2939	return (0);
2940}
2941
2942int
2943zfs_prop_get_userquota_int(zfs_handle_t *zhp, const char *propname,
2944    uint64_t *propvalue)
2945{
2946	zfs_userquota_prop_t type;
2947
2948	return (zfs_prop_get_userquota_common(zhp, propname, propvalue,
2949	    &type));
2950}
2951
2952int
2953zfs_prop_get_userquota(zfs_handle_t *zhp, const char *propname,
2954    char *propbuf, int proplen, boolean_t literal)
2955{
2956	int err;
2957	uint64_t propvalue;
2958	zfs_userquota_prop_t type;
2959
2960	err = zfs_prop_get_userquota_common(zhp, propname, &propvalue,
2961	    &type);
2962
2963	if (err)
2964		return (err);
2965
2966	if (literal) {
2967		(void) snprintf(propbuf, proplen, "%llu", propvalue);
2968	} else if (propvalue == 0 &&
2969	    (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) {
2970		(void) strlcpy(propbuf, "none", proplen);
2971	} else {
2972		zfs_nicenum(propvalue, propbuf, proplen);
2973	}
2974	return (0);
2975}
2976
2977int
2978zfs_prop_get_written_int(zfs_handle_t *zhp, const char *propname,
2979    uint64_t *propvalue)
2980{
2981	int err;
2982	zfs_cmd_t zc = { 0 };
2983	const char *snapname;
2984
2985	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2986
2987	snapname = strchr(propname, '@') + 1;
2988	if (strchr(snapname, '@')) {
2989		(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
2990	} else {
2991		/* snapname is the short name, append it to zhp's fsname */
2992		char *cp;
2993
2994		(void) strlcpy(zc.zc_value, zhp->zfs_name,
2995		    sizeof (zc.zc_value));
2996		cp = strchr(zc.zc_value, '@');
2997		if (cp != NULL)
2998			*cp = '\0';
2999		(void) strlcat(zc.zc_value, "@", sizeof (zc.zc_value));
3000		(void) strlcat(zc.zc_value, snapname, sizeof (zc.zc_value));
3001	}
3002
3003	err = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SPACE_WRITTEN, &zc);
3004	if (err)
3005		return (err);
3006
3007	*propvalue = zc.zc_cookie;
3008	return (0);
3009}
3010
3011int
3012zfs_prop_get_written(zfs_handle_t *zhp, const char *propname,
3013    char *propbuf, int proplen, boolean_t literal)
3014{
3015	int err;
3016	uint64_t propvalue;
3017
3018	err = zfs_prop_get_written_int(zhp, propname, &propvalue);
3019
3020	if (err)
3021		return (err);
3022
3023	if (literal) {
3024		(void) snprintf(propbuf, proplen, "%llu", propvalue);
3025	} else {
3026		zfs_nicenum(propvalue, propbuf, proplen);
3027	}
3028	return (0);
3029}
3030
3031/*
3032 * Returns the name of the given zfs handle.
3033 */
3034const char *
3035zfs_get_name(const zfs_handle_t *zhp)
3036{
3037	return (zhp->zfs_name);
3038}
3039
3040/*
3041 * Returns the name of the parent pool for the given zfs handle.
3042 */
3043const char *
3044zfs_get_pool_name(const zfs_handle_t *zhp)
3045{
3046	return (zhp->zpool_hdl->zpool_name);
3047}
3048
3049/*
3050 * Returns the type of the given zfs handle.
3051 */
3052zfs_type_t
3053zfs_get_type(const zfs_handle_t *zhp)
3054{
3055	return (zhp->zfs_type);
3056}
3057
3058/*
3059 * Is one dataset name a child dataset of another?
3060 *
3061 * Needs to handle these cases:
3062 * Dataset 1	"a/foo"		"a/foo"		"a/foo"		"a/foo"
3063 * Dataset 2	"a/fo"		"a/foobar"	"a/bar/baz"	"a/foo/bar"
3064 * Descendant?	No.		No.		No.		Yes.
3065 */
3066static boolean_t
3067is_descendant(const char *ds1, const char *ds2)
3068{
3069	size_t d1len = strlen(ds1);
3070
3071	/* ds2 can't be a descendant if it's smaller */
3072	if (strlen(ds2) < d1len)
3073		return (B_FALSE);
3074
3075	/* otherwise, compare strings and verify that there's a '/' char */
3076	return (ds2[d1len] == '/' && (strncmp(ds1, ds2, d1len) == 0));
3077}
3078
3079/*
3080 * Given a complete name, return just the portion that refers to the parent.
3081 * Will return -1 if there is no parent (path is just the name of the
3082 * pool).
3083 */
3084static int
3085parent_name(const char *path, char *buf, size_t buflen)
3086{
3087	char *slashp;
3088
3089	(void) strlcpy(buf, path, buflen);
3090
3091	if ((slashp = strrchr(buf, '/')) == NULL)
3092		return (-1);
3093	*slashp = '\0';
3094
3095	return (0);
3096}
3097
3098/*
3099 * If accept_ancestor is false, then check to make sure that the given path has
3100 * a parent, and that it exists.  If accept_ancestor is true, then find the
3101 * closest existing ancestor for the given path.  In prefixlen return the
3102 * length of already existing prefix of the given path.  We also fetch the
3103 * 'zoned' property, which is used to validate property settings when creating
3104 * new datasets.
3105 */
3106static int
3107check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned,
3108    boolean_t accept_ancestor, int *prefixlen)
3109{
3110	zfs_cmd_t zc = { 0 };
3111	char parent[ZFS_MAX_DATASET_NAME_LEN];
3112	char *slash;
3113	zfs_handle_t *zhp;
3114	char errbuf[1024];
3115	uint64_t is_zoned;
3116
3117	(void) snprintf(errbuf, sizeof (errbuf),
3118	    dgettext(TEXT_DOMAIN, "cannot create '%s'"), path);
3119
3120	/* get parent, and check to see if this is just a pool */
3121	if (parent_name(path, parent, sizeof (parent)) != 0) {
3122		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3123		    "missing dataset name"));
3124		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3125	}
3126
3127	/* check to see if the pool exists */
3128	if ((slash = strchr(parent, '/')) == NULL)
3129		slash = parent + strlen(parent);
3130	(void) strncpy(zc.zc_name, parent, slash - parent);
3131	zc.zc_name[slash - parent] = '\0';
3132	if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 &&
3133	    errno == ENOENT) {
3134		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3135		    "no such pool '%s'"), zc.zc_name);
3136		return (zfs_error(hdl, EZFS_NOENT, errbuf));
3137	}
3138
3139	/* check to see if the parent dataset exists */
3140	while ((zhp = make_dataset_handle(hdl, parent)) == NULL) {
3141		if (errno == ENOENT && accept_ancestor) {
3142			/*
3143			 * Go deeper to find an ancestor, give up on top level.
3144			 */
3145			if (parent_name(parent, parent, sizeof (parent)) != 0) {
3146				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3147				    "no such pool '%s'"), zc.zc_name);
3148				return (zfs_error(hdl, EZFS_NOENT, errbuf));
3149			}
3150		} else if (errno == ENOENT) {
3151			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3152			    "parent does not exist"));
3153			return (zfs_error(hdl, EZFS_NOENT, errbuf));
3154		} else
3155			return (zfs_standard_error(hdl, errno, errbuf));
3156	}
3157
3158	is_zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
3159	if (zoned != NULL)
3160		*zoned = is_zoned;
3161
3162	/* we are in a non-global zone, but parent is in the global zone */
3163	if (getzoneid() != GLOBAL_ZONEID && !is_zoned) {
3164		(void) zfs_standard_error(hdl, EPERM, errbuf);
3165		zfs_close(zhp);
3166		return (-1);
3167	}
3168
3169	/* make sure parent is a filesystem */
3170	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
3171		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3172		    "parent is not a filesystem"));
3173		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
3174		zfs_close(zhp);
3175		return (-1);
3176	}
3177
3178	zfs_close(zhp);
3179	if (prefixlen != NULL)
3180		*prefixlen = strlen(parent);
3181	return (0);
3182}
3183
3184/*
3185 * Finds whether the dataset of the given type(s) exists.
3186 */
3187boolean_t
3188zfs_dataset_exists(libzfs_handle_t *hdl, const char *path, zfs_type_t types)
3189{
3190	zfs_handle_t *zhp;
3191
3192	if (!zfs_validate_name(hdl, path, types, B_FALSE))
3193		return (B_FALSE);
3194
3195	/*
3196	 * Try to get stats for the dataset, which will tell us if it exists.
3197	 */
3198	if ((zhp = make_dataset_handle(hdl, path)) != NULL) {
3199		int ds_type = zhp->zfs_type;
3200
3201		zfs_close(zhp);
3202		if (types & ds_type)
3203			return (B_TRUE);
3204	}
3205	return (B_FALSE);
3206}
3207
3208/*
3209 * Given a path to 'target', create all the ancestors between
3210 * the prefixlen portion of the path, and the target itself.
3211 * Fail if the initial prefixlen-ancestor does not already exist.
3212 */
3213int
3214create_parents(libzfs_handle_t *hdl, char *target, int prefixlen)
3215{
3216	zfs_handle_t *h;
3217	char *cp;
3218	const char *opname;
3219
3220	/* make sure prefix exists */
3221	cp = target + prefixlen;
3222	if (*cp != '/') {
3223		assert(strchr(cp, '/') == NULL);
3224		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
3225	} else {
3226		*cp = '\0';
3227		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
3228		*cp = '/';
3229	}
3230	if (h == NULL)
3231		return (-1);
3232	zfs_close(h);
3233
3234	/*
3235	 * Attempt to create, mount, and share any ancestor filesystems,
3236	 * up to the prefixlen-long one.
3237	 */
3238	for (cp = target + prefixlen + 1;
3239	    (cp = strchr(cp, '/')) != NULL; *cp = '/', cp++) {
3240
3241		*cp = '\0';
3242
3243		h = make_dataset_handle(hdl, target);
3244		if (h) {
3245			/* it already exists, nothing to do here */
3246			zfs_close(h);
3247			continue;
3248		}
3249
3250		if (zfs_create(hdl, target, ZFS_TYPE_FILESYSTEM,
3251		    NULL) != 0) {
3252			opname = dgettext(TEXT_DOMAIN, "create");
3253			goto ancestorerr;
3254		}
3255
3256		h = zfs_open(hdl, target, ZFS_TYPE_FILESYSTEM);
3257		if (h == NULL) {
3258			opname = dgettext(TEXT_DOMAIN, "open");
3259			goto ancestorerr;
3260		}
3261
3262		if (zfs_mount(h, NULL, 0) != 0) {
3263			opname = dgettext(TEXT_DOMAIN, "mount");
3264			goto ancestorerr;
3265		}
3266
3267		if (zfs_share(h) != 0) {
3268			opname = dgettext(TEXT_DOMAIN, "share");
3269			goto ancestorerr;
3270		}
3271
3272		zfs_close(h);
3273	}
3274
3275	return (0);
3276
3277ancestorerr:
3278	zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3279	    "failed to %s ancestor '%s'"), opname, target);
3280	return (-1);
3281}
3282
3283/*
3284 * Creates non-existing ancestors of the given path.
3285 */
3286int
3287zfs_create_ancestors(libzfs_handle_t *hdl, const char *path)
3288{
3289	int prefix;
3290	char *path_copy;
3291	int rc = 0;
3292
3293	if (check_parents(hdl, path, NULL, B_TRUE, &prefix) != 0)
3294		return (-1);
3295
3296	if ((path_copy = strdup(path)) != NULL) {
3297		rc = create_parents(hdl, path_copy, prefix);
3298		free(path_copy);
3299	}
3300	if (path_copy == NULL || rc != 0)
3301		return (-1);
3302
3303	return (0);
3304}
3305
3306/*
3307 * Create a new filesystem or volume.
3308 */
3309int
3310zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
3311    nvlist_t *props)
3312{
3313	int ret;
3314	uint64_t size = 0;
3315	uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
3316	char errbuf[1024];
3317	uint64_t zoned;
3318	enum lzc_dataset_type ost;
3319	zpool_handle_t *zpool_handle;
3320
3321	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3322	    "cannot create '%s'"), path);
3323
3324	/* validate the path, taking care to note the extended error message */
3325	if (!zfs_validate_name(hdl, path, type, B_TRUE))
3326		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3327
3328	/* validate parents exist */
3329	if (check_parents(hdl, path, &zoned, B_FALSE, NULL) != 0)
3330		return (-1);
3331
3332	/*
3333	 * The failure modes when creating a dataset of a different type over
3334	 * one that already exists is a little strange.  In particular, if you
3335	 * try to create a dataset on top of an existing dataset, the ioctl()
3336	 * will return ENOENT, not EEXIST.  To prevent this from happening, we
3337	 * first try to see if the dataset exists.
3338	 */
3339	if (zfs_dataset_exists(hdl, path, ZFS_TYPE_DATASET)) {
3340		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3341		    "dataset already exists"));
3342		return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3343	}
3344
3345	if (type == ZFS_TYPE_VOLUME)
3346		ost = LZC_DATSET_TYPE_ZVOL;
3347	else
3348		ost = LZC_DATSET_TYPE_ZFS;
3349
3350	/* open zpool handle for prop validation */
3351	char pool_path[ZFS_MAX_DATASET_NAME_LEN];
3352	(void) strlcpy(pool_path, path, sizeof (pool_path));
3353
3354	/* truncate pool_path at first slash */
3355	char *p = strchr(pool_path, '/');
3356	if (p != NULL)
3357		*p = '\0';
3358
3359	if ((zpool_handle = zpool_open(hdl, pool_path)) == NULL)
3360		return (-1);
3361
3362	if (props && (props = zfs_valid_proplist(hdl, type, props,
3363	    zoned, NULL, zpool_handle, errbuf)) == 0) {
3364		zpool_close(zpool_handle);
3365		return (-1);
3366	}
3367	zpool_close(zpool_handle);
3368
3369	if (type == ZFS_TYPE_VOLUME) {
3370		/*
3371		 * If we are creating a volume, the size and block size must
3372		 * satisfy a few restraints.  First, the blocksize must be a
3373		 * valid block size between SPA_{MIN,MAX}BLOCKSIZE.  Second, the
3374		 * volsize must be a multiple of the block size, and cannot be
3375		 * zero.
3376		 */
3377		if (props == NULL || nvlist_lookup_uint64(props,
3378		    zfs_prop_to_name(ZFS_PROP_VOLSIZE), &size) != 0) {
3379			nvlist_free(props);
3380			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3381			    "missing volume size"));
3382			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3383		}
3384
3385		if ((ret = nvlist_lookup_uint64(props,
3386		    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
3387		    &blocksize)) != 0) {
3388			if (ret == ENOENT) {
3389				blocksize = zfs_prop_default_numeric(
3390				    ZFS_PROP_VOLBLOCKSIZE);
3391			} else {
3392				nvlist_free(props);
3393				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3394				    "missing volume block size"));
3395				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3396			}
3397		}
3398
3399		if (size == 0) {
3400			nvlist_free(props);
3401			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3402			    "volume size cannot be zero"));
3403			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3404		}
3405
3406		if (size % blocksize != 0) {
3407			nvlist_free(props);
3408			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3409			    "volume size must be a multiple of volume block "
3410			    "size"));
3411			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
3412		}
3413	}
3414
3415	/* create the dataset */
3416	ret = lzc_create(path, ost, props);
3417	nvlist_free(props);
3418
3419	/* check for failure */
3420	if (ret != 0) {
3421		char parent[ZFS_MAX_DATASET_NAME_LEN];
3422		(void) parent_name(path, parent, sizeof (parent));
3423
3424		switch (errno) {
3425		case ENOENT:
3426			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3427			    "no such parent '%s'"), parent);
3428			return (zfs_error(hdl, EZFS_NOENT, errbuf));
3429
3430		case EINVAL:
3431			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3432			    "parent '%s' is not a filesystem"), parent);
3433			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3434
3435		case ENOTSUP:
3436			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3437			    "pool must be upgraded to set this "
3438			    "property or value"));
3439			return (zfs_error(hdl, EZFS_BADVERSION, errbuf));
3440#ifdef _ILP32
3441		case EOVERFLOW:
3442			/*
3443			 * This platform can't address a volume this big.
3444			 */
3445			if (type == ZFS_TYPE_VOLUME)
3446				return (zfs_error(hdl, EZFS_VOLTOOBIG,
3447				    errbuf));
3448#endif
3449			/* FALLTHROUGH */
3450		default:
3451			return (zfs_standard_error(hdl, errno, errbuf));
3452		}
3453	}
3454
3455	return (0);
3456}
3457
3458/*
3459 * Destroys the given dataset.  The caller must make sure that the filesystem
3460 * isn't mounted, and that there are no active dependents. If the file system
3461 * does not exist this function does nothing.
3462 */
3463int
3464zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
3465{
3466	zfs_cmd_t zc = { 0 };
3467
3468	if (zhp->zfs_type == ZFS_TYPE_BOOKMARK) {
3469		nvlist_t *nv = fnvlist_alloc();
3470		fnvlist_add_boolean(nv, zhp->zfs_name);
3471		int error = lzc_destroy_bookmarks(nv, NULL);
3472		fnvlist_free(nv);
3473		if (error != 0) {
3474			return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3475			    dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
3476			    zhp->zfs_name));
3477		}
3478		return (0);
3479	}
3480
3481	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
3482
3483	if (ZFS_IS_VOLUME(zhp)) {
3484		zc.zc_objset_type = DMU_OST_ZVOL;
3485	} else {
3486		zc.zc_objset_type = DMU_OST_ZFS;
3487	}
3488
3489	zc.zc_defer_destroy = defer;
3490	if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0 &&
3491	    errno != ENOENT) {
3492		return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3493		    dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
3494		    zhp->zfs_name));
3495	}
3496
3497	remove_mountpoint(zhp);
3498
3499	return (0);
3500}
3501
3502struct destroydata {
3503	nvlist_t *nvl;
3504	const char *snapname;
3505};
3506
3507static int
3508zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
3509{
3510	struct destroydata *dd = arg;
3511	char name[ZFS_MAX_DATASET_NAME_LEN];
3512	int rv = 0;
3513
3514	(void) snprintf(name, sizeof (name),
3515	    "%s@%s", zhp->zfs_name, dd->snapname);
3516
3517	if (lzc_exists(name))
3518		verify(nvlist_add_boolean(dd->nvl, name) == 0);
3519
3520	rv = zfs_iter_filesystems(zhp, zfs_check_snap_cb, dd);
3521	zfs_close(zhp);
3522	return (rv);
3523}
3524
3525/*
3526 * Destroys all snapshots with the given name in zhp & descendants.
3527 */
3528int
3529zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname, boolean_t defer)
3530{
3531	int ret;
3532	struct destroydata dd = { 0 };
3533
3534	dd.snapname = snapname;
3535	verify(nvlist_alloc(&dd.nvl, NV_UNIQUE_NAME, 0) == 0);
3536	(void) zfs_check_snap_cb(zfs_handle_dup(zhp), &dd);
3537
3538	if (nvlist_empty(dd.nvl)) {
3539		ret = zfs_standard_error_fmt(zhp->zfs_hdl, ENOENT,
3540		    dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
3541		    zhp->zfs_name, snapname);
3542	} else {
3543		ret = zfs_destroy_snaps_nvl(zhp->zfs_hdl, dd.nvl, defer);
3544	}
3545	nvlist_free(dd.nvl);
3546	return (ret);
3547}
3548
3549/*
3550 * Destroys all the snapshots named in the nvlist.
3551 */
3552int
3553zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer)
3554{
3555	int ret;
3556	nvlist_t *errlist = NULL;
3557
3558	ret = lzc_destroy_snaps(snaps, defer, &errlist);
3559
3560	if (ret == 0) {
3561		nvlist_free(errlist);
3562		return (0);
3563	}
3564
3565	if (nvlist_empty(errlist)) {
3566		char errbuf[1024];
3567		(void) snprintf(errbuf, sizeof (errbuf),
3568		    dgettext(TEXT_DOMAIN, "cannot destroy snapshots"));
3569
3570		ret = zfs_standard_error(hdl, ret, errbuf);
3571	}
3572	for (nvpair_t *pair = nvlist_next_nvpair(errlist, NULL);
3573	    pair != NULL; pair = nvlist_next_nvpair(errlist, pair)) {
3574		char errbuf[1024];
3575		(void) snprintf(errbuf, sizeof (errbuf),
3576		    dgettext(TEXT_DOMAIN, "cannot destroy snapshot %s"),
3577		    nvpair_name(pair));
3578
3579		switch (fnvpair_value_int32(pair)) {
3580		case EEXIST:
3581			zfs_error_aux(hdl,
3582			    dgettext(TEXT_DOMAIN, "snapshot is cloned"));
3583			ret = zfs_error(hdl, EZFS_EXISTS, errbuf);
3584			break;
3585		default:
3586			ret = zfs_standard_error(hdl, errno, errbuf);
3587			break;
3588		}
3589	}
3590
3591	nvlist_free(errlist);
3592	return (ret);
3593}
3594
3595/*
3596 * Clones the given dataset.  The target must be of the same type as the source.
3597 */
3598int
3599zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
3600{
3601	char parent[ZFS_MAX_DATASET_NAME_LEN];
3602	int ret;
3603	char errbuf[1024];
3604	libzfs_handle_t *hdl = zhp->zfs_hdl;
3605	uint64_t zoned;
3606
3607	assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
3608
3609	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3610	    "cannot create '%s'"), target);
3611
3612	/* validate the target/clone name */
3613	if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
3614		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3615
3616	/* validate parents exist */
3617	if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
3618		return (-1);
3619
3620	(void) parent_name(target, parent, sizeof (parent));
3621
3622	/* do the clone */
3623
3624	if (props) {
3625		zfs_type_t type;
3626		if (ZFS_IS_VOLUME(zhp)) {
3627			type = ZFS_TYPE_VOLUME;
3628		} else {
3629			type = ZFS_TYPE_FILESYSTEM;
3630		}
3631		if ((props = zfs_valid_proplist(hdl, type, props, zoned,
3632		    zhp, zhp->zpool_hdl, errbuf)) == NULL)
3633			return (-1);
3634	}
3635
3636	ret = lzc_clone(target, zhp->zfs_name, props);
3637	nvlist_free(props);
3638
3639	if (ret != 0) {
3640		switch (errno) {
3641
3642		case ENOENT:
3643			/*
3644			 * The parent doesn't exist.  We should have caught this
3645			 * above, but there may a race condition that has since
3646			 * destroyed the parent.
3647			 *
3648			 * At this point, we don't know whether it's the source
3649			 * that doesn't exist anymore, or whether the target
3650			 * dataset doesn't exist.
3651			 */
3652			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3653			    "no such parent '%s'"), parent);
3654			return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
3655
3656		case EXDEV:
3657			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3658			    "source and target pools differ"));
3659			return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET,
3660			    errbuf));
3661
3662		default:
3663			return (zfs_standard_error(zhp->zfs_hdl, errno,
3664			    errbuf));
3665		}
3666	}
3667
3668	return (ret);
3669}
3670
3671/*
3672 * Promotes the given clone fs to be the clone parent.
3673 */
3674int
3675zfs_promote(zfs_handle_t *zhp)
3676{
3677	libzfs_handle_t *hdl = zhp->zfs_hdl;
3678	char snapname[ZFS_MAX_DATASET_NAME_LEN];
3679	int ret;
3680	char errbuf[1024];
3681
3682	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3683	    "cannot promote '%s'"), zhp->zfs_name);
3684
3685	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
3686		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3687		    "snapshots can not be promoted"));
3688		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3689	}
3690
3691	if (zhp->zfs_dmustats.dds_origin[0] == '\0') {
3692		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3693		    "not a cloned filesystem"));
3694		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
3695	}
3696
3697	ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname));
3698
3699	if (ret != 0) {
3700		switch (ret) {
3701		case EEXIST:
3702			/* There is a conflicting snapshot name. */
3703			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3704			    "conflicting snapshot '%s' from parent '%s'"),
3705			    snapname, zhp->zfs_dmustats.dds_origin);
3706			return (zfs_error(hdl, EZFS_EXISTS, errbuf));
3707
3708		default:
3709			return (zfs_standard_error(hdl, ret, errbuf));
3710		}
3711	}
3712	return (ret);
3713}
3714
3715typedef struct snapdata {
3716	nvlist_t *sd_nvl;
3717	const char *sd_snapname;
3718} snapdata_t;
3719
3720static int
3721zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
3722{
3723	snapdata_t *sd = arg;
3724	char name[ZFS_MAX_DATASET_NAME_LEN];
3725	int rv = 0;
3726
3727	if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) == 0) {
3728		(void) snprintf(name, sizeof (name),
3729		    "%s@%s", zfs_get_name(zhp), sd->sd_snapname);
3730
3731		fnvlist_add_boolean(sd->sd_nvl, name);
3732
3733		rv = zfs_iter_filesystems(zhp, zfs_snapshot_cb, sd);
3734	}
3735	zfs_close(zhp);
3736
3737	return (rv);
3738}
3739
3740/*
3741 * Creates snapshots.  The keys in the snaps nvlist are the snapshots to be
3742 * created.
3743 */
3744int
3745zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
3746{
3747	int ret;
3748	char errbuf[1024];
3749	nvpair_t *elem;
3750	nvlist_t *errors;
3751
3752	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3753	    "cannot create snapshots "));
3754
3755	elem = NULL;
3756	while ((elem = nvlist_next_nvpair(snaps, elem)) != NULL) {
3757		const char *snapname = nvpair_name(elem);
3758
3759		/* validate the target name */
3760		if (!zfs_validate_name(hdl, snapname, ZFS_TYPE_SNAPSHOT,
3761		    B_TRUE)) {
3762			(void) snprintf(errbuf, sizeof (errbuf),
3763			    dgettext(TEXT_DOMAIN,
3764			    "cannot create snapshot '%s'"), snapname);
3765			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3766		}
3767	}
3768
3769	/*
3770	 * get pool handle for prop validation. assumes all snaps are in the
3771	 * same pool, as does lzc_snapshot (below).
3772	 */
3773	char pool[ZFS_MAX_DATASET_NAME_LEN];
3774	elem = nvlist_next_nvpair(snaps, NULL);
3775	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
3776	pool[strcspn(pool, "/@")] = '\0';
3777	zpool_handle_t *zpool_hdl = zpool_open(hdl, pool);
3778
3779	if (props != NULL &&
3780	    (props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
3781	    props, B_FALSE, NULL, zpool_hdl, errbuf)) == NULL) {
3782		zpool_close(zpool_hdl);
3783		return (-1);
3784	}
3785	zpool_close(zpool_hdl);
3786
3787	ret = lzc_snapshot(snaps, props, &errors);
3788
3789	if (ret != 0) {
3790		boolean_t printed = B_FALSE;
3791		for (elem = nvlist_next_nvpair(errors, NULL);
3792		    elem != NULL;
3793		    elem = nvlist_next_nvpair(errors, elem)) {
3794			(void) snprintf(errbuf, sizeof (errbuf),
3795			    dgettext(TEXT_DOMAIN,
3796			    "cannot create snapshot '%s'"), nvpair_name(elem));
3797			(void) zfs_standard_error(hdl,
3798			    fnvpair_value_int32(elem), errbuf);
3799			printed = B_TRUE;
3800		}
3801		if (!printed) {
3802			switch (ret) {
3803			case EXDEV:
3804				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
3805				    "multiple snapshots of same "
3806				    "fs not allowed"));
3807				(void) zfs_error(hdl, EZFS_EXISTS, errbuf);
3808
3809				break;
3810			default:
3811				(void) zfs_standard_error(hdl, ret, errbuf);
3812			}
3813		}
3814	}
3815
3816	nvlist_free(props);
3817	nvlist_free(errors);
3818	return (ret);
3819}
3820
3821int
3822zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive,
3823    nvlist_t *props)
3824{
3825	int ret;
3826	snapdata_t sd = { 0 };
3827	char fsname[ZFS_MAX_DATASET_NAME_LEN];
3828	char *cp;
3829	zfs_handle_t *zhp;
3830	char errbuf[1024];
3831
3832	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3833	    "cannot snapshot %s"), path);
3834
3835	if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT, B_TRUE))
3836		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3837
3838	(void) strlcpy(fsname, path, sizeof (fsname));
3839	cp = strchr(fsname, '@');
3840	*cp = '\0';
3841	sd.sd_snapname = cp + 1;
3842
3843	if ((zhp = zfs_open(hdl, fsname, ZFS_TYPE_FILESYSTEM |
3844	    ZFS_TYPE_VOLUME)) == NULL) {
3845		return (-1);
3846	}
3847
3848	verify(nvlist_alloc(&sd.sd_nvl, NV_UNIQUE_NAME, 0) == 0);
3849	if (recursive) {
3850		(void) zfs_snapshot_cb(zfs_handle_dup(zhp), &sd);
3851	} else {
3852		fnvlist_add_boolean(sd.sd_nvl, path);
3853	}
3854
3855	ret = zfs_snapshot_nvl(hdl, sd.sd_nvl, props);
3856	nvlist_free(sd.sd_nvl);
3857	zfs_close(zhp);
3858	return (ret);
3859}
3860
3861/*
3862 * Destroy any more recent snapshots.  We invoke this callback on any dependents
3863 * of the snapshot first.  If the 'cb_dependent' member is non-zero, then this
3864 * is a dependent and we should just destroy it without checking the transaction
3865 * group.
3866 */
3867typedef struct rollback_data {
3868	const char	*cb_target;		/* the snapshot */
3869	uint64_t	cb_create;		/* creation time reference */
3870	boolean_t	cb_error;
3871	boolean_t	cb_force;
3872} rollback_data_t;
3873
3874static int
3875rollback_destroy_dependent(zfs_handle_t *zhp, void *data)
3876{
3877	rollback_data_t *cbp = data;
3878	prop_changelist_t *clp;
3879
3880	/* We must destroy this clone; first unmount it */
3881	clp = changelist_gather(zhp, ZFS_PROP_NAME, 0,
3882	    cbp->cb_force ? MS_FORCE: 0);
3883	if (clp == NULL || changelist_prefix(clp) != 0) {
3884		cbp->cb_error = B_TRUE;
3885		zfs_close(zhp);
3886		return (0);
3887	}
3888	if (zfs_destroy(zhp, B_FALSE) != 0)
3889		cbp->cb_error = B_TRUE;
3890	else
3891		changelist_remove(clp, zhp->zfs_name);
3892	(void) changelist_postfix(clp);
3893	changelist_free(clp);
3894
3895	zfs_close(zhp);
3896	return (0);
3897}
3898
3899static int
3900rollback_destroy(zfs_handle_t *zhp, void *data)
3901{
3902	rollback_data_t *cbp = data;
3903
3904	if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > cbp->cb_create) {
3905		cbp->cb_error |= zfs_iter_dependents(zhp, B_FALSE,
3906		    rollback_destroy_dependent, cbp);
3907
3908		cbp->cb_error |= zfs_destroy(zhp, B_FALSE);
3909	}
3910
3911	zfs_close(zhp);
3912	return (0);
3913}
3914
3915/*
3916 * Given a dataset, rollback to a specific snapshot, discarding any
3917 * data changes since then and making it the active dataset.
3918 *
3919 * Any snapshots and bookmarks more recent than the target are
3920 * destroyed, along with their dependents (i.e. clones).
3921 */
3922int
3923zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, boolean_t force)
3924{
3925	rollback_data_t cb = { 0 };
3926	int err;
3927	boolean_t restore_resv = 0;
3928	uint64_t old_volsize = 0, new_volsize;
3929	zfs_prop_t resv_prop;
3930
3931	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
3932	    zhp->zfs_type == ZFS_TYPE_VOLUME);
3933
3934	/*
3935	 * Destroy all recent snapshots and their dependents.
3936	 */
3937	cb.cb_force = force;
3938	cb.cb_target = snap->zfs_name;
3939	cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
3940	(void) zfs_iter_snapshots(zhp, B_FALSE, rollback_destroy, &cb);
3941	(void) zfs_iter_bookmarks(zhp, rollback_destroy, &cb);
3942
3943	if (cb.cb_error)
3944		return (-1);
3945
3946	/*
3947	 * Now that we have verified that the snapshot is the latest,
3948	 * rollback to the given snapshot.
3949	 */
3950
3951	if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
3952		if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
3953			return (-1);
3954		old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3955		restore_resv =
3956		    (old_volsize == zfs_prop_get_int(zhp, resv_prop));
3957	}
3958
3959	/*
3960	 * Pass both the filesystem and the wanted snapshot names,
3961	 * we would get an error back if the snapshot is destroyed or
3962	 * a new snapshot is created before this request is processed.
3963	 */
3964	err = lzc_rollback_to(zhp->zfs_name, snap->zfs_name);
3965	if (err == EXDEV) {
3966		zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3967		    "'%s' is not the latest snapshot"), snap->zfs_name);
3968		(void) zfs_error_fmt(zhp->zfs_hdl, EZFS_BUSY,
3969		    dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
3970		    zhp->zfs_name);
3971		return (err);
3972	} else if (err != 0) {
3973		(void) zfs_standard_error_fmt(zhp->zfs_hdl, errno,
3974		    dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
3975		    zhp->zfs_name);
3976		return (err);
3977	}
3978
3979	/*
3980	 * For volumes, if the pre-rollback volsize matched the pre-
3981	 * rollback reservation and the volsize has changed then set
3982	 * the reservation property to the post-rollback volsize.
3983	 * Make a new handle since the rollback closed the dataset.
3984	 */
3985	if ((zhp->zfs_type == ZFS_TYPE_VOLUME) &&
3986	    (zhp = make_dataset_handle(zhp->zfs_hdl, zhp->zfs_name))) {
3987		if (restore_resv) {
3988			new_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
3989			if (old_volsize != new_volsize)
3990				err = zfs_prop_set_int(zhp, resv_prop,
3991				    new_volsize);
3992		}
3993		zfs_close(zhp);
3994	}
3995	return (err);
3996}
3997
3998/*
3999 * Renames the given dataset.
4000 */
4001int
4002zfs_rename(zfs_handle_t *zhp, const char *source, const char *target,
4003    renameflags_t flags)
4004{
4005	int ret = 0;
4006	zfs_cmd_t zc = { 0 };
4007	char *delim;
4008	prop_changelist_t *cl = NULL;
4009	zfs_handle_t *zhrp = NULL;
4010	char *parentname = NULL;
4011	char parent[ZFS_MAX_DATASET_NAME_LEN];
4012	char property[ZFS_MAXPROPLEN];
4013	libzfs_handle_t *hdl = zhp->zfs_hdl;
4014	char errbuf[1024];
4015
4016	/* if we have the same exact name, just return success */
4017	if (strcmp(zhp->zfs_name, target) == 0)
4018		return (0);
4019
4020	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4021	    "cannot rename to '%s'"), target);
4022
4023	if (source != NULL) {
4024		/*
4025		 * This is recursive snapshots rename, put snapshot name
4026		 * (that might not exist) into zfs_name.
4027		 */
4028		assert(flags.recurse);
4029
4030		(void) strlcat(zhp->zfs_name, "@", sizeof(zhp->zfs_name));
4031		(void) strlcat(zhp->zfs_name, source, sizeof(zhp->zfs_name));
4032		zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
4033	}
4034
4035	/*
4036	 * Make sure the target name is valid
4037	 */
4038	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
4039		if ((strchr(target, '@') == NULL) ||
4040		    *target == '@') {
4041			/*
4042			 * Snapshot target name is abbreviated,
4043			 * reconstruct full dataset name
4044			 */
4045			(void) strlcpy(parent, zhp->zfs_name,
4046			    sizeof (parent));
4047			delim = strchr(parent, '@');
4048			if (strchr(target, '@') == NULL)
4049				*(++delim) = '\0';
4050			else
4051				*delim = '\0';
4052			(void) strlcat(parent, target, sizeof (parent));
4053			target = parent;
4054		} else {
4055			/*
4056			 * Make sure we're renaming within the same dataset.
4057			 */
4058			delim = strchr(target, '@');
4059			if (strncmp(zhp->zfs_name, target, delim - target)
4060			    != 0 || zhp->zfs_name[delim - target] != '@') {
4061				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4062				    "snapshots must be part of same "
4063				    "dataset"));
4064				return (zfs_error(hdl, EZFS_CROSSTARGET,
4065				    errbuf));
4066			}
4067		}
4068		if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
4069			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4070	} else {
4071		if (flags.recurse) {
4072			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4073			    "recursive rename must be a snapshot"));
4074			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4075		}
4076
4077		if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
4078			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4079
4080		/* validate parents */
4081		if (check_parents(hdl, target, NULL, B_FALSE, NULL) != 0)
4082			return (-1);
4083
4084		/* make sure we're in the same pool */
4085		verify((delim = strchr(target, '/')) != NULL);
4086		if (strncmp(zhp->zfs_name, target, delim - target) != 0 ||
4087		    zhp->zfs_name[delim - target] != '/') {
4088			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4089			    "datasets must be within same pool"));
4090			return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
4091		}
4092
4093		/* new name cannot be a child of the current dataset name */
4094		if (is_descendant(zhp->zfs_name, target)) {
4095			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4096			    "New dataset name cannot be a descendant of "
4097			    "current dataset name"));
4098			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
4099		}
4100	}
4101
4102	(void) snprintf(errbuf, sizeof (errbuf),
4103	    dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name);
4104
4105	if (getzoneid() == GLOBAL_ZONEID &&
4106	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
4107		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4108		    "dataset is used in a non-global zone"));
4109		return (zfs_error(hdl, EZFS_ZONED, errbuf));
4110	}
4111
4112	/*
4113	 * Avoid unmounting file systems with mountpoint property set to
4114	 * 'legacy' or 'none' even if -u option is not given.
4115	 */
4116	if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
4117	    !flags.recurse && !flags.nounmount &&
4118	    zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, property,
4119	    sizeof (property), NULL, NULL, 0, B_FALSE) == 0 &&
4120	    (strcmp(property, "legacy") == 0 ||
4121	     strcmp(property, "none") == 0)) {
4122		flags.nounmount = B_TRUE;
4123	}
4124	if (flags.recurse) {
4125
4126		parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
4127		if (parentname == NULL) {
4128			ret = -1;
4129			goto error;
4130		}
4131		delim = strchr(parentname, '@');
4132		*delim = '\0';
4133		zhrp = zfs_open(zhp->zfs_hdl, parentname, ZFS_TYPE_DATASET);
4134		if (zhrp == NULL) {
4135			ret = -1;
4136			goto error;
4137		}
4138	} else if (zhp->zfs_type != ZFS_TYPE_SNAPSHOT) {
4139		if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
4140		    flags.nounmount ? CL_GATHER_DONT_UNMOUNT : 0,
4141		    flags.forceunmount ? MS_FORCE : 0)) == NULL) {
4142			return (-1);
4143		}
4144
4145		if (changelist_haszonedchild(cl)) {
4146			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4147			    "child dataset with inherited mountpoint is used "
4148			    "in a non-global zone"));
4149			(void) zfs_error(hdl, EZFS_ZONED, errbuf);
4150			ret = -1;
4151			goto error;
4152		}
4153
4154		if ((ret = changelist_prefix(cl)) != 0)
4155			goto error;
4156	}
4157
4158	if (ZFS_IS_VOLUME(zhp))
4159		zc.zc_objset_type = DMU_OST_ZVOL;
4160	else
4161		zc.zc_objset_type = DMU_OST_ZFS;
4162
4163	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4164	(void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
4165
4166	zc.zc_cookie = flags.recurse ? 1 : 0;
4167	if (flags.nounmount)
4168		zc.zc_cookie |= 2;
4169
4170	if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
4171		/*
4172		 * if it was recursive, the one that actually failed will
4173		 * be in zc.zc_name
4174		 */
4175		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4176		    "cannot rename '%s'"), zc.zc_name);
4177
4178		if (flags.recurse && errno == EEXIST) {
4179			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4180			    "a child dataset already has a snapshot "
4181			    "with the new name"));
4182			(void) zfs_error(hdl, EZFS_EXISTS, errbuf);
4183		} else {
4184			(void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
4185		}
4186
4187		/*
4188		 * On failure, we still want to remount any filesystems that
4189		 * were previously mounted, so we don't alter the system state.
4190		 */
4191		if (cl != NULL)
4192			(void) changelist_postfix(cl);
4193	} else {
4194		if (cl != NULL) {
4195			changelist_rename(cl, zfs_get_name(zhp), target);
4196			ret = changelist_postfix(cl);
4197		}
4198	}
4199
4200error:
4201	if (parentname != NULL) {
4202		free(parentname);
4203	}
4204	if (zhrp != NULL) {
4205		zfs_close(zhrp);
4206	}
4207	if (cl != NULL) {
4208		changelist_free(cl);
4209	}
4210	return (ret);
4211}
4212
4213nvlist_t *
4214zfs_get_user_props(zfs_handle_t *zhp)
4215{
4216	return (zhp->zfs_user_props);
4217}
4218
4219nvlist_t *
4220zfs_get_recvd_props(zfs_handle_t *zhp)
4221{
4222	if (zhp->zfs_recvd_props == NULL)
4223		if (get_recvd_props_ioctl(zhp) != 0)
4224			return (NULL);
4225	return (zhp->zfs_recvd_props);
4226}
4227
4228/*
4229 * This function is used by 'zfs list' to determine the exact set of columns to
4230 * display, and their maximum widths.  This does two main things:
4231 *
4232 *      - If this is a list of all properties, then expand the list to include
4233 *        all native properties, and set a flag so that for each dataset we look
4234 *        for new unique user properties and add them to the list.
4235 *
4236 *      - For non fixed-width properties, keep track of the maximum width seen
4237 *        so that we can size the column appropriately. If the user has
4238 *        requested received property values, we also need to compute the width
4239 *        of the RECEIVED column.
4240 */
4241int
4242zfs_expand_proplist(zfs_handle_t *zhp, zprop_list_t **plp, boolean_t received,
4243    boolean_t literal)
4244{
4245	libzfs_handle_t *hdl = zhp->zfs_hdl;
4246	zprop_list_t *entry;
4247	zprop_list_t **last, **start;
4248	nvlist_t *userprops, *propval;
4249	nvpair_t *elem;
4250	char *strval;
4251	char buf[ZFS_MAXPROPLEN];
4252
4253	if (zprop_expand_list(hdl, plp, ZFS_TYPE_DATASET) != 0)
4254		return (-1);
4255
4256	userprops = zfs_get_user_props(zhp);
4257
4258	entry = *plp;
4259	if (entry->pl_all && nvlist_next_nvpair(userprops, NULL) != NULL) {
4260		/*
4261		 * Go through and add any user properties as necessary.  We
4262		 * start by incrementing our list pointer to the first
4263		 * non-native property.
4264		 */
4265		start = plp;
4266		while (*start != NULL) {
4267			if ((*start)->pl_prop == ZPROP_INVAL)
4268				break;
4269			start = &(*start)->pl_next;
4270		}
4271
4272		elem = NULL;
4273		while ((elem = nvlist_next_nvpair(userprops, elem)) != NULL) {
4274			/*
4275			 * See if we've already found this property in our list.
4276			 */
4277			for (last = start; *last != NULL;
4278			    last = &(*last)->pl_next) {
4279				if (strcmp((*last)->pl_user_prop,
4280				    nvpair_name(elem)) == 0)
4281					break;
4282			}
4283
4284			if (*last == NULL) {
4285				if ((entry = zfs_alloc(hdl,
4286				    sizeof (zprop_list_t))) == NULL ||
4287				    ((entry->pl_user_prop = zfs_strdup(hdl,
4288				    nvpair_name(elem)))) == NULL) {
4289					free(entry);
4290					return (-1);
4291				}
4292
4293				entry->pl_prop = ZPROP_INVAL;
4294				entry->pl_width = strlen(nvpair_name(elem));
4295				entry->pl_all = B_TRUE;
4296				*last = entry;
4297			}
4298		}
4299	}
4300
4301	/*
4302	 * Now go through and check the width of any non-fixed columns
4303	 */
4304	for (entry = *plp; entry != NULL; entry = entry->pl_next) {
4305		if (entry->pl_fixed && !literal)
4306			continue;
4307
4308		if (entry->pl_prop != ZPROP_INVAL) {
4309			if (zfs_prop_get(zhp, entry->pl_prop,
4310			    buf, sizeof (buf), NULL, NULL, 0, literal) == 0) {
4311				if (strlen(buf) > entry->pl_width)
4312					entry->pl_width = strlen(buf);
4313			}
4314			if (received && zfs_prop_get_recvd(zhp,
4315			    zfs_prop_to_name(entry->pl_prop),
4316			    buf, sizeof (buf), literal) == 0)
4317				if (strlen(buf) > entry->pl_recvd_width)
4318					entry->pl_recvd_width = strlen(buf);
4319		} else {
4320			if (nvlist_lookup_nvlist(userprops, entry->pl_user_prop,
4321			    &propval) == 0) {
4322				verify(nvlist_lookup_string(propval,
4323				    ZPROP_VALUE, &strval) == 0);
4324				if (strlen(strval) > entry->pl_width)
4325					entry->pl_width = strlen(strval);
4326			}
4327			if (received && zfs_prop_get_recvd(zhp,
4328			    entry->pl_user_prop,
4329			    buf, sizeof (buf), literal) == 0)
4330				if (strlen(buf) > entry->pl_recvd_width)
4331					entry->pl_recvd_width = strlen(buf);
4332		}
4333	}
4334
4335	return (0);
4336}
4337
4338int
4339zfs_deleg_share_nfs(libzfs_handle_t *hdl, char *dataset, char *path,
4340    char *resource, void *export, void *sharetab,
4341    int sharemax, zfs_share_op_t operation)
4342{
4343	zfs_cmd_t zc = { 0 };
4344	int error;
4345
4346	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
4347	(void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
4348	if (resource)
4349		(void) strlcpy(zc.zc_string, resource, sizeof (zc.zc_string));
4350	zc.zc_share.z_sharedata = (uint64_t)(uintptr_t)sharetab;
4351	zc.zc_share.z_exportdata = (uint64_t)(uintptr_t)export;
4352	zc.zc_share.z_sharetype = operation;
4353	zc.zc_share.z_sharemax = sharemax;
4354	error = ioctl(hdl->libzfs_fd, ZFS_IOC_SHARE, &zc);
4355	return (error);
4356}
4357
4358void
4359zfs_prune_proplist(zfs_handle_t *zhp, uint8_t *props)
4360{
4361	nvpair_t *curr;
4362
4363	/*
4364	 * Keep a reference to the props-table against which we prune the
4365	 * properties.
4366	 */
4367	zhp->zfs_props_table = props;
4368
4369	curr = nvlist_next_nvpair(zhp->zfs_props, NULL);
4370
4371	while (curr) {
4372		zfs_prop_t zfs_prop = zfs_name_to_prop(nvpair_name(curr));
4373		nvpair_t *next = nvlist_next_nvpair(zhp->zfs_props, curr);
4374
4375		/*
4376		 * User properties will result in ZPROP_INVAL, and since we
4377		 * only know how to prune standard ZFS properties, we always
4378		 * leave these in the list.  This can also happen if we
4379		 * encounter an unknown DSL property (when running older
4380		 * software, for example).
4381		 */
4382		if (zfs_prop != ZPROP_INVAL && props[zfs_prop] == B_FALSE)
4383			(void) nvlist_remove(zhp->zfs_props,
4384			    nvpair_name(curr), nvpair_type(curr));
4385		curr = next;
4386	}
4387}
4388
4389#ifdef illumos
4390static int
4391zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path,
4392    zfs_smb_acl_op_t cmd, char *resource1, char *resource2)
4393{
4394	zfs_cmd_t zc = { 0 };
4395	nvlist_t *nvlist = NULL;
4396	int error;
4397
4398	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
4399	(void) strlcpy(zc.zc_value, path, sizeof (zc.zc_value));
4400	zc.zc_cookie = (uint64_t)cmd;
4401
4402	if (cmd == ZFS_SMB_ACL_RENAME) {
4403		if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) {
4404			(void) no_memory(hdl);
4405			return (0);
4406		}
4407	}
4408
4409	switch (cmd) {
4410	case ZFS_SMB_ACL_ADD:
4411	case ZFS_SMB_ACL_REMOVE:
4412		(void) strlcpy(zc.zc_string, resource1, sizeof (zc.zc_string));
4413		break;
4414	case ZFS_SMB_ACL_RENAME:
4415		if (nvlist_add_string(nvlist, ZFS_SMB_ACL_SRC,
4416		    resource1) != 0) {
4417				(void) no_memory(hdl);
4418				return (-1);
4419		}
4420		if (nvlist_add_string(nvlist, ZFS_SMB_ACL_TARGET,
4421		    resource2) != 0) {
4422				(void) no_memory(hdl);
4423				return (-1);
4424		}
4425		if (zcmd_write_src_nvlist(hdl, &zc, nvlist) != 0) {
4426			nvlist_free(nvlist);
4427			return (-1);
4428		}
4429		break;
4430	case ZFS_SMB_ACL_PURGE:
4431		break;
4432	default:
4433		return (-1);
4434	}
4435	error = ioctl(hdl->libzfs_fd, ZFS_IOC_SMB_ACL, &zc);
4436	nvlist_free(nvlist);
4437	return (error);
4438}
4439
4440int
4441zfs_smb_acl_add(libzfs_handle_t *hdl, char *dataset,
4442    char *path, char *resource)
4443{
4444	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_ADD,
4445	    resource, NULL));
4446}
4447
4448int
4449zfs_smb_acl_remove(libzfs_handle_t *hdl, char *dataset,
4450    char *path, char *resource)
4451{
4452	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_REMOVE,
4453	    resource, NULL));
4454}
4455
4456int
4457zfs_smb_acl_purge(libzfs_handle_t *hdl, char *dataset, char *path)
4458{
4459	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_PURGE,
4460	    NULL, NULL));
4461}
4462
4463int
4464zfs_smb_acl_rename(libzfs_handle_t *hdl, char *dataset, char *path,
4465    char *oldname, char *newname)
4466{
4467	return (zfs_smb_acl_mgmt(hdl, dataset, path, ZFS_SMB_ACL_RENAME,
4468	    oldname, newname));
4469}
4470#endif	/* illumos */
4471
4472int
4473zfs_userspace(zfs_handle_t *zhp, zfs_userquota_prop_t type,
4474    zfs_userspace_cb_t func, void *arg)
4475{
4476	zfs_cmd_t zc = { 0 };
4477	zfs_useracct_t buf[100];
4478	libzfs_handle_t *hdl = zhp->zfs_hdl;
4479	int ret;
4480
4481	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4482
4483	zc.zc_objset_type = type;
4484	zc.zc_nvlist_dst = (uintptr_t)buf;
4485
4486	for (;;) {
4487		zfs_useracct_t *zua = buf;
4488
4489		zc.zc_nvlist_dst_size = sizeof (buf);
4490		if (zfs_ioctl(hdl, ZFS_IOC_USERSPACE_MANY, &zc) != 0) {
4491			char errbuf[1024];
4492
4493			(void) snprintf(errbuf, sizeof (errbuf),
4494			    dgettext(TEXT_DOMAIN,
4495			    "cannot get used/quota for %s"), zc.zc_name);
4496			return (zfs_standard_error_fmt(hdl, errno, errbuf));
4497		}
4498		if (zc.zc_nvlist_dst_size == 0)
4499			break;
4500
4501		while (zc.zc_nvlist_dst_size > 0) {
4502			if ((ret = func(arg, zua->zu_domain, zua->zu_rid,
4503			    zua->zu_space)) != 0)
4504				return (ret);
4505			zua++;
4506			zc.zc_nvlist_dst_size -= sizeof (zfs_useracct_t);
4507		}
4508	}
4509
4510	return (0);
4511}
4512
4513struct holdarg {
4514	nvlist_t *nvl;
4515	const char *snapname;
4516	const char *tag;
4517	boolean_t recursive;
4518	int error;
4519};
4520
4521static int
4522zfs_hold_one(zfs_handle_t *zhp, void *arg)
4523{
4524	struct holdarg *ha = arg;
4525	char name[ZFS_MAX_DATASET_NAME_LEN];
4526	int rv = 0;
4527
4528	(void) snprintf(name, sizeof (name),
4529	    "%s@%s", zhp->zfs_name, ha->snapname);
4530
4531	if (lzc_exists(name))
4532		fnvlist_add_string(ha->nvl, name, ha->tag);
4533
4534	if (ha->recursive)
4535		rv = zfs_iter_filesystems(zhp, zfs_hold_one, ha);
4536	zfs_close(zhp);
4537	return (rv);
4538}
4539
4540int
4541zfs_hold(zfs_handle_t *zhp, const char *snapname, const char *tag,
4542    boolean_t recursive, int cleanup_fd)
4543{
4544	int ret;
4545	struct holdarg ha;
4546
4547	ha.nvl = fnvlist_alloc();
4548	ha.snapname = snapname;
4549	ha.tag = tag;
4550	ha.recursive = recursive;
4551	(void) zfs_hold_one(zfs_handle_dup(zhp), &ha);
4552
4553	if (nvlist_empty(ha.nvl)) {
4554		char errbuf[1024];
4555
4556		fnvlist_free(ha.nvl);
4557		ret = ENOENT;
4558		(void) snprintf(errbuf, sizeof (errbuf),
4559		    dgettext(TEXT_DOMAIN,
4560		    "cannot hold snapshot '%s@%s'"),
4561		    zhp->zfs_name, snapname);
4562		(void) zfs_standard_error(zhp->zfs_hdl, ret, errbuf);
4563		return (ret);
4564	}
4565
4566	ret = zfs_hold_nvl(zhp, cleanup_fd, ha.nvl);
4567	fnvlist_free(ha.nvl);
4568
4569	return (ret);
4570}
4571
4572int
4573zfs_hold_nvl(zfs_handle_t *zhp, int cleanup_fd, nvlist_t *holds)
4574{
4575	int ret;
4576	nvlist_t *errors;
4577	libzfs_handle_t *hdl = zhp->zfs_hdl;
4578	char errbuf[1024];
4579	nvpair_t *elem;
4580
4581	errors = NULL;
4582	ret = lzc_hold(holds, cleanup_fd, &errors);
4583
4584	if (ret == 0) {
4585		/* There may be errors even in the success case. */
4586		fnvlist_free(errors);
4587		return (0);
4588	}
4589
4590	if (nvlist_empty(errors)) {
4591		/* no hold-specific errors */
4592		(void) snprintf(errbuf, sizeof (errbuf),
4593		    dgettext(TEXT_DOMAIN, "cannot hold"));
4594		switch (ret) {
4595		case ENOTSUP:
4596			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4597			    "pool must be upgraded"));
4598			(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
4599			break;
4600		case EINVAL:
4601			(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4602			break;
4603		default:
4604			(void) zfs_standard_error(hdl, ret, errbuf);
4605		}
4606	}
4607
4608	for (elem = nvlist_next_nvpair(errors, NULL);
4609	    elem != NULL;
4610	    elem = nvlist_next_nvpair(errors, elem)) {
4611		(void) snprintf(errbuf, sizeof (errbuf),
4612		    dgettext(TEXT_DOMAIN,
4613		    "cannot hold snapshot '%s'"), nvpair_name(elem));
4614		switch (fnvpair_value_int32(elem)) {
4615		case E2BIG:
4616			/*
4617			 * Temporary tags wind up having the ds object id
4618			 * prepended. So even if we passed the length check
4619			 * above, it's still possible for the tag to wind
4620			 * up being slightly too long.
4621			 */
4622			(void) zfs_error(hdl, EZFS_TAGTOOLONG, errbuf);
4623			break;
4624		case EINVAL:
4625			(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4626			break;
4627		case EEXIST:
4628			(void) zfs_error(hdl, EZFS_REFTAG_HOLD, errbuf);
4629			break;
4630		default:
4631			(void) zfs_standard_error(hdl,
4632			    fnvpair_value_int32(elem), errbuf);
4633		}
4634	}
4635
4636	fnvlist_free(errors);
4637	return (ret);
4638}
4639
4640static int
4641zfs_release_one(zfs_handle_t *zhp, void *arg)
4642{
4643	struct holdarg *ha = arg;
4644	char name[ZFS_MAX_DATASET_NAME_LEN];
4645	int rv = 0;
4646	nvlist_t *existing_holds;
4647
4648	(void) snprintf(name, sizeof (name),
4649	    "%s@%s", zhp->zfs_name, ha->snapname);
4650
4651	if (lzc_get_holds(name, &existing_holds) != 0) {
4652		ha->error = ENOENT;
4653	} else if (!nvlist_exists(existing_holds, ha->tag)) {
4654		ha->error = ESRCH;
4655	} else {
4656		nvlist_t *torelease = fnvlist_alloc();
4657		fnvlist_add_boolean(torelease, ha->tag);
4658		fnvlist_add_nvlist(ha->nvl, name, torelease);
4659		fnvlist_free(torelease);
4660	}
4661
4662	if (ha->recursive)
4663		rv = zfs_iter_filesystems(zhp, zfs_release_one, ha);
4664	zfs_close(zhp);
4665	return (rv);
4666}
4667
4668int
4669zfs_release(zfs_handle_t *zhp, const char *snapname, const char *tag,
4670    boolean_t recursive)
4671{
4672	int ret;
4673	struct holdarg ha;
4674	nvlist_t *errors = NULL;
4675	nvpair_t *elem;
4676	libzfs_handle_t *hdl = zhp->zfs_hdl;
4677	char errbuf[1024];
4678
4679	ha.nvl = fnvlist_alloc();
4680	ha.snapname = snapname;
4681	ha.tag = tag;
4682	ha.recursive = recursive;
4683	ha.error = 0;
4684	(void) zfs_release_one(zfs_handle_dup(zhp), &ha);
4685
4686	if (nvlist_empty(ha.nvl)) {
4687		fnvlist_free(ha.nvl);
4688		ret = ha.error;
4689		(void) snprintf(errbuf, sizeof (errbuf),
4690		    dgettext(TEXT_DOMAIN,
4691		    "cannot release hold from snapshot '%s@%s'"),
4692		    zhp->zfs_name, snapname);
4693		if (ret == ESRCH) {
4694			(void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
4695		} else {
4696			(void) zfs_standard_error(hdl, ret, errbuf);
4697		}
4698		return (ret);
4699	}
4700
4701	ret = lzc_release(ha.nvl, &errors);
4702	fnvlist_free(ha.nvl);
4703
4704	if (ret == 0) {
4705		/* There may be errors even in the success case. */
4706		fnvlist_free(errors);
4707		return (0);
4708	}
4709
4710	if (nvlist_empty(errors)) {
4711		/* no hold-specific errors */
4712		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
4713		    "cannot release"));
4714		switch (errno) {
4715		case ENOTSUP:
4716			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4717			    "pool must be upgraded"));
4718			(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
4719			break;
4720		default:
4721			(void) zfs_standard_error_fmt(hdl, errno, errbuf);
4722		}
4723	}
4724
4725	for (elem = nvlist_next_nvpair(errors, NULL);
4726	    elem != NULL;
4727	    elem = nvlist_next_nvpair(errors, elem)) {
4728		(void) snprintf(errbuf, sizeof (errbuf),
4729		    dgettext(TEXT_DOMAIN,
4730		    "cannot release hold from snapshot '%s'"),
4731		    nvpair_name(elem));
4732		switch (fnvpair_value_int32(elem)) {
4733		case ESRCH:
4734			(void) zfs_error(hdl, EZFS_REFTAG_RELE, errbuf);
4735			break;
4736		case EINVAL:
4737			(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
4738			break;
4739		default:
4740			(void) zfs_standard_error_fmt(hdl,
4741			    fnvpair_value_int32(elem), errbuf);
4742		}
4743	}
4744
4745	fnvlist_free(errors);
4746	return (ret);
4747}
4748
4749int
4750zfs_get_fsacl(zfs_handle_t *zhp, nvlist_t **nvl)
4751{
4752	zfs_cmd_t zc = { 0 };
4753	libzfs_handle_t *hdl = zhp->zfs_hdl;
4754	int nvsz = 2048;
4755	void *nvbuf;
4756	int err = 0;
4757	char errbuf[1024];
4758
4759	assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
4760	    zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4761
4762tryagain:
4763
4764	nvbuf = malloc(nvsz);
4765	if (nvbuf == NULL) {
4766		err = (zfs_error(hdl, EZFS_NOMEM, strerror(errno)));
4767		goto out;
4768	}
4769
4770	zc.zc_nvlist_dst_size = nvsz;
4771	zc.zc_nvlist_dst = (uintptr_t)nvbuf;
4772
4773	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4774
4775	if (ioctl(hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) {
4776		(void) snprintf(errbuf, sizeof (errbuf),
4777		    dgettext(TEXT_DOMAIN, "cannot get permissions on '%s'"),
4778		    zc.zc_name);
4779		switch (errno) {
4780		case ENOMEM:
4781			free(nvbuf);
4782			nvsz = zc.zc_nvlist_dst_size;
4783			goto tryagain;
4784
4785		case ENOTSUP:
4786			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4787			    "pool must be upgraded"));
4788			err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4789			break;
4790		case EINVAL:
4791			err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4792			break;
4793		case ENOENT:
4794			err = zfs_error(hdl, EZFS_NOENT, errbuf);
4795			break;
4796		default:
4797			err = zfs_standard_error_fmt(hdl, errno, errbuf);
4798			break;
4799		}
4800	} else {
4801		/* success */
4802		int rc = nvlist_unpack(nvbuf, zc.zc_nvlist_dst_size, nvl, 0);
4803		if (rc) {
4804			(void) snprintf(errbuf, sizeof (errbuf), dgettext(
4805			    TEXT_DOMAIN, "cannot get permissions on '%s'"),
4806			    zc.zc_name);
4807			err = zfs_standard_error_fmt(hdl, rc, errbuf);
4808		}
4809	}
4810
4811	free(nvbuf);
4812out:
4813	return (err);
4814}
4815
4816int
4817zfs_set_fsacl(zfs_handle_t *zhp, boolean_t un, nvlist_t *nvl)
4818{
4819	zfs_cmd_t zc = { 0 };
4820	libzfs_handle_t *hdl = zhp->zfs_hdl;
4821	char *nvbuf;
4822	char errbuf[1024];
4823	size_t nvsz;
4824	int err;
4825
4826	assert(zhp->zfs_type == ZFS_TYPE_VOLUME ||
4827	    zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4828
4829	err = nvlist_size(nvl, &nvsz, NV_ENCODE_NATIVE);
4830	assert(err == 0);
4831
4832	nvbuf = malloc(nvsz);
4833
4834	err = nvlist_pack(nvl, &nvbuf, &nvsz, NV_ENCODE_NATIVE, 0);
4835	assert(err == 0);
4836
4837	zc.zc_nvlist_src_size = nvsz;
4838	zc.zc_nvlist_src = (uintptr_t)nvbuf;
4839	zc.zc_perm_action = un;
4840
4841	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4842
4843	if (zfs_ioctl(hdl, ZFS_IOC_SET_FSACL, &zc) != 0) {
4844		(void) snprintf(errbuf, sizeof (errbuf),
4845		    dgettext(TEXT_DOMAIN, "cannot set permissions on '%s'"),
4846		    zc.zc_name);
4847		switch (errno) {
4848		case ENOTSUP:
4849			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4850			    "pool must be upgraded"));
4851			err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4852			break;
4853		case EINVAL:
4854			err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4855			break;
4856		case ENOENT:
4857			err = zfs_error(hdl, EZFS_NOENT, errbuf);
4858			break;
4859		default:
4860			err = zfs_standard_error_fmt(hdl, errno, errbuf);
4861			break;
4862		}
4863	}
4864
4865	free(nvbuf);
4866
4867	return (err);
4868}
4869
4870int
4871zfs_get_holds(zfs_handle_t *zhp, nvlist_t **nvl)
4872{
4873	int err;
4874	char errbuf[1024];
4875
4876	err = lzc_get_holds(zhp->zfs_name, nvl);
4877
4878	if (err != 0) {
4879		libzfs_handle_t *hdl = zhp->zfs_hdl;
4880
4881		(void) snprintf(errbuf, sizeof (errbuf),
4882		    dgettext(TEXT_DOMAIN, "cannot get holds for '%s'"),
4883		    zhp->zfs_name);
4884		switch (err) {
4885		case ENOTSUP:
4886			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4887			    "pool must be upgraded"));
4888			err = zfs_error(hdl, EZFS_BADVERSION, errbuf);
4889			break;
4890		case EINVAL:
4891			err = zfs_error(hdl, EZFS_BADTYPE, errbuf);
4892			break;
4893		case ENOENT:
4894			err = zfs_error(hdl, EZFS_NOENT, errbuf);
4895			break;
4896		default:
4897			err = zfs_standard_error_fmt(hdl, errno, errbuf);
4898			break;
4899		}
4900	}
4901
4902	return (err);
4903}
4904
4905/*
4906 * Convert the zvol's volume size to an appropriate reservation.
4907 * Note: If this routine is updated, it is necessary to update the ZFS test
4908 * suite's shell version in reservation.kshlib.
4909 */
4910uint64_t
4911zvol_volsize_to_reservation(uint64_t volsize, nvlist_t *props)
4912{
4913	uint64_t numdb;
4914	uint64_t nblocks, volblocksize;
4915	int ncopies;
4916	char *strval;
4917
4918	if (nvlist_lookup_string(props,
4919	    zfs_prop_to_name(ZFS_PROP_COPIES), &strval) == 0)
4920		ncopies = atoi(strval);
4921	else
4922		ncopies = 1;
4923	if (nvlist_lookup_uint64(props,
4924	    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
4925	    &volblocksize) != 0)
4926		volblocksize = ZVOL_DEFAULT_BLOCKSIZE;
4927	nblocks = volsize/volblocksize;
4928	/* start with metadnode L0-L6 */
4929	numdb = 7;
4930	/* calculate number of indirects */
4931	while (nblocks > 1) {
4932		nblocks += DNODES_PER_LEVEL - 1;
4933		nblocks /= DNODES_PER_LEVEL;
4934		numdb += nblocks;
4935	}
4936	numdb *= MIN(SPA_DVAS_PER_BP, ncopies + 1);
4937	volsize *= ncopies;
4938	/*
4939	 * this is exactly DN_MAX_INDBLKSHIFT when metadata isn't
4940	 * compressed, but in practice they compress down to about
4941	 * 1100 bytes
4942	 */
4943	numdb *= 1ULL << DN_MAX_INDBLKSHIFT;
4944	volsize += numdb;
4945	return (volsize);
4946}
4947
4948/*
4949 * Attach/detach the given filesystem to/from the given jail.
4950 */
4951int
4952zfs_jail(zfs_handle_t *zhp, int jailid, int attach)
4953{
4954	libzfs_handle_t *hdl = zhp->zfs_hdl;
4955	zfs_cmd_t zc = { 0 };
4956	char errbuf[1024];
4957	unsigned long cmd;
4958	int ret;
4959
4960	if (attach) {
4961		(void) snprintf(errbuf, sizeof (errbuf),
4962		    dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name);
4963	} else {
4964		(void) snprintf(errbuf, sizeof (errbuf),
4965		    dgettext(TEXT_DOMAIN, "cannot unjail '%s'"), zhp->zfs_name);
4966	}
4967
4968	switch (zhp->zfs_type) {
4969	case ZFS_TYPE_VOLUME:
4970		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4971		    "volumes can not be jailed"));
4972		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4973	case ZFS_TYPE_SNAPSHOT:
4974		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
4975		    "snapshots can not be jailed"));
4976		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
4977	}
4978	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
4979
4980	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
4981	zc.zc_objset_type = DMU_OST_ZFS;
4982	zc.zc_jailid = jailid;
4983
4984	cmd = attach ? ZFS_IOC_JAIL : ZFS_IOC_UNJAIL;
4985	if ((ret = ioctl(hdl->libzfs_fd, cmd, &zc)) != 0)
4986		zfs_standard_error(hdl, errno, errbuf);
4987
4988	return (ret);
4989}
4990