From 9e51cfbfd2ab013cb5e8474e74a499827f73318f Mon Sep 17 00:00:00 2001 From: "Peter H. Froehlich" Date: Fri, 23 Apr 2021 17:59:31 +0200 Subject: Replace fstypes.[ch] and make --type work for real. --- Makefile | 8 ++-- README.md | 9 ++++ fstypes.c | 69 --------------------------- fstypes.h | 40 ---------------- mkgpt.c | 40 +--------------- part_ids.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ part_ids.h | 19 ++++++++ test-mkgpt.sh | 7 +-- 8 files changed, 183 insertions(+), 155 deletions(-) delete mode 100644 fstypes.c delete mode 100644 fstypes.h create mode 100644 part_ids.c create mode 100644 part_ids.h 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 - -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 #include @@ -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) @@ -331,41 +328,6 @@ dump_help(char *fname) 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() { 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 +#include +#include +#include + +#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 -- cgit 1.4.1-2-gfad0