]> FriiDump Source - friidump.git/blobdiff - src/redump_dat.c
FriiDump 0.5.3.16 candidate: add native reports and Linux Xbox support
[friidump.git] / src / redump_dat.c
index 6231679b06a0964c0928c3c6e170770092881037..d2aba7c2ca7a1619052a343ba0bd5f0939c2b500 100644 (file)
@@ -5,6 +5,116 @@
 #include <stdlib.h>
 #include <string.h>
 
 #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)
 static int redump_ascii_equal(const char *a, const char *b) {
     unsigned char ca, cb;
     if (!a || !b)