Skip to content

Commit

Permalink
zsv_mkdirs: do not abort on intermediate-dir existence error on mkdir…
Browse files Browse the repository at this point in the history
…() (#363)

* zsv_mkdirs: do not abort on failure to find existence of or create intermediate dir
* app/utils/dirs.c: minor updates to comment and ZSV_NO_JQ conditional build
  • Loading branch information
liquidaty authored Feb 17, 2025
1 parent a5691ce commit 152a421
Showing 1 changed file with 39 additions and 10 deletions.
49 changes: 39 additions & 10 deletions app/utils/dirs.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@
#include <dirent.h>
#include <errno.h>
#include <zsv/utils/os.h>
#ifndef ZSV_NO_JQ
#include <zsv/utils/json.h>
#include <zsv/utils/jq.h>
#endif
#include <zsv/utils/dirs.h>
#include <zsv/utils/string.h>
#include <unistd.h> // unlink
#include <sys/stat.h>
#ifndef ZSV_NO_JQ
#include <yajl_helper/yajl_helper.h>
#endif

#if defined(_WIN32)
#include <windows.h>
Expand Down Expand Up @@ -75,6 +79,8 @@ size_t zsv_get_config_dir(char *buff, size_t buffsize, const char *prefix) {
* return true (non-zero) or false (zero)
*/
int zsv_dir_exists(const char *path) {
// TO DO: support win long filepath prefix
// TO DO: work properly if dir exists but we don't have permission
struct stat path_stat;
if (!stat(path, &path_stat))
return S_ISDIR(path_stat.st_mode);
Expand All @@ -86,14 +92,27 @@ int zsv_dir_exists(const char *path) {
* return zero on success
*/
int zsv_mkdirs(const char *path, char path_is_filename) {
char *p = NULL;
int rc = 0;

if (!path || !*path)
return -1;
size_t len = strlen(path);

#ifdef WIN32
// TO DO: handle windows long-file prefix "\\?\"
// for now, explicitly do not handle
if (len > 2 && path[2] == '?')
fprintf(stderr, "Invalid path (long file prefix not supported): %s\n", path);
#endif

if (len < 1 || len > FILENAME_MAX)
return -1;

char *tmp = strdup(path);
if (!tmp) {
perror(path);
return -1;
}

if (len && strchr("/\\", tmp[len - 1]))
tmp[--len] = 0;

Expand All @@ -113,6 +132,7 @@ int zsv_mkdirs(const char *path, char path_is_filename) {
offset = path_end - tmp;
else {
fprintf(stderr, "Invalid path: %s\n", path);
free(tmp);
return -1;
}
}
Expand All @@ -124,7 +144,10 @@ int zsv_mkdirs(const char *path, char path_is_filename) {
offset = 1;
#endif

for (p = tmp + offset; !rc && *p; p++)
// TO DO: first find the longest subdir that exists, in *reverse* order so as
// to properly handle case where no access to intermediate dir,
// and then only start mkdir from there
for (char *p = tmp + offset; !rc && *p; p++) {
if (strchr("/\\", *p)) {
char tmp_c = p[1];
p[0] = FILESLASH;
Expand All @@ -136,21 +159,27 @@ int zsv_mkdirs(const char *path, char path_is_filename) {
S_IRWXU
#endif
)) {
rc = -1;
fprintf(stderr, "Error creating directory: ");
perror(tmp);
} else
p[1] = tmp_c;
if (errno != EEXIST) { // errno could be EEXIST if we have no permissions to an intermediate directory
perror(tmp);
rc = -1;
}
}
p[1] = tmp_c;
}
}

if (!rc && path_is_filename == 0 && *tmp && !zsv_dir_exists(tmp) &&
mkdir(tmp
#ifndef WIN32
,
S_IRWXU
#endif
))
rc = -1;
)) {
if (errno != EEXIST) {
perror(tmp);
rc = -1;
}
}

free(tmp);
return rc;
Expand Down

0 comments on commit 152a421

Please sign in to comment.