zfs_main.c revision 13043:8c712bbb18ea
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26#include <assert.h>
27#include <ctype.h>
28#include <errno.h>
29#include <libgen.h>
30#include <libintl.h>
31#include <libuutil.h>
32#include <libnvpair.h>
33#include <locale.h>
34#include <stddef.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <strings.h>
38#include <unistd.h>
39#include <fcntl.h>
40#include <zone.h>
41#include <grp.h>
42#include <pwd.h>
43#include <signal.h>
44#include <sys/mkdev.h>
45#include <sys/mntent.h>
46#include <sys/mnttab.h>
47#include <sys/mount.h>
48#include <sys/stat.h>
49#include <sys/fs/zfs.h>
50#include <sys/types.h>
51#include <time.h>
52
53#include <libzfs.h>
54#include <libuutil.h>
55
56#include "zfs_iter.h"
57#include "zfs_util.h"
58#include "zfs_comutil.h"
59
60libzfs_handle_t *g_zfs;
61
62static FILE *mnttab_file;
63static char history_str[HIS_MAX_RECORD_LEN];
64const char *pypath = "/usr/lib/zfs/pyzfs.py";
65
66static int zfs_do_clone(int argc, char **argv);
67static int zfs_do_create(int argc, char **argv);
68static int zfs_do_destroy(int argc, char **argv);
69static int zfs_do_get(int argc, char **argv);
70static int zfs_do_inherit(int argc, char **argv);
71static int zfs_do_list(int argc, char **argv);
72static int zfs_do_mount(int argc, char **argv);
73static int zfs_do_rename(int argc, char **argv);
74static int zfs_do_rollback(int argc, char **argv);
75static int zfs_do_set(int argc, char **argv);
76static int zfs_do_upgrade(int argc, char **argv);
77static int zfs_do_snapshot(int argc, char **argv);
78static int zfs_do_unmount(int argc, char **argv);
79static int zfs_do_share(int argc, char **argv);
80static int zfs_do_unshare(int argc, char **argv);
81static int zfs_do_send(int argc, char **argv);
82static int zfs_do_receive(int argc, char **argv);
83static int zfs_do_promote(int argc, char **argv);
84static int zfs_do_userspace(int argc, char **argv);
85static int zfs_do_python(int argc, char **argv);
86static int zfs_do_hold(int argc, char **argv);
87static int zfs_do_release(int argc, char **argv);
88static int zfs_do_diff(int argc, char **argv);
89
90/*
91 * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
92 */
93
94#ifdef DEBUG
95const char *
96_umem_debug_init(void)
97{
98	return ("default,verbose"); /* $UMEM_DEBUG setting */
99}
100
101const char *
102_umem_logging_init(void)
103{
104	return ("fail,contents"); /* $UMEM_LOGGING setting */
105}
106#endif
107
108typedef enum {
109	HELP_CLONE,
110	HELP_CREATE,
111	HELP_DESTROY,
112	HELP_GET,
113	HELP_INHERIT,
114	HELP_UPGRADE,
115	HELP_LIST,
116	HELP_MOUNT,
117	HELP_PROMOTE,
118	HELP_RECEIVE,
119	HELP_RENAME,
120	HELP_ROLLBACK,
121	HELP_SEND,
122	HELP_SET,
123	HELP_SHARE,
124	HELP_SNAPSHOT,
125	HELP_UNMOUNT,
126	HELP_UNSHARE,
127	HELP_ALLOW,
128	HELP_UNALLOW,
129	HELP_USERSPACE,
130	HELP_GROUPSPACE,
131	HELP_HOLD,
132	HELP_HOLDS,
133	HELP_RELEASE,
134	HELP_DIFF
135} zfs_help_t;
136
137typedef struct zfs_command {
138	const char	*name;
139	int		(*func)(int argc, char **argv);
140	zfs_help_t	usage;
141} zfs_command_t;
142
143/*
144 * Master command table.  Each ZFS command has a name, associated function, and
145 * usage message.  The usage messages need to be internationalized, so we have
146 * to have a function to return the usage message based on a command index.
147 *
148 * These commands are organized according to how they are displayed in the usage
149 * message.  An empty command (one with a NULL name) indicates an empty line in
150 * the generic usage message.
151 */
152static zfs_command_t command_table[] = {
153	{ "create",	zfs_do_create,		HELP_CREATE		},
154	{ "destroy",	zfs_do_destroy,		HELP_DESTROY		},
155	{ NULL },
156	{ "snapshot",	zfs_do_snapshot,	HELP_SNAPSHOT		},
157	{ "rollback",	zfs_do_rollback,	HELP_ROLLBACK		},
158	{ "clone",	zfs_do_clone,		HELP_CLONE		},
159	{ "promote",	zfs_do_promote,		HELP_PROMOTE		},
160	{ "rename",	zfs_do_rename,		HELP_RENAME		},
161	{ NULL },
162	{ "list",	zfs_do_list,		HELP_LIST		},
163	{ NULL },
164	{ "set",	zfs_do_set,		HELP_SET		},
165	{ "get",	zfs_do_get,		HELP_GET		},
166	{ "inherit",	zfs_do_inherit,		HELP_INHERIT		},
167	{ "upgrade",	zfs_do_upgrade,		HELP_UPGRADE		},
168	{ "userspace",	zfs_do_userspace,	HELP_USERSPACE		},
169	{ "groupspace",	zfs_do_userspace,	HELP_GROUPSPACE		},
170	{ NULL },
171	{ "mount",	zfs_do_mount,		HELP_MOUNT		},
172	{ "unmount",	zfs_do_unmount,		HELP_UNMOUNT		},
173	{ "share",	zfs_do_share,		HELP_SHARE		},
174	{ "unshare",	zfs_do_unshare,		HELP_UNSHARE		},
175	{ NULL },
176	{ "send",	zfs_do_send,		HELP_SEND		},
177	{ "receive",	zfs_do_receive,		HELP_RECEIVE		},
178	{ NULL },
179	{ "allow",	zfs_do_python,		HELP_ALLOW		},
180	{ NULL },
181	{ "unallow",	zfs_do_python,		HELP_UNALLOW		},
182	{ NULL },
183	{ "hold",	zfs_do_hold,		HELP_HOLD		},
184	{ "holds",	zfs_do_python,		HELP_HOLDS		},
185	{ "release",	zfs_do_release,		HELP_RELEASE		},
186	{ "diff",	zfs_do_diff,		HELP_DIFF		},
187};
188
189#define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
190
191zfs_command_t *current_command;
192
193static const char *
194get_usage(zfs_help_t idx)
195{
196	switch (idx) {
197	case HELP_CLONE:
198		return (gettext("\tclone [-p] [-o property=value] ... "
199		    "<snapshot> <filesystem|volume>\n"));
200	case HELP_CREATE:
201		return (gettext("\tcreate [-p] [-o property=value] ... "
202		    "<filesystem>\n"
203		    "\tcreate [-ps] [-b blocksize] [-o property=value] ... "
204		    "-V <size> <volume>\n"));
205	case HELP_DESTROY:
206		return (gettext("\tdestroy [-rRf] <filesystem|volume>\n"
207		    "\tdestroy [-rRd] <snapshot>\n"));
208	case HELP_GET:
209		return (gettext("\tget [-rHp] [-d max] "
210		    "[-o \"all\" | field[,...]] [-s source[,...]]\n"
211		    "\t    <\"all\" | property[,...]> "
212		    "[filesystem|volume|snapshot] ...\n"));
213	case HELP_INHERIT:
214		return (gettext("\tinherit [-rS] <property> "
215		    "<filesystem|volume|snapshot> ...\n"));
216	case HELP_UPGRADE:
217		return (gettext("\tupgrade [-v]\n"
218		    "\tupgrade [-r] [-V version] <-a | filesystem ...>\n"));
219	case HELP_LIST:
220		return (gettext("\tlist [-rH][-d max] "
221		    "[-o property[,...]] [-t type[,...]] [-s property] ...\n"
222		    "\t    [-S property] ... "
223		    "[filesystem|volume|snapshot] ...\n"));
224	case HELP_MOUNT:
225		return (gettext("\tmount\n"
226		    "\tmount [-vO] [-o opts] <-a | filesystem>\n"));
227	case HELP_PROMOTE:
228		return (gettext("\tpromote <clone-filesystem>\n"));
229	case HELP_RECEIVE:
230		return (gettext("\treceive [-vnFu] <filesystem|volume|"
231		"snapshot>\n"
232		"\treceive [-vnFu] [-d | -e] <filesystem>\n"));
233	case HELP_RENAME:
234		return (gettext("\trename <filesystem|volume|snapshot> "
235		    "<filesystem|volume|snapshot>\n"
236		    "\trename -p <filesystem|volume> <filesystem|volume>\n"
237		    "\trename -r <snapshot> <snapshot>"));
238	case HELP_ROLLBACK:
239		return (gettext("\trollback [-rRf] <snapshot>\n"));
240	case HELP_SEND:
241		return (gettext("\tsend [-RDp] [-[iI] snapshot] <snapshot>\n"));
242	case HELP_SET:
243		return (gettext("\tset <property=value> "
244		    "<filesystem|volume|snapshot> ...\n"));
245	case HELP_SHARE:
246		return (gettext("\tshare <-a | filesystem>\n"));
247	case HELP_SNAPSHOT:
248		return (gettext("\tsnapshot [-r] [-o property=value] ... "
249		    "<filesystem@snapname|volume@snapname>\n"));
250	case HELP_UNMOUNT:
251		return (gettext("\tunmount [-f] "
252		    "<-a | filesystem|mountpoint>\n"));
253	case HELP_UNSHARE:
254		return (gettext("\tunshare "
255		    "<-a | filesystem|mountpoint>\n"));
256	case HELP_ALLOW:
257		return (gettext("\tallow <filesystem|volume>\n"
258		    "\tallow [-ldug] "
259		    "<\"everyone\"|user|group>[,...] <perm|@setname>[,...]\n"
260		    "\t    <filesystem|volume>\n"
261		    "\tallow [-ld] -e <perm|@setname>[,...] "
262		    "<filesystem|volume>\n"
263		    "\tallow -c <perm|@setname>[,...] <filesystem|volume>\n"
264		    "\tallow -s @setname <perm|@setname>[,...] "
265		    "<filesystem|volume>\n"));
266	case HELP_UNALLOW:
267		return (gettext("\tunallow [-rldug] "
268		    "<\"everyone\"|user|group>[,...]\n"
269		    "\t    [<perm|@setname>[,...]] <filesystem|volume>\n"
270		    "\tunallow [-rld] -e [<perm|@setname>[,...]] "
271		    "<filesystem|volume>\n"
272		    "\tunallow [-r] -c [<perm|@setname>[,...]] "
273		    "<filesystem|volume>\n"
274		    "\tunallow [-r] -s @setname [<perm|@setname>[,...]] "
275		    "<filesystem|volume>\n"));
276	case HELP_USERSPACE:
277		return (gettext("\tuserspace [-hniHp] [-o field[,...]] "
278		    "[-sS field] ... [-t type[,...]]\n"
279		    "\t    <filesystem|snapshot>\n"));
280	case HELP_GROUPSPACE:
281		return (gettext("\tgroupspace [-hniHpU] [-o field[,...]] "
282		    "[-sS field] ... [-t type[,...]]\n"
283		    "\t    <filesystem|snapshot>\n"));
284	case HELP_HOLD:
285		return (gettext("\thold [-r] <tag> <snapshot> ...\n"));
286	case HELP_HOLDS:
287		return (gettext("\tholds [-r] <snapshot> ...\n"));
288	case HELP_RELEASE:
289		return (gettext("\trelease [-r] <tag> <snapshot> ...\n"));
290	case HELP_DIFF:
291		return (gettext("\tdiff [-FHt] <snapshot> "
292		    "[snapshot|filesystem]\n"));
293	}
294
295	abort();
296	/* NOTREACHED */
297}
298
299void
300nomem(void)
301{
302	(void) fprintf(stderr, gettext("internal error: out of memory\n"));
303	exit(1);
304}
305
306/*
307 * Utility function to guarantee malloc() success.
308 */
309
310void *
311safe_malloc(size_t size)
312{
313	void *data;
314
315	if ((data = calloc(1, size)) == NULL)
316		nomem();
317
318	return (data);
319}
320
321static char *
322safe_strdup(char *str)
323{
324	char *dupstr = strdup(str);
325
326	if (dupstr == NULL)
327		nomem();
328
329	return (dupstr);
330}
331
332/*
333 * Callback routine that will print out information for each of
334 * the properties.
335 */
336static int
337usage_prop_cb(int prop, void *cb)
338{
339	FILE *fp = cb;
340
341	(void) fprintf(fp, "\t%-15s ", zfs_prop_to_name(prop));
342
343	if (zfs_prop_readonly(prop))
344		(void) fprintf(fp, " NO    ");
345	else
346		(void) fprintf(fp, "YES    ");
347
348	if (zfs_prop_inheritable(prop))
349		(void) fprintf(fp, "  YES   ");
350	else
351		(void) fprintf(fp, "   NO   ");
352
353	if (zfs_prop_values(prop) == NULL)
354		(void) fprintf(fp, "-\n");
355	else
356		(void) fprintf(fp, "%s\n", zfs_prop_values(prop));
357
358	return (ZPROP_CONT);
359}
360
361/*
362 * Display usage message.  If we're inside a command, display only the usage for
363 * that command.  Otherwise, iterate over the entire command table and display
364 * a complete usage message.
365 */
366static void
367usage(boolean_t requested)
368{
369	int i;
370	boolean_t show_properties = B_FALSE;
371	FILE *fp = requested ? stdout : stderr;
372
373	if (current_command == NULL) {
374
375		(void) fprintf(fp, gettext("usage: zfs command args ...\n"));
376		(void) fprintf(fp,
377		    gettext("where 'command' is one of the following:\n\n"));
378
379		for (i = 0; i < NCOMMAND; i++) {
380			if (command_table[i].name == NULL)
381				(void) fprintf(fp, "\n");
382			else
383				(void) fprintf(fp, "%s",
384				    get_usage(command_table[i].usage));
385		}
386
387		(void) fprintf(fp, gettext("\nEach dataset is of the form: "
388		    "pool/[dataset/]*dataset[@name]\n"));
389	} else {
390		(void) fprintf(fp, gettext("usage:\n"));
391		(void) fprintf(fp, "%s", get_usage(current_command->usage));
392	}
393
394	if (current_command != NULL &&
395	    (strcmp(current_command->name, "set") == 0 ||
396	    strcmp(current_command->name, "get") == 0 ||
397	    strcmp(current_command->name, "inherit") == 0 ||
398	    strcmp(current_command->name, "list") == 0))
399		show_properties = B_TRUE;
400
401	if (show_properties) {
402		(void) fprintf(fp,
403		    gettext("\nThe following properties are supported:\n"));
404
405		(void) fprintf(fp, "\n\t%-14s %s  %s   %s\n\n",
406		    "PROPERTY", "EDIT", "INHERIT", "VALUES");
407
408		/* Iterate over all properties */
409		(void) zprop_iter(usage_prop_cb, fp, B_FALSE, B_TRUE,
410		    ZFS_TYPE_DATASET);
411
412		(void) fprintf(fp, "\t%-15s ", "userused@...");
413		(void) fprintf(fp, " NO       NO   <size>\n");
414		(void) fprintf(fp, "\t%-15s ", "groupused@...");
415		(void) fprintf(fp, " NO       NO   <size>\n");
416		(void) fprintf(fp, "\t%-15s ", "userquota@...");
417		(void) fprintf(fp, "YES       NO   <size> | none\n");
418		(void) fprintf(fp, "\t%-15s ", "groupquota@...");
419		(void) fprintf(fp, "YES       NO   <size> | none\n");
420
421		(void) fprintf(fp, gettext("\nSizes are specified in bytes "
422		    "with standard units such as K, M, G, etc.\n"));
423		(void) fprintf(fp, gettext("\nUser-defined properties can "
424		    "be specified by using a name containing a colon (:).\n"));
425		(void) fprintf(fp, gettext("\nThe {user|group}{used|quota}@ "
426		    "properties must be appended with\n"
427		    "a user or group specifier of one of these forms:\n"
428		    "    POSIX name      (eg: \"matt\")\n"
429		    "    POSIX id        (eg: \"126829\")\n"
430		    "    SMB name@domain (eg: \"matt@sun\")\n"
431		    "    SMB SID         (eg: \"S-1-234-567-89\")\n"));
432	} else {
433		(void) fprintf(fp,
434		    gettext("\nFor the property list, run: %s\n"),
435		    "zfs set|get");
436		(void) fprintf(fp,
437		    gettext("\nFor the delegated permission list, run: %s\n"),
438		    "zfs allow|unallow");
439	}
440
441	/*
442	 * See comments at end of main().
443	 */
444	if (getenv("ZFS_ABORT") != NULL) {
445		(void) printf("dumping core by request\n");
446		abort();
447	}
448
449	exit(requested ? 0 : 2);
450}
451
452static int
453parseprop(nvlist_t *props)
454{
455	char *propname = optarg;
456	char *propval, *strval;
457
458	if ((propval = strchr(propname, '=')) == NULL) {
459		(void) fprintf(stderr, gettext("missing "
460		    "'=' for -o option\n"));
461		return (-1);
462	}
463	*propval = '\0';
464	propval++;
465	if (nvlist_lookup_string(props, propname, &strval) == 0) {
466		(void) fprintf(stderr, gettext("property '%s' "
467		    "specified multiple times\n"), propname);
468		return (-1);
469	}
470	if (nvlist_add_string(props, propname, propval) != 0)
471		nomem();
472	return (0);
473}
474
475static int
476parse_depth(char *opt, int *flags)
477{
478	char *tmp;
479	int depth;
480
481	depth = (int)strtol(opt, &tmp, 0);
482	if (*tmp) {
483		(void) fprintf(stderr,
484		    gettext("%s is not an integer\n"), optarg);
485		usage(B_FALSE);
486	}
487	if (depth < 0) {
488		(void) fprintf(stderr,
489		    gettext("Depth can not be negative.\n"));
490		usage(B_FALSE);
491	}
492	*flags |= (ZFS_ITER_DEPTH_LIMIT|ZFS_ITER_RECURSE);
493	return (depth);
494}
495
496#define	PROGRESS_DELAY 2		/* seconds */
497
498static char *pt_reverse = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
499static time_t pt_begin;
500static char *pt_header = NULL;
501static boolean_t pt_shown;
502
503static void
504start_progress_timer(void)
505{
506	pt_begin = time(NULL) + PROGRESS_DELAY;
507	pt_shown = B_FALSE;
508}
509
510static void
511set_progress_header(char *header)
512{
513	assert(pt_header == NULL);
514	pt_header = safe_strdup(header);
515	if (pt_shown) {
516		(void) printf("%s: ", header);
517		(void) fflush(stdout);
518	}
519}
520
521static void
522update_progress(char *update)
523{
524	if (!pt_shown && time(NULL) > pt_begin) {
525		int len = strlen(update);
526
527		(void) printf("%s: %s%*.*s", pt_header, update, len, len,
528		    pt_reverse);
529		(void) fflush(stdout);
530		pt_shown = B_TRUE;
531	} else if (pt_shown) {
532		int len = strlen(update);
533
534		(void) printf("%s%*.*s", update, len, len, pt_reverse);
535		(void) fflush(stdout);
536	}
537}
538
539static void
540finish_progress(char *done)
541{
542	if (pt_shown) {
543		(void) printf("%s\n", done);
544		(void) fflush(stdout);
545	}
546	free(pt_header);
547	pt_header = NULL;
548}
549/*
550 * zfs clone [-p] [-o prop=value] ... <snap> <fs | vol>
551 *
552 * Given an existing dataset, create a writable copy whose initial contents
553 * are the same as the source.  The newly created dataset maintains a
554 * dependency on the original; the original cannot be destroyed so long as
555 * the clone exists.
556 *
557 * The '-p' flag creates all the non-existing ancestors of the target first.
558 */
559static int
560zfs_do_clone(int argc, char **argv)
561{
562	zfs_handle_t *zhp = NULL;
563	boolean_t parents = B_FALSE;
564	nvlist_t *props;
565	int ret;
566	int c;
567
568	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
569		nomem();
570
571	/* check options */
572	while ((c = getopt(argc, argv, "o:p")) != -1) {
573		switch (c) {
574		case 'o':
575			if (parseprop(props))
576				return (1);
577			break;
578		case 'p':
579			parents = B_TRUE;
580			break;
581		case '?':
582			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
583			    optopt);
584			goto usage;
585		}
586	}
587
588	argc -= optind;
589	argv += optind;
590
591	/* check number of arguments */
592	if (argc < 1) {
593		(void) fprintf(stderr, gettext("missing source dataset "
594		    "argument\n"));
595		goto usage;
596	}
597	if (argc < 2) {
598		(void) fprintf(stderr, gettext("missing target dataset "
599		    "argument\n"));
600		goto usage;
601	}
602	if (argc > 2) {
603		(void) fprintf(stderr, gettext("too many arguments\n"));
604		goto usage;
605	}
606
607	/* open the source dataset */
608	if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL)
609		return (1);
610
611	if (parents && zfs_name_valid(argv[1], ZFS_TYPE_FILESYSTEM |
612	    ZFS_TYPE_VOLUME)) {
613		/*
614		 * Now create the ancestors of the target dataset.  If the
615		 * target already exists and '-p' option was used we should not
616		 * complain.
617		 */
618		if (zfs_dataset_exists(g_zfs, argv[1], ZFS_TYPE_FILESYSTEM |
619		    ZFS_TYPE_VOLUME))
620			return (0);
621		if (zfs_create_ancestors(g_zfs, argv[1]) != 0)
622			return (1);
623	}
624
625	/* pass to libzfs */
626	ret = zfs_clone(zhp, argv[1], props);
627
628	/* create the mountpoint if necessary */
629	if (ret == 0) {
630		zfs_handle_t *clone;
631
632		clone = zfs_open(g_zfs, argv[1], ZFS_TYPE_DATASET);
633		if (clone != NULL) {
634			if (zfs_get_type(clone) != ZFS_TYPE_VOLUME)
635				if ((ret = zfs_mount(clone, NULL, 0)) == 0)
636					ret = zfs_share(clone);
637			zfs_close(clone);
638		}
639	}
640
641	zfs_close(zhp);
642	nvlist_free(props);
643
644	return (!!ret);
645
646usage:
647	if (zhp)
648		zfs_close(zhp);
649	nvlist_free(props);
650	usage(B_FALSE);
651	return (-1);
652}
653
654/*
655 * zfs create [-p] [-o prop=value] ... fs
656 * zfs create [-ps] [-b blocksize] [-o prop=value] ... -V vol size
657 *
658 * Create a new dataset.  This command can be used to create filesystems
659 * and volumes.  Snapshot creation is handled by 'zfs snapshot'.
660 * For volumes, the user must specify a size to be used.
661 *
662 * The '-s' flag applies only to volumes, and indicates that we should not try
663 * to set the reservation for this volume.  By default we set a reservation
664 * equal to the size for any volume.  For pools with SPA_VERSION >=
665 * SPA_VERSION_REFRESERVATION, we set a refreservation instead.
666 *
667 * The '-p' flag creates all the non-existing ancestors of the target first.
668 */
669static int
670zfs_do_create(int argc, char **argv)
671{
672	zfs_type_t type = ZFS_TYPE_FILESYSTEM;
673	zfs_handle_t *zhp = NULL;
674	uint64_t volsize;
675	int c;
676	boolean_t noreserve = B_FALSE;
677	boolean_t bflag = B_FALSE;
678	boolean_t parents = B_FALSE;
679	int ret = 1;
680	nvlist_t *props;
681	uint64_t intval;
682	int canmount = ZFS_CANMOUNT_OFF;
683
684	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
685		nomem();
686
687	/* check options */
688	while ((c = getopt(argc, argv, ":V:b:so:p")) != -1) {
689		switch (c) {
690		case 'V':
691			type = ZFS_TYPE_VOLUME;
692			if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) {
693				(void) fprintf(stderr, gettext("bad volume "
694				    "size '%s': %s\n"), optarg,
695				    libzfs_error_description(g_zfs));
696				goto error;
697			}
698
699			if (nvlist_add_uint64(props,
700			    zfs_prop_to_name(ZFS_PROP_VOLSIZE), intval) != 0)
701				nomem();
702			volsize = intval;
703			break;
704		case 'p':
705			parents = B_TRUE;
706			break;
707		case 'b':
708			bflag = B_TRUE;
709			if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) {
710				(void) fprintf(stderr, gettext("bad volume "
711				    "block size '%s': %s\n"), optarg,
712				    libzfs_error_description(g_zfs));
713				goto error;
714			}
715
716			if (nvlist_add_uint64(props,
717			    zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
718			    intval) != 0)
719				nomem();
720			break;
721		case 'o':
722			if (parseprop(props))
723				goto error;
724			break;
725		case 's':
726			noreserve = B_TRUE;
727			break;
728		case ':':
729			(void) fprintf(stderr, gettext("missing size "
730			    "argument\n"));
731			goto badusage;
732			break;
733		case '?':
734			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
735			    optopt);
736			goto badusage;
737		}
738	}
739
740	if ((bflag || noreserve) && type != ZFS_TYPE_VOLUME) {
741		(void) fprintf(stderr, gettext("'-s' and '-b' can only be "
742		    "used when creating a volume\n"));
743		goto badusage;
744	}
745
746	argc -= optind;
747	argv += optind;
748
749	/* check number of arguments */
750	if (argc == 0) {
751		(void) fprintf(stderr, gettext("missing %s argument\n"),
752		    zfs_type_to_name(type));
753		goto badusage;
754	}
755	if (argc > 1) {
756		(void) fprintf(stderr, gettext("too many arguments\n"));
757		goto badusage;
758	}
759
760	if (type == ZFS_TYPE_VOLUME && !noreserve) {
761		zpool_handle_t *zpool_handle;
762		uint64_t spa_version;
763		char *p;
764		zfs_prop_t resv_prop;
765		char *strval;
766
767		if (p = strchr(argv[0], '/'))
768			*p = '\0';
769		zpool_handle = zpool_open(g_zfs, argv[0]);
770		if (p != NULL)
771			*p = '/';
772		if (zpool_handle == NULL)
773			goto error;
774		spa_version = zpool_get_prop_int(zpool_handle,
775		    ZPOOL_PROP_VERSION, NULL);
776		zpool_close(zpool_handle);
777		if (spa_version >= SPA_VERSION_REFRESERVATION)
778			resv_prop = ZFS_PROP_REFRESERVATION;
779		else
780			resv_prop = ZFS_PROP_RESERVATION;
781		volsize = zvol_volsize_to_reservation(volsize, props);
782
783		if (nvlist_lookup_string(props, zfs_prop_to_name(resv_prop),
784		    &strval) != 0) {
785			if (nvlist_add_uint64(props,
786			    zfs_prop_to_name(resv_prop), volsize) != 0) {
787				nvlist_free(props);
788				nomem();
789			}
790		}
791	}
792
793	if (parents && zfs_name_valid(argv[0], type)) {
794		/*
795		 * Now create the ancestors of target dataset.  If the target
796		 * already exists and '-p' option was used we should not
797		 * complain.
798		 */
799		if (zfs_dataset_exists(g_zfs, argv[0], type)) {
800			ret = 0;
801			goto error;
802		}
803		if (zfs_create_ancestors(g_zfs, argv[0]) != 0)
804			goto error;
805	}
806
807	/* pass to libzfs */
808	if (zfs_create(g_zfs, argv[0], type, props) != 0)
809		goto error;
810
811	if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL)
812		goto error;
813
814	ret = 0;
815	/*
816	 * if the user doesn't want the dataset automatically mounted,
817	 * then skip the mount/share step
818	 */
819	if (zfs_prop_valid_for_type(ZFS_PROP_CANMOUNT, type))
820		canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
821
822	/*
823	 * Mount and/or share the new filesystem as appropriate.  We provide a
824	 * verbose error message to let the user know that their filesystem was
825	 * in fact created, even if we failed to mount or share it.
826	 */
827	if (canmount == ZFS_CANMOUNT_ON) {
828		if (zfs_mount(zhp, NULL, 0) != 0) {
829			(void) fprintf(stderr, gettext("filesystem "
830			    "successfully created, but not mounted\n"));
831			ret = 1;
832		} else if (zfs_share(zhp) != 0) {
833			(void) fprintf(stderr, gettext("filesystem "
834			    "successfully created, but not shared\n"));
835			ret = 1;
836		}
837	}
838
839error:
840	if (zhp)
841		zfs_close(zhp);
842	nvlist_free(props);
843	return (ret);
844badusage:
845	nvlist_free(props);
846	usage(B_FALSE);
847	return (2);
848}
849
850/*
851 * zfs destroy [-rRf] <fs, vol>
852 * zfs destroy [-rRd] <snap>
853 *
854 *	-r	Recursively destroy all children
855 *	-R	Recursively destroy all dependents, including clones
856 *	-f	Force unmounting of any dependents
857 *	-d	If we can't destroy now, mark for deferred destruction
858 *
859 * Destroys the given dataset.  By default, it will unmount any filesystems,
860 * and refuse to destroy a dataset that has any dependents.  A dependent can
861 * either be a child, or a clone of a child.
862 */
863typedef struct destroy_cbdata {
864	boolean_t	cb_first;
865	int		cb_force;
866	int		cb_recurse;
867	int		cb_error;
868	int		cb_needforce;
869	int		cb_doclones;
870	boolean_t	cb_closezhp;
871	zfs_handle_t	*cb_target;
872	char		*cb_snapname;
873	boolean_t	cb_defer_destroy;
874} destroy_cbdata_t;
875
876/*
877 * Check for any dependents based on the '-r' or '-R' flags.
878 */
879static int
880destroy_check_dependent(zfs_handle_t *zhp, void *data)
881{
882	destroy_cbdata_t *cbp = data;
883	const char *tname = zfs_get_name(cbp->cb_target);
884	const char *name = zfs_get_name(zhp);
885
886	if (strncmp(tname, name, strlen(tname)) == 0 &&
887	    (name[strlen(tname)] == '/' || name[strlen(tname)] == '@')) {
888		/*
889		 * This is a direct descendant, not a clone somewhere else in
890		 * the hierarchy.
891		 */
892		if (cbp->cb_recurse)
893			goto out;
894
895		if (cbp->cb_first) {
896			(void) fprintf(stderr, gettext("cannot destroy '%s': "
897			    "%s has children\n"),
898			    zfs_get_name(cbp->cb_target),
899			    zfs_type_to_name(zfs_get_type(cbp->cb_target)));
900			(void) fprintf(stderr, gettext("use '-r' to destroy "
901			    "the following datasets:\n"));
902			cbp->cb_first = B_FALSE;
903			cbp->cb_error = 1;
904		}
905
906		(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
907	} else {
908		/*
909		 * This is a clone.  We only want to report this if the '-r'
910		 * wasn't specified, or the target is a snapshot.
911		 */
912		if (!cbp->cb_recurse &&
913		    zfs_get_type(cbp->cb_target) != ZFS_TYPE_SNAPSHOT)
914			goto out;
915
916		if (cbp->cb_first) {
917			(void) fprintf(stderr, gettext("cannot destroy '%s': "
918			    "%s has dependent clones\n"),
919			    zfs_get_name(cbp->cb_target),
920			    zfs_type_to_name(zfs_get_type(cbp->cb_target)));
921			(void) fprintf(stderr, gettext("use '-R' to destroy "
922			    "the following datasets:\n"));
923			cbp->cb_first = B_FALSE;
924			cbp->cb_error = 1;
925		}
926
927		(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
928	}
929
930out:
931	zfs_close(zhp);
932	return (0);
933}
934
935static int
936destroy_callback(zfs_handle_t *zhp, void *data)
937{
938	destroy_cbdata_t *cbp = data;
939
940	/*
941	 * Ignore pools (which we've already flagged as an error before getting
942	 * here).
943	 */
944	if (strchr(zfs_get_name(zhp), '/') == NULL &&
945	    zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
946		zfs_close(zhp);
947		return (0);
948	}
949
950	/*
951	 * Bail out on the first error.
952	 */
953	if (zfs_unmount(zhp, NULL, cbp->cb_force ? MS_FORCE : 0) != 0 ||
954	    zfs_destroy(zhp, cbp->cb_defer_destroy) != 0) {
955		zfs_close(zhp);
956		return (-1);
957	}
958
959	zfs_close(zhp);
960	return (0);
961}
962
963static int
964destroy_snap_clones(zfs_handle_t *zhp, void *arg)
965{
966	destroy_cbdata_t *cbp = arg;
967	char thissnap[MAXPATHLEN];
968	zfs_handle_t *szhp;
969	boolean_t closezhp = cbp->cb_closezhp;
970	int rv;
971
972	(void) snprintf(thissnap, sizeof (thissnap),
973	    "%s@%s", zfs_get_name(zhp), cbp->cb_snapname);
974
975	libzfs_print_on_error(g_zfs, B_FALSE);
976	szhp = zfs_open(g_zfs, thissnap, ZFS_TYPE_SNAPSHOT);
977	libzfs_print_on_error(g_zfs, B_TRUE);
978	if (szhp) {
979		/*
980		 * Destroy any clones of this snapshot
981		 */
982		if (zfs_iter_dependents(szhp, B_FALSE, destroy_callback,
983		    cbp) != 0) {
984			zfs_close(szhp);
985			if (closezhp)
986				zfs_close(zhp);
987			return (-1);
988		}
989		zfs_close(szhp);
990	}
991
992	cbp->cb_closezhp = B_TRUE;
993	rv = zfs_iter_filesystems(zhp, destroy_snap_clones, arg);
994	if (closezhp)
995		zfs_close(zhp);
996	return (rv);
997}
998
999static int
1000zfs_do_destroy(int argc, char **argv)
1001{
1002	destroy_cbdata_t cb = { 0 };
1003	int c;
1004	zfs_handle_t *zhp;
1005	char *cp;
1006	zfs_type_t type = ZFS_TYPE_DATASET;
1007
1008	/* check options */
1009	while ((c = getopt(argc, argv, "dfrR")) != -1) {
1010		switch (c) {
1011		case 'd':
1012			cb.cb_defer_destroy = B_TRUE;
1013			type = ZFS_TYPE_SNAPSHOT;
1014			break;
1015		case 'f':
1016			cb.cb_force = 1;
1017			break;
1018		case 'r':
1019			cb.cb_recurse = 1;
1020			break;
1021		case 'R':
1022			cb.cb_recurse = 1;
1023			cb.cb_doclones = 1;
1024			break;
1025		case '?':
1026		default:
1027			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1028			    optopt);
1029			usage(B_FALSE);
1030		}
1031	}
1032
1033	argc -= optind;
1034	argv += optind;
1035
1036	/* check number of arguments */
1037	if (argc == 0) {
1038		(void) fprintf(stderr, gettext("missing path argument\n"));
1039		usage(B_FALSE);
1040	}
1041	if (argc > 1) {
1042		(void) fprintf(stderr, gettext("too many arguments\n"));
1043		usage(B_FALSE);
1044	}
1045
1046	/*
1047	 * If we are doing recursive destroy of a snapshot, then the
1048	 * named snapshot may not exist.  Go straight to libzfs.
1049	 */
1050	if (cb.cb_recurse && (cp = strchr(argv[0], '@'))) {
1051		int ret;
1052
1053		*cp = '\0';
1054		if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL)
1055			return (1);
1056		*cp = '@';
1057		cp++;
1058
1059		if (cb.cb_doclones) {
1060			boolean_t defer = cb.cb_defer_destroy;
1061
1062			/*
1063			 * Temporarily ignore the defer_destroy setting since
1064			 * it's not supported for clones.
1065			 */
1066			cb.cb_defer_destroy = B_FALSE;
1067			cb.cb_snapname = cp;
1068			if (destroy_snap_clones(zhp, &cb) != 0) {
1069				zfs_close(zhp);
1070				return (1);
1071			}
1072			cb.cb_defer_destroy = defer;
1073		}
1074
1075		ret = zfs_destroy_snaps(zhp, cp, cb.cb_defer_destroy);
1076		zfs_close(zhp);
1077		if (ret) {
1078			(void) fprintf(stderr,
1079			    gettext("no snapshots destroyed\n"));
1080		}
1081		return (ret != 0);
1082	}
1083
1084	/* Open the given dataset */
1085	if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
1086		return (1);
1087
1088	cb.cb_target = zhp;
1089
1090	/*
1091	 * Perform an explicit check for pools before going any further.
1092	 */
1093	if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL &&
1094	    zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) {
1095		(void) fprintf(stderr, gettext("cannot destroy '%s': "
1096		    "operation does not apply to pools\n"),
1097		    zfs_get_name(zhp));
1098		(void) fprintf(stderr, gettext("use 'zfs destroy -r "
1099		    "%s' to destroy all datasets in the pool\n"),
1100		    zfs_get_name(zhp));
1101		(void) fprintf(stderr, gettext("use 'zpool destroy %s' "
1102		    "to destroy the pool itself\n"), zfs_get_name(zhp));
1103		zfs_close(zhp);
1104		return (1);
1105	}
1106
1107	/*
1108	 * Check for any dependents and/or clones.
1109	 */
1110	cb.cb_first = B_TRUE;
1111	if (!cb.cb_doclones && !cb.cb_defer_destroy &&
1112	    zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent,
1113	    &cb) != 0) {
1114		zfs_close(zhp);
1115		return (1);
1116	}
1117
1118	if (cb.cb_error || (!cb.cb_defer_destroy &&
1119	    (zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0))) {
1120		zfs_close(zhp);
1121		return (1);
1122	}
1123
1124	/*
1125	 * Do the real thing.  The callback will close the handle regardless of
1126	 * whether it succeeds or not.
1127	 */
1128
1129	if (destroy_callback(zhp, &cb) != 0)
1130		return (1);
1131
1132	return (0);
1133}
1134
1135static boolean_t
1136is_recvd_column(zprop_get_cbdata_t *cbp)
1137{
1138	int i;
1139	zfs_get_column_t col;
1140
1141	for (i = 0; i < ZFS_GET_NCOLS &&
1142	    (col = cbp->cb_columns[i]) != GET_COL_NONE; i++)
1143		if (col == GET_COL_RECVD)
1144			return (B_TRUE);
1145	return (B_FALSE);
1146}
1147
1148/*
1149 * zfs get [-rHp] [-o all | field[,field]...] [-s source[,source]...]
1150 *	< all | property[,property]... > < fs | snap | vol > ...
1151 *
1152 *	-r	recurse over any child datasets
1153 *	-H	scripted mode.  Headers are stripped, and fields are separated
1154 *		by tabs instead of spaces.
1155 *	-o	Set of fields to display.  One of "name,property,value,
1156 *		received,source". Default is "name,property,value,source".
1157 *		"all" is an alias for all five.
1158 *	-s	Set of sources to allow.  One of
1159 *		"local,default,inherited,received,temporary,none".  Default is
1160 *		all six.
1161 *	-p	Display values in parsable (literal) format.
1162 *
1163 *  Prints properties for the given datasets.  The user can control which
1164 *  columns to display as well as which property types to allow.
1165 */
1166
1167/*
1168 * Invoked to display the properties for a single dataset.
1169 */
1170static int
1171get_callback(zfs_handle_t *zhp, void *data)
1172{
1173	char buf[ZFS_MAXPROPLEN];
1174	char rbuf[ZFS_MAXPROPLEN];
1175	zprop_source_t sourcetype;
1176	char source[ZFS_MAXNAMELEN];
1177	zprop_get_cbdata_t *cbp = data;
1178	nvlist_t *user_props = zfs_get_user_props(zhp);
1179	zprop_list_t *pl = cbp->cb_proplist;
1180	nvlist_t *propval;
1181	char *strval;
1182	char *sourceval;
1183	boolean_t received = is_recvd_column(cbp);
1184
1185	for (; pl != NULL; pl = pl->pl_next) {
1186		char *recvdval = NULL;
1187		/*
1188		 * Skip the special fake placeholder.  This will also skip over
1189		 * the name property when 'all' is specified.
1190		 */
1191		if (pl->pl_prop == ZFS_PROP_NAME &&
1192		    pl == cbp->cb_proplist)
1193			continue;
1194
1195		if (pl->pl_prop != ZPROP_INVAL) {
1196			if (zfs_prop_get(zhp, pl->pl_prop, buf,
1197			    sizeof (buf), &sourcetype, source,
1198			    sizeof (source),
1199			    cbp->cb_literal) != 0) {
1200				if (pl->pl_all)
1201					continue;
1202				if (!zfs_prop_valid_for_type(pl->pl_prop,
1203				    ZFS_TYPE_DATASET)) {
1204					(void) fprintf(stderr,
1205					    gettext("No such property '%s'\n"),
1206					    zfs_prop_to_name(pl->pl_prop));
1207					continue;
1208				}
1209				sourcetype = ZPROP_SRC_NONE;
1210				(void) strlcpy(buf, "-", sizeof (buf));
1211			}
1212
1213			if (received && (zfs_prop_get_recvd(zhp,
1214			    zfs_prop_to_name(pl->pl_prop), rbuf, sizeof (rbuf),
1215			    cbp->cb_literal) == 0))
1216				recvdval = rbuf;
1217
1218			zprop_print_one_property(zfs_get_name(zhp), cbp,
1219			    zfs_prop_to_name(pl->pl_prop),
1220			    buf, sourcetype, source, recvdval);
1221		} else if (zfs_prop_userquota(pl->pl_user_prop)) {
1222			sourcetype = ZPROP_SRC_LOCAL;
1223
1224			if (zfs_prop_get_userquota(zhp, pl->pl_user_prop,
1225			    buf, sizeof (buf), cbp->cb_literal) != 0) {
1226				sourcetype = ZPROP_SRC_NONE;
1227				(void) strlcpy(buf, "-", sizeof (buf));
1228			}
1229
1230			zprop_print_one_property(zfs_get_name(zhp), cbp,
1231			    pl->pl_user_prop, buf, sourcetype, source, NULL);
1232		} else {
1233			if (nvlist_lookup_nvlist(user_props,
1234			    pl->pl_user_prop, &propval) != 0) {
1235				if (pl->pl_all)
1236					continue;
1237				sourcetype = ZPROP_SRC_NONE;
1238				strval = "-";
1239			} else {
1240				verify(nvlist_lookup_string(propval,
1241				    ZPROP_VALUE, &strval) == 0);
1242				verify(nvlist_lookup_string(propval,
1243				    ZPROP_SOURCE, &sourceval) == 0);
1244
1245				if (strcmp(sourceval,
1246				    zfs_get_name(zhp)) == 0) {
1247					sourcetype = ZPROP_SRC_LOCAL;
1248				} else if (strcmp(sourceval,
1249				    ZPROP_SOURCE_VAL_RECVD) == 0) {
1250					sourcetype = ZPROP_SRC_RECEIVED;
1251				} else {
1252					sourcetype = ZPROP_SRC_INHERITED;
1253					(void) strlcpy(source,
1254					    sourceval, sizeof (source));
1255				}
1256			}
1257
1258			if (received && (zfs_prop_get_recvd(zhp,
1259			    pl->pl_user_prop, rbuf, sizeof (rbuf),
1260			    cbp->cb_literal) == 0))
1261				recvdval = rbuf;
1262
1263			zprop_print_one_property(zfs_get_name(zhp), cbp,
1264			    pl->pl_user_prop, strval, sourcetype,
1265			    source, recvdval);
1266		}
1267	}
1268
1269	return (0);
1270}
1271
1272static int
1273zfs_do_get(int argc, char **argv)
1274{
1275	zprop_get_cbdata_t cb = { 0 };
1276	int i, c, flags = 0;
1277	char *value, *fields;
1278	int ret;
1279	int limit = 0;
1280	zprop_list_t fake_name = { 0 };
1281
1282	/*
1283	 * Set up default columns and sources.
1284	 */
1285	cb.cb_sources = ZPROP_SRC_ALL;
1286	cb.cb_columns[0] = GET_COL_NAME;
1287	cb.cb_columns[1] = GET_COL_PROPERTY;
1288	cb.cb_columns[2] = GET_COL_VALUE;
1289	cb.cb_columns[3] = GET_COL_SOURCE;
1290	cb.cb_type = ZFS_TYPE_DATASET;
1291
1292	/* check options */
1293	while ((c = getopt(argc, argv, ":d:o:s:rHp")) != -1) {
1294		switch (c) {
1295		case 'p':
1296			cb.cb_literal = B_TRUE;
1297			break;
1298		case 'd':
1299			limit = parse_depth(optarg, &flags);
1300			break;
1301		case 'r':
1302			flags |= ZFS_ITER_RECURSE;
1303			break;
1304		case 'H':
1305			cb.cb_scripted = B_TRUE;
1306			break;
1307		case ':':
1308			(void) fprintf(stderr, gettext("missing argument for "
1309			    "'%c' option\n"), optopt);
1310			usage(B_FALSE);
1311			break;
1312		case 'o':
1313			/*
1314			 * Process the set of columns to display.  We zero out
1315			 * the structure to give us a blank slate.
1316			 */
1317			bzero(&cb.cb_columns, sizeof (cb.cb_columns));
1318			i = 0;
1319			while (*optarg != '\0') {
1320				static char *col_subopts[] =
1321				    { "name", "property", "value", "received",
1322				    "source", "all", NULL };
1323
1324				if (i == ZFS_GET_NCOLS) {
1325					(void) fprintf(stderr, gettext("too "
1326					    "many fields given to -o "
1327					    "option\n"));
1328					usage(B_FALSE);
1329				}
1330
1331				switch (getsubopt(&optarg, col_subopts,
1332				    &value)) {
1333				case 0:
1334					cb.cb_columns[i++] = GET_COL_NAME;
1335					break;
1336				case 1:
1337					cb.cb_columns[i++] = GET_COL_PROPERTY;
1338					break;
1339				case 2:
1340					cb.cb_columns[i++] = GET_COL_VALUE;
1341					break;
1342				case 3:
1343					cb.cb_columns[i++] = GET_COL_RECVD;
1344					flags |= ZFS_ITER_RECVD_PROPS;
1345					break;
1346				case 4:
1347					cb.cb_columns[i++] = GET_COL_SOURCE;
1348					break;
1349				case 5:
1350					if (i > 0) {
1351						(void) fprintf(stderr,
1352						    gettext("\"all\" conflicts "
1353						    "with specific fields "
1354						    "given to -o option\n"));
1355						usage(B_FALSE);
1356					}
1357					cb.cb_columns[0] = GET_COL_NAME;
1358					cb.cb_columns[1] = GET_COL_PROPERTY;
1359					cb.cb_columns[2] = GET_COL_VALUE;
1360					cb.cb_columns[3] = GET_COL_RECVD;
1361					cb.cb_columns[4] = GET_COL_SOURCE;
1362					flags |= ZFS_ITER_RECVD_PROPS;
1363					i = ZFS_GET_NCOLS;
1364					break;
1365				default:
1366					(void) fprintf(stderr,
1367					    gettext("invalid column name "
1368					    "'%s'\n"), value);
1369					usage(B_FALSE);
1370				}
1371			}
1372			break;
1373
1374		case 's':
1375			cb.cb_sources = 0;
1376			while (*optarg != '\0') {
1377				static char *source_subopts[] = {
1378					"local", "default", "inherited",
1379					"received", "temporary", "none",
1380					NULL };
1381
1382				switch (getsubopt(&optarg, source_subopts,
1383				    &value)) {
1384				case 0:
1385					cb.cb_sources |= ZPROP_SRC_LOCAL;
1386					break;
1387				case 1:
1388					cb.cb_sources |= ZPROP_SRC_DEFAULT;
1389					break;
1390				case 2:
1391					cb.cb_sources |= ZPROP_SRC_INHERITED;
1392					break;
1393				case 3:
1394					cb.cb_sources |= ZPROP_SRC_RECEIVED;
1395					break;
1396				case 4:
1397					cb.cb_sources |= ZPROP_SRC_TEMPORARY;
1398					break;
1399				case 5:
1400					cb.cb_sources |= ZPROP_SRC_NONE;
1401					break;
1402				default:
1403					(void) fprintf(stderr,
1404					    gettext("invalid source "
1405					    "'%s'\n"), value);
1406					usage(B_FALSE);
1407				}
1408			}
1409			break;
1410
1411		case '?':
1412			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1413			    optopt);
1414			usage(B_FALSE);
1415		}
1416	}
1417
1418	argc -= optind;
1419	argv += optind;
1420
1421	if (argc < 1) {
1422		(void) fprintf(stderr, gettext("missing property "
1423		    "argument\n"));
1424		usage(B_FALSE);
1425	}
1426
1427	fields = argv[0];
1428
1429	if (zprop_get_list(g_zfs, fields, &cb.cb_proplist, ZFS_TYPE_DATASET)
1430	    != 0)
1431		usage(B_FALSE);
1432
1433	argc--;
1434	argv++;
1435
1436	/*
1437	 * As part of zfs_expand_proplist(), we keep track of the maximum column
1438	 * width for each property.  For the 'NAME' (and 'SOURCE') columns, we
1439	 * need to know the maximum name length.  However, the user likely did
1440	 * not specify 'name' as one of the properties to fetch, so we need to
1441	 * make sure we always include at least this property for
1442	 * print_get_headers() to work properly.
1443	 */
1444	if (cb.cb_proplist != NULL) {
1445		fake_name.pl_prop = ZFS_PROP_NAME;
1446		fake_name.pl_width = strlen(gettext("NAME"));
1447		fake_name.pl_next = cb.cb_proplist;
1448		cb.cb_proplist = &fake_name;
1449	}
1450
1451	cb.cb_first = B_TRUE;
1452
1453	/* run for each object */
1454	ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_DATASET, NULL,
1455	    &cb.cb_proplist, limit, get_callback, &cb);
1456
1457	if (cb.cb_proplist == &fake_name)
1458		zprop_free_list(fake_name.pl_next);
1459	else
1460		zprop_free_list(cb.cb_proplist);
1461
1462	return (ret);
1463}
1464
1465/*
1466 * inherit [-rS] <property> <fs|vol> ...
1467 *
1468 *	-r	Recurse over all children
1469 *	-S	Revert to received value, if any
1470 *
1471 * For each dataset specified on the command line, inherit the given property
1472 * from its parent.  Inheriting a property at the pool level will cause it to
1473 * use the default value.  The '-r' flag will recurse over all children, and is
1474 * useful for setting a property on a hierarchy-wide basis, regardless of any
1475 * local modifications for each dataset.
1476 */
1477
1478typedef struct inherit_cbdata {
1479	const char *cb_propname;
1480	boolean_t cb_received;
1481} inherit_cbdata_t;
1482
1483static int
1484inherit_recurse_cb(zfs_handle_t *zhp, void *data)
1485{
1486	inherit_cbdata_t *cb = data;
1487	zfs_prop_t prop = zfs_name_to_prop(cb->cb_propname);
1488
1489	/*
1490	 * If we're doing it recursively, then ignore properties that
1491	 * are not valid for this type of dataset.
1492	 */
1493	if (prop != ZPROP_INVAL &&
1494	    !zfs_prop_valid_for_type(prop, zfs_get_type(zhp)))
1495		return (0);
1496
1497	return (zfs_prop_inherit(zhp, cb->cb_propname, cb->cb_received) != 0);
1498}
1499
1500static int
1501inherit_cb(zfs_handle_t *zhp, void *data)
1502{
1503	inherit_cbdata_t *cb = data;
1504
1505	return (zfs_prop_inherit(zhp, cb->cb_propname, cb->cb_received) != 0);
1506}
1507
1508static int
1509zfs_do_inherit(int argc, char **argv)
1510{
1511	int c;
1512	zfs_prop_t prop;
1513	inherit_cbdata_t cb = { 0 };
1514	char *propname;
1515	int ret;
1516	int flags = 0;
1517	boolean_t received = B_FALSE;
1518
1519	/* check options */
1520	while ((c = getopt(argc, argv, "rS")) != -1) {
1521		switch (c) {
1522		case 'r':
1523			flags |= ZFS_ITER_RECURSE;
1524			break;
1525		case 'S':
1526			received = B_TRUE;
1527			break;
1528		case '?':
1529		default:
1530			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1531			    optopt);
1532			usage(B_FALSE);
1533		}
1534	}
1535
1536	argc -= optind;
1537	argv += optind;
1538
1539	/* check number of arguments */
1540	if (argc < 1) {
1541		(void) fprintf(stderr, gettext("missing property argument\n"));
1542		usage(B_FALSE);
1543	}
1544	if (argc < 2) {
1545		(void) fprintf(stderr, gettext("missing dataset argument\n"));
1546		usage(B_FALSE);
1547	}
1548
1549	propname = argv[0];
1550	argc--;
1551	argv++;
1552
1553	if ((prop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
1554		if (zfs_prop_readonly(prop)) {
1555			(void) fprintf(stderr, gettext(
1556			    "%s property is read-only\n"),
1557			    propname);
1558			return (1);
1559		}
1560		if (!zfs_prop_inheritable(prop) && !received) {
1561			(void) fprintf(stderr, gettext("'%s' property cannot "
1562			    "be inherited\n"), propname);
1563			if (prop == ZFS_PROP_QUOTA ||
1564			    prop == ZFS_PROP_RESERVATION ||
1565			    prop == ZFS_PROP_REFQUOTA ||
1566			    prop == ZFS_PROP_REFRESERVATION)
1567				(void) fprintf(stderr, gettext("use 'zfs set "
1568				    "%s=none' to clear\n"), propname);
1569			return (1);
1570		}
1571		if (received && (prop == ZFS_PROP_VOLSIZE ||
1572		    prop == ZFS_PROP_VERSION)) {
1573			(void) fprintf(stderr, gettext("'%s' property cannot "
1574			    "be reverted to a received value\n"), propname);
1575			return (1);
1576		}
1577	} else if (!zfs_prop_user(propname)) {
1578		(void) fprintf(stderr, gettext("invalid property '%s'\n"),
1579		    propname);
1580		usage(B_FALSE);
1581	}
1582
1583	cb.cb_propname = propname;
1584	cb.cb_received = received;
1585
1586	if (flags & ZFS_ITER_RECURSE) {
1587		ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_DATASET,
1588		    NULL, NULL, 0, inherit_recurse_cb, &cb);
1589	} else {
1590		ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_DATASET,
1591		    NULL, NULL, 0, inherit_cb, &cb);
1592	}
1593
1594	return (ret);
1595}
1596
1597typedef struct upgrade_cbdata {
1598	uint64_t cb_numupgraded;
1599	uint64_t cb_numsamegraded;
1600	uint64_t cb_numfailed;
1601	uint64_t cb_version;
1602	boolean_t cb_newer;
1603	boolean_t cb_foundone;
1604	char cb_lastfs[ZFS_MAXNAMELEN];
1605} upgrade_cbdata_t;
1606
1607static int
1608same_pool(zfs_handle_t *zhp, const char *name)
1609{
1610	int len1 = strcspn(name, "/@");
1611	const char *zhname = zfs_get_name(zhp);
1612	int len2 = strcspn(zhname, "/@");
1613
1614	if (len1 != len2)
1615		return (B_FALSE);
1616	return (strncmp(name, zhname, len1) == 0);
1617}
1618
1619static int
1620upgrade_list_callback(zfs_handle_t *zhp, void *data)
1621{
1622	upgrade_cbdata_t *cb = data;
1623	int version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
1624
1625	/* list if it's old/new */
1626	if ((!cb->cb_newer && version < ZPL_VERSION) ||
1627	    (cb->cb_newer && version > ZPL_VERSION)) {
1628		char *str;
1629		if (cb->cb_newer) {
1630			str = gettext("The following filesystems are "
1631			    "formatted using a newer software version and\n"
1632			    "cannot be accessed on the current system.\n\n");
1633		} else {
1634			str = gettext("The following filesystems are "
1635			    "out of date, and can be upgraded.  After being\n"
1636			    "upgraded, these filesystems (and any 'zfs send' "
1637			    "streams generated from\n"
1638			    "subsequent snapshots) will no longer be "
1639			    "accessible by older software versions.\n\n");
1640		}
1641
1642		if (!cb->cb_foundone) {
1643			(void) puts(str);
1644			(void) printf(gettext("VER  FILESYSTEM\n"));
1645			(void) printf(gettext("---  ------------\n"));
1646			cb->cb_foundone = B_TRUE;
1647		}
1648
1649		(void) printf("%2u   %s\n", version, zfs_get_name(zhp));
1650	}
1651
1652	return (0);
1653}
1654
1655static int
1656upgrade_set_callback(zfs_handle_t *zhp, void *data)
1657{
1658	upgrade_cbdata_t *cb = data;
1659	int version = zfs_prop_get_int(zhp, ZFS_PROP_VERSION);
1660	int needed_spa_version;
1661	int spa_version;
1662
1663	if (zfs_spa_version(zhp, &spa_version) < 0)
1664		return (-1);
1665
1666	needed_spa_version = zfs_spa_version_map(cb->cb_version);
1667
1668	if (needed_spa_version < 0)
1669		return (-1);
1670
1671	if (spa_version < needed_spa_version) {
1672		/* can't upgrade */
1673		(void) printf(gettext("%s: can not be "
1674		    "upgraded; the pool version needs to first "
1675		    "be upgraded\nto version %d\n\n"),
1676		    zfs_get_name(zhp), needed_spa_version);
1677		cb->cb_numfailed++;
1678		return (0);
1679	}
1680
1681	/* upgrade */
1682	if (version < cb->cb_version) {
1683		char verstr[16];
1684		(void) snprintf(verstr, sizeof (verstr),
1685		    "%llu", cb->cb_version);
1686		if (cb->cb_lastfs[0] && !same_pool(zhp, cb->cb_lastfs)) {
1687			/*
1688			 * If they did "zfs upgrade -a", then we could
1689			 * be doing ioctls to different pools.  We need
1690			 * to log this history once to each pool.
1691			 */
1692			verify(zpool_stage_history(g_zfs, history_str) == 0);
1693		}
1694		if (zfs_prop_set(zhp, "version", verstr) == 0)
1695			cb->cb_numupgraded++;
1696		else
1697			cb->cb_numfailed++;
1698		(void) strcpy(cb->cb_lastfs, zfs_get_name(zhp));
1699	} else if (version > cb->cb_version) {
1700		/* can't downgrade */
1701		(void) printf(gettext("%s: can not be downgraded; "
1702		    "it is already at version %u\n"),
1703		    zfs_get_name(zhp), version);
1704		cb->cb_numfailed++;
1705	} else {
1706		cb->cb_numsamegraded++;
1707	}
1708	return (0);
1709}
1710
1711/*
1712 * zfs upgrade
1713 * zfs upgrade -v
1714 * zfs upgrade [-r] [-V <version>] <-a | filesystem>
1715 */
1716static int
1717zfs_do_upgrade(int argc, char **argv)
1718{
1719	boolean_t all = B_FALSE;
1720	boolean_t showversions = B_FALSE;
1721	int ret;
1722	upgrade_cbdata_t cb = { 0 };
1723	char c;
1724	int flags = ZFS_ITER_ARGS_CAN_BE_PATHS;
1725
1726	/* check options */
1727	while ((c = getopt(argc, argv, "rvV:a")) != -1) {
1728		switch (c) {
1729		case 'r':
1730			flags |= ZFS_ITER_RECURSE;
1731			break;
1732		case 'v':
1733			showversions = B_TRUE;
1734			break;
1735		case 'V':
1736			if (zfs_prop_string_to_index(ZFS_PROP_VERSION,
1737			    optarg, &cb.cb_version) != 0) {
1738				(void) fprintf(stderr,
1739				    gettext("invalid version %s\n"), optarg);
1740				usage(B_FALSE);
1741			}
1742			break;
1743		case 'a':
1744			all = B_TRUE;
1745			break;
1746		case '?':
1747		default:
1748			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
1749			    optopt);
1750			usage(B_FALSE);
1751		}
1752	}
1753
1754	argc -= optind;
1755	argv += optind;
1756
1757	if ((!all && !argc) && ((flags & ZFS_ITER_RECURSE) | cb.cb_version))
1758		usage(B_FALSE);
1759	if (showversions && (flags & ZFS_ITER_RECURSE || all ||
1760	    cb.cb_version || argc))
1761		usage(B_FALSE);
1762	if ((all || argc) && (showversions))
1763		usage(B_FALSE);
1764	if (all && argc)
1765		usage(B_FALSE);
1766
1767	if (showversions) {
1768		/* Show info on available versions. */
1769		(void) printf(gettext("The following filesystem versions are "
1770		    "supported:\n\n"));
1771		(void) printf(gettext("VER  DESCRIPTION\n"));
1772		(void) printf("---  -----------------------------------------"
1773		    "---------------\n");
1774		(void) printf(gettext(" 1   Initial ZFS filesystem version\n"));
1775		(void) printf(gettext(" 2   Enhanced directory entries\n"));
1776		(void) printf(gettext(" 3   Case insensitive and File system "
1777		    "unique identifier (FUID)\n"));
1778		(void) printf(gettext(" 4   userquota, groupquota "
1779		    "properties\n"));
1780		(void) printf(gettext(" 5   System attributes\n"));
1781		(void) printf(gettext("\nFor more information on a particular "
1782		    "version, including supported releases,\n"));
1783		(void) printf("see the ZFS Administration Guide.\n\n");
1784		ret = 0;
1785	} else if (argc || all) {
1786		/* Upgrade filesystems */
1787		if (cb.cb_version == 0)
1788			cb.cb_version = ZPL_VERSION;
1789		ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_FILESYSTEM,
1790		    NULL, NULL, 0, upgrade_set_callback, &cb);
1791		(void) printf(gettext("%llu filesystems upgraded\n"),
1792		    cb.cb_numupgraded);
1793		if (cb.cb_numsamegraded) {
1794			(void) printf(gettext("%llu filesystems already at "
1795			    "this version\n"),
1796			    cb.cb_numsamegraded);
1797		}
1798		if (cb.cb_numfailed != 0)
1799			ret = 1;
1800	} else {
1801		/* List old-version filesytems */
1802		boolean_t found;
1803		(void) printf(gettext("This system is currently running "
1804		    "ZFS filesystem version %llu.\n\n"), ZPL_VERSION);
1805
1806		flags |= ZFS_ITER_RECURSE;
1807		ret = zfs_for_each(0, NULL, flags, ZFS_TYPE_FILESYSTEM,
1808		    NULL, NULL, 0, upgrade_list_callback, &cb);
1809
1810		found = cb.cb_foundone;
1811		cb.cb_foundone = B_FALSE;
1812		cb.cb_newer = B_TRUE;
1813
1814		ret = zfs_for_each(0, NULL, flags, ZFS_TYPE_FILESYSTEM,
1815		    NULL, NULL, 0, upgrade_list_callback, &cb);
1816
1817		if (!cb.cb_foundone && !found) {
1818			(void) printf(gettext("All filesystems are "
1819			    "formatted with the current version.\n"));
1820		}
1821	}
1822
1823	return (ret);
1824}
1825
1826/*
1827 * zfs userspace
1828 */
1829static int
1830userspace_cb(void *arg, const char *domain, uid_t rid, uint64_t space)
1831{
1832	zfs_userquota_prop_t *typep = arg;
1833	zfs_userquota_prop_t p = *typep;
1834	char *name = NULL;
1835	char *ug, *propname;
1836	char namebuf[32];
1837	char sizebuf[32];
1838
1839	if (domain == NULL || domain[0] == '\0') {
1840		if (p == ZFS_PROP_GROUPUSED || p == ZFS_PROP_GROUPQUOTA) {
1841			struct group *g = getgrgid(rid);
1842			if (g)
1843				name = g->gr_name;
1844		} else {
1845			struct passwd *p = getpwuid(rid);
1846			if (p)
1847				name = p->pw_name;
1848		}
1849	}
1850
1851	if (p == ZFS_PROP_GROUPUSED || p == ZFS_PROP_GROUPQUOTA)
1852		ug = "group";
1853	else
1854		ug = "user";
1855
1856	if (p == ZFS_PROP_USERUSED || p == ZFS_PROP_GROUPUSED)
1857		propname = "used";
1858	else
1859		propname = "quota";
1860
1861	if (name == NULL) {
1862		(void) snprintf(namebuf, sizeof (namebuf),
1863		    "%llu", (longlong_t)rid);
1864		name = namebuf;
1865	}
1866	zfs_nicenum(space, sizebuf, sizeof (sizebuf));
1867
1868	(void) printf("%s %s %s%c%s %s\n", propname, ug, domain,
1869	    domain[0] ? '-' : ' ', name, sizebuf);
1870
1871	return (0);
1872}
1873
1874static int
1875zfs_do_userspace(int argc, char **argv)
1876{
1877	zfs_handle_t *zhp;
1878	zfs_userquota_prop_t p;
1879	int error;
1880
1881	/*
1882	 * Try the python version.  If the execv fails, we'll continue
1883	 * and do a simplistic implementation.
1884	 */
1885	(void) execv(pypath, argv-1);
1886
1887	(void) printf("internal error: %s not found\n"
1888	    "falling back on built-in implementation, "
1889	    "some features will not work\n", pypath);
1890
1891	if ((zhp = zfs_open(g_zfs, argv[argc-1], ZFS_TYPE_DATASET)) == NULL)
1892		return (1);
1893
1894	(void) printf("PROP TYPE NAME VALUE\n");
1895
1896	for (p = 0; p < ZFS_NUM_USERQUOTA_PROPS; p++) {
1897		error = zfs_userspace(zhp, p, userspace_cb, &p);
1898		if (error)
1899			break;
1900	}
1901	return (error);
1902}
1903
1904/*
1905 * list [-r][-d max] [-H] [-o property[,property]...] [-t type[,type]...]
1906 *      [-s property [-s property]...] [-S property [-S property]...]
1907 *      <dataset> ...
1908 *
1909 *	-r	Recurse over all children
1910 *	-d	Limit recursion by depth.
1911 *	-H	Scripted mode; elide headers and separate columns by tabs
1912 *	-o	Control which fields to display.
1913 *	-t	Control which object types to display.
1914 *	-s	Specify sort columns, descending order.
1915 *	-S	Specify sort columns, ascending order.
1916 *
1917 * When given no arguments, lists all filesystems in the system.
1918 * Otherwise, list the specified datasets, optionally recursing down them if
1919 * '-r' is specified.
1920 */
1921typedef struct list_cbdata {
1922	boolean_t	cb_first;
1923	boolean_t	cb_scripted;
1924	zprop_list_t	*cb_proplist;
1925} list_cbdata_t;
1926
1927/*
1928 * Given a list of columns to display, output appropriate headers for each one.
1929 */
1930static void
1931print_header(zprop_list_t *pl)
1932{
1933	char headerbuf[ZFS_MAXPROPLEN];
1934	const char *header;
1935	int i;
1936	boolean_t first = B_TRUE;
1937	boolean_t right_justify;
1938
1939	for (; pl != NULL; pl = pl->pl_next) {
1940		if (!first) {
1941			(void) printf("  ");
1942		} else {
1943			first = B_FALSE;
1944		}
1945
1946		right_justify = B_FALSE;
1947		if (pl->pl_prop != ZPROP_INVAL) {
1948			header = zfs_prop_column_name(pl->pl_prop);
1949			right_justify = zfs_prop_align_right(pl->pl_prop);
1950		} else {
1951			for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
1952				headerbuf[i] = toupper(pl->pl_user_prop[i]);
1953			headerbuf[i] = '\0';
1954			header = headerbuf;
1955		}
1956
1957		if (pl->pl_next == NULL && !right_justify)
1958			(void) printf("%s", header);
1959		else if (right_justify)
1960			(void) printf("%*s", pl->pl_width, header);
1961		else
1962			(void) printf("%-*s", pl->pl_width, header);
1963	}
1964
1965	(void) printf("\n");
1966}
1967
1968/*
1969 * Given a dataset and a list of fields, print out all the properties according
1970 * to the described layout.
1971 */
1972static void
1973print_dataset(zfs_handle_t *zhp, zprop_list_t *pl, boolean_t scripted)
1974{
1975	boolean_t first = B_TRUE;
1976	char property[ZFS_MAXPROPLEN];
1977	nvlist_t *userprops = zfs_get_user_props(zhp);
1978	nvlist_t *propval;
1979	char *propstr;
1980	boolean_t right_justify;
1981	int width;
1982
1983	for (; pl != NULL; pl = pl->pl_next) {
1984		if (!first) {
1985			if (scripted)
1986				(void) printf("\t");
1987			else
1988				(void) printf("  ");
1989		} else {
1990			first = B_FALSE;
1991		}
1992
1993		if (pl->pl_prop != ZPROP_INVAL) {
1994			if (zfs_prop_get(zhp, pl->pl_prop, property,
1995			    sizeof (property), NULL, NULL, 0, B_FALSE) != 0)
1996				propstr = "-";
1997			else
1998				propstr = property;
1999
2000			right_justify = zfs_prop_align_right(pl->pl_prop);
2001		} else if (zfs_prop_userquota(pl->pl_user_prop)) {
2002			if (zfs_prop_get_userquota(zhp, pl->pl_user_prop,
2003			    property, sizeof (property), B_FALSE) != 0)
2004				propstr = "-";
2005			else
2006				propstr = property;
2007			right_justify = B_TRUE;
2008		} else {
2009			if (nvlist_lookup_nvlist(userprops,
2010			    pl->pl_user_prop, &propval) != 0)
2011				propstr = "-";
2012			else
2013				verify(nvlist_lookup_string(propval,
2014				    ZPROP_VALUE, &propstr) == 0);
2015			right_justify = B_FALSE;
2016		}
2017
2018		width = pl->pl_width;
2019
2020		/*
2021		 * If this is being called in scripted mode, or if this is the
2022		 * last column and it is left-justified, don't include a width
2023		 * format specifier.
2024		 */
2025		if (scripted || (pl->pl_next == NULL && !right_justify))
2026			(void) printf("%s", propstr);
2027		else if (right_justify)
2028			(void) printf("%*s", width, propstr);
2029		else
2030			(void) printf("%-*s", width, propstr);
2031	}
2032
2033	(void) printf("\n");
2034}
2035
2036/*
2037 * Generic callback function to list a dataset or snapshot.
2038 */
2039static int
2040list_callback(zfs_handle_t *zhp, void *data)
2041{
2042	list_cbdata_t *cbp = data;
2043
2044	if (cbp->cb_first) {
2045		if (!cbp->cb_scripted)
2046			print_header(cbp->cb_proplist);
2047		cbp->cb_first = B_FALSE;
2048	}
2049
2050	print_dataset(zhp, cbp->cb_proplist, cbp->cb_scripted);
2051
2052	return (0);
2053}
2054
2055static int
2056zfs_do_list(int argc, char **argv)
2057{
2058	int c;
2059	boolean_t scripted = B_FALSE;
2060	static char default_fields[] =
2061	    "name,used,available,referenced,mountpoint";
2062	int types = ZFS_TYPE_DATASET;
2063	boolean_t types_specified = B_FALSE;
2064	char *fields = NULL;
2065	list_cbdata_t cb = { 0 };
2066	char *value;
2067	int limit = 0;
2068	int ret;
2069	zfs_sort_column_t *sortcol = NULL;
2070	int flags = ZFS_ITER_PROP_LISTSNAPS | ZFS_ITER_ARGS_CAN_BE_PATHS;
2071
2072	/* check options */
2073	while ((c = getopt(argc, argv, ":d:o:rt:Hs:S:")) != -1) {
2074		switch (c) {
2075		case 'o':
2076			fields = optarg;
2077			break;
2078		case 'd':
2079			limit = parse_depth(optarg, &flags);
2080			break;
2081		case 'r':
2082			flags |= ZFS_ITER_RECURSE;
2083			break;
2084		case 'H':
2085			scripted = B_TRUE;
2086			break;
2087		case 's':
2088			if (zfs_add_sort_column(&sortcol, optarg,
2089			    B_FALSE) != 0) {
2090				(void) fprintf(stderr,
2091				    gettext("invalid property '%s'\n"), optarg);
2092				usage(B_FALSE);
2093			}
2094			break;
2095		case 'S':
2096			if (zfs_add_sort_column(&sortcol, optarg,
2097			    B_TRUE) != 0) {
2098				(void) fprintf(stderr,
2099				    gettext("invalid property '%s'\n"), optarg);
2100				usage(B_FALSE);
2101			}
2102			break;
2103		case 't':
2104			types = 0;
2105			types_specified = B_TRUE;
2106			flags &= ~ZFS_ITER_PROP_LISTSNAPS;
2107			while (*optarg != '\0') {
2108				static char *type_subopts[] = { "filesystem",
2109				    "volume", "snapshot", "all", NULL };
2110
2111				switch (getsubopt(&optarg, type_subopts,
2112				    &value)) {
2113				case 0:
2114					types |= ZFS_TYPE_FILESYSTEM;
2115					break;
2116				case 1:
2117					types |= ZFS_TYPE_VOLUME;
2118					break;
2119				case 2:
2120					types |= ZFS_TYPE_SNAPSHOT;
2121					break;
2122				case 3:
2123					types = ZFS_TYPE_DATASET;
2124					break;
2125
2126				default:
2127					(void) fprintf(stderr,
2128					    gettext("invalid type '%s'\n"),
2129					    value);
2130					usage(B_FALSE);
2131				}
2132			}
2133			break;
2134		case ':':
2135			(void) fprintf(stderr, gettext("missing argument for "
2136			    "'%c' option\n"), optopt);
2137			usage(B_FALSE);
2138			break;
2139		case '?':
2140			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2141			    optopt);
2142			usage(B_FALSE);
2143		}
2144	}
2145
2146	argc -= optind;
2147	argv += optind;
2148
2149	if (fields == NULL)
2150		fields = default_fields;
2151
2152	/*
2153	 * If "-o space" and no types were specified, don't display snapshots.
2154	 */
2155	if (strcmp(fields, "space") == 0 && types_specified == B_FALSE)
2156		types &= ~ZFS_TYPE_SNAPSHOT;
2157
2158	/*
2159	 * If the user specifies '-o all', the zprop_get_list() doesn't
2160	 * normally include the name of the dataset.  For 'zfs list', we always
2161	 * want this property to be first.
2162	 */
2163	if (zprop_get_list(g_zfs, fields, &cb.cb_proplist, ZFS_TYPE_DATASET)
2164	    != 0)
2165		usage(B_FALSE);
2166
2167	cb.cb_scripted = scripted;
2168	cb.cb_first = B_TRUE;
2169
2170	ret = zfs_for_each(argc, argv, flags, types, sortcol, &cb.cb_proplist,
2171	    limit, list_callback, &cb);
2172
2173	zprop_free_list(cb.cb_proplist);
2174	zfs_free_sort_columns(sortcol);
2175
2176	if (ret == 0 && cb.cb_first && !cb.cb_scripted)
2177		(void) printf(gettext("no datasets available\n"));
2178
2179	return (ret);
2180}
2181
2182/*
2183 * zfs rename <fs | snap | vol> <fs | snap | vol>
2184 * zfs rename -p <fs | vol> <fs | vol>
2185 * zfs rename -r <snap> <snap>
2186 *
2187 * Renames the given dataset to another of the same type.
2188 *
2189 * The '-p' flag creates all the non-existing ancestors of the target first.
2190 */
2191/* ARGSUSED */
2192static int
2193zfs_do_rename(int argc, char **argv)
2194{
2195	zfs_handle_t *zhp;
2196	int c;
2197	int ret;
2198	boolean_t recurse = B_FALSE;
2199	boolean_t parents = B_FALSE;
2200
2201	/* check options */
2202	while ((c = getopt(argc, argv, "pr")) != -1) {
2203		switch (c) {
2204		case 'p':
2205			parents = B_TRUE;
2206			break;
2207		case 'r':
2208			recurse = B_TRUE;
2209			break;
2210		case '?':
2211		default:
2212			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2213			    optopt);
2214			usage(B_FALSE);
2215		}
2216	}
2217
2218	argc -= optind;
2219	argv += optind;
2220
2221	/* check number of arguments */
2222	if (argc < 1) {
2223		(void) fprintf(stderr, gettext("missing source dataset "
2224		    "argument\n"));
2225		usage(B_FALSE);
2226	}
2227	if (argc < 2) {
2228		(void) fprintf(stderr, gettext("missing target dataset "
2229		    "argument\n"));
2230		usage(B_FALSE);
2231	}
2232	if (argc > 2) {
2233		(void) fprintf(stderr, gettext("too many arguments\n"));
2234		usage(B_FALSE);
2235	}
2236
2237	if (recurse && parents) {
2238		(void) fprintf(stderr, gettext("-p and -r options are mutually "
2239		    "exclusive\n"));
2240		usage(B_FALSE);
2241	}
2242
2243	if (recurse && strchr(argv[0], '@') == 0) {
2244		(void) fprintf(stderr, gettext("source dataset for recursive "
2245		    "rename must be a snapshot\n"));
2246		usage(B_FALSE);
2247	}
2248
2249	if ((zhp = zfs_open(g_zfs, argv[0], parents ? ZFS_TYPE_FILESYSTEM |
2250	    ZFS_TYPE_VOLUME : ZFS_TYPE_DATASET)) == NULL)
2251		return (1);
2252
2253	/* If we were asked and the name looks good, try to create ancestors. */
2254	if (parents && zfs_name_valid(argv[1], zfs_get_type(zhp)) &&
2255	    zfs_create_ancestors(g_zfs, argv[1]) != 0) {
2256		zfs_close(zhp);
2257		return (1);
2258	}
2259
2260	ret = (zfs_rename(zhp, argv[1], recurse) != 0);
2261
2262	zfs_close(zhp);
2263	return (ret);
2264}
2265
2266/*
2267 * zfs promote <fs>
2268 *
2269 * Promotes the given clone fs to be the parent
2270 */
2271/* ARGSUSED */
2272static int
2273zfs_do_promote(int argc, char **argv)
2274{
2275	zfs_handle_t *zhp;
2276	int ret;
2277
2278	/* check options */
2279	if (argc > 1 && argv[1][0] == '-') {
2280		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2281		    argv[1][1]);
2282		usage(B_FALSE);
2283	}
2284
2285	/* check number of arguments */
2286	if (argc < 2) {
2287		(void) fprintf(stderr, gettext("missing clone filesystem"
2288		    " argument\n"));
2289		usage(B_FALSE);
2290	}
2291	if (argc > 2) {
2292		(void) fprintf(stderr, gettext("too many arguments\n"));
2293		usage(B_FALSE);
2294	}
2295
2296	zhp = zfs_open(g_zfs, argv[1], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
2297	if (zhp == NULL)
2298		return (1);
2299
2300	ret = (zfs_promote(zhp) != 0);
2301
2302
2303	zfs_close(zhp);
2304	return (ret);
2305}
2306
2307/*
2308 * zfs rollback [-rRf] <snapshot>
2309 *
2310 *	-r	Delete any intervening snapshots before doing rollback
2311 *	-R	Delete any snapshots and their clones
2312 *	-f	ignored for backwards compatability
2313 *
2314 * Given a filesystem, rollback to a specific snapshot, discarding any changes
2315 * since then and making it the active dataset.  If more recent snapshots exist,
2316 * the command will complain unless the '-r' flag is given.
2317 */
2318typedef struct rollback_cbdata {
2319	uint64_t	cb_create;
2320	boolean_t	cb_first;
2321	int		cb_doclones;
2322	char		*cb_target;
2323	int		cb_error;
2324	boolean_t	cb_recurse;
2325	boolean_t	cb_dependent;
2326} rollback_cbdata_t;
2327
2328/*
2329 * Report any snapshots more recent than the one specified.  Used when '-r' is
2330 * not specified.  We reuse this same callback for the snapshot dependents - if
2331 * 'cb_dependent' is set, then this is a dependent and we should report it
2332 * without checking the transaction group.
2333 */
2334static int
2335rollback_check(zfs_handle_t *zhp, void *data)
2336{
2337	rollback_cbdata_t *cbp = data;
2338
2339	if (cbp->cb_doclones) {
2340		zfs_close(zhp);
2341		return (0);
2342	}
2343
2344	if (!cbp->cb_dependent) {
2345		if (strcmp(zfs_get_name(zhp), cbp->cb_target) != 0 &&
2346		    zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
2347		    zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
2348		    cbp->cb_create) {
2349
2350			if (cbp->cb_first && !cbp->cb_recurse) {
2351				(void) fprintf(stderr, gettext("cannot "
2352				    "rollback to '%s': more recent snapshots "
2353				    "exist\n"),
2354				    cbp->cb_target);
2355				(void) fprintf(stderr, gettext("use '-r' to "
2356				    "force deletion of the following "
2357				    "snapshots:\n"));
2358				cbp->cb_first = 0;
2359				cbp->cb_error = 1;
2360			}
2361
2362			if (cbp->cb_recurse) {
2363				cbp->cb_dependent = B_TRUE;
2364				if (zfs_iter_dependents(zhp, B_TRUE,
2365				    rollback_check, cbp) != 0) {
2366					zfs_close(zhp);
2367					return (-1);
2368				}
2369				cbp->cb_dependent = B_FALSE;
2370			} else {
2371				(void) fprintf(stderr, "%s\n",
2372				    zfs_get_name(zhp));
2373			}
2374		}
2375	} else {
2376		if (cbp->cb_first && cbp->cb_recurse) {
2377			(void) fprintf(stderr, gettext("cannot rollback to "
2378			    "'%s': clones of previous snapshots exist\n"),
2379			    cbp->cb_target);
2380			(void) fprintf(stderr, gettext("use '-R' to "
2381			    "force deletion of the following clones and "
2382			    "dependents:\n"));
2383			cbp->cb_first = 0;
2384			cbp->cb_error = 1;
2385		}
2386
2387		(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
2388	}
2389
2390	zfs_close(zhp);
2391	return (0);
2392}
2393
2394static int
2395zfs_do_rollback(int argc, char **argv)
2396{
2397	int ret;
2398	int c;
2399	boolean_t force = B_FALSE;
2400	rollback_cbdata_t cb = { 0 };
2401	zfs_handle_t *zhp, *snap;
2402	char parentname[ZFS_MAXNAMELEN];
2403	char *delim;
2404
2405	/* check options */
2406	while ((c = getopt(argc, argv, "rRf")) != -1) {
2407		switch (c) {
2408		case 'r':
2409			cb.cb_recurse = 1;
2410			break;
2411		case 'R':
2412			cb.cb_recurse = 1;
2413			cb.cb_doclones = 1;
2414			break;
2415		case 'f':
2416			force = B_TRUE;
2417			break;
2418		case '?':
2419			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2420			    optopt);
2421			usage(B_FALSE);
2422		}
2423	}
2424
2425	argc -= optind;
2426	argv += optind;
2427
2428	/* check number of arguments */
2429	if (argc < 1) {
2430		(void) fprintf(stderr, gettext("missing dataset argument\n"));
2431		usage(B_FALSE);
2432	}
2433	if (argc > 1) {
2434		(void) fprintf(stderr, gettext("too many arguments\n"));
2435		usage(B_FALSE);
2436	}
2437
2438	/* open the snapshot */
2439	if ((snap = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL)
2440		return (1);
2441
2442	/* open the parent dataset */
2443	(void) strlcpy(parentname, argv[0], sizeof (parentname));
2444	verify((delim = strrchr(parentname, '@')) != NULL);
2445	*delim = '\0';
2446	if ((zhp = zfs_open(g_zfs, parentname, ZFS_TYPE_DATASET)) == NULL) {
2447		zfs_close(snap);
2448		return (1);
2449	}
2450
2451	/*
2452	 * Check for more recent snapshots and/or clones based on the presence
2453	 * of '-r' and '-R'.
2454	 */
2455	cb.cb_target = argv[0];
2456	cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
2457	cb.cb_first = B_TRUE;
2458	cb.cb_error = 0;
2459	if ((ret = zfs_iter_children(zhp, rollback_check, &cb)) != 0)
2460		goto out;
2461
2462	if ((ret = cb.cb_error) != 0)
2463		goto out;
2464
2465	/*
2466	 * Rollback parent to the given snapshot.
2467	 */
2468	ret = zfs_rollback(zhp, snap, force);
2469
2470out:
2471	zfs_close(snap);
2472	zfs_close(zhp);
2473
2474	if (ret == 0)
2475		return (0);
2476	else
2477		return (1);
2478}
2479
2480/*
2481 * zfs set property=value { fs | snap | vol } ...
2482 *
2483 * Sets the given property for all datasets specified on the command line.
2484 */
2485typedef struct set_cbdata {
2486	char		*cb_propname;
2487	char		*cb_value;
2488} set_cbdata_t;
2489
2490static int
2491set_callback(zfs_handle_t *zhp, void *data)
2492{
2493	set_cbdata_t *cbp = data;
2494
2495	if (zfs_prop_set(zhp, cbp->cb_propname, cbp->cb_value) != 0) {
2496		switch (libzfs_errno(g_zfs)) {
2497		case EZFS_MOUNTFAILED:
2498			(void) fprintf(stderr, gettext("property may be set "
2499			    "but unable to remount filesystem\n"));
2500			break;
2501		case EZFS_SHARENFSFAILED:
2502			(void) fprintf(stderr, gettext("property may be set "
2503			    "but unable to reshare filesystem\n"));
2504			break;
2505		}
2506		return (1);
2507	}
2508	return (0);
2509}
2510
2511static int
2512zfs_do_set(int argc, char **argv)
2513{
2514	set_cbdata_t cb;
2515	int ret;
2516
2517	/* check for options */
2518	if (argc > 1 && argv[1][0] == '-') {
2519		(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2520		    argv[1][1]);
2521		usage(B_FALSE);
2522	}
2523
2524	/* check number of arguments */
2525	if (argc < 2) {
2526		(void) fprintf(stderr, gettext("missing property=value "
2527		    "argument\n"));
2528		usage(B_FALSE);
2529	}
2530	if (argc < 3) {
2531		(void) fprintf(stderr, gettext("missing dataset name\n"));
2532		usage(B_FALSE);
2533	}
2534
2535	/* validate property=value argument */
2536	cb.cb_propname = argv[1];
2537	if (((cb.cb_value = strchr(cb.cb_propname, '=')) == NULL) ||
2538	    (cb.cb_value[1] == '\0')) {
2539		(void) fprintf(stderr, gettext("missing value in "
2540		    "property=value argument\n"));
2541		usage(B_FALSE);
2542	}
2543
2544	*cb.cb_value = '\0';
2545	cb.cb_value++;
2546
2547	if (*cb.cb_propname == '\0') {
2548		(void) fprintf(stderr,
2549		    gettext("missing property in property=value argument\n"));
2550		usage(B_FALSE);
2551	}
2552
2553	ret = zfs_for_each(argc - 2, argv + 2, NULL,
2554	    ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, &cb);
2555
2556	return (ret);
2557}
2558
2559/*
2560 * zfs snapshot [-r] [-o prop=value] ... <fs@snap>
2561 *
2562 * Creates a snapshot with the given name.  While functionally equivalent to
2563 * 'zfs create', it is a separate command to differentiate intent.
2564 */
2565static int
2566zfs_do_snapshot(int argc, char **argv)
2567{
2568	boolean_t recursive = B_FALSE;
2569	int ret;
2570	char c;
2571	nvlist_t *props;
2572
2573	if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
2574		nomem();
2575
2576	/* check options */
2577	while ((c = getopt(argc, argv, "ro:")) != -1) {
2578		switch (c) {
2579		case 'o':
2580			if (parseprop(props))
2581				return (1);
2582			break;
2583		case 'r':
2584			recursive = B_TRUE;
2585			break;
2586		case '?':
2587			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2588			    optopt);
2589			goto usage;
2590		}
2591	}
2592
2593	argc -= optind;
2594	argv += optind;
2595
2596	/* check number of arguments */
2597	if (argc < 1) {
2598		(void) fprintf(stderr, gettext("missing snapshot argument\n"));
2599		goto usage;
2600	}
2601	if (argc > 1) {
2602		(void) fprintf(stderr, gettext("too many arguments\n"));
2603		goto usage;
2604	}
2605
2606	ret = zfs_snapshot(g_zfs, argv[0], recursive, props);
2607	nvlist_free(props);
2608	if (ret && recursive)
2609		(void) fprintf(stderr, gettext("no snapshots were created\n"));
2610	return (ret != 0);
2611
2612usage:
2613	nvlist_free(props);
2614	usage(B_FALSE);
2615	return (-1);
2616}
2617
2618/*
2619 * zfs send [-vDp] -R [-i|-I <@snap>] <fs@snap>
2620 * zfs send [-vDp] [-i|-I <@snap>] <fs@snap>
2621 *
2622 * Send a backup stream to stdout.
2623 */
2624static int
2625zfs_do_send(int argc, char **argv)
2626{
2627	char *fromname = NULL;
2628	char *toname = NULL;
2629	char *cp;
2630	zfs_handle_t *zhp;
2631	sendflags_t flags = { 0 };
2632	int c, err;
2633	nvlist_t *dbgnv;
2634	boolean_t extraverbose = B_FALSE;
2635
2636	/* check options */
2637	while ((c = getopt(argc, argv, ":i:I:RDpv")) != -1) {
2638		switch (c) {
2639		case 'i':
2640			if (fromname)
2641				usage(B_FALSE);
2642			fromname = optarg;
2643			break;
2644		case 'I':
2645			if (fromname)
2646				usage(B_FALSE);
2647			fromname = optarg;
2648			flags.doall = B_TRUE;
2649			break;
2650		case 'R':
2651			flags.replicate = B_TRUE;
2652			break;
2653		case 'p':
2654			flags.props = B_TRUE;
2655			break;
2656		case 'v':
2657			if (flags.verbose)
2658				extraverbose = B_TRUE;
2659			flags.verbose = B_TRUE;
2660			break;
2661		case 'D':
2662			flags.dedup = B_TRUE;
2663			break;
2664		case ':':
2665			(void) fprintf(stderr, gettext("missing argument for "
2666			    "'%c' option\n"), optopt);
2667			usage(B_FALSE);
2668			break;
2669		case '?':
2670			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2671			    optopt);
2672			usage(B_FALSE);
2673		}
2674	}
2675
2676	argc -= optind;
2677	argv += optind;
2678
2679	/* check number of arguments */
2680	if (argc < 1) {
2681		(void) fprintf(stderr, gettext("missing snapshot argument\n"));
2682		usage(B_FALSE);
2683	}
2684	if (argc > 1) {
2685		(void) fprintf(stderr, gettext("too many arguments\n"));
2686		usage(B_FALSE);
2687	}
2688
2689	if (isatty(STDOUT_FILENO)) {
2690		(void) fprintf(stderr,
2691		    gettext("Error: Stream can not be written to a terminal.\n"
2692		    "You must redirect standard output.\n"));
2693		return (1);
2694	}
2695
2696	cp = strchr(argv[0], '@');
2697	if (cp == NULL) {
2698		(void) fprintf(stderr,
2699		    gettext("argument must be a snapshot\n"));
2700		usage(B_FALSE);
2701	}
2702	*cp = '\0';
2703	toname = cp + 1;
2704	zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
2705	if (zhp == NULL)
2706		return (1);
2707
2708	/*
2709	 * If they specified the full path to the snapshot, chop off
2710	 * everything except the short name of the snapshot, but special
2711	 * case if they specify the origin.
2712	 */
2713	if (fromname && (cp = strchr(fromname, '@')) != NULL) {
2714		char origin[ZFS_MAXNAMELEN];
2715		zprop_source_t src;
2716
2717		(void) zfs_prop_get(zhp, ZFS_PROP_ORIGIN,
2718		    origin, sizeof (origin), &src, NULL, 0, B_FALSE);
2719
2720		if (strcmp(origin, fromname) == 0) {
2721			fromname = NULL;
2722			flags.fromorigin = B_TRUE;
2723		} else {
2724			*cp = '\0';
2725			if (cp != fromname && strcmp(argv[0], fromname)) {
2726				(void) fprintf(stderr,
2727				    gettext("incremental source must be "
2728				    "in same filesystem\n"));
2729				usage(B_FALSE);
2730			}
2731			fromname = cp + 1;
2732			if (strchr(fromname, '@') || strchr(fromname, '/')) {
2733				(void) fprintf(stderr,
2734				    gettext("invalid incremental source\n"));
2735				usage(B_FALSE);
2736			}
2737		}
2738	}
2739
2740	if (flags.replicate && fromname == NULL)
2741		flags.doall = B_TRUE;
2742
2743	err = zfs_send(zhp, fromname, toname, flags, STDOUT_FILENO, NULL, 0,
2744	    extraverbose ? &dbgnv : NULL);
2745
2746	if (extraverbose) {
2747		/*
2748		 * dump_nvlist prints to stdout, but that's been
2749		 * redirected to a file.  Make it print to stderr
2750		 * instead.
2751		 */
2752		(void) dup2(STDERR_FILENO, STDOUT_FILENO);
2753		dump_nvlist(dbgnv, 0);
2754		nvlist_free(dbgnv);
2755	}
2756	zfs_close(zhp);
2757
2758	return (err != 0);
2759}
2760
2761/*
2762 * zfs receive [-vnFu] [-d | -e] <fs@snap>
2763 *
2764 * Restore a backup stream from stdin.
2765 */
2766static int
2767zfs_do_receive(int argc, char **argv)
2768{
2769	int c, err;
2770	recvflags_t flags = { 0 };
2771
2772	/* check options */
2773	while ((c = getopt(argc, argv, ":denuvF")) != -1) {
2774		switch (c) {
2775		case 'd':
2776			flags.isprefix = B_TRUE;
2777			break;
2778		case 'e':
2779			flags.isprefix = B_TRUE;
2780			flags.istail = B_TRUE;
2781			break;
2782		case 'n':
2783			flags.dryrun = B_TRUE;
2784			break;
2785		case 'u':
2786			flags.nomount = B_TRUE;
2787			break;
2788		case 'v':
2789			flags.verbose = B_TRUE;
2790			break;
2791		case 'F':
2792			flags.force = B_TRUE;
2793			break;
2794		case ':':
2795			(void) fprintf(stderr, gettext("missing argument for "
2796			    "'%c' option\n"), optopt);
2797			usage(B_FALSE);
2798			break;
2799		case '?':
2800			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2801			    optopt);
2802			usage(B_FALSE);
2803		}
2804	}
2805
2806	argc -= optind;
2807	argv += optind;
2808
2809	/* check number of arguments */
2810	if (argc < 1) {
2811		(void) fprintf(stderr, gettext("missing snapshot argument\n"));
2812		usage(B_FALSE);
2813	}
2814	if (argc > 1) {
2815		(void) fprintf(stderr, gettext("too many arguments\n"));
2816		usage(B_FALSE);
2817	}
2818
2819	if (isatty(STDIN_FILENO)) {
2820		(void) fprintf(stderr,
2821		    gettext("Error: Backup stream can not be read "
2822		    "from a terminal.\n"
2823		    "You must redirect standard input.\n"));
2824		return (1);
2825	}
2826
2827	err = zfs_receive(g_zfs, argv[0], flags, STDIN_FILENO, NULL);
2828
2829	return (err != 0);
2830}
2831
2832static int
2833zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding)
2834{
2835	int errors = 0;
2836	int i;
2837	const char *tag;
2838	boolean_t recursive = B_FALSE;
2839	boolean_t temphold = B_FALSE;
2840	const char *opts = holding ? "rt" : "r";
2841	int c;
2842
2843	/* check options */
2844	while ((c = getopt(argc, argv, opts)) != -1) {
2845		switch (c) {
2846		case 'r':
2847			recursive = B_TRUE;
2848			break;
2849		case 't':
2850			temphold = B_TRUE;
2851			break;
2852		case '?':
2853			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
2854			    optopt);
2855			usage(B_FALSE);
2856		}
2857	}
2858
2859	argc -= optind;
2860	argv += optind;
2861
2862	/* check number of arguments */
2863	if (argc < 2)
2864		usage(B_FALSE);
2865
2866	tag = argv[0];
2867	--argc;
2868	++argv;
2869
2870	if (holding && tag[0] == '.') {
2871		/* tags starting with '.' are reserved for libzfs */
2872		(void) fprintf(stderr, gettext("tag may not start with '.'\n"));
2873		usage(B_FALSE);
2874	}
2875
2876	for (i = 0; i < argc; ++i) {
2877		zfs_handle_t *zhp;
2878		char parent[ZFS_MAXNAMELEN];
2879		const char *delim;
2880		char *path = argv[i];
2881
2882		delim = strchr(path, '@');
2883		if (delim == NULL) {
2884			(void) fprintf(stderr,
2885			    gettext("'%s' is not a snapshot\n"), path);
2886			++errors;
2887			continue;
2888		}
2889		(void) strncpy(parent, path, delim - path);
2890		parent[delim - path] = '\0';
2891
2892		zhp = zfs_open(g_zfs, parent,
2893		    ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
2894		if (zhp == NULL) {
2895			++errors;
2896			continue;
2897		}
2898		if (holding) {
2899			if (zfs_hold(zhp, delim+1, tag, recursive,
2900			    temphold, B_FALSE, -1, 0, 0) != 0)
2901				++errors;
2902		} else {
2903			if (zfs_release(zhp, delim+1, tag, recursive) != 0)
2904				++errors;
2905		}
2906		zfs_close(zhp);
2907	}
2908
2909	return (errors != 0);
2910}
2911
2912/*
2913 * zfs hold [-r] [-t] <tag> <snap> ...
2914 *
2915 *	-r	Recursively hold
2916 *	-t	Temporary hold (hidden option)
2917 *
2918 * Apply a user-hold with the given tag to the list of snapshots.
2919 */
2920static int
2921zfs_do_hold(int argc, char **argv)
2922{
2923	return (zfs_do_hold_rele_impl(argc, argv, B_TRUE));
2924}
2925
2926/*
2927 * zfs release [-r] <tag> <snap> ...
2928 *
2929 *	-r	Recursively release
2930 *
2931 * Release a user-hold with the given tag from the list of snapshots.
2932 */
2933static int
2934zfs_do_release(int argc, char **argv)
2935{
2936	return (zfs_do_hold_rele_impl(argc, argv, B_FALSE));
2937}
2938
2939#define	CHECK_SPINNER 30
2940#define	SPINNER_TIME 3		/* seconds */
2941#define	MOUNT_TIME 5		/* seconds */
2942
2943static int
2944get_one_dataset(zfs_handle_t *zhp, void *data)
2945{
2946	static char *spin[] = { "-", "\\", "|", "/" };
2947	static int spinval = 0;
2948	static int spincheck = 0;
2949	static time_t last_spin_time = (time_t)0;
2950	get_all_cb_t *cbp = data;
2951	zfs_type_t type = zfs_get_type(zhp);
2952
2953	if (cbp->cb_verbose) {
2954		if (--spincheck < 0) {
2955			time_t now = time(NULL);
2956			if (last_spin_time + SPINNER_TIME < now) {
2957				update_progress(spin[spinval++ % 4]);
2958				last_spin_time = now;
2959			}
2960			spincheck = CHECK_SPINNER;
2961		}
2962	}
2963
2964	/*
2965	 * Interate over any nested datasets.
2966	 */
2967	if (zfs_iter_filesystems(zhp, get_one_dataset, data) != 0) {
2968		zfs_close(zhp);
2969		return (1);
2970	}
2971
2972	/*
2973	 * Skip any datasets whose type does not match.
2974	 */
2975	if ((type & ZFS_TYPE_FILESYSTEM) == 0) {
2976		zfs_close(zhp);
2977		return (0);
2978	}
2979	libzfs_add_handle(cbp, zhp);
2980	assert(cbp->cb_used <= cbp->cb_alloc);
2981
2982	return (0);
2983}
2984
2985static void
2986get_all_datasets(zfs_handle_t ***dslist, size_t *count, boolean_t verbose)
2987{
2988	get_all_cb_t cb = { 0 };
2989	cb.cb_verbose = verbose;
2990	cb.cb_getone = get_one_dataset;
2991
2992	if (verbose)
2993		set_progress_header(gettext("Reading ZFS config"));
2994	(void) zfs_iter_root(g_zfs, get_one_dataset, &cb);
2995
2996	*dslist = cb.cb_handles;
2997	*count = cb.cb_used;
2998
2999	if (verbose)
3000		finish_progress(gettext("done."));
3001}
3002
3003/*
3004 * Generic callback for sharing or mounting filesystems.  Because the code is so
3005 * similar, we have a common function with an extra parameter to determine which
3006 * mode we are using.
3007 */
3008#define	OP_SHARE	0x1
3009#define	OP_MOUNT	0x2
3010
3011/*
3012 * Share or mount a dataset.
3013 */
3014static int
3015share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
3016    boolean_t explicit, const char *options)
3017{
3018	char mountpoint[ZFS_MAXPROPLEN];
3019	char shareopts[ZFS_MAXPROPLEN];
3020	char smbshareopts[ZFS_MAXPROPLEN];
3021	const char *cmdname = op == OP_SHARE ? "share" : "mount";
3022	struct mnttab mnt;
3023	uint64_t zoned, canmount;
3024	boolean_t shared_nfs, shared_smb;
3025
3026	assert(zfs_get_type(zhp) & ZFS_TYPE_FILESYSTEM);
3027
3028	/*
3029	 * Check to make sure we can mount/share this dataset.  If we
3030	 * are in the global zone and the filesystem is exported to a
3031	 * local zone, or if we are in a local zone and the
3032	 * filesystem is not exported, then it is an error.
3033	 */
3034	zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED);
3035
3036	if (zoned && getzoneid() == GLOBAL_ZONEID) {
3037		if (!explicit)
3038			return (0);
3039
3040		(void) fprintf(stderr, gettext("cannot %s '%s': "
3041		    "dataset is exported to a local zone\n"), cmdname,
3042		    zfs_get_name(zhp));
3043		return (1);
3044
3045	} else if (!zoned && getzoneid() != GLOBAL_ZONEID) {
3046		if (!explicit)
3047			return (0);
3048
3049		(void) fprintf(stderr, gettext("cannot %s '%s': "
3050		    "permission denied\n"), cmdname,
3051		    zfs_get_name(zhp));
3052		return (1);
3053	}
3054
3055	/*
3056	 * Ignore any filesystems which don't apply to us. This
3057	 * includes those with a legacy mountpoint, or those with
3058	 * legacy share options.
3059	 */
3060	verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
3061	    sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0);
3062	verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts,
3063	    sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0);
3064	verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB, smbshareopts,
3065	    sizeof (smbshareopts), NULL, NULL, 0, B_FALSE) == 0);
3066
3067	if (op == OP_SHARE && strcmp(shareopts, "off") == 0 &&
3068	    strcmp(smbshareopts, "off") == 0) {
3069		if (!explicit)
3070			return (0);
3071
3072		(void) fprintf(stderr, gettext("cannot share '%s': "
3073		    "legacy share\n"), zfs_get_name(zhp));
3074		(void) fprintf(stderr, gettext("use share(1M) to "
3075		    "share this filesystem, or set "
3076		    "sharenfs property on\n"));
3077		return (1);
3078	}
3079
3080	/*
3081	 * We cannot share or mount legacy filesystems. If the
3082	 * shareopts is non-legacy but the mountpoint is legacy, we
3083	 * treat it as a legacy share.
3084	 */
3085	if (strcmp(mountpoint, "legacy") == 0) {
3086		if (!explicit)
3087			return (0);
3088
3089		(void) fprintf(stderr, gettext("cannot %s '%s': "
3090		    "legacy mountpoint\n"), cmdname, zfs_get_name(zhp));
3091		(void) fprintf(stderr, gettext("use %s(1M) to "
3092		    "%s this filesystem\n"), cmdname, cmdname);
3093		return (1);
3094	}
3095
3096	if (strcmp(mountpoint, "none") == 0) {
3097		if (!explicit)
3098			return (0);
3099
3100		(void) fprintf(stderr, gettext("cannot %s '%s': no "
3101		    "mountpoint set\n"), cmdname, zfs_get_name(zhp));
3102		return (1);
3103	}
3104
3105	/*
3106	 * canmount	explicit	outcome
3107	 * on		no		pass through
3108	 * on		yes		pass through
3109	 * off		no		return 0
3110	 * off		yes		display error, return 1
3111	 * noauto	no		return 0
3112	 * noauto	yes		pass through
3113	 */
3114	canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
3115	if (canmount == ZFS_CANMOUNT_OFF) {
3116		if (!explicit)
3117			return (0);
3118
3119		(void) fprintf(stderr, gettext("cannot %s '%s': "
3120		    "'canmount' property is set to 'off'\n"), cmdname,
3121		    zfs_get_name(zhp));
3122		return (1);
3123	} else if (canmount == ZFS_CANMOUNT_NOAUTO && !explicit) {
3124		return (0);
3125	}
3126
3127	/*
3128	 * At this point, we have verified that the mountpoint and/or
3129	 * shareopts are appropriate for auto management. If the
3130	 * filesystem is already mounted or shared, return (failing
3131	 * for explicit requests); otherwise mount or share the
3132	 * filesystem.
3133	 */
3134	switch (op) {
3135	case OP_SHARE:
3136
3137		shared_nfs = zfs_is_shared_nfs(zhp, NULL);
3138		shared_smb = zfs_is_shared_smb(zhp, NULL);
3139
3140		if (shared_nfs && shared_smb ||
3141		    (shared_nfs && strcmp(shareopts, "on") == 0 &&
3142		    strcmp(smbshareopts, "off") == 0) ||
3143		    (shared_smb && strcmp(smbshareopts, "on") == 0 &&
3144		    strcmp(shareopts, "off") == 0)) {
3145			if (!explicit)
3146				return (0);
3147
3148			(void) fprintf(stderr, gettext("cannot share "
3149			    "'%s': filesystem already shared\n"),
3150			    zfs_get_name(zhp));
3151			return (1);
3152		}
3153
3154		if (!zfs_is_mounted(zhp, NULL) &&
3155		    zfs_mount(zhp, NULL, 0) != 0)
3156			return (1);
3157
3158		if (protocol == NULL) {
3159			if (zfs_shareall(zhp) != 0)
3160				return (1);
3161		} else if (strcmp(protocol, "nfs") == 0) {
3162			if (zfs_share_nfs(zhp))
3163				return (1);
3164		} else if (strcmp(protocol, "smb") == 0) {
3165			if (zfs_share_smb(zhp))
3166				return (1);
3167		} else {
3168			(void) fprintf(stderr, gettext("cannot share "
3169			    "'%s': invalid share type '%s' "
3170			    "specified\n"),
3171			    zfs_get_name(zhp), protocol);
3172			return (1);
3173		}
3174
3175		break;
3176
3177	case OP_MOUNT:
3178		if (options == NULL)
3179			mnt.mnt_mntopts = "";
3180		else
3181			mnt.mnt_mntopts = (char *)options;
3182
3183		if (!hasmntopt(&mnt, MNTOPT_REMOUNT) &&
3184		    zfs_is_mounted(zhp, NULL)) {
3185			if (!explicit)
3186				return (0);
3187
3188			(void) fprintf(stderr, gettext("cannot mount "
3189			    "'%s': filesystem already mounted\n"),
3190			    zfs_get_name(zhp));
3191			return (1);
3192		}
3193
3194		if (zfs_mount(zhp, options, flags) != 0)
3195			return (1);
3196		break;
3197	}
3198
3199	return (0);
3200}
3201
3202/*
3203 * Reports progress in the form "(current/total)".  Not thread-safe.
3204 */
3205static void
3206report_mount_progress(int current, int total)
3207{
3208	static time_t last_progress_time = 0;
3209	time_t now = time(NULL);
3210	char info[32];
3211
3212	/* report 1..n instead of 0..n-1 */
3213	++current;
3214
3215	/* display header if we're here for the first time */
3216	if (current == 1) {
3217		set_progress_header(gettext("Mounting ZFS filesystems"));
3218	} else if (current != total && last_progress_time + MOUNT_TIME >= now) {
3219		/* too soon to report again */
3220		return;
3221	}
3222
3223	last_progress_time = now;
3224
3225	(void) sprintf(info, "(%d/%d)", current, total);
3226
3227	if (current == total)
3228		finish_progress(info);
3229	else
3230		update_progress(info);
3231}
3232
3233static void
3234append_options(char *mntopts, char *newopts)
3235{
3236	int len = strlen(mntopts);
3237
3238	/* original length plus new string to append plus 1 for the comma */
3239	if (len + 1 + strlen(newopts) >= MNT_LINE_MAX) {
3240		(void) fprintf(stderr, gettext("the opts argument for "
3241		    "'%c' option is too long (more than %d chars)\n"),
3242		    "-o", MNT_LINE_MAX);
3243		usage(B_FALSE);
3244	}
3245
3246	if (*mntopts)
3247		mntopts[len++] = ',';
3248
3249	(void) strcpy(&mntopts[len], newopts);
3250}
3251
3252static int
3253share_mount(int op, int argc, char **argv)
3254{
3255	int do_all = 0;
3256	boolean_t verbose = B_FALSE;
3257	int c, ret = 0;
3258	char *options = NULL;
3259	int flags = 0;
3260
3261	/* check options */
3262	while ((c = getopt(argc, argv, op == OP_MOUNT ? ":avo:O" : "a"))
3263	    != -1) {
3264		switch (c) {
3265		case 'a':
3266			do_all = 1;
3267			break;
3268		case 'v':
3269			verbose = B_TRUE;
3270			break;
3271		case 'o':
3272			if (*optarg == '\0') {
3273				(void) fprintf(stderr, gettext("empty mount "
3274				    "options (-o) specified\n"));
3275				usage(B_FALSE);
3276			}
3277
3278			if (options == NULL)
3279				options = safe_malloc(MNT_LINE_MAX + 1);
3280
3281			/* option validation is done later */
3282			append_options(options, optarg);
3283			break;
3284
3285		case 'O':
3286			flags |= MS_OVERLAY;
3287			break;
3288		case ':':
3289			(void) fprintf(stderr, gettext("missing argument for "
3290			    "'%c' option\n"), optopt);
3291			usage(B_FALSE);
3292			break;
3293		case '?':
3294			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3295			    optopt);
3296			usage(B_FALSE);
3297		}
3298	}
3299
3300	argc -= optind;
3301	argv += optind;
3302
3303	/* check number of arguments */
3304	if (do_all) {
3305		zfs_handle_t **dslist = NULL;
3306		size_t i, count = 0;
3307		char *protocol = NULL;
3308
3309		if (op == OP_SHARE && argc > 0) {
3310			if (strcmp(argv[0], "nfs") != 0 &&
3311			    strcmp(argv[0], "smb") != 0) {
3312				(void) fprintf(stderr, gettext("share type "
3313				    "must be 'nfs' or 'smb'\n"));
3314				usage(B_FALSE);
3315			}
3316			protocol = argv[0];
3317			argc--;
3318			argv++;
3319		}
3320
3321		if (argc != 0) {
3322			(void) fprintf(stderr, gettext("too many arguments\n"));
3323			usage(B_FALSE);
3324		}
3325
3326		start_progress_timer();
3327		get_all_datasets(&dslist, &count, verbose);
3328
3329		if (count == 0)
3330			return (0);
3331
3332		qsort(dslist, count, sizeof (void *), libzfs_dataset_cmp);
3333
3334		for (i = 0; i < count; i++) {
3335			if (verbose)
3336				report_mount_progress(i, count);
3337
3338			if (share_mount_one(dslist[i], op, flags, protocol,
3339			    B_FALSE, options) != 0)
3340				ret = 1;
3341			zfs_close(dslist[i]);
3342		}
3343
3344		free(dslist);
3345	} else if (argc == 0) {
3346		struct mnttab entry;
3347
3348		if ((op == OP_SHARE) || (options != NULL)) {
3349			(void) fprintf(stderr, gettext("missing filesystem "
3350			    "argument (specify -a for all)\n"));
3351			usage(B_FALSE);
3352		}
3353
3354		/*
3355		 * When mount is given no arguments, go through /etc/mnttab and
3356		 * display any active ZFS mounts.  We hide any snapshots, since
3357		 * they are controlled automatically.
3358		 */
3359		rewind(mnttab_file);
3360		while (getmntent(mnttab_file, &entry) == 0) {
3361			if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0 ||
3362			    strchr(entry.mnt_special, '@') != NULL)
3363				continue;
3364
3365			(void) printf("%-30s  %s\n", entry.mnt_special,
3366			    entry.mnt_mountp);
3367		}
3368
3369	} else {
3370		zfs_handle_t *zhp;
3371
3372		if (argc > 1) {
3373			(void) fprintf(stderr,
3374			    gettext("too many arguments\n"));
3375			usage(B_FALSE);
3376		}
3377
3378		if ((zhp = zfs_open(g_zfs, argv[0],
3379		    ZFS_TYPE_FILESYSTEM)) == NULL) {
3380			ret = 1;
3381		} else {
3382			ret = share_mount_one(zhp, op, flags, NULL, B_TRUE,
3383			    options);
3384			zfs_close(zhp);
3385		}
3386	}
3387
3388	return (ret);
3389}
3390
3391/*
3392 * zfs mount -a [nfs]
3393 * zfs mount filesystem
3394 *
3395 * Mount all filesystems, or mount the given filesystem.
3396 */
3397static int
3398zfs_do_mount(int argc, char **argv)
3399{
3400	return (share_mount(OP_MOUNT, argc, argv));
3401}
3402
3403/*
3404 * zfs share -a [nfs | smb]
3405 * zfs share filesystem
3406 *
3407 * Share all filesystems, or share the given filesystem.
3408 */
3409static int
3410zfs_do_share(int argc, char **argv)
3411{
3412	return (share_mount(OP_SHARE, argc, argv));
3413}
3414
3415typedef struct unshare_unmount_node {
3416	zfs_handle_t	*un_zhp;
3417	char		*un_mountp;
3418	uu_avl_node_t	un_avlnode;
3419} unshare_unmount_node_t;
3420
3421/* ARGSUSED */
3422static int
3423unshare_unmount_compare(const void *larg, const void *rarg, void *unused)
3424{
3425	const unshare_unmount_node_t *l = larg;
3426	const unshare_unmount_node_t *r = rarg;
3427
3428	return (strcmp(l->un_mountp, r->un_mountp));
3429}
3430
3431/*
3432 * Convenience routine used by zfs_do_umount() and manual_unmount().  Given an
3433 * absolute path, find the entry /etc/mnttab, verify that its a ZFS filesystem,
3434 * and unmount it appropriately.
3435 */
3436static int
3437unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
3438{
3439	zfs_handle_t *zhp;
3440	int ret;
3441	struct stat64 statbuf;
3442	struct extmnttab entry;
3443	const char *cmdname = (op == OP_SHARE) ? "unshare" : "unmount";
3444	ino_t path_inode;
3445
3446	/*
3447	 * Search for the path in /etc/mnttab.  Rather than looking for the
3448	 * specific path, which can be fooled by non-standard paths (i.e. ".."
3449	 * or "//"), we stat() the path and search for the corresponding
3450	 * (major,minor) device pair.
3451	 */
3452	if (stat64(path, &statbuf) != 0) {
3453		(void) fprintf(stderr, gettext("cannot %s '%s': %s\n"),
3454		    cmdname, path, strerror(errno));
3455		return (1);
3456	}
3457	path_inode = statbuf.st_ino;
3458
3459	/*
3460	 * Search for the given (major,minor) pair in the mount table.
3461	 */
3462	rewind(mnttab_file);
3463	while ((ret = getextmntent(mnttab_file, &entry, 0)) == 0) {
3464		if (entry.mnt_major == major(statbuf.st_dev) &&
3465		    entry.mnt_minor == minor(statbuf.st_dev))
3466			break;
3467	}
3468	if (ret != 0) {
3469		if (op == OP_SHARE) {
3470			(void) fprintf(stderr, gettext("cannot %s '%s': not "
3471			    "currently mounted\n"), cmdname, path);
3472			return (1);
3473		}
3474		(void) fprintf(stderr, gettext("warning: %s not in mnttab\n"),
3475		    path);
3476		if ((ret = umount2(path, flags)) != 0)
3477			(void) fprintf(stderr, gettext("%s: %s\n"), path,
3478			    strerror(errno));
3479		return (ret != 0);
3480	}
3481
3482	if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) {
3483		(void) fprintf(stderr, gettext("cannot %s '%s': not a ZFS "
3484		    "filesystem\n"), cmdname, path);
3485		return (1);
3486	}
3487
3488	if ((zhp = zfs_open(g_zfs, entry.mnt_special,
3489	    ZFS_TYPE_FILESYSTEM)) == NULL)
3490		return (1);
3491
3492	ret = 1;
3493	if (stat64(entry.mnt_mountp, &statbuf) != 0) {
3494		(void) fprintf(stderr, gettext("cannot %s '%s': %s\n"),
3495		    cmdname, path, strerror(errno));
3496		goto out;
3497	} else if (statbuf.st_ino != path_inode) {
3498		(void) fprintf(stderr, gettext("cannot "
3499		    "%s '%s': not a mountpoint\n"), cmdname, path);
3500		goto out;
3501	}
3502
3503	if (op == OP_SHARE) {
3504		char nfs_mnt_prop[ZFS_MAXPROPLEN];
3505		char smbshare_prop[ZFS_MAXPROPLEN];
3506
3507		verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, nfs_mnt_prop,
3508		    sizeof (nfs_mnt_prop), NULL, NULL, 0, B_FALSE) == 0);
3509		verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB, smbshare_prop,
3510		    sizeof (smbshare_prop), NULL, NULL, 0, B_FALSE) == 0);
3511
3512		if (strcmp(nfs_mnt_prop, "off") == 0 &&
3513		    strcmp(smbshare_prop, "off") == 0) {
3514			(void) fprintf(stderr, gettext("cannot unshare "
3515			    "'%s': legacy share\n"), path);
3516			(void) fprintf(stderr, gettext("use "
3517			    "unshare(1M) to unshare this filesystem\n"));
3518		} else if (!zfs_is_shared(zhp)) {
3519			(void) fprintf(stderr, gettext("cannot unshare '%s': "
3520			    "not currently shared\n"), path);
3521		} else {
3522			ret = zfs_unshareall_bypath(zhp, path);
3523		}
3524	} else {
3525		char mtpt_prop[ZFS_MAXPROPLEN];
3526
3527		verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mtpt_prop,
3528		    sizeof (mtpt_prop), NULL, NULL, 0, B_FALSE) == 0);
3529
3530		if (is_manual) {
3531			ret = zfs_unmount(zhp, NULL, flags);
3532		} else if (strcmp(mtpt_prop, "legacy") == 0) {
3533			(void) fprintf(stderr, gettext("cannot unmount "
3534			    "'%s': legacy mountpoint\n"),
3535			    zfs_get_name(zhp));
3536			(void) fprintf(stderr, gettext("use umount(1M) "
3537			    "to unmount this filesystem\n"));
3538		} else {
3539			ret = zfs_unmountall(zhp, flags);
3540		}
3541	}
3542
3543out:
3544	zfs_close(zhp);
3545
3546	return (ret != 0);
3547}
3548
3549/*
3550 * Generic callback for unsharing or unmounting a filesystem.
3551 */
3552static int
3553unshare_unmount(int op, int argc, char **argv)
3554{
3555	int do_all = 0;
3556	int flags = 0;
3557	int ret = 0;
3558	int c;
3559	zfs_handle_t *zhp;
3560	char nfs_mnt_prop[ZFS_MAXPROPLEN];
3561	char sharesmb[ZFS_MAXPROPLEN];
3562
3563	/* check options */
3564	while ((c = getopt(argc, argv, op == OP_SHARE ? "a" : "af")) != -1) {
3565		switch (c) {
3566		case 'a':
3567			do_all = 1;
3568			break;
3569		case 'f':
3570			flags = MS_FORCE;
3571			break;
3572		case '?':
3573			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3574			    optopt);
3575			usage(B_FALSE);
3576		}
3577	}
3578
3579	argc -= optind;
3580	argv += optind;
3581
3582	if (do_all) {
3583		/*
3584		 * We could make use of zfs_for_each() to walk all datasets in
3585		 * the system, but this would be very inefficient, especially
3586		 * since we would have to linearly search /etc/mnttab for each
3587		 * one.  Instead, do one pass through /etc/mnttab looking for
3588		 * zfs entries and call zfs_unmount() for each one.
3589		 *
3590		 * Things get a little tricky if the administrator has created
3591		 * mountpoints beneath other ZFS filesystems.  In this case, we
3592		 * have to unmount the deepest filesystems first.  To accomplish
3593		 * this, we place all the mountpoints in an AVL tree sorted by
3594		 * the special type (dataset name), and walk the result in
3595		 * reverse to make sure to get any snapshots first.
3596		 */
3597		struct mnttab entry;
3598		uu_avl_pool_t *pool;
3599		uu_avl_t *tree;
3600		unshare_unmount_node_t *node;
3601		uu_avl_index_t idx;
3602		uu_avl_walk_t *walk;
3603
3604		if (argc != 0) {
3605			(void) fprintf(stderr, gettext("too many arguments\n"));
3606			usage(B_FALSE);
3607		}
3608
3609		if (((pool = uu_avl_pool_create("unmount_pool",
3610		    sizeof (unshare_unmount_node_t),
3611		    offsetof(unshare_unmount_node_t, un_avlnode),
3612		    unshare_unmount_compare, UU_DEFAULT)) == NULL) ||
3613		    ((tree = uu_avl_create(pool, NULL, UU_DEFAULT)) == NULL))
3614			nomem();
3615
3616		rewind(mnttab_file);
3617		while (getmntent(mnttab_file, &entry) == 0) {
3618
3619			/* ignore non-ZFS entries */
3620			if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
3621				continue;
3622
3623			/* ignore snapshots */
3624			if (strchr(entry.mnt_special, '@') != NULL)
3625				continue;
3626
3627			if ((zhp = zfs_open(g_zfs, entry.mnt_special,
3628			    ZFS_TYPE_FILESYSTEM)) == NULL) {
3629				ret = 1;
3630				continue;
3631			}
3632
3633			switch (op) {
3634			case OP_SHARE:
3635				verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS,
3636				    nfs_mnt_prop,
3637				    sizeof (nfs_mnt_prop),
3638				    NULL, NULL, 0, B_FALSE) == 0);
3639				if (strcmp(nfs_mnt_prop, "off") != 0)
3640					break;
3641				verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB,
3642				    nfs_mnt_prop,
3643				    sizeof (nfs_mnt_prop),
3644				    NULL, NULL, 0, B_FALSE) == 0);
3645				if (strcmp(nfs_mnt_prop, "off") == 0)
3646					continue;
3647				break;
3648			case OP_MOUNT:
3649				/* Ignore legacy mounts */
3650				verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT,
3651				    nfs_mnt_prop,
3652				    sizeof (nfs_mnt_prop),
3653				    NULL, NULL, 0, B_FALSE) == 0);
3654				if (strcmp(nfs_mnt_prop, "legacy") == 0)
3655					continue;
3656				/* Ignore canmount=noauto mounts */
3657				if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) ==
3658				    ZFS_CANMOUNT_NOAUTO)
3659					continue;
3660			default:
3661				break;
3662			}
3663
3664			node = safe_malloc(sizeof (unshare_unmount_node_t));
3665			node->un_zhp = zhp;
3666			node->un_mountp = safe_strdup(entry.mnt_mountp);
3667
3668			uu_avl_node_init(node, &node->un_avlnode, pool);
3669
3670			if (uu_avl_find(tree, node, NULL, &idx) == NULL) {
3671				uu_avl_insert(tree, node, idx);
3672			} else {
3673				zfs_close(node->un_zhp);
3674				free(node->un_mountp);
3675				free(node);
3676			}
3677		}
3678
3679		/*
3680		 * Walk the AVL tree in reverse, unmounting each filesystem and
3681		 * removing it from the AVL tree in the process.
3682		 */
3683		if ((walk = uu_avl_walk_start(tree,
3684		    UU_WALK_REVERSE | UU_WALK_ROBUST)) == NULL)
3685			nomem();
3686
3687		while ((node = uu_avl_walk_next(walk)) != NULL) {
3688			uu_avl_remove(tree, node);
3689
3690			switch (op) {
3691			case OP_SHARE:
3692				if (zfs_unshareall_bypath(node->un_zhp,
3693				    node->un_mountp) != 0)
3694					ret = 1;
3695				break;
3696
3697			case OP_MOUNT:
3698				if (zfs_unmount(node->un_zhp,
3699				    node->un_mountp, flags) != 0)
3700					ret = 1;
3701				break;
3702			}
3703
3704			zfs_close(node->un_zhp);
3705			free(node->un_mountp);
3706			free(node);
3707		}
3708
3709		uu_avl_walk_end(walk);
3710		uu_avl_destroy(tree);
3711		uu_avl_pool_destroy(pool);
3712
3713	} else {
3714		if (argc != 1) {
3715			if (argc == 0)
3716				(void) fprintf(stderr,
3717				    gettext("missing filesystem argument\n"));
3718			else
3719				(void) fprintf(stderr,
3720				    gettext("too many arguments\n"));
3721			usage(B_FALSE);
3722		}
3723
3724		/*
3725		 * We have an argument, but it may be a full path or a ZFS
3726		 * filesystem.  Pass full paths off to unmount_path() (shared by
3727		 * manual_unmount), otherwise open the filesystem and pass to
3728		 * zfs_unmount().
3729		 */
3730		if (argv[0][0] == '/')
3731			return (unshare_unmount_path(op, argv[0],
3732			    flags, B_FALSE));
3733
3734		if ((zhp = zfs_open(g_zfs, argv[0],
3735		    ZFS_TYPE_FILESYSTEM)) == NULL)
3736			return (1);
3737
3738		verify(zfs_prop_get(zhp, op == OP_SHARE ?
3739		    ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT,
3740		    nfs_mnt_prop, sizeof (nfs_mnt_prop), NULL,
3741		    NULL, 0, B_FALSE) == 0);
3742
3743		switch (op) {
3744		case OP_SHARE:
3745			verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS,
3746			    nfs_mnt_prop,
3747			    sizeof (nfs_mnt_prop),
3748			    NULL, NULL, 0, B_FALSE) == 0);
3749			verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB,
3750			    sharesmb, sizeof (sharesmb), NULL, NULL,
3751			    0, B_FALSE) == 0);
3752
3753			if (strcmp(nfs_mnt_prop, "off") == 0 &&
3754			    strcmp(sharesmb, "off") == 0) {
3755				(void) fprintf(stderr, gettext("cannot "
3756				    "unshare '%s': legacy share\n"),
3757				    zfs_get_name(zhp));
3758				(void) fprintf(stderr, gettext("use "
3759				    "unshare(1M) to unshare this "
3760				    "filesystem\n"));
3761				ret = 1;
3762			} else if (!zfs_is_shared(zhp)) {
3763				(void) fprintf(stderr, gettext("cannot "
3764				    "unshare '%s': not currently "
3765				    "shared\n"), zfs_get_name(zhp));
3766				ret = 1;
3767			} else if (zfs_unshareall(zhp) != 0) {
3768				ret = 1;
3769			}
3770			break;
3771
3772		case OP_MOUNT:
3773			if (strcmp(nfs_mnt_prop, "legacy") == 0) {
3774				(void) fprintf(stderr, gettext("cannot "
3775				    "unmount '%s': legacy "
3776				    "mountpoint\n"), zfs_get_name(zhp));
3777				(void) fprintf(stderr, gettext("use "
3778				    "umount(1M) to unmount this "
3779				    "filesystem\n"));
3780				ret = 1;
3781			} else if (!zfs_is_mounted(zhp, NULL)) {
3782				(void) fprintf(stderr, gettext("cannot "
3783				    "unmount '%s': not currently "
3784				    "mounted\n"),
3785				    zfs_get_name(zhp));
3786				ret = 1;
3787			} else if (zfs_unmountall(zhp, flags) != 0) {
3788				ret = 1;
3789			}
3790			break;
3791		}
3792
3793		zfs_close(zhp);
3794	}
3795
3796	return (ret);
3797}
3798
3799/*
3800 * zfs unmount -a
3801 * zfs unmount filesystem
3802 *
3803 * Unmount all filesystems, or a specific ZFS filesystem.
3804 */
3805static int
3806zfs_do_unmount(int argc, char **argv)
3807{
3808	return (unshare_unmount(OP_MOUNT, argc, argv));
3809}
3810
3811/*
3812 * zfs unshare -a
3813 * zfs unshare filesystem
3814 *
3815 * Unshare all filesystems, or a specific ZFS filesystem.
3816 */
3817static int
3818zfs_do_unshare(int argc, char **argv)
3819{
3820	return (unshare_unmount(OP_SHARE, argc, argv));
3821}
3822
3823/* ARGSUSED */
3824static int
3825zfs_do_python(int argc, char **argv)
3826{
3827	(void) execv(pypath, argv-1);
3828	(void) printf("internal error: %s not found\n", pypath);
3829	return (-1);
3830}
3831
3832/*
3833 * Called when invoked as /etc/fs/zfs/mount.  Do the mount if the mountpoint is
3834 * 'legacy'.  Otherwise, complain that use should be using 'zfs mount'.
3835 */
3836static int
3837manual_mount(int argc, char **argv)
3838{
3839	zfs_handle_t *zhp;
3840	char mountpoint[ZFS_MAXPROPLEN];
3841	char mntopts[MNT_LINE_MAX] = { '\0' };
3842	int ret;
3843	int c;
3844	int flags = 0;
3845	char *dataset, *path;
3846
3847	/* check options */
3848	while ((c = getopt(argc, argv, ":mo:O")) != -1) {
3849		switch (c) {
3850		case 'o':
3851			(void) strlcpy(mntopts, optarg, sizeof (mntopts));
3852			break;
3853		case 'O':
3854			flags |= MS_OVERLAY;
3855			break;
3856		case 'm':
3857			flags |= MS_NOMNTTAB;
3858			break;
3859		case ':':
3860			(void) fprintf(stderr, gettext("missing argument for "
3861			    "'%c' option\n"), optopt);
3862			usage(B_FALSE);
3863			break;
3864		case '?':
3865			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3866			    optopt);
3867			(void) fprintf(stderr, gettext("usage: mount [-o opts] "
3868			    "<path>\n"));
3869			return (2);
3870		}
3871	}
3872
3873	argc -= optind;
3874	argv += optind;
3875
3876	/* check that we only have two arguments */
3877	if (argc != 2) {
3878		if (argc == 0)
3879			(void) fprintf(stderr, gettext("missing dataset "
3880			    "argument\n"));
3881		else if (argc == 1)
3882			(void) fprintf(stderr,
3883			    gettext("missing mountpoint argument\n"));
3884		else
3885			(void) fprintf(stderr, gettext("too many arguments\n"));
3886		(void) fprintf(stderr, "usage: mount <dataset> <mountpoint>\n");
3887		return (2);
3888	}
3889
3890	dataset = argv[0];
3891	path = argv[1];
3892
3893	/* try to open the dataset */
3894	if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_FILESYSTEM)) == NULL)
3895		return (1);
3896
3897	(void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
3898	    sizeof (mountpoint), NULL, NULL, 0, B_FALSE);
3899
3900	/* check for legacy mountpoint and complain appropriately */
3901	ret = 0;
3902	if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) {
3903		if (mount(dataset, path, MS_OPTIONSTR | flags, MNTTYPE_ZFS,
3904		    NULL, 0, mntopts, sizeof (mntopts)) != 0) {
3905			(void) fprintf(stderr, gettext("mount failed: %s\n"),
3906			    strerror(errno));
3907			ret = 1;
3908		}
3909	} else {
3910		(void) fprintf(stderr, gettext("filesystem '%s' cannot be "
3911		    "mounted using 'mount -F zfs'\n"), dataset);
3912		(void) fprintf(stderr, gettext("Use 'zfs set mountpoint=%s' "
3913		    "instead.\n"), path);
3914		(void) fprintf(stderr, gettext("If you must use 'mount -F zfs' "
3915		    "or /etc/vfstab, use 'zfs set mountpoint=legacy'.\n"));
3916		(void) fprintf(stderr, gettext("See zfs(1M) for more "
3917		    "information.\n"));
3918		ret = 1;
3919	}
3920
3921	return (ret);
3922}
3923
3924/*
3925 * Called when invoked as /etc/fs/zfs/umount.  Unlike a manual mount, we allow
3926 * unmounts of non-legacy filesystems, as this is the dominant administrative
3927 * interface.
3928 */
3929static int
3930manual_unmount(int argc, char **argv)
3931{
3932	int flags = 0;
3933	int c;
3934
3935	/* check options */
3936	while ((c = getopt(argc, argv, "f")) != -1) {
3937		switch (c) {
3938		case 'f':
3939			flags = MS_FORCE;
3940			break;
3941		case '?':
3942			(void) fprintf(stderr, gettext("invalid option '%c'\n"),
3943			    optopt);
3944			(void) fprintf(stderr, gettext("usage: unmount [-f] "
3945			    "<path>\n"));
3946			return (2);
3947		}
3948	}
3949
3950	argc -= optind;
3951	argv += optind;
3952
3953	/* check arguments */
3954	if (argc != 1) {
3955		if (argc == 0)
3956			(void) fprintf(stderr, gettext("missing path "
3957			    "argument\n"));
3958		else
3959			(void) fprintf(stderr, gettext("too many arguments\n"));
3960		(void) fprintf(stderr, gettext("usage: unmount [-f] <path>\n"));
3961		return (2);
3962	}
3963
3964	return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE));
3965}
3966
3967static int
3968find_command_idx(char *command, int *idx)
3969{
3970	int i;
3971
3972	for (i = 0; i < NCOMMAND; i++) {
3973		if (command_table[i].name == NULL)
3974			continue;
3975
3976		if (strcmp(command, command_table[i].name) == 0) {
3977			*idx = i;
3978			return (0);
3979		}
3980	}
3981	return (1);
3982}
3983
3984static int
3985zfs_do_diff(int argc, char **argv)
3986{
3987	zfs_handle_t *zhp;
3988	int flags = 0;
3989	char *tosnap = NULL;
3990	char *fromsnap = NULL;
3991	char *atp, *copy;
3992	int err;
3993	int c;
3994
3995	while ((c = getopt(argc, argv, "FHt")) != -1) {
3996		switch (c) {
3997		case 'F':
3998			flags |= ZFS_DIFF_CLASSIFY;
3999			break;
4000		case 'H':
4001			flags |= ZFS_DIFF_PARSEABLE;
4002			break;
4003		case 't':
4004			flags |= ZFS_DIFF_TIMESTAMP;
4005			break;
4006		default:
4007			(void) fprintf(stderr,
4008			    gettext("invalid option '%c'\n"), optopt);
4009			usage(B_FALSE);
4010		}
4011	}
4012
4013	argc -= optind;
4014	argv += optind;
4015
4016	if (argc < 1) {
4017		(void) fprintf(stderr,
4018		gettext("must provide at least one snapshot name\n"));
4019		usage(B_FALSE);
4020	}
4021
4022	if (argc > 2) {
4023		(void) fprintf(stderr, gettext("too many arguments\n"));
4024		usage(B_FALSE);
4025	}
4026
4027	fromsnap = argv[0];
4028	tosnap = (argc == 2) ? argv[1] : NULL;
4029
4030	copy = NULL;
4031	if (*fromsnap != '@')
4032		copy = strdup(fromsnap);
4033	else if (tosnap)
4034		copy = strdup(tosnap);
4035	if (copy == NULL)
4036		usage(B_FALSE);
4037
4038	if (atp = strchr(copy, '@'))
4039		*atp = '\0';
4040
4041	if ((zhp = zfs_open(g_zfs, copy, ZFS_TYPE_FILESYSTEM)) == NULL)
4042		return (1);
4043
4044	free(copy);
4045
4046	/*
4047	 * Ignore SIGPIPE so that the library can give us
4048	 * information on any failure
4049	 */
4050	(void) sigignore(SIGPIPE);
4051
4052	err = zfs_show_diffs(zhp, STDOUT_FILENO, fromsnap, tosnap, flags);
4053
4054	zfs_close(zhp);
4055
4056	return (err != 0);
4057}
4058
4059int
4060main(int argc, char **argv)
4061{
4062	int ret;
4063	int i;
4064	char *progname;
4065	char *cmdname;
4066
4067	(void) setlocale(LC_ALL, "");
4068	(void) textdomain(TEXT_DOMAIN);
4069
4070	opterr = 0;
4071
4072	if ((g_zfs = libzfs_init()) == NULL) {
4073		(void) fprintf(stderr, gettext("internal error: failed to "
4074		    "initialize ZFS library\n"));
4075		return (1);
4076	}
4077
4078	zpool_set_history_str("zfs", argc, argv, history_str);
4079	verify(zpool_stage_history(g_zfs, history_str) == 0);
4080
4081	libzfs_print_on_error(g_zfs, B_TRUE);
4082
4083	if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) {
4084		(void) fprintf(stderr, gettext("internal error: unable to "
4085		    "open %s\n"), MNTTAB);
4086		return (1);
4087	}
4088
4089	/*
4090	 * This command also doubles as the /etc/fs mount and unmount program.
4091	 * Determine if we should take this behavior based on argv[0].
4092	 */
4093	progname = basename(argv[0]);
4094	if (strcmp(progname, "mount") == 0) {
4095		ret = manual_mount(argc, argv);
4096	} else if (strcmp(progname, "umount") == 0) {
4097		ret = manual_unmount(argc, argv);
4098	} else {
4099		/*
4100		 * Make sure the user has specified some command.
4101		 */
4102		if (argc < 2) {
4103			(void) fprintf(stderr, gettext("missing command\n"));
4104			usage(B_FALSE);
4105		}
4106
4107		cmdname = argv[1];
4108
4109		/*
4110		 * The 'umount' command is an alias for 'unmount'
4111		 */
4112		if (strcmp(cmdname, "umount") == 0)
4113			cmdname = "unmount";
4114
4115		/*
4116		 * The 'recv' command is an alias for 'receive'
4117		 */
4118		if (strcmp(cmdname, "recv") == 0)
4119			cmdname = "receive";
4120
4121		/*
4122		 * Special case '-?'
4123		 */
4124		if (strcmp(cmdname, "-?") == 0)
4125			usage(B_TRUE);
4126
4127		/*
4128		 * Run the appropriate command.
4129		 */
4130		libzfs_mnttab_cache(g_zfs, B_TRUE);
4131		if (find_command_idx(cmdname, &i) == 0) {
4132			current_command = &command_table[i];
4133			ret = command_table[i].func(argc - 1, argv + 1);
4134		} else if (strchr(cmdname, '=') != NULL) {
4135			verify(find_command_idx("set", &i) == 0);
4136			current_command = &command_table[i];
4137			ret = command_table[i].func(argc, argv);
4138		} else {
4139			(void) fprintf(stderr, gettext("unrecognized "
4140			    "command '%s'\n"), cmdname);
4141			usage(B_FALSE);
4142		}
4143		libzfs_mnttab_cache(g_zfs, B_FALSE);
4144	}
4145
4146	(void) fclose(mnttab_file);
4147
4148	libzfs_fini(g_zfs);
4149
4150	/*
4151	 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
4152	 * for the purposes of running ::findleaks.
4153	 */
4154	if (getenv("ZFS_ABORT") != NULL) {
4155		(void) printf("dumping core by request\n");
4156		abort();
4157	}
4158
4159	return (ret);
4160}
4161