Remove autotools products
[zfs.git] / cmd / zpool / zpool_main.c
index b1b71ac..21548c8 100644 (file)
@@ -21,6 +21,9 @@
 
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
  */
 
 #include <assert.h>
@@ -66,6 +69,8 @@ static int zpool_do_online(int, char **);
 static int zpool_do_offline(int, char **);
 static int zpool_do_clear(int, char **);
 
+static int zpool_do_reguid(int, char **);
+
 static int zpool_do_attach(int, char **);
 static int zpool_do_detach(int, char **);
 static int zpool_do_replace(int, char **);
@@ -125,7 +130,8 @@ typedef enum {
        HELP_EVENTS,
        HELP_GET,
        HELP_SET,
-       HELP_SPLIT
+       HELP_SPLIT,
+       HELP_REGUID
 } zpool_help_t;
 
 
@@ -169,6 +175,7 @@ static zpool_command_t command_table[] = {
        { "import",     zpool_do_import,        HELP_IMPORT             },
        { "export",     zpool_do_export,        HELP_EXPORT             },
        { "upgrade",    zpool_do_upgrade,       HELP_UPGRADE            },
+       { "reguid",     zpool_do_reguid,        HELP_REGUID             },
        { NULL },
        { "history",    zpool_do_history,       HELP_HISTORY            },
        { "events",     zpool_do_events,        HELP_EVENTS             },
@@ -241,7 +248,7 @@ get_usage(zpool_help_t idx) {
                    "\tupgrade -v\n"
                    "\tupgrade [-V version] <-a | pool ...>\n"));
        case HELP_EVENTS:
-               return (gettext("\tevents [-vfc]\n"));
+               return (gettext("\tevents [-vHfc]\n"));
        case HELP_GET:
                return (gettext("\tget <\"all\" | property[,...]> "
                    "<pool> ...\n"));
@@ -251,6 +258,8 @@ get_usage(zpool_help_t idx) {
                return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
                    "\t    [-o property=value] <pool> <newpool> "
                    "[<device> ...]\n"));
+       case HELP_REGUID:
+               return (gettext("\treguid <pool>\n"));
        }
 
        abort();
@@ -488,7 +497,7 @@ zpool_do_add(int argc, char **argv)
        }
 
        /* pass off to get_vdev_spec for processing */
-       nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
+       nvroot = make_root_vdev(zhp, NULL, force, !force, B_FALSE, dryrun,
            argc, argv);
        if (nvroot == NULL) {
                zpool_close(zhp);
@@ -688,7 +697,7 @@ zpool_do_create(int argc, char **argv)
        }
 
        /* pass off to get_vdev_spec for bulk processing */
-       nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
+       nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun,
            argc - 1, argv + 1);
        if (nvroot == NULL)
                goto errout;
@@ -716,9 +725,7 @@ zpool_do_create(int argc, char **argv)
            (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
            strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
                char buf[MAXPATHLEN];
-#ifdef HAVE_ZPL
                DIR *dirp;
-#endif
 
                if (mountpoint && mountpoint[0] != '/') {
                        (void) fprintf(stderr, gettext("invalid mountpoint "
@@ -743,7 +750,6 @@ zpool_do_create(int argc, char **argv)
                                    mountpoint);
                }
 
-#ifdef HAVE_ZPL
                if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
                        (void) fprintf(stderr, gettext("mountpoint '%s' : "
                            "%s\n"), buf, strerror(errno));
@@ -766,7 +772,6 @@ zpool_do_create(int argc, char **argv)
                                goto errout;
                        }
                }
-#endif /* HAVE_ZPL */
        }
 
        if (dryrun) {
@@ -797,12 +802,8 @@ zpool_do_create(int argc, char **argv)
                                            zfs_prop_to_name(
                                            ZFS_PROP_MOUNTPOINT),
                                            mountpoint) == 0);
-#ifdef HAVE_ZPL
                                if (zfs_mount(pool, NULL, 0) == 0)
                                        ret = zfs_shareall(pool);
-#else
-                               ret = 0;
-#endif /* HAVE_ZPL */
                                zfs_close(pool);
                        }
                } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
@@ -1342,6 +1343,7 @@ show_import(nvlist_t *config)
        const char *health;
        uint_t vsc;
        int namewidth;
+       char *comment;
 
        verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
            &name) == 0);
@@ -1358,9 +1360,9 @@ show_import(nvlist_t *config)
 
        reason = zpool_import_status(config, &msgid);
 
-       (void) printf(gettext("  pool: %s\n"), name);
-       (void) printf(gettext("    id: %llu\n"), (u_longlong_t)guid);
-       (void) printf(gettext(" state: %s"), health);
+       (void) printf(gettext("   pool: %s\n"), name);
+       (void) printf(gettext("     id: %llu\n"), (u_longlong_t)guid);
+       (void) printf(gettext("  state: %s"), health);
        if (pool_state == POOL_STATE_DESTROYED)
                (void) printf(gettext(" (DESTROYED)"));
        (void) printf("\n");
@@ -1369,58 +1371,59 @@ show_import(nvlist_t *config)
        case ZPOOL_STATUS_MISSING_DEV_R:
        case ZPOOL_STATUS_MISSING_DEV_NR:
        case ZPOOL_STATUS_BAD_GUID_SUM:
-               (void) printf(gettext("status: One or more devices are missing "
-                   "from the system.\n"));
+               (void) printf(gettext(" status: One or more devices are "
+                   "missing from the system.\n"));
                break;
 
        case ZPOOL_STATUS_CORRUPT_LABEL_R:
        case ZPOOL_STATUS_CORRUPT_LABEL_NR:
-               (void) printf(gettext("status: One or more devices contains "
+               (void) printf(gettext(" status: One or more devices contains "
                    "corrupted data.\n"));
                break;
 
        case ZPOOL_STATUS_CORRUPT_DATA:
-               (void) printf(gettext("status: The pool data is corrupted.\n"));
+               (void) printf(
+                   gettext(" status: The pool data is corrupted.\n"));
                break;
 
        case ZPOOL_STATUS_OFFLINE_DEV:
-               (void) printf(gettext("status: One or more devices "
+               (void) printf(gettext(" status: One or more devices "
                    "are offlined.\n"));
                break;
 
        case ZPOOL_STATUS_CORRUPT_POOL:
-               (void) printf(gettext("status: The pool metadata is "
+               (void) printf(gettext(" status: The pool metadata is "
                    "corrupted.\n"));
                break;
 
        case ZPOOL_STATUS_VERSION_OLDER:
-               (void) printf(gettext("status: The pool is formatted using an "
+               (void) printf(gettext(" status: The pool is formatted using an "
                    "older on-disk version.\n"));
                break;
 
        case ZPOOL_STATUS_VERSION_NEWER:
-               (void) printf(gettext("status: The pool is formatted using an "
+               (void) printf(gettext(" status: The pool is formatted using an "
                    "incompatible version.\n"));
                break;
 
        case ZPOOL_STATUS_HOSTID_MISMATCH:
-               (void) printf(gettext("status: The pool was last accessed by "
+               (void) printf(gettext(" status: The pool was last accessed by "
                    "another system.\n"));
                break;
 
        case ZPOOL_STATUS_FAULTED_DEV_R:
        case ZPOOL_STATUS_FAULTED_DEV_NR:
-               (void) printf(gettext("status: One or more devices are "
+               (void) printf(gettext(" status: One or more devices are "
                    "faulted.\n"));
                break;
 
        case ZPOOL_STATUS_BAD_LOG:
-               (void) printf(gettext("status: An intent log record cannot be "
+               (void) printf(gettext(" status: An intent log record cannot be "
                    "read.\n"));
                break;
 
        case ZPOOL_STATUS_RESILVERING:
-               (void) printf(gettext("status: One or more devices were being "
+               (void) printf(gettext(" status: One or more devices were being "
                    "resilvered.\n"));
                break;
 
@@ -1436,26 +1439,26 @@ show_import(nvlist_t *config)
         */
        if (vs->vs_state == VDEV_STATE_HEALTHY) {
                if (reason == ZPOOL_STATUS_VERSION_OLDER)
-                       (void) printf(gettext("action: The pool can be "
+                       (void) printf(gettext(" action: The pool can be "
                            "imported using its name or numeric identifier, "
                            "though\n\tsome features will not be available "
                            "without an explicit 'zpool upgrade'.\n"));
                else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH)
-                       (void) printf(gettext("action: The pool can be "
+                       (void) printf(gettext(" action: The pool can be "
                            "imported using its name or numeric "
                            "identifier and\n\tthe '-f' flag.\n"));
                else
-                       (void) printf(gettext("action: The pool can be "
+                       (void) printf(gettext(" action: The pool can be "
                            "imported using its name or numeric "
                            "identifier.\n"));
        } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
-               (void) printf(gettext("action: The pool can be imported "
+               (void) printf(gettext(" action: The pool can be imported "
                    "despite missing or damaged devices.  The\n\tfault "
                    "tolerance of the pool may be compromised if imported.\n"));
        } else {
                switch (reason) {
                case ZPOOL_STATUS_VERSION_NEWER:
-                       (void) printf(gettext("action: The pool cannot be "
+                       (void) printf(gettext(" action: The pool cannot be "
                            "imported.  Access the pool on a system running "
                            "newer\n\tsoftware, or recreate the pool from "
                            "backup.\n"));
@@ -1463,16 +1466,20 @@ show_import(nvlist_t *config)
                case ZPOOL_STATUS_MISSING_DEV_R:
                case ZPOOL_STATUS_MISSING_DEV_NR:
                case ZPOOL_STATUS_BAD_GUID_SUM:
-                       (void) printf(gettext("action: The pool cannot be "
+                       (void) printf(gettext(" action: The pool cannot be "
                            "imported. Attach the missing\n\tdevices and try "
                            "again.\n"));
                        break;
                default:
-                       (void) printf(gettext("action: The pool cannot be "
+                       (void) printf(gettext(" action: The pool cannot be "
                            "imported due to damaged devices or data.\n"));
                }
        }
 
+       /* Print the comment attached to the pool. */
+       if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
+               (void) printf(gettext("comment: %s\n"), comment);
+
        /*
         * If the state is "closed" or "can't open", and the aux state
         * is "corrupt data":
@@ -1490,10 +1497,10 @@ show_import(nvlist_t *config)
        }
 
        if (msgid != NULL)
-               (void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
+               (void) printf(gettext("   see: http://zfsonlinux.org/msg/%s\n"),
                    msgid);
 
-       (void) printf(gettext("config:\n\n"));
+       (void) printf(gettext(" config:\n\n"));
 
        namewidth = max_width(NULL, nvroot, 0, 0);
        if (namewidth < 10)
@@ -1541,7 +1548,9 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
 
                if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
                    &hostid) == 0) {
-                       if ((unsigned long)hostid != gethostid()) {
+                       unsigned long system_hostid = gethostid() & 0xffffffff;
+
+                       if ((unsigned long)hostid != system_hostid) {
                                char *hostname;
                                uint64_t timestamp;
                                time_t t;
@@ -1579,14 +1588,12 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
        if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
                return (1);
 
-#if HAVE_ZPL
        if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
            !(flags & ZFS_IMPORT_ONLY) &&
            zpool_enable_datasets(zhp, mntopts, 0) != 0) {
                zpool_close(zhp);
                return (1);
        }
-#endif /* HAVE_ZPL */
 
        zpool_close(zhp);
        return (0);
@@ -2094,10 +2101,15 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
                return;
 
        for (c = 0; c < children; c++) {
-               uint64_t ishole = B_FALSE;
+               uint64_t ishole = B_FALSE, islog = B_FALSE;
 
-               if (nvlist_lookup_uint64(newchild[c],
-                   ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
+               (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
+                   &ishole);
+
+               (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
+                   &islog);
+
+               if (ishole || islog)
                        continue;
 
                vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
@@ -2107,6 +2119,31 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
        }
 
        /*
+        * Log device section
+        */
+
+       if (num_logs(newnv) > 0) {
+               (void) printf("%-*s      -      -      -      -      -      "
+                   "-\n", cb->cb_namewidth, "logs");
+
+               for (c = 0; c < children; c++) {
+                       uint64_t islog = B_FALSE;
+                       (void) nvlist_lookup_uint64(newchild[c],
+                           ZPOOL_CONFIG_IS_LOG, &islog);
+
+                       if (islog) {
+                               vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
+                                   B_FALSE);
+                               print_vdev_stats(zhp, vname, oldnv ?
+                                   oldchild[c] : NULL, newchild[c],
+                                   cb, depth + 2);
+                               free(vname);
+                       }
+               }
+
+       }
+
+       /*
         * Include level 2 ARC devices in iostat output
         */
        if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
@@ -2183,11 +2220,30 @@ print_iostat(zpool_handle_t *zhp, void *data)
        return (0);
 }
 
+static int
+get_columns(void)
+{
+       struct winsize ws;
+       int columns = 80;
+       int error;
+
+       if (isatty(STDOUT_FILENO)) {
+               error = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
+               if (error == 0)
+                       columns = ws.ws_col;
+       } else {
+               columns = 999;
+       }
+
+       return columns;
+}
+
 int
 get_namewidth(zpool_handle_t *zhp, void *data)
 {
        iostat_cbdata_t *cb = data;
        nvlist_t *config, *nvroot;
+       int columns;
 
        if ((config = zpool_get_config(zhp, NULL)) != NULL) {
                verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
@@ -2195,17 +2251,20 @@ get_namewidth(zpool_handle_t *zhp, void *data)
                if (!cb->cb_verbose)
                        cb->cb_namewidth = strlen(zpool_get_name(zhp));
                else
-                       cb->cb_namewidth = max_width(zhp, nvroot, 0, 0);
+                       cb->cb_namewidth = max_width(zhp, nvroot, 0,
+                           cb->cb_namewidth);
        }
 
        /*
-        * The width must fall into the range [10,38].  The upper limit is the
-        * maximum we can have and still fit in 80 columns.
+        * The width must be at least 10, but may be as large as the
+        * column width - 42 so that we can still fit in one line.
         */
+       columns = get_columns();
+
        if (cb->cb_namewidth < 10)
                cb->cb_namewidth = 10;
-       if (cb->cb_namewidth > 38)
-               cb->cb_namewidth = 38;
+       if (cb->cb_namewidth > columns - 42)
+               cb->cb_namewidth = columns - 42;
 
        return (0);
 }
@@ -2366,42 +2425,48 @@ zpool_do_iostat(int argc, char **argv)
                pool_list_update(list);
 
                if ((npools = pool_list_count(list)) == 0)
-                       break;
-
-               /*
-                * Refresh all statistics.  This is done as an explicit step
-                * before calculating the maximum name width, so that any
-                * configuration changes are properly accounted for.
-                */
-               (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
+                       (void) fprintf(stderr, gettext("no pools available\n"));
+               else {
+                       /*
+                        * Refresh all statistics.  This is done as an
+                        * explicit step before calculating the maximum name
+                        * width, so that any * configuration changes are
+                        * properly accounted for.
+                        */
+                       (void) pool_list_iter(list, B_FALSE, refresh_iostat,
+                               &cb);
 
-               /*
-                * Iterate over all pools to determine the maximum width
-                * for the pool / device name column across all pools.
-                */
-               cb.cb_namewidth = 0;
-               (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
+                       /*
+                        * Iterate over all pools to determine the maximum width
+                        * for the pool / device name column across all pools.
+                        */
+                       cb.cb_namewidth = 0;
+                       (void) pool_list_iter(list, B_FALSE, get_namewidth,
+                               &cb);
 
-               if (timestamp_fmt != NODATE)
-                       print_timestamp(timestamp_fmt);
+                       if (timestamp_fmt != NODATE)
+                               print_timestamp(timestamp_fmt);
 
-               /*
-                * If it's the first time, or verbose mode, print the header.
-                */
-               if (++cb.cb_iteration == 1 || verbose)
-                       print_iostat_header(&cb);
+                       /*
+                        * If it's the first time, or verbose mode, print the
+                        * header.
+                        */
+                       if (++cb.cb_iteration == 1 || verbose)
+                               print_iostat_header(&cb);
 
-               (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
+                       (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
 
-               /*
-                * If there's more than one pool, and we're not in verbose mode
-                * (which prints a separator for us), then print a separator.
-                */
-               if (npools > 1 && !verbose)
-                       print_iostat_separator(&cb);
+                       /*
+                        * If there's more than one pool, and we're not in
+                        * verbose mode (which prints a separator for us),
+                        * then print a separator.
+                        */
+                       if (npools > 1 && !verbose)
+                               print_iostat_separator(&cb);
 
-               if (verbose)
-                       (void) printf("\n");
+                       if (verbose)
+                               (void) printf("\n");
+               }
 
                /*
                 * Flush the output so that redirection to a file isn't buffered
@@ -2600,10 +2665,12 @@ zpool_do_list(int argc, char **argv)
                ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
                    list_callback, &cb);
 
-               if (argc == 0 && cb.cb_first && !cb.cb_scripted) {
-                       (void) printf(gettext("no pools available\n"));
+               if (argc == 0 && cb.cb_first)
+                       (void) fprintf(stderr, gettext("no pools available\n"));
+               else if (argc && cb.cb_first) {
+                       /* cannot open the given pool */
                        zprop_free_list(cb.cb_proplist);
-                       return (0);
+                       return (1);
                }
 
                if (interval == 0)
@@ -2691,7 +2758,7 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing)
                return (1);
        }
 
-       nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
+       nvroot = make_root_vdev(zhp, NULL, force, B_FALSE, replacing, B_FALSE,
            argc, argv);
        if (nvroot == NULL) {
                zpool_close(zhp);
@@ -3151,6 +3218,52 @@ zpool_do_clear(int argc, char **argv)
        return (ret);
 }
 
+/*
+ * zpool reguid <pool>
+ */
+int
+zpool_do_reguid(int argc, char **argv)
+{
+       int c;
+       char *poolname;
+       zpool_handle_t *zhp;
+       int ret = 0;
+
+       /* check options */
+       while ((c = getopt(argc, argv, "")) != -1) {
+               switch (c) {
+               case '?':
+                       (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+                           optopt);
+                       usage(B_FALSE);
+               }
+       }
+
+       argc -= optind;
+       argv += optind;
+
+       /* get pool name and check number of arguments */
+       if (argc < 1) {
+               (void) fprintf(stderr, gettext("missing pool name\n"));
+               usage(B_FALSE);
+       }
+
+       if (argc > 1) {
+               (void) fprintf(stderr, gettext("too many arguments\n"));
+               usage(B_FALSE);
+       }
+
+       poolname = argv[0];
+       if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
+               return (1);
+
+       ret = zpool_reguid(zhp);
+
+       zpool_close(zhp);
+       return (ret);
+}
+
+
 typedef struct scrub_cbdata {
        int     cb_type;
        int     cb_argc;
@@ -3448,7 +3561,7 @@ print_dedup_stats(nvlist_t *config)
  *        pool: tank
  *     status: DEGRADED
  *     reason: One or more devices ...
- *         see: http://www.sun.com/msg/ZFS-xxxx-01
+ *         see: http://zfsonlinux.org/msg/ZFS-xxxx-01
  *     config:
  *             mirror          DEGRADED
  *                c1t0d0       OK
@@ -3656,7 +3769,7 @@ status_callback(zpool_handle_t *zhp, void *data)
        }
 
        if (msgid != NULL)
-               (void) printf(gettext("   see: http://www.sun.com/msg/%s\n"),
+               (void) printf(gettext("   see: http://zfsonlinux.org/msg/%s\n"),
                    msgid);
 
        if (config != NULL) {
@@ -3793,7 +3906,7 @@ zpool_do_status(int argc, char **argv)
                    status_callback, &cb);
 
                if (argc == 0 && cb.cb_count == 0)
-                       (void) printf(gettext("no pools available\n"));
+                       (void) fprintf(stderr, gettext("no pools available\n"));
                else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
                        (void) printf(gettext("all pools are healthy\n"));
 
@@ -4219,7 +4332,7 @@ zpool_do_history(int argc, char **argv)
            &cbdata);
 
        if (argc == 0 && cbdata.first == B_TRUE) {
-               (void) printf(gettext("no pools available\n"));
+               (void) fprintf(stderr, gettext("no pools available\n"));
                return (0);
        }
 
@@ -4228,6 +4341,7 @@ zpool_do_history(int argc, char **argv)
 
 typedef struct ev_opts {
        int verbose;
+       int scripted;
        int follow;
        int clear;
 } ev_opts_t;
@@ -4342,7 +4456,7 @@ zpool_do_events_nvprint(nvlist_t *nvl, int depth)
                        printf(gettext("(embedded nvlist)\n"));
                        (void) nvpair_value_nvlist(nvp, &cnv);
                        zpool_do_events_nvprint(cnv, depth + 8);
-                       printf(gettext("%*s(end %s)\n"), depth, "", name);
+                       printf(gettext("%*s(end %s)"), depth, "", name);
                        break;
 
                case DATA_TYPE_NVLIST_ARRAY: {
@@ -4472,7 +4586,8 @@ zpool_do_events_next(ev_opts_t *opts)
         cleanup_fd = open(ZFS_DEV, O_RDWR);
         VERIFY(cleanup_fd >= 0);
 
-       (void) printf(gettext("%-30s %s\n"), "TIME", "CLASS");
+       if (!opts->scripted)
+               (void) printf(gettext("%-30s %s\n"), "TIME", "CLASS");
 
        while (1) {
                ret = zpool_events_next(g_zfs, &nvl, &dropped,
@@ -4523,11 +4638,14 @@ zpool_do_events(int argc, char **argv)
        int c;
 
        /* check options */
-       while ((c = getopt(argc, argv, "vfc")) != -1) {
+       while ((c = getopt(argc, argv, "vHfc")) != -1) {
                switch (c) {
                case 'v':
                        opts.verbose = 1;
                        break;
+               case 'H':
+                       opts.scripted = 1;
+                       break;
                case 'f':
                        opts.follow = 1;
                        break;
@@ -4712,14 +4830,6 @@ main(int argc, char **argv)
        (void) setlocale(LC_ALL, "");
        (void) textdomain(TEXT_DOMAIN);
 
-       if ((g_zfs = libzfs_init()) == NULL) {
-               (void) fprintf(stderr, gettext("internal error: failed to "
-                   "initialize ZFS library\n"));
-               return (1);
-       }
-
-       libzfs_print_on_error(g_zfs, B_TRUE);
-
        opterr = 0;
 
        /*
@@ -4735,9 +4845,15 @@ main(int argc, char **argv)
        /*
         * Special case '-?'
         */
-       if (strcmp(cmdname, "-?") == 0)
+       if ((strcmp(cmdname, "-?") == 0) ||
+            strcmp(cmdname, "--help") == 0)
                usage(B_TRUE);
 
+       if ((g_zfs = libzfs_init()) == NULL)
+               return (1);
+
+       libzfs_print_on_error(g_zfs, B_TRUE);
+
        zpool_set_history_str("zpool", argc, argv, history_str);
        verify(zpool_stage_history(g_zfs, history_str) == 0);