#include <stdlib.h>
#include <string.h>
+static int redump_path_exists(const char *path) {
+ FILE *f;
+ if (!path || !path[0])
+ return 0;
+ f = fopen(path, "rb");
+ if (!f)
+ return 0;
+ fclose(f);
+ return 1;
+}
+
+static int redump_join_path(
+ const char *dir,
+ const char *child_dir,
+ const char *basename,
+ char *out_path,
+ size_t out_path_size
+) {
+ int written;
+
+ if (!dir || !dir[0] || !basename || !basename[0] ||
+ !out_path || out_path_size == 0)
+ return 0;
+
+ if (child_dir && child_dir[0])
+ written = snprintf(out_path, out_path_size, "%s/%s/%s",
+ dir, child_dir, basename);
+ else
+ written = snprintf(out_path, out_path_size, "%s/%s",
+ dir, basename);
+
+ if (written < 0 || (size_t)written >= out_path_size) {
+ out_path[0] = '\0';
+ return 0;
+ }
+
+ return 1;
+}
+
+int redump_resolve_dat_path(
+ const char *explicit_dir,
+ const char *executable_dir,
+ const char *basename,
+ char *out_path,
+ size_t out_path_size
+) {
+ char candidate[1024];
+
+ if (!basename || !basename[0] || !out_path || out_path_size == 0)
+ return 0;
+
+ out_path[0] = '\0';
+
+ if (explicit_dir && explicit_dir[0]) {
+ if (!redump_join_path(explicit_dir, NULL, basename,
+ out_path, out_path_size))
+ return 0;
+ return redump_path_exists(out_path);
+ }
+
+ if (executable_dir && executable_dir[0] &&
+ redump_join_path(executable_dir, "redump_dat", basename,
+ candidate, sizeof(candidate))) {
+ if (redump_path_exists(candidate)) {
+ snprintf(out_path, out_path_size, "%s", candidate);
+ return 1;
+ }
+
+ /* Retain the executable-relative path as the preferred diagnostic
+ * candidate if neither automatic location exists. */
+ snprintf(out_path, out_path_size, "%s", candidate);
+ }
+
+ if (redump_join_path(".", "redump_dat", basename,
+ candidate, sizeof(candidate))) {
+ if (redump_path_exists(candidate)) {
+ snprintf(out_path, out_path_size, "%s", candidate);
+ return 1;
+ }
+
+ if (!out_path[0])
+ snprintf(out_path, out_path_size, "%s", candidate);
+ }
+
+ return 0;
+}
+
static int redump_ascii_equal(const char *a, const char *b) {
unsigned char ca, cb;
if (!a || !b)