From de40fa5ef688dfa9a2b86c5207a17a0bb421fec4 Mon Sep 17 00:00:00 2001 From: Thorsten Kukuk Date: Wed, 4 Dec 2024 15:56:06 +0100 Subject: [PATCH] Make mkdir_p more robust --- lib/sqlite.c | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/lib/sqlite.c b/lib/sqlite.c index e39701b..1b89085 100644 --- a/lib/sqlite.c +++ b/lib/sqlite.c @@ -42,20 +42,50 @@ /* Begin - local helper functions */ -static void -mkdir_p(const char *pathname, mode_t mode) +static int +mkdir_p(const char *path, mode_t mode) { - if (mkdir(pathname, mode) == 0 || errno == EEXIST || errno != ENOENT) - return; + if (path == NULL) + return -EINVAL; + + if (mkdir(path, mode) == 0) + return 0; + + if (errno == EEXIST) + { + struct stat st; + + /* Check if the existing path is a directory */ + if (stat(path, &st) != 0) + return -errno; + + /* If not, fail with ENOTDIR */ + if (!S_ISDIR(st.st_mode)) + return -ENOTDIR; - char *buf = strdup(pathname); - mkdir_p(dirname(buf), mode); + /* if it is a directory, return */ + return 0; + } + + /* If it fails for any reason but ENOENT, fail */ + if (errno != ENOENT) + return -errno; + + char *buf = strdup(path); + if (buf == NULL) + return -ENOMEM; + + int r = mkdir_p(dirname(buf), mode); free(buf); + /* if we couldn't create the parent, fail, too */ + if (r < 0) + return r; - mkdir(pathname, mode); + return mkdir(path, mode); } -static void strip_extension(char *in_str) +static void +strip_extension(char *in_str) { static const int name_min_len = 1; static const int max_ext_len = 4;