xref: /titanic_52/usr/src/cmd/zfs/zfs_main.c (revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8)
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 <libgen.h>
32 #include <libintl.h>
33 #include <libuutil.h>
34 #include <locale.h>
35 #include <stddef.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <strings.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41 #include <zone.h>
42 #include <sys/mkdev.h>
43 #include <sys/mntent.h>
44 #include <sys/mnttab.h>
45 #include <sys/mount.h>
46 #include <sys/stat.h>
47 
48 #include <libzfs.h>
49 
50 #include "zfs_iter.h"
51 #include "zfs_util.h"
52 
53 libzfs_handle_t *g_zfs;
54 
55 static FILE *mnttab_file;
56 
57 static int zfs_do_clone(int argc, char **argv);
58 static int zfs_do_create(int argc, char **argv);
59 static int zfs_do_destroy(int argc, char **argv);
60 static int zfs_do_get(int argc, char **argv);
61 static int zfs_do_inherit(int argc, char **argv);
62 static int zfs_do_list(int argc, char **argv);
63 static int zfs_do_mount(int argc, char **argv);
64 static int zfs_do_rename(int argc, char **argv);
65 static int zfs_do_rollback(int argc, char **argv);
66 static int zfs_do_set(int argc, char **argv);
67 static int zfs_do_snapshot(int argc, char **argv);
68 static int zfs_do_unmount(int argc, char **argv);
69 static int zfs_do_share(int argc, char **argv);
70 static int zfs_do_unshare(int argc, char **argv);
71 static int zfs_do_send(int argc, char **argv);
72 static int zfs_do_receive(int argc, char **argv);
73 static int zfs_do_promote(int argc, char **argv);
74 
75 /*
76  * These libumem hooks provide a reasonable set of defaults for the allocator's
77  * debugging facilities.
78  */
79 const char *
80 _umem_debug_init()
81 {
82 	return ("default,verbose"); /* $UMEM_DEBUG setting */
83 }
84 
85 const char *
86 _umem_logging_init(void)
87 {
88 	return ("fail,contents"); /* $UMEM_LOGGING setting */
89 }
90 
91 typedef enum {
92 	HELP_CLONE,
93 	HELP_CREATE,
94 	HELP_DESTROY,
95 	HELP_GET,
96 	HELP_INHERIT,
97 	HELP_LIST,
98 	HELP_MOUNT,
99 	HELP_PROMOTE,
100 	HELP_RECEIVE,
101 	HELP_RENAME,
102 	HELP_ROLLBACK,
103 	HELP_SEND,
104 	HELP_SET,
105 	HELP_SHARE,
106 	HELP_SNAPSHOT,
107 	HELP_UNMOUNT,
108 	HELP_UNSHARE
109 } zfs_help_t;
110 
111 typedef struct zfs_command {
112 	const char	*name;
113 	int		(*func)(int argc, char **argv);
114 	zfs_help_t	usage;
115 } zfs_command_t;
116 
117 /*
118  * Master command table.  Each ZFS command has a name, associated function, and
119  * usage message.  The usage messages need to be internationalized, so we have
120  * to have a function to return the usage message based on a command index.
121  *
122  * These commands are organized according to how they are displayed in the usage
123  * message.  An empty command (one with a NULL name) indicates an empty line in
124  * the generic usage message.
125  */
126 static zfs_command_t command_table[] = {
127 	{ "create",	zfs_do_create,		HELP_CREATE		},
128 	{ "destroy",	zfs_do_destroy,		HELP_DESTROY		},
129 	{ NULL },
130 	{ "snapshot",	zfs_do_snapshot,	HELP_SNAPSHOT		},
131 	{ "rollback",	zfs_do_rollback,	HELP_ROLLBACK		},
132 	{ "clone",	zfs_do_clone,		HELP_CLONE		},
133 	{ "promote",	zfs_do_promote,		HELP_PROMOTE		},
134 	{ "rename",	zfs_do_rename,		HELP_RENAME		},
135 	{ NULL },
136 	{ "list",	zfs_do_list,		HELP_LIST		},
137 	{ NULL },
138 	{ "set",	zfs_do_set,		HELP_SET		},
139 	{ "get", 	zfs_do_get,		HELP_GET		},
140 	{ "inherit",	zfs_do_inherit,		HELP_INHERIT		},
141 	{ NULL },
142 	{ "mount",	zfs_do_mount,		HELP_MOUNT		},
143 	{ NULL },
144 	{ "unmount",	zfs_do_unmount,		HELP_UNMOUNT		},
145 	{ NULL },
146 	{ "share",	zfs_do_share,		HELP_SHARE		},
147 	{ NULL },
148 	{ "unshare",	zfs_do_unshare,		HELP_UNSHARE		},
149 	{ NULL },
150 	{ "send",	zfs_do_send,		HELP_SEND		},
151 	{ "receive",	zfs_do_receive,		HELP_RECEIVE		},
152 };
153 
154 #define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
155 
156 zfs_command_t *current_command;
157 
158 static const char *
159 get_usage(zfs_help_t idx)
160 {
161 	switch (idx) {
162 	case HELP_CLONE:
163 		return (gettext("\tclone <snapshot> <filesystem|volume>\n"));
164 	case HELP_CREATE:
165 		return (gettext("\tcreate [[-o property=value] ... ] "
166 		    "<filesystem>\n"
167 		    "\tcreate [-s] [-b blocksize] [[-o property=value] ...]\n"
168 		    "\t    -V <size> <volume>\n"));
169 	case HELP_DESTROY:
170 		return (gettext("\tdestroy [-rRf] "
171 		    "<filesystem|volume|snapshot>\n"));
172 	case HELP_GET:
173 		return (gettext("\tget [-rHp] [-o field[,field]...] "
174 		    "[-s source[,source]...]\n"
175 		    "\t    <all | property[,property]...> "
176 		    "[filesystem|volume|snapshot] ...\n"));
177 	case HELP_INHERIT:
178 		return (gettext("\tinherit [-r] <property> "
179 		    "<filesystem|volume> ...\n"));
180 	case HELP_LIST:
181 		return (gettext("\tlist [-rH] [-o property[,property]...] "
182 		    "[-t type[,type]...]\n"
183 		    "\t    [-s property [-s property]...]"
184 		    " [-S property [-S property]...]\n"
185 		    "\t    [filesystem|volume|snapshot] ...\n"));
186 	case HELP_MOUNT:
187 		return (gettext("\tmount\n"
188 		    "\tmount [-o opts] [-O] -a\n"
189 		    "\tmount [-o opts] [-O] <filesystem>\n"));
190 	case HELP_PROMOTE:
191 		return (gettext("\tpromote <clone filesystem>\n"));
192 	case HELP_RECEIVE:
193 		return (gettext("\treceive [-vnF] <filesystem|volume|"
194 		"snapshot>\n"
195 		"\treceive [-vnF] -d <filesystem>\n"));
196 	case HELP_RENAME:
197 		return (gettext("\trename <filesystem|volume|snapshot> "
198 		    "<filesystem|volume|snapshot>\n"));
199 	case HELP_ROLLBACK:
200 		return (gettext("\trollback [-rRf] <snapshot>\n"));
201 	case HELP_SEND:
202 		return (gettext("\tsend [-i <snapshot>] <snapshot>\n"));
203 	case HELP_SET:
204 		return (gettext("\tset <property=value> "
205 		    "<filesystem|volume> ...\n"));
206 	case HELP_SHARE:
207 		return (gettext("\tshare -a\n"
208 		    "\tshare <filesystem>\n"));
209 	case HELP_SNAPSHOT:
210 		return (gettext("\tsnapshot [-r] "
211 		    "<filesystem@name|volume@name>\n"));
212 	case HELP_UNMOUNT:
213 		return (gettext("\tunmount [-f] -a\n"
214 		    "\tunmount [-f] <filesystem|mountpoint>\n"));
215 	case HELP_UNSHARE:
216 		return (gettext("\tunshare [-f] -a\n"
217 		    "\tunshare [-f] <filesystem|mountpoint>\n"));
218 	}
219 
220 	abort();
221 	/* NOTREACHED */
222 }
223 
224 /*
225  * Utility function to guarantee malloc() success.
226  */
227 void *
228 safe_malloc(size_t size)
229 {
230 	void *data;
231 
232 	if ((data = calloc(1, size)) == NULL) {
233 		(void) fprintf(stderr, "internal error: out of memory\n");
234 		exit(1);
235 	}
236 
237 	return (data);
238 }
239 
240 /*
241  * Display usage message.  If we're inside a command, display only the usage for
242  * that command.  Otherwise, iterate over the entire command table and display
243  * a complete usage message.
244  */
245 static void
246 usage(boolean_t requested)
247 {
248 	int i;
249 	boolean_t show_properties = B_FALSE;
250 	FILE *fp = requested ? stdout : stderr;
251 
252 	if (current_command == NULL) {
253 
254 		(void) fprintf(fp, gettext("usage: zfs command args ...\n"));
255 		(void) fprintf(fp,
256 		    gettext("where 'command' is one of the following:\n\n"));
257 
258 		for (i = 0; i < NCOMMAND; i++) {
259 			if (command_table[i].name == NULL)
260 				(void) fprintf(fp, "\n");
261 			else
262 				(void) fprintf(fp, "%s",
263 				    get_usage(command_table[i].usage));
264 		}
265 
266 		(void) fprintf(fp, gettext("\nEach dataset is of the form: "
267 		    "pool/[dataset/]*dataset[@name]\n"));
268 	} else {
269 		(void) fprintf(fp, gettext("usage:\n"));
270 		(void) fprintf(fp, "%s", get_usage(current_command->usage));
271 	}
272 
273 	if (current_command != NULL &&
274 	    (strcmp(current_command->name, "set") == 0 ||
275 	    strcmp(current_command->name, "get") == 0 ||
276 	    strcmp(current_command->name, "inherit") == 0 ||
277 	    strcmp(current_command->name, "list") == 0))
278 		show_properties = B_TRUE;
279 
280 	if (show_properties) {
281 
282 		(void) fprintf(fp,
283 		    gettext("\nThe following properties are supported:\n"));
284 
285 		(void) fprintf(fp, "\n\t%-13s  %s  %s   %s\n\n",
286 		    "PROPERTY", "EDIT", "INHERIT", "VALUES");
287 
288 		for (i = 0; i < ZFS_NPROP_VISIBLE; i++) {
289 			(void) fprintf(fp, "\t%-13s  ", zfs_prop_to_name(i));
290 
291 			if (zfs_prop_readonly(i))
292 				(void) fprintf(fp, "  NO    ");
293 			else
294 				(void) fprintf(fp, " YES    ");
295 
296 			if (zfs_prop_inheritable(i))
297 				(void) fprintf(fp, "  YES   ");
298 			else
299 				(void) fprintf(fp, "   NO   ");
300 
301 			if (zfs_prop_values(i) == NULL)
302 				(void) fprintf(fp, "-\n");
303 			else
304 				(void) fprintf(fp, "%s\n", zfs_prop_values(i));
305 		}
306 		(void) fprintf(fp, gettext("\nSizes are specified in bytes "
307 		    "with standard units such as K, M, G, etc.\n"));
308 		(void) fprintf(fp, gettext("\n\nUser-defined properties can "
309 		    "be specified by using a name containing a colon (:).\n"));
310 	} else {
311 		/*
312 		 * TRANSLATION NOTE:
313 		 * "zfs set|get" must not be localised this is the
314 		 * command name and arguments.
315 		 */
316 		(void) fprintf(fp,
317 		    gettext("\nFor the property list, run: zfs set|get\n"));
318 	}
319 
320 	/*
321 	 * See comments at end of main().
322 	 */
323 	if (getenv("ZFS_ABORT") != NULL) {
324 		(void) printf("dumping core by request\n");
325 		abort();
326 	}
327 
328 	exit(requested ? 0 : 2);
329 }
330 
331 /*
332  * zfs clone <fs, snap, vol> fs
333  *
334  * Given an existing dataset, create a writable copy whose initial contents
335  * are the same as the source.  The newly created dataset maintains a
336  * dependency on the original; the original cannot be destroyed so long as
337  * the clone exists.
338  */
339 static int
340 zfs_do_clone(int argc, char **argv)
341 {
342 	zfs_handle_t *zhp;
343 	int ret;
344 
345 	/* check options */
346 	if (argc > 1 && argv[1][0] == '-') {
347 		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
348 		    argv[1][1]);
349 		usage(B_FALSE);
350 	}
351 
352 	/* check number of arguments */
353 	if (argc < 2) {
354 		(void) fprintf(stderr, gettext("missing source dataset "
355 		    "argument\n"));
356 		usage(B_FALSE);
357 	}
358 	if (argc < 3) {
359 		(void) fprintf(stderr, gettext("missing target dataset "
360 		    "argument\n"));
361 		usage(B_FALSE);
362 	}
363 	if (argc > 3) {
364 		(void) fprintf(stderr, gettext("too many arguments\n"));
365 		usage(B_FALSE);
366 	}
367 
368 	/* open the source dataset */
369 	if ((zhp = zfs_open(g_zfs, argv[1], ZFS_TYPE_SNAPSHOT)) == NULL)
370 		return (1);
371 
372 	/* pass to libzfs */
373 	ret = zfs_clone(zhp, argv[2], NULL);
374 
375 	/* create the mountpoint if necessary */
376 	if (ret == 0) {
377 		zfs_handle_t *clone = zfs_open(g_zfs, argv[2], ZFS_TYPE_ANY);
378 		if (clone != NULL) {
379 			if ((ret = zfs_mount(clone, NULL, 0)) == 0)
380 				ret = zfs_share(clone);
381 			zfs_close(clone);
382 		}
383 		zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE);
384 	}
385 
386 	zfs_close(zhp);
387 
388 	return (ret == 0 ? 0 : 1);
389 }
390 
391 /*
392  * zfs create [-o prop=value] ... fs
393  * zfs create [-s] [-b blocksize] [-o prop=value] ... -V vol size
394  *
395  * Create a new dataset.  This command can be used to create filesystems
396  * and volumes.  Snapshot creation is handled by 'zfs snapshot'.
397  * For volumes, the user must specify a size to be used.
398  *
399  * The '-s' flag applies only to volumes, and indicates that we should not try
400  * to set the reservation for this volume.  By default we set a reservation
401  * equal to the size for any volume.
402  */
403 static int
404 zfs_do_create(int argc, char **argv)
405 {
406 	zfs_type_t type = ZFS_TYPE_FILESYSTEM;
407 	zfs_handle_t *zhp = NULL;
408 	uint64_t volsize;
409 	int c;
410 	boolean_t noreserve = B_FALSE;
411 	int ret = 1;
412 	nvlist_t *props = NULL;
413 	uint64_t intval;
414 	char *propname;
415 	char *propval = NULL;
416 	char *strval;
417 
418 	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) {
419 		(void) fprintf(stderr, gettext("internal error: "
420 		    "out of memory\n"));
421 		return (1);
422 	}
423 
424 	/* check options */
425 	while ((c = getopt(argc, argv, ":V:b:so:")) != -1) {
426 		switch (c) {
427 		case 'V':
428 			type = ZFS_TYPE_VOLUME;
429 			if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) {
430 				(void) fprintf(stderr, gettext("bad volume "
431 				    "size '%s': %s\n"), optarg,
432 				    libzfs_error_description(g_zfs));
433 				goto error;
434 			}
435 
436 			if (nvlist_add_uint64(props,
437 			    zfs_prop_to_name(ZFS_PROP_VOLSIZE),
438 			    intval) != 0) {
439 				(void) fprintf(stderr, gettext("internal "
440 				    "error: out of memory\n"));
441 				goto error;
442 			}
443 			volsize = intval;
444 			break;
445 		case 'b':
446 			if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) {
447 				(void) fprintf(stderr, gettext("bad volume "
448 				    "block size '%s': %s\n"), optarg,
449 				    libzfs_error_description(g_zfs));
450 				goto error;
451 			}
452 
453 			if (nvlist_add_uint64(props,
454 			    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
455 			    intval) != 0) {
456 				(void) fprintf(stderr, gettext("internal "
457 				    "error: out of memory\n"));
458 				goto error;
459 			}
460 			break;
461 		case 'o':
462 			propname = optarg;
463 			if ((propval = strchr(propname, '=')) == NULL) {
464 				(void) fprintf(stderr, gettext("missing "
465 				    "'=' for -o option\n"));
466 				goto error;
467 			}
468 			*propval = '\0';
469 			propval++;
470 			if (nvlist_lookup_string(props, propname,
471 			    &strval) == 0) {
472 				(void) fprintf(stderr, gettext("property '%s' "
473 				    "specified multiple times\n"), propname);
474 				goto error;
475 			}
476 			if (nvlist_add_string(props, propname, propval) != 0) {
477 				(void) fprintf(stderr, gettext("internal "
478 				    "error: out of memory\n"));
479 				goto error;
480 			}
481 			break;
482 		case 's':
483 			noreserve = B_TRUE;
484 			break;
485 		case ':':
486 			(void) fprintf(stderr, gettext("missing size "
487 			    "argument\n"));
488 			goto badusage;
489 			break;
490 		case '?':
491 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
492 			    optopt);
493 			goto badusage;
494 		}
495 	}
496 
497 	if (noreserve && type != ZFS_TYPE_VOLUME) {
498 		(void) fprintf(stderr, gettext("'-s' can only be used when "
499 		    "creating a volume\n"));
500 		goto badusage;
501 	}
502 
503 	argc -= optind;
504 	argv += optind;
505 
506 	/* check number of arguments */
507 	if (argc == 0) {
508 		(void) fprintf(stderr, gettext("missing %s argument\n"),
509 		    zfs_type_to_name(type));
510 		goto badusage;
511 	}
512 	if (argc > 1) {
513 		(void) fprintf(stderr, gettext("too many arguments\n"));
514 		goto badusage;
515 	}
516 
517 	if (type == ZFS_TYPE_VOLUME && !noreserve &&
518 	    nvlist_lookup_string(props, zfs_prop_to_name(ZFS_PROP_RESERVATION),
519 	    &strval) != 0) {
520 		if (nvlist_add_uint64(props,
521 		    zfs_prop_to_name(ZFS_PROP_RESERVATION),
522 		    volsize) != 0) {
523 			(void) fprintf(stderr, gettext("internal "
524 			    "error: out of memory\n"));
525 			nvlist_free(props);
526 			return (1);
527 		}
528 	}
529 
530 	/* pass to libzfs */
531 	if (zfs_create(g_zfs, argv[0], type, props) != 0)
532 		goto error;
533 
534 	if (propval != NULL)
535 		*(propval - 1) = '=';
536 	zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
537 	    B_FALSE, B_FALSE);
538 
539 	if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL)
540 		goto error;
541 
542 	/*
543 	 * Mount and/or share the new filesystem as appropriate.  We provide a
544 	 * verbose error message to let the user know that their filesystem was
545 	 * in fact created, even if we failed to mount or share it.
546 	 */
547 	if (zfs_mount(zhp, NULL, 0) != 0) {
548 		(void) fprintf(stderr, gettext("filesystem successfully "
549 		    "created, but not mounted\n"));
550 		ret = 1;
551 	} else if (zfs_share(zhp) != 0) {
552 		(void) fprintf(stderr, gettext("filesystem successfully "
553 		    "created, but not shared\n"));
554 		ret = 1;
555 	} else {
556 		ret = 0;
557 	}
558 
559 error:
560 	if (zhp)
561 		zfs_close(zhp);
562 	nvlist_free(props);
563 	return (ret);
564 badusage:
565 	nvlist_free(props);
566 	usage(B_FALSE);
567 	return (2);
568 }
569 
570 /*
571  * zfs destroy [-rf] <fs, snap, vol>
572  *
573  * 	-r	Recursively destroy all children
574  * 	-R	Recursively destroy all dependents, including clones
575  * 	-f	Force unmounting of any dependents
576  *
577  * Destroys the given dataset.  By default, it will unmount any filesystems,
578  * and refuse to destroy a dataset that has any dependents.  A dependent can
579  * either be a child, or a clone of a child.
580  */
581 typedef struct destroy_cbdata {
582 	boolean_t	cb_first;
583 	int		cb_force;
584 	int		cb_recurse;
585 	int		cb_error;
586 	int		cb_needforce;
587 	int		cb_doclones;
588 	zfs_handle_t	*cb_target;
589 	char		*cb_snapname;
590 } destroy_cbdata_t;
591 
592 /*
593  * Check for any dependents based on the '-r' or '-R' flags.
594  */
595 static int
596 destroy_check_dependent(zfs_handle_t *zhp, void *data)
597 {
598 	destroy_cbdata_t *cbp = data;
599 	const char *tname = zfs_get_name(cbp->cb_target);
600 	const char *name = zfs_get_name(zhp);
601 
602 	if (strncmp(tname, name, strlen(tname)) == 0 &&
603 	    (name[strlen(tname)] == '/' || name[strlen(tname)] == '@')) {
604 		/*
605 		 * This is a direct descendant, not a clone somewhere else in
606 		 * the hierarchy.
607 		 */
608 		if (cbp->cb_recurse)
609 			goto out;
610 
611 		if (cbp->cb_first) {
612 			(void) fprintf(stderr, gettext("cannot destroy '%s': "
613 			    "%s has children\n"),
614 			    zfs_get_name(cbp->cb_target),
615 			    zfs_type_to_name(zfs_get_type(cbp->cb_target)));
616 			(void) fprintf(stderr, gettext("use '-r' to destroy "
617 			    "the following datasets:\n"));
618 			cbp->cb_first = B_FALSE;
619 			cbp->cb_error = 1;
620 		}
621 
622 		(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
623 	} else {
624 		/*
625 		 * This is a clone.  We only want to report this if the '-r'
626 		 * wasn't specified, or the target is a snapshot.
627 		 */
628 		if (!cbp->cb_recurse &&
629 		    zfs_get_type(cbp->cb_target) != ZFS_TYPE_SNAPSHOT)
630 			goto out;
631 
632 		if (cbp->cb_first) {
633 			(void) fprintf(stderr, gettext("cannot destroy '%s': "
634 			    "%s has dependent clones\n"),
635 			    zfs_get_name(cbp->cb_target),
636 			    zfs_type_to_name(zfs_get_type(cbp->cb_target)));
637 			(void) fprintf(stderr, gettext("use '-R' to destroy "
638 			    "the following datasets:\n"));
639 			cbp->cb_first = B_FALSE;
640 			cbp->cb_error = 1;
641 		}
642 
643 		(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
644 	}
645 
646 out:
647 	zfs_close(zhp);
648 	return (0);
649 }
650 
651 static int
652 destroy_callback(zfs_handle_t *zhp, void *data)
653 {
654 	destroy_cbdata_t *cbp = data;
655 
656 	/*
657 	 * Ignore pools (which we've already flagged as an error before getting
658 	 * here.
659 	 */
660 	if (strchr(zfs_get_name(zhp), '/') == NULL &&
661 	    zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
662 		zfs_close(zhp);
663 		return (0);
664 	}
665 
666 	/*
667 	 * Bail out on the first error.
668 	 */
669 	if (zfs_unmount(zhp, NULL, cbp->cb_force ? MS_FORCE : 0) != 0 ||
670 	    zfs_destroy(zhp) != 0) {
671 		zfs_close(zhp);
672 		return (-1);
673 	}
674 
675 	zfs_close(zhp);
676 	return (0);
677 }
678 
679 static int
680 destroy_snap_clones(zfs_handle_t *zhp, void *arg)
681 {
682 	destroy_cbdata_t *cbp = arg;
683 	char thissnap[MAXPATHLEN];
684 	zfs_handle_t *szhp;
685 
686 	(void) snprintf(thissnap, sizeof (thissnap),
687 	    "%s@%s", zfs_get_name(zhp), cbp->cb_snapname);
688 
689 	libzfs_print_on_error(g_zfs, B_FALSE);
690 	szhp = zfs_open(g_zfs, thissnap, ZFS_TYPE_SNAPSHOT);
691 	libzfs_print_on_error(g_zfs, B_TRUE);
692 	if (szhp) {
693 		/*
694 		 * Destroy any clones of this snapshot
695 		 */
696 		if (zfs_iter_dependents(szhp, B_FALSE, destroy_callback,
697 		    cbp) != 0) {
698 			zfs_close(szhp);
699 			return (-1);
700 		}
701 		zfs_close(szhp);
702 	}
703 
704 	return (zfs_iter_filesystems(zhp, destroy_snap_clones, arg));
705 }
706 
707 static int
708 zfs_do_destroy(int argc, char **argv)
709 {
710 	destroy_cbdata_t cb = { 0 };
711 	int c;
712 	zfs_handle_t *zhp;
713 	char *cp;
714 
715 	/* check options */
716 	while ((c = getopt(argc, argv, "frR")) != -1) {
717 		switch (c) {
718 		case 'f':
719 			cb.cb_force = 1;
720 			break;
721 		case 'r':
722 			cb.cb_recurse = 1;
723 			break;
724 		case 'R':
725 			cb.cb_recurse = 1;
726 			cb.cb_doclones = 1;
727 			break;
728 		case '?':
729 		default:
730 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
731 			    optopt);
732 			usage(B_FALSE);
733 		}
734 	}
735 
736 	argc -= optind;
737 	argv += optind;
738 
739 	/* check number of arguments */
740 	if (argc == 0) {
741 		(void) fprintf(stderr, gettext("missing path argument\n"));
742 		usage(B_FALSE);
743 	}
744 	if (argc > 1) {
745 		(void) fprintf(stderr, gettext("too many arguments\n"));
746 		usage(B_FALSE);
747 	}
748 
749 	/*
750 	 * If we are doing recursive destroy of a snapshot, then the
751 	 * named snapshot may not exist.  Go straight to libzfs.
752 	 */
753 	if (cb.cb_recurse && (cp = strchr(argv[0], '@'))) {
754 		int ret;
755 
756 		*cp = '\0';
757 		if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL)
758 			return (1);
759 		*cp = '@';
760 		cp++;
761 
762 		if (cb.cb_doclones) {
763 			cb.cb_snapname = cp;
764 			if (destroy_snap_clones(zhp, &cb) != 0) {
765 				zfs_close(zhp);
766 				return (1);
767 			}
768 		}
769 
770 		ret = zfs_destroy_snaps(zhp, cp);
771 		zfs_close(zhp);
772 		if (ret) {
773 			(void) fprintf(stderr,
774 			    gettext("no snapshots destroyed\n"));
775 		}
776 		return (ret != 0);
777 	}
778 
779 
780 	/* Open the given dataset */
781 	if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL)
782 		return (1);
783 
784 	cb.cb_target = zhp;
785 
786 	/*
787 	 * Perform an explicit check for pools before going any further.
788 	 */
789 	if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
790 	    zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
791 		(void) fprintf(stderr, gettext("cannot destroy '%s': "
792 		    "operation does not apply to pools\n"),
793 		    zfs_get_name(zhp));
794 		(void) fprintf(stderr, gettext("use 'zfs destroy -r "
795 		    "%s' to destroy all datasets in the pool\n"),
796 		    zfs_get_name(zhp));
797 		(void) fprintf(stderr, gettext("use 'zpool destroy %s' "
798 		    "to destroy the pool itself\n"), zfs_get_name(zhp));
799 		zfs_close(zhp);
800 		return (1);
801 	}
802 
803 	/*
804 	 * Check for any dependents and/or clones.
805 	 */
806 	cb.cb_first = B_TRUE;
807 	if (!cb.cb_doclones &&
808 	    zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent,
809 	    &cb) != 0) {
810 		zfs_close(zhp);
811 		return (1);
812 	}
813 
814 
815 	if (cb.cb_error ||
816 	    zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0) {
817 		zfs_close(zhp);
818 		return (1);
819 	}
820 
821 	/*
822 	 * Do the real thing.  The callback will close the handle regardless of
823 	 * whether it succeeds or not.
824 	 */
825 	if (destroy_callback(zhp, &cb) != 0)
826 		return (1);
827 
828 	zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
829 	    B_FALSE, B_FALSE);
830 
831 	return (0);
832 }
833 
834 /*
835  * zfs get [-rHp] [-o field[,field]...] [-s source[,source]...]
836  * 	< all | property[,property]... > < fs | snap | vol > ...
837  *
838  *	-r	recurse over any child datasets
839  *	-H	scripted mode.  Headers are stripped, and fields are separated
840  *		by tabs instead of spaces.
841  *	-o	Set of fields to display.  One of "name,property,value,source".
842  *		Default is all four.
843  *	-s	Set of sources to allow.  One of
844  *		"local,default,inherited,temporary,none".  Default is all
845  *		five.
846  *	-p	Display values in parsable (literal) format.
847  *
848  *  Prints properties for the given datasets.  The user can control which
849  *  columns to display as well as which property types to allow.
850  */
851 typedef struct get_cbdata {
852 	int cb_sources;
853 	int cb_columns[4];
854 	int cb_colwidths[5];
855 	boolean_t cb_scripted;
856 	boolean_t cb_literal;
857 	boolean_t cb_first;
858 	zfs_proplist_t *cb_proplist;
859 } get_cbdata_t;
860 
861 #define	GET_COL_NAME		1
862 #define	GET_COL_PROPERTY	2
863 #define	GET_COL_VALUE		3
864 #define	GET_COL_SOURCE		4
865 
866 /*
867  * Print the column headers for 'zfs get'.
868  */
869 static void
870 print_get_headers(get_cbdata_t *cbp)
871 {
872 	zfs_proplist_t *pl = cbp->cb_proplist;
873 	int i;
874 	char *title;
875 	size_t len;
876 
877 	cbp->cb_first = B_FALSE;
878 	if (cbp->cb_scripted)
879 		return;
880 
881 	/*
882 	 * Start with the length of the column headers.
883 	 */
884 	cbp->cb_colwidths[GET_COL_NAME] = strlen(gettext("NAME"));
885 	cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(gettext("PROPERTY"));
886 	cbp->cb_colwidths[GET_COL_VALUE] = strlen(gettext("VALUE"));
887 	cbp->cb_colwidths[GET_COL_SOURCE] = strlen(gettext("SOURCE"));
888 
889 	/*
890 	 * Go through and calculate the widths for each column.  For the
891 	 * 'source' column, we kludge it up by taking the worst-case scenario of
892 	 * inheriting from the longest name.  This is acceptable because in the
893 	 * majority of cases 'SOURCE' is the last column displayed, and we don't
894 	 * use the width anyway.  Note that the 'VALUE' column can be oversized,
895 	 * if the name of the property is much longer the any values we find.
896 	 */
897 	for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
898 		/*
899 		 * 'PROPERTY' column
900 		 */
901 		if (pl->pl_prop != ZFS_PROP_INVAL) {
902 			len = strlen(zfs_prop_to_name(pl->pl_prop));
903 			if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
904 				cbp->cb_colwidths[GET_COL_PROPERTY] = len;
905 		} else {
906 			len = strlen(pl->pl_user_prop);
907 			if (len > cbp->cb_colwidths[GET_COL_PROPERTY])
908 				cbp->cb_colwidths[GET_COL_PROPERTY] = len;
909 		}
910 
911 		/*
912 		 * 'VALUE' column
913 		 */
914 		if ((pl->pl_prop != ZFS_PROP_NAME || !pl->pl_all) &&
915 		    pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE])
916 			cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width;
917 
918 		/*
919 		 * 'NAME' and 'SOURCE' columns
920 		 */
921 		if (pl->pl_prop == ZFS_PROP_NAME &&
922 		    pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) {
923 			cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width;
924 			cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width +
925 			    strlen(gettext("inherited from"));
926 		}
927 	}
928 
929 	/*
930 	 * Now go through and print the headers.
931 	 */
932 	for (i = 0; i < 4; i++) {
933 		switch (cbp->cb_columns[i]) {
934 		case GET_COL_NAME:
935 			title = gettext("NAME");
936 			break;
937 		case GET_COL_PROPERTY:
938 			title = gettext("PROPERTY");
939 			break;
940 		case GET_COL_VALUE:
941 			title = gettext("VALUE");
942 			break;
943 		case GET_COL_SOURCE:
944 			title = gettext("SOURCE");
945 			break;
946 		default:
947 			title = NULL;
948 		}
949 
950 		if (title != NULL) {
951 			if (i == 3 || cbp->cb_columns[i + 1] == 0)
952 				(void) printf("%s", title);
953 			else
954 				(void) printf("%-*s  ",
955 				    cbp->cb_colwidths[cbp->cb_columns[i]],
956 				    title);
957 		}
958 	}
959 	(void) printf("\n");
960 }
961 
962 /*
963  * Display a single line of output, according to the settings in the callback
964  * structure.
965  */
966 static void
967 print_one_property(zfs_handle_t *zhp, get_cbdata_t *cbp, const char *propname,
968     const char *value, zfs_source_t sourcetype, const char *source)
969 {
970 	int i;
971 	const char *str;
972 	char buf[128];
973 
974 	/*
975 	 * Ignore those source types that the user has chosen to ignore.
976 	 */
977 	if ((sourcetype & cbp->cb_sources) == 0)
978 		return;
979 
980 	if (cbp->cb_first)
981 		print_get_headers(cbp);
982 
983 	for (i = 0; i < 4; i++) {
984 		switch (cbp->cb_columns[i]) {
985 		case GET_COL_NAME:
986 			str = zfs_get_name(zhp);
987 			break;
988 
989 		case GET_COL_PROPERTY:
990 			str = propname;
991 			break;
992 
993 		case GET_COL_VALUE:
994 			str = value;
995 			break;
996 
997 		case GET_COL_SOURCE:
998 			switch (sourcetype) {
999 			case ZFS_SRC_NONE:
1000 				str = "-";
1001 				break;
1002 
1003 			case ZFS_SRC_DEFAULT:
1004 				str = "default";
1005 				break;
1006 
1007 			case ZFS_SRC_LOCAL:
1008 				str = "local";
1009 				break;
1010 
1011 			case ZFS_SRC_TEMPORARY:
1012 				str = "temporary";
1013 				break;
1014 
1015 			case ZFS_SRC_INHERITED:
1016 				(void) snprintf(buf, sizeof (buf),
1017 				    "inherited from %s", source);
1018 				str = buf;
1019 				break;
1020 			}
1021 			break;
1022 
1023 		default:
1024 			continue;
1025 		}
1026 
1027 		if (cbp->cb_columns[i + 1] == 0)
1028 			(void) printf("%s", str);
1029 		else if (cbp->cb_scripted)
1030 			(void) printf("%s\t", str);
1031 		else
1032 			(void) printf("%-*s  ",
1033 			    cbp->cb_colwidths[cbp->cb_columns[i]],
1034 			    str);
1035 
1036 	}
1037 
1038 	(void) printf("\n");
1039 }
1040 
1041 /*
1042  * Invoked to display the properties for a single dataset.
1043  */
1044 static int
1045 get_callback(zfs_handle_t *zhp, void *data)
1046 {
1047 	char buf[ZFS_MAXPROPLEN];
1048 	zfs_source_t sourcetype;
1049 	char source[ZFS_MAXNAMELEN];
1050 	get_cbdata_t *cbp = data;
1051 	nvlist_t *userprop = zfs_get_user_props(zhp);
1052 	zfs_proplist_t *pl = cbp->cb_proplist;
1053 	nvlist_t *propval;
1054 	char *strval;
1055 	char *sourceval;
1056 
1057 	for (; pl != NULL; pl = pl->pl_next) {
1058 		/*
1059 		 * Skip the special fake placeholder.  This will also skip over
1060 		 * the name property when 'all' is specified.
1061 		 */
1062 		if (pl->pl_prop == ZFS_PROP_NAME &&
1063 		    pl == cbp->cb_proplist)
1064 			continue;
1065 
1066 		if (pl->pl_prop != ZFS_PROP_INVAL) {
1067 			if (zfs_prop_get(zhp, pl->pl_prop, buf,
1068 			    sizeof (buf), &sourcetype, source,
1069 			    sizeof (source),
1070 			    cbp->cb_literal) != 0) {
1071 				if (pl->pl_all)
1072 					continue;
1073 				sourcetype = ZFS_SRC_NONE;
1074 				(void) strlcpy(buf, "-", sizeof (buf));
1075 			}
1076 
1077 			print_one_property(zhp, cbp,
1078 			    zfs_prop_to_name(pl->pl_prop),
1079 			    buf, sourcetype, source);
1080 		} else {
1081 			if (nvlist_lookup_nvlist(userprop,
1082 			    pl->pl_user_prop, &propval) != 0) {
1083 				if (pl->pl_all)
1084 					continue;
1085 				sourcetype = ZFS_SRC_NONE;
1086 				strval = "-";
1087 			} else {
1088 				verify(nvlist_lookup_string(propval,
1089 				    ZFS_PROP_VALUE, &strval) == 0);
1090 				verify(nvlist_lookup_string(propval,
1091 				    ZFS_PROP_SOURCE, &sourceval) == 0);
1092 
1093 				if (strcmp(sourceval,
1094 				    zfs_get_name(zhp)) == 0) {
1095 					sourcetype = ZFS_SRC_LOCAL;
1096 				} else {
1097 					sourcetype = ZFS_SRC_INHERITED;
1098 					(void) strlcpy(source,
1099 					    sourceval, sizeof (source));
1100 				}
1101 			}
1102 
1103 			print_one_property(zhp, cbp,
1104 			    pl->pl_user_prop, strval, sourcetype,
1105 			    source);
1106 		}
1107 	}
1108 
1109 	return (0);
1110 }
1111 
1112 static int
1113 zfs_do_get(int argc, char **argv)
1114 {
1115 	get_cbdata_t cb = { 0 };
1116 	boolean_t recurse = B_FALSE;
1117 	int i, c;
1118 	char *value, *fields;
1119 	int ret;
1120 	zfs_proplist_t fake_name = { 0 };
1121 
1122 	/*
1123 	 * Set up default columns and sources.
1124 	 */
1125 	cb.cb_sources = ZFS_SRC_ALL;
1126 	cb.cb_columns[0] = GET_COL_NAME;
1127 	cb.cb_columns[1] = GET_COL_PROPERTY;
1128 	cb.cb_columns[2] = GET_COL_VALUE;
1129 	cb.cb_columns[3] = GET_COL_SOURCE;
1130 
1131 	/* check options */
1132 	while ((c = getopt(argc, argv, ":o:s:rHp")) != -1) {
1133 		switch (c) {
1134 		case 'p':
1135 			cb.cb_literal = B_TRUE;
1136 			break;
1137 		case 'r':
1138 			recurse = B_TRUE;
1139 			break;
1140 		case 'H':
1141 			cb.cb_scripted = B_TRUE;
1142 			break;
1143 		case ':':
1144 			(void) fprintf(stderr, gettext("missing argument for "
1145 			    "'%c' option\n"), optopt);
1146 			usage(B_FALSE);
1147 			break;
1148 		case 'o':
1149 			/*
1150 			 * Process the set of columns to display.  We zero out
1151 			 * the structure to give us a blank slate.
1152 			 */
1153 			bzero(&cb.cb_columns, sizeof (cb.cb_columns));
1154 			i = 0;
1155 			while (*optarg != '\0') {
1156 				static char *col_subopts[] =
1157 				    { "name", "property", "value", "source",
1158 				    NULL };
1159 
1160 				if (i == 4) {
1161 					(void) fprintf(stderr, gettext("too "
1162 					    "many fields given to -o "
1163 					    "option\n"));
1164 					usage(B_FALSE);
1165 				}
1166 
1167 				switch (getsubopt(&optarg, col_subopts,
1168 				    &value)) {
1169 				case 0:
1170 					cb.cb_columns[i++] = GET_COL_NAME;
1171 					break;
1172 				case 1:
1173 					cb.cb_columns[i++] = GET_COL_PROPERTY;
1174 					break;
1175 				case 2:
1176 					cb.cb_columns[i++] = GET_COL_VALUE;
1177 					break;
1178 				case 3:
1179 					cb.cb_columns[i++] = GET_COL_SOURCE;
1180 					break;
1181 				default:
1182 					(void) fprintf(stderr,
1183 					    gettext("invalid column name "
1184 					    "'%s'\n"), value);
1185 					    usage(B_FALSE);
1186 				}
1187 			}
1188 			break;
1189 
1190 		case 's':
1191 			cb.cb_sources = 0;
1192 			while (*optarg != '\0') {
1193 				static char *source_subopts[] = {
1194 					"local", "default", "inherited",
1195 					"temporary", "none", NULL };
1196 
1197 				switch (getsubopt(&optarg, source_subopts,
1198 				    &value)) {
1199 				case 0:
1200 					cb.cb_sources |= ZFS_SRC_LOCAL;
1201 					break;
1202 				case 1:
1203 					cb.cb_sources |= ZFS_SRC_DEFAULT;
1204 					break;
1205 				case 2:
1206 					cb.cb_sources |= ZFS_SRC_INHERITED;
1207 					break;
1208 				case 3:
1209 					cb.cb_sources |= ZFS_SRC_TEMPORARY;
1210 					break;
1211 				case 4:
1212 					cb.cb_sources |= ZFS_SRC_NONE;
1213 					break;
1214 				default:
1215 					(void) fprintf(stderr,
1216 					    gettext("invalid source "
1217 					    "'%s'\n"), value);
1218 					    usage(B_FALSE);
1219 				}
1220 			}
1221 			break;
1222 
1223 		case '?':
1224 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1225 			    optopt);
1226 			usage(B_FALSE);
1227 		}
1228 	}
1229 
1230 	argc -= optind;
1231 	argv += optind;
1232 
1233 	if (argc < 1) {
1234 		(void) fprintf(stderr, gettext("missing property "
1235 		    "argument\n"));
1236 		usage(B_FALSE);
1237 	}
1238 
1239 	fields = argv[0];
1240 
1241 	if (zfs_get_proplist(g_zfs, fields, &cb.cb_proplist) != 0)
1242 		usage(B_FALSE);
1243 
1244 	argc--;
1245 	argv++;
1246 
1247 	/*
1248 	 * As part of zfs_expand_proplist(), we keep track of the maximum column
1249 	 * width for each property.  For the 'NAME' (and 'SOURCE') columns, we
1250 	 * need to know the maximum name length.  However, the user likely did
1251 	 * not specify 'name' as one of the properties to fetch, so we need to
1252 	 * make sure we always include at least this property for
1253 	 * print_get_headers() to work properly.
1254 	 */
1255 	if (cb.cb_proplist != NULL) {
1256 		fake_name.pl_prop = ZFS_PROP_NAME;
1257 		fake_name.pl_width = strlen(gettext("NAME"));
1258 		fake_name.pl_next = cb.cb_proplist;
1259 		cb.cb_proplist = &fake_name;
1260 	}
1261 
1262 	cb.cb_first = B_TRUE;
1263 
1264 	/* run for each object */
1265 	ret = zfs_for_each(argc, argv, recurse, ZFS_TYPE_ANY, NULL,
1266 	    &cb.cb_proplist, get_callback, &cb);
1267 
1268 	if (cb.cb_proplist == &fake_name)
1269 		zfs_free_proplist(fake_name.pl_next);
1270 	else
1271 		zfs_free_proplist(cb.cb_proplist);
1272 
1273 	return (ret);
1274 }
1275 
1276 /*
1277  * inherit [-r] <property> <fs|vol> ...
1278  *
1279  * 	-r	Recurse over all children
1280  *
1281  * For each dataset specified on the command line, inherit the given property
1282  * from its parent.  Inheriting a property at the pool level will cause it to
1283  * use the default value.  The '-r' flag will recurse over all children, and is
1284  * useful for setting a property on a hierarchy-wide basis, regardless of any
1285  * local modifications for each dataset.
1286  */
1287 typedef struct inherit_cbdata {
1288 	char		*cb_propname;
1289 	boolean_t	cb_any_successful;
1290 } inherit_cbdata_t;
1291 
1292 static int
1293 inherit_callback(zfs_handle_t *zhp, void *data)
1294 {
1295 	inherit_cbdata_t *cbp = data;
1296 	int ret;
1297 
1298 	ret = zfs_prop_inherit(zhp, cbp->cb_propname);
1299 	if (ret == 0)
1300 		cbp->cb_any_successful = B_TRUE;
1301 	return (ret != 0);
1302 }
1303 
1304 static int
1305 zfs_do_inherit(int argc, char **argv)
1306 {
1307 	boolean_t recurse = B_FALSE;
1308 	int c;
1309 	zfs_prop_t prop;
1310 	inherit_cbdata_t cb;
1311 	int ret;
1312 
1313 	/* check options */
1314 	while ((c = getopt(argc, argv, "r")) != -1) {
1315 		switch (c) {
1316 		case 'r':
1317 			recurse = B_TRUE;
1318 			break;
1319 		case '?':
1320 		default:
1321 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1322 			    optopt);
1323 			usage(B_FALSE);
1324 		}
1325 	}
1326 
1327 	argc -= optind;
1328 	argv += optind;
1329 
1330 	/* check number of arguments */
1331 	if (argc < 1) {
1332 		(void) fprintf(stderr, gettext("missing property argument\n"));
1333 		usage(B_FALSE);
1334 	}
1335 	if (argc < 2) {
1336 		(void) fprintf(stderr, gettext("missing dataset argument\n"));
1337 		usage(B_FALSE);
1338 	}
1339 
1340 	cb.cb_propname = argv[0];
1341 	argc--;
1342 	argv++;
1343 
1344 	if ((prop = zfs_name_to_prop(cb.cb_propname)) != ZFS_PROP_INVAL) {
1345 		if (zfs_prop_readonly(prop)) {
1346 			(void) fprintf(stderr, gettext(
1347 			    "%s property is read-only\n"),
1348 			    cb.cb_propname);
1349 			return (1);
1350 		}
1351 		if (!zfs_prop_inheritable(prop)) {
1352 			(void) fprintf(stderr, gettext("'%s' property cannot "
1353 			    "be inherited\n"), cb.cb_propname);
1354 			if (prop == ZFS_PROP_QUOTA ||
1355 			    prop == ZFS_PROP_RESERVATION)
1356 				(void) fprintf(stderr, gettext("use 'zfs set "
1357 				    "%s=none' to clear\n"), cb.cb_propname);
1358 			return (1);
1359 		}
1360 	} else if (!zfs_prop_user(cb.cb_propname)) {
1361 		(void) fprintf(stderr, gettext(
1362 		    "invalid property '%s'\n"),
1363 		    cb.cb_propname);
1364 		usage(B_FALSE);
1365 	}
1366 
1367 	cb.cb_any_successful = B_FALSE;
1368 
1369 	ret = zfs_for_each(argc, argv, recurse,
1370 	    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, NULL, NULL,
1371 	    inherit_callback, &cb);
1372 
1373 	if (cb.cb_any_successful) {
1374 		zpool_log_history(g_zfs, argc + optind + 1, argv - optind - 1,
1375 		    argv[0], B_FALSE, B_FALSE);
1376 	}
1377 
1378 	return (ret);
1379 }
1380 
1381 /*
1382  * list [-rH] [-o property[,property]...] [-t type[,type]...]
1383  *      [-s property [-s property]...] [-S property [-S property]...]
1384  *      <dataset> ...
1385  *
1386  * 	-r	Recurse over all children
1387  * 	-H	Scripted mode; elide headers and separate colums by tabs
1388  * 	-o	Control which fields to display.
1389  * 	-t	Control which object types to display.
1390  *	-s	Specify sort columns, descending order.
1391  *	-S	Specify sort columns, ascending order.
1392  *
1393  * When given no arguments, lists all filesystems in the system.
1394  * Otherwise, list the specified datasets, optionally recursing down them if
1395  * '-r' is specified.
1396  */
1397 typedef struct list_cbdata {
1398 	boolean_t	cb_first;
1399 	boolean_t	cb_scripted;
1400 	zfs_proplist_t	*cb_proplist;
1401 } list_cbdata_t;
1402 
1403 /*
1404  * Given a list of columns to display, output appropriate headers for each one.
1405  */
1406 static void
1407 print_header(zfs_proplist_t *pl)
1408 {
1409 	char headerbuf[ZFS_MAXPROPLEN];
1410 	const char *header;
1411 	int i;
1412 	boolean_t first = B_TRUE;
1413 	boolean_t right_justify;
1414 
1415 	for (; pl != NULL; pl = pl->pl_next) {
1416 		if (!first) {
1417 			(void) printf("  ");
1418 		} else {
1419 			first = B_FALSE;
1420 		}
1421 
1422 		right_justify = B_FALSE;
1423 		if (pl->pl_prop != ZFS_PROP_INVAL) {
1424 			header = zfs_prop_column_name(pl->pl_prop);
1425 			right_justify = zfs_prop_align_right(pl->pl_prop);
1426 		} else {
1427 			for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
1428 				headerbuf[i] = toupper(pl->pl_user_prop[i]);
1429 			headerbuf[i] = '\0';
1430 			header = headerbuf;
1431 		}
1432 
1433 		if (pl->pl_next == NULL && !right_justify)
1434 			(void) printf("%s", header);
1435 		else if (right_justify)
1436 			(void) printf("%*s", pl->pl_width, header);
1437 		else
1438 			(void) printf("%-*s", pl->pl_width, header);
1439 	}
1440 
1441 	(void) printf("\n");
1442 }
1443 
1444 /*
1445  * Given a dataset and a list of fields, print out all the properties according
1446  * to the described layout.
1447  */
1448 static void
1449 print_dataset(zfs_handle_t *zhp, zfs_proplist_t *pl, int scripted)
1450 {
1451 	boolean_t first = B_TRUE;
1452 	char property[ZFS_MAXPROPLEN];
1453 	nvlist_t *userprops = zfs_get_user_props(zhp);
1454 	nvlist_t *propval;
1455 	char *propstr;
1456 	boolean_t right_justify;
1457 	int width;
1458 
1459 	for (; pl != NULL; pl = pl->pl_next) {
1460 		if (!first) {
1461 			if (scripted)
1462 				(void) printf("\t");
1463 			else
1464 				(void) printf("  ");
1465 		} else {
1466 			first = B_FALSE;
1467 		}
1468 
1469 		right_justify = B_FALSE;
1470 		if (pl->pl_prop != ZFS_PROP_INVAL) {
1471 			if (zfs_prop_get(zhp, pl->pl_prop, property,
1472 			    sizeof (property), NULL, NULL, 0, B_FALSE) != 0)
1473 				propstr = "-";
1474 			else
1475 				propstr = property;
1476 
1477 			right_justify = zfs_prop_align_right(pl->pl_prop);
1478 		} else {
1479 			if (nvlist_lookup_nvlist(userprops,
1480 			    pl->pl_user_prop, &propval) != 0)
1481 				propstr = "-";
1482 			else
1483 				verify(nvlist_lookup_string(propval,
1484 				    ZFS_PROP_VALUE, &propstr) == 0);
1485 		}
1486 
1487 		width = pl->pl_width;
1488 
1489 		/*
1490 		 * If this is being called in scripted mode, or if this is the
1491 		 * last column and it is left-justified, don't include a width
1492 		 * format specifier.
1493 		 */
1494 		if (scripted || (pl->pl_next == NULL && !right_justify))
1495 			(void) printf("%s", propstr);
1496 		else if (right_justify)
1497 			(void) printf("%*s", width, propstr);
1498 		else
1499 			(void) printf("%-*s", width, propstr);
1500 	}
1501 
1502 	(void) printf("\n");
1503 }
1504 
1505 /*
1506  * Generic callback function to list a dataset or snapshot.
1507  */
1508 static int
1509 list_callback(zfs_handle_t *zhp, void *data)
1510 {
1511 	list_cbdata_t *cbp = data;
1512 
1513 	if (cbp->cb_first) {
1514 		if (!cbp->cb_scripted)
1515 			print_header(cbp->cb_proplist);
1516 		cbp->cb_first = B_FALSE;
1517 	}
1518 
1519 	print_dataset(zhp, cbp->cb_proplist, cbp->cb_scripted);
1520 
1521 	return (0);
1522 }
1523 
1524 static int
1525 zfs_do_list(int argc, char **argv)
1526 {
1527 	int c;
1528 	boolean_t recurse = B_FALSE;
1529 	boolean_t scripted = B_FALSE;
1530 	static char default_fields[] =
1531 	    "name,used,available,referenced,mountpoint";
1532 	int types = ZFS_TYPE_ANY;
1533 	char *fields = NULL;
1534 	char *basic_fields = default_fields;
1535 	list_cbdata_t cb = { 0 };
1536 	char *value;
1537 	int ret;
1538 	char *type_subopts[] = { "filesystem", "volume", "snapshot", NULL };
1539 	zfs_sort_column_t *sortcol = NULL;
1540 
1541 	/* check options */
1542 	while ((c = getopt(argc, argv, ":o:rt:Hs:S:")) != -1) {
1543 		switch (c) {
1544 		case 'o':
1545 			fields = optarg;
1546 			break;
1547 		case 'r':
1548 			recurse = B_TRUE;
1549 			break;
1550 		case 'H':
1551 			scripted = B_TRUE;
1552 			break;
1553 		case 's':
1554 			if (zfs_add_sort_column(&sortcol, optarg,
1555 			    B_FALSE) != 0) {
1556 				(void) fprintf(stderr,
1557 				    gettext("invalid property '%s'\n"), optarg);
1558 				usage(B_FALSE);
1559 			}
1560 			break;
1561 		case 'S':
1562 			if (zfs_add_sort_column(&sortcol, optarg,
1563 			    B_TRUE) != 0) {
1564 				(void) fprintf(stderr,
1565 				    gettext("invalid property '%s'\n"), optarg);
1566 				usage(B_FALSE);
1567 			}
1568 			break;
1569 		case 't':
1570 			types = 0;
1571 			while (*optarg != '\0') {
1572 				switch (getsubopt(&optarg, type_subopts,
1573 				    &value)) {
1574 				case 0:
1575 					types |= ZFS_TYPE_FILESYSTEM;
1576 					break;
1577 				case 1:
1578 					types |= ZFS_TYPE_VOLUME;
1579 					break;
1580 				case 2:
1581 					types |= ZFS_TYPE_SNAPSHOT;
1582 					break;
1583 				default:
1584 					(void) fprintf(stderr,
1585 					    gettext("invalid type '%s'\n"),
1586 					    value);
1587 					usage(B_FALSE);
1588 				}
1589 			}
1590 			break;
1591 		case ':':
1592 			(void) fprintf(stderr, gettext("missing argument for "
1593 			    "'%c' option\n"), optopt);
1594 			usage(B_FALSE);
1595 			break;
1596 		case '?':
1597 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1598 			    optopt);
1599 			usage(B_FALSE);
1600 		}
1601 	}
1602 
1603 	argc -= optind;
1604 	argv += optind;
1605 
1606 	if (fields == NULL)
1607 		fields = basic_fields;
1608 
1609 	/*
1610 	 * If the user specifies '-o all', the zfs_get_proplist() doesn't
1611 	 * normally include the name of the dataset.  For 'zfs list', we always
1612 	 * want this property to be first.
1613 	 */
1614 	if (zfs_get_proplist(g_zfs, fields, &cb.cb_proplist) != 0)
1615 		usage(B_FALSE);
1616 
1617 	cb.cb_scripted = scripted;
1618 	cb.cb_first = B_TRUE;
1619 
1620 	ret = zfs_for_each(argc, argv, recurse, types, sortcol, &cb.cb_proplist,
1621 	    list_callback, &cb);
1622 
1623 	zfs_free_proplist(cb.cb_proplist);
1624 	zfs_free_sort_columns(sortcol);
1625 
1626 	if (ret == 0 && cb.cb_first)
1627 		(void) printf(gettext("no datasets available\n"));
1628 
1629 	return (ret);
1630 }
1631 
1632 /*
1633  * zfs rename <fs | snap | vol> <fs | snap | vol>
1634  *
1635  * Renames the given dataset to another of the same type.
1636  */
1637 /* ARGSUSED */
1638 static int
1639 zfs_do_rename(int argc, char **argv)
1640 {
1641 	zfs_handle_t *zhp;
1642 	int ret;
1643 
1644 	/* check options */
1645 	if (argc > 1 && argv[1][0] == '-') {
1646 		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1647 		    argv[1][1]);
1648 		usage(B_FALSE);
1649 	}
1650 
1651 	/* check number of arguments */
1652 	if (argc < 2) {
1653 		(void) fprintf(stderr, gettext("missing source dataset "
1654 		    "argument\n"));
1655 		usage(B_FALSE);
1656 	}
1657 	if (argc < 3) {
1658 		(void) fprintf(stderr, gettext("missing target dataset "
1659 		    "argument\n"));
1660 		usage(B_FALSE);
1661 	}
1662 	if (argc > 3) {
1663 		(void) fprintf(stderr, gettext("too many arguments\n"));
1664 		usage(B_FALSE);
1665 	}
1666 
1667 	if ((zhp = zfs_open(g_zfs, argv[1], ZFS_TYPE_ANY)) == NULL)
1668 		return (1);
1669 
1670 	ret = (zfs_rename(zhp, argv[2]) != 0);
1671 
1672 	if (!ret)
1673 		zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE);
1674 
1675 	zfs_close(zhp);
1676 	return (ret);
1677 }
1678 
1679 /*
1680  * zfs promote <fs>
1681  *
1682  * Promotes the given clone fs to be the parent
1683  */
1684 /* ARGSUSED */
1685 static int
1686 zfs_do_promote(int argc, char **argv)
1687 {
1688 	zfs_handle_t *zhp;
1689 	int ret;
1690 
1691 	/* check options */
1692 	if (argc > 1 && argv[1][0] == '-') {
1693 		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1694 		    argv[1][1]);
1695 		usage(B_FALSE);
1696 	}
1697 
1698 	/* check number of arguments */
1699 	if (argc < 2) {
1700 		(void) fprintf(stderr, gettext("missing clone filesystem"
1701 		    " argument\n"));
1702 		usage(B_FALSE);
1703 	}
1704 	if (argc > 2) {
1705 		(void) fprintf(stderr, gettext("too many arguments\n"));
1706 		usage(B_FALSE);
1707 	}
1708 
1709 	zhp = zfs_open(g_zfs, argv[1], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
1710 	if (zhp == NULL)
1711 		return (1);
1712 
1713 	ret = (zfs_promote(zhp) != 0);
1714 
1715 	if (!ret)
1716 		zpool_log_history(g_zfs, argc, argv, argv[1], B_FALSE, B_FALSE);
1717 
1718 	zfs_close(zhp);
1719 	return (ret);
1720 }
1721 
1722 /*
1723  * zfs rollback [-rfR] <snapshot>
1724  *
1725  * 	-r	Delete any intervening snapshots before doing rollback
1726  * 	-R	Delete any snapshots and their clones
1727  * 	-f	Force unmount filesystems, even if they are in use.
1728  *
1729  * Given a filesystem, rollback to a specific snapshot, discarding any changes
1730  * since then and making it the active dataset.  If more recent snapshots exist,
1731  * the command will complain unless the '-r' flag is given.
1732  */
1733 typedef struct rollback_cbdata {
1734 	uint64_t	cb_create;
1735 	boolean_t	cb_first;
1736 	int		cb_doclones;
1737 	char		*cb_target;
1738 	int		cb_error;
1739 	boolean_t	cb_recurse;
1740 	boolean_t	cb_dependent;
1741 } rollback_cbdata_t;
1742 
1743 /*
1744  * Report any snapshots more recent than the one specified.  Used when '-r' is
1745  * not specified.  We reuse this same callback for the snapshot dependents - if
1746  * 'cb_dependent' is set, then this is a dependent and we should report it
1747  * without checking the transaction group.
1748  */
1749 static int
1750 rollback_check(zfs_handle_t *zhp, void *data)
1751 {
1752 	rollback_cbdata_t *cbp = data;
1753 
1754 	if (cbp->cb_doclones) {
1755 		zfs_close(zhp);
1756 		return (0);
1757 	}
1758 
1759 	if (!cbp->cb_dependent) {
1760 		if (strcmp(zfs_get_name(zhp), cbp->cb_target) != 0 &&
1761 		    zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
1762 		    zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
1763 		    cbp->cb_create) {
1764 
1765 			if (cbp->cb_first && !cbp->cb_recurse) {
1766 				(void) fprintf(stderr, gettext("cannot "
1767 				    "rollback to '%s': more recent snapshots "
1768 				    "exist\n"),
1769 				    cbp->cb_target);
1770 				(void) fprintf(stderr, gettext("use '-r' to "
1771 				    "force deletion of the following "
1772 				    "snapshots:\n"));
1773 				cbp->cb_first = 0;
1774 				cbp->cb_error = 1;
1775 			}
1776 
1777 			if (cbp->cb_recurse) {
1778 				cbp->cb_dependent = B_TRUE;
1779 				if (zfs_iter_dependents(zhp, B_TRUE,
1780 				    rollback_check, cbp) != 0) {
1781 					zfs_close(zhp);
1782 					return (-1);
1783 				}
1784 				cbp->cb_dependent = B_FALSE;
1785 			} else {
1786 				(void) fprintf(stderr, "%s\n",
1787 				    zfs_get_name(zhp));
1788 			}
1789 		}
1790 	} else {
1791 		if (cbp->cb_first && cbp->cb_recurse) {
1792 			(void) fprintf(stderr, gettext("cannot rollback to "
1793 			    "'%s': clones of previous snapshots exist\n"),
1794 			    cbp->cb_target);
1795 			(void) fprintf(stderr, gettext("use '-R' to "
1796 			    "force deletion of the following clones and "
1797 			    "dependents:\n"));
1798 			cbp->cb_first = 0;
1799 			cbp->cb_error = 1;
1800 		}
1801 
1802 		(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
1803 	}
1804 
1805 	zfs_close(zhp);
1806 	return (0);
1807 }
1808 
1809 static int
1810 zfs_do_rollback(int argc, char **argv)
1811 {
1812 	int ret;
1813 	int c;
1814 	rollback_cbdata_t cb = { 0 };
1815 	zfs_handle_t *zhp, *snap;
1816 	char parentname[ZFS_MAXNAMELEN];
1817 	char *delim;
1818 	int force = 0;
1819 
1820 	/* check options */
1821 	while ((c = getopt(argc, argv, "rfR")) != -1) {
1822 		switch (c) {
1823 		case 'f':
1824 			force = 1;
1825 			break;
1826 		case 'r':
1827 			cb.cb_recurse = 1;
1828 			break;
1829 		case 'R':
1830 			cb.cb_recurse = 1;
1831 			cb.cb_doclones = 1;
1832 			break;
1833 		case '?':
1834 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1835 			    optopt);
1836 			usage(B_FALSE);
1837 		}
1838 	}
1839 
1840 	argc -= optind;
1841 	argv += optind;
1842 
1843 	/* check number of arguments */
1844 	if (argc < 1) {
1845 		(void) fprintf(stderr, gettext("missing dataset argument\n"));
1846 		usage(B_FALSE);
1847 	}
1848 	if (argc > 1) {
1849 		(void) fprintf(stderr, gettext("too many arguments\n"));
1850 		usage(B_FALSE);
1851 	}
1852 
1853 	/* open the snapshot */
1854 	if ((snap = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL)
1855 		return (1);
1856 
1857 	/* open the parent dataset */
1858 	(void) strlcpy(parentname, argv[0], sizeof (parentname));
1859 	verify((delim = strrchr(parentname, '@')) != NULL);
1860 	*delim = '\0';
1861 	if ((zhp = zfs_open(g_zfs, parentname, ZFS_TYPE_ANY)) == NULL) {
1862 		zfs_close(snap);
1863 		return (1);
1864 	}
1865 
1866 	/*
1867 	 * Check for more recent snapshots and/or clones based on the presence
1868 	 * of '-r' and '-R'.
1869 	 */
1870 	cb.cb_target = argv[0];
1871 	cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
1872 	cb.cb_first = B_TRUE;
1873 	cb.cb_error = 0;
1874 	if ((ret = zfs_iter_children(zhp, rollback_check, &cb)) != 0)
1875 		goto out;
1876 
1877 	if ((ret = cb.cb_error) != 0)
1878 		goto out;
1879 
1880 	/*
1881 	 * Rollback parent to the given snapshot.
1882 	 */
1883 	ret = zfs_rollback(zhp, snap, force);
1884 
1885 	if (!ret) {
1886 		zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
1887 		    B_FALSE, B_FALSE);
1888 	}
1889 
1890 out:
1891 	zfs_close(snap);
1892 	zfs_close(zhp);
1893 
1894 	if (ret == 0)
1895 		return (0);
1896 	else
1897 		return (1);
1898 }
1899 
1900 /*
1901  * zfs set property=value { fs | snap | vol } ...
1902  *
1903  * Sets the given property for all datasets specified on the command line.
1904  */
1905 typedef struct set_cbdata {
1906 	char		*cb_propname;
1907 	char		*cb_value;
1908 	boolean_t	cb_any_successful;
1909 } set_cbdata_t;
1910 
1911 static int
1912 set_callback(zfs_handle_t *zhp, void *data)
1913 {
1914 	set_cbdata_t *cbp = data;
1915 
1916 	if (zfs_prop_set(zhp, cbp->cb_propname, cbp->cb_value) != 0) {
1917 		switch (libzfs_errno(g_zfs)) {
1918 		case EZFS_MOUNTFAILED:
1919 			(void) fprintf(stderr, gettext("property may be set "
1920 			    "but unable to remount filesystem\n"));
1921 			break;
1922 		case EZFS_SHAREFAILED:
1923 			(void) fprintf(stderr, gettext("property may be set "
1924 			    "but unable to reshare filesystem\n"));
1925 			break;
1926 		}
1927 		return (1);
1928 	}
1929 	cbp->cb_any_successful = B_TRUE;
1930 	return (0);
1931 }
1932 
1933 static int
1934 zfs_do_set(int argc, char **argv)
1935 {
1936 	set_cbdata_t cb;
1937 	int ret;
1938 
1939 	/* check for options */
1940 	if (argc > 1 && argv[1][0] == '-') {
1941 		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1942 		    argv[1][1]);
1943 		usage(B_FALSE);
1944 	}
1945 
1946 	/* check number of arguments */
1947 	if (argc < 2) {
1948 		(void) fprintf(stderr, gettext("missing property=value "
1949 		    "argument\n"));
1950 		usage(B_FALSE);
1951 	}
1952 	if (argc < 3) {
1953 		(void) fprintf(stderr, gettext("missing dataset name\n"));
1954 		usage(B_FALSE);
1955 	}
1956 
1957 	/* validate property=value argument */
1958 	cb.cb_propname = argv[1];
1959 	if ((cb.cb_value = strchr(cb.cb_propname, '=')) == NULL) {
1960 		(void) fprintf(stderr, gettext("missing value in "
1961 		    "property=value argument\n"));
1962 		usage(B_FALSE);
1963 	}
1964 
1965 	*cb.cb_value = '\0';
1966 	cb.cb_value++;
1967 	cb.cb_any_successful = B_FALSE;
1968 
1969 	if (*cb.cb_propname == '\0') {
1970 		(void) fprintf(stderr,
1971 		    gettext("missing property in property=value argument\n"));
1972 		usage(B_FALSE);
1973 	}
1974 
1975 	ret = zfs_for_each(argc - 2, argv + 2, B_FALSE,
1976 	    ZFS_TYPE_ANY, NULL, NULL, set_callback, &cb);
1977 
1978 	if (cb.cb_any_successful) {
1979 		*(cb.cb_value - 1) = '=';
1980 		zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE);
1981 	}
1982 
1983 	return (ret);
1984 }
1985 
1986 /*
1987  * zfs snapshot [-r] <fs@snap>
1988  *
1989  * Creates a snapshot with the given name.  While functionally equivalent to
1990  * 'zfs create', it is a separate command to diffferentiate intent.
1991  */
1992 static int
1993 zfs_do_snapshot(int argc, char **argv)
1994 {
1995 	int recursive = B_FALSE;
1996 	int ret;
1997 	char c;
1998 
1999 	/* check options */
2000 	while ((c = getopt(argc, argv, ":r")) != -1) {
2001 		switch (c) {
2002 		case 'r':
2003 			recursive = B_TRUE;
2004 			break;
2005 		case '?':
2006 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2007 			    optopt);
2008 			usage(B_FALSE);
2009 		}
2010 	}
2011 
2012 	argc -= optind;
2013 	argv += optind;
2014 
2015 	/* check number of arguments */
2016 	if (argc < 1) {
2017 		(void) fprintf(stderr, gettext("missing snapshot argument\n"));
2018 		usage(B_FALSE);
2019 	}
2020 	if (argc > 1) {
2021 		(void) fprintf(stderr, gettext("too many arguments\n"));
2022 		usage(B_FALSE);
2023 	}
2024 
2025 	ret = zfs_snapshot(g_zfs, argv[0], recursive);
2026 	if (ret && recursive)
2027 		(void) fprintf(stderr, gettext("no snapshots were created\n"));
2028 	if (!ret) {
2029 		zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
2030 		    B_FALSE, B_FALSE);
2031 	}
2032 	return (ret != 0);
2033 }
2034 
2035 /*
2036  * zfs send [-i <@snap>] <fs@snap>
2037  *
2038  * Send a backup stream to stdout.
2039  */
2040 static int
2041 zfs_do_send(int argc, char **argv)
2042 {
2043 	char *fromname = NULL;
2044 	char *cp;
2045 	zfs_handle_t *zhp;
2046 	int c, err;
2047 
2048 	/* check options */
2049 	while ((c = getopt(argc, argv, ":i:")) != -1) {
2050 		switch (c) {
2051 		case 'i':
2052 			if (fromname)
2053 				usage(B_FALSE);
2054 			fromname = optarg;
2055 			break;
2056 		case ':':
2057 			(void) fprintf(stderr, gettext("missing argument for "
2058 			    "'%c' option\n"), optopt);
2059 			usage(B_FALSE);
2060 			break;
2061 		case '?':
2062 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2063 			    optopt);
2064 			usage(B_FALSE);
2065 		}
2066 	}
2067 
2068 	argc -= optind;
2069 	argv += optind;
2070 
2071 	/* check number of arguments */
2072 	if (argc < 1) {
2073 		(void) fprintf(stderr, gettext("missing snapshot argument\n"));
2074 		usage(B_FALSE);
2075 	}
2076 	if (argc > 1) {
2077 		(void) fprintf(stderr, gettext("too many arguments\n"));
2078 		usage(B_FALSE);
2079 	}
2080 
2081 	if (isatty(STDOUT_FILENO)) {
2082 		(void) fprintf(stderr,
2083 		    gettext("Error: Stream can not be written to a terminal.\n"
2084 			    "You must redirect standard output.\n"));
2085 		return (1);
2086 	}
2087 
2088 	if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL)
2089 		return (1);
2090 
2091 	/*
2092 	 * If they specified the full path to the snapshot, chop off
2093 	 * everything except the short name of the snapshot.
2094 	 */
2095 	if (fromname && (cp = strchr(fromname, '@')) != NULL) {
2096 		if (cp != fromname &&
2097 		    strncmp(argv[0], fromname, cp - fromname + 1)) {
2098 			(void) fprintf(stderr,
2099 			    gettext("incremental source must be "
2100 			    "in same filesystem\n"));
2101 			usage(B_FALSE);
2102 		}
2103 		fromname = cp + 1;
2104 		if (strchr(fromname, '@') || strchr(fromname, '/')) {
2105 			(void) fprintf(stderr,
2106 			    gettext("invalid incremental source\n"));
2107 			usage(B_FALSE);
2108 		}
2109 	}
2110 
2111 	err = zfs_send(zhp, fromname);
2112 	zfs_close(zhp);
2113 
2114 	return (err != 0);
2115 }
2116 
2117 /*
2118  * zfs receive <fs@snap>
2119  *
2120  * Restore a backup stream from stdin.
2121  */
2122 static int
2123 zfs_do_receive(int argc, char **argv)
2124 {
2125 	int c, err;
2126 	boolean_t isprefix = B_FALSE;
2127 	boolean_t dryrun = B_FALSE;
2128 	boolean_t verbose = B_FALSE;
2129 	boolean_t force = B_FALSE;
2130 
2131 	/* check options */
2132 	while ((c = getopt(argc, argv, ":dnvF")) != -1) {
2133 		switch (c) {
2134 		case 'd':
2135 			isprefix = B_TRUE;
2136 			break;
2137 		case 'n':
2138 			dryrun = B_TRUE;
2139 			break;
2140 		case 'v':
2141 			verbose = B_TRUE;
2142 			break;
2143 		case 'F':
2144 			force = B_TRUE;
2145 			break;
2146 		case ':':
2147 			(void) fprintf(stderr, gettext("missing argument for "
2148 			    "'%c' option\n"), optopt);
2149 			usage(B_FALSE);
2150 			break;
2151 		case '?':
2152 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2153 			    optopt);
2154 			usage(B_FALSE);
2155 		}
2156 	}
2157 
2158 	argc -= optind;
2159 	argv += optind;
2160 
2161 	/* check number of arguments */
2162 	if (argc < 1) {
2163 		(void) fprintf(stderr, gettext("missing snapshot argument\n"));
2164 		usage(B_FALSE);
2165 	}
2166 	if (argc > 1) {
2167 		(void) fprintf(stderr, gettext("too many arguments\n"));
2168 		usage(B_FALSE);
2169 	}
2170 
2171 	if (isatty(STDIN_FILENO)) {
2172 		(void) fprintf(stderr,
2173 		    gettext("Error: Backup stream can not be read "
2174 			    "from a terminal.\n"
2175 			    "You must redirect standard input.\n"));
2176 		return (1);
2177 	}
2178 
2179 	err = zfs_receive(g_zfs, argv[0], isprefix, verbose, dryrun, force);
2180 
2181 	if (!err) {
2182 		zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0],
2183 		    B_FALSE, B_FALSE);
2184 	}
2185 
2186 	return (err != 0);
2187 }
2188 
2189 typedef struct get_all_cbdata {
2190 	zfs_handle_t	**cb_handles;
2191 	size_t		cb_alloc;
2192 	size_t		cb_used;
2193 } get_all_cbdata_t;
2194 
2195 static int
2196 get_one_filesystem(zfs_handle_t *zhp, void *data)
2197 {
2198 	get_all_cbdata_t *cbp = data;
2199 
2200 	/*
2201 	 * Skip any zvols
2202 	 */
2203 	if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
2204 		zfs_close(zhp);
2205 		return (0);
2206 	}
2207 
2208 	if (cbp->cb_alloc == cbp->cb_used) {
2209 		zfs_handle_t **handles;
2210 
2211 		if (cbp->cb_alloc == 0)
2212 			cbp->cb_alloc = 64;
2213 		else
2214 			cbp->cb_alloc *= 2;
2215 
2216 		handles = safe_malloc(cbp->cb_alloc * sizeof (void *));
2217 
2218 		if (cbp->cb_handles) {
2219 			bcopy(cbp->cb_handles, handles,
2220 			    cbp->cb_used * sizeof (void *));
2221 			free(cbp->cb_handles);
2222 		}
2223 
2224 		cbp->cb_handles = handles;
2225 	}
2226 
2227 	cbp->cb_handles[cbp->cb_used++] = zhp;
2228 
2229 	return (zfs_iter_filesystems(zhp, get_one_filesystem, data));
2230 }
2231 
2232 static void
2233 get_all_filesystems(zfs_handle_t ***fslist, size_t *count)
2234 {
2235 	get_all_cbdata_t cb = { 0 };
2236 
2237 	(void) zfs_iter_root(g_zfs, get_one_filesystem, &cb);
2238 
2239 	*fslist = cb.cb_handles;
2240 	*count = cb.cb_used;
2241 }
2242 
2243 static int
2244 mountpoint_compare(const void *a, const void *b)
2245 {
2246 	zfs_handle_t **za = (zfs_handle_t **)a;
2247 	zfs_handle_t **zb = (zfs_handle_t **)b;
2248 	char mounta[MAXPATHLEN];
2249 	char mountb[MAXPATHLEN];
2250 
2251 	verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta,
2252 	    sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0);
2253 	verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb,
2254 	    sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0);
2255 
2256 	return (strcmp(mounta, mountb));
2257 }
2258 
2259 /*
2260  * Generic callback for sharing or mounting filesystems.  Because the code is so
2261  * similar, we have a common function with an extra parameter to determine which
2262  * mode we are using.
2263  */
2264 #define	OP_SHARE	0x1
2265 #define	OP_MOUNT	0x2
2266 
2267 typedef struct share_mount_cbdata {
2268 	int	cb_type;
2269 	int	cb_explicit;
2270 	int	cb_flags;
2271 	const char *cb_options;
2272 } share_mount_cbdata_t;
2273 
2274 /*
2275  * Share or mount the filesystem.
2276  */
2277 static int
2278 share_mount_callback(zfs_handle_t *zhp, void *data)
2279 {
2280 	char mountpoint[ZFS_MAXPROPLEN];
2281 	char shareopts[ZFS_MAXPROPLEN];
2282 	share_mount_cbdata_t *cbp = data;
2283 	const char *cmdname = cbp->cb_type == OP_SHARE ? "share" : "mount";
2284 	struct mnttab mnt;
2285 	uint64_t zoned, canmount;
2286 
2287 	if (cbp->cb_options == NULL)
2288 		mnt.mnt_mntopts = "";
2289 	else
2290 		mnt.mnt_mntopts = (char *)cbp->cb_options;
2291 
2292 	/*
2293 	 * Check to make sure we can mount/share this dataset.  If we are in the
2294 	 * global zone and the filesystem is exported to a local zone, or if we
2295 	 * are in a local zone and the filesystem is not exported, then it is an
2296 	 * error.
2297 	 */
2298 	zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
2299 
2300 	if (zoned && getzoneid() == GLOBAL_ZONEID) {
2301 		if (!cbp->cb_explicit)
2302 			return (0);
2303 
2304 		(void) fprintf(stderr, gettext("cannot %s '%s': dataset is "
2305 		    "exported to a local zone\n"), cmdname, zfs_get_name(zhp));
2306 		return (1);
2307 
2308 	} else if (!zoned && getzoneid() != GLOBAL_ZONEID) {
2309 		if (!cbp->cb_explicit)
2310 			return (0);
2311 
2312 		(void) fprintf(stderr, gettext("cannot %s '%s': permission "
2313 		    "denied\n"), cmdname, zfs_get_name(zhp));
2314 		return (1);
2315 	}
2316 
2317 	/*
2318 	 * Inore any filesystems which don't apply to us.  This includes those
2319 	 * with a legacy mountpoint, or those with legacy share options.
2320 	 */
2321 	verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
2322 	    sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
2323 	verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts,
2324 	    sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0);
2325 	canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
2326 
2327 	if (cbp->cb_type == OP_SHARE) {
2328 		if (strcmp(shareopts, "off") == 0) {
2329 			if (!cbp->cb_explicit)
2330 				return (0);
2331 
2332 			(void) fprintf(stderr, gettext("cannot share '%s': "
2333 			    "legacy share\n"), zfs_get_name(zhp));
2334 			(void) fprintf(stderr, gettext("use share(1M) to "
2335 			    "share this filesystem\n"));
2336 			return (1);
2337 		}
2338 	}
2339 
2340 	/*
2341 	 * We cannot share or mount legacy filesystems.  If the shareopts is
2342 	 * non-legacy but the mountpoint is legacy, we treat it as a legacy
2343 	 * share.
2344 	 */
2345 	if (strcmp(mountpoint, "legacy") == 0) {
2346 		if (!cbp->cb_explicit)
2347 			return (0);
2348 
2349 		(void) fprintf(stderr, gettext("cannot %s '%s': "
2350 		    "legacy mountpoint\n"), cmdname, zfs_get_name(zhp));
2351 		(void) fprintf(stderr, gettext("use %s to "
2352 		    "%s this filesystem\n"), cbp->cb_type == OP_SHARE ?
2353 		    "share(1M)" : "mount(1M)", cmdname);
2354 		return (1);
2355 	}
2356 
2357 	if (strcmp(mountpoint, "none") == 0) {
2358 		if (!cbp->cb_explicit)
2359 			return (0);
2360 
2361 		(void) fprintf(stderr, gettext("cannot %s '%s': no "
2362 		    "mountpoint set\n"), cmdname, zfs_get_name(zhp));
2363 		return (1);
2364 	}
2365 
2366 	if (!canmount) {
2367 		if (!cbp->cb_explicit)
2368 			return (0);
2369 
2370 		(void) fprintf(stderr, gettext("cannot %s '%s': 'canmount' "
2371 		    "property is set to 'off'\n"), cmdname, zfs_get_name(zhp));
2372 		return (1);
2373 	}
2374 
2375 	/*
2376 	 * At this point, we have verified that the mountpoint and/or shareopts
2377 	 * are appropriate for auto management.  Determine if the filesystem is
2378 	 * currently mounted or shared, and abort if this is an explicit
2379 	 * request.
2380 	 */
2381 	switch (cbp->cb_type) {
2382 	case OP_SHARE:
2383 		if (zfs_is_shared(zhp, NULL)) {
2384 			if (cbp->cb_explicit) {
2385 				(void) fprintf(stderr, gettext("cannot share "
2386 				    "'%s': filesystem already shared\n"),
2387 				    zfs_get_name(zhp));
2388 				return (1);
2389 			} else {
2390 				return (0);
2391 			}
2392 		}
2393 		break;
2394 
2395 	case OP_MOUNT:
2396 		if (!hasmntopt(&mnt, MNTOPT_REMOUNT) &&
2397 		    zfs_is_mounted(zhp, NULL)) {
2398 			if (cbp->cb_explicit) {
2399 				(void) fprintf(stderr, gettext("cannot mount "
2400 				    "'%s': filesystem already mounted\n"),
2401 				    zfs_get_name(zhp));
2402 				return (1);
2403 			} else {
2404 				return (0);
2405 			}
2406 		}
2407 		break;
2408 	}
2409 
2410 	/*
2411 	 * Mount and optionally share the filesystem.
2412 	 */
2413 	switch (cbp->cb_type) {
2414 	case OP_SHARE:
2415 		{
2416 			if (!zfs_is_mounted(zhp, NULL) &&
2417 			    zfs_mount(zhp, NULL, 0) != 0)
2418 				return (1);
2419 
2420 			if (zfs_share(zhp) != 0)
2421 				return (1);
2422 		}
2423 		break;
2424 
2425 	case OP_MOUNT:
2426 		if (zfs_mount(zhp, cbp->cb_options, cbp->cb_flags) != 0)
2427 			return (1);
2428 		break;
2429 	}
2430 
2431 	return (0);
2432 }
2433 
2434 static int
2435 share_or_mount(int type, int argc, char **argv)
2436 {
2437 	int do_all = 0;
2438 	int c, ret = 0;
2439 	share_mount_cbdata_t cb = { 0 };
2440 
2441 	cb.cb_type = type;
2442 
2443 	/* check options */
2444 	while ((c = getopt(argc, argv, type == OP_MOUNT ? ":ao:O" : "a"))
2445 	    != -1) {
2446 		switch (c) {
2447 		case 'a':
2448 			do_all = 1;
2449 			break;
2450 		case 'o':
2451 			cb.cb_options = optarg;
2452 			break;
2453 		case 'O':
2454 			cb.cb_flags |= MS_OVERLAY;
2455 			break;
2456 		case ':':
2457 			(void) fprintf(stderr, gettext("missing argument for "
2458 			    "'%c' option\n"), optopt);
2459 			usage(B_FALSE);
2460 			break;
2461 		case '?':
2462 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2463 			    optopt);
2464 			usage(B_FALSE);
2465 		}
2466 	}
2467 
2468 	argc -= optind;
2469 	argv += optind;
2470 
2471 	/* check number of arguments */
2472 	if (do_all) {
2473 		zfs_handle_t **fslist = NULL;
2474 		size_t i, count = 0;
2475 
2476 		if (argc != 0) {
2477 			(void) fprintf(stderr, gettext("too many arguments\n"));
2478 			usage(B_FALSE);
2479 		}
2480 
2481 		get_all_filesystems(&fslist, &count);
2482 
2483 		if (count == 0)
2484 			return (0);
2485 
2486 		qsort(fslist, count, sizeof (void *), mountpoint_compare);
2487 
2488 		for (i = 0; i < count; i++) {
2489 			if (share_mount_callback(fslist[i], &cb) != 0)
2490 				ret = 1;
2491 		}
2492 
2493 		for (i = 0; i < count; i++)
2494 			zfs_close(fslist[i]);
2495 
2496 		free(fslist);
2497 	} else if (argc == 0) {
2498 		struct mnttab entry;
2499 
2500 		if (type == OP_SHARE) {
2501 			(void) fprintf(stderr, gettext("missing filesystem "
2502 			    "argument\n"));
2503 			usage(B_FALSE);
2504 		}
2505 
2506 		/*
2507 		 * When mount is given no arguments, go through /etc/mnttab and
2508 		 * display any active ZFS mounts.  We hide any snapshots, since
2509 		 * they are controlled automatically.
2510 		 */
2511 		rewind(mnttab_file);
2512 		while (getmntent(mnttab_file, &entry) == 0) {
2513 			if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0 ||
2514 			    strchr(entry.mnt_special, '@') != NULL)
2515 				continue;
2516 
2517 			(void) printf("%-30s  %s\n", entry.mnt_special,
2518 			    entry.mnt_mountp);
2519 		}
2520 
2521 	} else {
2522 		zfs_handle_t *zhp;
2523 
2524 		if (argc > 1) {
2525 			(void) fprintf(stderr,
2526 			    gettext("too many arguments\n"));
2527 			usage(B_FALSE);
2528 		}
2529 
2530 		if ((zhp = zfs_open(g_zfs, argv[0],
2531 		    ZFS_TYPE_FILESYSTEM)) == NULL)
2532 			ret = 1;
2533 		else {
2534 			cb.cb_explicit = B_TRUE;
2535 			ret = share_mount_callback(zhp, &cb);
2536 			zfs_close(zhp);
2537 		}
2538 	}
2539 
2540 	return (ret);
2541 }
2542 
2543 /*
2544  * zfs mount -a
2545  * zfs mount filesystem
2546  *
2547  * Mount all filesystems, or mount the given filesystem.
2548  */
2549 static int
2550 zfs_do_mount(int argc, char **argv)
2551 {
2552 	return (share_or_mount(OP_MOUNT, argc, argv));
2553 }
2554 
2555 /*
2556  * zfs share -a
2557  * zfs share filesystem
2558  *
2559  * Share all filesystems, or share the given filesystem.
2560  */
2561 static int
2562 zfs_do_share(int argc, char **argv)
2563 {
2564 	return (share_or_mount(OP_SHARE, argc, argv));
2565 }
2566 
2567 typedef struct unshare_unmount_node {
2568 	zfs_handle_t	*un_zhp;
2569 	char		*un_mountp;
2570 	uu_avl_node_t	un_avlnode;
2571 } unshare_unmount_node_t;
2572 
2573 /* ARGSUSED */
2574 static int
2575 unshare_unmount_compare(const void *larg, const void *rarg, void *unused)
2576 {
2577 	const unshare_unmount_node_t *l = larg;
2578 	const unshare_unmount_node_t *r = rarg;
2579 
2580 	return (strcmp(l->un_mountp, r->un_mountp));
2581 }
2582 
2583 /*
2584  * Convenience routine used by zfs_do_umount() and manual_unmount().  Given an
2585  * absolute path, find the entry /etc/mnttab, verify that its a ZFS filesystem,
2586  * and unmount it appropriately.
2587  */
2588 static int
2589 unshare_unmount_path(int type, char *path, int flags, boolean_t is_manual)
2590 {
2591 	zfs_handle_t *zhp;
2592 	int ret;
2593 	struct stat64 statbuf;
2594 	struct extmnttab entry;
2595 	const char *cmdname = (type == OP_SHARE) ? "unshare" : "unmount";
2596 	char property[ZFS_MAXPROPLEN];
2597 
2598 	/*
2599 	 * Search for the path in /etc/mnttab.  Rather than looking for the
2600 	 * specific path, which can be fooled by non-standard paths (i.e. ".."
2601 	 * or "//"), we stat() the path and search for the corresponding
2602 	 * (major,minor) device pair.
2603 	 */
2604 	if (stat64(path, &statbuf) != 0) {
2605 		(void) fprintf(stderr, gettext("cannot %s '%s': %s\n"),
2606 		    cmdname, path, strerror(errno));
2607 		return (1);
2608 	}
2609 
2610 	/*
2611 	 * Search for the given (major,minor) pair in the mount table.
2612 	 */
2613 	rewind(mnttab_file);
2614 	while ((ret = getextmntent(mnttab_file, &entry, 0)) == 0) {
2615 		if (entry.mnt_major == major(statbuf.st_dev) &&
2616 		    entry.mnt_minor == minor(statbuf.st_dev))
2617 			break;
2618 	}
2619 	if (ret != 0) {
2620 		(void) fprintf(stderr, gettext("cannot %s '%s': not "
2621 		    "currently mounted\n"), cmdname, path);
2622 		return (1);
2623 	}
2624 
2625 	if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
2626 		(void) fprintf(stderr, gettext("cannot %s '%s': not a ZFS "
2627 		    "filesystem\n"), cmdname, path);
2628 		return (1);
2629 	}
2630 
2631 	if ((zhp = zfs_open(g_zfs, entry.mnt_special,
2632 	    ZFS_TYPE_FILESYSTEM)) == NULL)
2633 		return (1);
2634 
2635 	verify(zfs_prop_get(zhp, type == OP_SHARE ?
2636 		ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property,
2637 		sizeof (property), NULL, NULL, 0, B_FALSE) == 0);
2638 
2639 	if (type == OP_SHARE) {
2640 		if (strcmp(property, "off") == 0) {
2641 			(void) fprintf(stderr, gettext("cannot unshare "
2642 			    "'%s': legacy share\n"), path);
2643 			(void) fprintf(stderr, gettext("use "
2644 			    "unshare(1M) to unshare this filesystem\n"));
2645 			ret = 1;
2646 		} else if (!zfs_is_shared(zhp, NULL)) {
2647 			(void) fprintf(stderr, gettext("cannot unshare '%s': "
2648 			    "not currently shared\n"), path);
2649 			ret = 1;
2650 		} else {
2651 			ret = zfs_unshareall(zhp);
2652 		}
2653 	} else {
2654 		if (is_manual) {
2655 			ret = zfs_unmount(zhp, NULL, flags);
2656 		} else if (strcmp(property, "legacy") == 0) {
2657 			(void) fprintf(stderr, gettext("cannot unmount "
2658 			    "'%s': legacy mountpoint\n"),
2659 			    zfs_get_name(zhp));
2660 			(void) fprintf(stderr, gettext("use umount(1M) "
2661 			    "to unmount this filesystem\n"));
2662 			ret = 1;
2663 		} else {
2664 			ret = zfs_unmountall(zhp, flags);
2665 		}
2666 	}
2667 
2668 	zfs_close(zhp);
2669 
2670 	return (ret != 0);
2671 }
2672 
2673 /*
2674  * Generic callback for unsharing or unmounting a filesystem.
2675  */
2676 static int
2677 unshare_unmount(int type, int argc, char **argv)
2678 {
2679 	int do_all = 0;
2680 	int flags = 0;
2681 	int ret = 0;
2682 	int c;
2683 	zfs_handle_t *zhp;
2684 	char property[ZFS_MAXPROPLEN];
2685 
2686 	/* check options */
2687 	while ((c = getopt(argc, argv, type == OP_SHARE ? "a" : "af")) != -1) {
2688 		switch (c) {
2689 		case 'a':
2690 			do_all = 1;
2691 			break;
2692 		case 'f':
2693 			flags = MS_FORCE;
2694 			break;
2695 		case '?':
2696 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2697 			    optopt);
2698 			usage(B_FALSE);
2699 		}
2700 	}
2701 
2702 	argc -= optind;
2703 	argv += optind;
2704 
2705 	/* ensure correct number of arguments */
2706 	if (do_all) {
2707 		if (argc != 0) {
2708 			(void) fprintf(stderr, gettext("too many arguments\n"));
2709 			usage(B_FALSE);
2710 		}
2711 	} else if (argc != 1) {
2712 		if (argc == 0)
2713 			(void) fprintf(stderr,
2714 			    gettext("missing filesystem argument\n"));
2715 		else
2716 			(void) fprintf(stderr,
2717 			    gettext("too many arguments\n"));
2718 		usage(B_FALSE);
2719 	}
2720 
2721 	if (do_all) {
2722 		/*
2723 		 * We could make use of zfs_for_each() to walk all datasets in
2724 		 * the system, but this would be very inefficient, especially
2725 		 * since we would have to linearly search /etc/mnttab for each
2726 		 * one.  Instead, do one pass through /etc/mnttab looking for
2727 		 * zfs entries and call zfs_unmount() for each one.
2728 		 *
2729 		 * Things get a little tricky if the administrator has created
2730 		 * mountpoints beneath other ZFS filesystems.  In this case, we
2731 		 * have to unmount the deepest filesystems first.  To accomplish
2732 		 * this, we place all the mountpoints in an AVL tree sorted by
2733 		 * the special type (dataset name), and walk the result in
2734 		 * reverse to make sure to get any snapshots first.
2735 		 */
2736 		struct mnttab entry;
2737 		uu_avl_pool_t *pool;
2738 		uu_avl_t *tree;
2739 		unshare_unmount_node_t *node;
2740 		uu_avl_index_t idx;
2741 		uu_avl_walk_t *walk;
2742 
2743 		if ((pool = uu_avl_pool_create("unmount_pool",
2744 		    sizeof (unshare_unmount_node_t),
2745 		    offsetof(unshare_unmount_node_t, un_avlnode),
2746 		    unshare_unmount_compare,
2747 		    UU_DEFAULT)) == NULL) {
2748 			(void) fprintf(stderr, gettext("internal error: "
2749 			    "out of memory\n"));
2750 			exit(1);
2751 		}
2752 
2753 		if ((tree = uu_avl_create(pool, NULL, UU_DEFAULT)) == NULL) {
2754 			(void) fprintf(stderr, gettext("internal error: "
2755 			    "out of memory\n"));
2756 			exit(1);
2757 		}
2758 
2759 		rewind(mnttab_file);
2760 		while (getmntent(mnttab_file, &entry) == 0) {
2761 
2762 			/* ignore non-ZFS entries */
2763 			if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
2764 				continue;
2765 
2766 			/* ignore snapshots */
2767 			if (strchr(entry.mnt_special, '@') != NULL)
2768 				continue;
2769 
2770 			if ((zhp = zfs_open(g_zfs, entry.mnt_special,
2771 			    ZFS_TYPE_FILESYSTEM)) == NULL) {
2772 				ret = 1;
2773 				continue;
2774 			}
2775 
2776 			verify(zfs_prop_get(zhp, type == OP_SHARE ?
2777 			    ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT,
2778 			    property, sizeof (property), NULL, NULL,
2779 			    0, B_FALSE) == 0);
2780 
2781 			/* Ignore legacy mounts and shares */
2782 			if ((type == OP_SHARE &&
2783 			    strcmp(property, "off") == 0) ||
2784 			    (type == OP_MOUNT &&
2785 			    strcmp(property, "legacy") == 0)) {
2786 				zfs_close(zhp);
2787 				continue;
2788 			}
2789 
2790 			node = safe_malloc(sizeof (unshare_unmount_node_t));
2791 			node->un_zhp = zhp;
2792 
2793 			if ((node->un_mountp = strdup(entry.mnt_mountp)) ==
2794 			    NULL) {
2795 				(void) fprintf(stderr, gettext("internal error:"
2796 				    " out of memory\n"));
2797 				exit(1);
2798 			}
2799 
2800 			uu_avl_node_init(node, &node->un_avlnode, pool);
2801 
2802 			if (uu_avl_find(tree, node, NULL, &idx) == NULL) {
2803 				uu_avl_insert(tree, node, idx);
2804 			} else {
2805 				zfs_close(node->un_zhp);
2806 				free(node->un_mountp);
2807 				free(node);
2808 			}
2809 		}
2810 
2811 		/*
2812 		 * Walk the AVL tree in reverse, unmounting each filesystem and
2813 		 * removing it from the AVL tree in the process.
2814 		 */
2815 		if ((walk = uu_avl_walk_start(tree,
2816 		    UU_WALK_REVERSE | UU_WALK_ROBUST)) == NULL) {
2817 			(void) fprintf(stderr,
2818 			    gettext("internal error: out of memory"));
2819 			exit(1);
2820 		}
2821 
2822 		while ((node = uu_avl_walk_next(walk)) != NULL) {
2823 			uu_avl_remove(tree, node);
2824 
2825 			switch (type) {
2826 			case OP_SHARE:
2827 				if (zfs_unshare(node->un_zhp,
2828 				    node->un_mountp) != 0)
2829 					ret = 1;
2830 				break;
2831 
2832 			case OP_MOUNT:
2833 				if (zfs_unmount(node->un_zhp,
2834 				    node->un_mountp, flags) != 0)
2835 					ret = 1;
2836 				break;
2837 			}
2838 
2839 			zfs_close(node->un_zhp);
2840 			free(node->un_mountp);
2841 			free(node);
2842 		}
2843 
2844 		uu_avl_walk_end(walk);
2845 		uu_avl_destroy(tree);
2846 		uu_avl_pool_destroy(pool);
2847 	} else {
2848 		/*
2849 		 * We have an argument, but it may be a full path or a ZFS
2850 		 * filesystem.  Pass full paths off to unmount_path() (shared by
2851 		 * manual_unmount), otherwise open the filesystem and pass to
2852 		 * zfs_unmount().
2853 		 */
2854 		if (argv[0][0] == '/')
2855 			return (unshare_unmount_path(type, argv[0],
2856 				flags, B_FALSE));
2857 
2858 		if ((zhp = zfs_open(g_zfs, argv[0],
2859 		    ZFS_TYPE_FILESYSTEM)) == NULL)
2860 			return (1);
2861 
2862 		verify(zfs_prop_get(zhp, type == OP_SHARE ?
2863 		    ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property,
2864 		    sizeof (property), NULL, NULL, 0, B_FALSE) == 0);
2865 
2866 		switch (type) {
2867 		case OP_SHARE:
2868 			if (strcmp(property, "off") == 0) {
2869 				(void) fprintf(stderr, gettext("cannot unshare "
2870 				    "'%s': legacy share\n"), zfs_get_name(zhp));
2871 				(void) fprintf(stderr, gettext("use unshare(1M)"
2872 				    " to unshare this filesystem\n"));
2873 				ret = 1;
2874 			} else if (!zfs_is_shared(zhp, NULL)) {
2875 				(void) fprintf(stderr, gettext("cannot unshare "
2876 				    "'%s': not currently shared\n"),
2877 				    zfs_get_name(zhp));
2878 				ret = 1;
2879 			} else if (zfs_unshareall(zhp) != 0) {
2880 				ret = 1;
2881 			}
2882 			break;
2883 
2884 		case OP_MOUNT:
2885 			if (strcmp(property, "legacy") == 0) {
2886 				(void) fprintf(stderr, gettext("cannot unmount "
2887 				    "'%s': legacy mountpoint\n"),
2888 				    zfs_get_name(zhp));
2889 				(void) fprintf(stderr, gettext("use umount(1M) "
2890 				    "to unmount this filesystem\n"));
2891 				ret = 1;
2892 			} else if (!zfs_is_mounted(zhp, NULL)) {
2893 				(void) fprintf(stderr, gettext("cannot unmount "
2894 				    "'%s': not currently mounted\n"),
2895 				    zfs_get_name(zhp));
2896 				ret = 1;
2897 			} else if (zfs_unmountall(zhp, flags) != 0) {
2898 				ret = 1;
2899 			}
2900 		}
2901 
2902 		zfs_close(zhp);
2903 	}
2904 
2905 	return (ret);
2906 }
2907 
2908 /*
2909  * zfs unmount -a
2910  * zfs unmount filesystem
2911  *
2912  * Unmount all filesystems, or a specific ZFS filesystem.
2913  */
2914 static int
2915 zfs_do_unmount(int argc, char **argv)
2916 {
2917 	return (unshare_unmount(OP_MOUNT, argc, argv));
2918 }
2919 
2920 /*
2921  * zfs unshare -a
2922  * zfs unshare filesystem
2923  *
2924  * Unshare all filesystems, or a specific ZFS filesystem.
2925  */
2926 static int
2927 zfs_do_unshare(int argc, char **argv)
2928 {
2929 	return (unshare_unmount(OP_SHARE, argc, argv));
2930 }
2931 
2932 /*
2933  * Called when invoked as /etc/fs/zfs/mount.  Do the mount if the mountpoint is
2934  * 'legacy'.  Otherwise, complain that use should be using 'zfs mount'.
2935  */
2936 static int
2937 manual_mount(int argc, char **argv)
2938 {
2939 	zfs_handle_t *zhp;
2940 	char mountpoint[ZFS_MAXPROPLEN];
2941 	char mntopts[MNT_LINE_MAX] = { '\0' };
2942 	int ret;
2943 	int c;
2944 	int flags = 0;
2945 	char *dataset, *path;
2946 
2947 	/* check options */
2948 	while ((c = getopt(argc, argv, ":mo:O")) != -1) {
2949 		switch (c) {
2950 		case 'o':
2951 			(void) strlcpy(mntopts, optarg, sizeof (mntopts));
2952 			break;
2953 		case 'O':
2954 			flags |= MS_OVERLAY;
2955 			break;
2956 		case 'm':
2957 			flags |= MS_NOMNTTAB;
2958 			break;
2959 		case ':':
2960 			(void) fprintf(stderr, gettext("missing argument for "
2961 			    "'%c' option\n"), optopt);
2962 			usage(B_FALSE);
2963 			break;
2964 		case '?':
2965 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2966 			    optopt);
2967 			(void) fprintf(stderr, gettext("usage: mount [-o opts] "
2968 			    "<path>\n"));
2969 			return (2);
2970 		}
2971 	}
2972 
2973 	argc -= optind;
2974 	argv += optind;
2975 
2976 	/* check that we only have two arguments */
2977 	if (argc != 2) {
2978 		if (argc == 0)
2979 			(void) fprintf(stderr, gettext("missing dataset "
2980 			    "argument\n"));
2981 		else if (argc == 1)
2982 			(void) fprintf(stderr,
2983 			    gettext("missing mountpoint argument\n"));
2984 		else
2985 			(void) fprintf(stderr, gettext("too many arguments\n"));
2986 		(void) fprintf(stderr, "usage: mount <dataset> <mountpoint>\n");
2987 		return (2);
2988 	}
2989 
2990 	dataset = argv[0];
2991 	path = argv[1];
2992 
2993 	/* try to open the dataset */
2994 	if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_FILESYSTEM)) == NULL)
2995 		return (1);
2996 
2997 	(void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
2998 	    sizeof (mountpoint), NULL, NULL, 0, B_FALSE);
2999 
3000 	/* check for legacy mountpoint and complain appropriately */
3001 	ret = 0;
3002 	if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) {
3003 		if (mount(dataset, path, MS_OPTIONSTR | flags, MNTTYPE_ZFS,
3004 		    NULL, 0, mntopts, sizeof (mntopts)) != 0) {
3005 			(void) fprintf(stderr, gettext("mount failed: %s\n"),
3006 			    strerror(errno));
3007 			ret = 1;
3008 		}
3009 	} else {
3010 		(void) fprintf(stderr, gettext("filesystem '%s' cannot be "
3011 		    "mounted using 'mount -F zfs'\n"), dataset);
3012 		(void) fprintf(stderr, gettext("Use 'zfs set mountpoint=%s' "
3013 		    "instead.\n"), path);
3014 		(void) fprintf(stderr, gettext("If you must use 'mount -F zfs' "
3015 		    "or /etc/vfstab, use 'zfs set mountpoint=legacy'.\n"));
3016 		(void) fprintf(stderr, gettext("See zfs(1M) for more "
3017 		    "information.\n"));
3018 		ret = 1;
3019 	}
3020 
3021 	return (ret);
3022 }
3023 
3024 /*
3025  * Called when invoked as /etc/fs/zfs/umount.  Unlike a manual mount, we allow
3026  * unmounts of non-legacy filesystems, as this is the dominant administrative
3027  * interface.
3028  */
3029 static int
3030 manual_unmount(int argc, char **argv)
3031 {
3032 	int flags = 0;
3033 	int c;
3034 
3035 	/* check options */
3036 	while ((c = getopt(argc, argv, "f")) != -1) {
3037 		switch (c) {
3038 		case 'f':
3039 			flags = MS_FORCE;
3040 			break;
3041 		case '?':
3042 			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3043 			    optopt);
3044 			(void) fprintf(stderr, gettext("usage: unmount [-f] "
3045 			    "<path>\n"));
3046 			return (2);
3047 		}
3048 	}
3049 
3050 	argc -= optind;
3051 	argv += optind;
3052 
3053 	/* check arguments */
3054 	if (argc != 1) {
3055 		if (argc == 0)
3056 			(void) fprintf(stderr, gettext("missing path "
3057 			    "argument\n"));
3058 		else
3059 			(void) fprintf(stderr, gettext("too many arguments\n"));
3060 		(void) fprintf(stderr, gettext("usage: unmount [-f] <path>\n"));
3061 		return (2);
3062 	}
3063 
3064 	return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE));
3065 }
3066 
3067 static int
3068 volcheck(zpool_handle_t *zhp, void *data)
3069 {
3070 	boolean_t isinit = *((boolean_t *)data);
3071 
3072 	if (isinit)
3073 		return (zpool_create_zvol_links(zhp));
3074 	else
3075 		return (zpool_remove_zvol_links(zhp));
3076 }
3077 
3078 /*
3079  * Iterate over all pools in the system and either create or destroy /dev/zvol
3080  * links, depending on the value of 'isinit'.
3081  */
3082 static int
3083 do_volcheck(boolean_t isinit)
3084 {
3085 	return (zpool_iter(g_zfs, volcheck, &isinit) ? 1 : 0);
3086 }
3087 
3088 int
3089 main(int argc, char **argv)
3090 {
3091 	int ret;
3092 	int i;
3093 	char *progname;
3094 	char *cmdname;
3095 
3096 	(void) setlocale(LC_ALL, "");
3097 	(void) textdomain(TEXT_DOMAIN);
3098 
3099 	opterr = 0;
3100 
3101 	if ((g_zfs = libzfs_init()) == NULL) {
3102 		(void) fprintf(stderr, gettext("internal error: failed to "
3103 		    "initialize ZFS library\n"));
3104 		return (1);
3105 	}
3106 
3107 	libzfs_print_on_error(g_zfs, B_TRUE);
3108 
3109 	if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) {
3110 		(void) fprintf(stderr, gettext("internal error: unable to "
3111 		    "open %s\n"), MNTTAB);
3112 		return (1);
3113 	}
3114 
3115 	/*
3116 	 * This command also doubles as the /etc/fs mount and unmount program.
3117 	 * Determine if we should take this behavior based on argv[0].
3118 	 */
3119 	progname = basename(argv[0]);
3120 	if (strcmp(progname, "mount") == 0) {
3121 		ret = manual_mount(argc, argv);
3122 	} else if (strcmp(progname, "umount") == 0) {
3123 		ret = manual_unmount(argc, argv);
3124 	} else {
3125 		/*
3126 		 * Make sure the user has specified some command.
3127 		 */
3128 		if (argc < 2) {
3129 			(void) fprintf(stderr, gettext("missing command\n"));
3130 			usage(B_FALSE);
3131 		}
3132 
3133 		cmdname = argv[1];
3134 
3135 		/*
3136 		 * The 'umount' command is an alias for 'unmount'
3137 		 */
3138 		if (strcmp(cmdname, "umount") == 0)
3139 			cmdname = "unmount";
3140 
3141 		/*
3142 		 * The 'recv' command is an alias for 'receive'
3143 		 */
3144 		if (strcmp(cmdname, "recv") == 0)
3145 			cmdname = "receive";
3146 
3147 		/*
3148 		 * Special case '-?'
3149 		 */
3150 		if (strcmp(cmdname, "-?") == 0)
3151 			usage(B_TRUE);
3152 
3153 		/*
3154 		 * 'volinit' and 'volfini' do not appear in the usage message,
3155 		 * so we have to special case them here.
3156 		 */
3157 		if (strcmp(cmdname, "volinit") == 0)
3158 			return (do_volcheck(B_TRUE));
3159 		else if (strcmp(cmdname, "volfini") == 0)
3160 			return (do_volcheck(B_FALSE));
3161 
3162 		/*
3163 		 * Run the appropriate command.
3164 		 */
3165 		for (i = 0; i < NCOMMAND; i++) {
3166 			if (command_table[i].name == NULL)
3167 				continue;
3168 
3169 			if (strcmp(cmdname, command_table[i].name) == 0) {
3170 				current_command = &command_table[i];
3171 				ret = command_table[i].func(argc - 1, argv + 1);
3172 				break;
3173 			}
3174 		}
3175 
3176 		if (i == NCOMMAND) {
3177 			(void) fprintf(stderr, gettext("unrecognized "
3178 			    "command '%s'\n"), cmdname);
3179 			usage(B_FALSE);
3180 		}
3181 	}
3182 
3183 	(void) fclose(mnttab_file);
3184 
3185 	libzfs_fini(g_zfs);
3186 
3187 	/*
3188 	 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
3189 	 * for the purposes of running ::findleaks.
3190 	 */
3191 	if (getenv("ZFS_ABORT") != NULL) {
3192 		(void) printf("dumping core by request\n");
3193 		abort();
3194 	}
3195 
3196 	return (ret);
3197 }
3198