Add tools
This commit is contained in:
parent
8c10334252
commit
24f1366b51
|
@ -0,0 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.0)
|
||||
project(utils)
|
||||
add_executable(container "container.c")
|
||||
target_compile_options(container PUBLIC -g3)
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue