diff options
author | Denis Kenzior <denkenz@gmail.com> | 2024-01-29 11:13:39 -0600 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2024-01-29 11:19:57 -0600 |
commit | e859d6f5b9defb9ed130afd7c502d127daf3933e (patch) | |
tree | 48485a52987eea64b5d6635c139fe4b050a36d77 | |
parent | 4e00818e5a1db9a8368e573b683f49855d54dc4a (diff) |
dir: Add l_dir_create
-rw-r--r-- | ell/dir.c | 52 | ||||
-rw-r--r-- | ell/dir.h | 2 | ||||
-rw-r--r-- | ell/ell.sym | 1 |
3 files changed, 55 insertions, 0 deletions
@@ -15,8 +15,10 @@ #include <limits.h> #include <sys/inotify.h> #include <errno.h> +#include <sys/stat.h> #include "private.h" +#include "useful.h" #include "queue.h" #include "io.h" #include "dir.h" @@ -336,3 +338,53 @@ done: l_free(watch); } + +/** + * l_dir_create: + * @abspath: Absolute path of the directory to create + * + * Attempts to create a directory tree given by @abspath. @abspath must be + * an absolute path. + * + * Returns: 0 if successful, a negative errno otherwise + **/ +LIB_EXPORT int l_dir_create(const char *abspath) +{ + static const mode_t create_mode = S_IRUSR | S_IWUSR | S_IXUSR; + struct stat st; + _auto_(l_free) char *dir = NULL; + const char *prev, *next; + int err; + + if (!abspath || abspath[0] != '/') + return -EINVAL; + + err = stat(abspath, &st); + if (!err) { + /* File exists */ + if (S_ISDIR(st.st_mode)) + return 0; + + return -ENOTDIR; + } + + if (errno != ENOENT) + return -errno; + + dir = l_malloc(strlen(abspath) + 1); + dir[0] = '\0'; + + for (prev = abspath; prev[0] && (next = strchrnul(prev + 1, '/')); + prev = next) { + /* Skip consecutive '/' characters */ + if (next - prev == 1) + continue; + + strncat(dir, prev, next - prev); + + if (mkdir(dir, create_mode) == -1 && errno != EEXIST) + return -errno; + } + + return 0; +} @@ -33,6 +33,8 @@ struct l_dir_watch *l_dir_watch_new(const char *pathname, l_dir_watch_destroy_func_t destroy); void l_dir_watch_destroy(struct l_dir_watch *watch); +int l_dir_create(const char *abspath); + #ifdef __cplusplus } #endif diff --git a/ell/ell.sym b/ell/ell.sym index e12fd0e8..17acd406 100644 --- a/ell/ell.sym +++ b/ell/ell.sym @@ -307,6 +307,7 @@ global: l_dhcp6_lease_get_preferred_lifetime; l_dhcp6_lease_get_start_time; /* dir */ + l_dir_create; l_dir_watch_new; l_dir_watch_destroy; /* file */ |