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