xref: /titanic_41/usr/src/lib/libzfs/common/libzfs_dataset.c (revision 1daa57680c1c12da0548089a11b00a9d6d077bb5)
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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <assert.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <libdevinfo.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 <zone.h>
39 #include <fcntl.h>
40 #include <sys/mntent.h>
41 #include <sys/mnttab.h>
42 #include <sys/mount.h>
43 
44 #include <sys/spa.h>
45 #include <sys/zio.h>
46 #include <libzfs.h>
47 
48 #include "zfs_namecheck.h"
49 #include "zfs_prop.h"
50 #include "libzfs_impl.h"
51 
52 /*
53  * Given a single type (not a mask of types), return the type in a human
54  * readable form.
55  */
56 const char *
57 zfs_type_to_name(zfs_type_t type)
58 {
59 	switch (type) {
60 	case ZFS_TYPE_FILESYSTEM:
61 		return (dgettext(TEXT_DOMAIN, "filesystem"));
62 	case ZFS_TYPE_SNAPSHOT:
63 		return (dgettext(TEXT_DOMAIN, "snapshot"));
64 	case ZFS_TYPE_VOLUME:
65 		return (dgettext(TEXT_DOMAIN, "volume"));
66 	}
67 
68 	return (NULL);
69 }
70 
71 /*
72  * Given a path and mask of ZFS types, return a string describing this dataset.
73  * This is used when we fail to open a dataset and we cannot get an exact type.
74  * We guess what the type would have been based on the path and the mask of
75  * acceptable types.
76  */
77 static const char *
78 path_to_str(const char *path, int types)
79 {
80 	/*
81 	 * When given a single type, always report the exact type.
82 	 */
83 	if (types == ZFS_TYPE_SNAPSHOT)
84 		return (dgettext(TEXT_DOMAIN, "snapshot"));
85 	if (types == ZFS_TYPE_FILESYSTEM)
86 		return (dgettext(TEXT_DOMAIN, "filesystem"));
87 	if (types == ZFS_TYPE_VOLUME)
88 		return (dgettext(TEXT_DOMAIN, "volume"));
89 
90 	/*
91 	 * The user is requesting more than one type of dataset.  If this is the
92 	 * case, consult the path itself.  If we're looking for a snapshot, and
93 	 * a '@' is found, then report it as "snapshot".  Otherwise, remove the
94 	 * snapshot attribute and try again.
95 	 */
96 	if (types & ZFS_TYPE_SNAPSHOT) {
97 		if (strchr(path, '@') != NULL)
98 			return (dgettext(TEXT_DOMAIN, "snapshot"));
99 		return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT));
100 	}
101 
102 
103 	/*
104 	 * The user has requested either filesystems or volumes.
105 	 * We have no way of knowing a priori what type this would be, so always
106 	 * report it as "filesystem" or "volume", our two primitive types.
107 	 */
108 	if (types & ZFS_TYPE_FILESYSTEM)
109 		return (dgettext(TEXT_DOMAIN, "filesystem"));
110 
111 	assert(types & ZFS_TYPE_VOLUME);
112 	return (dgettext(TEXT_DOMAIN, "volume"));
113 }
114 
115 /*
116  * Validate a ZFS path.  This is used even before trying to open the dataset, to
117  * provide a more meaningful error message.  We place a more useful message in
118  * 'buf' detailing exactly why the name was not valid.
119  */
120 static int
121 zfs_validate_name(libzfs_handle_t *hdl, const char *path, int type)
122 {
123 	namecheck_err_t why;
124 	char what;
125 
126 	if (dataset_namecheck(path, &why, &what) != 0) {
127 		if (hdl != NULL) {
128 			switch (why) {
129 			case NAME_ERR_TOOLONG:
130 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
131 				    "name is too long"));
132 				break;
133 
134 			case NAME_ERR_LEADING_SLASH:
135 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
136 				    "leading slash in name"));
137 				break;
138 
139 			case NAME_ERR_EMPTY_COMPONENT:
140 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
141 				    "empty component in name"));
142 				break;
143 
144 			case NAME_ERR_TRAILING_SLASH:
145 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
146 				    "trailing slash in name"));
147 				break;
148 
149 			case NAME_ERR_INVALCHAR:
150 				zfs_error_aux(hdl,
151 				    dgettext(TEXT_DOMAIN, "invalid character "
152 				    "'%c' in name"), what);
153 				break;
154 
155 			case NAME_ERR_MULTIPLE_AT:
156 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
157 				    "multiple '@' delimiters in name"));
158 				break;
159 			}
160 		}
161 
162 		return (0);
163 	}
164 
165 	if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
166 		if (hdl != NULL)
167 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
168 			    "snapshot delimiter '@' in filesystem name"));
169 		return (0);
170 	}
171 
172 	if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) {
173 		if (hdl != NULL)
174 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
175 			    "missing '@' delimeter in snapshot name"));
176 		return (0);
177 	}
178 
179 	return (-1);
180 }
181 
182 int
183 zfs_name_valid(const char *name, zfs_type_t type)
184 {
185 	return (zfs_validate_name(NULL, name, type));
186 }
187 
188 /*
189  * Utility function to gather stats (objset and zpl) for the given object.
190  */
191 static int
192 get_stats(zfs_handle_t *zhp)
193 {
194 	zfs_cmd_t zc = { 0 };
195 
196 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
197 
198 	if ((zc.zc_config_src = (uint64_t)(uintptr_t)malloc(1024)) == NULL)
199 		return (-1);
200 	zc.zc_config_src_size = 1024;
201 
202 	while (ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0) {
203 		if (errno == ENOMEM) {
204 			free((void *)(uintptr_t)zc.zc_config_src);
205 			if ((zc.zc_config_src = (uint64_t)(uintptr_t)
206 			    malloc(zc.zc_config_src_size)) == NULL)
207 				return (-1);
208 		} else {
209 			free((void *)(uintptr_t)zc.zc_config_src);
210 			return (-1);
211 		}
212 	}
213 
214 	bcopy(&zc.zc_objset_stats, &zhp->zfs_dmustats,
215 	    sizeof (zc.zc_objset_stats));
216 
217 	(void) strcpy(zhp->zfs_root, zc.zc_root);
218 
219 	if (zhp->zfs_props) {
220 		nvlist_free(zhp->zfs_props);
221 		zhp->zfs_props = NULL;
222 	}
223 
224 	if (nvlist_unpack((void *)(uintptr_t)zc.zc_config_src,
225 	    zc.zc_config_src_size, &zhp->zfs_props, 0) != 0) {
226 		free((void *)(uintptr_t)zc.zc_config_src);
227 		return (-1);
228 	}
229 
230 	zhp->zfs_volsize = zc.zc_volsize;
231 	zhp->zfs_volblocksize = zc.zc_volblocksize;
232 
233 	free((void *)(uintptr_t)zc.zc_config_src);
234 
235 	return (0);
236 }
237 
238 /*
239  * Refresh the properties currently stored in the handle.
240  */
241 void
242 zfs_refresh_properties(zfs_handle_t *zhp)
243 {
244 	(void) get_stats(zhp);
245 }
246 
247 /*
248  * Makes a handle from the given dataset name.  Used by zfs_open() and
249  * zfs_iter_* to create child handles on the fly.
250  */
251 zfs_handle_t *
252 make_dataset_handle(libzfs_handle_t *hdl, const char *path)
253 {
254 	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
255 
256 	if (zhp == NULL)
257 		return (NULL);
258 
259 	zhp->zfs_hdl = hdl;
260 
261 top:
262 	(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
263 
264 	if (get_stats(zhp) != 0) {
265 		free(zhp);
266 		return (NULL);
267 	}
268 
269 	if (zhp->zfs_dmustats.dds_inconsistent) {
270 		zfs_cmd_t zc = { 0 };
271 
272 		/*
273 		 * If it is dds_inconsistent, then we've caught it in
274 		 * the middle of a 'zfs receive' or 'zfs destroy', and
275 		 * it is inconsistent from the ZPL's point of view, so
276 		 * can't be mounted.  However, it could also be that we
277 		 * have crashed in the middle of one of those
278 		 * operations, in which case we need to get rid of the
279 		 * inconsistent state.  We do that by either rolling
280 		 * back to the previous snapshot (which will fail if
281 		 * there is none), or destroying the filesystem.  Note
282 		 * that if we are still in the middle of an active
283 		 * 'receive' or 'destroy', then the rollback and destroy
284 		 * will fail with EBUSY and we will drive on as usual.
285 		 */
286 
287 		(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
288 
289 		if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
290 			(void) zvol_remove_link(hdl, zhp->zfs_name);
291 			zc.zc_objset_type = DMU_OST_ZVOL;
292 		} else {
293 			zc.zc_objset_type = DMU_OST_ZFS;
294 		}
295 
296 		/* If we can successfully roll it back, reget the stats */
297 		if (ioctl(hdl->libzfs_fd, ZFS_IOC_ROLLBACK, &zc) == 0)
298 			goto top;
299 		/*
300 		 * If we can sucessfully destroy it, pretend that it
301 		 * never existed.
302 		 */
303 		if (ioctl(hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc) == 0) {
304 			free(zhp);
305 			errno = ENOENT;
306 			return (NULL);
307 		}
308 	}
309 
310 	/*
311 	 * We've managed to open the dataset and gather statistics.  Determine
312 	 * the high-level type.
313 	 */
314 	if (zhp->zfs_dmustats.dds_is_snapshot)
315 		zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
316 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
317 		zhp->zfs_type = ZFS_TYPE_VOLUME;
318 	else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
319 		zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
320 	else
321 		abort();	/* we should never see any other types */
322 
323 	return (zhp);
324 }
325 
326 /*
327  * Opens the given snapshot, filesystem, or volume.   The 'types'
328  * argument is a mask of acceptable types.  The function will print an
329  * appropriate error message and return NULL if it can't be opened.
330  */
331 zfs_handle_t *
332 zfs_open(libzfs_handle_t *hdl, const char *path, int types)
333 {
334 	zfs_handle_t *zhp;
335 	char errbuf[1024];
336 
337 	(void) snprintf(errbuf, sizeof (errbuf),
338 	    dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
339 
340 	/*
341 	 * Validate the name before we even try to open it.
342 	 */
343 	if (!zfs_validate_name(hdl, path, ZFS_TYPE_ANY)) {
344 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
345 		    "invalid dataset name"));
346 		(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
347 		return (NULL);
348 	}
349 
350 	/*
351 	 * Try to get stats for the dataset, which will tell us if it exists.
352 	 */
353 	errno = 0;
354 	if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
355 		(void) zfs_standard_error(hdl, errno, errbuf, path);
356 		return (NULL);
357 	}
358 
359 	if (!(types & zhp->zfs_type)) {
360 		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
361 		zfs_close(zhp);
362 		return (NULL);
363 	}
364 
365 	return (zhp);
366 }
367 
368 /*
369  * Release a ZFS handle.  Nothing to do but free the associated memory.
370  */
371 void
372 zfs_close(zfs_handle_t *zhp)
373 {
374 	if (zhp->zfs_mntopts)
375 		free(zhp->zfs_mntopts);
376 	if (zhp->zfs_props)
377 		nvlist_free(zhp->zfs_props);
378 	free(zhp);
379 }
380 
381 struct {
382 	const char *name;
383 	uint64_t value;
384 } checksum_table[] = {
385 	{ "on",		ZIO_CHECKSUM_ON },
386 	{ "off",	ZIO_CHECKSUM_OFF },
387 	{ "fletcher2",	ZIO_CHECKSUM_FLETCHER_2 },
388 	{ "fletcher4",	ZIO_CHECKSUM_FLETCHER_4 },
389 	{ "sha256",	ZIO_CHECKSUM_SHA256 },
390 	{ NULL }
391 };
392 
393 struct {
394 	const char *name;
395 	uint64_t value;
396 } compress_table[] = {
397 	{ "on",		ZIO_COMPRESS_ON },
398 	{ "off",	ZIO_COMPRESS_OFF },
399 	{ "lzjb",	ZIO_COMPRESS_LZJB },
400 	{ NULL }
401 };
402 
403 struct {
404 	const char *name;
405 	uint64_t value;
406 } snapdir_table[] = {
407 	{ "hidden",	ZFS_SNAPDIR_HIDDEN },
408 	{ "visible",	ZFS_SNAPDIR_VISIBLE },
409 	{ NULL }
410 };
411 
412 struct {
413 	const char *name;
414 	uint64_t value;
415 } acl_mode_table[] = {
416 	{ "discard",	DISCARD },
417 	{ "groupmask",	GROUPMASK },
418 	{ "passthrough", PASSTHROUGH },
419 	{ NULL }
420 };
421 
422 struct {
423 	const char *name;
424 	uint64_t value;
425 } acl_inherit_table[] = {
426 	{ "discard",	DISCARD },
427 	{ "noallow",	NOALLOW },
428 	{ "secure",	SECURE },
429 	{ "passthrough", PASSTHROUGH },
430 	{ NULL }
431 };
432 
433 
434 /*
435  * Given a numeric suffix, convert the value into a number of bits that the
436  * resulting value must be shifted.
437  */
438 static int
439 str2shift(libzfs_handle_t *hdl, const char *buf)
440 {
441 	const char *ends = "BKMGTPEZ";
442 	int i;
443 
444 	if (buf[0] == '\0')
445 		return (0);
446 	for (i = 0; i < strlen(ends); i++) {
447 		if (toupper(buf[0]) == ends[i])
448 			break;
449 	}
450 	if (i == strlen(ends)) {
451 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
452 		    "invalid numeric suffix '%s'"), buf);
453 		return (-1);
454 	}
455 
456 	/*
457 	 * We want to allow trailing 'b' characters for 'GB' or 'Mb'.  But don't
458 	 * allow 'BB' - that's just weird.
459 	 */
460 	if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
461 	    toupper(buf[0]) != 'B'))
462 		return (10*i);
463 
464 	zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
465 	    "invalid numeric suffix '%s'"), buf);
466 	return (-1);
467 }
468 
469 /*
470  * Convert a string of the form '100G' into a real number.  Used when setting
471  * properties or creating a volume.  'buf' is used to place an extended error
472  * message for the caller to use.
473  */
474 static int
475 nicestrtonum(libzfs_handle_t *hdl, const char *value, uint64_t *num)
476 {
477 	char *end;
478 	int shift;
479 
480 	*num = 0;
481 
482 	/* Check to see if this looks like a number.  */
483 	if ((value[0] < '0' || value[0] > '9') && value[0] != '.') {
484 		if (hdl)
485 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
486 			    "bad numeric value '%s'"), value);
487 		return (-1);
488 	}
489 
490 	/* Rely on stroll() to process the numeric portion.  */
491 	errno = 0;
492 	*num = strtoll(value, &end, 10);
493 
494 	/*
495 	 * Check for ERANGE, which indicates that the value is too large to fit
496 	 * in a 64-bit value.
497 	 */
498 	if (errno == ERANGE) {
499 		if (hdl)
500 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
501 			    "numeric value is too large"));
502 		return (-1);
503 	}
504 
505 	/*
506 	 * If we have a decimal value, then do the computation with floating
507 	 * point arithmetic.  Otherwise, use standard arithmetic.
508 	 */
509 	if (*end == '.') {
510 		double fval = strtod(value, &end);
511 
512 		if ((shift = str2shift(hdl, end)) == -1)
513 			return (-1);
514 
515 		fval *= pow(2, shift);
516 
517 		if (fval > UINT64_MAX) {
518 			if (hdl)
519 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
520 				    "numeric value is too large"));
521 			return (-1);
522 		}
523 
524 		*num = (uint64_t)fval;
525 	} else {
526 		if ((shift = str2shift(hdl, end)) == -1)
527 			return (-1);
528 
529 		/* Check for overflow */
530 		if (shift >= 64 || (*num << shift) >> shift != *num) {
531 			if (hdl)
532 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
533 				    "numeric value is too large"));
534 			return (-1);
535 		}
536 
537 		*num <<= shift;
538 	}
539 
540 	return (0);
541 }
542 
543 int
544 zfs_nicestrtonum(const char *str, uint64_t *val)
545 {
546 	return (nicestrtonum(NULL, str, val));
547 }
548 
549 /*
550  * Given a property type and value, verify that the value is appropriate.  Used
551  * by zfs_prop_set() and some libzfs consumers.
552  */
553 int
554 zfs_prop_validate(libzfs_handle_t *hdl, zfs_prop_t prop, const char *value,
555     uint64_t *intval)
556 {
557 	const char *propname = zfs_prop_to_name(prop);
558 	uint64_t number;
559 	char errbuf[1024];
560 	int i;
561 
562 	/*
563 	 * Check to see if this a read-only property.
564 	 */
565 	if (zfs_prop_readonly(prop))
566 		return (zfs_error(hdl, EZFS_PROPREADONLY,
567 		    dgettext(TEXT_DOMAIN, "cannot set %s property"), propname));
568 
569 	(void) snprintf(errbuf, sizeof (errbuf),
570 	    dgettext(TEXT_DOMAIN, "bad %s value '%s'"), propname, value);
571 
572 	/* See if the property value is too long */
573 	if (strlen(value) >= ZFS_MAXPROPLEN) {
574 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "value is too long"));
575 		return (zfs_error(hdl, EZFS_BADPROP, errbuf));
576 	}
577 
578 	/* Perform basic checking based on property type */
579 	switch (zfs_prop_get_type(prop)) {
580 	case prop_type_boolean:
581 		if (strcmp(value, "on") == 0) {
582 			number = 1;
583 		} else if (strcmp(value, "off") == 0) {
584 			number = 0;
585 		} else {
586 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
587 			    "must be 'on' or 'off'"));
588 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
589 		}
590 		break;
591 
592 	case prop_type_number:
593 		/* treat 'none' as 0 */
594 		if (strcmp(value, "none") == 0) {
595 			number = 0;
596 			break;
597 		}
598 
599 		if (nicestrtonum(hdl, value, &number) != 0)
600 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
601 
602 		/* don't allow 0 for quota, use 'none' instead */
603 		if (prop == ZFS_PROP_QUOTA && number == 0 &&
604 		    strcmp(value, "none") != 0) {
605 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
606 			    "use 'quota=none' to disable"));
607 			return (zfs_error(hdl, EZFS_BADPROP, errbuf));
608 		}
609 
610 		/* must be power of two within SPA_{MIN,MAX}BLOCKSIZE */
611 		if (prop == ZFS_PROP_RECORDSIZE ||
612 		    prop == ZFS_PROP_VOLBLOCKSIZE) {
613 			if (number < SPA_MINBLOCKSIZE ||
614 			    number > SPA_MAXBLOCKSIZE || !ISP2(number)) {
615 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
616 				    "must be power of 2 from %u to %uk"),
617 				    (uint_t)SPA_MINBLOCKSIZE,
618 				    (uint_t)SPA_MAXBLOCKSIZE >> 10);
619 				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
620 			}
621 		}
622 
623 		break;
624 
625 	case prop_type_string:
626 	case prop_type_index:
627 		/*
628 		 * The two writable string values, 'mountpoint' and
629 		 * 'checksum' need special consideration.  The 'index' types are
630 		 * specified as strings by the user, but passed to the kernel as
631 		 * integers.
632 		 */
633 		switch (prop) {
634 		case ZFS_PROP_MOUNTPOINT:
635 			if (strcmp(value, ZFS_MOUNTPOINT_NONE) == 0 ||
636 			    strcmp(value, ZFS_MOUNTPOINT_LEGACY) == 0)
637 				break;
638 
639 			if (value[0] != '/') {
640 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
641 				    "must be an absolute path, 'none', or "
642 				    "'legacy'"));
643 				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
644 			}
645 			break;
646 
647 		case ZFS_PROP_CHECKSUM:
648 			for (i = 0; checksum_table[i].name != NULL; i++) {
649 				if (strcmp(value, checksum_table[i].name)
650 				    == 0) {
651 					number = checksum_table[i].value;
652 					break;
653 				}
654 			}
655 
656 			if (checksum_table[i].name == NULL) {
657 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
658 				    "must be 'on', 'off', 'fletcher2', "
659 				    "'fletcher4', or 'sha256'"));
660 				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
661 			}
662 			break;
663 
664 		case ZFS_PROP_COMPRESSION:
665 			for (i = 0; compress_table[i].name != NULL; i++) {
666 				if (strcmp(value, compress_table[i].name)
667 				    == 0) {
668 					number = compress_table[i].value;
669 					break;
670 				}
671 			}
672 
673 			if (compress_table[i].name == NULL) {
674 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
675 				    "must be 'on', 'off', or 'lzjb'"));
676 				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
677 			}
678 			break;
679 
680 		case ZFS_PROP_SNAPDIR:
681 			for (i = 0; snapdir_table[i].name != NULL; i++) {
682 				if (strcmp(value, snapdir_table[i].name) == 0) {
683 					number = snapdir_table[i].value;
684 					break;
685 				}
686 			}
687 
688 			if (snapdir_table[i].name == NULL) {
689 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
690 				    "must be 'hidden' or 'visible'"));
691 				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
692 			}
693 			break;
694 
695 		case ZFS_PROP_ACLMODE:
696 			for (i = 0; acl_mode_table[i].name != NULL; i++) {
697 				if (strcmp(value, acl_mode_table[i].name)
698 				    == 0) {
699 					number = acl_mode_table[i].value;
700 					break;
701 				}
702 			}
703 
704 			if (acl_mode_table[i].name == NULL) {
705 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
706 				    "must be 'disacard', 'groupmask', or "
707 				    "'passthrough'"));
708 				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
709 			}
710 			break;
711 
712 		case ZFS_PROP_ACLINHERIT:
713 			for (i = 0; acl_inherit_table[i].name != NULL; i++) {
714 				if (strcmp(value, acl_inherit_table[i].name)
715 				    == 0) {
716 					number = acl_inherit_table[i].value;
717 					break;
718 				}
719 			}
720 
721 			if (acl_inherit_table[i].name == NULL) {
722 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
723 				    "must be 'discard, 'noallow', 'secure', "
724 				    "or 'passthrough'"));
725 				return (zfs_error(hdl, EZFS_BADPROP, errbuf));
726 			}
727 			break;
728 
729 		case ZFS_PROP_SHARENFS:
730 			/*
731 			 * Nothing to do for 'sharenfs', this gets passed on to
732 			 * share(1M) verbatim.
733 			 */
734 			break;
735 		}
736 	}
737 
738 	if (intval != NULL)
739 		*intval = number;
740 
741 	return (0);
742 }
743 
744 /*
745  * Given a property name and value, set the property for the given dataset.
746  */
747 int
748 zfs_prop_set(zfs_handle_t *zhp, zfs_prop_t prop, const char *propval)
749 {
750 	const char *propname = zfs_prop_to_name(prop);
751 	uint64_t number;
752 	zfs_cmd_t zc = { 0 };
753 	int ret;
754 	prop_changelist_t *cl;
755 	char errbuf[1024];
756 	libzfs_handle_t *hdl = zhp->zfs_hdl;
757 
758 	if (zfs_prop_validate(zhp->zfs_hdl, prop, propval, &number) != 0)
759 		return (-1);
760 
761 
762 	(void) snprintf(errbuf, sizeof (errbuf),
763 	    dgettext(TEXT_DOMAIN, "cannot set %s for '%s'"), propname,
764 	    zhp->zfs_name);
765 
766 	/*
767 	 * Check to see if the value applies to this type
768 	 */
769 	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
770 		return (zfs_error(hdl, EZFS_PROPTYPE, errbuf));
771 
772 	/*
773 	 * For the mountpoint and sharenfs properties, check if it can be set
774 	 * in a global/non-global zone based on the zoned property value:
775 	 *
776 	 *		global zone	    non-global zone
777 	 * -----------------------------------------------------
778 	 * zoned=on	mountpoint (no)	    mountpoint (yes)
779 	 *		sharenfs (no)	    sharenfs (no)
780 	 *
781 	 * zoned=off	mountpoint (yes)	N/A
782 	 *		sharenfs (yes)
783 	 */
784 	if (prop == ZFS_PROP_MOUNTPOINT || prop == ZFS_PROP_SHARENFS) {
785 		if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
786 			if (getzoneid() == GLOBAL_ZONEID) {
787 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
788 				    "dataset is used in a non-global zone"));
789 				return (zfs_error(hdl, EZFS_ZONED, errbuf));
790 			} else if (prop == ZFS_PROP_SHARENFS) {
791 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
792 				    "filesystems cannot be shared in a "
793 				    "non-global zone"));
794 				return (zfs_error(hdl, EZFS_ZONED, errbuf));
795 			}
796 		} else if (getzoneid() != GLOBAL_ZONEID) {
797 			/*
798 			 * If zoned property is 'off', this must be in
799 			 * a globle zone. If not, something is wrong.
800 			 */
801 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
802 			    "dataset is used in a non-global zone, but "
803 			    "'zoned' property is not set"));
804 			return (zfs_error(hdl, EZFS_ZONED, errbuf));
805 		}
806 	}
807 
808 	if ((cl = changelist_gather(zhp, prop, 0)) == NULL)
809 		return (-1);
810 
811 	if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
812 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
813 		    "child dataset with inherited mountpoint is used "
814 		    "in a non-global zone"));
815 		ret = zfs_error(hdl, EZFS_ZONED, errbuf);
816 		goto error;
817 	}
818 
819 	if ((ret = changelist_prefix(cl)) != 0)
820 		goto error;
821 
822 	/*
823 	 * Execute the corresponding ioctl() to set this property.
824 	 */
825 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
826 
827 	switch (prop) {
828 	case ZFS_PROP_QUOTA:
829 		zc.zc_cookie = number;
830 		ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SET_QUOTA, &zc);
831 		break;
832 	case ZFS_PROP_RESERVATION:
833 		zc.zc_cookie = number;
834 		ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SET_RESERVATION,
835 		    &zc);
836 		break;
837 	case ZFS_PROP_MOUNTPOINT:
838 	case ZFS_PROP_SHARENFS:
839 		/*
840 		 * These properties are passed down as real strings.
841 		 */
842 		(void) strlcpy(zc.zc_prop_name, propname,
843 		    sizeof (zc.zc_prop_name));
844 		(void) strlcpy(zc.zc_prop_value, propval,
845 		    sizeof (zc.zc_prop_value));
846 		zc.zc_intsz = 1;
847 		zc.zc_numints = strlen(propval) + 1;
848 		ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SET_PROP, &zc);
849 		break;
850 	case ZFS_PROP_VOLSIZE:
851 		zc.zc_volsize = number;
852 		ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SET_VOLSIZE, &zc);
853 		break;
854 	case ZFS_PROP_VOLBLOCKSIZE:
855 		zc.zc_volblocksize = number;
856 		ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SET_VOLBLOCKSIZE,
857 		    &zc);
858 		break;
859 	default:
860 		(void) strlcpy(zc.zc_prop_name, propname,
861 		    sizeof (zc.zc_prop_name));
862 		/* LINTED - alignment */
863 		*(uint64_t *)zc.zc_prop_value = number;
864 		zc.zc_intsz = 8;
865 		zc.zc_numints = 1;
866 		ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SET_PROP, &zc);
867 		break;
868 	}
869 
870 	if (ret != 0) {
871 		switch (errno) {
872 
873 		case ENOSPC:
874 			/*
875 			 * For quotas and reservations, ENOSPC indicates
876 			 * something different; setting a quota or reservation
877 			 * doesn't use any disk space.
878 			 */
879 			switch (prop) {
880 			case ZFS_PROP_QUOTA:
881 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
882 				    "size is less than current used or "
883 				    "reserved space"));
884 				(void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
885 				break;
886 
887 			case ZFS_PROP_RESERVATION:
888 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
889 				    "size is greater than available space"));
890 				(void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
891 				break;
892 
893 			default:
894 				(void) zfs_standard_error(hdl, errno, errbuf);
895 				break;
896 			}
897 			break;
898 
899 		case EBUSY:
900 			if (prop == ZFS_PROP_VOLBLOCKSIZE)
901 				(void) zfs_error(hdl, EZFS_VOLHASDATA, errbuf);
902 			else
903 				return (zfs_standard_error(hdl, EBUSY, errbuf));
904 			break;
905 
906 		case EROFS:
907 			(void) zfs_error(hdl, EZFS_DSREADONLY, errbuf);
908 			break;
909 
910 		case EOVERFLOW:
911 			/*
912 			 * This platform can't address a volume this big.
913 			 */
914 #ifdef _ILP32
915 			if (prop == ZFS_PROP_VOLSIZE) {
916 				(void) zfs_error(hdl, EZFS_VOLTOOBIG, errbuf);
917 				break;
918 			}
919 #endif
920 			/* FALLTHROUGH */
921 		default:
922 			(void) zfs_standard_error(hdl, errno, errbuf);
923 		}
924 	} else {
925 		/*
926 		 * Refresh the statistics so the new property value
927 		 * is reflected.
928 		 */
929 		if ((ret = changelist_postfix(cl)) != 0)
930 			goto error;
931 
932 		(void) get_stats(zhp);
933 	}
934 
935 error:
936 	changelist_free(cl);
937 	return (ret);
938 }
939 
940 /*
941  * Given a property, inherit the value from the parent dataset.
942  */
943 int
944 zfs_prop_inherit(zfs_handle_t *zhp, zfs_prop_t prop)
945 {
946 	const char *propname = zfs_prop_to_name(prop);
947 	zfs_cmd_t zc = { 0 };
948 	int ret;
949 	prop_changelist_t *cl;
950 	libzfs_handle_t *hdl = zhp->zfs_hdl;
951 	char errbuf[1024];
952 
953 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
954 	    "cannot inherit %s for '%s'"), propname, zhp->zfs_name);
955 
956 	/*
957 	 * Verify that this property is inheritable.
958 	 */
959 	if (zfs_prop_readonly(prop))
960 		return (zfs_error(hdl, EZFS_PROPREADONLY, errbuf));
961 
962 	if (!zfs_prop_inheritable(prop))
963 		return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf));
964 
965 	/*
966 	 * Check to see if the value applies to this type
967 	 */
968 	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
969 		return (zfs_error(hdl, EZFS_PROPTYPE, errbuf));
970 
971 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
972 	(void) strlcpy(zc.zc_prop_name, propname, sizeof (zc.zc_prop_name));
973 
974 	if (prop == ZFS_PROP_MOUNTPOINT && getzoneid() == GLOBAL_ZONEID &&
975 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
976 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
977 		    "dataset is used in a non-global zone"));
978 		return (zfs_error(hdl, EZFS_ZONED, errbuf));
979 	}
980 
981 	/*
982 	 * Determine datasets which will be affected by this change, if any.
983 	 */
984 	if ((cl = changelist_gather(zhp, prop, 0)) == NULL)
985 		return (-1);
986 
987 	if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
988 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
989 		    "child dataset with inherited mountpoint is used "
990 		    "in a non-global zone"));
991 		ret = zfs_error(hdl, EZFS_ZONED, errbuf);
992 		goto error;
993 	}
994 
995 	if ((ret = changelist_prefix(cl)) != 0)
996 		goto error;
997 
998 	zc.zc_numints = 0;
999 
1000 	if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd,
1001 	    ZFS_IOC_SET_PROP, &zc)) != 0) {
1002 		return (zfs_standard_error(hdl, errno, errbuf));
1003 	} else {
1004 
1005 		if ((ret = changelist_postfix(cl)) != 0)
1006 			goto error;
1007 
1008 		/*
1009 		 * Refresh the statistics so the new property is reflected.
1010 		 */
1011 		(void) get_stats(zhp);
1012 	}
1013 
1014 
1015 error:
1016 	changelist_free(cl);
1017 	return (ret);
1018 }
1019 
1020 static void
1021 nicebool(int value, char *buf, size_t buflen)
1022 {
1023 	if (value)
1024 		(void) strlcpy(buf, "on", buflen);
1025 	else
1026 		(void) strlcpy(buf, "off", buflen);
1027 }
1028 
1029 /*
1030  * True DSL properties are stored in an nvlist.  The following two functions
1031  * extract them appropriately.
1032  */
1033 static uint64_t
1034 getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
1035 {
1036 	nvlist_t *nv;
1037 	uint64_t value;
1038 
1039 	if (nvlist_lookup_nvlist(zhp->zfs_props,
1040 	    zfs_prop_to_name(prop), &nv) == 0) {
1041 		verify(nvlist_lookup_uint64(nv, ZFS_PROP_VALUE, &value) == 0);
1042 		verify(nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source) == 0);
1043 	} else {
1044 		value = zfs_prop_default_numeric(prop);
1045 		*source = "";
1046 	}
1047 
1048 	return (value);
1049 }
1050 
1051 static char *
1052 getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
1053 {
1054 	nvlist_t *nv;
1055 	char *value;
1056 
1057 	if (nvlist_lookup_nvlist(zhp->zfs_props,
1058 	    zfs_prop_to_name(prop), &nv) == 0) {
1059 		verify(nvlist_lookup_string(nv, ZFS_PROP_VALUE, &value) == 0);
1060 		verify(nvlist_lookup_string(nv, ZFS_PROP_SOURCE, source) == 0);
1061 	} else {
1062 		if ((value = (char *)zfs_prop_default_string(prop)) == NULL)
1063 			value = "";
1064 		*source = "";
1065 	}
1066 
1067 	return (value);
1068 }
1069 
1070 /*
1071  * Internal function for getting a numeric property.  Both zfs_prop_get() and
1072  * zfs_prop_get_int() are built using this interface.
1073  *
1074  * Certain properties can be overridden using 'mount -o'.  In this case, scan
1075  * the contents of the /etc/mnttab entry, searching for the appropriate options.
1076  * If they differ from the on-disk values, report the current values and mark
1077  * the source "temporary".
1078  */
1079 static int
1080 get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zfs_source_t *src,
1081     char **source, uint64_t *val)
1082 {
1083 	struct mnttab mnt;
1084 
1085 	*source = NULL;
1086 
1087 	/*
1088 	 * Because looking up the mount options is potentially expensive
1089 	 * (iterating over all of /etc/mnttab), we defer its calculation until
1090 	 * we're looking up a property which requires its presence.
1091 	 */
1092 	if (!zhp->zfs_mntcheck &&
1093 	    (prop == ZFS_PROP_ATIME ||
1094 	    prop == ZFS_PROP_DEVICES ||
1095 	    prop == ZFS_PROP_EXEC ||
1096 	    prop == ZFS_PROP_READONLY ||
1097 	    prop == ZFS_PROP_SETUID ||
1098 	    prop == ZFS_PROP_MOUNTED)) {
1099 		struct mnttab search = { 0 }, entry;
1100 
1101 		search.mnt_special = (char *)zhp->zfs_name;
1102 		search.mnt_fstype = MNTTYPE_ZFS;
1103 		rewind(zhp->zfs_hdl->libzfs_mnttab);
1104 
1105 		if (getmntany(zhp->zfs_hdl->libzfs_mnttab, &entry,
1106 		    &search) == 0 && (zhp->zfs_mntopts =
1107 		    zfs_strdup(zhp->zfs_hdl,
1108 		    entry.mnt_mntopts)) == NULL)
1109 			return (-1);
1110 
1111 		zhp->zfs_mntcheck = B_TRUE;
1112 	}
1113 
1114 	if (zhp->zfs_mntopts == NULL)
1115 		mnt.mnt_mntopts = "";
1116 	else
1117 		mnt.mnt_mntopts = zhp->zfs_mntopts;
1118 
1119 	switch (prop) {
1120 	case ZFS_PROP_ATIME:
1121 		*val = getprop_uint64(zhp, prop, source);
1122 
1123 		if (hasmntopt(&mnt, MNTOPT_ATIME) && !*val) {
1124 			*val = B_TRUE;
1125 			if (src)
1126 				*src = ZFS_SRC_TEMPORARY;
1127 		} else if (hasmntopt(&mnt, MNTOPT_NOATIME) && *val) {
1128 			*val = B_FALSE;
1129 			if (src)
1130 				*src = ZFS_SRC_TEMPORARY;
1131 		}
1132 		break;
1133 
1134 	case ZFS_PROP_AVAILABLE:
1135 		*val = zhp->zfs_dmustats.dds_available;
1136 		break;
1137 
1138 	case ZFS_PROP_DEVICES:
1139 		*val = getprop_uint64(zhp, prop, source);
1140 
1141 		if (hasmntopt(&mnt, MNTOPT_DEVICES) && !*val) {
1142 			*val = B_TRUE;
1143 			if (src)
1144 				*src = ZFS_SRC_TEMPORARY;
1145 		} else if (hasmntopt(&mnt, MNTOPT_NODEVICES) && *val) {
1146 			*val = B_FALSE;
1147 			if (src)
1148 				*src = ZFS_SRC_TEMPORARY;
1149 		}
1150 		break;
1151 
1152 	case ZFS_PROP_EXEC:
1153 		*val = getprop_uint64(zhp, prop, source);
1154 
1155 		if (hasmntopt(&mnt, MNTOPT_EXEC) && !*val) {
1156 			*val = B_TRUE;
1157 			if (src)
1158 				*src = ZFS_SRC_TEMPORARY;
1159 		} else if (hasmntopt(&mnt, MNTOPT_NOEXEC) && *val) {
1160 			*val = B_FALSE;
1161 			if (src)
1162 				*src = ZFS_SRC_TEMPORARY;
1163 		}
1164 		break;
1165 
1166 	case ZFS_PROP_RECORDSIZE:
1167 	case ZFS_PROP_COMPRESSION:
1168 	case ZFS_PROP_ZONED:
1169 		*val = getprop_uint64(zhp, prop, source);
1170 		break;
1171 
1172 	case ZFS_PROP_READONLY:
1173 		*val = getprop_uint64(zhp, prop, source);
1174 
1175 		if (hasmntopt(&mnt, MNTOPT_RO) && !*val) {
1176 			*val = B_TRUE;
1177 			if (src)
1178 				*src = ZFS_SRC_TEMPORARY;
1179 		} else if (hasmntopt(&mnt, MNTOPT_RW) && *val) {
1180 			*val = B_FALSE;
1181 			if (src)
1182 				*src = ZFS_SRC_TEMPORARY;
1183 		}
1184 		break;
1185 
1186 	case ZFS_PROP_CREATION:
1187 		*val = zhp->zfs_dmustats.dds_creation_time;
1188 		break;
1189 
1190 	case ZFS_PROP_QUOTA:
1191 		if (zhp->zfs_dmustats.dds_quota == 0)
1192 			*source = "";	/* default */
1193 		else
1194 			*source = zhp->zfs_name;
1195 		*val = zhp->zfs_dmustats.dds_quota;
1196 		break;
1197 
1198 	case ZFS_PROP_RESERVATION:
1199 		if (zhp->zfs_dmustats.dds_reserved == 0)
1200 			*source = "";	/* default */
1201 		else
1202 			*source = zhp->zfs_name;
1203 		*val = zhp->zfs_dmustats.dds_reserved;
1204 		break;
1205 
1206 	case ZFS_PROP_COMPRESSRATIO:
1207 		/*
1208 		 * Using physical space and logical space, calculate the
1209 		 * compression ratio.  We return the number as a multiple of
1210 		 * 100, so '2.5x' would be returned as 250.
1211 		 */
1212 		if (zhp->zfs_dmustats.dds_compressed_bytes == 0)
1213 			*val = 100ULL;
1214 		else
1215 			*val =
1216 			    (zhp->zfs_dmustats.dds_uncompressed_bytes * 100 /
1217 			    zhp->zfs_dmustats.dds_compressed_bytes);
1218 		break;
1219 
1220 	case ZFS_PROP_REFERENCED:
1221 		/*
1222 		 * 'referenced' refers to the amount of physical space
1223 		 * referenced (possibly shared) by this object.
1224 		 */
1225 		*val = zhp->zfs_dmustats.dds_space_refd;
1226 		break;
1227 
1228 	case ZFS_PROP_SETUID:
1229 		*val = getprop_uint64(zhp, prop, source);
1230 
1231 		if (hasmntopt(&mnt, MNTOPT_SETUID) && !*val) {
1232 			*val = B_TRUE;
1233 			if (src)
1234 				*src = ZFS_SRC_TEMPORARY;
1235 		} else if (hasmntopt(&mnt, MNTOPT_NOSETUID) && *val) {
1236 			*val = B_FALSE;
1237 			if (src)
1238 				*src = ZFS_SRC_TEMPORARY;
1239 		}
1240 		break;
1241 
1242 	case ZFS_PROP_VOLSIZE:
1243 		*val = zhp->zfs_volsize;
1244 		break;
1245 
1246 	case ZFS_PROP_VOLBLOCKSIZE:
1247 		*val = zhp->zfs_volblocksize;
1248 		break;
1249 
1250 	case ZFS_PROP_USED:
1251 		*val = zhp->zfs_dmustats.dds_space_used;
1252 		break;
1253 
1254 	case ZFS_PROP_CREATETXG:
1255 		*val = zhp->zfs_dmustats.dds_creation_txg;
1256 		break;
1257 
1258 	case ZFS_PROP_MOUNTED:
1259 		*val = (zhp->zfs_mntopts != NULL);
1260 		break;
1261 
1262 	default:
1263 		zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
1264 		    "cannot get non-numeric property"));
1265 		return (zfs_error(zhp->zfs_hdl, EZFS_BADPROP,
1266 		    dgettext(TEXT_DOMAIN, "internal error")));
1267 	}
1268 
1269 	return (0);
1270 }
1271 
1272 /*
1273  * Calculate the source type, given the raw source string.
1274  */
1275 static void
1276 get_source(zfs_handle_t *zhp, zfs_source_t *srctype, char *source,
1277     char *statbuf, size_t statlen)
1278 {
1279 	if (statbuf == NULL || *srctype == ZFS_SRC_TEMPORARY)
1280 		return;
1281 
1282 	if (source == NULL) {
1283 		*srctype = ZFS_SRC_NONE;
1284 	} else if (source[0] == '\0') {
1285 		*srctype = ZFS_SRC_DEFAULT;
1286 	} else {
1287 		if (strcmp(source, zhp->zfs_name) == 0) {
1288 			*srctype = ZFS_SRC_LOCAL;
1289 		} else {
1290 			(void) strlcpy(statbuf, source, statlen);
1291 			*srctype = ZFS_SRC_INHERITED;
1292 		}
1293 	}
1294 
1295 }
1296 
1297 /*
1298  * Retrieve a property from the given object.  If 'literal' is specified, then
1299  * numbers are left as exact values.  Otherwise, numbers are converted to a
1300  * human-readable form.
1301  *
1302  * Returns 0 on success, or -1 on error.
1303  */
1304 int
1305 zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
1306     zfs_source_t *src, char *statbuf, size_t statlen, boolean_t literal)
1307 {
1308 	char *source = NULL;
1309 	uint64_t val;
1310 	char *str;
1311 	int i;
1312 	const char *root;
1313 
1314 	/*
1315 	 * Check to see if this property applies to our object
1316 	 */
1317 	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
1318 		return (-1);
1319 
1320 	if (src)
1321 		*src = ZFS_SRC_NONE;
1322 
1323 	switch (prop) {
1324 	case ZFS_PROP_ATIME:
1325 	case ZFS_PROP_READONLY:
1326 	case ZFS_PROP_SETUID:
1327 	case ZFS_PROP_ZONED:
1328 	case ZFS_PROP_DEVICES:
1329 	case ZFS_PROP_EXEC:
1330 		/*
1331 		 * Basic boolean values are built on top of
1332 		 * get_numeric_property().
1333 		 */
1334 		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
1335 			return (-1);
1336 		nicebool(val, propbuf, proplen);
1337 
1338 		break;
1339 
1340 	case ZFS_PROP_AVAILABLE:
1341 	case ZFS_PROP_RECORDSIZE:
1342 	case ZFS_PROP_CREATETXG:
1343 	case ZFS_PROP_REFERENCED:
1344 	case ZFS_PROP_USED:
1345 	case ZFS_PROP_VOLSIZE:
1346 	case ZFS_PROP_VOLBLOCKSIZE:
1347 		/*
1348 		 * Basic numeric values are built on top of
1349 		 * get_numeric_property().
1350 		 */
1351 		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
1352 			return (-1);
1353 		if (literal)
1354 			(void) snprintf(propbuf, proplen, "%llu", val);
1355 		else
1356 			zfs_nicenum(val, propbuf, proplen);
1357 		break;
1358 
1359 	case ZFS_PROP_COMPRESSION:
1360 		val = getprop_uint64(zhp, prop, &source);
1361 		for (i = 0; compress_table[i].name != NULL; i++) {
1362 			if (compress_table[i].value == val)
1363 				break;
1364 		}
1365 		assert(compress_table[i].name != NULL);
1366 		(void) strlcpy(propbuf, compress_table[i].name, proplen);
1367 		break;
1368 
1369 	case ZFS_PROP_CHECKSUM:
1370 		val = getprop_uint64(zhp, prop, &source);
1371 		for (i = 0; checksum_table[i].name != NULL; i++) {
1372 			if (checksum_table[i].value == val)
1373 				break;
1374 		}
1375 		assert(checksum_table[i].name != NULL);
1376 		(void) strlcpy(propbuf, checksum_table[i].name, proplen);
1377 		break;
1378 
1379 	case ZFS_PROP_SNAPDIR:
1380 		val = getprop_uint64(zhp, prop, &source);
1381 		for (i = 0; snapdir_table[i].name != NULL; i++) {
1382 			if (snapdir_table[i].value == val)
1383 				break;
1384 		}
1385 		assert(snapdir_table[i].name != NULL);
1386 		(void) strlcpy(propbuf, snapdir_table[i].name, proplen);
1387 		break;
1388 
1389 	case ZFS_PROP_ACLMODE:
1390 		val = getprop_uint64(zhp, prop, &source);
1391 		for (i = 0; acl_mode_table[i].name != NULL; i++) {
1392 			if (acl_mode_table[i].value == val)
1393 				break;
1394 		}
1395 		assert(acl_mode_table[i].name != NULL);
1396 		(void) strlcpy(propbuf, acl_mode_table[i].name, proplen);
1397 		break;
1398 
1399 	case ZFS_PROP_ACLINHERIT:
1400 		val = getprop_uint64(zhp, prop, &source);
1401 		for (i = 0; acl_inherit_table[i].name != NULL; i++) {
1402 			if (acl_inherit_table[i].value == val)
1403 				break;
1404 		}
1405 		assert(acl_inherit_table[i].name != NULL);
1406 		(void) strlcpy(propbuf, acl_inherit_table[i].name, proplen);
1407 		break;
1408 
1409 	case ZFS_PROP_CREATION:
1410 		/*
1411 		 * 'creation' is a time_t stored in the statistics.  We convert
1412 		 * this into a string unless 'literal' is specified.
1413 		 */
1414 		{
1415 			time_t time = (time_t)
1416 			    zhp->zfs_dmustats.dds_creation_time;
1417 			struct tm t;
1418 
1419 			if (literal ||
1420 			    localtime_r(&time, &t) == NULL ||
1421 			    strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
1422 			    &t) == 0)
1423 				(void) snprintf(propbuf, proplen, "%llu",
1424 				    zhp->zfs_dmustats.dds_creation_time);
1425 		}
1426 		break;
1427 
1428 	case ZFS_PROP_MOUNTPOINT:
1429 		/*
1430 		 * Getting the precise mountpoint can be tricky.
1431 		 *
1432 		 *  - for 'none' or 'legacy', return those values.
1433 		 *  - for default mountpoints, construct it as /zfs/<dataset>
1434 		 *  - for inherited mountpoints, we want to take everything
1435 		 *    after our ancestor and append it to the inherited value.
1436 		 *
1437 		 * If the pool has an alternate root, we want to prepend that
1438 		 * root to any values we return.
1439 		 */
1440 		root = zhp->zfs_root;
1441 		str = getprop_string(zhp, prop, &source);
1442 
1443 		if (str[0] == '\0') {
1444 			(void) snprintf(propbuf, proplen, "%s/zfs/%s",
1445 			    root, zhp->zfs_name);
1446 		} else if (str[0] == '/') {
1447 			const char *relpath = zhp->zfs_name + strlen(source);
1448 
1449 			if (relpath[0] == '/')
1450 				relpath++;
1451 			if (str[1] == '\0')
1452 				str++;
1453 
1454 			if (relpath[0] == '\0')
1455 				(void) snprintf(propbuf, proplen, "%s%s",
1456 				    root, str);
1457 			else
1458 				(void) snprintf(propbuf, proplen, "%s%s%s%s",
1459 				    root, str, relpath[0] == '@' ? "" : "/",
1460 				    relpath);
1461 		} else {
1462 			/* 'legacy' or 'none' */
1463 			(void) strlcpy(propbuf, str, proplen);
1464 		}
1465 
1466 		break;
1467 
1468 	case ZFS_PROP_SHARENFS:
1469 		(void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
1470 		    proplen);
1471 		break;
1472 
1473 	case ZFS_PROP_ORIGIN:
1474 		(void) strlcpy(propbuf, zhp->zfs_dmustats.dds_clone_of,
1475 		    proplen);
1476 		/*
1477 		 * If there is no parent at all, return failure to indicate that
1478 		 * it doesn't apply to this dataset.
1479 		 */
1480 		if (propbuf[0] == '\0')
1481 			return (-1);
1482 		break;
1483 
1484 	case ZFS_PROP_QUOTA:
1485 	case ZFS_PROP_RESERVATION:
1486 		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
1487 			return (-1);
1488 
1489 		/*
1490 		 * If quota or reservation is 0, we translate this into 'none'
1491 		 * (unless literal is set), and indicate that it's the default
1492 		 * value.  Otherwise, we print the number nicely and indicate
1493 		 * that its set locally.
1494 		 */
1495 		if (val == 0) {
1496 			if (literal)
1497 				(void) strlcpy(propbuf, "0", proplen);
1498 			else
1499 				(void) strlcpy(propbuf, "none", proplen);
1500 		} else {
1501 			if (literal)
1502 				(void) snprintf(propbuf, proplen, "%llu", val);
1503 			else
1504 				zfs_nicenum(val, propbuf, proplen);
1505 		}
1506 		break;
1507 
1508 	case ZFS_PROP_COMPRESSRATIO:
1509 		if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
1510 			return (-1);
1511 		(void) snprintf(propbuf, proplen, "%lld.%02lldx", val / 100,
1512 		    val % 100);
1513 		break;
1514 
1515 	case ZFS_PROP_TYPE:
1516 		switch (zhp->zfs_type) {
1517 		case ZFS_TYPE_FILESYSTEM:
1518 			str = "filesystem";
1519 			break;
1520 		case ZFS_TYPE_VOLUME:
1521 			str = "volume";
1522 			break;
1523 		case ZFS_TYPE_SNAPSHOT:
1524 			str = "snapshot";
1525 			break;
1526 		default:
1527 			abort();
1528 		}
1529 		(void) snprintf(propbuf, proplen, "%s", str);
1530 		break;
1531 
1532 	case ZFS_PROP_MOUNTED:
1533 		/*
1534 		 * The 'mounted' property is a pseudo-property that described
1535 		 * whether the filesystem is currently mounted.  Even though
1536 		 * it's a boolean value, the typical values of "on" and "off"
1537 		 * don't make sense, so we translate to "yes" and "no".
1538 		 */
1539 		if (get_numeric_property(zhp, ZFS_PROP_MOUNTED,
1540 		    src, &source, &val) != 0)
1541 			return (-1);
1542 		if (val)
1543 			(void) strlcpy(propbuf, "yes", proplen);
1544 		else
1545 			(void) strlcpy(propbuf, "no", proplen);
1546 		break;
1547 
1548 	case ZFS_PROP_NAME:
1549 		/*
1550 		 * The 'name' property is a pseudo-property derived from the
1551 		 * dataset name.  It is presented as a real property to simplify
1552 		 * consumers.
1553 		 */
1554 		(void) strlcpy(propbuf, zhp->zfs_name, proplen);
1555 		break;
1556 
1557 	default:
1558 		abort();
1559 	}
1560 
1561 	get_source(zhp, src, source, statbuf, statlen);
1562 
1563 	return (0);
1564 }
1565 
1566 /*
1567  * Utility function to get the given numeric property.  Does no validation that
1568  * the given property is the appropriate type; should only be used with
1569  * hard-coded property types.
1570  */
1571 uint64_t
1572 zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
1573 {
1574 	char *source;
1575 	zfs_source_t sourcetype = ZFS_SRC_NONE;
1576 	uint64_t val;
1577 
1578 	(void) get_numeric_property(zhp, prop, &sourcetype, &source, &val);
1579 
1580 	return (val);
1581 }
1582 
1583 /*
1584  * Similar to zfs_prop_get(), but returns the value as an integer.
1585  */
1586 int
1587 zfs_prop_get_numeric(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t *value,
1588     zfs_source_t *src, char *statbuf, size_t statlen)
1589 {
1590 	char *source;
1591 
1592 	/*
1593 	 * Check to see if this property applies to our object
1594 	 */
1595 	if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
1596 		return (zfs_error(zhp->zfs_hdl, EZFS_PROPTYPE,
1597 		    dgettext(TEXT_DOMAIN, "cannot get property '%s'"),
1598 		    zfs_prop_to_name(prop)));
1599 
1600 	if (src)
1601 		*src = ZFS_SRC_NONE;
1602 
1603 	if (get_numeric_property(zhp, prop, src, &source, value) != 0)
1604 		return (-1);
1605 
1606 	get_source(zhp, src, source, statbuf, statlen);
1607 
1608 	return (0);
1609 }
1610 
1611 /*
1612  * Returns the name of the given zfs handle.
1613  */
1614 const char *
1615 zfs_get_name(const zfs_handle_t *zhp)
1616 {
1617 	return (zhp->zfs_name);
1618 }
1619 
1620 /*
1621  * Returns the type of the given zfs handle.
1622  */
1623 zfs_type_t
1624 zfs_get_type(const zfs_handle_t *zhp)
1625 {
1626 	return (zhp->zfs_type);
1627 }
1628 
1629 /*
1630  * Iterate over all child filesystems
1631  */
1632 int
1633 zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data)
1634 {
1635 	zfs_cmd_t zc = { 0 };
1636 	zfs_handle_t *nzhp;
1637 	int ret;
1638 
1639 	for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1640 	    ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DATASET_LIST_NEXT, &zc) == 0;
1641 	    (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) {
1642 		/*
1643 		 * Ignore private dataset names.
1644 		 */
1645 		if (dataset_name_hidden(zc.zc_name))
1646 			continue;
1647 
1648 		/*
1649 		 * Silently ignore errors, as the only plausible explanation is
1650 		 * that the pool has since been removed.
1651 		 */
1652 		if ((nzhp = make_dataset_handle(zhp->zfs_hdl,
1653 		    zc.zc_name)) == NULL)
1654 			continue;
1655 
1656 		if ((ret = func(nzhp, data)) != 0)
1657 			return (ret);
1658 	}
1659 
1660 	/*
1661 	 * An errno value of ESRCH indicates normal completion.  If ENOENT is
1662 	 * returned, then the underlying dataset has been removed since we
1663 	 * obtained the handle.
1664 	 */
1665 	if (errno != ESRCH && errno != ENOENT)
1666 		return (zfs_standard_error(zhp->zfs_hdl, errno,
1667 		    dgettext(TEXT_DOMAIN, "cannot iterate filesystems")));
1668 
1669 	return (0);
1670 }
1671 
1672 /*
1673  * Iterate over all snapshots
1674  */
1675 int
1676 zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data)
1677 {
1678 	zfs_cmd_t zc = { 0 };
1679 	zfs_handle_t *nzhp;
1680 	int ret;
1681 
1682 	for ((void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1683 	    ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SNAPSHOT_LIST_NEXT,
1684 	    &zc) == 0;
1685 	    (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name))) {
1686 
1687 		if ((nzhp = make_dataset_handle(zhp->zfs_hdl,
1688 		    zc.zc_name)) == NULL)
1689 			continue;
1690 
1691 		if ((ret = func(nzhp, data)) != 0)
1692 			return (ret);
1693 	}
1694 
1695 	/*
1696 	 * An errno value of ESRCH indicates normal completion.  If ENOENT is
1697 	 * returned, then the underlying dataset has been removed since we
1698 	 * obtained the handle.  Silently ignore this case, and return success.
1699 	 */
1700 	if (errno != ESRCH && errno != ENOENT)
1701 		return (zfs_standard_error(zhp->zfs_hdl, errno,
1702 		    dgettext(TEXT_DOMAIN, "cannot iterate filesystems")));
1703 
1704 	return (0);
1705 }
1706 
1707 /*
1708  * Iterate over all children, snapshots and filesystems
1709  */
1710 int
1711 zfs_iter_children(zfs_handle_t *zhp, zfs_iter_f func, void *data)
1712 {
1713 	int ret;
1714 
1715 	if ((ret = zfs_iter_filesystems(zhp, func, data)) != 0)
1716 		return (ret);
1717 
1718 	return (zfs_iter_snapshots(zhp, func, data));
1719 }
1720 
1721 /*
1722  * Given a complete name, return just the portion that refers to the parent.
1723  * Can return NULL if this is a pool.
1724  */
1725 static int
1726 parent_name(const char *path, char *buf, size_t buflen)
1727 {
1728 	char *loc;
1729 
1730 	if ((loc = strrchr(path, '/')) == NULL)
1731 		return (-1);
1732 
1733 	(void) strncpy(buf, path, MIN(buflen, loc - path));
1734 	buf[loc - path] = '\0';
1735 
1736 	return (0);
1737 }
1738 
1739 /*
1740  * Checks to make sure that the given path has a parent, and that it exists.
1741  */
1742 static int
1743 check_parents(libzfs_handle_t *hdl, const char *path)
1744 {
1745 	zfs_cmd_t zc = { 0 };
1746 	char parent[ZFS_MAXNAMELEN];
1747 	char *slash;
1748 	zfs_handle_t *zhp;
1749 	char errbuf[1024];
1750 
1751 	(void) snprintf(errbuf, sizeof (errbuf), "cannot create '%s'",
1752 	    path);
1753 
1754 	/* get parent, and check to see if this is just a pool */
1755 	if (parent_name(path, parent, sizeof (parent)) != 0) {
1756 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1757 		    "missing dataset name"));
1758 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
1759 	}
1760 
1761 	/* check to see if the pool exists */
1762 	if ((slash = strchr(parent, '/')) == NULL)
1763 		slash = parent + strlen(parent);
1764 	(void) strncpy(zc.zc_name, parent, slash - parent);
1765 	zc.zc_name[slash - parent] = '\0';
1766 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) != 0 &&
1767 	    errno == ENOENT) {
1768 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1769 		    "no such pool '%s'"), zc.zc_name);
1770 		return (zfs_error(hdl, EZFS_NOENT, errbuf));
1771 	}
1772 
1773 	/* check to see if the parent dataset exists */
1774 	if ((zhp = make_dataset_handle(hdl, parent)) == NULL) {
1775 		switch (errno) {
1776 		case ENOENT:
1777 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1778 			    "parent does not exist"));
1779 			return (zfs_error(hdl, EZFS_NOENT, errbuf));
1780 
1781 		default:
1782 			return (zfs_standard_error(hdl, errno, errbuf));
1783 		}
1784 	}
1785 
1786 	/* we are in a non-global zone, but parent is in the global zone */
1787 	if (getzoneid() != GLOBAL_ZONEID &&
1788 	    !zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
1789 		(void) zfs_standard_error(hdl, EPERM, errbuf);
1790 		zfs_close(zhp);
1791 		return (-1);
1792 	}
1793 
1794 	/* make sure parent is a filesystem */
1795 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
1796 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1797 		    "parent is not a filesystem"));
1798 		(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
1799 		zfs_close(zhp);
1800 		return (-1);
1801 	}
1802 
1803 	zfs_close(zhp);
1804 	return (0);
1805 }
1806 
1807 /*
1808  * Create a new filesystem or volume.  'sizestr' and 'blocksizestr' are used
1809  * only for volumes, and indicate the size and blocksize of the volume.
1810  */
1811 int
1812 zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
1813 	const char *sizestr, const char *blocksizestr)
1814 {
1815 	zfs_cmd_t zc = { 0 };
1816 	int ret;
1817 	uint64_t size = 0;
1818 	uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
1819 	char errbuf[1024];
1820 
1821 	/* convert sizestr into integer size */
1822 	if (sizestr != NULL && nicestrtonum(hdl, sizestr, &size) != 0)
1823 		return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1824 		    "bad volume size '%s'"), sizestr));
1825 
1826 	/* convert blocksizestr into integer blocksize */
1827 	if (blocksizestr != NULL && nicestrtonum(hdl, blocksizestr,
1828 	    &blocksize) != 0)
1829 		return (zfs_error(hdl, EZFS_BADPROP, dgettext(TEXT_DOMAIN,
1830 		    "bad volume blocksize '%s'"), blocksizestr));
1831 
1832 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
1833 	    "cannot create '%s'"), path);
1834 
1835 	/* validate the path, taking care to note the extended error message */
1836 	if (!zfs_validate_name(hdl, path, type))
1837 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
1838 
1839 	/* validate parents exist */
1840 	if (check_parents(hdl, path) != 0)
1841 		return (-1);
1842 
1843 	/*
1844 	 * The failure modes when creating a dataset of a different type over
1845 	 * one that already exists is a little strange.  In particular, if you
1846 	 * try to create a dataset on top of an existing dataset, the ioctl()
1847 	 * will return ENOENT, not EEXIST.  To prevent this from happening, we
1848 	 * first try to see if the dataset exists.
1849 	 */
1850 	(void) strlcpy(zc.zc_name, path, sizeof (zc.zc_name));
1851 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0) {
1852 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1853 		    "dataset already exists"));
1854 		return (zfs_error(hdl, EZFS_EXISTS, errbuf));
1855 	}
1856 
1857 	if (type == ZFS_TYPE_VOLUME)
1858 		zc.zc_objset_type = DMU_OST_ZVOL;
1859 	else
1860 		zc.zc_objset_type = DMU_OST_ZFS;
1861 
1862 	if (type == ZFS_TYPE_VOLUME) {
1863 		/*
1864 		 * If we are creating a volume, the size and block size must
1865 		 * satisfy a few restraints.  First, the blocksize must be a
1866 		 * valid block size between SPA_{MIN,MAX}BLOCKSIZE.  Second, the
1867 		 * volsize must be a multiple of the block size, and cannot be
1868 		 * zero.
1869 		 */
1870 		if (size == 0) {
1871 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1872 			    "cannot be zero"));
1873 			return (zfs_error(hdl, EZFS_BADPROP,
1874 			    dgettext(TEXT_DOMAIN, "bad volume size '%s'"),
1875 			    sizestr));
1876 		}
1877 
1878 		if (blocksize < SPA_MINBLOCKSIZE ||
1879 		    blocksize > SPA_MAXBLOCKSIZE || !ISP2(blocksize)) {
1880 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1881 			    "must be power of 2 from %u to %uk"),
1882 			    (uint_t)SPA_MINBLOCKSIZE,
1883 			    (uint_t)SPA_MAXBLOCKSIZE >> 10);
1884 			return (zfs_error(hdl, EZFS_BADPROP,
1885 			    dgettext(TEXT_DOMAIN,
1886 			    "bad volume block size '%s'"), blocksizestr));
1887 		}
1888 
1889 		if (size % blocksize != 0) {
1890 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1891 			    "must be a multiple of volume block size"));
1892 			return (zfs_error(hdl, EZFS_BADPROP,
1893 			    dgettext(TEXT_DOMAIN, "bad volume size '%s'"),
1894 			    sizestr));
1895 		}
1896 
1897 		zc.zc_volsize = size;
1898 		zc.zc_volblocksize = blocksize;
1899 	}
1900 
1901 	/* create the dataset */
1902 	ret = ioctl(hdl->libzfs_fd, ZFS_IOC_CREATE, &zc);
1903 
1904 	if (ret == 0 && type == ZFS_TYPE_VOLUME)
1905 		ret = zvol_create_link(hdl, path);
1906 
1907 	/* check for failure */
1908 	if (ret != 0) {
1909 		char parent[ZFS_MAXNAMELEN];
1910 		(void) parent_name(path, parent, sizeof (parent));
1911 
1912 		switch (errno) {
1913 		case ENOENT:
1914 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1915 			    "no such parent '%s'"), parent);
1916 			return (zfs_error(hdl, EZFS_NOENT, errbuf));
1917 
1918 		case EINVAL:
1919 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1920 			    "parent '%s' is not a filesysem"), parent);
1921 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
1922 
1923 		case EDOM:
1924 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1925 			    "must be power of 2 from %u to %uk"),
1926 			    (uint_t)SPA_MINBLOCKSIZE,
1927 			    (uint_t)SPA_MAXBLOCKSIZE >> 10);
1928 
1929 			return (zfs_error(hdl, EZFS_BADPROP,
1930 			    dgettext(TEXT_DOMAIN, "bad block size '%s'"),
1931 			    blocksizestr ? blocksizestr : "<unknown>"));
1932 
1933 #ifdef _ILP32
1934 		case EOVERFLOW:
1935 			/*
1936 			 * This platform can't address a volume this big.
1937 			 */
1938 			if (type == ZFS_TYPE_VOLUME)
1939 				return (zfs_error(hdl, EZFS_VOLTOOBIG,
1940 				    errbuf));
1941 #endif
1942 			/* FALLTHROUGH */
1943 		default:
1944 			return (zfs_standard_error(hdl, errno, errbuf));
1945 		}
1946 	}
1947 
1948 	return (0);
1949 }
1950 
1951 /*
1952  * Destroys the given dataset.  The caller must make sure that the filesystem
1953  * isn't mounted, and that there are no active dependents.
1954  */
1955 int
1956 zfs_destroy(zfs_handle_t *zhp)
1957 {
1958 	zfs_cmd_t zc = { 0 };
1959 	int ret;
1960 
1961 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
1962 
1963 	/*
1964 	 * We use the check for 'zfs_volblocksize' instead of ZFS_TYPE_VOLUME
1965 	 * so that we do the right thing for snapshots of volumes.
1966 	 */
1967 	if (zhp->zfs_volblocksize != 0) {
1968 		if (zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0)
1969 			return (-1);
1970 
1971 		zc.zc_objset_type = DMU_OST_ZVOL;
1972 	} else {
1973 		zc.zc_objset_type = DMU_OST_ZFS;
1974 	}
1975 
1976 	ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY, &zc);
1977 	if (ret != 0) {
1978 		return (zfs_standard_error(zhp->zfs_hdl, errno,
1979 		    dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
1980 		    zhp->zfs_name));
1981 	}
1982 
1983 	remove_mountpoint(zhp);
1984 
1985 	return (0);
1986 }
1987 
1988 struct destroydata {
1989 	char *snapname;
1990 	boolean_t gotone;
1991 };
1992 
1993 static int
1994 zfs_remove_link_cb(zfs_handle_t *zhp, void *arg)
1995 {
1996 	struct destroydata *dd = arg;
1997 	zfs_handle_t *szhp;
1998 	char name[ZFS_MAXNAMELEN];
1999 
2000 	(void) strcpy(name, zhp->zfs_name);
2001 	(void) strcat(name, "@");
2002 	(void) strcat(name, dd->snapname);
2003 
2004 	szhp = make_dataset_handle(zhp->zfs_hdl, name);
2005 	if (szhp) {
2006 		dd->gotone = B_TRUE;
2007 		zfs_close(szhp);
2008 	}
2009 
2010 	if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
2011 		(void) zvol_remove_link(zhp->zfs_hdl, name);
2012 		/*
2013 		 * NB: this is simply a best-effort.  We don't want to
2014 		 * return an error, because then we wouldn't visit all
2015 		 * the volumes.
2016 		 */
2017 	}
2018 
2019 	return (zfs_iter_filesystems(zhp, zfs_remove_link_cb, arg));
2020 }
2021 
2022 /*
2023  * Destroys all snapshots with the given name in zhp & descendants.
2024  */
2025 int
2026 zfs_destroy_snaps(zfs_handle_t *zhp, char *snapname)
2027 {
2028 	zfs_cmd_t zc = { 0 };
2029 	int ret;
2030 	struct destroydata dd = { 0 };
2031 
2032 	dd.snapname = snapname;
2033 	(void) zfs_remove_link_cb(zhp, &dd);
2034 
2035 	if (!dd.gotone) {
2036 		return (zfs_standard_error(zhp->zfs_hdl, ENOENT,
2037 		    dgettext(TEXT_DOMAIN, "cannot destroy '%s@%s'"),
2038 		    zhp->zfs_name, snapname));
2039 	}
2040 
2041 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2042 	(void) strlcpy(zc.zc_prop_value, snapname, sizeof (zc.zc_prop_value));
2043 
2044 	ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY_SNAPS, &zc);
2045 	if (ret != 0) {
2046 		char errbuf[1024];
2047 
2048 		(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2049 		    "cannot destroy '%s@%s'"), zc.zc_name, snapname);
2050 
2051 		switch (errno) {
2052 		case EEXIST:
2053 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2054 			    "snapshot is cloned"));
2055 			return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, errbuf));
2056 
2057 		default:
2058 			return (zfs_standard_error(zhp->zfs_hdl, errno,
2059 			    errbuf));
2060 		}
2061 	}
2062 
2063 	return (0);
2064 }
2065 
2066 /*
2067  * Clones the given dataset.  The target must be of the same type as the source.
2068  */
2069 int
2070 zfs_clone(zfs_handle_t *zhp, const char *target)
2071 {
2072 	zfs_cmd_t zc = { 0 };
2073 	char parent[ZFS_MAXNAMELEN];
2074 	int ret;
2075 	char errbuf[1024];
2076 	libzfs_handle_t *hdl = zhp->zfs_hdl;
2077 
2078 	assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
2079 
2080 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2081 	    "cannot create '%s'"), target);
2082 
2083 	/* validate the target name */
2084 	if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM))
2085 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2086 
2087 	/* validate parents exist */
2088 	if (check_parents(zhp->zfs_hdl, target) != 0)
2089 		return (-1);
2090 
2091 	(void) parent_name(target, parent, sizeof (parent));
2092 
2093 	/* do the clone */
2094 	if (zhp->zfs_volblocksize != 0)
2095 		zc.zc_objset_type = DMU_OST_ZVOL;
2096 	else
2097 		zc.zc_objset_type = DMU_OST_ZFS;
2098 
2099 	(void) strlcpy(zc.zc_name, target, sizeof (zc.zc_name));
2100 	(void) strlcpy(zc.zc_filename, zhp->zfs_name, sizeof (zc.zc_filename));
2101 	ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_CREATE, &zc);
2102 
2103 	if (ret != 0) {
2104 		switch (errno) {
2105 
2106 		case ENOENT:
2107 			/*
2108 			 * The parent doesn't exist.  We should have caught this
2109 			 * above, but there may a race condition that has since
2110 			 * destroyed the parent.
2111 			 *
2112 			 * At this point, we don't know whether it's the source
2113 			 * that doesn't exist anymore, or whether the target
2114 			 * dataset doesn't exist.
2115 			 */
2116 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2117 			    "no such parent '%s'"), parent);
2118 			return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));
2119 
2120 		case EXDEV:
2121 			zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2122 			    "source and target pools differ"));
2123 			return (zfs_error(zhp->zfs_hdl, EZFS_CROSSTARGET,
2124 			    errbuf));
2125 
2126 		default:
2127 			return (zfs_standard_error(zhp->zfs_hdl, errno,
2128 			    errbuf));
2129 		}
2130 	} else if (zhp->zfs_volblocksize != 0) {
2131 		ret = zvol_create_link(zhp->zfs_hdl, target);
2132 	}
2133 
2134 	return (ret);
2135 }
2136 
2137 typedef struct promote_data {
2138 	char cb_mountpoint[MAXPATHLEN];
2139 	const char *cb_target;
2140 	const char *cb_errbuf;
2141 	uint64_t cb_pivot_txg;
2142 } promote_data_t;
2143 
2144 static int
2145 promote_snap_cb(zfs_handle_t *zhp, void *data)
2146 {
2147 	promote_data_t *pd = data;
2148 	zfs_handle_t *szhp;
2149 	char snapname[MAXPATHLEN];
2150 
2151 	/* We don't care about snapshots after the pivot point */
2152 	if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > pd->cb_pivot_txg)
2153 		return (0);
2154 
2155 	/* Remove the device link if it's a zvol. */
2156 	if (zhp->zfs_volblocksize != 0)
2157 		(void) zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name);
2158 
2159 	/* Check for conflicting names */
2160 	(void) strcpy(snapname, pd->cb_target);
2161 	(void) strcat(snapname, strchr(zhp->zfs_name, '@'));
2162 	szhp = make_dataset_handle(zhp->zfs_hdl, snapname);
2163 	if (szhp != NULL) {
2164 		zfs_close(szhp);
2165 		zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
2166 		    "snapshot name '%s' from origin \n"
2167 		    "conflicts with '%s' from target"),
2168 		    zhp->zfs_name, snapname);
2169 		return (zfs_error(zhp->zfs_hdl, EZFS_EXISTS, pd->cb_errbuf));
2170 	}
2171 	return (0);
2172 }
2173 
2174 static int
2175 promote_snap_done_cb(zfs_handle_t *zhp, void *data)
2176 {
2177 	promote_data_t *pd = data;
2178 
2179 	/* We don't care about snapshots after the pivot point */
2180 	if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > pd->cb_pivot_txg)
2181 		return (0);
2182 
2183 	/* Create the device link if it's a zvol. */
2184 	if (zhp->zfs_volblocksize != 0)
2185 		(void) zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
2186 
2187 	return (0);
2188 }
2189 
2190 /*
2191  * Promotes the given clone fs to be the clone parent.
2192  */
2193 int
2194 zfs_promote(zfs_handle_t *zhp)
2195 {
2196 	libzfs_handle_t *hdl = zhp->zfs_hdl;
2197 	zfs_cmd_t zc = { 0 };
2198 	char parent[MAXPATHLEN];
2199 	char *cp;
2200 	int ret;
2201 	zfs_handle_t *pzhp;
2202 	promote_data_t pd;
2203 	char errbuf[1024];
2204 
2205 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2206 	    "cannot promote '%s'"), zhp->zfs_name);
2207 
2208 	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
2209 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2210 		    "snapshots can not be promoted"));
2211 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
2212 	}
2213 
2214 	(void) strcpy(parent, zhp->zfs_dmustats.dds_clone_of);
2215 	if (parent[0] == '\0') {
2216 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2217 		    "not a cloned filesystem"));
2218 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
2219 	}
2220 	cp = strchr(parent, '@');
2221 	*cp = '\0';
2222 
2223 	/* Walk the snapshots we will be moving */
2224 	pzhp = zfs_open(hdl, zhp->zfs_dmustats.dds_clone_of, ZFS_TYPE_SNAPSHOT);
2225 	if (pzhp == NULL)
2226 		return (-1);
2227 	pd.cb_pivot_txg = zfs_prop_get_int(pzhp, ZFS_PROP_CREATETXG);
2228 	zfs_close(pzhp);
2229 	pd.cb_target = zhp->zfs_name;
2230 	pd.cb_errbuf = errbuf;
2231 	pzhp = zfs_open(hdl, parent, ZFS_TYPE_ANY);
2232 	if (pzhp == NULL)
2233 		return (-1);
2234 	(void) zfs_prop_get(pzhp, ZFS_PROP_MOUNTPOINT, pd.cb_mountpoint,
2235 	    sizeof (pd.cb_mountpoint), NULL, NULL, 0, FALSE);
2236 	ret = zfs_iter_snapshots(pzhp, promote_snap_cb, &pd);
2237 	if (ret != 0) {
2238 		zfs_close(pzhp);
2239 		return (-1);
2240 	}
2241 
2242 	/* issue the ioctl */
2243 	(void) strlcpy(zc.zc_prop_value, zhp->zfs_dmustats.dds_clone_of,
2244 	    sizeof (zc.zc_prop_value));
2245 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2246 	ret = ioctl(hdl->libzfs_fd, ZFS_IOC_PROMOTE, &zc);
2247 
2248 	if (ret != 0) {
2249 		int save_errno = errno;
2250 
2251 		(void) zfs_iter_snapshots(pzhp, promote_snap_done_cb, &pd);
2252 		zfs_close(pzhp);
2253 
2254 		switch (save_errno) {
2255 		case EEXIST:
2256 			/*
2257 			 * There is a conflicting snapshot name.  We
2258 			 * should have caught this above, but they could
2259 			 * have renamed something in the mean time.
2260 			 */
2261 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2262 			    "conflicting snapshot name from parent '%s'"),
2263 			    parent);
2264 			return (zfs_error(hdl, EZFS_EXISTS, errbuf));
2265 
2266 		default:
2267 			return (zfs_standard_error(hdl, save_errno, errbuf));
2268 		}
2269 	} else {
2270 		(void) zfs_iter_snapshots(zhp, promote_snap_done_cb, &pd);
2271 	}
2272 
2273 	zfs_close(pzhp);
2274 	return (ret);
2275 }
2276 
2277 static int
2278 zfs_create_link_cb(zfs_handle_t *zhp, void *arg)
2279 {
2280 	char *snapname = arg;
2281 
2282 	if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
2283 		char name[MAXPATHLEN];
2284 
2285 		(void) strcpy(name, zhp->zfs_name);
2286 		(void) strcat(name, "@");
2287 		(void) strcat(name, snapname);
2288 		(void) zvol_create_link(zhp->zfs_hdl, name);
2289 		/*
2290 		 * NB: this is simply a best-effort.  We don't want to
2291 		 * return an error, because then we wouldn't visit all
2292 		 * the volumes.
2293 		 */
2294 	}
2295 	return (zfs_iter_filesystems(zhp, zfs_create_link_cb, snapname));
2296 }
2297 
2298 /*
2299  * Takes a snapshot of the given dataset
2300  */
2301 int
2302 zfs_snapshot(libzfs_handle_t *hdl, const char *path, boolean_t recursive)
2303 {
2304 	const char *delim;
2305 	char *parent;
2306 	zfs_handle_t *zhp;
2307 	zfs_cmd_t zc = { 0 };
2308 	int ret;
2309 	char errbuf[1024];
2310 
2311 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2312 	    "cannot snapshot '%s'"), path);
2313 
2314 	/* validate the target name */
2315 	if (!zfs_validate_name(hdl, path, ZFS_TYPE_SNAPSHOT))
2316 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2317 
2318 	/* make sure the parent exists and is of the appropriate type */
2319 	delim = strchr(path, '@');
2320 	if ((parent = zfs_alloc(hdl, delim - path + 1)) == NULL)
2321 		return (-1);
2322 	(void) strncpy(parent, path, delim - path);
2323 	parent[delim - path] = '\0';
2324 
2325 	if ((zhp = zfs_open(hdl, parent, ZFS_TYPE_FILESYSTEM |
2326 	    ZFS_TYPE_VOLUME)) == NULL) {
2327 		free(parent);
2328 		return (-1);
2329 	}
2330 
2331 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2332 	(void) strlcpy(zc.zc_prop_value, delim+1, sizeof (zc.zc_prop_value));
2333 	zc.zc_cookie = recursive;
2334 	ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_SNAPSHOT, &zc);
2335 
2336 	/*
2337 	 * if it was recursive, the one that actually failed will be in
2338 	 * zc.zc_name.
2339 	 */
2340 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2341 	    "cannot create snapshot '%s@%s'"), zc.zc_name, zc.zc_prop_value);
2342 	if (ret == 0 && recursive) {
2343 		(void) zfs_iter_filesystems(zhp,
2344 		    zfs_create_link_cb, (char *)delim+1);
2345 	}
2346 	if (ret == 0 && zhp->zfs_type == ZFS_TYPE_VOLUME) {
2347 		ret = zvol_create_link(zhp->zfs_hdl, path);
2348 		if (ret != 0) {
2349 			(void) ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_DESTROY,
2350 			    &zc);
2351 		}
2352 	}
2353 
2354 	if (ret != 0)
2355 		(void) zfs_standard_error(hdl, errno, errbuf);
2356 
2357 	free(parent);
2358 	zfs_close(zhp);
2359 
2360 	return (ret);
2361 }
2362 
2363 /*
2364  * Dumps a backup of tosnap, incremental from fromsnap if it isn't NULL.
2365  */
2366 int
2367 zfs_send(zfs_handle_t *zhp_to, zfs_handle_t *zhp_from)
2368 {
2369 	zfs_cmd_t zc = { 0 };
2370 	int ret;
2371 	char errbuf[1024];
2372 	libzfs_handle_t *hdl = zhp_to->zfs_hdl;
2373 
2374 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2375 	    "cannot send '%s'"), zhp_to->zfs_name);
2376 
2377 	/* do the ioctl() */
2378 	(void) strlcpy(zc.zc_name, zhp_to->zfs_name, sizeof (zc.zc_name));
2379 	if (zhp_from) {
2380 		(void) strlcpy(zc.zc_prop_value, zhp_from->zfs_name,
2381 		    sizeof (zc.zc_name));
2382 	} else {
2383 		zc.zc_prop_value[0] = '\0';
2384 	}
2385 	zc.zc_cookie = STDOUT_FILENO;
2386 
2387 	ret = ioctl(zhp_to->zfs_hdl->libzfs_fd, ZFS_IOC_SENDBACKUP, &zc);
2388 	if (ret != 0) {
2389 		switch (errno) {
2390 
2391 		case EXDEV:
2392 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2393 			    "not an ealier snapshot from the same fs"));
2394 			return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
2395 
2396 		case EDQUOT:
2397 		case EFBIG:
2398 		case EIO:
2399 		case ENOLINK:
2400 		case ENOSPC:
2401 		case ENOSTR:
2402 		case ENXIO:
2403 		case EPIPE:
2404 		case ERANGE:
2405 		case EFAULT:
2406 		case EROFS:
2407 			zfs_error_aux(hdl, strerror(errno));
2408 			return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
2409 
2410 		default:
2411 			return (zfs_standard_error(hdl, errno, errbuf));
2412 		}
2413 	}
2414 
2415 	return (ret);
2416 }
2417 
2418 /*
2419  * Restores a backup of tosnap from stdin.
2420  */
2421 int
2422 zfs_receive(libzfs_handle_t *hdl, const char *tosnap, int isprefix,
2423     int verbose, int dryrun)
2424 {
2425 	zfs_cmd_t zc = { 0 };
2426 	time_t begin_time;
2427 	int ioctl_err, err, bytes, size;
2428 	char *cp;
2429 	dmu_replay_record_t drr;
2430 	struct drr_begin *drrb = &zc.zc_begin_record;
2431 	char errbuf[1024];
2432 
2433 	begin_time = time(NULL);
2434 
2435 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2436 	    "cannot receive"));
2437 
2438 	/* trim off snapname, if any */
2439 	(void) strcpy(zc.zc_name, tosnap);
2440 	cp = strchr(zc.zc_name, '@');
2441 	if (cp)
2442 		*cp = '\0';
2443 
2444 	/* read in the BEGIN record */
2445 	cp = (char *)&drr;
2446 	bytes = 0;
2447 	do {
2448 		size = read(STDIN_FILENO, cp, sizeof (drr) - bytes);
2449 		cp += size;
2450 		bytes += size;
2451 	} while (size > 0);
2452 
2453 	if (size < 0 || bytes != sizeof (drr)) {
2454 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
2455 		    "stream (failed to read first record)"));
2456 		return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
2457 	}
2458 
2459 	zc.zc_begin_record = drr.drr_u.drr_begin;
2460 
2461 	if (drrb->drr_magic != DMU_BACKUP_MAGIC &&
2462 	    drrb->drr_magic != BSWAP_64(DMU_BACKUP_MAGIC)) {
2463 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "invalid "
2464 		    "stream (bad magic number)"));
2465 		return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
2466 	}
2467 
2468 	if (drrb->drr_version != DMU_BACKUP_VERSION &&
2469 	    drrb->drr_version != BSWAP_64(DMU_BACKUP_VERSION)) {
2470 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "only version "
2471 		    "0x%llx is supported (stream is version 0x%llx)"),
2472 		    DMU_BACKUP_VERSION, drrb->drr_version);
2473 		return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
2474 	}
2475 
2476 	/*
2477 	 * Determine name of destination snapshot.
2478 	 */
2479 	(void) strcpy(zc.zc_filename, tosnap);
2480 	if (isprefix) {
2481 		if (strchr(tosnap, '@') != NULL) {
2482 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2483 			    "destination must be a filesystem"));
2484 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
2485 		}
2486 
2487 		cp = strchr(drr.drr_u.drr_begin.drr_toname, '/');
2488 		if (cp == NULL)
2489 			cp = drr.drr_u.drr_begin.drr_toname;
2490 		else
2491 			cp++;
2492 
2493 		(void) strcat(zc.zc_filename, "/");
2494 		(void) strcat(zc.zc_filename, cp);
2495 	} else if (strchr(tosnap, '@') == NULL) {
2496 		/*
2497 		 * they specified just a filesystem; tack on the
2498 		 * snapname from the backup.
2499 		 */
2500 		cp = strchr(drr.drr_u.drr_begin.drr_toname, '@');
2501 		if (cp == NULL || strlen(tosnap) + strlen(cp) >= MAXNAMELEN)
2502 			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2503 		(void) strcat(zc.zc_filename, cp);
2504 	}
2505 
2506 	if (drrb->drr_fromguid) {
2507 		zfs_handle_t *h;
2508 		/* incremental backup stream */
2509 
2510 		/* do the ioctl to the containing fs */
2511 		(void) strcpy(zc.zc_name, zc.zc_filename);
2512 		cp = strchr(zc.zc_name, '@');
2513 		*cp = '\0';
2514 
2515 		/* make sure destination fs exists */
2516 		h = zfs_open(hdl, zc.zc_name,
2517 		    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
2518 		if (h == NULL)
2519 			return (-1);
2520 		if (!dryrun) {
2521 			/* unmount destination fs or remove device link. */
2522 			if (h->zfs_type == ZFS_TYPE_FILESYSTEM) {
2523 				(void) zfs_unmount(h, NULL, 0);
2524 			} else {
2525 				(void) zvol_remove_link(hdl, h->zfs_name);
2526 			}
2527 		}
2528 		zfs_close(h);
2529 	} else {
2530 		/* full backup stream */
2531 
2532 		(void) strcpy(zc.zc_name, zc.zc_filename);
2533 
2534 		/* make sure they aren't trying to receive into the root */
2535 		if (strchr(zc.zc_name, '/') == NULL) {
2536 			cp = strchr(zc.zc_name, '@');
2537 			if (cp)
2538 				*cp = '\0';
2539 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2540 			    "destination '%s' already exists"), zc.zc_name);
2541 			return (zfs_error(hdl, EZFS_EXISTS, errbuf));
2542 		}
2543 
2544 		if (isprefix) {
2545 			zfs_handle_t *h;
2546 
2547 			/* make sure prefix exists */
2548 			h = zfs_open(hdl, tosnap, ZFS_TYPE_FILESYSTEM);
2549 			if (h == NULL)
2550 				return (-1);
2551 			zfs_close(h);
2552 
2553 			/* create any necessary ancestors up to prefix */
2554 			zc.zc_objset_type = DMU_OST_ZFS;
2555 
2556 			/*
2557 			 * zc.zc_name is now the full name of the snap
2558 			 * we're restoring into.  Attempt to create,
2559 			 * mount, and share any ancestor filesystems, up
2560 			 * to the one that was named.
2561 			 */
2562 			for (cp = zc.zc_name + strlen(tosnap) + 1;
2563 			    cp = strchr(cp, '/'); *cp = '/', cp++) {
2564 				const char *opname;
2565 				*cp = '\0';
2566 
2567 				opname = dgettext(TEXT_DOMAIN, "create");
2568 				if (zfs_create(hdl, zc.zc_name,
2569 				    ZFS_TYPE_FILESYSTEM, NULL, NULL) != 0) {
2570 					if (errno == EEXIST)
2571 						continue;
2572 					goto ancestorerr;
2573 				}
2574 
2575 				opname = dgettext(TEXT_DOMAIN, "open");
2576 				h = zfs_open(hdl, zc.zc_name,
2577 				    ZFS_TYPE_FILESYSTEM);
2578 				if (h == NULL)
2579 					goto ancestorerr;
2580 
2581 				opname = dgettext(TEXT_DOMAIN, "mount");
2582 				if (zfs_mount(h, NULL, 0) != 0)
2583 					goto ancestorerr;
2584 
2585 				opname = dgettext(TEXT_DOMAIN, "share");
2586 				if (zfs_share(h) != 0)
2587 					goto ancestorerr;
2588 
2589 				zfs_close(h);
2590 
2591 				continue;
2592 ancestorerr:
2593 				zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2594 				    "failed to %s ancestor '%s'"), opname,
2595 				    zc.zc_name);
2596 				return (zfs_error(hdl, EZFS_BADRESTORE,
2597 				    errbuf));
2598 			}
2599 		}
2600 
2601 		/* Make sure destination fs does not exist */
2602 		cp = strchr(zc.zc_name, '@');
2603 		*cp = '\0';
2604 		if (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0) {
2605 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2606 			    "destination '%s' exists"), zc.zc_name);
2607 			return (zfs_error(hdl, EZFS_EXISTS, errbuf));
2608 		}
2609 
2610 		/* Do the recvbackup ioctl to the fs's parent. */
2611 		cp = strrchr(zc.zc_name, '/');
2612 		*cp = '\0';
2613 	}
2614 
2615 	(void) strcpy(zc.zc_prop_value, tosnap);
2616 	zc.zc_cookie = STDIN_FILENO;
2617 	zc.zc_intsz = isprefix;
2618 	if (verbose) {
2619 		(void) printf("%s %s stream of %s into %s\n",
2620 		    dryrun ? "would receive" : "receiving",
2621 		    drrb->drr_fromguid ? "incremental" : "full",
2622 		    drr.drr_u.drr_begin.drr_toname,
2623 		    zc.zc_filename);
2624 		(void) fflush(stdout);
2625 	}
2626 	if (dryrun)
2627 		return (0);
2628 	err = ioctl_err = ioctl(hdl->libzfs_fd, ZFS_IOC_RECVBACKUP, &zc);
2629 	if (ioctl_err != 0) {
2630 		switch (errno) {
2631 		case ENODEV:
2632 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2633 			    "most recent snapshot does not match incremental "
2634 			    "source"));
2635 			(void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
2636 			break;
2637 		case ETXTBSY:
2638 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2639 			    "destination has been modified since most recent "
2640 			    "snapshot"));
2641 			(void) zfs_error(hdl, EZFS_BADRESTORE, errbuf);
2642 			break;
2643 		case EEXIST:
2644 			if (drrb->drr_fromguid == 0) {
2645 				/* it's the containing fs that exists */
2646 				cp = strchr(zc.zc_filename, '@');
2647 				*cp = '\0';
2648 			}
2649 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2650 			    "destination already exists"));
2651 			(void) zfs_error(hdl, EZFS_EXISTS, dgettext(TEXT_DOMAIN,
2652 			    "cannot restore to %s"), zc.zc_filename);
2653 			break;
2654 		case EINVAL:
2655 			(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
2656 			break;
2657 		case ECKSUM:
2658 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2659 			    "invalid stream (checksum mismatch)"));
2660 			(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
2661 			break;
2662 		default:
2663 			(void) zfs_standard_error(hdl, errno, errbuf);
2664 		}
2665 	}
2666 
2667 	/*
2668 	 * Mount or recreate the /dev links for the target filesystem
2669 	 * (if created, or if we tore them down to do an incremental
2670 	 * restore), and the /dev links for the new snapshot (if
2671 	 * created).
2672 	 */
2673 	cp = strchr(zc.zc_filename, '@');
2674 	if (cp && (ioctl_err == 0 || drrb->drr_fromguid)) {
2675 		zfs_handle_t *h;
2676 
2677 		*cp = '\0';
2678 		h = zfs_open(hdl, zc.zc_filename,
2679 		    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
2680 		*cp = '@';
2681 		if (h) {
2682 			if (h->zfs_type == ZFS_TYPE_FILESYSTEM) {
2683 				err = zfs_mount(h, NULL, 0);
2684 			} else {
2685 				err = zvol_create_link(hdl, h->zfs_name);
2686 				if (err == 0 && ioctl_err == 0)
2687 					err = zvol_create_link(hdl,
2688 					    zc.zc_filename);
2689 			}
2690 			zfs_close(h);
2691 		}
2692 	}
2693 
2694 	if (err || ioctl_err)
2695 		return (-1);
2696 
2697 	if (verbose) {
2698 		char buf1[64];
2699 		char buf2[64];
2700 		uint64_t bytes = zc.zc_cookie;
2701 		time_t delta = time(NULL) - begin_time;
2702 		if (delta == 0)
2703 			delta = 1;
2704 		zfs_nicenum(bytes, buf1, sizeof (buf1));
2705 		zfs_nicenum(bytes/delta, buf2, sizeof (buf1));
2706 
2707 		(void) printf("received %sb stream in %lu seconds (%sb/sec)\n",
2708 		    buf1, delta, buf2);
2709 	}
2710 	return (0);
2711 }
2712 
2713 /*
2714  * Destroy any more recent snapshots.  We invoke this callback on any dependents
2715  * of the snapshot first.  If the 'cb_dependent' member is non-zero, then this
2716  * is a dependent and we should just destroy it without checking the transaction
2717  * group.
2718  */
2719 typedef struct rollback_data {
2720 	const char	*cb_target;		/* the snapshot */
2721 	uint64_t	cb_create;		/* creation time reference */
2722 	prop_changelist_t *cb_clp;		/* changelist pointer */
2723 	int		cb_error;
2724 	boolean_t	cb_dependent;
2725 } rollback_data_t;
2726 
2727 static int
2728 rollback_destroy(zfs_handle_t *zhp, void *data)
2729 {
2730 	rollback_data_t *cbp = data;
2731 
2732 	if (!cbp->cb_dependent) {
2733 		if (strcmp(zhp->zfs_name, cbp->cb_target) != 0 &&
2734 		    zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
2735 		    zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
2736 		    cbp->cb_create) {
2737 
2738 			cbp->cb_dependent = B_TRUE;
2739 			if (zfs_iter_dependents(zhp, B_FALSE, rollback_destroy,
2740 			    cbp) != 0)
2741 				cbp->cb_error = 1;
2742 			cbp->cb_dependent = B_FALSE;
2743 
2744 			if (zfs_destroy(zhp) != 0)
2745 				cbp->cb_error = 1;
2746 			else
2747 				changelist_remove(zhp, cbp->cb_clp);
2748 		}
2749 	} else {
2750 		if (zfs_destroy(zhp) != 0)
2751 			cbp->cb_error = 1;
2752 		else
2753 			changelist_remove(zhp, cbp->cb_clp);
2754 	}
2755 
2756 	zfs_close(zhp);
2757 	return (0);
2758 }
2759 
2760 /*
2761  * Rollback the dataset to its latest snapshot.
2762  */
2763 static int
2764 do_rollback(zfs_handle_t *zhp)
2765 {
2766 	int ret;
2767 	zfs_cmd_t zc = { 0 };
2768 
2769 	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM ||
2770 	    zhp->zfs_type == ZFS_TYPE_VOLUME);
2771 
2772 	if (zhp->zfs_type == ZFS_TYPE_VOLUME &&
2773 	    zvol_remove_link(zhp->zfs_hdl, zhp->zfs_name) != 0)
2774 		return (-1);
2775 
2776 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2777 
2778 	if (zhp->zfs_volblocksize != 0)
2779 		zc.zc_objset_type = DMU_OST_ZVOL;
2780 	else
2781 		zc.zc_objset_type = DMU_OST_ZFS;
2782 
2783 	/*
2784 	 * We rely on the consumer to verify that there are no newer snapshots
2785 	 * for the given dataset.  Given these constraints, we can simply pass
2786 	 * the name on to the ioctl() call.  There is still an unlikely race
2787 	 * condition where the user has taken a snapshot since we verified that
2788 	 * this was the most recent.
2789 	 */
2790 	if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_ROLLBACK,
2791 	    &zc)) != 0) {
2792 		(void) zfs_standard_error(zhp->zfs_hdl, errno,
2793 		    dgettext(TEXT_DOMAIN, "cannot rollback '%s'"),
2794 		    zhp->zfs_name);
2795 	} else if (zhp->zfs_type == ZFS_TYPE_VOLUME) {
2796 		ret = zvol_create_link(zhp->zfs_hdl, zhp->zfs_name);
2797 	}
2798 
2799 	return (ret);
2800 }
2801 
2802 /*
2803  * Given a dataset, rollback to a specific snapshot, discarding any
2804  * data changes since then and making it the active dataset.
2805  *
2806  * Any snapshots more recent than the target are destroyed, along with
2807  * their dependents.
2808  */
2809 int
2810 zfs_rollback(zfs_handle_t *zhp, zfs_handle_t *snap, int flag)
2811 {
2812 	int ret;
2813 	rollback_data_t cb = { 0 };
2814 	prop_changelist_t *clp;
2815 
2816 	/*
2817 	 * Unmount all dependendents of the dataset and the dataset itself.
2818 	 * The list we need to gather is the same as for doing rename
2819 	 */
2820 	clp = changelist_gather(zhp, ZFS_PROP_NAME, flag ? MS_FORCE: 0);
2821 	if (clp == NULL)
2822 		return (-1);
2823 
2824 	if ((ret = changelist_prefix(clp)) != 0)
2825 		goto out;
2826 
2827 	/*
2828 	 * Destroy all recent snapshots and its dependends.
2829 	 */
2830 	cb.cb_target = snap->zfs_name;
2831 	cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
2832 	cb.cb_clp = clp;
2833 	(void) zfs_iter_children(zhp, rollback_destroy, &cb);
2834 
2835 	if ((ret = cb.cb_error) != 0) {
2836 		(void) changelist_postfix(clp);
2837 		goto out;
2838 	}
2839 
2840 	/*
2841 	 * Now that we have verified that the snapshot is the latest,
2842 	 * rollback to the given snapshot.
2843 	 */
2844 	ret = do_rollback(zhp);
2845 
2846 	if (ret != 0) {
2847 		(void) changelist_postfix(clp);
2848 		goto out;
2849 	}
2850 
2851 	/*
2852 	 * We only want to re-mount the filesystem if it was mounted in the
2853 	 * first place.
2854 	 */
2855 	ret = changelist_postfix(clp);
2856 
2857 out:
2858 	changelist_free(clp);
2859 	return (ret);
2860 }
2861 
2862 /*
2863  * Iterate over all dependents for a given dataset.  This includes both
2864  * hierarchical dependents (children) and data dependents (snapshots and
2865  * clones).  The bulk of the processing occurs in get_dependents() in
2866  * libzfs_graph.c.
2867  */
2868 int
2869 zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion,
2870     zfs_iter_f func, void *data)
2871 {
2872 	char **dependents;
2873 	size_t count;
2874 	int i;
2875 	zfs_handle_t *child;
2876 	int ret = 0;
2877 
2878 	if (get_dependents(zhp->zfs_hdl, allowrecursion, zhp->zfs_name,
2879 	    &dependents, &count) != 0)
2880 		return (-1);
2881 
2882 	for (i = 0; i < count; i++) {
2883 		if ((child = make_dataset_handle(zhp->zfs_hdl,
2884 		    dependents[i])) == NULL)
2885 			continue;
2886 
2887 		if ((ret = func(child, data)) != 0)
2888 			break;
2889 	}
2890 
2891 	for (i = 0; i < count; i++)
2892 		free(dependents[i]);
2893 	free(dependents);
2894 
2895 	return (ret);
2896 }
2897 
2898 /*
2899  * Renames the given dataset.
2900  */
2901 int
2902 zfs_rename(zfs_handle_t *zhp, const char *target)
2903 {
2904 	int ret;
2905 	zfs_cmd_t zc = { 0 };
2906 	char *delim;
2907 	prop_changelist_t *cl;
2908 	char parent[ZFS_MAXNAMELEN];
2909 	libzfs_handle_t *hdl = zhp->zfs_hdl;
2910 	char errbuf[1024];
2911 
2912 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
2913 	(void) strlcpy(zc.zc_prop_value, target, sizeof (zc.zc_prop_value));
2914 
2915 	/* if we have the same exact name, just return success */
2916 	if (strcmp(zhp->zfs_name, target) == 0)
2917 		return (0);
2918 
2919 	(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
2920 	    "cannot rename to '%s'"), target);
2921 
2922 	/*
2923 	 * Make sure the target name is valid
2924 	 */
2925 	if (!zfs_validate_name(hdl, target, zhp->zfs_type))
2926 		return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2927 
2928 	if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
2929 
2930 		if ((delim = strchr(target, '@')) == NULL) {
2931 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2932 			    "not a snapshot"));
2933 			return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
2934 		}
2935 
2936 		/*
2937 		 * Make sure we're renaming within the same dataset.
2938 		 */
2939 		if (strncmp(zhp->zfs_name, target, delim - target) != 0 ||
2940 		    zhp->zfs_name[delim - target] != '@') {
2941 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2942 			    "snapshots must be part of same dataset"));
2943 			return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
2944 		}
2945 
2946 		(void) strncpy(parent, target, delim - target);
2947 		parent[delim - target] = '\0';
2948 	} else {
2949 		/* validate parents */
2950 		if (check_parents(hdl, target) != 0)
2951 			return (-1);
2952 
2953 		(void) parent_name(target, parent, sizeof (parent));
2954 
2955 		/* make sure we're in the same pool */
2956 		verify((delim = strchr(target, '/')) != NULL);
2957 		if (strncmp(zhp->zfs_name, target, delim - target) != 0 ||
2958 		    zhp->zfs_name[delim - target] != '/') {
2959 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2960 			    "datasets must be within same pool"));
2961 			return (zfs_error(hdl, EZFS_CROSSTARGET, errbuf));
2962 		}
2963 
2964 		/* new name cannot be a child of the current dataset name */
2965 		if (strncmp(parent, zhp->zfs_name,
2966 			    strlen(zhp->zfs_name)) == 0) {
2967 			zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2968 			    "New dataset name cannot be a descendent of "
2969 			    "current dataset name"));
2970 			return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
2971 		}
2972 	}
2973 
2974 	(void) snprintf(errbuf, sizeof (errbuf),
2975 	    dgettext(TEXT_DOMAIN, "cannot rename '%s'"), zhp->zfs_name);
2976 
2977 	if (getzoneid() == GLOBAL_ZONEID &&
2978 	    zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) {
2979 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2980 		    "dataset is used in a non-global zone"));
2981 		return (zfs_error(hdl, EZFS_ZONED, errbuf));
2982 	}
2983 
2984 	if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0)) == NULL)
2985 		return (-1);
2986 
2987 	if (changelist_haszonedchild(cl)) {
2988 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
2989 		    "child dataset with inherited mountpoint is used "
2990 		    "in a non-global zone"));
2991 		ret = zfs_error(hdl, EZFS_ZONED, errbuf);
2992 		goto error;
2993 	}
2994 
2995 	if ((ret = changelist_prefix(cl)) != 0)
2996 		goto error;
2997 
2998 	if (zhp->zfs_volblocksize != 0)
2999 		zc.zc_objset_type = DMU_OST_ZVOL;
3000 	else
3001 		zc.zc_objset_type = DMU_OST_ZFS;
3002 
3003 	if ((ret = ioctl(zhp->zfs_hdl->libzfs_fd, ZFS_IOC_RENAME, &zc)) != 0) {
3004 		(void) zfs_standard_error(zhp->zfs_hdl, errno, errbuf);
3005 
3006 		/*
3007 		 * On failure, we still want to remount any filesystems that
3008 		 * were previously mounted, so we don't alter the system state.
3009 		 */
3010 		(void) changelist_postfix(cl);
3011 	} else {
3012 		changelist_rename(cl, zfs_get_name(zhp), target);
3013 
3014 		ret = changelist_postfix(cl);
3015 	}
3016 
3017 error:
3018 	changelist_free(cl);
3019 	return (ret);
3020 }
3021 
3022 /*
3023  * Given a zvol dataset, issue the ioctl to create the appropriate minor node,
3024  * poke devfsadm to create the /dev link, and then wait for the link to appear.
3025  */
3026 int
3027 zvol_create_link(libzfs_handle_t *hdl, const char *dataset)
3028 {
3029 	zfs_cmd_t zc = { 0 };
3030 	di_devlink_handle_t dhdl;
3031 
3032 	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
3033 
3034 	/*
3035 	 * Issue the appropriate ioctl.
3036 	 */
3037 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_CREATE_MINOR, &zc) != 0) {
3038 		switch (errno) {
3039 		case EEXIST:
3040 			/*
3041 			 * Silently ignore the case where the link already
3042 			 * exists.  This allows 'zfs volinit' to be run multiple
3043 			 * times without errors.
3044 			 */
3045 			return (0);
3046 
3047 		default:
3048 			return (zfs_standard_error(hdl, errno,
3049 			    dgettext(TEXT_DOMAIN, "cannot create device links "
3050 			    "for '%s'"), dataset));
3051 		}
3052 	}
3053 
3054 	/*
3055 	 * Call devfsadm and wait for the links to magically appear.
3056 	 */
3057 	if ((dhdl = di_devlink_init(ZFS_DRIVER, DI_MAKE_LINK)) == NULL) {
3058 		zfs_error_aux(hdl, strerror(errno));
3059 		(void) zfs_error(hdl, EZFS_DEVLINKS,
3060 		    dgettext(TEXT_DOMAIN, "cannot create device links "
3061 		    "for '%s'"), dataset);
3062 		(void) ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc);
3063 		return (-1);
3064 	} else {
3065 		(void) di_devlink_fini(&dhdl);
3066 	}
3067 
3068 	return (0);
3069 }
3070 
3071 /*
3072  * Remove a minor node for the given zvol and the associated /dev links.
3073  */
3074 int
3075 zvol_remove_link(libzfs_handle_t *hdl, const char *dataset)
3076 {
3077 	zfs_cmd_t zc = { 0 };
3078 
3079 	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
3080 
3081 	if (ioctl(hdl->libzfs_fd, ZFS_IOC_REMOVE_MINOR, &zc) != 0) {
3082 		switch (errno) {
3083 		case ENXIO:
3084 			/*
3085 			 * Silently ignore the case where the link no longer
3086 			 * exists, so that 'zfs volfini' can be run multiple
3087 			 * times without errors.
3088 			 */
3089 			return (0);
3090 
3091 		default:
3092 			return (zfs_standard_error(hdl, errno,
3093 			    dgettext(TEXT_DOMAIN, "cannot remove device "
3094 			    "links for '%s'"), dataset));
3095 		}
3096 	}
3097 
3098 	return (0);
3099 }
3100