summaryrefslogtreecommitdiffstats
path: root/sbin/gpt/map.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2002-07-20 19:27:43 +0000
committerpeter <peter@FreeBSD.org>2002-07-20 19:27:43 +0000
commit6dfc24537dd08c0fd54fef53634257ed5b85aa8e (patch)
tree58b29ec4f042260b9ce91a33c9f2cd135c628d9c /sbin/gpt/map.c
parentaefe01915ae8c5993f364f973809e39b9773eb59 (diff)
downloadFreeBSD-src-6dfc24537dd08c0fd54fef53634257ed5b85aa8e.zip
FreeBSD-src-6dfc24537dd08c0fd54fef53634257ed5b85aa8e.tar.gz
Grab a snapshot of Marcel's gpt tool. This is still a work-in-progress
but is useful to have handy. EFI GPT partitions are used instead of the fdisk+disklabel combination. They are pure 64 bit LBA, are fully extensible, support up to 16383 partitons per disk, etc.
Diffstat (limited to 'sbin/gpt/map.c')
-rw-r--r--sbin/gpt/map.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/sbin/gpt/map.c b/sbin/gpt/map.c
new file mode 100644
index 0000000..93d0f61
--- /dev/null
+++ b/sbin/gpt/map.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2002 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "map.h"
+
+static int lbawidth;
+static map_t *mediamap;
+
+static map_t *
+mkmap(off_t start, off_t size, int type)
+{
+ map_t *m;
+
+ m = malloc(sizeof(*m));
+ if (m == NULL)
+ return (NULL);
+ m->map_start = start;
+ m->map_size = size;
+ m->map_next = m->map_prev = NULL;
+ m->map_type = type;
+ m->map_data = NULL;
+ return (m);
+}
+
+map_t *
+map_add(off_t start, off_t size, int type, void *data)
+{
+ map_t *m, *n, *p;
+
+ n = mediamap;
+ while (n != NULL && n->map_start + n->map_size <= start)
+ n = n->map_next;
+ if (n == NULL)
+ return (NULL);
+
+ if (n->map_start + n->map_size < start + size) {
+ warnx("error: bogus map");
+ return (0);
+ }
+
+ if (n->map_start == start && n->map_size == size) {
+ if (n->map_type != MAP_TYPE_UNUSED)
+ warnx("warning: partition(%llu,%llu) mirrored",
+ (long long)start, (long long)size);
+ n->map_type = type;
+ n->map_data = data;
+ return (n);
+ }
+
+ if (n->map_type != MAP_TYPE_UNUSED) {
+ warnx(
+ "error: partition(%llu,%llu) overlaps partition(%llu,%llu)",
+ (long long)start, (long long)size,
+ (long long)n->map_start, (long long)n->map_size);
+ return (0);
+ }
+
+ m = mkmap(start, size, type);
+ if (m == NULL)
+ return (NULL);
+
+ m->map_data = data;
+
+ if (start == n->map_start) {
+ m->map_prev = n->map_prev;
+ m->map_next = n;
+ if (m->map_prev != NULL)
+ m->map_prev->map_next = m;
+ else
+ mediamap = m;
+ n->map_prev = m;
+ n->map_start += size;
+ n->map_size -= size;
+ } else if (start + size == n->map_start + n->map_size) {
+ p = n;
+ m->map_next = p->map_next;
+ m->map_prev = p;
+ if (m->map_next != NULL)
+ m->map_next->map_prev = m;
+ p->map_next = m;
+ p->map_size -= size;
+ } else {
+ p = mkmap(n->map_start, start - n->map_start, n->map_type);
+ n->map_start += p->map_size + m->map_size;
+ n->map_size -= (p->map_size + m->map_size);
+ p->map_prev = n->map_prev;
+ m->map_prev = p;
+ n->map_prev = m;
+ m->map_next = n;
+ p->map_next = m;
+ if (p->map_prev != NULL)
+ p->map_prev->map_next = p;
+ else
+ mediamap = p;
+ }
+
+ return (m);
+}
+
+map_t *
+map_find(int type)
+{
+ map_t *m;
+
+ m = mediamap;
+ while (m != NULL && m->map_type != type)
+ m = m->map_next;
+ return (m);
+}
+
+map_t *
+map_first(void)
+{
+ return mediamap;
+}
+
+map_t *
+map_last(void)
+{
+ map_t *m;
+
+ m = mediamap;
+ while (m != NULL && m->map_next != NULL)
+ m = m->map_next;
+ return (m);
+}
+
+off_t
+map_unused(off_t start, off_t size)
+{
+ map_t *m;
+
+ m = mediamap;
+
+ while (m != NULL && m->map_start + m->map_size <= start)
+ m = m->map_next;
+ if (m == NULL || m->map_type != MAP_TYPE_UNUSED)
+ return (0LL);
+ if (size)
+ return ((m->map_start + m->map_size >= start + size) ? 1 : 0);
+ return (m->map_size - (start - m->map_start));
+}
+
+void
+map_dump(void)
+{
+ off_t end;
+ map_t *m;
+
+ printf(" %*s", lbawidth, "start");
+ printf(" %*s", lbawidth, "end");
+ printf(" %*s", lbawidth, "size");
+ printf(" %s\n", "contents");
+
+ m = mediamap;
+ while (m != NULL) {
+ end = m->map_start + m->map_size - 1;
+ printf(" %*llu", lbawidth, (long long)m->map_start);
+ printf(" %*llu", lbawidth, (long long)end);
+ printf(" %*llu", lbawidth, (long long)m->map_size);
+
+ putchar(' '); putchar(' ');
+ switch (m->map_type) {
+ case MAP_TYPE_MBR:
+ printf("MBR");
+ break;
+ case MAP_TYPE_PRI_GPT_HDR:
+ printf("Pri GPT header");
+ break;
+ case MAP_TYPE_SEC_GPT_HDR:
+ printf("Sec GPT header");
+ break;
+ case MAP_TYPE_PRI_GPT_TBL:
+ printf("Pri GPT table");
+ break;
+ case MAP_TYPE_SEC_GPT_TBL:
+ printf("Sec GPT table");
+ break;
+ case MAP_TYPE_MBR_PART:
+ printf("MBR partition");
+ break;
+ case MAP_TYPE_GPT_PART:
+ printf("GPT partition");
+ break;
+ }
+ putchar('\n');
+ m = m->map_next;
+ }
+}
+
+void
+map_init(off_t size)
+{
+ char buf[32];
+
+ mediamap = mkmap(0LL, size, MAP_TYPE_UNUSED);
+ lbawidth = sprintf(buf, "%llu", (long long)size);
+ if (lbawidth < 5)
+ lbawidth = 5;
+}
OpenPOWER on IntegriCloud