"\tsend [-Le] [-i snapshot|bookmark] "
"<filesystem|volume|snapshot>\n"));
case HELP_SET:
- return (gettext("\tset <property=value> "
+ return (gettext("\tset <property=value> ... "
"<filesystem|volume|snapshot> ...\n"));
case HELP_SHARE:
return (gettext("\tshare <-a | filesystem>\n"));
exit(requested ? 0 : 2);
}
+/*
+ * Take a property=value argument string and add it to the given nvlist.
+ * Modifies the argument inplace.
+ */
static int
-parseprop(nvlist_t *props)
+parseprop(nvlist_t *props, char *propname)
{
- char *propname = optarg;
char *propval, *strval;
if ((propval = strchr(propname, '=')) == NULL) {
(void) fprintf(stderr, gettext("missing "
- "'=' for -o option\n"));
+ "'=' for property=value argument\n"));
return (-1);
}
*propval = '\0';
pt_header = NULL;
}
+static int
+zfs_mount_and_share(libzfs_handle_t *hdl, const char *dataset, zfs_type_t type)
+{
+ zfs_handle_t *zhp = NULL;
+ int ret = 0;
+
+ zhp = zfs_open(hdl, dataset, type);
+ if (zhp == NULL)
+ return (1);
+
+ /*
+ * Volumes may neither be mounted or shared. Potentially in the
+ * future filesystems detected on these volumes could be mounted.
+ */
+ if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) {
+ zfs_close(zhp);
+ return (0);
+ }
+
+ /*
+ * Mount and/or share the new filesystem as appropriate. We provide a
+ * verbose error message to let the user know that their filesystem was
+ * in fact created, even if we failed to mount or share it.
+ *
+ * If the user doesn't want the dataset automatically mounted, then
+ * skip the mount/share step
+ */
+ if (zfs_prop_valid_for_type(ZFS_PROP_CANMOUNT, type, B_FALSE) &&
+ zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_ON) {
+ if (zfs_mount(zhp, NULL, 0) != 0) {
+ (void) fprintf(stderr, gettext("filesystem "
+ "successfully created, but not mounted\n"));
+ ret = 1;
+ } else if (zfs_share(zhp) != 0) {
+ (void) fprintf(stderr, gettext("filesystem "
+ "successfully created, but not shared\n"));
+ ret = 1;
+ }
+ }
+
+ zfs_close(zhp);
+
+ return (ret);
+}
+
/*
* zfs clone [-p] [-o prop=value] ... <snap> <fs | vol>
*
while ((c = getopt(argc, argv, "o:p")) != -1) {
switch (c) {
case 'o':
- if (parseprop(props))
+ if (parseprop(props, optarg) != 0)
return (1);
break;
case 'p':
/* create the mountpoint if necessary */
if (ret == 0) {
- zfs_handle_t *clone;
- int canmount = ZFS_CANMOUNT_OFF;
-
if (log_history) {
(void) zpool_log_history(g_zfs, history_str);
log_history = B_FALSE;
}
- clone = zfs_open(g_zfs, argv[1], ZFS_TYPE_DATASET);
- if (clone != NULL) {
- /*
- * if the user doesn't want the dataset automatically
- * mounted, then skip the mount/share step.
- */
- if (zfs_prop_valid_for_type(ZFS_PROP_CANMOUNT,
- zfs_get_type(clone), B_FALSE))
- canmount = zfs_prop_get_int(clone,
- ZFS_PROP_CANMOUNT);
-
- if (zfs_get_type(clone) != ZFS_TYPE_VOLUME &&
- canmount == ZFS_CANMOUNT_ON)
- if ((ret = zfs_mount(clone, NULL, 0)) == 0)
- ret = zfs_share(clone);
- zfs_close(clone);
- }
+ ret = zfs_mount_and_share(g_zfs, argv[1], ZFS_TYPE_DATASET);
}
zfs_close(zhp);
zfs_do_create(int argc, char **argv)
{
zfs_type_t type = ZFS_TYPE_FILESYSTEM;
- zfs_handle_t *zhp = NULL;
uint64_t volsize = 0;
int c;
boolean_t noreserve = B_FALSE;
int ret = 1;
nvlist_t *props;
uint64_t intval;
- int canmount = ZFS_CANMOUNT_OFF;
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
nomem();
nomem();
break;
case 'o':
- if (parseprop(props))
+ if (parseprop(props, optarg))
goto error;
break;
case 's':
log_history = B_FALSE;
}
- if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL)
- goto error;
-
- ret = 0;
- /*
- * if the user doesn't want the dataset automatically mounted,
- * then skip the mount/share step
- */
- if (zfs_prop_valid_for_type(ZFS_PROP_CANMOUNT, type, B_FALSE))
- canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT);
-
- /*
- * Mount and/or share the new filesystem as appropriate. We provide a
- * verbose error message to let the user know that their filesystem was
- * in fact created, even if we failed to mount or share it.
- */
- if (canmount == ZFS_CANMOUNT_ON) {
- if (zfs_mount(zhp, NULL, 0) != 0) {
- (void) fprintf(stderr, gettext("filesystem "
- "successfully created, but not mounted\n"));
- ret = 1;
- } else if (zfs_share(zhp) != 0) {
- (void) fprintf(stderr, gettext("filesystem "
- "successfully created, but not shared\n"));
- ret = 1;
- }
- }
-
+ ret = zfs_mount_and_share(g_zfs, argv[0], ZFS_TYPE_DATASET);
error:
- if (zhp)
- zfs_close(zhp);
nvlist_free(props);
return (ret);
badusage:
}
/*
- * zfs set property=value { fs | snap | vol } ...
+ * zfs set property=value ... { fs | snap | vol } ...
*
- * Sets the given property for all datasets specified on the command line.
+ * Sets the given properties for all datasets specified on the command line.
*/
-typedef struct set_cbdata {
- char *cb_propname;
- char *cb_value;
-} set_cbdata_t;
static int
set_callback(zfs_handle_t *zhp, void *data)
{
- set_cbdata_t *cbp = data;
+ nvlist_t *props = data;
- if (zfs_prop_set(zhp, cbp->cb_propname, cbp->cb_value) != 0) {
+ if (zfs_prop_set_list(zhp, props) != 0) {
switch (libzfs_errno(g_zfs)) {
case EZFS_MOUNTFAILED:
(void) fprintf(stderr, gettext("property may be set "
static int
zfs_do_set(int argc, char **argv)
{
- set_cbdata_t cb;
+ nvlist_t *props = NULL;
+ int ds_start = -1; /* argv idx of first dataset arg */
int ret = 0;
+ int i;
/* check for options */
if (argc > 1 && argv[1][0] == '-') {
/* check number of arguments */
if (argc < 2) {
- (void) fprintf(stderr, gettext("missing property=value "
- "argument\n"));
+ (void) fprintf(stderr, gettext("missing arguments\n"));
usage(B_FALSE);
}
if (argc < 3) {
- (void) fprintf(stderr, gettext("missing dataset name\n"));
+ if (strchr(argv[1], '=') == NULL) {
+ (void) fprintf(stderr, gettext("missing property=value "
+ "argument(s)\n"));
+ } else {
+ (void) fprintf(stderr, gettext("missing dataset "
+ "name(s)\n"));
+ }
usage(B_FALSE);
}
- /* validate property=value argument */
- cb.cb_propname = argv[1];
- if (((cb.cb_value = strchr(cb.cb_propname, '=')) == NULL) ||
- (cb.cb_value[1] == '\0')) {
- (void) fprintf(stderr, gettext("missing value in "
- "property=value argument\n"));
+ /* validate argument order: prop=val args followed by dataset args */
+ for (i = 1; i < argc; i++) {
+ if (strchr(argv[i], '=') != NULL) {
+ if (ds_start > 0) {
+ /* out-of-order prop=val argument */
+ (void) fprintf(stderr, gettext("invalid "
+ "argument order\n"));
+ usage(B_FALSE);
+ }
+ } else if (ds_start < 0) {
+ ds_start = i;
+ }
+ }
+ if (ds_start < 0) {
+ (void) fprintf(stderr, gettext("missing dataset name(s)\n"));
usage(B_FALSE);
}
- *cb.cb_value = '\0';
- cb.cb_value++;
-
- if (*cb.cb_propname == '\0') {
- (void) fprintf(stderr,
- gettext("missing property in property=value argument\n"));
- usage(B_FALSE);
+ /* Populate a list of property settings */
+ if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
+ nomem();
+ for (i = 1; i < ds_start; i++) {
+ if ((ret = parseprop(props, argv[i])) != 0)
+ goto error;
}
- ret = zfs_for_each(argc - 2, argv + 2, 0,
- ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, &cb);
+ ret = zfs_for_each(argc - ds_start, argv + ds_start, 0,
+ ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, props);
+error:
+ nvlist_free(props);
return (ret);
}
while ((c = getopt(argc, argv, "ro:")) != -1) {
switch (c) {
case 'o':
- if (parseprop(props))
+ if (parseprop(props, optarg))
return (1);
break;
case 'r':