diff options
Diffstat (limited to 'usr/src/cmd')
-rw-r--r-- | usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c | 31 | ||||
-rw-r--r-- | usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c | 31 | ||||
-rw-r--r-- | usr/src/cmd/truss/codes.c | 10 | ||||
-rw-r--r-- | usr/src/cmd/zdb/zdb.c | 3 | ||||
-rw-r--r-- | usr/src/cmd/zfs/Makefile | 4 | ||||
-rw-r--r-- | usr/src/cmd/zfs/zfs_main.c | 581 | ||||
-rw-r--r-- | usr/src/cmd/zpool/zpool_main.c | 343 | ||||
-rw-r--r-- | usr/src/cmd/ztest/ztest.c | 2 |
8 files changed, 824 insertions, 181 deletions
diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c b/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c index 3822265013..69e8c95725 100644 --- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c +++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_create.c @@ -450,18 +450,31 @@ create_zfs(tgt_node_t *x, ucred_t *cred) xmlTextReaderPtr r; const priv_set_t *eset; - eset = ucred_getprivset(cred, PRIV_EFFECTIVE); - if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) : - ucred_geteuid(cred) != 0) { - xml_rtn_msg(&msg, ERR_NO_PERMISSION); + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) { + xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); goto error; } - if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) { - xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); + if (((zh = libzfs_init()) == NULL) || + ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_ANY)) == NULL)) { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); goto error; } + eset = ucred_getprivset(cred, PRIV_EFFECTIVE); + if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) : + ucred_geteuid(cred) != 0) { + + /* + * See if user has ZFS dataset permissions to do operation + */ + if (zfs_iscsi_perm_check(zh, dataset, cred) != 0) { + xml_rtn_msg(&msg, ERR_NO_PERMISSION); + goto error; + } + } + + while ((dnode = tgt_node_next(targets_config, XML_ELEMENT_TARG, dnode)) != NULL) { if (strcmp(dnode->x_value, dataset) == 0) { @@ -470,12 +483,6 @@ create_zfs(tgt_node_t *x, ucred_t *cred) } } - if (((zh = libzfs_init()) == NULL) || - ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_ANY)) == NULL)) { - xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); - goto error; - } - prop_len = 1024; if ((prop = malloc(prop_len)) == NULL) { xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); diff --git a/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c b/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c index 0f907bb977..dd3c1f4434 100644 --- a/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c +++ b/usr/src/cmd/iscsi/iscsitgtd/mgmt_remove.c @@ -37,6 +37,7 @@ #include <unistd.h> #include <priv.h> #include <syslog.h> +#include <libzfs.h> #include <iscsitgt_impl.h> #include "utility.h" @@ -94,21 +95,37 @@ remove_zfs(tgt_node_t *x, ucred_t *cred) { char *prop; char *msg = NULL; - tgt_node_t *targ = NULL; + tgt_node_t *targ = NULL; const priv_set_t *eset; + libzfs_handle_t *zh = NULL; - eset = ucred_getprivset(cred, PRIV_EFFECTIVE); - if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) : - ucred_geteuid(cred) != 0) { - xml_rtn_msg(&msg, ERR_NO_PERMISSION); + if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) { + xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); return (msg); } - if (tgt_find_value_str(x, XML_ELEMENT_NAME, &prop) == False) { - xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); + if ((zh = libzfs_init()) == NULL) { + xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); + free(prop); return (msg); } + eset = ucred_getprivset(cred, PRIV_EFFECTIVE); + if (eset != NULL ? !priv_ismember(eset, PRIV_SYS_CONFIG) : + ucred_geteuid(cred) != 0) { + /* + * See if user has ZFS dataset permissions to do operation + */ + if (zfs_iscsi_perm_check(zh, prop, cred) != 0) { + xml_rtn_msg(&msg, ERR_NO_PERMISSION); + free(prop); + libzfs_fini(zh); + return (msg); + } + } + + libzfs_fini(zh); + while ((targ = tgt_node_next(targets_config, XML_ELEMENT_TARG, targ)) != NULL) { if (strcmp(targ->x_value, prop) == 0) diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c index dbc2ccca9e..4e59786350 100644 --- a/usr/src/cmd/truss/codes.c +++ b/usr/src/cmd/truss/codes.c @@ -864,8 +864,6 @@ const struct ioc { "zfs_cmd_t" }, { (uint_t)ZFS_IOC_POOL_GET_HISTORY, "ZFS_IOC_POOL_GET_HISTORY", "zfs_cmd_t" }, - { (uint_t)ZFS_IOC_POOL_LOG_HISTORY, "ZFS_IOC_POOL_LOG_HISTORY", - "zfs_cmd_t" }, { (uint_t)ZFS_IOC_VDEV_ADD, "ZFS_IOC_VDEV_ADD", "zfs_cmd_t" }, { (uint_t)ZFS_IOC_VDEV_REMOVE, "ZFS_IOC_VDEV_REMOVE", @@ -926,6 +924,14 @@ const struct ioc { "zfs_cmd_t" }, { (uint_t)ZFS_IOC_POOL_GET_PROPS, "ZFS_IOC_POOL_GET_PROPS", "zfs_cmd_t" }, + { (uint_t)ZFS_IOC_SET_FSACL, "ZFS_IOC_SET_FSACL", + "zfs_cmd_t" }, + { (uint_t)ZFS_IOC_GET_FSACL, "ZFS_IOC_GET_FSACL", + "zfs_cmd_t" }, + { (uint_t)ZFS_IOC_ISCSI_PERM_CHECK, "ZFS_IOC_ISCSI_PERM_CHECK", + "zfs_cmd_t" }, + { (uint_t)ZFS_IOC_SHARE, "ZFS_IOC_SHARE", + "zfs_cmd_t" }, /* kssl ioctls */ { (uint_t)KSSL_ADD_ENTRY, "KSSL_ADD_ENTRY", diff --git a/usr/src/cmd/zdb/zdb.c b/usr/src/cmd/zdb/zdb.c index 41d61d2904..23cf656ebe 100644 --- a/usr/src/cmd/zdb/zdb.c +++ b/usr/src/cmd/zdb/zdb.c @@ -700,6 +700,8 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size) (void) printf("\t\treserved = %s\n", resv); (void) printf("\t\tprops_zapobj = %llu\n", (u_longlong_t)dd->dd_props_zapobj); + (void) printf("\t\tdeleg_zapobj = %llu\n", + (u_longlong_t)dd->dd_deleg_zapobj); } /*ARGSUSED*/ @@ -888,6 +890,7 @@ static object_viewer_t *object_viewer[DMU_OT_NUMTYPES] = { dump_uint8, /* SPA history */ dump_uint64, /* SPA history offsets */ dump_zap, /* Pool properties */ + dump_zap, /* DSL permissions */ }; static void diff --git a/usr/src/cmd/zfs/Makefile b/usr/src/cmd/zfs/Makefile index 9b80822041..4761bea33e 100644 --- a/usr/src/cmd/zfs/Makefile +++ b/usr/src/cmd/zfs/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -38,7 +38,7 @@ LINKPROGS= mount umount ROOTETCFSTYPE= $(ROOTETC)/fs/$(FSTYPE) USRLIBFSTYPE= $(ROOTLIB)/fs/$(FSTYPE) -LDLIBS += -lzfs -luutil -lumem -lnvpair +LDLIBS += -lzfs -luutil -lumem -lnvpair -lavl C99MODE= -xc99=%all C99LMODE= -Xc99=%all diff --git a/usr/src/cmd/zfs/zfs_main.c b/usr/src/cmd/zfs/zfs_main.c index 84dfaafedd..fd178add9e 100644 --- a/usr/src/cmd/zfs/zfs_main.c +++ b/usr/src/cmd/zfs/zfs_main.c @@ -32,6 +32,7 @@ #include <libgen.h> #include <libintl.h> #include <libuutil.h> +#include <libnvpair.h> #include <locale.h> #include <stddef.h> #include <stdio.h> @@ -45,8 +46,10 @@ #include <sys/mnttab.h> #include <sys/mount.h> #include <sys/stat.h> +#include <sys/avl.h> #include <libzfs.h> +#include <libuutil.h> #include "zfs_iter.h" #include "zfs_util.h" @@ -72,6 +75,8 @@ static int zfs_do_unshare(int argc, char **argv); static int zfs_do_send(int argc, char **argv); static int zfs_do_receive(int argc, char **argv); static int zfs_do_promote(int argc, char **argv); +static int zfs_do_allow(int argc, char **argv); +static int zfs_do_unallow(int argc, char **argv); /* * These libumem hooks provide a reasonable set of defaults for the allocator's @@ -106,7 +111,9 @@ typedef enum { HELP_SHARE, HELP_SNAPSHOT, HELP_UNMOUNT, - HELP_UNSHARE + HELP_UNSHARE, + HELP_ALLOW, + HELP_UNALLOW } zfs_help_t; typedef struct zfs_command { @@ -150,6 +157,10 @@ static zfs_command_t command_table[] = { { NULL }, { "send", zfs_do_send, HELP_SEND }, { "receive", zfs_do_receive, HELP_RECEIVE }, + { NULL }, + { "allow", zfs_do_allow, HELP_ALLOW }, + { NULL }, + { "unallow", zfs_do_unallow, HELP_UNALLOW }, }; #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) @@ -220,6 +231,47 @@ get_usage(zfs_help_t idx) case HELP_UNSHARE: return (gettext("\tunshare [-f] -a\n" "\tunshare [-f] <filesystem|mountpoint>\n")); + case HELP_ALLOW: + return (gettext("\tallow [-l][-d] <everyone|user|group>[," + "<everyone|user|group>...]\n\t " + "<perm>|@<setname>[,<perm>|@<setname>...]\n\t" + " <filesystem|volume\n" + "\tallow [-l] [-d] -u <user> " + "<perm>|@<setname>[,<perm>|@<setname>...]\n\t" + " <filesystem|volume>\n" + "\tallow [-l] [-d] -g <group> " + "<perm>|@<setname>[,<perm>|@<setname>...]\n\t" + " <filesystem|volume>\n" + "\tallow [-l] [-d] -e " + "<perm>|@<setname>[,<perm>|@<setname>...]\n\t" + " <filesystem|volume>\n" + "\tallow -c " + "<perm>|@<setname>[,<perm>|@<setname>...]\n\t" + " <filesystem|volume>\n" + "\tallow -s @setname " + "<perm>|@<setname>[,<perm>|@<setname>...]\n\t" + " <filesystem|volume>\n")); + + case HELP_UNALLOW: + return (gettext("\tunallow [-r][-l][-d] <everyone|user|group>[," + "<everyone|user|group>...] \n\t " + "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t" + " <filesystem|volume>\n" + "\tunallow [-r][-l][-d] -u user " + "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t" + " <filesystem|volume>\n" + "\tunallow [-r][-l][-d] -g group " + "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t" + " <filesystem|volume>\n" + "\tunallow [-r][-l][-d] -e " + "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t" + " <filesystem|volume>\n" + "\tunallow [-r] -c " + "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t" + " <filesystem|volume>\n" + "\tunallow [-r] -s @setname " + "[<perm>|@<setname>[,<perm>|@<setname>...]]\n\t" + " <filesystem|volume> \n\t")); } abort(); @@ -426,8 +478,6 @@ zfs_do_clone(int argc, char **argv) ret = zfs_share(clone); zfs_close(clone); } - zpool_log_history(g_zfs, argc + optind, argv - optind, argv[1], - B_FALSE, B_FALSE); } zfs_close(zhp); @@ -598,11 +648,6 @@ zfs_do_create(int argc, char **argv) if (zfs_create(g_zfs, argv[0], type, props) != 0) goto error; - if (propval != NULL) - *(propval - 1) = '='; - zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0], - B_FALSE, B_FALSE); - if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL) goto error; @@ -848,9 +893,6 @@ zfs_do_destroy(int argc, char **argv) if (ret) { (void) fprintf(stderr, gettext("no snapshots destroyed\n")); - } else { - zpool_log_history(g_zfs, argc + optind, argv - optind, - argv[0], B_FALSE, B_FALSE); } return (ret != 0); } @@ -890,7 +932,6 @@ zfs_do_destroy(int argc, char **argv) return (1); } - if (cb.cb_error || zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0) { zfs_close(zhp); @@ -901,11 +942,10 @@ zfs_do_destroy(int argc, char **argv) * Do the real thing. The callback will close the handle regardless of * whether it succeeds or not. */ + if (destroy_callback(zhp, &cb) != 0) return (1); - zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0], - B_FALSE, B_FALSE); return (0); } @@ -1181,20 +1221,14 @@ zfs_do_get(int argc, char **argv) * useful for setting a property on a hierarchy-wide basis, regardless of any * local modifications for each dataset. */ -typedef struct inherit_cbdata { - char *cb_propname; - boolean_t cb_any_successful; -} inherit_cbdata_t; static int inherit_callback(zfs_handle_t *zhp, void *data) { - inherit_cbdata_t *cbp = data; + char *propname = data; int ret; - ret = zfs_prop_inherit(zhp, cbp->cb_propname); - if (ret == 0) - cbp->cb_any_successful = B_TRUE; + ret = zfs_prop_inherit(zhp, propname); return (ret != 0); } @@ -1204,7 +1238,7 @@ zfs_do_inherit(int argc, char **argv) boolean_t recurse = B_FALSE; int c; zfs_prop_t prop; - inherit_cbdata_t cb; + char *propname; int ret; /* check options */ @@ -1234,43 +1268,35 @@ zfs_do_inherit(int argc, char **argv) usage(B_FALSE); } - cb.cb_propname = argv[0]; + propname = argv[0]; argc--; argv++; - if ((prop = zfs_name_to_prop(cb.cb_propname)) != ZFS_PROP_INVAL) { + if ((prop = zfs_name_to_prop(propname)) != ZFS_PROP_INVAL) { if (zfs_prop_readonly(prop)) { (void) fprintf(stderr, gettext( "%s property is read-only\n"), - cb.cb_propname); + propname); return (1); } if (!zfs_prop_inheritable(prop)) { (void) fprintf(stderr, gettext("'%s' property cannot " - "be inherited\n"), cb.cb_propname); + "be inherited\n"), propname); if (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_RESERVATION) (void) fprintf(stderr, gettext("use 'zfs set " - "%s=none' to clear\n"), cb.cb_propname); + "%s=none' to clear\n"), propname); return (1); } - } else if (!zfs_prop_user(cb.cb_propname)) { - (void) fprintf(stderr, gettext( - "invalid property '%s'\n"), - cb.cb_propname); + } else if (!zfs_prop_user(propname)) { + (void) fprintf(stderr, gettext("invalid property '%s'\n"), + propname); usage(B_FALSE); } - cb.cb_any_successful = B_FALSE; - ret = zfs_for_each(argc, argv, recurse, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, NULL, NULL, - inherit_callback, &cb, B_FALSE); - - if (cb.cb_any_successful) { - zpool_log_history(g_zfs, argc + optind + 1, argv - optind - 1, - argv[0], B_FALSE, B_FALSE); - } + inherit_callback, propname, B_FALSE); return (ret); } @@ -1606,10 +1632,6 @@ zfs_do_rename(int argc, char **argv) ret = (zfs_rename(zhp, argv[1], recurse) != 0); - if (!ret) - zpool_log_history(g_zfs, argc + optind, argv - optind, argv[1], - B_FALSE, B_FALSE); - zfs_close(zhp); return (ret); } @@ -1650,8 +1672,6 @@ zfs_do_promote(int argc, char **argv) ret = (zfs_promote(zhp) != 0); - if (!ret) - zpool_log_history(g_zfs, argc, argv, argv[1], B_FALSE, B_FALSE); zfs_close(zhp); return (ret); @@ -1820,11 +1840,6 @@ zfs_do_rollback(int argc, char **argv) */ ret = zfs_rollback(zhp, snap, force); - if (!ret) { - zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0], - B_FALSE, B_FALSE); - } - out: zfs_close(snap); zfs_close(zhp); @@ -1843,7 +1858,6 @@ out: typedef struct set_cbdata { char *cb_propname; char *cb_value; - boolean_t cb_any_successful; } set_cbdata_t; static int @@ -1864,7 +1878,6 @@ set_callback(zfs_handle_t *zhp, void *data) } return (1); } - cbp->cb_any_successful = B_TRUE; return (0); } @@ -1902,7 +1915,6 @@ zfs_do_set(int argc, char **argv) *cb.cb_value = '\0'; cb.cb_value++; - cb.cb_any_successful = B_FALSE; if (*cb.cb_propname == '\0') { (void) fprintf(stderr, @@ -1910,14 +1922,10 @@ zfs_do_set(int argc, char **argv) usage(B_FALSE); } + ret = zfs_for_each(argc - 2, argv + 2, B_FALSE, ZFS_TYPE_ANY, NULL, NULL, set_callback, &cb, B_FALSE); - if (cb.cb_any_successful) { - *(cb.cb_value - 1) = '='; - zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE); - } - return (ret); } @@ -1963,10 +1971,6 @@ zfs_do_snapshot(int argc, char **argv) ret = zfs_snapshot(g_zfs, argv[0], recursive); if (ret && recursive) (void) fprintf(stderr, gettext("no snapshots were created\n")); - if (!ret) { - zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0], - B_FALSE, B_FALSE); - } return (ret != 0); } @@ -2117,12 +2121,386 @@ zfs_do_receive(int argc, char **argv) err = zfs_receive(g_zfs, argv[0], isprefix, verbose, dryrun, force, STDIN_FILENO); - if (!err) { - zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0], - B_FALSE, B_FALSE); + return (err != 0); +} + +typedef struct allow_cb { + int a_permcnt; + size_t a_treeoffset; +} allow_cb_t; + +static void +zfs_print_perms(avl_tree_t *tree) +{ + zfs_perm_node_t *permnode; + + permnode = avl_first(tree); + while (permnode != NULL) { + (void) printf("%s", permnode->z_pname); + permnode = AVL_NEXT(tree, permnode); + if (permnode) + (void) printf(","); + else + (void) printf("\n"); } +} - return (err != 0); +/* + * Iterate over user/groups/everyone/... and the call perm_iter + * function to print actual permission when tree has >0 nodes. + */ +static void +zfs_iter_perms(avl_tree_t *tree, const char *banner, allow_cb_t *cb) +{ + zfs_allow_node_t *item; + avl_tree_t *ptree; + + item = avl_first(tree); + while (item) { + ptree = (void *)((char *)item + cb->a_treeoffset); + if (avl_numnodes(ptree)) { + if (cb->a_permcnt++ == 0) + (void) printf("%s\n", banner); + (void) printf("\t%s", item->z_key); + /* + * Avoid an extra space being printed + * for "everyone" which is keyed with a null + * string + */ + if (item->z_key[0] != '\0') + (void) printf(" "); + zfs_print_perms(ptree); + } + item = AVL_NEXT(tree, item); + } +} + +#define LINES "-------------------------------------------------------------\n" +static int +zfs_print_allows(char *ds) +{ + zfs_allow_t *curperms, *perms; + zfs_handle_t *zhp; + allow_cb_t allowcb = { 0 }; + char banner[MAXPATHLEN]; + + if (ds[0] == '-') + usage(B_FALSE); + + if (strrchr(ds, '@')) { + (void) fprintf(stderr, gettext("Snapshots don't have 'allow'" + " permissions\n")); + return (1); + } + if ((zhp = zfs_open(g_zfs, ds, ZFS_TYPE_ANY)) == NULL) + return (1); + + if (zfs_perm_get(zhp, &perms)) { + (void) fprintf(stderr, + gettext("Failed to retrieve 'allows' on %s\n"), ds); + zfs_close(zhp); + return (1); + } + + zfs_close(zhp); + + if (perms != NULL) + (void) printf("%s", LINES); + for (curperms = perms; curperms; curperms = curperms->z_next) { + + (void) snprintf(banner, sizeof (banner), + "Permission sets on (%s)", curperms->z_setpoint); + allowcb.a_treeoffset = + offsetof(zfs_allow_node_t, z_localdescend); + allowcb.a_permcnt = 0; + zfs_iter_perms(&curperms->z_sets, banner, &allowcb); + + (void) snprintf(banner, sizeof (banner), + "Create time permissions on (%s)", curperms->z_setpoint); + allowcb.a_treeoffset = + offsetof(zfs_allow_node_t, z_localdescend); + allowcb.a_permcnt = 0; + zfs_iter_perms(&curperms->z_crperms, banner, &allowcb); + + + (void) snprintf(banner, sizeof (banner), + "Local permissions on (%s)", curperms->z_setpoint); + allowcb.a_treeoffset = offsetof(zfs_allow_node_t, z_local); + allowcb.a_permcnt = 0; + zfs_iter_perms(&curperms->z_user, banner, &allowcb); + zfs_iter_perms(&curperms->z_group, banner, &allowcb); + zfs_iter_perms(&curperms->z_everyone, banner, &allowcb); + + (void) snprintf(banner, sizeof (banner), + "Descendent permissions on (%s)", curperms->z_setpoint); + allowcb.a_treeoffset = offsetof(zfs_allow_node_t, z_descend); + allowcb.a_permcnt = 0; + zfs_iter_perms(&curperms->z_user, banner, &allowcb); + zfs_iter_perms(&curperms->z_group, banner, &allowcb); + zfs_iter_perms(&curperms->z_everyone, banner, &allowcb); + + (void) snprintf(banner, sizeof (banner), + "Local+Descendent permissions on (%s)", + curperms->z_setpoint); + allowcb.a_treeoffset = + offsetof(zfs_allow_node_t, z_localdescend); + allowcb.a_permcnt = 0; + zfs_iter_perms(&curperms->z_user, banner, &allowcb); + zfs_iter_perms(&curperms->z_group, banner, &allowcb); + zfs_iter_perms(&curperms->z_everyone, banner, &allowcb); + + (void) printf("%s", LINES); + } + zfs_free_allows(perms); + return (0); +} + +#define ALLOWOPTIONS "ldcsu:g:e" +#define UNALLOWOPTIONS "ldcsu:g:er" + +/* + * Validate options, and build necessary datastructure to display/remove/add + * permissions. + * Returns 0 - If permissions should be added/removed + * Returns 1 - If permissions should be displayed. + * Returns -1 - on failure + */ +int +parse_allow_args(int *argc, char **argv[], boolean_t unallow, + char **ds, int *recurse, nvlist_t **zperms) +{ + int c; + char *options = unallow ? UNALLOWOPTIONS : ALLOWOPTIONS; + zfs_deleg_inherit_t deleg_type = ZFS_DELEG_NONE; + zfs_deleg_who_type_t who_type = ZFS_DELEG_WHO_UNKNOWN; + char *who; + char *perms = NULL; + zfs_handle_t *zhp; + + while ((c = getopt(*argc, *argv, options)) != -1) { + switch (c) { + case 'l': + if (who_type == ZFS_DELEG_CREATE || + who_type == ZFS_DELEG_NAMED_SET) + usage(B_FALSE); + + deleg_type |= ZFS_DELEG_PERM_LOCAL; + break; + case 'd': + if (who_type == ZFS_DELEG_CREATE || + who_type == ZFS_DELEG_NAMED_SET) + usage(B_FALSE); + + deleg_type |= ZFS_DELEG_PERM_DESCENDENT; + break; + case 'r': + *recurse = B_TRUE; + break; + case 'c': + if (who_type != ZFS_DELEG_WHO_UNKNOWN) + usage(B_FALSE); + if (deleg_type) + usage(B_FALSE); + who_type = ZFS_DELEG_CREATE; + break; + case 's': + if (who_type != ZFS_DELEG_WHO_UNKNOWN) + usage(B_FALSE); + if (deleg_type) + usage(B_FALSE); + who_type = ZFS_DELEG_NAMED_SET; + break; + case 'u': + if (who_type != ZFS_DELEG_WHO_UNKNOWN) + usage(B_FALSE); + who_type = ZFS_DELEG_USER; + who = optarg; + break; + case 'g': + if (who_type != ZFS_DELEG_WHO_UNKNOWN) + usage(B_FALSE); + who_type = ZFS_DELEG_GROUP; + who = optarg; + break; + case 'e': + if (who_type != ZFS_DELEG_WHO_UNKNOWN) + usage(B_FALSE); + who_type = ZFS_DELEG_EVERYONE; + break; + default: + usage(B_FALSE); + break; + } + } + + if (deleg_type == 0) + deleg_type = ZFS_DELEG_PERM_LOCALDESCENDENT; + + *argc -= optind; + *argv += optind; + + if (unallow == B_FALSE && *argc == 1) { + /* + * Only print permissions if no options were processed + */ + if (optind == 1) + return (1); + else + usage(B_FALSE); + } + + /* + * initialize variables for zfs_build_perms based on number + * of arguments. + * 3 arguments ==> zfs [un]allow joe perm,perm,perm <dataset> or + * zfs [un]allow -s @set1 perm,perm <dataset> + * 2 arguments ==> zfs [un]allow -c perm,perm <dataset> or + * zfs [un]allow -u|-g <name> perm <dataset> or + * zfs [un]allow -e perm,perm <dataset> + * zfs unallow joe <dataset> + * zfs unallow -s @set1 <dataset> + * 1 argument ==> zfs [un]allow -e <dataset> or + * zfs [un]allow -c <dataset> + */ + + switch (*argc) { + case 3: + perms = (*argv)[1]; + who = (*argv)[0]; + *ds = (*argv)[2]; + + /* + * advance argc/argv for do_allow cases. + * for do_allow case make sure who have a know who type + * and its not a permission set. + */ + if (unallow == B_TRUE) { + *argc -= 2; + *argv += 2; + } else if (who_type != ZFS_DELEG_WHO_UNKNOWN && + who_type != ZFS_DELEG_NAMED_SET) + usage(B_FALSE); + break; + + case 2: + if (unallow == B_TRUE && (who_type == ZFS_DELEG_EVERYONE || + who_type == ZFS_DELEG_CREATE || who != NULL)) { + perms = (*argv)[0]; + *ds = (*argv)[1]; + } else { + if (unallow == B_FALSE && + (who_type == ZFS_DELEG_WHO_UNKNOWN || + who_type == ZFS_DELEG_NAMED_SET)) + usage(B_FALSE); + else if (who_type == ZFS_DELEG_WHO_UNKNOWN || + who_type == ZFS_DELEG_NAMED_SET) + who = (*argv)[0]; + else if (who_type != ZFS_DELEG_NAMED_SET) + perms = (*argv)[0]; + *ds = (*argv)[1]; + } + if (unallow == B_TRUE) { + (*argc)--; + (*argv)++; + } + break; + + case 1: + if (unallow == B_FALSE) + usage(B_FALSE); + if (who == NULL && who_type != ZFS_DELEG_CREATE && + who_type != ZFS_DELEG_EVERYONE) + usage(B_FALSE); + *ds = (*argv)[0]; + break; + + default: + usage(B_FALSE); + } + + if (strrchr(*ds, '@')) { + (void) fprintf(stderr, + gettext("Can't set or remove 'allow' permissions " + "on snapshots.\n")); + return (-1); + } + + if ((zhp = zfs_open(g_zfs, *ds, ZFS_TYPE_ANY)) == NULL) + return (-1); + + if ((zfs_build_perms(zhp, who, perms, + who_type, deleg_type, zperms)) != 0) { + zfs_close(zhp); + return (-1); + } + zfs_close(zhp); + return (0); +} + +static int +zfs_do_allow(int argc, char **argv) +{ + char *ds; + nvlist_t *zperms = NULL; + zfs_handle_t *zhp; + int unused; + int ret; + + if ((ret = parse_allow_args(&argc, &argv, B_FALSE, &ds, + &unused, &zperms)) == -1) + return (1); + + if (ret == 1) + return (zfs_print_allows(argv[0])); + + if ((zhp = zfs_open(g_zfs, ds, ZFS_TYPE_ANY)) == NULL) + return (1); + + if (zfs_perm_set(zhp, zperms)) { + zfs_close(zhp); + nvlist_free(zperms); + return (1); + } + nvlist_free(zperms); + zfs_close(zhp); + + return (0); +} + +static int +unallow_callback(zfs_handle_t *zhp, void *data) +{ + nvlist_t *nvp = (nvlist_t *)data; + int error; + + error = zfs_perm_remove(zhp, nvp); + if (error) { + (void) fprintf(stderr, gettext("Failed to remove permissions " + "on %s\n"), zfs_get_name(zhp)); + } + return (error); +} + +static int +zfs_do_unallow(int argc, char **argv) +{ + int recurse = B_FALSE; + char *ds; + int error; + nvlist_t *zperms = NULL; + + if (parse_allow_args(&argc, &argv, B_TRUE, + &ds, &recurse, &zperms) == -1) + return (1); + + error = zfs_for_each(argc, argv, recurse, + ZFS_TYPE_FILESYSTEM|ZFS_TYPE_VOLUME, NULL, + NULL, unallow_callback, (void *)zperms, B_FALSE); + + if (zperms) + nvlist_free(zperms); + + return (error); } typedef struct get_all_cbdata { @@ -3143,6 +3521,34 @@ do_volcheck(boolean_t isinit) return (zpool_iter(g_zfs, volcheck, &isinit) ? 1 : 0); } +static int +find_command_idx(char *command, int *idx) +{ + int i; + + for (i = 0; i < NCOMMAND; i++) { + if (command_table[i].name == NULL) + continue; + + if (strcmp(command, command_table[i].name) == 0) { + *idx = i; + return (0); + } + } + return (1); +} + +zfs_prop_t +propset_cb(zfs_prop_t prop, void *data) +{ + char *cmdname = (char *)data; + + if (strcmp(cmdname, zfs_prop_to_name(prop)) == 0) + return (prop); + + return (ZFS_PROP_CONT); +} + int main(int argc, char **argv) { @@ -3150,6 +3556,8 @@ main(int argc, char **argv) int i; char *progname; char *cmdname; + char *str; + boolean_t found = B_FALSE; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); @@ -3162,6 +3570,8 @@ main(int argc, char **argv) return (1); } + zpool_stage_history(g_zfs, argc, argv, B_TRUE, B_FALSE); + libzfs_print_on_error(g_zfs, B_TRUE); if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) { @@ -3220,18 +3630,41 @@ main(int argc, char **argv) /* * Run the appropriate command. */ - for (i = 0; i < NCOMMAND; i++) { - if (command_table[i].name == NULL) - continue; + if (find_command_idx(cmdname, &i) == 0) { + current_command = &command_table[i]; + ret = command_table[i].func(argc - 1, argv + 1); + found = B_TRUE; + } - if (strcmp(cmdname, command_table[i].name) == 0) { + /* + * Check and see if they are doing property=value + */ + if (found == B_FALSE && + ((str = strchr(cmdname, '=')) != NULL)) { + *str = '\0'; + if (zfs_prop_iter(propset_cb, cmdname, + B_FALSE) != ZFS_PROP_INVAL) + found = B_TRUE; + + if (found == B_FALSE && zfs_prop_user(cmdname)) + found = B_TRUE; + + if (found == B_TRUE && + find_command_idx("set", &i) == 0) { + *str = '='; current_command = &command_table[i]; - ret = command_table[i].func(argc - 1, argv + 1); - break; + ret = command_table[i].func(argc, argv); + } else { + (void) fprintf(stderr, + gettext("invalid property '%s'\n"), + cmdname); + found = B_TRUE; + ret = 1; } + } - if (i == NCOMMAND) { + if (found == B_FALSE) { (void) fprintf(stderr, gettext("unrecognized " "command '%s'\n"), cmdname); usage(B_FALSE); diff --git a/usr/src/cmd/zpool/zpool_main.c b/usr/src/cmd/zpool/zpool_main.c index 6dc540299f..0bd2146ec5 100644 --- a/usr/src/cmd/zpool/zpool_main.c +++ b/usr/src/cmd/zpool/zpool_main.c @@ -41,6 +41,8 @@ #include <strings.h> #include <unistd.h> #include <priv.h> +#include <pwd.h> +#include <zone.h> #include <sys/fs/zfs.h> #include <sys/stat.h> @@ -188,12 +190,13 @@ get_usage(zpool_help_t idx) { case HELP_EXPORT: return (gettext("\texport [-f] <pool> ...\n")); case HELP_HISTORY: - return (gettext("\thistory [<pool>]\n")); + return (gettext("\thistory [-il] [<pool>] ...\n")); case HELP_IMPORT: return (gettext("\timport [-d dir] [-D]\n" - "\timport [-d dir] [-D] [-f] [-o opts] [-R root] -a\n" - "\timport [-d dir] [-D] [-f] [-o opts] [-R root ]" - " <pool | id> [newpool]\n")); + "\timport [-p property=value] [-d dir] [-D] [-f] " + "[-o opts] [-R root] -a\n" + "\timport [-p property=value] [-d dir] [-D] [-f] \n" + "\t [-o opts] [-R root ] <pool | id> [newpool]\n")); case HELP_IOSTAT: return (gettext("\tiostat [-v] [pool] ... [interval " "[count]]\n")); @@ -524,10 +527,6 @@ zpool_do_add(int argc, char **argv) ret = 0; } else { ret = (zpool_add(zhp, nvroot) != 0); - if (!ret) { - zpool_log_history(g_zfs, argc + 1 + optind, - argv - 1 - optind, poolname, B_TRUE, B_FALSE); - } } nvlist_free(nvroot); @@ -569,10 +568,6 @@ zpool_do_remove(int argc, char **argv) return (1); ret = (zpool_vdev_remove(zhp, argv[1]) != 0); - if (!ret) { - zpool_log_history(g_zfs, ++argc, --argv, poolname, B_TRUE, - B_FALSE); - } return (ret); } @@ -767,8 +762,6 @@ zpool_do_create(int argc, char **argv) ret = zfs_share_nfs(pool); zfs_close(pool); } - zpool_log_history(g_zfs, argc + optind, argv - optind, - poolname, B_TRUE, B_TRUE); } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) { (void) fprintf(stderr, gettext("pool name may have " "been omitted\n")); @@ -841,9 +834,6 @@ zpool_do_destroy(int argc, char **argv) return (1); } - zpool_log_history(g_zfs, argc + optind, argv - optind, pool, B_TRUE, - B_FALSE); - ret = (zpool_destroy(zhp) != 0); zpool_close(zhp); @@ -904,9 +894,6 @@ zpool_do_export(int argc, char **argv) continue; } - zpool_log_history(g_zfs, argc + optind, argv - optind, argv[i], - B_TRUE, B_FALSE); - if (zpool_export(zhp) != 0) ret = 1; @@ -1219,12 +1206,13 @@ show_import(nvlist_t *config) */ static int do_import(nvlist_t *config, const char *newname, const char *mntopts, - const char *altroot, int force, int argc, char **argv) + const char *altroot, int force, nvlist_t *props) { zpool_handle_t *zhp; char *name; uint64_t state; uint64_t version; + int error = 0; verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME, &name) == 0); @@ -1277,17 +1265,33 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts, if (newname != NULL) name = (char *)newname; - zpool_log_history(g_zfs, argc, argv, name, B_TRUE, B_FALSE); - verify((zhp = zpool_open(g_zfs, name)) != NULL); + if (props) { + nvpair_t *pair = nvlist_next_nvpair(props, NULL); + char *value; + + if (pair != NULL) { + do { + verify((nvpair_value_string(pair, + &value)) == 0); + + if ((error = zpool_set_prop(zhp, + nvpair_name(pair), value)) != 0) + break; + + } while (pair = nvlist_next_nvpair(props, pair)); + } + } + + if (zpool_enable_datasets(zhp, mntopts, 0) != 0) { zpool_close(zhp); return (1); } zpool_close(zhp); - return (0); + return (error); } /* @@ -1309,6 +1313,10 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts, * * -a Import all pools found. * + * -o temporary mount options. + * + * -p property=value + * * The import command scans for pools to import, and import pools based on pool * name and GUID. The pool can also be renamed as part of the import process. */ @@ -1329,12 +1337,15 @@ zpool_do_import(int argc, char **argv) nvlist_t *config; uint64_t searchguid; char *searchname; + char *propname; + char *propval, *strval; nvlist_t *found_config; + nvlist_t *props = NULL; boolean_t first; uint64_t pool_state; /* check options */ - while ((c = getopt(argc, argv, ":Dfd:R:ao:")) != -1) { + while ((c = getopt(argc, argv, ":Dfd:R:ao:p:")) != -1) { switch (c) { case 'a': do_all = B_TRUE; @@ -1369,6 +1380,48 @@ zpool_do_import(int argc, char **argv) "'%c' option\n"), optopt); usage(B_FALSE); break; + case 'p': + if (props == NULL && + nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { + (void) fprintf(stderr, + gettext("internal error: " + "out of memory\n")); + err = B_TRUE; + goto error; + } + + propname = optarg; + if ((propval = strchr(propname, '=')) == NULL) { + (void) fprintf(stderr, gettext("missing " + "'=' for -o option\n")); + err = B_TRUE; + goto error; + } + *propval = '\0'; + propval++; + + if (zpool_name_to_prop(propname) == ZFS_PROP_INVAL) { + (void) fprintf(stderr, + gettext("property '%s' is " + "not a valid pool property\n"), propname); + err = B_TRUE; + goto error; + } + + if (nvlist_lookup_string(props, propname, + &strval) == 0) { + (void) fprintf(stderr, gettext("property '%s' " + "specified multiple times\n"), propname); + err = B_TRUE; + goto error; + } + if (nvlist_add_string(props, propname, propval) != 0) { + (void) fprintf(stderr, gettext("internal " + "error: out of memory\n")); + err = B_TRUE; + goto error; + } + break; case '?': (void) fprintf(stderr, gettext("invalid option '%c'\n"), optopt); @@ -1463,8 +1516,7 @@ zpool_do_import(int argc, char **argv) if (do_all) err |= do_import(config, NULL, mntopts, - altroot, do_force, argc + optind, - argv - optind); + altroot, do_force, props); else show_import(config); } else if (searchname != NULL) { @@ -1512,8 +1564,7 @@ zpool_do_import(int argc, char **argv) err = B_TRUE; } else { err |= do_import(found_config, argc == 1 ? NULL : - argv[1], mntopts, altroot, do_force, argc + optind, - argv - optind); + argv[1], mntopts, altroot, do_force, props); } } @@ -1525,6 +1576,9 @@ zpool_do_import(int argc, char **argv) (void) fprintf(stderr, gettext("no pools available to import\n")); +error: + if (props) + nvlist_free(props); nvlist_free(pools); free(searchdirs); @@ -2172,8 +2226,6 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing) char *poolname, *old_disk, *new_disk; zpool_handle_t *zhp; int ret; - int log_argc; - char **log_argv; /* check options */ while ((c = getopt(argc, argv, "f")) != -1) { @@ -2188,8 +2240,6 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing) } } - log_argc = argc; - log_argv = argv; argc -= optind; argv += optind; @@ -2247,11 +2297,6 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing) ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing); - if (!ret) { - zpool_log_history(g_zfs, log_argc, log_argv, poolname, B_TRUE, - B_FALSE); - } - nvlist_free(nvroot); zpool_close(zhp); @@ -2341,10 +2386,6 @@ zpool_do_detach(int argc, char **argv) ret = zpool_vdev_detach(zhp, path); - if (!ret) { - zpool_log_history(g_zfs, argc + optind, argv - optind, poolname, - B_TRUE, B_FALSE); - } zpool_close(zhp); return (ret); @@ -2411,10 +2452,6 @@ zpool_do_online(int argc, char **argv) } } - if (!ret) { - zpool_log_history(g_zfs, argc + optind, argv - optind, poolname, - B_TRUE, B_FALSE); - } zpool_close(zhp); return (ret); @@ -2477,10 +2514,6 @@ zpool_do_offline(int argc, char **argv) ret = 1; } - if (!ret) { - zpool_log_history(g_zfs, argc + optind, argv - optind, poolname, - B_TRUE, B_FALSE); - } zpool_close(zhp); return (ret); @@ -2517,8 +2550,6 @@ zpool_do_clear(int argc, char **argv) if (zpool_clear(zhp, device) != 0) ret = 1; - if (!ret) - zpool_log_history(g_zfs, argc, argv, pool, B_TRUE, B_FALSE); zpool_close(zhp); return (ret); @@ -2547,11 +2578,6 @@ scrub_callback(zpool_handle_t *zhp, void *data) err = zpool_scrub(zhp, cb->cb_type); - if (!err) { - zpool_log_history(g_zfs, cb->cb_argc, cb->cb_argv, - zpool_get_name(zhp), B_TRUE, B_FALSE); - } - return (err != 0); } @@ -3223,9 +3249,6 @@ upgrade_cb(zpool_handle_t *zhp, void *arg) cbp->cb_first = B_FALSE; ret = zpool_upgrade(zhp); if (!ret) { - zpool_log_history(g_zfs, cbp->cb_argc, - cbp->cb_argv, zpool_get_name(zhp), B_TRUE, - B_FALSE); (void) printf(gettext("Successfully upgraded " "'%s'\n"), zpool_get_name(zhp)); } @@ -3257,7 +3280,6 @@ upgrade_one(zpool_handle_t *zhp, void *data) nvlist_t *config; uint64_t version; int ret; - upgrade_cbdata_t *cbp = data; config = zpool_get_config(zhp, NULL); verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION, @@ -3278,8 +3300,6 @@ upgrade_one(zpool_handle_t *zhp, void *data) ret = zpool_upgrade(zhp); if (!ret) { - zpool_log_history(g_zfs, cbp->cb_argc, cbp->cb_argv, - zpool_get_name(zhp), B_TRUE, B_FALSE); (void) printf(gettext("Successfully upgraded '%s' " "from version %llu to version %llu\n"), zpool_get_name(zhp), (u_longlong_t)version, (u_longlong_t)ZFS_VERSION); @@ -3357,8 +3377,9 @@ zpool_do_upgrade(int argc, char **argv) (void) printf(gettext(" 4 zpool history\n")); (void) printf(gettext(" 5 Compression using the gzip " "algorithm\n")); - (void) printf(gettext(" 6 pool properties ")); + (void) printf(gettext(" 6 pool properties\n")); (void) printf(gettext(" 7 Separate intent log devices\n")); + (void) printf(gettext(" 8 Delegated administration\n")); (void) printf(gettext("For more information on a particular " "version, including supported releases, see:\n\n")); (void) printf("http://www.opensolaris.org/os/community/zfs/" @@ -3399,6 +3420,49 @@ zpool_do_upgrade(int argc, char **argv) return (ret); } +typedef struct hist_cbdata { + boolean_t first; + int longfmt; + int internal; +} hist_cbdata_t; + +char *hist_event_table[LOG_END] = { + "invalid event", + "pool create", + "vdev add", + "pool remove", + "pool destroy", + "pool export", + "pool import", + "vdev attach", + "vdev replace", + "vdev detach", + "vdev online", + "vdev offline", + "vdev upgrade", + "pool clear", + "pool scrub", + "pool property set", + "create", + "clone", + "destroy", + "destroy_begin_sync", + "inherit", + "property set", + "quota set", + "permission update", + "permission remove", + "permission who remove", + "promote", + "receive", + "rename", + "reservation set", + "replay_inc_sync", + "replay_full_sync", + "rollback", + "snapshot", +}; + /* * Print out the command history for a specific pool. */ @@ -3409,13 +3473,22 @@ get_history_one(zpool_handle_t *zhp, void *data) nvlist_t **records; uint_t numrecords; char *cmdstr; + char *pathstr; uint64_t dst_time; time_t tsec; struct tm t; char tbuf[30]; int ret, i; + uint64_t who; + struct passwd *pwd; + char *hostname; + char *zonename; + char internalstr[MAXPATHLEN]; + hist_cbdata_t *cb = (hist_cbdata_t *)data; + uint64_t txg; + uint64_t ievent; - *(boolean_t *)data = B_FALSE; + cb->first = B_FALSE; (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp)); @@ -3426,14 +3499,65 @@ get_history_one(zpool_handle_t *zhp, void *data) &records, &numrecords) == 0); for (i = 0; i < numrecords; i++) { if (nvlist_lookup_uint64(records[i], ZPOOL_HIST_TIME, - &dst_time) == 0) { - verify(nvlist_lookup_string(records[i], ZPOOL_HIST_CMD, - &cmdstr) == 0); - tsec = dst_time; - (void) localtime_r(&tsec, &t); - (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); - (void) printf("%s %s\n", tbuf, cmdstr); + &dst_time) != 0) + continue; + + /* is it an internal event or a standard event? */ + if (nvlist_lookup_string(records[i], ZPOOL_HIST_CMD, + &cmdstr) != 0) { + if (cb->internal == 0) + continue; + + if (nvlist_lookup_uint64(records[i], + ZPOOL_HIST_INT_EVENT, &ievent) != 0) + continue; + verify(nvlist_lookup_uint64(records[i], + ZPOOL_HIST_TXG, &txg) == 0); + verify(nvlist_lookup_string(records[i], + ZPOOL_HIST_INT_STR, &pathstr) == 0); + if (ievent > LOG_END) + continue; + (void) snprintf(internalstr, + sizeof (internalstr), + "[internal %s txg:%lld] %s", + hist_event_table[ievent], txg, + pathstr); + cmdstr = internalstr; } + tsec = dst_time; + (void) localtime_r(&tsec, &t); + (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t); + (void) printf("%s %s", tbuf, cmdstr); + + if (!cb->longfmt) { + (void) printf("\n"); + continue; + } + (void) printf(" ["); + if (nvlist_lookup_uint64(records[i], + ZPOOL_HIST_WHO, &who) == 0) { + pwd = getpwuid((uid_t)who); + if (pwd) + (void) printf("user %s on", + pwd->pw_name); + else + (void) printf("user %d on", + (int)who); + } else { + (void) printf(gettext("no info]\n")); + continue; + } + if (nvlist_lookup_string(records[i], + ZPOOL_HIST_HOST, &hostname) == 0) { + (void) printf(" %s", hostname); + } + if (nvlist_lookup_string(records[i], + ZPOOL_HIST_ZONE, &zonename) == 0) { + (void) printf(":%s", zonename); + } + + (void) printf("]"); + (void) printf("\n"); } (void) printf("\n"); nvlist_free(nvhis); @@ -3446,19 +3570,38 @@ get_history_one(zpool_handle_t *zhp, void *data) * * Displays the history of commands that modified pools. */ + + int zpool_do_history(int argc, char **argv) { - boolean_t first = B_TRUE; + hist_cbdata_t cbdata = { 0 }; int ret; + int c; + cbdata.first = B_TRUE; + /* check options */ + while ((c = getopt(argc, argv, "li")) != -1) { + switch (c) { + case 'l': + cbdata.longfmt = 1; + break; + case 'i': + cbdata.internal = 1; + break; + case '?': + (void) fprintf(stderr, gettext("invalid option '%c'\n"), + optopt); + usage(B_FALSE); + } + } argc -= optind; argv += optind; ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one, - &first); + &cbdata); - if (argc == 0 && first == B_TRUE) { + if (argc == 0 && cbdata.first == B_TRUE) { (void) printf(gettext("no pools available\n")); return (0); } @@ -3593,11 +3736,6 @@ zpool_do_set(int argc, char **argv) error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL, set_callback, &cb); - if (cb.cb_any_successful) { - *(cb.cb_value - 1) = '='; - zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE); - } - return (error); } @@ -3618,13 +3756,25 @@ find_command_idx(char *command, int *idx) return (1); } +zpool_prop_t +propset_cb(zpool_prop_t prop, void *data) +{ + char *cmdname = (char *)data; + + if (strcmp(cmdname, zpool_prop_to_name(prop)) == 0) + return (prop); + + return (ZFS_PROP_CONT); +} + int main(int argc, char **argv) { int ret; int i; char *cmdname; - int found = 0; + boolean_t found = B_FALSE; + char *str; (void) setlocale(LC_ALL, ""); (void) textdomain(TEXT_DOMAIN); @@ -3649,6 +3799,12 @@ main(int argc, char **argv) cmdname = argv[1]; + /* Handle special case of pool create for staging history */ + if (strcmp(cmdname, "create") != 0) + zpool_stage_history(g_zfs, argc, argv, B_FALSE, B_FALSE); + else + zpool_stage_history(g_zfs, argc, argv, B_FALSE, B_TRUE); + /* * Special case '-?' */ @@ -3661,7 +3817,7 @@ main(int argc, char **argv) if (find_command_idx(cmdname, &i) == 0) { current_command = &command_table[i]; ret = command_table[i].func(argc - 1, argv + 1); - found++; + found = B_TRUE; } /* @@ -3674,7 +3830,28 @@ main(int argc, char **argv) return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf)); } - if (!found) { + /* is this a zpool property=value */ + if (found == B_FALSE && ((str = strchr(cmdname, '=')) != NULL)) { + *str = '\0'; + if (zpool_prop_iter(propset_cb, cmdname, + B_FALSE) != ZFS_PROP_INVAL) { + if (find_command_idx("set", &i) == 0) { + *str = '='; + current_command = &command_table[i]; + ret = command_table[i].func(argc, argv); + found = B_TRUE; + } + } + + if (found == B_FALSE) { + *str = '='; + (void) fprintf(stderr, + gettext("invalid property '%s'\n"), cmdname); + found = B_TRUE; + } + } + + if (found == B_FALSE) { (void) fprintf(stderr, gettext("unrecognized " "command '%s'\n"), cmdname); usage(B_FALSE); diff --git a/usr/src/cmd/ztest/ztest.c b/usr/src/cmd/ztest/ztest.c index 04f97821f9..289108f605 100644 --- a/usr/src/cmd/ztest/ztest.c +++ b/usr/src/cmd/ztest/ztest.c @@ -1089,7 +1089,7 @@ ztest_vdev_LUN_growth(ztest_args_t *za) /* ARGSUSED */ static void -ztest_create_cb(objset_t *os, void *arg, dmu_tx_t *tx) +ztest_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx) { /* * Create the directory object. |