privacore-open-source-searc.../GbMakePath.cpp
2016-10-24 13:29:02 +02:00

82 lines
1.8 KiB
C++

#include "GbMakePath.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
int makePath(const char *path, int mode) {
//first check if the path already exist
struct stat st;
if(stat(path,&st)==0) {
if(S_ISDIR(st.st_mode))
return 0; //excellent
else {
errno = ENOTDIR;
return -1;
}
}
//loop over the components in the path, creating them if necessary
const char *path_end = path+strlen(path);
for(const char *component_start = path; component_start<path_end; ) {
const char *component_end = strchr(component_start+1,'/');
if(!component_end) {
component_end = component_start;
while(*component_end)
component_end++;
}
char buf[1024];
memcpy(buf, path, (size_t)(component_end-path));
buf[component_end-path] = '\0';
if(stat(buf,&st)==0) {
if(!S_ISDIR(st.st_mode)) {
errno = ENOTDIR;
return -1;
}
} else {
int rc = mkdir(buf, mode);
if(rc!=0)
return -1;
}
component_start = component_end;
if(*component_start=='/')
component_start++;
}
return 0;
}
#ifdef UNITTEST
#include <assert.h>
int main(void) {
rmdir("/tmp/GbMakePath/dir1/dir2");
rmdir("/tmp/GbMakePath/dir1");
rmdir("/tmp/GbMakePath");
assert(makePath("/tmp/GbMakePath/dir1/dir2",0777)==0);
assert(access("/tmp/GbMakePath/dir1/dir2",X_OK)==0);
rmdir("/tmp/GbMakePath/dir1/dir2");
rmdir("/tmp/GbMakePath/dir1");
rmdir("/tmp/GbMakePath");
assert(makePath("/tmp/GbMakePath//dir1//dir2",0777)==0);
assert(access("/tmp/GbMakePath/dir1/dir2",X_OK)==0);
rmdir("/tmp/GbMakePath/dir1/dir2");
rmdir("/tmp/GbMakePath/dir1");
rmdir("/tmp/GbMakePath");
assert(makePath("/tmp/GbMakePath/dir1/dir2",0777)==0);
assert(makePath("/tmp/GbMakePath/dir1/dir2",0777)==0);
assert(makePath("/tmp/GbMakePath/dir1",0777)==0);
assert(makePath("/proc/foobooblarg",0777)!=0);
return 0;
}
#endif