From d26fad4619f9d68bf6c3c0163a45e48787ba43f7 Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Thu, 17 Nov 2022 22:57:29 +0000 Subject: [PATCH] Add UtilMkdir() to recursively make directories --- src/Db.c | 24 ++++++++++++---- src/Util.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++ src/include/Db.h | 2 +- src/include/Util.h | 3 ++ 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/src/Db.c b/src/Db.c index 173ed97..48c92df 100644 --- a/src/Db.c +++ b/src/Db.c @@ -255,11 +255,23 @@ DbCreate(Db * db, char *prefix, char *key) file = DbFileName(db, prefix, key); - if (UtilLastModified(file)) + if (UtilLastModified(file) || UtilMkdir(prefix, 0750) < 0) + { + Free(file); + return NULL; + } + + fp = fopen(file, "w"); + Free(file); + if (!fp) { return NULL; } + fprintf(fp, "{}"); + fflush(fp); + fclose(fp); + return DbLock(db, prefix, key); } @@ -380,7 +392,7 @@ finish: return ref; } -void +int DbUnlock(Db * db, DbRef * ref) { FILE *fp; @@ -388,7 +400,7 @@ DbUnlock(Db * db, DbRef * ref) if (!db || !ref) { - return; + return 0; } pthread_mutex_lock(&db->lock); @@ -396,8 +408,8 @@ DbUnlock(Db * db, DbRef * ref) file = DbFileName(db, ref->prefix, ref->key); fp = fopen(file, "w"); if (!fp) - { /* TODO: This seems dangerous */ - return; + { + return 0; } JsonEncode(ref->json, fp); @@ -415,6 +427,8 @@ DbUnlock(Db * db, DbRef * ref) pthread_mutex_destroy(&ref->lock); Free(ref); } + + return 1; } HashMap * diff --git a/src/Util.c b/src/Util.c index 3b10a17..ab98bf9 100644 --- a/src/Util.c +++ b/src/Util.c @@ -66,6 +66,77 @@ UtilLastModified(char *path) } } +int +UtilMkdir(const char *dir, const mode_t mode) +{ + char tmp[PATH_MAX]; + char *p = NULL; + + struct stat st; + + size_t len; + + len = strnlen(dir, PATH_MAX); + if (!len || len == PATH_MAX) + { + errno = ENAMETOOLONG; + return -1; + } + + memcpy(tmp, dir, len); + tmp[len] = '\0'; + + if (tmp[len - 1] == '/') + { + tmp[len - 1] = '\0'; + } + + if (stat(tmp, &st) == 0 && S_ISDIR(st.st_mode)) + { + return 0; + } + + for (p = tmp + 1; *p; p++) + { + if (*p == '/') + { + *p = 0; + + if (stat(tmp, &st) != 0) + { + if (mkdir(tmp, mode) < 0) + { + /* errno already set by mkdir() */ + return -1; + } + } + else if (!S_ISDIR(st.st_mode)) + { + errno = ENOTDIR; + return -1; + } + + *p = '/'; + } + } + + if (stat(tmp, &st) != 0) + { + if (mkdir(tmp, mode) < 0) + { + /* errno already set by mkdir() */ + return -1; + } + } + else if (!S_ISDIR(st.st_mode)) + { + errno = ENOTDIR; + return -1; + } + + return 0; +} + char * UtilUtf8Encode(unsigned long utf8) { diff --git a/src/include/Db.h b/src/include/Db.h index 97a72bf..9d43813 100644 --- a/src/include/Db.h +++ b/src/include/Db.h @@ -43,7 +43,7 @@ extern DbRef * extern DbRef * DbLock(Db *, char *, char *); -extern void +extern int DbUnlock(Db *, DbRef *); extern HashMap * diff --git a/src/include/Util.h b/src/include/Util.h index 8237940..7ec97eb 100644 --- a/src/include/Util.h +++ b/src/include/Util.h @@ -60,6 +60,9 @@ extern unsigned long extern unsigned long UtilLastModified(char *); +extern int + UtilMkdir(const char *, const mode_t); + /* * Encode a single UTF-8 codepoint as a string buffer containing * between 1 and 4 bytes. The string buffer is allocated on the heap,