X-Git-Url: https://git.jtryba.com/browse/friidump.git/blobdiff_plain/6e43cd3fd4f7324a177331a01d653b4c19c4bca7..refs/heads/main:/src/redump_dat.c?ds=sidebyside diff --git a/src/redump_dat.c b/src/redump_dat.c index 6231679..d2aba7c 100644 --- a/src/redump_dat.c +++ b/src/redump_dat.c @@ -5,6 +5,116 @@ #include #include +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: /bin/friidump with data under + * /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)