From 615e3302c9dd358bb64cd56d1f3814ad8d5df84d Mon Sep 17 00:00:00 2001 From: vetch Date: Sat, 4 Jan 2020 19:37:32 +0100 Subject: rearranged files, updated makefile --- src/memory/makefs.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/memory/makefs.c (limited to 'src/memory/makefs.c') diff --git a/src/memory/makefs.c b/src/memory/makefs.c new file mode 100644 index 0000000..379e8c5 --- /dev/null +++ b/src/memory/makefs.c @@ -0,0 +1,97 @@ +// Take files given on stdin and make them into a ramfs image of our +// own, (stupid) simple format. +// In the format: for each file comes the null-terminated string +// with filename, then null-padding until a 4-aligned offset, then +// 4-byte little-endian size of the file and then the contents +// of the file and then another null-padding until a 4-aligned offset. +// Files encoded this way go one after another (so it's easy to add +// something at the beginning). +// At the and comes one null-byte (as if a file with empty name +// was there). + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ANSI_FG_RED "\033[0;31m" +#define ANSI_FG_DEFAULT "\033[0;39m" + +int main(int argc, char **argv) +{ + // process files in the order they are provided on the command line + for (int i = 1; i < argc; i++) + { + struct stat fileinfo; + + if (stat(argv[i], &fileinfo)) + err(-1, "couldn't stat " ANSI_FG_RED "%s" ANSI_FG_DEFAULT, + argv[i]); + + if (!S_ISREG(fileinfo.st_mode)) + errx(-1, ANSI_FG_RED "%s" ANSI_FG_DEFAULT + " is not a regular file.", argv[i]); + + // don't allow files with size so big, that it can't be encoded + // in a 4-byte unsigned int... In practice even smaller files + // won't fit on the rpi. + if (fileinfo.st_size > UINT32_MAX) + errx(-1, ANSI_FG_RED "%s" ANSI_FG_DEFAULT + " is too big.", argv[i]); + + uint32_t file_size = fileinfo.st_size; + uint32_t name_size = strlen(argv[i]) + 1; // 1 for null-byte + + if (fwrite(argv[i], 1, name_size, stdout) != name_size) + errx(-1, "error writing to stdout"); + + // pad with null-bytes until a 4-aligned offset + for (uint32_t j = 0; (j + name_size) & 0b11; j++) + if (putchar('\0')) + errx(-1, "error writing to stdout"); + + // TODO convert file_size to little endian first (in case our + // host is be). + if (fwrite(&file_size, 4, 1, stdout) != 1) + errx(-1, "error writing to stdout"); + + // flush b4 running cat, so that stuff we've written comes + // b4 the actual file contents in the output + if (fflush(stdout)) + err(-1, "couldn't flush stdout"); + + // we don't copy the actual file ourselves - we run cat for that + pid_t pid; + int wstatus; + switch (pid = fork()) + { + case -1: + err(-1, "couldn't fork"); + case 0: + if (execlp("cat", "cat", argv[i], NULL)) + err(-1, "couldn't execute cat"); + default: + if (wait(&wstatus) == -1) + err(-1, "error waiting for child"); + + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) + exit(-1); + } + + // again, pad with null-bytes until a 4-aligned offset + for (uint32_t j = 0; (j + file_size) & 0b11; j++) + if (putchar('\0')) + errx(-1, "error writing to stdout"); + } + + if (putchar('\0')) + errx(-1, "error writing to stdout"); + + return 0; +} + -- cgit v1.2.3