From 742c76b9f67aa71e5133ef78a10a2fe14e1591f1 Mon Sep 17 00:00:00 2001 From: Fabian Keil Date: Thu, 4 Nov 2021 16:27:31 +0100 Subject: [PATCH 261/325] sbin/geom/misc: Add g_metadata_search() Obtained from: ElectroBSD --- sbin/geom/misc/subr.c | 73 +++++++++++++++++++++++++++++++++++++++++++ sbin/geom/misc/subr.h | 3 ++ 2 files changed, 76 insertions(+) diff --git a/sbin/geom/misc/subr.c b/sbin/geom/misc/subr.c index 3985ae56edc6..eb25c484a94d 100644 --- a/sbin/geom/misc/subr.c +++ b/sbin/geom/misc/subr.c @@ -273,6 +273,79 @@ 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) +{ + struct std_metadata stdmd; + unsigned char *sector; + ssize_t sectorsize; + off_t mediasize; + int error, fd; + off_t offset; + + 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); + 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..80c27118db7b 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); 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.32.0