// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. // See LICENSE.md for license information. // SPDX-License-Identifier: MIT // // toolFile.c - whole-file reads and writes, numbers from the command line, // and fatal errors for the JoeyLib host tools (toolFile.h). #include #include #include #include #include #include #include "toolFile.h" #define FAIL_EXIT 1 static void failV(int code, const char *fmt, va_list args) __attribute__((noreturn, format(printf, 2, 0))); static const char *gToolName = "tool"; // ": " to stderr, then exit with code. static void failV(int code, const char *fmt, va_list args) { fprintf(stderr, "%s: ", gToolName); vfprintf(stderr, fmt, args); fputc('\n', stderr); exit(code); } void toolFail(const char *fmt, ...) { va_list args; va_start(args, fmt); failV(FAIL_EXIT, fmt, args); } void toolFailCode(int code, const char *fmt, ...) { va_list args; va_start(args, fmt); failV(code, fmt, args); } void toolFileName(const char *toolName) { gToolName = toolName; } bool toolParseInt(const char *s, size_t len, long *out) { char buf[32]; char *end; size_t i; while (len > 0u && isspace((unsigned char)*s)) { s++; len--; } while (len > 0u && isspace((unsigned char)s[len - 1u])) { len--; } if (len == 0u || len >= sizeof(buf)) { return false; } memcpy(buf, s, len); buf[len] = '\0'; for (i = (buf[0] == '+' || buf[0] == '-') ? 1u : 0u; i < len; i++) { if (!isdigit((unsigned char)buf[i])) { return false; } } errno = 0; *out = strtol(buf, &end, 10); return *end == '\0' && errno != ERANGE; } bool toolReadFile(const char *path, uint8_t **data, size_t *len) { FILE *f; uint8_t *buf; long size; f = fopen(path, "rb"); if (f == NULL) { return false; } if (fseek(f, 0, SEEK_END) != 0 || (size = ftell(f)) < 0 || fseek(f, 0, SEEK_SET) != 0) { fclose(f); return false; } buf = (uint8_t *)malloc((size_t)size + 1u); if (buf == NULL || fread(buf, 1, (size_t)size, f) != (size_t)size) { free(buf); fclose(f); return false; } fclose(f); buf[size] = 0u; *data = buf; *len = (size_t)size; return true; } bool toolWriteFile(const char *path, const uint8_t *data, size_t len) { FILE *f; bool ok; f = fopen(path, "wb"); if (f == NULL) { return false; } ok = fwrite(data, 1, len, f) == len; ok = fclose(f) == 0 && ok; return ok; }