1b179da01SKyle Evans /*- 2b179da01SKyle Evans * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 35952343eSKyle Evans * 45952343eSKyle Evans * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in> 55952343eSKyle Evans * All rights reserved. 65952343eSKyle Evans * 75952343eSKyle Evans * Redistribution and use in source and binary forms, with or without 85952343eSKyle Evans * modification, are permitted provided that the following conditions 95952343eSKyle Evans * are met: 105952343eSKyle Evans * 1. Redistributions of source code must retain the above copyright 115952343eSKyle Evans * notice, this list of conditions and the following disclaimer. 125952343eSKyle Evans * 2. Redistributions in binary form must reproduce the above copyright 135952343eSKyle Evans * notice, this list of conditions and the following disclaimer in the 145952343eSKyle Evans * documentation and/or other materials provided with the distribution. 155952343eSKyle Evans * 165952343eSKyle Evans * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 175952343eSKyle Evans * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 185952343eSKyle Evans * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 195952343eSKyle Evans * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 205952343eSKyle Evans * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 215952343eSKyle Evans * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 225952343eSKyle Evans * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 235952343eSKyle Evans * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 245952343eSKyle Evans * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 255952343eSKyle Evans * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 265952343eSKyle Evans * SUCH DAMAGE. 275952343eSKyle Evans */ 285952343eSKyle Evans 29b6e7c421SKyle Evans #include <sys/cdefs.h> 30b6e7c421SKyle Evans __FBSDID("$FreeBSD$"); 31b6e7c421SKyle Evans 325952343eSKyle Evans #include <sys/param.h> 335952343eSKyle Evans #include <sys/mount.h> 345952343eSKyle Evans #include <errno.h> 3583244ec1SKyle Evans #include <libutil.h> 365952343eSKyle Evans #include <stdbool.h> 375952343eSKyle Evans #include <stdio.h> 385952343eSKyle Evans #include <stdint.h> 395952343eSKyle Evans #include <stdlib.h> 405952343eSKyle Evans #include <string.h> 415952343eSKyle Evans #include <sysexits.h> 4283244ec1SKyle Evans #include <time.h> 435952343eSKyle Evans #include <unistd.h> 445952343eSKyle Evans 455952343eSKyle Evans #include <be.h> 465952343eSKyle Evans 47d694059fSKyle Evans #include "bectl.h" 48d694059fSKyle Evans 499e004b21SKyle Evans static int bectl_cmd_activate(int argc, char *argv[]); 509e004b21SKyle Evans static int bectl_cmd_create(int argc, char *argv[]); 519e004b21SKyle Evans static int bectl_cmd_destroy(int argc, char *argv[]); 529e004b21SKyle Evans static int bectl_cmd_export(int argc, char *argv[]); 539e004b21SKyle Evans static int bectl_cmd_import(int argc, char *argv[]); 54*3d1a1f2cSKyle Evans #if SOON 559e004b21SKyle Evans static int bectl_cmd_add(int argc, char *argv[]); 56*3d1a1f2cSKyle Evans #endif 579e004b21SKyle Evans static int bectl_cmd_mount(int argc, char *argv[]); 589e004b21SKyle Evans static int bectl_cmd_rename(int argc, char *argv[]); 599e004b21SKyle Evans static int bectl_cmd_unmount(int argc, char *argv[]); 605952343eSKyle Evans 61d694059fSKyle Evans libbe_handle_t *be; 625952343eSKyle Evans 63d694059fSKyle Evans int 645952343eSKyle Evans usage(bool explicit) 655952343eSKyle Evans { 6616a10da8SKyle Evans FILE *fp; 675952343eSKyle Evans 6816a10da8SKyle Evans fp = explicit ? stdout : stderr; 695952343eSKyle Evans fprintf(fp, 709e004b21SKyle Evans "usage:\tbectl ( -h | -? | subcommand [args...] )\n" 719e004b21SKyle Evans "\tbectl activate [-t] beName\n" 729e004b21SKyle Evans "\tbectl create [-e nonActiveBe | -e beName@snapshot] beName\n" 739e004b21SKyle Evans "\tbectl create beName@snapshot\n" 749e004b21SKyle Evans "\tbectl destroy [-F] beName | beName@snapshot⟩\n" 759e004b21SKyle Evans "\tbectl export sourceBe\n" 769e004b21SKyle Evans "\tbectl import targetBe\n" 77*3d1a1f2cSKyle Evans #if SOON 789e004b21SKyle Evans "\tbectl add (path)*\n" 79*3d1a1f2cSKyle Evans #endif 802a0b8dc2SKyle Evans "\tbectl jail [ -o key=value | -u key ]... bootenv\n" 819e004b21SKyle Evans "\tbectl list [-a] [-D] [-H] [-s]\n" 829e004b21SKyle Evans "\tbectl mount beName [mountpoint]\n" 839e004b21SKyle Evans "\tbectl rename origBeName newBeName\n" 84ad765da4SKyle Evans "\tbectl { ujail | unjail } ⟨jailID | jailName | bootenv)\n" 859e004b21SKyle Evans "\tbectl { umount | unmount } [-f] beName\n"); 865952343eSKyle Evans 875952343eSKyle Evans return (explicit ? 0 : EX_USAGE); 885952343eSKyle Evans } 895952343eSKyle Evans 905952343eSKyle Evans 915952343eSKyle Evans /* 925952343eSKyle Evans * Represents a relationship between the command name and the parser action 935952343eSKyle Evans * that handles it. 945952343eSKyle Evans */ 955952343eSKyle Evans struct command_map_entry { 965952343eSKyle Evans const char *command; 975952343eSKyle Evans int (*fn)(int argc, char *argv[]); 985952343eSKyle Evans }; 995952343eSKyle Evans 1005952343eSKyle Evans static struct command_map_entry command_map[] = 1015952343eSKyle Evans { 1029e004b21SKyle Evans { "activate", bectl_cmd_activate }, 1039e004b21SKyle Evans { "create", bectl_cmd_create }, 1049e004b21SKyle Evans { "destroy", bectl_cmd_destroy }, 1059e004b21SKyle Evans { "export", bectl_cmd_export }, 1069e004b21SKyle Evans { "import", bectl_cmd_import }, 107*3d1a1f2cSKyle Evans #if SOON 1089e004b21SKyle Evans { "add", bectl_cmd_add }, 109*3d1a1f2cSKyle Evans #endif 1109e004b21SKyle Evans { "jail", bectl_cmd_jail }, 1119e004b21SKyle Evans { "list", bectl_cmd_list }, 1129e004b21SKyle Evans { "mount", bectl_cmd_mount }, 1139e004b21SKyle Evans { "rename", bectl_cmd_rename }, 1149e004b21SKyle Evans { "unjail", bectl_cmd_unjail }, 1159e004b21SKyle Evans { "unmount", bectl_cmd_unmount }, 1165952343eSKyle Evans }; 1175952343eSKyle Evans 1185952343eSKyle Evans static int 119b29bf2f8SKyle Evans get_cmd_index(const char *cmd, int *index) 1205952343eSKyle Evans { 12116a10da8SKyle Evans int map_size; 1225952343eSKyle Evans 12316a10da8SKyle Evans map_size = nitems(command_map); 1245952343eSKyle Evans for (int i = 0; i < map_size; ++i) { 1255952343eSKyle Evans if (strcmp(cmd, command_map[i].command) == 0) { 1265952343eSKyle Evans *index = i; 1275952343eSKyle Evans return (0); 1285952343eSKyle Evans } 1295952343eSKyle Evans } 1305952343eSKyle Evans 1315952343eSKyle Evans return (1); 1325952343eSKyle Evans } 1335952343eSKyle Evans 1345952343eSKyle Evans 1355952343eSKyle Evans static int 1369e004b21SKyle Evans bectl_cmd_activate(int argc, char *argv[]) 1375952343eSKyle Evans { 1385952343eSKyle Evans int err, opt; 1395952343eSKyle Evans bool temp; 1405952343eSKyle Evans 1415952343eSKyle Evans temp = false; 1425952343eSKyle Evans while ((opt = getopt(argc, argv, "t")) != -1) { 1435952343eSKyle Evans switch (opt) { 1445952343eSKyle Evans case 't': 1455952343eSKyle Evans temp = true; 1465952343eSKyle Evans break; 1475952343eSKyle Evans default: 1482c848957SKyle Evans fprintf(stderr, "bectl activate: unknown option '-%c'\n", 1495952343eSKyle Evans optopt); 1505952343eSKyle Evans return (usage(false)); 1515952343eSKyle Evans } 1525952343eSKyle Evans } 1535952343eSKyle Evans 1545952343eSKyle Evans argc -= optind; 1555952343eSKyle Evans argv += optind; 1565952343eSKyle Evans 1575952343eSKyle Evans if (argc != 1) { 1582c848957SKyle Evans fprintf(stderr, "bectl activate: wrong number of arguments\n"); 1595952343eSKyle Evans return (usage(false)); 1605952343eSKyle Evans } 1615952343eSKyle Evans 1625952343eSKyle Evans 1635952343eSKyle Evans /* activate logic goes here */ 16416a10da8SKyle Evans if ((err = be_activate(be, argv[0], temp)) != 0) 16516a10da8SKyle Evans /* XXX TODO: more specific error msg based on err */ 1665952343eSKyle Evans printf("did not successfully activate boot environment %s\n", 1675952343eSKyle Evans argv[0]); 16816a10da8SKyle Evans else 1695952343eSKyle Evans printf("successfully activated boot environment %s\n", argv[0]); 1705952343eSKyle Evans 17116a10da8SKyle Evans if (temp) 1725952343eSKyle Evans printf("for next boot\n"); 1735952343eSKyle Evans 1745952343eSKyle Evans return (err); 1755952343eSKyle Evans } 1765952343eSKyle Evans 1775952343eSKyle Evans 17816a10da8SKyle Evans /* 17916a10da8SKyle Evans * TODO: when only one arg is given, and it contains an "@" the this should 18016a10da8SKyle Evans * create that snapshot 18116a10da8SKyle Evans */ 1825952343eSKyle Evans static int 1839e004b21SKyle Evans bectl_cmd_create(int argc, char *argv[]) 1845952343eSKyle Evans { 18516a10da8SKyle Evans char *bootenv, *snapname, *source; 1865952343eSKyle Evans int err, opt; 1875952343eSKyle Evans 1885952343eSKyle Evans snapname = NULL; 1895952343eSKyle Evans while ((opt = getopt(argc, argv, "e:")) != -1) { 1905952343eSKyle Evans switch (opt) { 1915952343eSKyle Evans case 'e': 1925952343eSKyle Evans snapname = optarg; 1935952343eSKyle Evans break; 1945952343eSKyle Evans default: 1952c848957SKyle Evans fprintf(stderr, "bectl create: unknown option '-%c'\n", 1965952343eSKyle Evans optopt); 1975952343eSKyle Evans return (usage(false)); 1985952343eSKyle Evans } 1995952343eSKyle Evans } 2005952343eSKyle Evans 2015952343eSKyle Evans argc -= optind; 2025952343eSKyle Evans argv += optind; 2035952343eSKyle Evans 2045952343eSKyle Evans if (argc != 1) { 2052c848957SKyle Evans fprintf(stderr, "bectl create: wrong number of arguments\n"); 2065952343eSKyle Evans return (usage(false)); 2075952343eSKyle Evans } 2085952343eSKyle Evans 2095952343eSKyle Evans bootenv = *argv; 2105952343eSKyle Evans 2115952343eSKyle Evans if (snapname != NULL) { 21216a10da8SKyle Evans if (strchr(snapname, '@') != NULL) 2135952343eSKyle Evans err = be_create_from_existing_snap(be, bootenv, 2145952343eSKyle Evans snapname); 21516a10da8SKyle Evans else 2165952343eSKyle Evans err = be_create_from_existing(be, bootenv, snapname); 2175952343eSKyle Evans } else { 2185952343eSKyle Evans if ((snapname = strchr(bootenv, '@')) != NULL) { 2195952343eSKyle Evans *(snapname++) = '\0'; 220b29bf2f8SKyle Evans if ((err = be_snapshot(be, be_active_path(be), 22116a10da8SKyle Evans snapname, true, NULL)) != BE_ERR_SUCCESS) 2225952343eSKyle Evans fprintf(stderr, "failed to create snapshot\n"); 2235952343eSKyle Evans asprintf(&source, "%s@%s", be_active_path(be), snapname); 2245952343eSKyle Evans err = be_create_from_existing_snap(be, bootenv, 2255952343eSKyle Evans source); 2265952343eSKyle Evans return (err); 22716a10da8SKyle Evans } else 2285952343eSKyle Evans err = be_create(be, bootenv); 2295952343eSKyle Evans } 2305952343eSKyle Evans 2315952343eSKyle Evans switch (err) { 2325952343eSKyle Evans case BE_ERR_SUCCESS: 2335952343eSKyle Evans break; 2345952343eSKyle Evans default: 23516a10da8SKyle Evans if (snapname == NULL) 2365952343eSKyle Evans fprintf(stderr, 2375952343eSKyle Evans "failed to create bootenv %s\n", bootenv); 23816a10da8SKyle Evans else 2395952343eSKyle Evans fprintf(stderr, 2405952343eSKyle Evans "failed to create bootenv %s from snapshot %s\n", 2415952343eSKyle Evans bootenv, snapname); 2425952343eSKyle Evans } 2435952343eSKyle Evans 2445952343eSKyle Evans return (err); 2455952343eSKyle Evans } 2465952343eSKyle Evans 2475952343eSKyle Evans 2485952343eSKyle Evans static int 2499e004b21SKyle Evans bectl_cmd_export(int argc, char *argv[]) 2505952343eSKyle Evans { 2515952343eSKyle Evans char *bootenv; 2525952343eSKyle Evans 2535952343eSKyle Evans if (argc == 1) { 2542c848957SKyle Evans fprintf(stderr, "bectl export: missing boot environment name\n"); 2555952343eSKyle Evans return (usage(false)); 2565952343eSKyle Evans } 2575952343eSKyle Evans 2585952343eSKyle Evans if (argc > 2) { 2592c848957SKyle Evans fprintf(stderr, "bectl export: extra arguments provided\n"); 2605952343eSKyle Evans return (usage(false)); 2615952343eSKyle Evans } 2625952343eSKyle Evans 2635952343eSKyle Evans bootenv = argv[1]; 2645952343eSKyle Evans 2655952343eSKyle Evans if (isatty(STDOUT_FILENO)) { 2662c848957SKyle Evans fprintf(stderr, "bectl export: must redirect output\n"); 2675952343eSKyle Evans return (EX_USAGE); 2685952343eSKyle Evans } 2695952343eSKyle Evans 2705952343eSKyle Evans be_export(be, bootenv, STDOUT_FILENO); 2715952343eSKyle Evans 2725952343eSKyle Evans return (0); 2735952343eSKyle Evans } 2745952343eSKyle Evans 2755952343eSKyle Evans 2765952343eSKyle Evans static int 2779e004b21SKyle Evans bectl_cmd_import(int argc, char *argv[]) 2785952343eSKyle Evans { 2795952343eSKyle Evans char *bootenv; 2805952343eSKyle Evans int err; 2815952343eSKyle Evans 2825952343eSKyle Evans if (argc == 1) { 2832c848957SKyle Evans fprintf(stderr, "bectl import: missing boot environment name\n"); 2845952343eSKyle Evans return (usage(false)); 2855952343eSKyle Evans } 2865952343eSKyle Evans 2875952343eSKyle Evans if (argc > 2) { 2882c848957SKyle Evans fprintf(stderr, "bectl import: extra arguments provided\n"); 2895952343eSKyle Evans return (usage(false)); 2905952343eSKyle Evans } 2915952343eSKyle Evans 2925952343eSKyle Evans bootenv = argv[1]; 2935952343eSKyle Evans 2945952343eSKyle Evans if (isatty(STDIN_FILENO)) { 2952c848957SKyle Evans fprintf(stderr, "bectl import: input can not be from terminal\n"); 2965952343eSKyle Evans return (EX_USAGE); 2975952343eSKyle Evans } 2985952343eSKyle Evans 2995952343eSKyle Evans err = be_import(be, bootenv, STDIN_FILENO); 3005952343eSKyle Evans 3015952343eSKyle Evans return (err); 3025952343eSKyle Evans } 3035952343eSKyle Evans 304*3d1a1f2cSKyle Evans #if SOON 3055952343eSKyle Evans static int 3069e004b21SKyle Evans bectl_cmd_add(int argc, char *argv[]) 3075952343eSKyle Evans { 3085952343eSKyle Evans 3095952343eSKyle Evans if (argc < 2) { 3102c848957SKyle Evans fprintf(stderr, "bectl add: must provide at least one path\n"); 3115952343eSKyle Evans return (usage(false)); 3125952343eSKyle Evans } 3135952343eSKyle Evans 3145952343eSKyle Evans for (int i = 1; i < argc; ++i) { 3155952343eSKyle Evans printf("arg %d: %s\n", i, argv[i]); 31616a10da8SKyle Evans /* XXX TODO catch err */ 3175952343eSKyle Evans be_add_child(be, argv[i], true); 3185952343eSKyle Evans } 3195952343eSKyle Evans 3205952343eSKyle Evans return (0); 3215952343eSKyle Evans } 322*3d1a1f2cSKyle Evans #endif 3235952343eSKyle Evans 3245952343eSKyle Evans static int 3259e004b21SKyle Evans bectl_cmd_destroy(int argc, char *argv[]) 3265952343eSKyle Evans { 32716a10da8SKyle Evans char *target; 3285952343eSKyle Evans int opt, err; 3295952343eSKyle Evans bool force; 3305952343eSKyle Evans 3315952343eSKyle Evans force = false; 3325952343eSKyle Evans while ((opt = getopt(argc, argv, "F")) != -1) { 3335952343eSKyle Evans switch (opt) { 3345952343eSKyle Evans case 'F': 3355952343eSKyle Evans force = true; 3365952343eSKyle Evans break; 3375952343eSKyle Evans default: 3382c848957SKyle Evans fprintf(stderr, "bectl destroy: unknown option '-%c'\n", 3395952343eSKyle Evans optopt); 3405952343eSKyle Evans return (usage(false)); 3415952343eSKyle Evans } 3425952343eSKyle Evans } 3435952343eSKyle Evans 3445952343eSKyle Evans argc -= optind; 3455952343eSKyle Evans argv += optind; 3465952343eSKyle Evans 3475952343eSKyle Evans if (argc != 1) { 3482c848957SKyle Evans fprintf(stderr, "bectl destroy: wrong number of arguments\n"); 3495952343eSKyle Evans return (usage(false)); 3505952343eSKyle Evans } 3515952343eSKyle Evans 3525952343eSKyle Evans target = argv[0]; 3535952343eSKyle Evans 3545952343eSKyle Evans err = be_destroy(be, target, force); 3555952343eSKyle Evans 3565952343eSKyle Evans return (err); 3575952343eSKyle Evans } 3585952343eSKyle Evans 3595952343eSKyle Evans static int 3609e004b21SKyle Evans bectl_cmd_mount(int argc, char *argv[]) 3615952343eSKyle Evans { 3625952343eSKyle Evans char result_loc[BE_MAXPATHLEN]; 36316a10da8SKyle Evans char *bootenv, *mountpoint; 36416a10da8SKyle Evans int err; 3655952343eSKyle Evans 3665952343eSKyle Evans if (argc < 2) { 3672c848957SKyle Evans fprintf(stderr, "bectl mount: missing argument(s)\n"); 3685952343eSKyle Evans return (usage(false)); 3695952343eSKyle Evans } 3705952343eSKyle Evans 3715952343eSKyle Evans if (argc > 3) { 3722c848957SKyle Evans fprintf(stderr, "bectl mount: too many arguments\n"); 3735952343eSKyle Evans return (usage(false)); 3745952343eSKyle Evans } 3755952343eSKyle Evans 3765952343eSKyle Evans bootenv = argv[1]; 3775952343eSKyle Evans mountpoint = ((argc == 3) ? argv[2] : NULL); 3785952343eSKyle Evans 3795952343eSKyle Evans err = be_mount(be, bootenv, mountpoint, 0, result_loc); 3805952343eSKyle Evans 3815952343eSKyle Evans switch (err) { 3825952343eSKyle Evans case BE_ERR_SUCCESS: 3835952343eSKyle Evans printf("successfully mounted %s at %s\n", bootenv, result_loc); 3845952343eSKyle Evans break; 3855952343eSKyle Evans default: 3865952343eSKyle Evans fprintf(stderr, 3875952343eSKyle Evans (argc == 3) ? "failed to mount bootenv %s at %s\n" : 3885952343eSKyle Evans "failed to mount bootenv %s at temporary path %s\n", 3895952343eSKyle Evans bootenv, mountpoint); 3905952343eSKyle Evans } 3915952343eSKyle Evans 3925952343eSKyle Evans return (err); 3935952343eSKyle Evans } 3945952343eSKyle Evans 3955952343eSKyle Evans 3965952343eSKyle Evans static int 3979e004b21SKyle Evans bectl_cmd_rename(int argc, char *argv[]) 3985952343eSKyle Evans { 39916a10da8SKyle Evans char *dest, *src; 4005952343eSKyle Evans int err; 4015952343eSKyle Evans 4025952343eSKyle Evans if (argc < 3) { 4032c848957SKyle Evans fprintf(stderr, "bectl rename: missing argument\n"); 4045952343eSKyle Evans return (usage(false)); 4055952343eSKyle Evans } 4065952343eSKyle Evans 4075952343eSKyle Evans if (argc > 3) { 4082c848957SKyle Evans fprintf(stderr, "bectl rename: too many arguments\n"); 4095952343eSKyle Evans return (usage(false)); 4105952343eSKyle Evans } 4115952343eSKyle Evans 4125952343eSKyle Evans src = argv[1]; 4135952343eSKyle Evans dest = argv[2]; 4145952343eSKyle Evans 4155952343eSKyle Evans err = be_rename(be, src, dest); 4165952343eSKyle Evans 4175952343eSKyle Evans switch (err) { 4185952343eSKyle Evans case BE_ERR_SUCCESS: 4195952343eSKyle Evans break; 4205952343eSKyle Evans default: 4215952343eSKyle Evans fprintf(stderr, "failed to rename bootenv %s to %s\n", 4225952343eSKyle Evans src, dest); 4235952343eSKyle Evans } 4245952343eSKyle Evans 4255952343eSKyle Evans return (0); 4265952343eSKyle Evans } 4275952343eSKyle Evans 428ad765da4SKyle Evans static int 4299e004b21SKyle Evans bectl_cmd_unmount(int argc, char *argv[]) 4305952343eSKyle Evans { 43116a10da8SKyle Evans char *bootenv, *cmd; 4325952343eSKyle Evans int err, flags, opt; 4335952343eSKyle Evans 4345952343eSKyle Evans /* Store alias used */ 4355952343eSKyle Evans cmd = argv[0]; 4365952343eSKyle Evans 4375952343eSKyle Evans flags = 0; 4385952343eSKyle Evans while ((opt = getopt(argc, argv, "f")) != -1) { 4395952343eSKyle Evans switch (opt) { 4405952343eSKyle Evans case 'f': 4415952343eSKyle Evans flags |= BE_MNT_FORCE; 4425952343eSKyle Evans break; 4435952343eSKyle Evans default: 4442c848957SKyle Evans fprintf(stderr, "bectl %s: unknown option '-%c'\n", 4455952343eSKyle Evans cmd, optopt); 4465952343eSKyle Evans return (usage(false)); 4475952343eSKyle Evans } 4485952343eSKyle Evans } 4495952343eSKyle Evans 4505952343eSKyle Evans argc -= optind; 4515952343eSKyle Evans argv += optind; 4525952343eSKyle Evans 4535952343eSKyle Evans if (argc != 1) { 4542c848957SKyle Evans fprintf(stderr, "bectl %s: wrong number of arguments\n", cmd); 4555952343eSKyle Evans return (usage(false)); 4565952343eSKyle Evans } 4575952343eSKyle Evans 4585952343eSKyle Evans bootenv = argv[0]; 4595952343eSKyle Evans 4605952343eSKyle Evans err = be_unmount(be, bootenv, flags); 4615952343eSKyle Evans 4625952343eSKyle Evans switch (err) { 4635952343eSKyle Evans case BE_ERR_SUCCESS: 4645952343eSKyle Evans break; 4655952343eSKyle Evans default: 4665952343eSKyle Evans fprintf(stderr, "failed to unmount bootenv %s\n", bootenv); 4675952343eSKyle Evans } 4685952343eSKyle Evans 4695952343eSKyle Evans return (err); 4705952343eSKyle Evans } 4715952343eSKyle Evans 4725952343eSKyle Evans 4735952343eSKyle Evans int 4745952343eSKyle Evans main(int argc, char *argv[]) 4755952343eSKyle Evans { 476b29bf2f8SKyle Evans const char *command; 4775952343eSKyle Evans int command_index, rc; 4785952343eSKyle Evans 4795952343eSKyle Evans if (argc < 2) { 4805952343eSKyle Evans fprintf(stderr, "missing command\n"); 4815952343eSKyle Evans return (usage(false)); 4825952343eSKyle Evans } 4835952343eSKyle Evans 4845952343eSKyle Evans command = argv[1]; 4855952343eSKyle Evans 4865952343eSKyle Evans /* Handle command aliases */ 48716a10da8SKyle Evans if (strcmp(command, "umount") == 0) 4885952343eSKyle Evans command = "unmount"; 4895952343eSKyle Evans 49016a10da8SKyle Evans if (strcmp(command, "ujail") == 0) 4915952343eSKyle Evans command = "unjail"; 4925952343eSKyle Evans 49316a10da8SKyle Evans if ((strcmp(command, "-?") == 0) || (strcmp(command, "-h") == 0)) 4945952343eSKyle Evans return (usage(true)); 4955952343eSKyle Evans 4965952343eSKyle Evans if (get_cmd_index(command, &command_index)) { 4975952343eSKyle Evans fprintf(stderr, "unknown command: %s\n", command); 4985952343eSKyle Evans return (usage(false)); 4995952343eSKyle Evans } 5005952343eSKyle Evans 5015952343eSKyle Evans 50216a10da8SKyle Evans if ((be = libbe_init()) == NULL) 5035952343eSKyle Evans return (-1); 5045952343eSKyle Evans 5055952343eSKyle Evans libbe_print_on_error(be, true); 5065952343eSKyle Evans 50716a10da8SKyle Evans /* XXX TODO: can be simplified if offset by 2 instead of one */ 5085952343eSKyle Evans rc = command_map[command_index].fn(argc-1, argv+1); 5095952343eSKyle Evans 5105952343eSKyle Evans libbe_close(be); 5115952343eSKyle Evans return (rc); 5125952343eSKyle Evans } 513