#include #include #include #include #include #include static int uc_mkdir(const char *full_path, mode_t mode) { struct stat st; int rc; rc = stat(full_path, &st); if (rc == -1 && errno == ENOENT) { rc = mkdir(full_path, mode); if (rc == -1 && errno != EEXIST) { return -1; } } else if (rc == 0) { if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; return -1; } } else { return -1; } return 0; } int uc_mkdir_p(const char *full_path, mode_t mode) { struct stat st; int rc; char *path; char *p; int create_final = 1; if (full_path == NULL || full_path[0] == 0) { errno = EINVAL; return -1; } rc = stat(full_path, &st); if (rc == 0) { //already exists if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; return -1; } return 0; } path = strdup(full_path); if (path == NULL) { return -1; } //skip leading / for (p = path; *p == '/'; p++) ; for (;;) { p = strchr(p, '/'); if (p == NULL) { break; } *p = 0; rc = uc_mkdir(path, mode); if (rc != 0) { free(path); return -1; } *p = '/'; //in case of multiple / , e.g. foo//bar for (; *p == '/'; p++) ; if (*p == 0) { create_final = 0; break; } } //last part, in case full_path does not end with a / if (create_final) { rc = uc_mkdir(path, mode); } else { rc = 0; } free(path); return rc; }