120 lines
2.7 KiB
C
120 lines
2.7 KiB
C
// 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 <ctype.h>
|
|
#include <errno.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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";
|
|
|
|
|
|
// "<toolName>: <message>" 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;
|
|
}
|