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