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