Finalize mkdirp

This commit is contained in:
Nils O. Selåsdal
2015-01-30 20:50:50 +01:00
parent 7dbdec1d5b
commit a522c55155
+47 -27
View File
@@ -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);
} }