2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2004-2009 Pawel Jakub Dawidek <pjd@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/linker.h>
34 #include <sys/module.h>
36 #include <sys/sysctl.h>
55 #include "misc/subr.h"
57 #ifdef STATIC_GEOM_CLASSES
58 extern uint32_t gpart_version;
59 extern struct g_command gpart_class_commands[];
60 extern uint32_t glabel_version;
61 extern struct g_command glabel_class_commands[];
64 static char comm[MAXPATHLEN], *class_name = NULL, *gclass_name = NULL;
65 static uint32_t *version = NULL;
66 static int verbose = 0;
67 static struct g_command *class_commands = NULL;
69 #define GEOM_CLASS_CMDS 0x01
70 #define GEOM_STD_CMDS 0x02
72 #define GEOM_CLASS_WIDTH 10
74 static struct g_command *find_command(const char *cmdstr, int flags);
75 static void list_one_geom_by_provider(const char *provider_name);
76 static int std_available(const char *name);
78 static void std_help(struct gctl_req *req, unsigned flags);
79 static void std_list(struct gctl_req *req, unsigned flags);
80 static void std_status(struct gctl_req *req, unsigned flags);
81 static void std_load(struct gctl_req *req, unsigned flags);
82 static void std_unload(struct gctl_req *req, unsigned flags);
84 static struct g_command std_commands[] = {
85 { "help", 0, std_help, G_NULL_OPTS, NULL },
86 { "list", 0, std_list,
88 { 'a', "all", NULL, G_TYPE_BOOL },
93 { "status", 0, std_status,
95 { 'a', "all", NULL, G_TYPE_BOOL },
96 { 'g', "geoms", NULL, G_TYPE_BOOL },
97 { 's', "script", NULL, G_TYPE_BOOL },
102 { "load", G_FLAG_VERBOSE | G_FLAG_LOADKLD, std_load, G_NULL_OPTS,
104 { "unload", G_FLAG_VERBOSE, std_unload, G_NULL_OPTS, NULL },
109 usage_command(struct g_command *cmd, const char *prefix)
111 struct g_option *opt;
114 if (cmd->gc_usage != NULL) {
115 char *pos, *ptr, *sptr;
117 sptr = ptr = strdup(cmd->gc_usage);
118 while ((pos = strsep(&ptr, "\n")) != NULL) {
121 fprintf(stderr, "%s %s %s %s\n", prefix, comm,
128 fprintf(stderr, "%s %s %s", prefix, comm, cmd->gc_name);
129 if ((cmd->gc_flags & G_FLAG_VERBOSE) != 0)
130 fprintf(stderr, " [-v]");
132 opt = &cmd->gc_options[i];
133 if (opt->go_name == NULL)
135 if (opt->go_val != NULL || G_OPT_TYPE(opt) == G_TYPE_BOOL)
136 fprintf(stderr, " [");
138 fprintf(stderr, " ");
139 fprintf(stderr, "-%c", opt->go_char);
140 if (G_OPT_TYPE(opt) != G_TYPE_BOOL)
141 fprintf(stderr, " %s", opt->go_name);
142 if (opt->go_val != NULL || G_OPT_TYPE(opt) == G_TYPE_BOOL)
143 fprintf(stderr, "]");
145 fprintf(stderr, "\n");
152 if (class_name == NULL) {
153 fprintf(stderr, "usage: geom <class> <command> [options]\n");
154 fprintf(stderr, " geom -p <provider-name>\n");
155 fprintf(stderr, " geom -t\n");
158 struct g_command *cmd;
163 if (class_commands != NULL) {
165 cmd = &class_commands[i];
166 if (cmd->gc_name == NULL)
168 usage_command(cmd, prefix);
173 cmd = &std_commands[i];
174 if (cmd->gc_name == NULL)
177 * If class defines command, which has the same name as
178 * standard command, skip it, because it was already
181 if (find_command(cmd->gc_name, GEOM_CLASS_CMDS) != NULL)
183 usage_command(cmd, prefix);
193 char name1[64], name2[64];
195 snprintf(name1, sizeof(name1), "g_%s", class_name);
196 snprintf(name2, sizeof(name2), "geom_%s", class_name);
197 if (modfind(name1) < 0) {
198 /* Not present in kernel, try loading it. */
199 if (kldload(name2) < 0 || modfind(name1) < 0) {
200 if (errno != EEXIST) {
201 err(EXIT_FAILURE, "cannot load %s", name2);
208 strlcatf(char *str, size_t size, const char *format, ...)
218 va_start(ap, format);
219 ret = vsnprintf(str, size, format, ap);
226 * Find given option in options available for given command.
228 static struct g_option *
229 find_option(struct g_command *cmd, char ch)
231 struct g_option *opt;
235 opt = &cmd->gc_options[i];
236 if (opt->go_name == NULL)
238 if (opt->go_char == ch)
246 * Add given option to gctl_req.
249 set_option(struct gctl_req *req, struct g_option *opt, const char *val)
255 if (G_OPT_ISMULTI(opt)) {
258 if (G_OPT_NUM(opt) == UCHAR_MAX)
259 errx(EXIT_FAILURE, "Too many -%c options.", opt->go_char);
262 * Base option name length plus 3 bytes for option number
263 * (max. 255 options) plus 1 byte for terminating '\0'.
265 optnamesize = strlen(opt->go_name) + 3 + 1;
266 ptr = malloc(optnamesize);
268 errx(EXIT_FAILURE, "No memory.");
269 snprintf(ptr, optnamesize, "%s%u", opt->go_name, G_OPT_NUM(opt));
273 optname = opt->go_name;
276 if (G_OPT_TYPE(opt) == G_TYPE_NUMBER) {
277 if (expand_number(val, &number) == -1) {
278 err(EXIT_FAILURE, "Invalid value for '%c' argument",
281 ptr = malloc(sizeof(intmax_t));
283 errx(EXIT_FAILURE, "No memory.");
284 *(intmax_t *)ptr = number;
286 gctl_ro_param(req, optname, sizeof(intmax_t), opt->go_val);
287 } else if (G_OPT_TYPE(opt) == G_TYPE_STRING) {
288 gctl_ro_param(req, optname, -1, val);
289 } else if (G_OPT_TYPE(opt) == G_TYPE_BOOL) {
290 ptr = malloc(sizeof(int));
292 errx(EXIT_FAILURE, "No memory.");
293 *(int *)ptr = *val - '0';
295 gctl_ro_param(req, optname, sizeof(int), opt->go_val);
297 assert(!"Invalid type");
300 if (G_OPT_ISMULTI(opt))
301 free(__DECONST(char *, optname));
305 * 1. Add given argument by caller.
306 * 2. Add default values of not given arguments.
307 * 3. Add the rest of arguments.
310 parse_arguments(struct g_command *cmd, struct gctl_req *req, int *argc,
313 struct g_option *opt;
319 if ((cmd->gc_flags & G_FLAG_VERBOSE) != 0)
320 strlcat(opts, "v", sizeof(opts));
322 opt = &cmd->gc_options[i];
323 if (opt->go_name == NULL)
325 assert(G_OPT_TYPE(opt) != 0);
326 assert((opt->go_type & ~(G_TYPE_MASK | G_TYPE_MULTI)) == 0);
327 /* Multiple bool arguments makes no sense. */
328 assert(G_OPT_TYPE(opt) != G_TYPE_BOOL ||
329 (opt->go_type & G_TYPE_MULTI) == 0);
330 strlcatf(opts, sizeof(opts), "%c", opt->go_char);
331 if (G_OPT_TYPE(opt) != G_TYPE_BOOL)
332 strlcat(opts, ":", sizeof(opts));
336 * Add specified arguments.
338 while ((ch = getopt(*argc, *argv, opts)) != -1) {
339 /* Standard (not passed to kernel) options. */
345 /* Options passed to kernel. */
346 opt = find_option(cmd, ch);
349 if (!G_OPT_ISMULTI(opt) && G_OPT_ISDONE(opt)) {
350 warnx("Option '%c' specified twice.", opt->go_char);
355 if (G_OPT_TYPE(opt) == G_TYPE_BOOL)
356 set_option(req, opt, "1");
358 set_option(req, opt, optarg);
364 * Add not specified arguments, but with default values.
367 opt = &cmd->gc_options[i];
368 if (opt->go_name == NULL)
370 if (G_OPT_ISDONE(opt))
373 if (G_OPT_TYPE(opt) == G_TYPE_BOOL) {
374 assert(opt->go_val == NULL);
375 set_option(req, opt, "0");
377 if (opt->go_val == NULL) {
378 warnx("Option '%c' not specified.",
381 } else if (opt->go_val == G_VAL_OPTIONAL) {
384 set_option(req, opt, opt->go_val);
390 * Add rest of given arguments.
392 gctl_ro_param(req, "nargs", sizeof(int), argc);
393 for (i = 0; i < (unsigned)*argc; i++) {
396 snprintf(argname, sizeof(argname), "arg%u", i);
397 gctl_ro_param(req, argname, -1, (*argv)[i]);
402 * Find given command in commands available for given class.
404 static struct g_command *
405 find_command(const char *cmdstr, int flags)
407 struct g_command *cmd;
411 * First try to find command defined by loaded library.
413 if ((flags & GEOM_CLASS_CMDS) != 0 && class_commands != NULL) {
415 cmd = &class_commands[i];
416 if (cmd->gc_name == NULL)
418 if (strcmp(cmd->gc_name, cmdstr) == 0)
423 * Now try to find in standard commands.
425 if ((flags & GEOM_STD_CMDS) != 0) {
427 cmd = &std_commands[i];
428 if (cmd->gc_name == NULL)
430 if (strcmp(cmd->gc_name, cmdstr) == 0)
438 set_flags(struct g_command *cmd)
442 if ((cmd->gc_flags & G_FLAG_VERBOSE) != 0 && verbose)
443 flags |= G_FLAG_VERBOSE;
452 run_command(int argc, char *argv[])
454 struct g_command *cmd;
455 struct gctl_req *req;
459 /* First try to find a command defined by a class. */
460 cmd = find_command(argv[0], GEOM_CLASS_CMDS);
462 /* Now, try to find a standard command. */
463 cmd = find_command(argv[0], GEOM_STD_CMDS);
465 warnx("Unknown command: %s.", argv[0]);
468 if (!std_available(cmd->gc_name)) {
469 warnx("Command '%s' not available; "
470 "try 'load' first.", argv[0]);
474 if ((cmd->gc_flags & G_FLAG_LOADKLD) != 0)
477 req = gctl_get_handle();
478 gctl_ro_param(req, "class", -1, gclass_name);
479 gctl_ro_param(req, "verb", -1, argv[0]);
481 gctl_ro_param(req, "version", sizeof(*version), version);
482 parse_arguments(cmd, req, &argc, &argv);
484 bzero(buf, sizeof(buf));
485 if (cmd->gc_func != NULL) {
488 flags = set_flags(cmd);
489 cmd->gc_func(req, flags);
492 gctl_rw_param(req, "output", sizeof(buf), buf);
493 errstr = gctl_issue(req);
495 if (errstr != NULL && errstr[0] != '\0') {
497 if (strncmp(errstr, "warning: ", strlen("warning: ")) != 0) {
510 #ifndef STATIC_GEOM_CLASSES
516 path = getenv("GEOM_LIBRARY_PATH");
518 path = GEOM_CLASS_DIR;
525 char *curpath, path[MAXPATHLEN], *tofree, *totalpath;
526 uint32_t *lib_version;
531 tofree = totalpath = strdup(library_path());
532 if (totalpath == NULL)
533 err(EXIT_FAILURE, "Not enough memory for library path");
535 if (strchr(totalpath, ':') != NULL)
536 curpath = strsep(&totalpath, ":");
539 /* Traverse the paths to find one that contains the library we want. */
540 while (curpath != NULL) {
541 snprintf(path, sizeof(path), "%s/geom_%s.so", curpath,
543 ret = access(path, F_OK);
545 if (errno == ENOENT) {
547 * If we cannot find library, try the next
550 curpath = strsep(&totalpath, ":");
553 err(EXIT_FAILURE, "Cannot access library");
558 /* No library was found, but standard commands can still be used */
561 dlh = dlopen(path, RTLD_NOW);
563 errx(EXIT_FAILURE, "Cannot open library: %s.", dlerror());
564 lib_version = dlsym(dlh, "lib_version");
565 if (lib_version == NULL) {
566 warnx("Cannot find symbol %s: %s.", "lib_version", dlerror());
570 if (*lib_version != G_LIB_VERSION) {
572 errx(EXIT_FAILURE, "%s and %s are not synchronized.",
573 getprogname(), path);
575 version = dlsym(dlh, "version");
576 if (version == NULL) {
577 warnx("Cannot find symbol %s: %s.", "version", dlerror());
581 class_commands = dlsym(dlh, "class_commands");
582 if (class_commands == NULL) {
583 warnx("Cannot find symbol %s: %s.", "class_commands",
589 #endif /* !STATIC_GEOM_CLASSES */
592 * Class name should be all capital letters.
600 for (; *s1 != '\0'; s1++)
602 gclass_name = malloc(strlen(class_name) + 1);
603 if (gclass_name == NULL)
604 errx(EXIT_FAILURE, "No memory");
607 for (; *s2 != '\0'; s2++)
608 *s1++ = toupper(*s2);
613 get_class(int *argc, char ***argv)
616 snprintf(comm, sizeof(comm), "%s", basename((*argv)[0]));
617 if (strcmp(comm, "geom") == 0) {
620 else if (*argc == 2) {
621 if (strcmp((*argv)[1], "-h") == 0 ||
622 strcmp((*argv)[1], "help") == 0) {
626 strlcatf(comm, sizeof(comm), " %s", (*argv)[1]);
627 class_name = (*argv)[1];
630 } else if (*comm == 'g') {
631 class_name = comm + 1;
635 errx(EXIT_FAILURE, "Invalid utility name.");
638 #ifndef STATIC_GEOM_CLASSES
641 if (!strcasecmp(class_name, "part")) {
642 version = &gpart_version;
643 class_commands = gpart_class_commands;
644 } else if (!strcasecmp(class_name, "label")) {
645 version = &glabel_version;
646 class_commands = glabel_class_commands;
648 #endif /* !STATIC_GEOM_CLASSES */
652 /* If we can't load or list, it's not a class. */
653 if (!std_available("load") && !std_available("list"))
654 errx(EXIT_FAILURE, "Invalid class name '%s'.", class_name);
660 static struct ggeom *
661 find_geom_by_provider(struct gmesh *mesh, const char *name)
663 struct gclass *classp;
665 struct gprovider *pp;
667 LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
668 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
669 LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
670 if (strcmp(pp->lg_name, name) == 0)
680 compute_tree_width_geom(struct gmesh *mesh, struct ggeom *gp, int indent)
682 struct gclass *classp2;
684 struct gconsumer *cp2;
685 struct gprovider *pp;
686 int max_width, width;
688 max_width = width = indent + strlen(gp->lg_name);
690 LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
691 LIST_FOREACH(classp2, &mesh->lg_class, lg_class) {
692 LIST_FOREACH(gp2, &classp2->lg_geom, lg_geom) {
694 &gp2->lg_consumer, lg_consumer) {
695 if (pp != cp2->lg_provider)
697 width = compute_tree_width_geom(mesh,
699 if (width > max_width)
710 compute_tree_width(struct gmesh *mesh)
712 struct gclass *classp;
714 int max_width, width;
716 max_width = width = 0;
718 LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
719 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
720 if (!LIST_EMPTY(&gp->lg_consumer))
722 width = compute_tree_width_geom(mesh, gp, 0);
723 if (width > max_width)
732 show_tree_geom(struct gmesh *mesh, struct ggeom *gp, int indent, int width)
734 struct gclass *classp2;
736 struct gconsumer *cp2;
737 struct gprovider *pp;
739 if (LIST_EMPTY(&gp->lg_provider)) {
740 printf("%*s%-*.*s %-*.*s\n", indent, "",
741 width - indent, width - indent, gp->lg_name,
742 GEOM_CLASS_WIDTH, GEOM_CLASS_WIDTH, gp->lg_class->lg_name);
746 LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
747 printf("%*s%-*.*s %-*.*s %s\n", indent, "",
748 width - indent, width - indent, gp->lg_name,
749 GEOM_CLASS_WIDTH, GEOM_CLASS_WIDTH, gp->lg_class->lg_name,
752 LIST_FOREACH(classp2, &mesh->lg_class, lg_class) {
753 LIST_FOREACH(gp2, &classp2->lg_geom, lg_geom) {
755 &gp2->lg_consumer, lg_consumer) {
756 if (pp != cp2->lg_provider)
758 show_tree_geom(mesh, gp2,
770 struct gclass *classp;
774 error = geom_gettree(&mesh);
776 errc(EXIT_FAILURE, error, "Cannot get GEOM tree");
778 width = compute_tree_width(&mesh);
780 printf("%-*.*s %-*.*s %s\n",
781 width, width, "Geom",
782 GEOM_CLASS_WIDTH, GEOM_CLASS_WIDTH, "Class",
785 LIST_FOREACH(classp, &mesh.lg_class, lg_class) {
786 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
787 if (!LIST_EMPTY(&gp->lg_consumer))
789 show_tree_geom(&mesh, gp, 0, width);
795 main(int argc, char *argv[])
801 provider_name = NULL;
804 if (strcmp(getprogname(), "geom") == 0) {
805 while ((ch = getopt(argc, argv, "hp:t")) != -1) {
808 provider_name = strdup(optarg);
809 if (provider_name == NULL)
822 * Don't adjust argc and argv, it would break get_class().
826 if (tflag && provider_name != NULL) {
828 "At most one of -P and -t may be specified.");
831 if (provider_name != NULL) {
832 list_one_geom_by_provider(provider_name);
841 get_class(&argc, &argv);
842 run_command(argc, argv);
848 static struct gclass *
849 find_class(struct gmesh *mesh, const char *name)
851 struct gclass *classp;
853 LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
854 if (strcmp(classp->lg_name, name) == 0)
860 static struct ggeom *
861 find_geom(struct gclass *classp, const char *name)
865 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
866 if (strcmp(gp->lg_name, name) == 0)
873 list_one_provider(struct gprovider *pp, const char *prefix)
875 struct gconfig *conf;
878 printf("Name: %s\n", pp->lg_name);
879 humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
880 HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
881 printf("%sMediasize: %jd (%s)\n", prefix, (intmax_t)pp->lg_mediasize,
883 printf("%sSectorsize: %u\n", prefix, pp->lg_sectorsize);
884 if (pp->lg_stripesize > 0 || pp->lg_stripeoffset > 0) {
885 printf("%sStripesize: %ju\n", prefix, pp->lg_stripesize);
886 printf("%sStripeoffset: %ju\n", prefix, pp->lg_stripeoffset);
888 printf("%sMode: %s\n", prefix, pp->lg_mode);
889 LIST_FOREACH(conf, &pp->lg_config, lg_config) {
890 printf("%s%s: %s\n", prefix, conf->lg_name, conf->lg_val);
895 list_one_consumer(struct gconsumer *cp, const char *prefix)
897 struct gprovider *pp;
898 struct gconfig *conf;
900 pp = cp->lg_provider;
902 printf("[no provider]\n");
906 printf("Name: %s\n", pp->lg_name);
907 humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
908 HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
909 printf("%sMediasize: %jd (%s)\n", prefix,
910 (intmax_t)pp->lg_mediasize, buf);
911 printf("%sSectorsize: %u\n", prefix, pp->lg_sectorsize);
912 if (pp->lg_stripesize > 0 || pp->lg_stripeoffset > 0) {
913 printf("%sStripesize: %ju\n", prefix, pp->lg_stripesize);
914 printf("%sStripeoffset: %ju\n", prefix, pp->lg_stripeoffset);
916 printf("%sMode: %s\n", prefix, cp->lg_mode);
918 LIST_FOREACH(conf, &cp->lg_config, lg_config) {
919 printf("%s%s: %s\n", prefix, conf->lg_name, conf->lg_val);
924 list_one_geom(struct ggeom *gp)
926 struct gprovider *pp;
927 struct gconsumer *cp;
928 struct gconfig *conf;
931 printf("Geom name: %s\n", gp->lg_name);
932 LIST_FOREACH(conf, &gp->lg_config, lg_config) {
933 printf("%s: %s\n", conf->lg_name, conf->lg_val);
935 if (!LIST_EMPTY(&gp->lg_provider)) {
936 printf("Providers:\n");
938 LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
940 list_one_provider(pp, " ");
943 if (!LIST_EMPTY(&gp->lg_consumer)) {
944 printf("Consumers:\n");
946 LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
948 list_one_consumer(cp, " ");
955 list_one_geom_by_provider(const char *provider_name)
961 error = geom_gettree(&mesh);
963 errc(EXIT_FAILURE, error, "Cannot get GEOM tree");
965 gp = find_geom_by_provider(&mesh, provider_name);
967 errx(EXIT_FAILURE, "Cannot find provider '%s'.", provider_name);
969 printf("Geom class: %s\n", gp->lg_class->lg_name);
974 std_help(struct gctl_req *req __unused, unsigned flags __unused)
981 std_list_available(void)
984 struct gclass *classp;
987 error = geom_gettree(&mesh);
989 errc(EXIT_FAILURE, error, "Cannot get GEOM tree");
990 classp = find_class(&mesh, gclass_name);
991 geom_deletetree(&mesh);
998 std_list(struct gctl_req *req, unsigned flags __unused)
1001 struct gclass *classp;
1004 int all, error, i, nargs;
1006 error = geom_gettree(&mesh);
1008 errc(EXIT_FAILURE, error, "Cannot get GEOM tree");
1009 classp = find_class(&mesh, gclass_name);
1010 if (classp == NULL) {
1011 geom_deletetree(&mesh);
1012 errx(EXIT_FAILURE, "Class '%s' not found.", gclass_name);
1014 nargs = gctl_get_int(req, "nargs");
1015 all = gctl_get_int(req, "all");
1017 for (i = 0; i < nargs; i++) {
1018 name = gctl_get_ascii(req, "arg%d", i);
1019 gp = find_geom(classp, name);
1021 errx(EXIT_FAILURE, "Class '%s' does not have "
1022 "an instance named '%s'.",
1028 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
1029 if (LIST_EMPTY(&gp->lg_provider) && !all)
1034 geom_deletetree(&mesh);
1038 std_status_available(void)
1041 /* 'status' command is available when 'list' command is. */
1042 return (std_list_available());
1046 status_update_len(struct ggeom *gp, int *name_len, int *status_len)
1048 struct gconfig *conf;
1052 assert(name_len != NULL);
1053 assert(status_len != NULL);
1055 len = strlen(gp->lg_name);
1056 if (*name_len < len)
1058 LIST_FOREACH(conf, &gp->lg_config, lg_config) {
1059 if (strcasecmp(conf->lg_name, "state") == 0) {
1060 len = strlen(conf->lg_val);
1061 if (*status_len < len)
1068 status_update_len_prs(struct ggeom *gp, int *name_len, int *status_len)
1070 struct gprovider *pp;
1071 struct gconfig *conf;
1075 assert(name_len != NULL);
1076 assert(status_len != NULL);
1079 LIST_FOREACH(conf, &gp->lg_config, lg_config) {
1080 if (strcasecmp(conf->lg_name, "state") == 0) {
1081 glen = strlen(conf->lg_val);
1085 LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
1086 len = strlen(pp->lg_name);
1087 if (*name_len < len)
1090 LIST_FOREACH(conf, &pp->lg_config, lg_config) {
1091 if (strcasecmp(conf->lg_name, "state") == 0) {
1092 len = strlen(conf->lg_val);
1096 if (*status_len < len)
1102 status_one_consumer(struct gconsumer *cp)
1104 static char buf[256];
1105 struct gprovider *pp;
1106 struct gconfig *conf;
1107 const char *state, *syncr;
1109 pp = cp->lg_provider;
1114 LIST_FOREACH(conf, &cp->lg_config, lg_config) {
1115 if (strcasecmp(conf->lg_name, "state") == 0)
1116 state = conf->lg_val;
1117 if (strcasecmp(conf->lg_name, "synchronized") == 0)
1118 syncr = conf->lg_val;
1120 if (state == NULL && syncr == NULL)
1121 snprintf(buf, sizeof(buf), "%s", pp->lg_name);
1122 else if (state != NULL && syncr != NULL) {
1123 snprintf(buf, sizeof(buf), "%s (%s, %s)", pp->lg_name,
1126 snprintf(buf, sizeof(buf), "%s (%s)", pp->lg_name,
1127 state ? state : syncr);
1133 status_one_geom(struct ggeom *gp, int script, int name_len, int status_len)
1135 struct gconsumer *cp;
1136 struct gconfig *conf;
1137 const char *name, *status, *component;
1142 LIST_FOREACH(conf, &gp->lg_config, lg_config) {
1143 if (strcasecmp(conf->lg_name, "state") == 0) {
1144 status = conf->lg_val;
1149 LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
1150 component = status_one_consumer(cp);
1151 if (component == NULL)
1154 printf("%*s %*s %s\n", name_len, name, status_len, status,
1160 printf("%*s %*s %s\n", name_len, name, status_len, status,
1166 status_one_geom_prs(struct ggeom *gp, int script, int name_len, int status_len)
1168 struct gprovider *pp;
1169 struct gconsumer *cp;
1170 struct gconfig *conf;
1171 const char *name, *status, *component;
1174 LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
1177 LIST_FOREACH(conf, &gp->lg_config, lg_config) {
1178 if (strcasecmp(conf->lg_name, "state") == 0) {
1179 status = conf->lg_val;
1183 LIST_FOREACH(conf, &pp->lg_config, lg_config) {
1184 if (strcasecmp(conf->lg_name, "state") == 0) {
1185 status = conf->lg_val;
1190 LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
1191 component = status_one_consumer(cp);
1192 if (component == NULL)
1195 printf("%*s %*s %s\n", name_len, name,
1196 status_len, status, component);
1201 printf("%*s %*s %s\n", name_len, name,
1202 status_len, status, "N/A");
1208 std_status(struct gctl_req *req, unsigned flags __unused)
1211 struct gclass *classp;
1214 int name_len, status_len;
1215 int all, error, geoms, i, n, nargs, script;
1217 error = geom_gettree(&mesh);
1219 errc(EXIT_FAILURE, error, "Cannot get GEOM tree");
1220 classp = find_class(&mesh, gclass_name);
1222 errx(EXIT_FAILURE, "Class %s not found.", gclass_name);
1223 nargs = gctl_get_int(req, "nargs");
1224 all = gctl_get_int(req, "all");
1225 geoms = gctl_get_int(req, "geoms");
1226 script = gctl_get_int(req, "script");
1231 name_len = strlen("Name");
1232 status_len = strlen("Status");
1235 for (i = 0, n = 0; i < nargs; i++) {
1236 name = gctl_get_ascii(req, "arg%d", i);
1237 gp = find_geom(classp, name);
1239 errx(EXIT_FAILURE, "No such geom: %s.", name);
1241 status_update_len(gp,
1242 &name_len, &status_len);
1244 status_update_len_prs(gp,
1245 &name_len, &status_len);
1253 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
1254 if (LIST_EMPTY(&gp->lg_provider) && !all)
1257 status_update_len(gp,
1258 &name_len, &status_len);
1260 status_update_len_prs(gp,
1261 &name_len, &status_len);
1269 printf("%*s %*s %s\n", name_len, "Name", status_len, "Status",
1273 for (i = 0; i < nargs; i++) {
1274 name = gctl_get_ascii(req, "arg%d", i);
1275 gp = find_geom(classp, name);
1279 status_one_geom(gp, script, name_len,
1282 status_one_geom_prs(gp, script, name_len,
1287 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
1288 if (LIST_EMPTY(&gp->lg_provider) && !all)
1291 status_one_geom(gp, script, name_len,
1294 status_one_geom_prs(gp, script, name_len,
1300 geom_deletetree(&mesh);
1304 std_load_available(void)
1306 char name[MAXPATHLEN], paths[MAXPATHLEN * 8], *p;
1310 snprintf(name, sizeof(name), "g_%s", class_name);
1312 * If already in kernel, "load" command is not available.
1314 if (modfind(name) >= 0)
1316 bzero(paths, sizeof(paths));
1317 len = sizeof(paths);
1318 if (sysctlbyname("kern.module_path", paths, &len, NULL, 0) < 0)
1319 err(EXIT_FAILURE, "sysctl(kern.module_path)");
1320 for (p = strtok(paths, ";"); p != NULL; p = strtok(NULL, ";")) {
1321 snprintf(name, sizeof(name), "%s/geom_%s.ko", p, class_name);
1323 * If geom_<name>.ko file exists, "load" command is available.
1325 if (stat(name, &sb) == 0)
1332 std_load(struct gctl_req *req __unused, unsigned flags)
1336 * Do nothing special here, because of G_FLAG_LOADKLD flag,
1337 * module is already loaded.
1339 if ((flags & G_FLAG_VERBOSE) != 0)
1340 printf("Module available.\n");
1344 std_unload_available(void)
1349 snprintf(name, sizeof(name), "geom_%s", class_name);
1357 std_unload(struct gctl_req *req, unsigned flags __unused)
1362 snprintf(name, sizeof(name), "geom_%s", class_name);
1365 gctl_error(req, "Could not find module: %s.", strerror(errno));
1368 if (kldunload(id) < 0) {
1369 gctl_error(req, "Could not unload module: %s.",
1376 std_available(const char *name)
1379 if (strcmp(name, "help") == 0)
1381 else if (strcmp(name, "list") == 0)
1382 return (std_list_available());
1383 else if (strcmp(name, "status") == 0)
1384 return (std_status_available());
1385 else if (strcmp(name, "load") == 0)
1386 return (std_load_available());
1387 else if (strcmp(name, "unload") == 0)
1388 return (std_unload_available());
1390 assert(!"Unknown standard command.");