about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorPeter H. Froehlich <peter.hans.froehlich@gmail.com>2021-04-23 17:59:31 +0200
committerPeter H. Froehlich <peter.hans.froehlich@gmail.com>2021-04-23 17:59:31 +0200
commit9e51cfbfd2ab013cb5e8474e74a499827f73318f (patch)
tree67a859ab30bdf013bf289bcd108d18fbe3805390
parent5ce6e90c70378c63044b526f6a8196645971576a (diff)
downloadmkgpt-9e51cfbfd2ab013cb5e8474e74a499827f73318f.tar.gz
Replace fstypes.[ch] and make --type work for real.
-rw-r--r--Makefile8
-rw-r--r--README.md9
-rw-r--r--fstypes.c69
-rw-r--r--fstypes.h40
-rw-r--r--mkgpt.c40
-rw-r--r--part_ids.c146
-rw-r--r--part_ids.h19
-rwxr-xr-xtest-mkgpt.sh7
8 files changed, 183 insertions, 155 deletions
diff --git a/Makefile b/Makefile
index 731570a..707b325 100644
--- a/Makefile
+++ b/Makefile
@@ -16,14 +16,14 @@ static: prod
 musl-static: CC:=musl-gcc
 musl-static: static
 
-mkgpt: mkgpt.o crc32.o fstypes.o guid.o
+mkgpt: mkgpt.o crc32.o guid.o part_ids.o
 
-mkgpt.o: mkgpt.c guid.h fstypes.h part.h crc32.h
-fstypes.o: fstypes.c fstypes.h guid.h
+mkgpt.o: mkgpt.c guid.h part.h crc32.h
 guid.o: guid.c guid.h
 crc32.o: crc32.c crc32.h
+part_ids.o: part_ids.c part_ids.h guid.h
 
-.PHONY: check clean format install uninstall
+.PHONY: check clean format install uninstall  dev prod static musl-static
 check:
 	-cppcheck --enable=all --inconclusive --std=c11 .
 	-shellcheck *.sh
diff --git a/README.md b/README.md
index 601d2ed..8f8eabb 100644
--- a/README.md
+++ b/README.md
@@ -61,3 +61,12 @@ Optionally, the string `random` can be used to generate a random GUID.
 - some overly specific code (Linux, Windoze) without a strong need for it
 - some strange code (static info in oversized, dynamically populated array?)
 - some rather broken code (required calls in asserts, misaligned pointers)
+
+## References
+
+Not enough people seem to know about this, so here you go:
+
+- https://www.drdobbs.com/the-new-c-x-macros/184401387
+- https://www.embedded.com/reduce-c-language-coding-errors-with-x-macros-part-1/
+- https://www.embedded.com/reduce-c-language-coding-errors-with-x-macros-part-2/
+- https://www.embedded.com/reduce-c-language-coding-errors-with-x-macros-part-3/
diff --git a/fstypes.c b/fstypes.c
deleted file mode 100644
index 2e697cf..0000000
--- a/fstypes.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-
-/* Copyright (C) 2014 by John Cronin
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
-
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
-
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include "fstypes.h"
-#include <stddef.h>
-
-GUID fstypes[512];
-char *fsnames[512];
-
-void
-init_fstypes()
-{
-	int i;
-
-	for (i = 0; i < 512; i++) {
-		string_to_guid(
-			&fstypes[i], "00000000-0000-0000-0000-000000000000");
-		fsnames[i] = NULL;
-	}
-
-	string_to_guid(&fstypes[FSTYPE_EFI_SYSTEM],
-		"C12A7328-F81F-11D2-BA4B-00A0C93EC93B");
-	fsnames[FSTYPE_EFI_SYSTEM] = "system";
-	string_to_guid(&fstypes[FSTYPE_BIOS_BOOT],
-		"21686148-6449-6E6F-744E-656564454649");
-	fsnames[FSTYPE_BIOS_BOOT] = "bios";
-	string_to_guid(&fstypes[0x01], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");
-	fsnames[0x01] = "fat12";
-	string_to_guid(&fstypes[0x04], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");
-	fsnames[0x04] = "fat16";
-	string_to_guid(&fstypes[0x06], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");
-	fsnames[0x06] = "fat16b";
-	string_to_guid(&fstypes[0x07], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");
-	fsnames[0x07] = "ntfs";
-	string_to_guid(&fstypes[0x0b], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");
-	fsnames[0x0b] = "fat32";
-	string_to_guid(&fstypes[0x0c], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");
-	fsnames[0x0c] = "fat32x";
-	string_to_guid(&fstypes[0x0e], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");
-	fsnames[0x0e] = "fat16x";
-	string_to_guid(&fstypes[0x28], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");
-	fsnames[0x28] = "fat16+";
-	string_to_guid(&fstypes[0x29], "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7");
-	fsnames[0x29] = "fat32+";
-	string_to_guid(&fstypes[0x83], "0FC63DAF-8483-4772-8E79-3D69D8477DE4");
-	fsnames[0x83] = "linux";
-	string_to_guid(&fstypes[0x82], "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F");
-	fsnames[0x82] = "swap";
-}
diff --git a/fstypes.h b/fstypes.h
deleted file mode 100644
index ed75224..0000000
--- a/fstypes.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-
-/* SPDX-License-Identifier: MIT */
-
-/* Copyright (C) 2014 by John Cronin
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
-
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
-
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef FSTYPES_H
-#define FSTYPES_H
-
-#include "guid.h"
-
-extern GUID fstypes[512];
-extern char *fsnames[512];
-
-#define FSTYPE_EFI_SYSTEM 256
-#define FSTYPE_BIOS_BOOT 257
-
-void
-init_fstypes();
-
-#endif
diff --git a/mkgpt.c b/mkgpt.c
index d57196c..0c95953 100644
--- a/mkgpt.c
+++ b/mkgpt.c
@@ -22,9 +22,9 @@
  */
 
 #include "crc32.h"
-#include "fstypes.h"
 #include "guid.h"
 #include "part.h"
+#include "part_ids.h"
 
 #include <errno.h>
 #include <limits.h>
@@ -39,8 +39,6 @@ static int
 check_parts();
 static int
 parse_opts(int argc, char **argv);
-static int
-parse_guid(char *str, GUID *guid);
 static void
 write_output();
 
@@ -60,7 +58,6 @@ static int secondary_gpt_sect;
 int
 main(int argc, char **argv)
 {
-	init_fstypes();
 	random_guid(&disk_guid);
 
 	if (parse_opts(argc, argv) != 0)
@@ -332,41 +329,6 @@ dump_help(char *fname)
 }
 
 static int
-parse_guid(char *str, GUID *guid)
-{
-	long mbr_id = -1;
-
-	/* detect request for random uuid */
-	if (!strcmp(str, "random") || !strcmp(str, "rnd"))
-		return random_guid(guid);
-
-	/* detect mbr partition id by number */
-	mbr_id = strtol(str, NULL, 0);
-	if (mbr_id == LONG_MIN || mbr_id == LONG_MAX)
-		mbr_id = -1;
-
-	/* detect by name */
-	for (int i = 0; i < 512; i++) {
-		if (fsnames[i] == NULL)
-			continue;
-		if (!strcmp(fsnames[i], str)) {
-			mbr_id = i;
-			break;
-		}
-	}
-
-	if (mbr_id >= 0 && mbr_id <= 511) {
-		if (guid_is_zero(&fstypes[mbr_id]))
-			return -1;
-		*guid = fstypes[mbr_id];
-		return 0;
-	}
-
-	/* try and parse as guid */
-	return string_to_guid(guid, str);
-}
-
-static int
 check_parts()
 {
 	/* Iterate through the partitions, checking validity */
diff --git a/part_ids.c b/part_ids.c
new file mode 100644
index 0000000..d678598
--- /dev/null
+++ b/part_ids.c
@@ -0,0 +1,146 @@
+#include "part_ids.h"
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define MBR_SWAP 0x82
+#define MBR_LINUX 0x83
+#define EFI_SYSTEM 0x100
+#define BIOS_BOOT 0x101
+
+#define GUID_TABLE \
+	X(SWAP, "0657FD6D-A4AB-43C4-84E5-0933C84B4F4F") \
+	X(LINUX, "0FC63DAF-8483-4772-8E79-3D69D8477DE4") \
+	X(SYSTEM, "C12A7328-F81F-11D2-BA4B-00A0C93EC93B") \
+	X(BDP, "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7") \
+	X(BIOS, "21686148-6449-6E6F-744E-656564454649")
+
+#define ALIAS_TABLE \
+	X("fat12", 0x01, BDP) \
+	X("fat16", 0x04, BDP) \
+	X("fat16b", 0x06, BDP) \
+	X("ntfs", 0x07, BDP) \
+	X("fat32", 0x0b, BDP) \
+	X("fat32x", 0x0c, BDP) \
+	X("fat16x", 0x0e, BDP) \
+	X("fat16+", 0x28, BDP) \
+	X("fat32+", 0x29, BDP) \
+	X("swap", MBR_SWAP, SWAP) \
+	X("linux", MBR_LINUX, LINUX) \
+	X("system", EFI_SYSTEM, SYSTEM) \
+	X("bios", BIOS_BOOT, BIOS)
+
+/* First we generate compact indices for each GUID using an enum. */
+enum GUID_INDEX {
+#define X(index, guid) GUID_ ## index,
+	GUID_TABLE
+#undef X
+	NUM_GUIDS,
+};
+
+/*
+ * Then we plop down the GUIDs in a compact table. Overly compact maybe? Note
+ * that there are no pointers involved and no NUL terminators at the "end" of
+ * a GUID, so don't try to `printf` them directly!
+ */
+static char guids[NUM_GUIDS][GUID_STRLEN] = {
+#define X(index, guid) [GUID_ ## index] = guid,
+	GUID_TABLE
+#undef X
+};
+
+/*
+ * Now for the aliases that "point" to the GUIDs. Note that these are *not*
+ * sorted, but unless we have thousands of names, a linear search should be
+ * all we need. A `key` of `NULL` marks the end.
+ */
+static struct {char *key; int value;} name_to_guid[] = {
+#define X(name, id, index) {name, GUID_ ## index},
+	ALIAS_TABLE
+#undef X
+	{NULL, -1},
+};
+
+/*
+ * The same for the "short" MBR-style ids. A `key` of `-1` marks the end.
+ */
+static struct {int key; int value;} mbr_to_guid[] = {
+#define X(name, id, index) {id, GUID_ ## index},
+	ALIAS_TABLE
+#undef X
+	{-1, -1},
+};
+
+int
+valid_string_guid(const char str[GUID_STRLEN])
+{
+	/* TODO there may be a simpler way? but let's avoid regexp stuff... */
+
+	static const int spans[5] = {8, 4, 4, 4, 12}; /* spans of hex digits */
+	/* (sum spans) + 4 == GUID_STRLEN */
+
+	int pos = 0;
+
+	/* for all spans */
+	for (int i = 0; i < 5; i++) {
+		/* for all hex digits in span */
+		for (int j = 0; j < spans[i]; j++) {
+			if (!isxdigit(str[pos])) {
+				return 0;
+			}
+			pos++;
+		}
+		/* need a '-' except after the last span */
+		if (i == 4) {
+			break;
+		}
+
+		if (str[pos] != '-') {
+			return 0;
+		}
+		pos++;
+	}
+
+	return 1;
+}
+
+/*
+ * Parse GUID/UUID notation used on the command line.
+ * Returns 0 on success.
+ */
+int
+parse_guid(const char *str, GUID *guid)
+{
+	/* detect request for random uuid */
+	if (!strcmp(str, "random") || !strcmp(str, "rnd")) {
+		return random_guid(guid);
+	}
+
+	/* detect by name */
+	for (int i = 0; name_to_guid[i].key != NULL; i++) {
+		if (!strcmp(str, name_to_guid[i].key)) {
+			return string_to_guid(guid, guids[name_to_guid[i].value]);
+		}
+	}
+
+	/* try and parse as guid */
+	if (valid_string_guid(str)) {
+		return string_to_guid(guid, str);
+	}
+
+	/* detect mbr partition id by number */
+	errno = 0;
+	long mbr_id = strtol(str, NULL, 0);
+	if (errno != 0) {
+		return -1;
+	}
+	for (int i = 0; mbr_to_guid[i].key != -1; i++) {
+		if (mbr_to_guid[i].key == mbr_id) {
+			return string_to_guid(guid, guids[mbr_to_guid[i].value]);
+		}
+	}
+
+	return -1;
+}
diff --git a/part_ids.h b/part_ids.h
new file mode 100644
index 0000000..d686e0b
--- /dev/null
+++ b/part_ids.h
@@ -0,0 +1,19 @@
+#pragma once
+
+/* SPDX-License-Identifier: MIT */
+
+#ifndef PART_IDS_H
+#define PART_IDS_H
+
+#include "guid.h"
+
+/* Length of string-format GUID *excluding* NUL terminator. */
+#define GUID_STRLEN (sizeof("ABCDEF01-2345-6789-ABCD-EF0123456789") - 1)
+
+int
+valid_string_guid(const char str[GUID_STRLEN]);
+
+int
+parse_guid(const char *str, GUID *guid);
+
+#endif
diff --git a/test-mkgpt.sh b/test-mkgpt.sh
index 4cf75e3..6d291aa 100755
--- a/test-mkgpt.sh
+++ b/test-mkgpt.sh
@@ -10,8 +10,8 @@ if [ ! -x ./mkgpt ]; then
 fi
 
 mkdir -pv ${tmpdir}
-for name in a.img b.img c.img d.img; do
-	truncate --size=16M ${tmpdir}/${name}
+for name in a.img b.img c.img d.img e.img; do
+	truncate --size=8M ${tmpdir}/${name}
 done
 
 # TODO something goes wrong with --sector-size 1024 or 4096
@@ -19,7 +19,8 @@ done
 	--part ${tmpdir}/a.img --type system \
 	--part ${tmpdir}/b.img --type fat32 \
 	--part ${tmpdir}/c.img --type linux \
-	--part ${tmpdir}/d.img --type swap
+	--part ${tmpdir}/d.img --type 0x82 \
+	--part ${tmpdir}/e.img --type 21686148-6449-6E6F-744E-656564454649
 
 fdisk -l ${tmpdir}/bla.img