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