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