From 2c80b79f9856e08a62d7648f72bbb8eb847e7a09 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Thu, 4 Nov 2021 16:35:00 +0100 Subject: [PATCH 262/325] geli: Implement search command --- lib/geom/eli/geom_eli.c | 88 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/lib/geom/eli/geom_eli.c b/lib/geom/eli/geom_eli.c index bd1c60c40c96..a966ce6c0d70 100644 --- a/lib/geom/eli/geom_eli.c +++ b/lib/geom/eli/geom_eli.c @@ -84,6 +84,7 @@ static void eli_resize(struct gctl_req *req); static void eli_version(struct gctl_req *req); static void eli_clear(struct gctl_req *req); static void eli_dump(struct gctl_req *req); +static void eli_search(struct gctl_req *req); static int eli_backup_create(struct gctl_req *req, const char *prov, const char *file); @@ -109,6 +110,7 @@ static int eli_backup_create(struct gctl_req *req, const char *prov, * version [prov ...] * clear [-v] prov ... * dump [-v] prov ... + * search [-v] prov ... */ struct g_command class_commands[] = { { "init", G_FLAG_VERBOSE, eli_main, @@ -277,6 +279,9 @@ struct g_command class_commands[] = { { "dump", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, "[-v] prov ..." }, + { "search", G_FLAG_VERBOSE, eli_main, G_NULL_OPTS, + "[-v] prov ..." + }, G_CMD_SENTINEL }; @@ -339,6 +344,8 @@ eli_main(struct gctl_req *req, unsigned int flags) eli_restore(req); else if (strcmp(name, "resize") == 0) eli_resize(req); + else if (strcmp(name, "search") == 0) + eli_search(req); else if (strcmp(name, "version") == 0) eli_version(req); else if (strcmp(name, "dump") == 0) @@ -650,6 +657,62 @@ eli_metadata_read(struct gctl_req *req, const char *prov, return (0); } +static int +eli_metadata_search(struct gctl_req *req, const char *prov, + struct g_eli_metadata *md) +{ + unsigned char sector[sizeof(struct g_eli_metadata)]; + int error; + + if (g_get_sectorsize(prov) == 0) { + int fd; + + /* This is a file probably. */ + fd = open(prov, O_RDONLY); + if (fd == -1) { + gctl_error(req, "Cannot open %s: %s.", prov, + strerror(errno)); + return (-1); + } + if (read(fd, sector, sizeof(sector)) != sizeof(sector)) { + gctl_error(req, "Cannot read metadata from %s: %s.", + prov, strerror(errno)); + close(fd); + return (-1); + } + close(fd); + } else { + /* This is a GEOM provider. */ + error = g_metadata_search(prov, sector, sizeof(sector), + G_ELI_MAGIC); + if (error != 0) { + gctl_error(req, "Cannot read metadata from %s: %s.", + prov, strerror(error)); + return (-1); + } + } + error = eli_metadata_decode(sector, md); + switch (error) { + case 0: + break; + case EOPNOTSUPP: + gctl_error(req, + "Provider's %s metadata version %u is too new.\n" + "geli: The highest supported version is %u.", + prov, (unsigned int)md->md_version, G_ELI_VERSION); + return (-1); + case EINVAL: + gctl_error(req, "Inconsistent provider's %s metadata.", prov); + return (-1); + default: + gctl_error(req, + "Unexpected error while decoding provider's %s metadata: %s.", + prov, strerror(error)); + return (-1); + } + return (0); +} + static int eli_metadata_store(struct gctl_req *req, const char *prov, struct g_eli_metadata *md) @@ -1988,3 +2051,28 @@ eli_dump(struct gctl_req *req) printf("\n"); } } + +static void +eli_search(struct gctl_req *req) +{ + struct g_eli_metadata md; + const char *name; + int i, nargs; + + nargs = gctl_get_int(req, "nargs"); + if (nargs < 1) { + gctl_error(req, "Too few arguments."); + return; + } + + for (i = 0; i < nargs; i++) { + name = gctl_get_ascii(req, "arg%d", i); + if (eli_metadata_search(NULL, name, &md) == -1) { + gctl_error(req, "Not fully done."); + continue; + } + printf("Metadata found on %s:\n", name); + eli_metadata_dump(&md); + printf("\n"); + } +} -- 2.32.0