You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
2.6 KiB
136 lines
2.6 KiB
#include <errno.h> |
|
#include <sys/stat.h> |
|
|
|
int |
|
normalizepath(const char *path, char **normal) |
|
{ |
|
size_t len = strlen(path); |
|
*normal = (char *)malloc((len + 1) * sizeof(char)); |
|
const char *walk = path; |
|
const char *match; |
|
size_t newlen = 0; |
|
|
|
while ((match = strchr(walk, '/'))) { |
|
// Copy everything between match and walk |
|
strncpy(*normal + newlen, walk, match - walk); |
|
newlen += match - walk; |
|
walk += match - walk; |
|
|
|
// Skip all repeating slashes |
|
while (*walk == '/') |
|
walk++; |
|
|
|
// If not last character in path |
|
if (walk != path + len) |
|
(*normal)[newlen++] = '/'; |
|
} |
|
|
|
(*normal)[newlen++] = '\0'; |
|
|
|
// Copy remaining path |
|
strcat(*normal, walk); |
|
newlen += strlen(walk); |
|
|
|
*normal = (char *)realloc(*normal, newlen * sizeof(char)); |
|
|
|
return 0; |
|
} |
|
|
|
int |
|
parentdir(const char *path, char **parent) |
|
{ |
|
char *normal; |
|
char *walk; |
|
|
|
normalizepath(path, &normal); |
|
|
|
// Pointer to last '/' |
|
if (!(walk = strrchr(normal, '/'))) { |
|
free(normal); |
|
return -1; |
|
} |
|
|
|
// Get path up to last '/' |
|
size_t len = walk - normal; |
|
*parent = (char *)malloc((len + 1) * sizeof(char)); |
|
|
|
// Copy path up to last '/' |
|
strncpy(*parent, normal, len); |
|
// Add null char |
|
(*parent)[len] = '\0'; |
|
|
|
free(normal); |
|
|
|
return 0; |
|
} |
|
|
|
int |
|
mkdirp(const char *path) |
|
{ |
|
char *normal; |
|
char *walk; |
|
size_t normallen; |
|
|
|
normalizepath(path, &normal); |
|
normallen = strlen(normal); |
|
walk = normal; |
|
|
|
while (walk < normal + normallen + 1) { |
|
// Get length from walk to next / |
|
size_t n = strcspn(walk, "/"); |
|
|
|
// Skip path / |
|
if (n == 0) { |
|
walk++; |
|
continue; |
|
} |
|
|
|
// Length of current path segment |
|
size_t curpathlen = walk - normal + n; |
|
char curpath[curpathlen + 1]; |
|
struct stat s; |
|
|
|
// Copy path segment to stat |
|
strncpy(curpath, normal, curpathlen); |
|
strcpy(curpath + curpathlen, ""); |
|
int res = stat(curpath, &s); |
|
|
|
if (res < 0) { |
|
if (errno == ENOENT) { |
|
DEBUG("Making directory %s\n", curpath); |
|
if (mkdir(curpath, 0700) < 0) { |
|
fprintf(stderr, "Failed to make directory %s\n", curpath); |
|
perror(""); |
|
free(normal); |
|
return -1; |
|
} |
|
} else { |
|
fprintf(stderr, "Error statting directory %s\n", curpath); |
|
perror(""); |
|
free(normal); |
|
return -1; |
|
} |
|
} |
|
|
|
// Continue to next path segment |
|
walk += n; |
|
} |
|
|
|
free(normal); |
|
|
|
return 0; |
|
} |
|
|
|
int |
|
nullterminate(char **str, size_t *len) |
|
{ |
|
if ((*str)[*len - 1] == '\0') |
|
return 0; |
|
|
|
(*len)++; |
|
*str = (char*)realloc(*str, *len * sizeof(char)); |
|
(*str)[*len - 1] = '\0'; |
|
|
|
return 0; |
|
} |
|
|
|
|