OpenGrok

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