From b573cc7f4129bc3216f5953978be0a7bd29bfe69 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Thu, 4 Nov 2021 16:27:31 +0100 Subject: [PATCH 288/310] sbin/geom/misc: Add g_metadata_search() ... which is needed to implement a "search" subcommand for geli. Obtained from: ElectroBSD --- sbin/geom/misc/subr.c | 75 +++++++++++++++++++++++++++++++++++++++++++ sbin/geom/misc/subr.h | 3 ++ 2 files changed, 78 insertions(+) diff --git a/sbin/geom/misc/subr.c b/sbin/geom/misc/subr.c index 3985ae56edc6..5141ce256c67 100644 --- a/sbin/geom/misc/subr.c +++ b/sbin/geom/misc/subr.c @@ -273,6 +273,81 @@ g_metadata_read(const char *name, unsigned char *md, size_t size, return (error); } +int +g_metadata_search(const char *name, unsigned char *md, size_t size, + const char *magic, off_t *metadata_offset) +{ + struct std_metadata stdmd; + unsigned char *sector; + ssize_t sectorsize; + off_t mediasize; + int error, fd; + off_t offset; + + *metadata_offset = 0; + sector = NULL; + error = 0; + + fd = g_open(name, 0); + if (fd == -1) + return (errno); + mediasize = g_mediasize(fd); + if (mediasize == -1) { + error = errno; + goto out; + } + sectorsize = g_sectorsize(fd); + if (sectorsize == -1) { + error = errno; + goto out; + } + assert(sectorsize >= (ssize_t)size); + sector = malloc(sectorsize); + if (sector == NULL) { + error = ENOMEM; + goto out; + } + + fprintf(stderr, "Searching for %s metadata on %s.\n", magic, name); + + offset = mediasize - sectorsize; + while (offset > 0) { + if (offset % 1073741824 == 0) { + /* Should be reworded */ + fprintf(stderr, + "Next search offset is %ju.\n", (uintmax_t)offset); + } + if (pread(fd, sector, sectorsize, offset) != + sectorsize) { + error = errno; + fprintf(stderr, "Failed to read at offset %ju.\n", + (uintmax_t)offset); + goto out; + } + if (magic != NULL) { + std_metadata_decode(sector, &stdmd); + if (strcmp(stdmd.md_magic, magic) != 0) { + offset -= sectorsize; + continue; + } else { + fprintf(stderr, + "Found %s meta data at offset %ju.\n", + magic, (uintmax_t)offset); + *metadata_offset = offset; + break; + } + } + offset -= sectorsize; + } + + bcopy(sector, md, size); +out: + if (sector != NULL) + free(sector); + g_close(fd); + return (error); +} + /* * Actually write the GEOM label to the provider * diff --git a/sbin/geom/misc/subr.h b/sbin/geom/misc/subr.h index 579c94c21491..9a05d47f2c6f 100644 --- a/sbin/geom/misc/subr.h +++ b/sbin/geom/misc/subr.h @@ -41,6 +41,9 @@ unsigned int g_get_sectorsize(const char *name); int g_metadata_read(const char *name, unsigned char *md, size_t size, const char *magic); +int +g_metadata_search(const char *name, unsigned char *md, size_t size, + const char *magic, off_t *metadata_offset); int g_metadata_store(const char *name, const unsigned char *md, size_t size); int g_metadata_clear(const char *name, const char *magic); -- 2.37.1