Finalize mkdirp
This commit is contained in:
+47
-27
@@ -5,15 +5,40 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
static int uc_mkdir(const char *full_path, mode_t mode)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
int rc;
|
||||||
|
int created = 0;
|
||||||
|
|
||||||
|
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)
|
int uc_mkdir_p(const char *full_path, mode_t mode)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int rc = 0;
|
int rc;
|
||||||
char *path;
|
char *path;
|
||||||
char *p;
|
char *p;
|
||||||
|
int create_final = 1;
|
||||||
|
|
||||||
if (full_path == NULL || full_path[0] == 0) {
|
if (full_path == NULL || full_path[0] == 0) {
|
||||||
|
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -24,9 +49,8 @@ int uc_mkdir_p(const char *full_path, mode_t mode)
|
|||||||
errno = ENOTDIR;
|
errno = ENOTDIR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (st.st_mode != (mode | S_IFDIR) && chmod(full_path, mode) != 0) {
|
|
||||||
return -1;
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
path = strdup(full_path);
|
path = strdup(full_path);
|
||||||
@@ -46,34 +70,28 @@ int uc_mkdir_p(const char *full_path, mode_t mode)
|
|||||||
|
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
rc = stat(path, &st);
|
rc = uc_mkdir(path, mode);
|
||||||
if (rc != 0) { //doesn't exist
|
if (rc != 0) {
|
||||||
if (mkdir(path, mode) != 0) {
|
free(path);
|
||||||
free(path);
|
return -1;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else if (!S_ISDIR(st.st_mode)) {
|
|
||||||
errno = ENOTDIR;
|
|
||||||
free(path);
|
|
||||||
return -1;
|
|
||||||
} else { //dir already exist
|
|
||||||
|
|
||||||
if (st.st_mode != (mode | S_IFDIR) && chmod(path, mode) != 0) {
|
|
||||||
free(path);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//in case of multiple / , e.g. foo//bar
|
|
||||||
*p = '/';
|
*p = '/';
|
||||||
|
//in case of multiple / , e.g. foo//bar
|
||||||
for (; *p == '/'; p++)
|
for (; *p == '/'; p++)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
if (*p == 0) {
|
||||||
|
create_final = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//last part, in case full_path does not end with a /
|
//last part, in case full_path does not end with a /
|
||||||
rc = stat(path, &st);
|
if (create_final) {
|
||||||
if (rc != 0) {
|
rc = uc_mkdir(path, mode);
|
||||||
rc = mkdir(path, mode);
|
} else {
|
||||||
|
rc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(path);
|
free(path);
|
||||||
@@ -82,7 +100,9 @@ int uc_mkdir_p(const char *full_path, mode_t mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main()
|
||||||
{
|
{
|
||||||
uc_mkdir_p("a/b//c/d", 0777);
|
int rc = uc_mkdir_p("/tmp/a///", 0777);
|
||||||
|
printf("rc = %d\n", rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user