#include #include #include #include #include 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 [ ...] \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; }