#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
+) {
+ const char *environment_dir;
+ char candidate[1024];
+
+ if (!basename || !basename[0] || !out_path || out_path_size == 0)
+ return 0;
+
+ out_path[0] = '\0';
+
+ /* An explicit CLI directory is authoritative. Do not silently fall back
+ * when the operator supplied a path, because that would make evidence
+ * provenance ambiguous. */
+ 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);
+ }
+
+ /* Environment override is useful for packaged and read-only installs.
+ * Like the CLI override, it is authoritative when set. */
+ environment_dir = getenv("FRIIDUMP_REDUMP_DAT_DIR");
+ if (environment_dir && environment_dir[0]) {
+ if (!redump_join_path(environment_dir, NULL, basename,
+ out_path, out_path_size))
+ return 0;
+ return redump_path_exists(out_path);
+ }
+
+ /* Portable/source-build layout: DAT directory beside the executable. */
+ 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;
+ }
+ snprintf(out_path, out_path_size, "%s", candidate);
+ }
+
+ /* Installed Unix layout: <prefix>/bin/friidump with data under
+ * <prefix>/share/friidump/redump_dat. */
+ if (executable_dir && executable_dir[0] &&
+ redump_join_path(executable_dir, "../share/friidump/redump_dat",
+ basename, candidate, sizeof(candidate))) {
+ if (redump_path_exists(candidate)) {
+ snprintf(out_path, out_path_size, "%s", candidate);
+ return 1;
+ }
+ }
+
+ /* Development convenience for direct source-tree execution. */
+ 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)