105c91076SPawel Jakub Dawidek /*- 287070efbSPawel Jakub Dawidek * Copyright (c) 2004-2009 Pawel Jakub Dawidek <pjd@FreeBSD.org> 305c91076SPawel Jakub Dawidek * All rights reserved. 405c91076SPawel Jakub Dawidek * 505c91076SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 605c91076SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 705c91076SPawel Jakub Dawidek * are met: 805c91076SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 905c91076SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 1005c91076SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 1105c91076SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 1205c91076SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 1305c91076SPawel Jakub Dawidek * 1405c91076SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1505c91076SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1605c91076SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1705c91076SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 1805c91076SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1905c91076SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2005c91076SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2105c91076SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2205c91076SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2305c91076SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2405c91076SPawel Jakub Dawidek * SUCH DAMAGE. 2505c91076SPawel Jakub Dawidek */ 2605c91076SPawel Jakub Dawidek 2705c91076SPawel Jakub Dawidek #include <sys/cdefs.h> 2805c91076SPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 2905c91076SPawel Jakub Dawidek 3005c91076SPawel Jakub Dawidek #include <sys/param.h> 3105c91076SPawel Jakub Dawidek #include <sys/linker.h> 3205c91076SPawel Jakub Dawidek #include <sys/module.h> 3305c91076SPawel Jakub Dawidek #include <sys/stat.h> 3405c91076SPawel Jakub Dawidek #include <sys/sysctl.h> 3505c91076SPawel Jakub Dawidek #include <ctype.h> 3605c91076SPawel Jakub Dawidek #include <err.h> 3705c91076SPawel Jakub Dawidek #include <errno.h> 3805c91076SPawel Jakub Dawidek #include <stdio.h> 3905c91076SPawel Jakub Dawidek #include <stdlib.h> 4005c91076SPawel Jakub Dawidek #include <stdarg.h> 4105c91076SPawel Jakub Dawidek #include <stdint.h> 4205c91076SPawel Jakub Dawidek #include <string.h> 4305c91076SPawel Jakub Dawidek #include <unistd.h> 4405c91076SPawel Jakub Dawidek #include <libgen.h> 45af565b58SPawel Jakub Dawidek #include <libutil.h> 4605c91076SPawel Jakub Dawidek #include <inttypes.h> 4705c91076SPawel Jakub Dawidek #include <dlfcn.h> 4805c91076SPawel Jakub Dawidek #include <assert.h> 4905c91076SPawel Jakub Dawidek #include <libgeom.h> 5005c91076SPawel Jakub Dawidek #include <geom.h> 5105c91076SPawel Jakub Dawidek 5205c91076SPawel Jakub Dawidek #include "misc/subr.h" 5305c91076SPawel Jakub Dawidek 5414bf405bSMarcel Moolenaar #ifdef STATIC_GEOM_CLASSES 55a16f9b36SMarcel Moolenaar extern uint32_t gpart_version; 56a16f9b36SMarcel Moolenaar extern struct g_command gpart_class_commands[]; 57bc69d66fSXin LI extern uint32_t glabel_version; 58bc69d66fSXin LI extern struct g_command glabel_class_commands[]; 59a16f9b36SMarcel Moolenaar #endif 6005c91076SPawel Jakub Dawidek 6105c91076SPawel Jakub Dawidek static char comm[MAXPATHLEN], *class_name = NULL, *gclass_name = NULL; 6205c91076SPawel Jakub Dawidek static uint32_t *version = NULL; 6305c91076SPawel Jakub Dawidek static int verbose = 0; 6405c91076SPawel Jakub Dawidek static struct g_command *class_commands = NULL; 6505c91076SPawel Jakub Dawidek 66138cedfdSPawel Jakub Dawidek #define GEOM_CLASS_CMDS 0x01 67138cedfdSPawel Jakub Dawidek #define GEOM_STD_CMDS 0x02 68138cedfdSPawel Jakub Dawidek static struct g_command *find_command(const char *cmdstr, int flags); 6905c91076SPawel Jakub Dawidek static int std_available(const char *name); 7005c91076SPawel Jakub Dawidek 71b70eccf3SPawel Jakub Dawidek static void std_help(struct gctl_req *req, unsigned flags); 7205c91076SPawel Jakub Dawidek static void std_list(struct gctl_req *req, unsigned flags); 7318ee8840SPawel Jakub Dawidek static void std_status(struct gctl_req *req, unsigned flags); 7405c91076SPawel Jakub Dawidek static void std_load(struct gctl_req *req, unsigned flags); 7505c91076SPawel Jakub Dawidek static void std_unload(struct gctl_req *req, unsigned flags); 7605c91076SPawel Jakub Dawidek 7705c91076SPawel Jakub Dawidek struct g_command std_commands[] = { 783cf55d3aSMarcel Moolenaar { "help", 0, std_help, G_NULL_OPTS, NULL, NULL }, 793cf55d3aSMarcel Moolenaar { "list", 0, std_list, G_NULL_OPTS, NULL, 80c979e206SPawel Jakub Dawidek "[name ...]" 81c979e206SPawel Jakub Dawidek }, 82ba6821f0SPawel Jakub Dawidek { "status", 0, std_status, 83ba6821f0SPawel Jakub Dawidek { 846fc60008SPawel Jakub Dawidek { 's', "script", NULL, G_TYPE_BOOL }, 85ba6821f0SPawel Jakub Dawidek G_OPT_SENTINEL 86ba6821f0SPawel Jakub Dawidek }, 873cf55d3aSMarcel Moolenaar NULL, "[-s] [name ...]" 88c979e206SPawel Jakub Dawidek }, 893cf55d3aSMarcel Moolenaar { "load", G_FLAG_VERBOSE | G_FLAG_LOADKLD, std_load, G_NULL_OPTS, 903cf55d3aSMarcel Moolenaar NULL, NULL }, 913cf55d3aSMarcel Moolenaar { "unload", G_FLAG_VERBOSE, std_unload, G_NULL_OPTS, NULL, NULL }, 9205c91076SPawel Jakub Dawidek G_CMD_SENTINEL 9305c91076SPawel Jakub Dawidek }; 9405c91076SPawel Jakub Dawidek 9505c91076SPawel Jakub Dawidek static void 96c979e206SPawel Jakub Dawidek usage_command(struct g_command *cmd, const char *prefix) 9705c91076SPawel Jakub Dawidek { 9805c91076SPawel Jakub Dawidek struct g_option *opt; 99c979e206SPawel Jakub Dawidek unsigned i; 10005c91076SPawel Jakub Dawidek 101c979e206SPawel Jakub Dawidek if (cmd->gc_usage != NULL) { 102963feac4SPawel Jakub Dawidek char *pos, *ptr, *sptr; 103963feac4SPawel Jakub Dawidek 104963feac4SPawel Jakub Dawidek sptr = ptr = strdup(cmd->gc_usage); 105963feac4SPawel Jakub Dawidek while ((pos = strsep(&ptr, "\n")) != NULL) { 106963feac4SPawel Jakub Dawidek if (*pos == '\0') 107963feac4SPawel Jakub Dawidek continue; 108963feac4SPawel Jakub Dawidek fprintf(stderr, "%s %s %s %s\n", prefix, comm, 109963feac4SPawel Jakub Dawidek cmd->gc_name, pos); 110963feac4SPawel Jakub Dawidek } 111963feac4SPawel Jakub Dawidek free(sptr); 112c979e206SPawel Jakub Dawidek return; 113c979e206SPawel Jakub Dawidek } 114963feac4SPawel Jakub Dawidek 115963feac4SPawel Jakub Dawidek fprintf(stderr, "%s %s %s", prefix, comm, cmd->gc_name); 11605c91076SPawel Jakub Dawidek if ((cmd->gc_flags & G_FLAG_VERBOSE) != 0) 11705c91076SPawel Jakub Dawidek fprintf(stderr, " [-v]"); 118c979e206SPawel Jakub Dawidek for (i = 0; ; i++) { 119c979e206SPawel Jakub Dawidek opt = &cmd->gc_options[i]; 12005c91076SPawel Jakub Dawidek if (opt->go_name == NULL) 12105c91076SPawel Jakub Dawidek break; 1226fc60008SPawel Jakub Dawidek if (opt->go_val != NULL || G_OPT_TYPE(opt) == G_TYPE_BOOL) 12305c91076SPawel Jakub Dawidek fprintf(stderr, " ["); 12405c91076SPawel Jakub Dawidek else 12505c91076SPawel Jakub Dawidek fprintf(stderr, " "); 12605c91076SPawel Jakub Dawidek fprintf(stderr, "-%c", opt->go_char); 1276fc60008SPawel Jakub Dawidek if (G_OPT_TYPE(opt) != G_TYPE_BOOL) 12805c91076SPawel Jakub Dawidek fprintf(stderr, " %s", opt->go_name); 1296fc60008SPawel Jakub Dawidek if (opt->go_val != NULL || G_OPT_TYPE(opt) == G_TYPE_BOOL) 13005c91076SPawel Jakub Dawidek fprintf(stderr, "]"); 13105c91076SPawel Jakub Dawidek } 1323cf55d3aSMarcel Moolenaar if (cmd->gc_argname) 1333cf55d3aSMarcel Moolenaar fprintf(stderr, " %s", cmd->gc_argname); 134c979e206SPawel Jakub Dawidek fprintf(stderr, "\n"); 13505c91076SPawel Jakub Dawidek } 13605c91076SPawel Jakub Dawidek 13705c91076SPawel Jakub Dawidek static void 138c979e206SPawel Jakub Dawidek usage(void) 13905c91076SPawel Jakub Dawidek { 14005c91076SPawel Jakub Dawidek 14105c91076SPawel Jakub Dawidek if (class_name == NULL) { 142b70eccf3SPawel Jakub Dawidek errx(EXIT_FAILURE, "usage: %s <class> <command> [options]", 143b70eccf3SPawel Jakub Dawidek "geom"); 14405c91076SPawel Jakub Dawidek } else { 145c979e206SPawel Jakub Dawidek struct g_command *cmd; 14605c91076SPawel Jakub Dawidek const char *prefix; 14705c91076SPawel Jakub Dawidek unsigned i; 14805c91076SPawel Jakub Dawidek 14905c91076SPawel Jakub Dawidek prefix = "usage:"; 150c979e206SPawel Jakub Dawidek if (class_commands != NULL) { 151c979e206SPawel Jakub Dawidek for (i = 0; ; i++) { 152c979e206SPawel Jakub Dawidek cmd = &class_commands[i]; 153c979e206SPawel Jakub Dawidek if (cmd->gc_name == NULL) 154c979e206SPawel Jakub Dawidek break; 155c979e206SPawel Jakub Dawidek usage_command(cmd, prefix); 15605c91076SPawel Jakub Dawidek prefix = " "; 15705c91076SPawel Jakub Dawidek } 158c979e206SPawel Jakub Dawidek } 15905c91076SPawel Jakub Dawidek for (i = 0; ; i++) { 16005c91076SPawel Jakub Dawidek cmd = &std_commands[i]; 16105c91076SPawel Jakub Dawidek if (cmd->gc_name == NULL) 16205c91076SPawel Jakub Dawidek break; 163138cedfdSPawel Jakub Dawidek /* 164138cedfdSPawel Jakub Dawidek * If class defines command, which has the same name as 165138cedfdSPawel Jakub Dawidek * standard command, skip it, because it was already 166138cedfdSPawel Jakub Dawidek * shown on usage(). 167138cedfdSPawel Jakub Dawidek */ 168138cedfdSPawel Jakub Dawidek if (find_command(cmd->gc_name, GEOM_CLASS_CMDS) != NULL) 16905c91076SPawel Jakub Dawidek continue; 170c979e206SPawel Jakub Dawidek usage_command(cmd, prefix); 17105c91076SPawel Jakub Dawidek prefix = " "; 17205c91076SPawel Jakub Dawidek } 17305c91076SPawel Jakub Dawidek exit(EXIT_FAILURE); 17405c91076SPawel Jakub Dawidek } 17505c91076SPawel Jakub Dawidek } 17605c91076SPawel Jakub Dawidek 17705c91076SPawel Jakub Dawidek static void 17805c91076SPawel Jakub Dawidek load_module(void) 17905c91076SPawel Jakub Dawidek { 18005c91076SPawel Jakub Dawidek char name1[64], name2[64]; 18105c91076SPawel Jakub Dawidek 18205c91076SPawel Jakub Dawidek snprintf(name1, sizeof(name1), "g_%s", class_name); 18305c91076SPawel Jakub Dawidek snprintf(name2, sizeof(name2), "geom_%s", class_name); 18405c91076SPawel Jakub Dawidek if (modfind(name1) < 0) { 18505c91076SPawel Jakub Dawidek /* Not present in kernel, try loading it. */ 18605c91076SPawel Jakub Dawidek if (kldload(name2) < 0 || modfind(name1) < 0) { 18705c91076SPawel Jakub Dawidek if (errno != EEXIST) { 18805c91076SPawel Jakub Dawidek errx(EXIT_FAILURE, 18905c91076SPawel Jakub Dawidek "%s module not available!", name2); 19005c91076SPawel Jakub Dawidek } 19105c91076SPawel Jakub Dawidek } 19205c91076SPawel Jakub Dawidek } 19305c91076SPawel Jakub Dawidek } 19405c91076SPawel Jakub Dawidek 19505c91076SPawel Jakub Dawidek static int 19605c91076SPawel Jakub Dawidek strlcatf(char *str, size_t size, const char *format, ...) 19705c91076SPawel Jakub Dawidek { 19805c91076SPawel Jakub Dawidek size_t len; 19905c91076SPawel Jakub Dawidek va_list ap; 20005c91076SPawel Jakub Dawidek int ret; 20105c91076SPawel Jakub Dawidek 20205c91076SPawel Jakub Dawidek len = strlen(str); 20305c91076SPawel Jakub Dawidek str += len; 20405c91076SPawel Jakub Dawidek size -= len; 20505c91076SPawel Jakub Dawidek 20605c91076SPawel Jakub Dawidek va_start(ap, format); 20705c91076SPawel Jakub Dawidek ret = vsnprintf(str, size, format, ap); 20805c91076SPawel Jakub Dawidek va_end(ap); 20905c91076SPawel Jakub Dawidek 21005c91076SPawel Jakub Dawidek return (ret); 21105c91076SPawel Jakub Dawidek } 21205c91076SPawel Jakub Dawidek 21305c91076SPawel Jakub Dawidek /* 21405c91076SPawel Jakub Dawidek * Find given option in options available for given command. 21505c91076SPawel Jakub Dawidek */ 21605c91076SPawel Jakub Dawidek static struct g_option * 21705c91076SPawel Jakub Dawidek find_option(struct g_command *cmd, char ch) 21805c91076SPawel Jakub Dawidek { 21905c91076SPawel Jakub Dawidek struct g_option *opt; 22005c91076SPawel Jakub Dawidek unsigned i; 22105c91076SPawel Jakub Dawidek 22205c91076SPawel Jakub Dawidek for (i = 0; ; i++) { 22305c91076SPawel Jakub Dawidek opt = &cmd->gc_options[i]; 22405c91076SPawel Jakub Dawidek if (opt->go_name == NULL) 22505c91076SPawel Jakub Dawidek return (NULL); 22605c91076SPawel Jakub Dawidek if (opt->go_char == ch) 22705c91076SPawel Jakub Dawidek return (opt); 22805c91076SPawel Jakub Dawidek } 22905c91076SPawel Jakub Dawidek /* NOTREACHED */ 23005c91076SPawel Jakub Dawidek return (NULL); 23105c91076SPawel Jakub Dawidek } 23205c91076SPawel Jakub Dawidek 23305c91076SPawel Jakub Dawidek /* 23405c91076SPawel Jakub Dawidek * Add given option to gctl_req. 23505c91076SPawel Jakub Dawidek */ 23605c91076SPawel Jakub Dawidek static void 23705c91076SPawel Jakub Dawidek set_option(struct gctl_req *req, struct g_option *opt, const char *val) 23805c91076SPawel Jakub Dawidek { 239dc344ca5SMarcel Moolenaar char *s; 24005c91076SPawel Jakub Dawidek intmax_t number; 24105c91076SPawel Jakub Dawidek 242dc344ca5SMarcel Moolenaar if (G_OPT_TYPE(opt) == G_TYPE_NUMBER || 243dc344ca5SMarcel Moolenaar G_OPT_TYPE(opt) == G_TYPE_ASCNUM) { 244e84091cbSPawel Jakub Dawidek if (expand_number(val, &number) == -1) { 24505c91076SPawel Jakub Dawidek err(EXIT_FAILURE, "Invalid value for '%c' argument.", 24605c91076SPawel Jakub Dawidek opt->go_char); 24705c91076SPawel Jakub Dawidek } 248dc344ca5SMarcel Moolenaar if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) 24905c91076SPawel Jakub Dawidek opt->go_val = malloc(sizeof(intmax_t)); 250dc344ca5SMarcel Moolenaar else { 251dc344ca5SMarcel Moolenaar asprintf(&s, "%jd", number); 252dc344ca5SMarcel Moolenaar opt->go_val = s; 253dc344ca5SMarcel Moolenaar } 25405c91076SPawel Jakub Dawidek if (opt->go_val == NULL) 25505c91076SPawel Jakub Dawidek errx(EXIT_FAILURE, "No memory."); 256dc344ca5SMarcel Moolenaar if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) { 25705c91076SPawel Jakub Dawidek *(intmax_t *)opt->go_val = number; 258dc344ca5SMarcel Moolenaar gctl_ro_param(req, opt->go_name, sizeof(intmax_t), 259dc344ca5SMarcel Moolenaar opt->go_val); 260dc344ca5SMarcel Moolenaar } else 261dc344ca5SMarcel Moolenaar gctl_ro_param(req, opt->go_name, -1, opt->go_val); 262dc344ca5SMarcel Moolenaar } else if (G_OPT_TYPE(opt) == G_TYPE_ASCLBA) { 263dc344ca5SMarcel Moolenaar /* 264dc344ca5SMarcel Moolenaar * LBAs are ugly. The argument is a sector. The size of a 265dc344ca5SMarcel Moolenaar * sector is context specific (i.e. determined by the media), 266dc344ca5SMarcel Moolenaar * which we don't know here. But when users enter a value 267dc344ca5SMarcel Moolenaar * with a SI unit, they really mean the byte-size or byte- 268dc344ca5SMarcel Moolenaar * offset and not the size or offset in sectors. 269dc344ca5SMarcel Moolenaar * So how can we map the byte-oriented value into a sector- 270dc344ca5SMarcel Moolenaar * oriented value if we don't know the sector size in bytes? 271dc344ca5SMarcel Moolenaar * The approach taken here is: 272dc344ca5SMarcel Moolenaar * o Sectors are 512 bytes in size. Mostly the case anyway. 273dc344ca5SMarcel Moolenaar * o When no SI unit is specified the value is in sectors. 274dc344ca5SMarcel Moolenaar * o With an SI unit the value is in bytes. 275dc344ca5SMarcel Moolenaar * o The 'b' suffix forces byte interpretation and the 's' 276dc344ca5SMarcel Moolenaar * suffix forces sector interpretation. 277dc344ca5SMarcel Moolenaar * 278dc344ca5SMarcel Moolenaar * Thus: 279dc344ca5SMarcel Moolenaar * o 2 and 2s mean 2 sectors, and 2b means 2 bytes. 280dc344ca5SMarcel Moolenaar * o 4k and 4kb mean 4096 bytes, and 4ks means 4096 sectors. 281dc344ca5SMarcel Moolenaar * 282dc344ca5SMarcel Moolenaar * "This seemed like a good idea at the time" 283dc344ca5SMarcel Moolenaar */ 284dc344ca5SMarcel Moolenaar intmax_t mult, unit; 28505c91076SPawel Jakub Dawidek 286dc344ca5SMarcel Moolenaar number = strtoimax(val, &s, 0); 287dc344ca5SMarcel Moolenaar if (s == val) 288dc344ca5SMarcel Moolenaar errc(EXIT_FAILURE, EINVAL, "argument '%c'", 289dc344ca5SMarcel Moolenaar opt->go_char); 290dc344ca5SMarcel Moolenaar mult = 1; 291dc344ca5SMarcel Moolenaar unit = 512; /* sector */ 292dc344ca5SMarcel Moolenaar if (*s == '\0') 293dc344ca5SMarcel Moolenaar goto done; 294dc344ca5SMarcel Moolenaar switch (*s) { 295dc344ca5SMarcel Moolenaar case 'e': case 'E': 296dc344ca5SMarcel Moolenaar mult *= 1024; 297dc344ca5SMarcel Moolenaar /*FALLTHROUGH*/ 298dc344ca5SMarcel Moolenaar case 'p': case 'P': 299dc344ca5SMarcel Moolenaar mult *= 1024; 300dc344ca5SMarcel Moolenaar /*FALLTHROUGH*/ 301dc344ca5SMarcel Moolenaar case 't': case 'T': 302dc344ca5SMarcel Moolenaar mult *= 1024; 303dc344ca5SMarcel Moolenaar /*FALLTHROUGH*/ 304dc344ca5SMarcel Moolenaar case 'g': case 'G': 305dc344ca5SMarcel Moolenaar mult *= 1024; 306dc344ca5SMarcel Moolenaar /*FALLTHROUGH*/ 307dc344ca5SMarcel Moolenaar case 'm': case 'M': 308dc344ca5SMarcel Moolenaar mult *= 1024; 309dc344ca5SMarcel Moolenaar /*FALLTHROUGH*/ 310dc344ca5SMarcel Moolenaar case 'k': case 'K': 311dc344ca5SMarcel Moolenaar mult *= 1024; 312dc344ca5SMarcel Moolenaar break; 313dc344ca5SMarcel Moolenaar default: 314dc344ca5SMarcel Moolenaar goto sfx; 315dc344ca5SMarcel Moolenaar } 316dc344ca5SMarcel Moolenaar unit = 1; /* bytes */ 317dc344ca5SMarcel Moolenaar s++; 318dc344ca5SMarcel Moolenaar if (*s == '\0') 319dc344ca5SMarcel Moolenaar goto done; 320dc344ca5SMarcel Moolenaar sfx: 321dc344ca5SMarcel Moolenaar switch (*s) { 322dc344ca5SMarcel Moolenaar case 's': case 'S': 323dc344ca5SMarcel Moolenaar unit = 512; /* sector */ 324dc344ca5SMarcel Moolenaar break; 325dc344ca5SMarcel Moolenaar case 'b': case 'B': 326dc344ca5SMarcel Moolenaar unit = 1; /* bytes */ 327dc344ca5SMarcel Moolenaar break; 328dc344ca5SMarcel Moolenaar default: 329dc344ca5SMarcel Moolenaar errc(EXIT_FAILURE, EINVAL, "argument '%c': suffix '%c'", 330dc344ca5SMarcel Moolenaar opt->go_char, *s); 331dc344ca5SMarcel Moolenaar } 332dc344ca5SMarcel Moolenaar s++; 333dc344ca5SMarcel Moolenaar if (*s != '\0') 334dc344ca5SMarcel Moolenaar errx(EXIT_FAILURE, "argument '%c': junk at end (%s)", 335dc344ca5SMarcel Moolenaar opt->go_char, s); 336dc344ca5SMarcel Moolenaar done: 337dc344ca5SMarcel Moolenaar if (mult * unit < mult || number * mult * unit < number) 338dc344ca5SMarcel Moolenaar errc(EXIT_FAILURE, ERANGE, "argument '%c'", 339dc344ca5SMarcel Moolenaar opt->go_char); 340dc344ca5SMarcel Moolenaar number *= mult * unit; 341dc344ca5SMarcel Moolenaar if (number % 512) 342dc344ca5SMarcel Moolenaar errx(EXIT_FAILURE, "argument '%c': " 343dc344ca5SMarcel Moolenaar "not a valid block address", opt->go_char); 344dc344ca5SMarcel Moolenaar number /= 512; 345dc344ca5SMarcel Moolenaar asprintf(&s, "%jd", number); 346dc344ca5SMarcel Moolenaar if (s == NULL) 347dc344ca5SMarcel Moolenaar err(EXIT_FAILURE, NULL); 348dc344ca5SMarcel Moolenaar opt->go_val = s; 349dc344ca5SMarcel Moolenaar gctl_ro_param(req, opt->go_name, -1, s); 3506fc60008SPawel Jakub Dawidek } else if (G_OPT_TYPE(opt) == G_TYPE_STRING) { 35176490718SPawel Jakub Dawidek gctl_ro_param(req, opt->go_name, -1, val); 3526fc60008SPawel Jakub Dawidek } else if (G_OPT_TYPE(opt) == G_TYPE_BOOL) { 35305c91076SPawel Jakub Dawidek opt->go_val = malloc(sizeof(int)); 35405c91076SPawel Jakub Dawidek if (opt->go_val == NULL) 35505c91076SPawel Jakub Dawidek errx(EXIT_FAILURE, "No memory."); 35605c91076SPawel Jakub Dawidek *(int *)opt->go_val = *val - '0'; 357dc344ca5SMarcel Moolenaar gctl_ro_param(req, opt->go_name, sizeof(int), opt->go_val); 3586fc60008SPawel Jakub Dawidek } else { 3596fc60008SPawel Jakub Dawidek assert(!"Invalid type"); 36005c91076SPawel Jakub Dawidek } 36105c91076SPawel Jakub Dawidek } 36205c91076SPawel Jakub Dawidek 36305c91076SPawel Jakub Dawidek /* 36405c91076SPawel Jakub Dawidek * 1. Add given argument by caller. 36505c91076SPawel Jakub Dawidek * 2. Add default values of not given arguments. 36605c91076SPawel Jakub Dawidek * 3. Add the rest of arguments. 36705c91076SPawel Jakub Dawidek */ 36805c91076SPawel Jakub Dawidek static void 36905c91076SPawel Jakub Dawidek parse_arguments(struct g_command *cmd, struct gctl_req *req, int *argc, 37005c91076SPawel Jakub Dawidek char ***argv) 37105c91076SPawel Jakub Dawidek { 37205c91076SPawel Jakub Dawidek struct g_option *opt; 37305c91076SPawel Jakub Dawidek char opts[64]; 37405c91076SPawel Jakub Dawidek unsigned i; 37505c91076SPawel Jakub Dawidek int ch; 37605c91076SPawel Jakub Dawidek 37705c91076SPawel Jakub Dawidek *opts = '\0'; 37805c91076SPawel Jakub Dawidek if ((cmd->gc_flags & G_FLAG_VERBOSE) != 0) 37905c91076SPawel Jakub Dawidek strlcat(opts, "v", sizeof(opts)); 38005c91076SPawel Jakub Dawidek for (i = 0; ; i++) { 38105c91076SPawel Jakub Dawidek opt = &cmd->gc_options[i]; 38205c91076SPawel Jakub Dawidek if (opt->go_name == NULL) 38305c91076SPawel Jakub Dawidek break; 3846fc60008SPawel Jakub Dawidek assert(G_OPT_TYPE(opt) != 0); 3856fc60008SPawel Jakub Dawidek assert((opt->go_type & ~G_TYPE_MASK) == 0); 38605c91076SPawel Jakub Dawidek strlcatf(opts, sizeof(opts), "%c", opt->go_char); 3876fc60008SPawel Jakub Dawidek if (G_OPT_TYPE(opt) != G_TYPE_BOOL) 38805c91076SPawel Jakub Dawidek strlcat(opts, ":", sizeof(opts)); 38905c91076SPawel Jakub Dawidek } 39005c91076SPawel Jakub Dawidek 39105c91076SPawel Jakub Dawidek /* 39205c91076SPawel Jakub Dawidek * Add specified arguments. 39305c91076SPawel Jakub Dawidek */ 39405c91076SPawel Jakub Dawidek while ((ch = getopt(*argc, *argv, opts)) != -1) { 39505c91076SPawel Jakub Dawidek /* Standard (not passed to kernel) options. */ 39605c91076SPawel Jakub Dawidek switch (ch) { 39705c91076SPawel Jakub Dawidek case 'v': 39805c91076SPawel Jakub Dawidek verbose = 1; 39905c91076SPawel Jakub Dawidek continue; 40005c91076SPawel Jakub Dawidek } 40105c91076SPawel Jakub Dawidek /* Options passed to kernel. */ 40205c91076SPawel Jakub Dawidek opt = find_option(cmd, ch); 40305c91076SPawel Jakub Dawidek if (opt == NULL) 404c979e206SPawel Jakub Dawidek usage(); 40505c91076SPawel Jakub Dawidek if (G_OPT_ISDONE(opt)) { 4066fc60008SPawel Jakub Dawidek warnx("Option '%c' specified twice.", opt->go_char); 407c979e206SPawel Jakub Dawidek usage(); 40805c91076SPawel Jakub Dawidek } 40905c91076SPawel Jakub Dawidek G_OPT_DONE(opt); 41005c91076SPawel Jakub Dawidek 4116fc60008SPawel Jakub Dawidek if (G_OPT_TYPE(opt) == G_TYPE_BOOL) 41205c91076SPawel Jakub Dawidek set_option(req, opt, "1"); 41305c91076SPawel Jakub Dawidek else 41405c91076SPawel Jakub Dawidek set_option(req, opt, optarg); 41505c91076SPawel Jakub Dawidek } 41605c91076SPawel Jakub Dawidek *argc -= optind; 41705c91076SPawel Jakub Dawidek *argv += optind; 41805c91076SPawel Jakub Dawidek 41905c91076SPawel Jakub Dawidek /* 42005c91076SPawel Jakub Dawidek * Add not specified arguments, but with default values. 42105c91076SPawel Jakub Dawidek */ 42205c91076SPawel Jakub Dawidek for (i = 0; ; i++) { 42305c91076SPawel Jakub Dawidek opt = &cmd->gc_options[i]; 42405c91076SPawel Jakub Dawidek if (opt->go_name == NULL) 42505c91076SPawel Jakub Dawidek break; 42605c91076SPawel Jakub Dawidek if (G_OPT_ISDONE(opt)) 42705c91076SPawel Jakub Dawidek continue; 42805c91076SPawel Jakub Dawidek 4296fc60008SPawel Jakub Dawidek if (G_OPT_TYPE(opt) == G_TYPE_BOOL) { 43005c91076SPawel Jakub Dawidek assert(opt->go_val == NULL); 43105c91076SPawel Jakub Dawidek set_option(req, opt, "0"); 43205c91076SPawel Jakub Dawidek } else { 43305c91076SPawel Jakub Dawidek if (opt->go_val == NULL) { 4346fc60008SPawel Jakub Dawidek warnx("Option '%c' not specified.", 43505c91076SPawel Jakub Dawidek opt->go_char); 436c979e206SPawel Jakub Dawidek usage(); 43705c91076SPawel Jakub Dawidek } else { 4386fc60008SPawel Jakub Dawidek if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) { 43905c91076SPawel Jakub Dawidek gctl_ro_param(req, opt->go_name, 44005c91076SPawel Jakub Dawidek sizeof(intmax_t), opt->go_val); 441dc344ca5SMarcel Moolenaar } else if (G_OPT_TYPE(opt) == G_TYPE_STRING || 442dc344ca5SMarcel Moolenaar G_OPT_TYPE(opt) == G_TYPE_ASCNUM || 443dc344ca5SMarcel Moolenaar G_OPT_TYPE(opt) == G_TYPE_ASCLBA) { 444cf805fabSMarcel Moolenaar if (cmd->gc_argname == NULL || 445cf805fabSMarcel Moolenaar opt->go_val == NULL || 446cf805fabSMarcel Moolenaar *(char *)opt->go_val != '\0') 4473cf55d3aSMarcel Moolenaar gctl_ro_param(req, opt->go_name, 4483cf55d3aSMarcel Moolenaar -1, opt->go_val); 4496fc60008SPawel Jakub Dawidek } else { 4506fc60008SPawel Jakub Dawidek assert(!"Invalid type"); 45105c91076SPawel Jakub Dawidek } 45205c91076SPawel Jakub Dawidek } 45305c91076SPawel Jakub Dawidek } 45405c91076SPawel Jakub Dawidek } 4553cf55d3aSMarcel Moolenaar 4563cf55d3aSMarcel Moolenaar if (cmd->gc_argname == NULL) { 45705c91076SPawel Jakub Dawidek /* 45805c91076SPawel Jakub Dawidek * Add rest of given arguments. 45905c91076SPawel Jakub Dawidek */ 46005c91076SPawel Jakub Dawidek gctl_ro_param(req, "nargs", sizeof(int), argc); 46105c91076SPawel Jakub Dawidek for (i = 0; i < (unsigned)*argc; i++) { 46205c91076SPawel Jakub Dawidek char argname[16]; 46305c91076SPawel Jakub Dawidek 46405c91076SPawel Jakub Dawidek snprintf(argname, sizeof(argname), "arg%u", i); 46505c91076SPawel Jakub Dawidek gctl_ro_param(req, argname, -1, (*argv)[i]); 46605c91076SPawel Jakub Dawidek } 4673cf55d3aSMarcel Moolenaar } else { 4683cf55d3aSMarcel Moolenaar if (*argc != 1) 4693cf55d3aSMarcel Moolenaar usage(); 4703cf55d3aSMarcel Moolenaar gctl_ro_param(req, cmd->gc_argname, -1, (*argv)[0]); 4713cf55d3aSMarcel Moolenaar } 47205c91076SPawel Jakub Dawidek } 47305c91076SPawel Jakub Dawidek 47405c91076SPawel Jakub Dawidek /* 47505c91076SPawel Jakub Dawidek * Find given command in commands available for given class. 47605c91076SPawel Jakub Dawidek */ 47705c91076SPawel Jakub Dawidek static struct g_command * 478138cedfdSPawel Jakub Dawidek find_command(const char *cmdstr, int flags) 47905c91076SPawel Jakub Dawidek { 48005c91076SPawel Jakub Dawidek struct g_command *cmd; 48105c91076SPawel Jakub Dawidek unsigned i; 48205c91076SPawel Jakub Dawidek 48305c91076SPawel Jakub Dawidek /* 48405c91076SPawel Jakub Dawidek * First try to find command defined by loaded library. 48505c91076SPawel Jakub Dawidek */ 486138cedfdSPawel Jakub Dawidek if ((flags & GEOM_CLASS_CMDS) != 0 && class_commands != NULL) { 48705c91076SPawel Jakub Dawidek for (i = 0; ; i++) { 48805c91076SPawel Jakub Dawidek cmd = &class_commands[i]; 48905c91076SPawel Jakub Dawidek if (cmd->gc_name == NULL) 49005c91076SPawel Jakub Dawidek break; 49105c91076SPawel Jakub Dawidek if (strcmp(cmd->gc_name, cmdstr) == 0) 49205c91076SPawel Jakub Dawidek return (cmd); 49305c91076SPawel Jakub Dawidek } 49405c91076SPawel Jakub Dawidek } 49505c91076SPawel Jakub Dawidek /* 49605c91076SPawel Jakub Dawidek * Now try to find in standard commands. 49705c91076SPawel Jakub Dawidek */ 498138cedfdSPawel Jakub Dawidek if ((flags & GEOM_STD_CMDS) != 0) { 49905c91076SPawel Jakub Dawidek for (i = 0; ; i++) { 50005c91076SPawel Jakub Dawidek cmd = &std_commands[i]; 50105c91076SPawel Jakub Dawidek if (cmd->gc_name == NULL) 50205c91076SPawel Jakub Dawidek break; 50305c91076SPawel Jakub Dawidek if (strcmp(cmd->gc_name, cmdstr) == 0) 50405c91076SPawel Jakub Dawidek return (cmd); 50505c91076SPawel Jakub Dawidek } 506138cedfdSPawel Jakub Dawidek } 50705c91076SPawel Jakub Dawidek return (NULL); 50805c91076SPawel Jakub Dawidek } 50905c91076SPawel Jakub Dawidek 51005c91076SPawel Jakub Dawidek static unsigned 51105c91076SPawel Jakub Dawidek set_flags(struct g_command *cmd) 51205c91076SPawel Jakub Dawidek { 51305c91076SPawel Jakub Dawidek unsigned flags = 0; 51405c91076SPawel Jakub Dawidek 51505c91076SPawel Jakub Dawidek if ((cmd->gc_flags & G_FLAG_VERBOSE) != 0 && verbose) 51605c91076SPawel Jakub Dawidek flags |= G_FLAG_VERBOSE; 51705c91076SPawel Jakub Dawidek 51805c91076SPawel Jakub Dawidek return (flags); 51905c91076SPawel Jakub Dawidek } 52005c91076SPawel Jakub Dawidek 52105c91076SPawel Jakub Dawidek /* 52205c91076SPawel Jakub Dawidek * Run command. 52305c91076SPawel Jakub Dawidek */ 52405c91076SPawel Jakub Dawidek static void 52505c91076SPawel Jakub Dawidek run_command(int argc, char *argv[]) 52605c91076SPawel Jakub Dawidek { 52705c91076SPawel Jakub Dawidek struct g_command *cmd; 52805c91076SPawel Jakub Dawidek struct gctl_req *req; 52905c91076SPawel Jakub Dawidek const char *errstr; 53005c91076SPawel Jakub Dawidek char buf[4096]; 53105c91076SPawel Jakub Dawidek 532138cedfdSPawel Jakub Dawidek /* First try to find a command defined by a class. */ 533138cedfdSPawel Jakub Dawidek cmd = find_command(argv[0], GEOM_CLASS_CMDS); 534138cedfdSPawel Jakub Dawidek if (cmd == NULL) { 535138cedfdSPawel Jakub Dawidek /* Now, try to find a standard command. */ 536138cedfdSPawel Jakub Dawidek cmd = find_command(argv[0], GEOM_STD_CMDS); 53705c91076SPawel Jakub Dawidek if (cmd == NULL) { 5386fc60008SPawel Jakub Dawidek warnx("Unknown command: %s.", argv[0]); 539c979e206SPawel Jakub Dawidek usage(); 54005c91076SPawel Jakub Dawidek } 541138cedfdSPawel Jakub Dawidek if (!std_available(cmd->gc_name)) { 5426fc60008SPawel Jakub Dawidek warnx("Command '%s' not available.", argv[0]); 543138cedfdSPawel Jakub Dawidek exit(EXIT_FAILURE); 544138cedfdSPawel Jakub Dawidek } 545138cedfdSPawel Jakub Dawidek } 54605c91076SPawel Jakub Dawidek if ((cmd->gc_flags & G_FLAG_LOADKLD) != 0) 54705c91076SPawel Jakub Dawidek load_module(); 54805c91076SPawel Jakub Dawidek 54905c91076SPawel Jakub Dawidek req = gctl_get_handle(); 55005c91076SPawel Jakub Dawidek gctl_ro_param(req, "class", -1, gclass_name); 55105c91076SPawel Jakub Dawidek gctl_ro_param(req, "verb", -1, argv[0]); 55205c91076SPawel Jakub Dawidek if (version != NULL) 55305c91076SPawel Jakub Dawidek gctl_ro_param(req, "version", sizeof(*version), version); 55405c91076SPawel Jakub Dawidek parse_arguments(cmd, req, &argc, &argv); 55505c91076SPawel Jakub Dawidek 5561bcfab7fSPawel Jakub Dawidek bzero(buf, sizeof(buf)); 55705c91076SPawel Jakub Dawidek if (cmd->gc_func != NULL) { 55805c91076SPawel Jakub Dawidek unsigned flags; 55905c91076SPawel Jakub Dawidek 56005c91076SPawel Jakub Dawidek flags = set_flags(cmd); 56105c91076SPawel Jakub Dawidek cmd->gc_func(req, flags); 56205c91076SPawel Jakub Dawidek errstr = req->error; 56305c91076SPawel Jakub Dawidek } else { 56405c91076SPawel Jakub Dawidek gctl_rw_param(req, "output", sizeof(buf), buf); 56505c91076SPawel Jakub Dawidek errstr = gctl_issue(req); 56605c91076SPawel Jakub Dawidek } 56753767efdSPawel Jakub Dawidek if (errstr != NULL && errstr[0] != '\0') { 5686fc60008SPawel Jakub Dawidek warnx("%s", errstr); 569f792f1d8SPawel Jakub Dawidek if (strncmp(errstr, "warning: ", strlen("warning: ")) != 0) { 57005c91076SPawel Jakub Dawidek gctl_free(req); 57105c91076SPawel Jakub Dawidek exit(EXIT_FAILURE); 57205c91076SPawel Jakub Dawidek } 573f792f1d8SPawel Jakub Dawidek } 5741bcfab7fSPawel Jakub Dawidek if (buf[0] != '\0') 57505c91076SPawel Jakub Dawidek printf("%s", buf); 57605c91076SPawel Jakub Dawidek gctl_free(req); 57705c91076SPawel Jakub Dawidek if (verbose) 57805c91076SPawel Jakub Dawidek printf("Done.\n"); 57905c91076SPawel Jakub Dawidek exit(EXIT_SUCCESS); 58005c91076SPawel Jakub Dawidek } 58105c91076SPawel Jakub Dawidek 58214bf405bSMarcel Moolenaar #ifndef STATIC_GEOM_CLASSES 5833bad06e9SPawel Jakub Dawidek static const char * 5843bad06e9SPawel Jakub Dawidek library_path(void) 5853bad06e9SPawel Jakub Dawidek { 5863bad06e9SPawel Jakub Dawidek const char *path; 5873bad06e9SPawel Jakub Dawidek 5883bad06e9SPawel Jakub Dawidek path = getenv("GEOM_LIBRARY_PATH"); 5893bad06e9SPawel Jakub Dawidek if (path == NULL) 5903bad06e9SPawel Jakub Dawidek path = CLASS_DIR; 5913bad06e9SPawel Jakub Dawidek return (path); 5923bad06e9SPawel Jakub Dawidek } 5933bad06e9SPawel Jakub Dawidek 59405c91076SPawel Jakub Dawidek static void 59505c91076SPawel Jakub Dawidek load_library(void) 59605c91076SPawel Jakub Dawidek { 5975d824386SUlf Lilleengen char *curpath, path[MAXPATHLEN], *tofree, *totalpath; 59805c91076SPawel Jakub Dawidek uint32_t *lib_version; 59905c91076SPawel Jakub Dawidek void *dlh; 6002591e96cSUlf Lilleengen int ret; 60105c91076SPawel Jakub Dawidek 6022591e96cSUlf Lilleengen ret = 0; 6035d824386SUlf Lilleengen tofree = totalpath = strdup(library_path()); 6042591e96cSUlf Lilleengen if (totalpath == NULL) 6052591e96cSUlf Lilleengen err(EXIT_FAILURE, "Not enough memory for library path"); 6062591e96cSUlf Lilleengen 6072591e96cSUlf Lilleengen if (strchr(totalpath, ':') != NULL) 6082591e96cSUlf Lilleengen curpath = strsep(&totalpath, ":"); 6092591e96cSUlf Lilleengen else 6102591e96cSUlf Lilleengen curpath = totalpath; 6112591e96cSUlf Lilleengen /* Traverse the paths to find one that contains the library we want. */ 6122591e96cSUlf Lilleengen while (curpath != NULL) { 6132591e96cSUlf Lilleengen snprintf(path, sizeof(path), "%s/geom_%s.so", curpath, 6143bad06e9SPawel Jakub Dawidek class_name); 6152591e96cSUlf Lilleengen ret = access(path, F_OK); 6162591e96cSUlf Lilleengen if (ret == -1) { 617a73148d2SPawel Jakub Dawidek if (errno == ENOENT) { 61805c91076SPawel Jakub Dawidek /* 6192591e96cSUlf Lilleengen * If we cannot find library, try the next 6202591e96cSUlf Lilleengen * path. 62105c91076SPawel Jakub Dawidek */ 6222591e96cSUlf Lilleengen curpath = strsep(&totalpath, ":"); 6232591e96cSUlf Lilleengen continue; 62405c91076SPawel Jakub Dawidek } 625a73148d2SPawel Jakub Dawidek err(EXIT_FAILURE, "Cannot access library"); 626a73148d2SPawel Jakub Dawidek } 6272591e96cSUlf Lilleengen break; 6282591e96cSUlf Lilleengen } 6295d824386SUlf Lilleengen free(tofree); 6302591e96cSUlf Lilleengen /* No library was found, but standard commands can still be used */ 6312591e96cSUlf Lilleengen if (ret == -1) 6322591e96cSUlf Lilleengen return; 633a73148d2SPawel Jakub Dawidek dlh = dlopen(path, RTLD_NOW); 634a73148d2SPawel Jakub Dawidek if (dlh == NULL) 635a73148d2SPawel Jakub Dawidek errx(EXIT_FAILURE, "Cannot open library: %s.", dlerror()); 63605c91076SPawel Jakub Dawidek lib_version = dlsym(dlh, "lib_version"); 63705c91076SPawel Jakub Dawidek if (lib_version == NULL) { 6386fc60008SPawel Jakub Dawidek warnx("Cannot find symbol %s: %s.", "lib_version", dlerror()); 63905c91076SPawel Jakub Dawidek dlclose(dlh); 64005c91076SPawel Jakub Dawidek exit(EXIT_FAILURE); 64105c91076SPawel Jakub Dawidek } 64205c91076SPawel Jakub Dawidek if (*lib_version != G_LIB_VERSION) { 64305c91076SPawel Jakub Dawidek dlclose(dlh); 644f792f1d8SPawel Jakub Dawidek errx(EXIT_FAILURE, "%s and %s are not synchronized.", 645f792f1d8SPawel Jakub Dawidek getprogname(), path); 64605c91076SPawel Jakub Dawidek } 64705c91076SPawel Jakub Dawidek version = dlsym(dlh, "version"); 64805c91076SPawel Jakub Dawidek if (version == NULL) { 6496fc60008SPawel Jakub Dawidek warnx("Cannot find symbol %s: %s.", "version", dlerror()); 65005c91076SPawel Jakub Dawidek dlclose(dlh); 65105c91076SPawel Jakub Dawidek exit(EXIT_FAILURE); 65205c91076SPawel Jakub Dawidek } 65305c91076SPawel Jakub Dawidek class_commands = dlsym(dlh, "class_commands"); 65405c91076SPawel Jakub Dawidek if (class_commands == NULL) { 6556fc60008SPawel Jakub Dawidek warnx("Cannot find symbol %s: %s.", "class_commands", 6566fc60008SPawel Jakub Dawidek dlerror()); 65705c91076SPawel Jakub Dawidek dlclose(dlh); 65805c91076SPawel Jakub Dawidek exit(EXIT_FAILURE); 65905c91076SPawel Jakub Dawidek } 66005c91076SPawel Jakub Dawidek } 66114bf405bSMarcel Moolenaar #endif /* !STATIC_GEOM_CLASSES */ 66205c91076SPawel Jakub Dawidek 66305c91076SPawel Jakub Dawidek /* 66405c91076SPawel Jakub Dawidek * Class name should be all capital letters. 66505c91076SPawel Jakub Dawidek */ 66605c91076SPawel Jakub Dawidek static void 66705c91076SPawel Jakub Dawidek set_class_name(void) 66805c91076SPawel Jakub Dawidek { 66905c91076SPawel Jakub Dawidek char *s1, *s2; 67005c91076SPawel Jakub Dawidek 671ee602fbbSPawel Jakub Dawidek s1 = class_name; 672ee602fbbSPawel Jakub Dawidek for (; *s1 != '\0'; s1++) 673ee602fbbSPawel Jakub Dawidek *s1 = tolower(*s1); 674cb94ab30SPawel Jakub Dawidek gclass_name = malloc(strlen(class_name) + 1); 67505c91076SPawel Jakub Dawidek if (gclass_name == NULL) 67605c91076SPawel Jakub Dawidek errx(EXIT_FAILURE, "No memory"); 67705c91076SPawel Jakub Dawidek s1 = gclass_name; 67805c91076SPawel Jakub Dawidek s2 = class_name; 67905c91076SPawel Jakub Dawidek for (; *s2 != '\0'; s2++) 68005c91076SPawel Jakub Dawidek *s1++ = toupper(*s2); 68105c91076SPawel Jakub Dawidek *s1 = '\0'; 68205c91076SPawel Jakub Dawidek } 68305c91076SPawel Jakub Dawidek 68405c91076SPawel Jakub Dawidek static void 68505c91076SPawel Jakub Dawidek get_class(int *argc, char ***argv) 68605c91076SPawel Jakub Dawidek { 68705c91076SPawel Jakub Dawidek 68805c91076SPawel Jakub Dawidek snprintf(comm, sizeof(comm), "%s", basename((*argv)[0])); 68905c91076SPawel Jakub Dawidek if (strcmp(comm, "geom") == 0) { 69005c91076SPawel Jakub Dawidek if (*argc < 2) 691c979e206SPawel Jakub Dawidek usage(); 692687b0015SPawel Jakub Dawidek else if (*argc == 2) { 693687b0015SPawel Jakub Dawidek if (strcmp((*argv)[1], "-h") == 0 || 694687b0015SPawel Jakub Dawidek strcmp((*argv)[1], "help") == 0) { 695c979e206SPawel Jakub Dawidek usage(); 696687b0015SPawel Jakub Dawidek } 697687b0015SPawel Jakub Dawidek } 69805c91076SPawel Jakub Dawidek strlcatf(comm, sizeof(comm), " %s", (*argv)[1]); 69905c91076SPawel Jakub Dawidek class_name = (*argv)[1]; 70005c91076SPawel Jakub Dawidek *argc -= 2; 70105c91076SPawel Jakub Dawidek *argv += 2; 70205c91076SPawel Jakub Dawidek } else if (*comm == 'g') { 70305c91076SPawel Jakub Dawidek class_name = comm + 1; 70405c91076SPawel Jakub Dawidek *argc -= 1; 70505c91076SPawel Jakub Dawidek *argv += 1; 70605c91076SPawel Jakub Dawidek } else { 70705c91076SPawel Jakub Dawidek errx(EXIT_FAILURE, "Invalid utility name."); 70805c91076SPawel Jakub Dawidek } 709a16f9b36SMarcel Moolenaar 71014bf405bSMarcel Moolenaar #ifndef STATIC_GEOM_CLASSES 71105c91076SPawel Jakub Dawidek load_library(); 712a16f9b36SMarcel Moolenaar #else 713a16f9b36SMarcel Moolenaar if (!strcasecmp(class_name, "part")) { 714a16f9b36SMarcel Moolenaar version = &gpart_version; 715a16f9b36SMarcel Moolenaar class_commands = gpart_class_commands; 716bc69d66fSXin LI } else if (!strcasecmp(class_name, "label")) { 717bc69d66fSXin LI version = &glabel_version; 718bc69d66fSXin LI class_commands = glabel_class_commands; 719a16f9b36SMarcel Moolenaar } else 720a16f9b36SMarcel Moolenaar errx(EXIT_FAILURE, "Invalid class name."); 72114bf405bSMarcel Moolenaar #endif /* !STATIC_GEOM_CLASSES */ 722a16f9b36SMarcel Moolenaar 723a16f9b36SMarcel Moolenaar set_class_name(); 72405c91076SPawel Jakub Dawidek if (*argc < 1) 725c979e206SPawel Jakub Dawidek usage(); 72605c91076SPawel Jakub Dawidek } 72705c91076SPawel Jakub Dawidek 72805c91076SPawel Jakub Dawidek int 72905c91076SPawel Jakub Dawidek main(int argc, char *argv[]) 73005c91076SPawel Jakub Dawidek { 73105c91076SPawel Jakub Dawidek 73205c91076SPawel Jakub Dawidek get_class(&argc, &argv); 73305c91076SPawel Jakub Dawidek run_command(argc, argv); 73405c91076SPawel Jakub Dawidek /* NOTREACHED */ 73505c91076SPawel Jakub Dawidek 73605c91076SPawel Jakub Dawidek exit(EXIT_FAILURE); 73705c91076SPawel Jakub Dawidek } 73805c91076SPawel Jakub Dawidek 73905c91076SPawel Jakub Dawidek static struct gclass * 74005c91076SPawel Jakub Dawidek find_class(struct gmesh *mesh, const char *name) 74105c91076SPawel Jakub Dawidek { 74205c91076SPawel Jakub Dawidek struct gclass *classp; 74305c91076SPawel Jakub Dawidek 74405c91076SPawel Jakub Dawidek LIST_FOREACH(classp, &mesh->lg_class, lg_class) { 74505c91076SPawel Jakub Dawidek if (strcmp(classp->lg_name, name) == 0) 74605c91076SPawel Jakub Dawidek return (classp); 74705c91076SPawel Jakub Dawidek } 74805c91076SPawel Jakub Dawidek return (NULL); 74905c91076SPawel Jakub Dawidek } 75005c91076SPawel Jakub Dawidek 7511d723f1dSPawel Jakub Dawidek static struct ggeom * 7521d723f1dSPawel Jakub Dawidek find_geom(struct gclass *classp, const char *name) 75305c91076SPawel Jakub Dawidek { 75405c91076SPawel Jakub Dawidek struct ggeom *gp; 75505c91076SPawel Jakub Dawidek 75605c91076SPawel Jakub Dawidek LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 7571d723f1dSPawel Jakub Dawidek if (strcmp(gp->lg_name, name) == 0) 7581d723f1dSPawel Jakub Dawidek return (gp); 75905c91076SPawel Jakub Dawidek } 76005c91076SPawel Jakub Dawidek return (NULL); 76105c91076SPawel Jakub Dawidek } 76205c91076SPawel Jakub Dawidek 76305c91076SPawel Jakub Dawidek static void 7642d76e2dbSPawel Jakub Dawidek list_one_provider(struct gprovider *pp, const char *prefix) 76505c91076SPawel Jakub Dawidek { 76605c91076SPawel Jakub Dawidek struct gconfig *conf; 767af565b58SPawel Jakub Dawidek char buf[5]; 76805c91076SPawel Jakub Dawidek 7691d723f1dSPawel Jakub Dawidek printf("Name: %s\n", pp->lg_name); 770af565b58SPawel Jakub Dawidek humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "", 771af565b58SPawel Jakub Dawidek HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 7721d723f1dSPawel Jakub Dawidek printf("%sMediasize: %jd (%s)\n", prefix, (intmax_t)pp->lg_mediasize, 7731d723f1dSPawel Jakub Dawidek buf); 7741d723f1dSPawel Jakub Dawidek printf("%sSectorsize: %u\n", prefix, pp->lg_sectorsize); 7751d723f1dSPawel Jakub Dawidek printf("%sMode: %s\n", prefix, pp->lg_mode); 77605c91076SPawel Jakub Dawidek LIST_FOREACH(conf, &pp->lg_config, lg_config) { 7771d723f1dSPawel Jakub Dawidek printf("%s%s: %s\n", prefix, conf->lg_name, conf->lg_val); 7781d723f1dSPawel Jakub Dawidek } 7791d723f1dSPawel Jakub Dawidek } 7801d723f1dSPawel Jakub Dawidek 7811d723f1dSPawel Jakub Dawidek static void 7822d76e2dbSPawel Jakub Dawidek list_one_consumer(struct gconsumer *cp, const char *prefix) 7831d723f1dSPawel Jakub Dawidek { 7841d723f1dSPawel Jakub Dawidek struct gprovider *pp; 7851d723f1dSPawel Jakub Dawidek struct gconfig *conf; 7861d723f1dSPawel Jakub Dawidek 7871d723f1dSPawel Jakub Dawidek pp = cp->lg_provider; 7881d723f1dSPawel Jakub Dawidek if (pp == NULL) 7891d723f1dSPawel Jakub Dawidek printf("[no provider]\n"); 7901d723f1dSPawel Jakub Dawidek else { 7911d723f1dSPawel Jakub Dawidek char buf[5]; 7921d723f1dSPawel Jakub Dawidek 7931d723f1dSPawel Jakub Dawidek printf("Name: %s\n", pp->lg_name); 7941d723f1dSPawel Jakub Dawidek humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "", 7951d723f1dSPawel Jakub Dawidek HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 7961d723f1dSPawel Jakub Dawidek printf("%sMediasize: %jd (%s)\n", prefix, 7971d723f1dSPawel Jakub Dawidek (intmax_t)pp->lg_mediasize, buf); 7981d723f1dSPawel Jakub Dawidek printf("%sSectorsize: %u\n", prefix, pp->lg_sectorsize); 7991d723f1dSPawel Jakub Dawidek printf("%sMode: %s\n", prefix, cp->lg_mode); 8001d723f1dSPawel Jakub Dawidek } 8011d723f1dSPawel Jakub Dawidek LIST_FOREACH(conf, &cp->lg_config, lg_config) { 8021d723f1dSPawel Jakub Dawidek printf("%s%s: %s\n", prefix, conf->lg_name, conf->lg_val); 8031d723f1dSPawel Jakub Dawidek } 8041d723f1dSPawel Jakub Dawidek } 8051d723f1dSPawel Jakub Dawidek 8061d723f1dSPawel Jakub Dawidek static void 8072d76e2dbSPawel Jakub Dawidek list_one_geom(struct ggeom *gp) 8081d723f1dSPawel Jakub Dawidek { 8091d723f1dSPawel Jakub Dawidek struct gprovider *pp; 8101d723f1dSPawel Jakub Dawidek struct gconsumer *cp; 8111d723f1dSPawel Jakub Dawidek struct gconfig *conf; 8121d723f1dSPawel Jakub Dawidek unsigned n; 8131d723f1dSPawel Jakub Dawidek 8141d723f1dSPawel Jakub Dawidek printf("Geom name: %s\n", gp->lg_name); 8151d723f1dSPawel Jakub Dawidek LIST_FOREACH(conf, &gp->lg_config, lg_config) { 8161d723f1dSPawel Jakub Dawidek printf("%s: %s\n", conf->lg_name, conf->lg_val); 8171d723f1dSPawel Jakub Dawidek } 8181d723f1dSPawel Jakub Dawidek if (!LIST_EMPTY(&gp->lg_provider)) { 8191d723f1dSPawel Jakub Dawidek printf("Providers:\n"); 8201d723f1dSPawel Jakub Dawidek n = 1; 8211d723f1dSPawel Jakub Dawidek LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 8221d723f1dSPawel Jakub Dawidek printf("%u. ", n++); 8232d76e2dbSPawel Jakub Dawidek list_one_provider(pp, " "); 8241d723f1dSPawel Jakub Dawidek } 8251d723f1dSPawel Jakub Dawidek } 8261d723f1dSPawel Jakub Dawidek if (!LIST_EMPTY(&gp->lg_consumer)) { 8271d723f1dSPawel Jakub Dawidek printf("Consumers:\n"); 8281d723f1dSPawel Jakub Dawidek n = 1; 8291d723f1dSPawel Jakub Dawidek LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) { 8301d723f1dSPawel Jakub Dawidek printf("%u. ", n++); 8312d76e2dbSPawel Jakub Dawidek list_one_consumer(cp, " "); 8321d723f1dSPawel Jakub Dawidek } 83305c91076SPawel Jakub Dawidek } 83405c91076SPawel Jakub Dawidek printf("\n"); 83505c91076SPawel Jakub Dawidek } 83605c91076SPawel Jakub Dawidek 837b70eccf3SPawel Jakub Dawidek static void 838b70eccf3SPawel Jakub Dawidek std_help(struct gctl_req *req __unused, unsigned flags __unused) 839b70eccf3SPawel Jakub Dawidek { 840b70eccf3SPawel Jakub Dawidek 841c979e206SPawel Jakub Dawidek usage(); 842b70eccf3SPawel Jakub Dawidek } 843b70eccf3SPawel Jakub Dawidek 84405c91076SPawel Jakub Dawidek static int 84505c91076SPawel Jakub Dawidek std_list_available(void) 84605c91076SPawel Jakub Dawidek { 84705c91076SPawel Jakub Dawidek struct gmesh mesh; 84805c91076SPawel Jakub Dawidek struct gclass *classp; 84905c91076SPawel Jakub Dawidek int error; 85005c91076SPawel Jakub Dawidek 85105c91076SPawel Jakub Dawidek error = geom_gettree(&mesh); 8526fc60008SPawel Jakub Dawidek if (error != 0) 8536fc60008SPawel Jakub Dawidek errc(EXIT_FAILURE, error, "Cannot get GEOM tree"); 85405c91076SPawel Jakub Dawidek classp = find_class(&mesh, gclass_name); 85505c91076SPawel Jakub Dawidek geom_deletetree(&mesh); 85605c91076SPawel Jakub Dawidek if (classp != NULL) 85705c91076SPawel Jakub Dawidek return (1); 85805c91076SPawel Jakub Dawidek return (0); 85905c91076SPawel Jakub Dawidek } 86005c91076SPawel Jakub Dawidek 86105c91076SPawel Jakub Dawidek static void 86205c91076SPawel Jakub Dawidek std_list(struct gctl_req *req, unsigned flags __unused) 86305c91076SPawel Jakub Dawidek { 86405c91076SPawel Jakub Dawidek struct gmesh mesh; 86505c91076SPawel Jakub Dawidek struct gclass *classp; 8661d723f1dSPawel Jakub Dawidek struct ggeom *gp; 867f13942a7SPawel Jakub Dawidek const char *name; 868f13942a7SPawel Jakub Dawidek int error, i, nargs; 86905c91076SPawel Jakub Dawidek 87005c91076SPawel Jakub Dawidek error = geom_gettree(&mesh); 8716fc60008SPawel Jakub Dawidek if (error != 0) 8726fc60008SPawel Jakub Dawidek errc(EXIT_FAILURE, error, "Cannot get GEOM tree"); 87305c91076SPawel Jakub Dawidek classp = find_class(&mesh, gclass_name); 87405c91076SPawel Jakub Dawidek if (classp == NULL) { 87505c91076SPawel Jakub Dawidek geom_deletetree(&mesh); 8765d47cd0fSPawel Jakub Dawidek errx(EXIT_FAILURE, "Class %s not found.", gclass_name); 87705c91076SPawel Jakub Dawidek } 878f13942a7SPawel Jakub Dawidek nargs = gctl_get_int(req, "nargs"); 879f13942a7SPawel Jakub Dawidek if (nargs > 0) { 880f13942a7SPawel Jakub Dawidek for (i = 0; i < nargs; i++) { 881f13942a7SPawel Jakub Dawidek name = gctl_get_ascii(req, "arg%d", i); 8821d723f1dSPawel Jakub Dawidek gp = find_geom(classp, name); 8831d723f1dSPawel Jakub Dawidek if (gp != NULL) 8842d76e2dbSPawel Jakub Dawidek list_one_geom(gp); 8851d723f1dSPawel Jakub Dawidek else 8865d47cd0fSPawel Jakub Dawidek errx(EXIT_FAILURE, "No such geom: %s.", name); 88705c91076SPawel Jakub Dawidek } 88805c91076SPawel Jakub Dawidek } else { 88905c91076SPawel Jakub Dawidek LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 8905fd66a44SPawel Jakub Dawidek if (LIST_EMPTY(&gp->lg_provider)) 8915fd66a44SPawel Jakub Dawidek continue; 8922d76e2dbSPawel Jakub Dawidek list_one_geom(gp); 89305c91076SPawel Jakub Dawidek } 89405c91076SPawel Jakub Dawidek } 89505c91076SPawel Jakub Dawidek geom_deletetree(&mesh); 89605c91076SPawel Jakub Dawidek } 89705c91076SPawel Jakub Dawidek 89805c91076SPawel Jakub Dawidek static int 89918ee8840SPawel Jakub Dawidek std_status_available(void) 90018ee8840SPawel Jakub Dawidek { 90118ee8840SPawel Jakub Dawidek 90218ee8840SPawel Jakub Dawidek /* 'status' command is available when 'list' command is. */ 90318ee8840SPawel Jakub Dawidek return (std_list_available()); 90418ee8840SPawel Jakub Dawidek } 90518ee8840SPawel Jakub Dawidek 90618ee8840SPawel Jakub Dawidek static void 907da80913dSPawel Jakub Dawidek status_update_len(struct ggeom *gp, int *name_len, int *status_len) 90818ee8840SPawel Jakub Dawidek { 90918ee8840SPawel Jakub Dawidek struct gprovider *pp; 91018ee8840SPawel Jakub Dawidek struct gconfig *conf; 911da80913dSPawel Jakub Dawidek int len; 91218ee8840SPawel Jakub Dawidek 91318ee8840SPawel Jakub Dawidek assert(gp != NULL); 91418ee8840SPawel Jakub Dawidek assert(name_len != NULL); 91518ee8840SPawel Jakub Dawidek assert(status_len != NULL); 91618ee8840SPawel Jakub Dawidek 91718ee8840SPawel Jakub Dawidek pp = LIST_FIRST(&gp->lg_provider); 91818ee8840SPawel Jakub Dawidek if (pp != NULL) 91918ee8840SPawel Jakub Dawidek len = strlen(pp->lg_name); 92018ee8840SPawel Jakub Dawidek else 92118ee8840SPawel Jakub Dawidek len = strlen(gp->lg_name); 92218ee8840SPawel Jakub Dawidek if (*name_len < len) 92318ee8840SPawel Jakub Dawidek *name_len = len; 92418ee8840SPawel Jakub Dawidek LIST_FOREACH(conf, &gp->lg_config, lg_config) { 92518ee8840SPawel Jakub Dawidek if (strcasecmp(conf->lg_name, "state") == 0) { 92618ee8840SPawel Jakub Dawidek len = strlen(conf->lg_val); 92718ee8840SPawel Jakub Dawidek if (*status_len < len) 92818ee8840SPawel Jakub Dawidek *status_len = len; 92918ee8840SPawel Jakub Dawidek } 93018ee8840SPawel Jakub Dawidek } 93118ee8840SPawel Jakub Dawidek } 93218ee8840SPawel Jakub Dawidek 933ba6821f0SPawel Jakub Dawidek static char * 93418ee8840SPawel Jakub Dawidek status_one_consumer(struct gconsumer *cp) 93518ee8840SPawel Jakub Dawidek { 936ba6821f0SPawel Jakub Dawidek static char buf[256]; 93718ee8840SPawel Jakub Dawidek struct gprovider *pp; 93818ee8840SPawel Jakub Dawidek struct gconfig *conf; 93918ee8840SPawel Jakub Dawidek 94018ee8840SPawel Jakub Dawidek pp = cp->lg_provider; 94118ee8840SPawel Jakub Dawidek if (pp == NULL) 942ba6821f0SPawel Jakub Dawidek return (NULL); 94318ee8840SPawel Jakub Dawidek LIST_FOREACH(conf, &cp->lg_config, lg_config) { 94418ee8840SPawel Jakub Dawidek if (strcasecmp(conf->lg_name, "synchronized") == 0) 945ba6821f0SPawel Jakub Dawidek break; 94618ee8840SPawel Jakub Dawidek } 947ba6821f0SPawel Jakub Dawidek if (conf == NULL) 948ba6821f0SPawel Jakub Dawidek snprintf(buf, sizeof(buf), "%s", pp->lg_name); 949ba6821f0SPawel Jakub Dawidek else { 950ba6821f0SPawel Jakub Dawidek snprintf(buf, sizeof(buf), "%s (%s)", pp->lg_name, 951ba6821f0SPawel Jakub Dawidek conf->lg_val); 952ba6821f0SPawel Jakub Dawidek } 953ba6821f0SPawel Jakub Dawidek return (buf); 95418ee8840SPawel Jakub Dawidek } 95518ee8840SPawel Jakub Dawidek 95618ee8840SPawel Jakub Dawidek static void 957ba6821f0SPawel Jakub Dawidek status_one_geom(struct ggeom *gp, int script, int name_len, int status_len) 95818ee8840SPawel Jakub Dawidek { 95918ee8840SPawel Jakub Dawidek struct gprovider *pp; 96018ee8840SPawel Jakub Dawidek struct gconsumer *cp; 96118ee8840SPawel Jakub Dawidek struct gconfig *conf; 962ba6821f0SPawel Jakub Dawidek const char *name, *status, *component; 963ba6821f0SPawel Jakub Dawidek int gotone; 96418ee8840SPawel Jakub Dawidek 96518ee8840SPawel Jakub Dawidek pp = LIST_FIRST(&gp->lg_provider); 96618ee8840SPawel Jakub Dawidek if (pp != NULL) 96718ee8840SPawel Jakub Dawidek name = pp->lg_name; 96818ee8840SPawel Jakub Dawidek else 96918ee8840SPawel Jakub Dawidek name = gp->lg_name; 97018ee8840SPawel Jakub Dawidek LIST_FOREACH(conf, &gp->lg_config, lg_config) { 971ba6821f0SPawel Jakub Dawidek if (strcasecmp(conf->lg_name, "state") == 0) 97218ee8840SPawel Jakub Dawidek break; 97318ee8840SPawel Jakub Dawidek } 97418ee8840SPawel Jakub Dawidek if (conf == NULL) 975ba6821f0SPawel Jakub Dawidek status = "N/A"; 976ba6821f0SPawel Jakub Dawidek else 977ba6821f0SPawel Jakub Dawidek status = conf->lg_val; 978ba6821f0SPawel Jakub Dawidek gotone = 0; 97918ee8840SPawel Jakub Dawidek LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) { 980ba6821f0SPawel Jakub Dawidek component = status_one_consumer(cp); 981ba6821f0SPawel Jakub Dawidek if (component == NULL) 982ba6821f0SPawel Jakub Dawidek continue; 983ba6821f0SPawel Jakub Dawidek gotone = 1; 984ba6821f0SPawel Jakub Dawidek printf("%*s %*s %s\n", name_len, name, status_len, status, 985ba6821f0SPawel Jakub Dawidek component); 986ba6821f0SPawel Jakub Dawidek if (!script) 987ba6821f0SPawel Jakub Dawidek name = status = ""; 98818ee8840SPawel Jakub Dawidek } 989ba6821f0SPawel Jakub Dawidek if (!gotone) { 990ba6821f0SPawel Jakub Dawidek printf("%*s %*s %s\n", name_len, name, status_len, status, 991ba6821f0SPawel Jakub Dawidek "N/A"); 992ba6821f0SPawel Jakub Dawidek } 99318ee8840SPawel Jakub Dawidek } 99418ee8840SPawel Jakub Dawidek 99518ee8840SPawel Jakub Dawidek static void 99618ee8840SPawel Jakub Dawidek std_status(struct gctl_req *req, unsigned flags __unused) 99718ee8840SPawel Jakub Dawidek { 99818ee8840SPawel Jakub Dawidek struct gmesh mesh; 99918ee8840SPawel Jakub Dawidek struct gclass *classp; 100018ee8840SPawel Jakub Dawidek struct ggeom *gp; 1001f13942a7SPawel Jakub Dawidek const char *name; 1002da80913dSPawel Jakub Dawidek int name_len, status_len; 1003f13942a7SPawel Jakub Dawidek int error, i, n, nargs, script; 100418ee8840SPawel Jakub Dawidek 100518ee8840SPawel Jakub Dawidek error = geom_gettree(&mesh); 10066fc60008SPawel Jakub Dawidek if (error != 0) 10076fc60008SPawel Jakub Dawidek errc(EXIT_FAILURE, error, "Cannot get GEOM tree"); 100818ee8840SPawel Jakub Dawidek classp = find_class(&mesh, gclass_name); 10095d47cd0fSPawel Jakub Dawidek if (classp == NULL) 10105d47cd0fSPawel Jakub Dawidek errx(EXIT_FAILURE, "Class %s not found.", gclass_name); 1011f13942a7SPawel Jakub Dawidek nargs = gctl_get_int(req, "nargs"); 1012f13942a7SPawel Jakub Dawidek script = gctl_get_int(req, "script"); 101318ee8840SPawel Jakub Dawidek name_len = strlen("Name"); 101418ee8840SPawel Jakub Dawidek status_len = strlen("Status"); 1015f13942a7SPawel Jakub Dawidek if (nargs > 0) { 1016f13942a7SPawel Jakub Dawidek for (i = 0, n = 0; i < nargs; i++) { 1017f13942a7SPawel Jakub Dawidek name = gctl_get_ascii(req, "arg%d", i); 101818ee8840SPawel Jakub Dawidek gp = find_geom(classp, name); 101918ee8840SPawel Jakub Dawidek if (gp == NULL) 10205d47cd0fSPawel Jakub Dawidek errx(EXIT_FAILURE, "No such geom: %s.", name); 102118ee8840SPawel Jakub Dawidek else { 102218ee8840SPawel Jakub Dawidek status_update_len(gp, &name_len, &status_len); 102318ee8840SPawel Jakub Dawidek n++; 102418ee8840SPawel Jakub Dawidek } 102518ee8840SPawel Jakub Dawidek } 102618ee8840SPawel Jakub Dawidek if (n == 0) 102718ee8840SPawel Jakub Dawidek goto end; 102818ee8840SPawel Jakub Dawidek } else { 1029f13942a7SPawel Jakub Dawidek n = 0; 103018ee8840SPawel Jakub Dawidek LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 103118ee8840SPawel Jakub Dawidek if (LIST_EMPTY(&gp->lg_provider)) 103218ee8840SPawel Jakub Dawidek continue; 103318ee8840SPawel Jakub Dawidek status_update_len(gp, &name_len, &status_len); 103418ee8840SPawel Jakub Dawidek n++; 103518ee8840SPawel Jakub Dawidek } 103618ee8840SPawel Jakub Dawidek if (n == 0) 103718ee8840SPawel Jakub Dawidek goto end; 103818ee8840SPawel Jakub Dawidek } 1039f13942a7SPawel Jakub Dawidek if (!script) { 1040da80913dSPawel Jakub Dawidek printf("%*s %*s %s\n", name_len, "Name", status_len, "Status", 104118ee8840SPawel Jakub Dawidek "Components"); 1042ba6821f0SPawel Jakub Dawidek } 1043f13942a7SPawel Jakub Dawidek if (nargs > 0) { 1044f13942a7SPawel Jakub Dawidek for (i = 0; i < nargs; i++) { 1045f13942a7SPawel Jakub Dawidek name = gctl_get_ascii(req, "arg%d", i); 104618ee8840SPawel Jakub Dawidek gp = find_geom(classp, name); 104718ee8840SPawel Jakub Dawidek if (gp != NULL) { 1048f13942a7SPawel Jakub Dawidek status_one_geom(gp, script, name_len, 1049ba6821f0SPawel Jakub Dawidek status_len); 105018ee8840SPawel Jakub Dawidek } 105118ee8840SPawel Jakub Dawidek } 105218ee8840SPawel Jakub Dawidek } else { 105318ee8840SPawel Jakub Dawidek LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 105418ee8840SPawel Jakub Dawidek if (LIST_EMPTY(&gp->lg_provider)) 105518ee8840SPawel Jakub Dawidek continue; 1056f13942a7SPawel Jakub Dawidek status_one_geom(gp, script, name_len, status_len); 105718ee8840SPawel Jakub Dawidek } 105818ee8840SPawel Jakub Dawidek } 105918ee8840SPawel Jakub Dawidek end: 106018ee8840SPawel Jakub Dawidek geom_deletetree(&mesh); 106118ee8840SPawel Jakub Dawidek } 106218ee8840SPawel Jakub Dawidek 106318ee8840SPawel Jakub Dawidek static int 106405c91076SPawel Jakub Dawidek std_load_available(void) 106505c91076SPawel Jakub Dawidek { 106605c91076SPawel Jakub Dawidek char name[MAXPATHLEN], paths[MAXPATHLEN * 8], *p; 106705c91076SPawel Jakub Dawidek struct stat sb; 106805c91076SPawel Jakub Dawidek size_t len; 106905c91076SPawel Jakub Dawidek 107005c91076SPawel Jakub Dawidek snprintf(name, sizeof(name), "g_%s", class_name); 107105c91076SPawel Jakub Dawidek /* 107205c91076SPawel Jakub Dawidek * If already in kernel, "load" command is not available. 107305c91076SPawel Jakub Dawidek */ 107405c91076SPawel Jakub Dawidek if (modfind(name) >= 0) 107505c91076SPawel Jakub Dawidek return (0); 107605c91076SPawel Jakub Dawidek bzero(paths, sizeof(paths)); 107705c91076SPawel Jakub Dawidek len = sizeof(paths); 107805c91076SPawel Jakub Dawidek if (sysctlbyname("kern.module_path", paths, &len, NULL, 0) < 0) 107905c91076SPawel Jakub Dawidek err(EXIT_FAILURE, "sysctl(kern.module_path)"); 108005c91076SPawel Jakub Dawidek for (p = strtok(paths, ";"); p != NULL; p = strtok(NULL, ";")) { 108105c91076SPawel Jakub Dawidek snprintf(name, sizeof(name), "%s/geom_%s.ko", p, class_name); 108205c91076SPawel Jakub Dawidek /* 108305c91076SPawel Jakub Dawidek * If geom_<name>.ko file exists, "load" command is available. 108405c91076SPawel Jakub Dawidek */ 108505c91076SPawel Jakub Dawidek if (stat(name, &sb) == 0) 108605c91076SPawel Jakub Dawidek return (1); 108705c91076SPawel Jakub Dawidek } 108805c91076SPawel Jakub Dawidek return (0); 108905c91076SPawel Jakub Dawidek } 109005c91076SPawel Jakub Dawidek 109105c91076SPawel Jakub Dawidek static void 109205c91076SPawel Jakub Dawidek std_load(struct gctl_req *req __unused, unsigned flags) 109305c91076SPawel Jakub Dawidek { 109405c91076SPawel Jakub Dawidek 109505c91076SPawel Jakub Dawidek /* 109605c91076SPawel Jakub Dawidek * Do nothing special here, because of G_FLAG_LOADKLD flag, 109705c91076SPawel Jakub Dawidek * module is already loaded. 109805c91076SPawel Jakub Dawidek */ 109905c91076SPawel Jakub Dawidek if ((flags & G_FLAG_VERBOSE) != 0) 110005c91076SPawel Jakub Dawidek printf("Module available.\n"); 110105c91076SPawel Jakub Dawidek } 110205c91076SPawel Jakub Dawidek 110305c91076SPawel Jakub Dawidek static int 110405c91076SPawel Jakub Dawidek std_unload_available(void) 110505c91076SPawel Jakub Dawidek { 110605c91076SPawel Jakub Dawidek char name[64]; 110705c91076SPawel Jakub Dawidek int id; 110805c91076SPawel Jakub Dawidek 110905c91076SPawel Jakub Dawidek snprintf(name, sizeof(name), "geom_%s", class_name); 111005c91076SPawel Jakub Dawidek id = kldfind(name); 111105c91076SPawel Jakub Dawidek if (id >= 0) 111205c91076SPawel Jakub Dawidek return (1); 111305c91076SPawel Jakub Dawidek return (0); 111405c91076SPawel Jakub Dawidek } 111505c91076SPawel Jakub Dawidek 111605c91076SPawel Jakub Dawidek static void 111705c91076SPawel Jakub Dawidek std_unload(struct gctl_req *req, unsigned flags __unused) 111805c91076SPawel Jakub Dawidek { 111905c91076SPawel Jakub Dawidek char name[64]; 112005c91076SPawel Jakub Dawidek int id; 112105c91076SPawel Jakub Dawidek 112205c91076SPawel Jakub Dawidek snprintf(name, sizeof(name), "geom_%s", class_name); 112305c91076SPawel Jakub Dawidek id = kldfind(name); 112405c91076SPawel Jakub Dawidek if (id < 0) { 112505c91076SPawel Jakub Dawidek gctl_error(req, "Could not find module: %s.", strerror(errno)); 112605c91076SPawel Jakub Dawidek return; 112705c91076SPawel Jakub Dawidek } 112805c91076SPawel Jakub Dawidek if (kldunload(id) < 0) { 112905c91076SPawel Jakub Dawidek gctl_error(req, "Could not unload module: %s.", 113005c91076SPawel Jakub Dawidek strerror(errno)); 113105c91076SPawel Jakub Dawidek return; 113205c91076SPawel Jakub Dawidek } 113305c91076SPawel Jakub Dawidek } 113405c91076SPawel Jakub Dawidek 113505c91076SPawel Jakub Dawidek static int 113605c91076SPawel Jakub Dawidek std_available(const char *name) 113705c91076SPawel Jakub Dawidek { 113805c91076SPawel Jakub Dawidek 1139b70eccf3SPawel Jakub Dawidek if (strcmp(name, "help") == 0) 1140b70eccf3SPawel Jakub Dawidek return (1); 1141b70eccf3SPawel Jakub Dawidek else if (strcmp(name, "list") == 0) 114205c91076SPawel Jakub Dawidek return (std_list_available()); 114318ee8840SPawel Jakub Dawidek else if (strcmp(name, "status") == 0) 114418ee8840SPawel Jakub Dawidek return (std_status_available()); 114505c91076SPawel Jakub Dawidek else if (strcmp(name, "load") == 0) 114605c91076SPawel Jakub Dawidek return (std_load_available()); 114705c91076SPawel Jakub Dawidek else if (strcmp(name, "unload") == 0) 114805c91076SPawel Jakub Dawidek return (std_unload_available()); 114905c91076SPawel Jakub Dawidek else 115005c91076SPawel Jakub Dawidek assert(!"Unknown standard command."); 115105c91076SPawel Jakub Dawidek return (0); 115205c91076SPawel Jakub Dawidek } 1153