diff --git a/src/helpers.c b/src/helpers.c index 77a94fb..385d511 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -22,6 +22,24 @@ #include #include +#include "platforms.h" +#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \ + SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ + SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX +#include +#include +#include +#include +#include +#endif + +void simple_archiver_internal_free_c_string(char **str) { + if (str && *str) { + free(*str); + *str = NULL; + } +} + int simple_archiver_helper_is_big_endian(void) { union { uint32_t i; @@ -128,3 +146,48 @@ void simple_archiver_helper_cmd_string_argv_free_ptr(char ***argv_strs) { *argv_strs = NULL; } } + +int simple_archiver_helper_make_dirs(const char *file_path) { +#if SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_COSMOPOLITAN || \ + SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC || \ + SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX + __attribute__(( + cleanup(simple_archiver_internal_free_c_string))) char *path_dup = + strdup(file_path); + if (!path_dup) { + return 3; + } + const char *dir = dirname(path_dup); + if (strcmp(dir, "/") == 0 || strcmp(dir, ".") == 0) { + // At root. + return 0; + } + + int dir_fd = open(dir, O_RDONLY | O_DIRECTORY); + if (dir_fd == -1) { + if (errno == ENOTDIR) { + // Error, somehow got non-dir in path. + return 1; + } else { + // Directory does not exist. Check parent dir first. + int ret = simple_archiver_helper_make_dirs(dir); + if (ret != 0) { + return ret; + } + // Now make dir. + ret = mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + if (ret != 0) { + // Error. + return 2; + } + } + } else { + // Exists. + close(dir_fd); + } + + return 0; +#else + return 1; +#endif +} diff --git a/src/helpers.h b/src/helpers.h index 4643a76..809076c 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -43,4 +43,7 @@ char **simple_archiver_helper_cmd_string_to_argv(const char *cmd); void simple_archiver_helper_cmd_string_argv_free(char **argv_strs); void simple_archiver_helper_cmd_string_argv_free_ptr(char ***argv_strs); +/// Returns zero on success. +int simple_archiver_helper_make_dirs(const char *file_path); + #endif