diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-04 00:55:59 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-06 22:21:50 +0200 |
| commit | 892ecce78dec37a1b2701611dd72986442cd094d (patch) | |
| tree | bbd7fb0a0229795bf52d0b8a9ff9b06251363a67 /tools | |
| parent | 99554cc243c4b2ec290639a04ebc2f189890d6dd (diff) | |
| download | wnix-892ecce78dec37a1b2701611dd72986442cd094d.tar.gz | |
Import project skeleton from rts
https://gitea.privatedns.org/xavi/rts
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/CMakeLists.txt | 8 | ||||
| -rw-r--r-- | tools/add-header.c | 67 | ||||
| -rw-r--r-- | tools/container.c | 129 |
3 files changed, 204 insertions, 0 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..14d2b0e --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.0) +project(utils) +add_executable(container "container.c") +add_executable(add-header "add-header.c") +set(cflags -Wall -g3) +target_compile_options(container PUBLIC ${cflags}) +target_compile_options(add-header PUBLIC ${cflags}) +install(TARGETS container add-header DESTINATION bin) diff --git a/tools/add-header.c b/tools/add-header.c new file mode 100644 index 0000000..75f7458 --- /dev/null +++ b/tools/add-header.c @@ -0,0 +1,67 @@ +#include <errno.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int main(int argc, char **const argv) +{ + int ret = EXIT_FAILURE; + FILE *in = NULL, *out = NULL; + + if (argc < 3) + { + fprintf(stderr, "%s [arg ...] <in-file> <out-file>\n", *argv); + goto end; + } + + const char *const in_path = argv[argc - 2], + *const out_path = argv[argc - 1]; + + if (!(out = fopen(out_path, "wb"))) + { + fprintf(stderr, "could not open %s: %s\n", out_path, strerror(errno)); + goto end; + } + else if (!(in = fopen(in_path, "rb"))) + { + fprintf(stderr, "could not open %s: %s\n", in_path, strerror(errno)); + goto end; + } + + for (int i = 1; i < argc - 2; i++) + { + if (fprintf(out, "%s", argv[i]) < 0 + || putc('\0', out) == EOF + || ferror(out)) + { + fprintf(stderr, "failed writing to %s\n", out_path); + goto end; + } + } + + while (!feof(in)) + { + char c; + + if ((!fread(&c, sizeof c, 1, in) + || !fwrite(&c, sizeof c, 1, out)) + && (ferror(in) || ferror(out))) + { + fprintf(stderr, "ferror(%s)=%d, ferror(%s)=%d\n", + in_path, ferror(in), out_path, ferror(out)); + goto end; + } + } + + ret = EXIT_SUCCESS; + +end: + if (out) + fclose(out); + + if (in) + fclose(in); + + return ret; +} diff --git a/tools/container.c b/tools/container.c new file mode 100644 index 0000000..254eee3 --- /dev/null +++ b/tools/container.c @@ -0,0 +1,129 @@ +#include <errno.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static const char *filename(const char *const path) +{ + const char *ret = &path[strlen(path)]; + + while (ret != path && *(ret - 1) != '\\' && *(ret - 1) != '/') + ret--; + + return ret; +} + +static int dump_file(const char *const path, const char *const outpath, + FILE *const out) +{ + int ret = -1; + FILE *const f = fopen(path, "rb"); + + if (!f) + { + fprintf(stderr, "%s: could not open %s: %s\n", + __func__, path, strerror(errno)); + goto end; + } + + const char *const bname = filename(path); + + if (fprintf(out, "%s", bname) < 0) + { + fprintf(stderr, "fprintf(f, %s): %s\n", path, strerror(errno)); + goto end; + } + else if (fputc('\0', out) == EOF) + { + perror("could not write null character"); + goto end; + } + else if (fseek(f, 0, SEEK_END)) + { + perror("fseek(SEEK_END)"); + goto end; + } + + /* This won't work on files larger than 2 GiB if sizeof sz == 4, + * but this is acceptable for a PS1 video game. */ + const long sz = ftell(f); + + if (fprintf(out, "%ld", sz) < 0) + { + perror("could not write file size"); + goto end; + } + else if (fputc('\0', out) == EOF) + { + perror("could not write null character"); + goto end; + } + else if (fseek(f, 0, SEEK_SET)) + { + fprintf(stderr, "%s: fseek(SEEK_SET): %s\n", __func__, strerror(errno)); + goto end; + } + + while (!feof(f)) + { + char c; + + if (!fread(&c, sizeof c, 1, f)) + { + if (ferror(f)) + { + fprintf(stderr, "%s: ferror\n", path); + goto end; + } + } + else if (fputc(c, out) == EOF) + { + fprintf(stderr, "could not dump %s to %s", path, outpath); + goto end; + } + } + + ret = 0; + +end: + if (f) + fclose(f); + + return ret; +} + +int main(const int argc, const char *const *const argv) +{ + int ret = EXIT_FAILURE; + size_t n_in = 0; + FILE *out = NULL; + + if (argc < 3) + { + fprintf(stderr, "%s <file1> [<file2> ...] <output>\n", *argv); + goto end; + } + + const char *const outpath = argv[argc - 1]; + + n_in = argc - 2; + + if (!(out = fopen(outpath, "wb"))) + { + fprintf(stderr, "could not open %s: %s\n", outpath, strerror(errno)); + goto end; + } + + for (size_t i = 0; i < n_in; i++) + if (dump_file(argv[i + 1], outpath, out)) + goto end; + + ret = EXIT_SUCCESS; + +end: + if (out) + fclose(out); + + return ret; +} |
