Update 'zfs send' documentation
[zfs.git] / cmd / zfs / zfs_main.c
index 9516697..b6dc6d4 100644 (file)
@@ -238,7 +238,7 @@ get_usage(zfs_help_t idx)
        case HELP_ROLLBACK:
                return (gettext("\trollback [-rRf] <snapshot>\n"));
        case HELP_SEND:
-               return (gettext("\tsend [-RDp] [-[iI] snapshot] <snapshot>\n"));
+               return (gettext("\tsend [-vRDp] [-[iI] snapshot] <snapshot>\n"));
        case HELP_SET:
                return (gettext("\tset <property=value> "
                    "<filesystem|volume|snapshot> ...\n"));
@@ -546,6 +546,7 @@ finish_progress(char *done)
        free(pt_header);
        pt_header = NULL;
 }
+
 /*
  * zfs clone [-p] [-o prop=value] ... <snap> <fs | vol>
  *
@@ -671,7 +672,7 @@ zfs_do_create(int argc, char **argv)
 {
        zfs_type_t type = ZFS_TYPE_FILESYSTEM;
        zfs_handle_t *zhp = NULL;
-       uint64_t volsize;
+       uint64_t volsize = 0;
        int c;
        boolean_t noreserve = B_FALSE;
        boolean_t bflag = B_FALSE;
@@ -764,7 +765,7 @@ zfs_do_create(int argc, char **argv)
                zfs_prop_t resv_prop;
                char *strval;
 
-               if (p = strchr(argv[0], '/'))
+               if ((p = strchr(argv[0], '/')))
                        *p = '\0';
                zpool_handle = zpool_open(g_zfs, argv[0]);
                if (p != NULL)
@@ -1682,7 +1683,7 @@ upgrade_set_callback(zfs_handle_t *zhp, void *data)
        if (version < cb->cb_version) {
                char verstr[16];
                (void) snprintf(verstr, sizeof (verstr),
-                   "%llu", cb->cb_version);
+                   "%llu", (u_longlong_t)cb->cb_version);
                if (cb->cb_lastfs[0] && !same_pool(zhp, cb->cb_lastfs)) {
                        /*
                         * If they did "zfs upgrade -a", then we could
@@ -1720,7 +1721,7 @@ zfs_do_upgrade(int argc, char **argv)
        boolean_t showversions = B_FALSE;
        int ret;
        upgrade_cbdata_t cb = { 0 };
-       char c;
+       signed char c;
        int flags = ZFS_ITER_ARGS_CAN_BE_PATHS;
 
        /* check options */
@@ -1789,11 +1790,11 @@ zfs_do_upgrade(int argc, char **argv)
                ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_FILESYSTEM,
                    NULL, NULL, 0, upgrade_set_callback, &cb);
                (void) printf(gettext("%llu filesystems upgraded\n"),
-                   cb.cb_numupgraded);
+                   (u_longlong_t)cb.cb_numupgraded);
                if (cb.cb_numsamegraded) {
                        (void) printf(gettext("%llu filesystems already at "
                            "this version\n"),
-                           cb.cb_numsamegraded);
+                           (u_longlong_t)cb.cb_numsamegraded);
                }
                if (cb.cb_numfailed != 0)
                        ret = 1;
@@ -1878,16 +1879,6 @@ zfs_do_userspace(int argc, char **argv)
        zfs_userquota_prop_t p;
        int error;
 
-       /*
-        * Try the python version.  If the execv fails, we'll continue
-        * and do a simplistic implementation.
-        */
-       (void) execv(pypath, argv-1);
-
-       (void) printf("internal error: %s not found\n"
-           "falling back on built-in implementation, "
-           "some features will not work\n", pypath);
-
        if ((zhp = zfs_open(g_zfs, argv[argc-1], ZFS_TYPE_DATASET)) == NULL)
                return (1);
 
@@ -1957,9 +1948,9 @@ print_header(zprop_list_t *pl)
                if (pl->pl_next == NULL && !right_justify)
                        (void) printf("%s", header);
                else if (right_justify)
-                       (void) printf("%*s", pl->pl_width, header);
+                       (void) printf("%*s", (int)pl->pl_width, header);
                else
-                       (void) printf("%-*s", pl->pl_width, header);
+                       (void) printf("%-*s", (int)pl->pl_width, header);
        }
 
        (void) printf("\n");
@@ -2550,7 +2541,7 @@ zfs_do_set(int argc, char **argv)
                usage(B_FALSE);
        }
 
-       ret = zfs_for_each(argc - 2, argv + 2, NULL,
+       ret = zfs_for_each(argc - 2, argv + 2, 0,
            ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, &cb);
 
        return (ret);
@@ -2567,7 +2558,7 @@ zfs_do_snapshot(int argc, char **argv)
 {
        boolean_t recursive = B_FALSE;
        int ret;
-       char c;
+       signed char c;
        nvlist_t *props;
 
        if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
@@ -3137,11 +3128,11 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
                shared_nfs = zfs_is_shared_nfs(zhp, NULL);
                shared_smb = zfs_is_shared_smb(zhp, NULL);
 
-               if (shared_nfs && shared_smb ||
-                   (shared_nfs && strcmp(shareopts, "on") == 0 &&
-                   strcmp(smbshareopts, "off") == 0) ||
-                   (shared_smb && strcmp(smbshareopts, "on") == 0 &&
-                   strcmp(shareopts, "off") == 0)) {
+               if ((shared_nfs && shared_smb) ||
+                   ((shared_nfs && strcmp(shareopts, "on") == 0) &&
+                   (strcmp(smbshareopts, "off") == 0)) ||
+                   ((shared_smb && strcmp(smbshareopts, "on") == 0) &&
+                   (strcmp(shareopts, "off") == 0))) {
                        if (!explicit)
                                return (0);
 
@@ -3238,7 +3229,7 @@ append_options(char *mntopts, char *newopts)
        /* original length plus new string to append plus 1 for the comma */
        if (len + 1 + strlen(newopts) >= MNT_LINE_MAX) {
                (void) fprintf(stderr, gettext("the opts argument for "
-                   "'%c' option is too long (more than %d chars)\n"),
+                   "'%s' option is too long (more than %d chars)\n"),
                    "-o", MNT_LINE_MAX);
                usage(B_FALSE);
        }
@@ -3259,7 +3250,7 @@ share_mount(int op, int argc, char **argv)
        int flags = 0;
 
        /* check options */
-       while ((c = getopt(argc, argv, op == OP_MOUNT ? ":avo:O" : "a"))
+       while ((c = getopt(argc, argv, op == OP_MOUNT ? ":avo:" : "a"))
            != -1) {
                switch (c) {
                case 'a':
@@ -3282,9 +3273,6 @@ share_mount(int op, int argc, char **argv)
                        append_options(options, optarg);
                        break;
 
-               case 'O':
-                       flags |= MS_OVERLAY;
-                       break;
                case ':':
                        (void) fprintf(stderr, gettext("missing argument for "
                            "'%c' option\n"), optopt);
@@ -3352,7 +3340,7 @@ share_mount(int op, int argc, char **argv)
                }
 
                /*
-                * When mount is given no arguments, go through /etc/mnttab and
+                * When mount is given no arguments, go through /etc/mtab and
                 * display any active ZFS mounts.  We hide any snapshots, since
                 * they are controlled automatically.
                 */
@@ -3430,7 +3418,7 @@ unshare_unmount_compare(const void *larg, const void *rarg, void *unused)
 
 /*
  * Convenience routine used by zfs_do_umount() and manual_unmount().  Given an
- * absolute path, find the entry /etc/mnttab, verify that its a ZFS filesystem,
+ * absolute path, find the entry /etc/mtab, verify that its a ZFS filesystem,
  * and unmount it appropriately.
  */
 static int
@@ -3444,7 +3432,7 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
        ino_t path_inode;
 
        /*
-        * Search for the path in /etc/mnttab.  Rather than looking for the
+        * Search for the path in /etc/mtab.  Rather than looking for the
         * specific path, which can be fooled by non-standard paths (i.e. ".."
         * or "//"), we stat() the path and search for the corresponding
         * (major,minor) device pair.
@@ -3471,7 +3459,7 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
                            "currently mounted\n"), cmdname, path);
                        return (1);
                }
-               (void) fprintf(stderr, gettext("warning: %s not in mnttab\n"),
+               (void) fprintf(stderr, gettext("warning: %s not in mtab\n"),
                    path);
                if ((ret = umount2(path, flags)) != 0)
                        (void) fprintf(stderr, gettext("%s: %s\n"), path,
@@ -3513,8 +3501,8 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
                    strcmp(smbshare_prop, "off") == 0) {
                        (void) fprintf(stderr, gettext("cannot unshare "
                            "'%s': legacy share\n"), path);
-                       (void) fprintf(stderr, gettext("use "
-                           "unshare(1M) to unshare this filesystem\n"));
+                       (void) fprintf(stderr, gettext("use exportfs(8) "
+                           "or smbcontrol(1) to unshare this filesystem\n"));
                } else if (!zfs_is_shared(zhp)) {
                        (void) fprintf(stderr, gettext("cannot unshare '%s': "
                            "not currently shared\n"), path);
@@ -3533,7 +3521,7 @@ unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual)
                        (void) fprintf(stderr, gettext("cannot unmount "
                            "'%s': legacy mountpoint\n"),
                            zfs_get_name(zhp));
-                       (void) fprintf(stderr, gettext("use umount(1M) "
+                       (void) fprintf(stderr, gettext("use umount(8) "
                            "to unmount this filesystem\n"));
                } else {
                        ret = zfs_unmountall(zhp, flags);
@@ -3583,8 +3571,8 @@ unshare_unmount(int op, int argc, char **argv)
                /*
                 * We could make use of zfs_for_each() to walk all datasets in
                 * the system, but this would be very inefficient, especially
-                * since we would have to linearly search /etc/mnttab for each
-                * one.  Instead, do one pass through /etc/mnttab looking for
+                * since we would have to linearly search /etc/mtab for each
+                * one.  Instead, do one pass through /etc/mtab looking for
                 * zfs entries and call zfs_unmount() for each one.
                 *
                 * Things get a little tricky if the administrator has created
@@ -3596,7 +3584,7 @@ unshare_unmount(int op, int argc, char **argv)
                 */
                struct mnttab entry;
                uu_avl_pool_t *pool;
-               uu_avl_t *tree;
+               uu_avl_t *tree = NULL;
                unshare_unmount_node_t *node;
                uu_avl_index_t idx;
                uu_avl_walk_t *walk;
@@ -3829,141 +3817,6 @@ zfs_do_python(int argc, char **argv)
        return (-1);
 }
 
-/*
- * Called when invoked as /etc/fs/zfs/mount.  Do the mount if the mountpoint is
- * 'legacy'.  Otherwise, complain that use should be using 'zfs mount'.
- */
-static int
-manual_mount(int argc, char **argv)
-{
-       zfs_handle_t *zhp;
-       char mountpoint[ZFS_MAXPROPLEN];
-       char mntopts[MNT_LINE_MAX] = { '\0' };
-       int ret;
-       int c;
-       int flags = 0;
-       char *dataset, *path;
-
-       /* check options */
-       while ((c = getopt(argc, argv, ":mo:O")) != -1) {
-               switch (c) {
-               case 'o':
-                       (void) strlcpy(mntopts, optarg, sizeof (mntopts));
-                       break;
-               case 'O':
-                       flags |= MS_OVERLAY;
-                       break;
-               case 'm':
-                       flags |= MS_NOMNTTAB;
-                       break;
-               case ':':
-                       (void) fprintf(stderr, gettext("missing argument for "
-                           "'%c' option\n"), optopt);
-                       usage(B_FALSE);
-                       break;
-               case '?':
-                       (void) fprintf(stderr, gettext("invalid option '%c'\n"),
-                           optopt);
-                       (void) fprintf(stderr, gettext("usage: mount [-o opts] "
-                           "<path>\n"));
-                       return (2);
-               }
-       }
-
-       argc -= optind;
-       argv += optind;
-
-       /* check that we only have two arguments */
-       if (argc != 2) {
-               if (argc == 0)
-                       (void) fprintf(stderr, gettext("missing dataset "
-                           "argument\n"));
-               else if (argc == 1)
-                       (void) fprintf(stderr,
-                           gettext("missing mountpoint argument\n"));
-               else
-                       (void) fprintf(stderr, gettext("too many arguments\n"));
-               (void) fprintf(stderr, "usage: mount <dataset> <mountpoint>\n");
-               return (2);
-       }
-
-       dataset = argv[0];
-       path = argv[1];
-
-       /* try to open the dataset */
-       if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_FILESYSTEM)) == NULL)
-               return (1);
-
-       (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint,
-           sizeof (mountpoint), NULL, NULL, 0, B_FALSE);
-
-       /* check for legacy mountpoint and complain appropriately */
-       ret = 0;
-       if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) {
-               if (mount(dataset, path, MS_OPTIONSTR | flags, MNTTYPE_ZFS,
-                   NULL, 0, mntopts, sizeof (mntopts)) != 0) {
-                       (void) fprintf(stderr, gettext("mount failed: %s\n"),
-                           strerror(errno));
-                       ret = 1;
-               }
-       } else {
-               (void) fprintf(stderr, gettext("filesystem '%s' cannot be "
-                   "mounted using 'mount -F zfs'\n"), dataset);
-               (void) fprintf(stderr, gettext("Use 'zfs set mountpoint=%s' "
-                   "instead.\n"), path);
-               (void) fprintf(stderr, gettext("If you must use 'mount -F zfs' "
-                   "or /etc/vfstab, use 'zfs set mountpoint=legacy'.\n"));
-               (void) fprintf(stderr, gettext("See zfs(1M) for more "
-                   "information.\n"));
-               ret = 1;
-       }
-
-       return (ret);
-}
-
-/*
- * Called when invoked as /etc/fs/zfs/umount.  Unlike a manual mount, we allow
- * unmounts of non-legacy filesystems, as this is the dominant administrative
- * interface.
- */
-static int
-manual_unmount(int argc, char **argv)
-{
-       int flags = 0;
-       int c;
-
-       /* check options */
-       while ((c = getopt(argc, argv, "f")) != -1) {
-               switch (c) {
-               case 'f':
-                       flags = MS_FORCE;
-                       break;
-               case '?':
-                       (void) fprintf(stderr, gettext("invalid option '%c'\n"),
-                           optopt);
-                       (void) fprintf(stderr, gettext("usage: unmount [-f] "
-                           "<path>\n"));
-                       return (2);
-               }
-       }
-
-       argc -= optind;
-       argv += optind;
-
-       /* check arguments */
-       if (argc != 1) {
-               if (argc == 0)
-                       (void) fprintf(stderr, gettext("missing path "
-                           "argument\n"));
-               else
-                       (void) fprintf(stderr, gettext("too many arguments\n"));
-               (void) fprintf(stderr, gettext("usage: unmount [-f] <path>\n"));
-               return (2);
-       }
-
-       return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE));
-}
-
 static int
 find_command_idx(char *command, int *idx)
 {
@@ -4035,7 +3888,7 @@ zfs_do_diff(int argc, char **argv)
        if (copy == NULL)
                usage(B_FALSE);
 
-       if (atp = strchr(copy, '@'))
+       if ((atp = strchr(copy, '@')))
                *atp = '\0';
 
        if ((zhp = zfs_open(g_zfs, copy, ZFS_TYPE_FILESYSTEM)) == NULL)
@@ -4060,8 +3913,7 @@ int
 main(int argc, char **argv)
 {
        int ret;
-       int i;
-       char *progname;
+       int i = 0;
        char *cmdname;
 
        (void) setlocale(LC_ALL, "");
@@ -4069,17 +3921,6 @@ main(int argc, char **argv)
 
        opterr = 0;
 
-       if ((g_zfs = libzfs_init()) == NULL) {
-               (void) fprintf(stderr, gettext("internal error: failed to "
-                   "initialize ZFS library\n"));
-               return (1);
-       }
-
-       zpool_set_history_str("zfs", argc, argv, history_str);
-       verify(zpool_stage_history(g_zfs, history_str) == 0);
-
-       libzfs_print_on_error(g_zfs, B_TRUE);
-
        if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) {
                (void) fprintf(stderr, gettext("internal error: unable to "
                    "open %s\n"), MNTTAB);
@@ -4087,66 +3928,64 @@ main(int argc, char **argv)
        }
 
        /*
-        * This command also doubles as the /etc/fs mount and unmount program.
-        * Determine if we should take this behavior based on argv[0].
+        * Make sure the user has specified some command.
         */
-       progname = basename(argv[0]);
-       if (strcmp(progname, "mount") == 0) {
-               ret = manual_mount(argc, argv);
-       } else if (strcmp(progname, "umount") == 0) {
-               ret = manual_unmount(argc, argv);
-       } else {
-               /*
-                * Make sure the user has specified some command.
-                */
-               if (argc < 2) {
-                       (void) fprintf(stderr, gettext("missing command\n"));
-                       usage(B_FALSE);
-               }
+       if (argc < 2) {
+               (void) fprintf(stderr, gettext("missing command\n"));
+               usage(B_FALSE);
+       }
 
-               cmdname = argv[1];
+       cmdname = argv[1];
 
-               /*
-                * The 'umount' command is an alias for 'unmount'
-                */
-               if (strcmp(cmdname, "umount") == 0)
-                       cmdname = "unmount";
+       /*
+        * The 'umount' command is an alias for 'unmount'
+        */
+       if (strcmp(cmdname, "umount") == 0)
+               cmdname = "unmount";
 
-               /*
-                * The 'recv' command is an alias for 'receive'
-                */
-               if (strcmp(cmdname, "recv") == 0)
-                       cmdname = "receive";
+       /*
+        * The 'recv' command is an alias for 'receive'
+        */
+       if (strcmp(cmdname, "recv") == 0)
+               cmdname = "receive";
 
-               /*
-                * Special case '-?'
-                */
-               if (strcmp(cmdname, "-?") == 0)
-                       usage(B_TRUE);
+       /*
+        * Special case '-?'
+        */
+       if ((strcmp(cmdname, "-?") == 0) ||
+           (strcmp(cmdname, "--help") == 0))
+               usage(B_TRUE);
 
-               /*
-                * Run the appropriate command.
-                */
-               libzfs_mnttab_cache(g_zfs, B_TRUE);
-               if (find_command_idx(cmdname, &i) == 0) {
-                       current_command = &command_table[i];
-                       ret = command_table[i].func(argc - 1, argv + 1);
-               } else if (strchr(cmdname, '=') != NULL) {
-                       verify(find_command_idx("set", &i) == 0);
-                       current_command = &command_table[i];
-                       ret = command_table[i].func(argc, argv);
-               } else {
-                       (void) fprintf(stderr, gettext("unrecognized "
-                           "command '%s'\n"), cmdname);
-                       usage(B_FALSE);
-               }
-               libzfs_mnttab_cache(g_zfs, B_FALSE);
-       }
+       if ((g_zfs = libzfs_init()) == NULL)
+               return (1);
 
-       (void) fclose(mnttab_file);
+       zpool_set_history_str("zfs", argc, argv, history_str);
+       verify(zpool_stage_history(g_zfs, history_str) == 0);
+
+       libzfs_print_on_error(g_zfs, B_TRUE);
 
+       /*
+        * Run the appropriate command.
+        */
+       libzfs_mnttab_cache(g_zfs, B_TRUE);
+       if (find_command_idx(cmdname, &i) == 0) {
+               current_command = &command_table[i];
+               ret = command_table[i].func(argc - 1, argv + 1);
+       } else if (strchr(cmdname, '=') != NULL) {
+               verify(find_command_idx("set", &i) == 0);
+               current_command = &command_table[i];
+               ret = command_table[i].func(argc, argv);
+       } else {
+               (void) fprintf(stderr, gettext("unrecognized "
+                   "command '%s'\n"), cmdname);
+               usage(B_FALSE);
+               ret = 1;
+       }
+       libzfs_mnttab_cache(g_zfs, B_FALSE);
        libzfs_fini(g_zfs);
 
+       (void) fclose(mnttab_file);
+
        /*
         * The 'ZFS_ABORT' environment variable causes us to dump core on exit
         * for the purposes of running ::findleaks.