diff options
Diffstat (limited to 'src/saturn-mkiso.c')
-rw-r--r-- | src/saturn-mkiso.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/src/saturn-mkiso.c b/src/saturn-mkiso.c new file mode 100644 index 0000000..766d3ce --- /dev/null +++ b/src/saturn-mkiso.c @@ -0,0 +1,116 @@ +#include <getopt.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static void usage(const char *progname) +{ + static const int width = 24; + + printf("usage: %s -h\n", progname); + printf(" %s -bo[ABC] [files...]\n\n", progname); + printf("\t%-*s%s\n", width, "-h", "Show this help text"); + printf("\t%-*s%s\n", width, "-b bootsector", "Bootsector image"); + printf("\t%-*s%s\n", width, "-o output", "Output isofs file"); + printf("\t%-*s%s\n", width, "-A abstract_path", "Path in isofs of abstract file"); + printf("\t%-*s%s\n", width, "-B bibliography_path", "Path in isofs of bibliography file"); + printf("\t%-*s%s\n", width, "-C copyright_path", "Path in isofs of copyright file"); + printf("\t%-*s%s\n", width, "files...", "Files to include in the isofs image"); + + printf("\nFor -A/B/C, the path must refer to a file which exists within the isofs image.\n"); +} + +#define FLAG_o (1U << 1) +#define FLAG_b (1U << 3) +#define FLAG_A (1U << 5) +#define FLAG_B (1U << 7) +#define FLAG_C (1U << 9) + +int main(int argc, char **argv) +{ + static const char *optpat = "ho:b:A:B:C:"; + static const char *fileopts = "boABC"; + char *specialfiles[5] = { + 0, 0, "DUMMY.TXT", "DUMMY.TXT", "DUMMY.TXT", + }; + +#define SPECIALFILE(c) specialfiles[strchr(fileopts, (c)) - fileopts] + + uint32_t seen = 0; + int opt, fail = 0; + +#define SEEN(flags) ((seen | (flags)) == seen) +#define FLAG(c) (1U << (strchr(optpat, (c)) - optpat)) + + extern char *optarg; + extern int optind, optopt; + while ((opt = getopt(argc, argv, optpat)) != -1) { + uint32_t flag = opt == '?' ? 0 : FLAG(opt); + if (SEEN(flag)) { + fprintf(stderr, "%s: Duplicate option -%c\n", argv[0], opt); + fail = 1; + continue; + } + seen |= flag; + + switch (opt) { + case 'h': + usage(argv[0]); + return 0; + + case 'b': + case 'o': + case 'A': + case 'B': + case 'C': + SPECIALFILE(opt) = optarg; + break; + + default: + fail = 1; + } + } + + for (const char *c = "bo"; *c; c++) { + if (!SEEN(FLAG(*c))) { + fprintf(stderr, "%s: Missing required option -%c\n", argv[0], *c); + fail = 1; + } + } + if (fail) { + fprintf(stderr, "\nUse -h option for help on correct usage.\n"); + return 1; + } + + char *argprefix[] = { + "mkisofs", "-graft-points", "-full-iso9660-filenames", + "-G", SPECIALFILE('b'), + "-o", SPECIALFILE('o'), + "-abstract", SPECIALFILE('A'), + "-biblio", SPECIALFILE('B'), + "-copyright", SPECIALFILE('C'), + }; + +#define ARRAYLEN(a) (sizeof(a) / sizeof *(a)) + + char **args = calloc(argc - optind + ARRAYLEN(argprefix) + 2, sizeof *args); + if (!args) { + perror("malloc"); + return 1; + } + + size_t argidx; + for (argidx = 0; argidx < ARRAYLEN(argprefix); argidx++) + args[argidx] = argprefix[argidx]; + while (argv[optind]) + args[argidx++] = argv[optind++]; + if (!SEEN(FLAG_A | FLAG_B | FLAG_C)) + args[argidx++] = "DUMMY.TXT=/dev/null"; + + execvp("mkisofs", args); + perror("exec"); + return 1; +} + |