summaryrefslogtreecommitdiffstats
path: root/sbin/geom/class/part/geom_part.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/geom/class/part/geom_part.c')
-rw-r--r--sbin/geom/class/part/geom_part.c184
1 files changed, 183 insertions, 1 deletions
diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c
index ce9dfb3..30db6c0 100644
--- a/sbin/geom/class/part/geom_part.c
+++ b/sbin/geom/class/part/geom_part.c
@@ -31,8 +31,8 @@ __FBSDID("$FreeBSD$");
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
+#include <err.h>
#include <fcntl.h>
-#include <readpassphrase.h>
#include <string.h>
#include <strings.h>
#include <libgeom.h>
@@ -49,6 +49,8 @@ uint32_t version = 0;
static char optional[] = "";
static char flags[] = "C";
+static void gpart_show(struct gctl_req *, unsigned);
+
struct g_command class_commands[] = {
{ "add", 0, NULL, {
{ 'b', "start", NULL, G_TYPE_STRING },
@@ -86,6 +88,186 @@ struct g_command class_commands[] = {
G_OPT_SENTINEL },
"geom", NULL
},
+ { "show", 0, gpart_show, G_NULL_OPTS, "[geom ...]", NULL },
{ "undo", 0, NULL, G_NULL_OPTS, "geom", NULL },
G_CMD_SENTINEL
};
+
+static struct gclass *
+find_class(struct gmesh *mesh, const char *name)
+{
+ struct gclass *classp;
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
+ if (strcmp(classp->lg_name, name) == 0)
+ return (classp);
+ }
+ return (NULL);
+}
+
+static struct ggeom *
+find_geom(struct gclass *classp, const char *name)
+{
+ struct ggeom *gp;
+
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
+ if (strcmp(gp->lg_name, name) == 0)
+ return (gp);
+ }
+ return (NULL);
+}
+
+static const char *
+find_geomcfg(struct ggeom *gp, const char *cfg)
+{
+ struct gconfig *gc;
+
+ LIST_FOREACH(gc, &gp->lg_config, lg_config) {
+ if (!strcmp(gc->lg_name, cfg))
+ return (gc->lg_val);
+ }
+ return (NULL);
+}
+
+static const char *
+find_provcfg(struct gprovider *pp, const char *cfg)
+{
+ struct gconfig *gc;
+
+ LIST_FOREACH(gc, &pp->lg_config, lg_config) {
+ if (!strcmp(gc->lg_name, cfg))
+ return (gc->lg_val);
+ }
+ return (NULL);
+}
+
+static struct gprovider *
+find_provider(struct ggeom *gp, unsigned long long minsector)
+{
+ struct gprovider *pp, *bestpp;
+ unsigned long long offset;
+ unsigned long long sector, bestsector;
+
+ bestpp = NULL;
+ LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
+ offset = atoll(find_provcfg(pp, "offset"));
+ sector = offset / pp->lg_sectorsize;
+ if (sector < minsector)
+ continue;
+ if (bestpp != NULL && sector >= bestsector)
+ continue;
+ bestpp = pp;
+ bestsector = sector;
+ }
+ return (bestpp);
+}
+
+static const char *
+fmtsize(long double rawsz)
+{
+ static char buf[32];
+ static const char *sfx[] = { "B", "KB", "MB", "GB", "TB" };
+ long double sz;
+ int sfxidx;
+
+ sfxidx = 0;
+ sz = (long double)rawsz;
+ while (sfxidx < 4 && sz > 1099.0) {
+ sz /= 1000;
+ sfxidx++;
+ }
+
+ sprintf(buf, "%.1Lf%s", sz, sfx[sfxidx]);
+ return (buf);
+}
+
+static void
+gpart_show_geom(struct ggeom *gp)
+{
+ struct gprovider *pp;
+ const char *s, *scheme;
+ unsigned long long first, last, sector, end;
+ unsigned long long offset, length, secsz;
+ int idx, wblocks, wname;
+
+ scheme = find_geomcfg(gp, "scheme");
+ s = find_geomcfg(gp, "first");
+ first = atoll(s);
+ s = find_geomcfg(gp, "last");
+ last = atoll(s);
+ wblocks = strlen(s);
+ wname = strlen(gp->lg_name);
+ pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
+ secsz = pp->lg_sectorsize;
+ printf("=>%*llu %*llu %*s %s (%s)\n",
+ wblocks, first, wblocks, (last - first + 1),
+ wname, gp->lg_name,
+ scheme, fmtsize(pp->lg_mediasize));
+
+ while ((pp = find_provider(gp, first)) != NULL) {
+ s = find_provcfg(pp, "offset");
+ offset = atoll(s);
+ sector = offset / secsz;
+ s = find_provcfg(pp, "length");
+ length = atoll(s);
+ s = find_provcfg(pp, "index");
+ idx = atoi(s);
+ end = sector + length / secsz;
+ if (first < sector) {
+ printf(" %*llu %*llu %*s - free - (%s)\n",
+ wblocks, first, wblocks, sector - first,
+ wname, "",
+ fmtsize((sector - first) * secsz));
+ }
+ printf(" %*llu %*llu %*d %s (%s)\n",
+ wblocks, sector, wblocks, end - sector,
+ wname, idx,
+ find_provcfg(pp, "type"), fmtsize(pp->lg_mediasize));
+ first = end;
+ }
+ if (first <= last) {
+ printf(" %*llu %*llu %*s - free - (%s)\n",
+ wblocks, first, wblocks, last - first + 1,
+ wname, "",
+ fmtsize((last - first + 1) * secsz));
+ }
+ printf("\n");
+}
+
+static void
+gpart_show(struct gctl_req *req, unsigned fl __unused)
+{
+ struct gmesh mesh;
+ struct gclass *classp;
+ struct ggeom *gp;
+ const char *name;
+ int error, i, nargs;
+
+ name = gctl_get_ascii(req, "class");
+ if (name == NULL)
+ abort();
+ error = geom_gettree(&mesh);
+ if (error != 0)
+ errc(EXIT_FAILURE, error, "Cannot get GEOM tree");
+ classp = find_class(&mesh, name);
+ if (classp == NULL) {
+ geom_deletetree(&mesh);
+ errx(EXIT_FAILURE, "Class %s not found.", name);
+ }
+ nargs = gctl_get_int(req, "nargs");
+ if (nargs > 0) {
+ for (i = 0; i < nargs; i++) {
+ name = gctl_get_ascii(req, "arg%d", i);
+ gp = find_geom(classp, name);
+ if (gp != NULL)
+ gpart_show_geom(gp);
+ else
+ errx(EXIT_FAILURE, "No such geom: %s.", name);
+ }
+ } else {
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
+ gpart_show_geom(gp);
+ }
+ }
+ geom_deletetree(&mesh);
+}
OpenPOWER on IntegriCloud