util.c (2635B)
1 #include <errno.h> 2 #include <sys/stat.h> 3 4 int 5 normalizepath(const char *path, char **normal) 6 { 7 size_t len = strlen(path); 8 *normal = (char *)malloc((len + 1) * sizeof(char)); 9 const char *walk = path; 10 const char *match; 11 size_t newlen = 0; 12 13 while ((match = strchr(walk, '/'))) { 14 // Copy everything between match and walk 15 strncpy(*normal + newlen, walk, match - walk); 16 newlen += match - walk; 17 walk += match - walk; 18 19 // Skip all repeating slashes 20 while (*walk == '/') 21 walk++; 22 23 // If not last character in path 24 if (walk != path + len) 25 (*normal)[newlen++] = '/'; 26 } 27 28 (*normal)[newlen++] = '\0'; 29 30 // Copy remaining path 31 strcat(*normal, walk); 32 newlen += strlen(walk); 33 34 *normal = (char *)realloc(*normal, newlen * sizeof(char)); 35 36 return 0; 37 } 38 39 int 40 parentdir(const char *path, char **parent) 41 { 42 char *normal; 43 char *walk; 44 45 normalizepath(path, &normal); 46 47 // Pointer to last '/' 48 if (!(walk = strrchr(normal, '/'))) { 49 free(normal); 50 return -1; 51 } 52 53 // Get path up to last '/' 54 size_t len = walk - normal; 55 *parent = (char *)malloc((len + 1) * sizeof(char)); 56 57 // Copy path up to last '/' 58 strncpy(*parent, normal, len); 59 // Add null char 60 (*parent)[len] = '\0'; 61 62 free(normal); 63 64 return 0; 65 } 66 67 int 68 mkdirp(const char *path) 69 { 70 char *normal; 71 char *walk; 72 size_t normallen; 73 74 normalizepath(path, &normal); 75 normallen = strlen(normal); 76 walk = normal; 77 78 while (walk < normal + normallen + 1) { 79 // Get length from walk to next / 80 size_t n = strcspn(walk, "/"); 81 82 // Skip path / 83 if (n == 0) { 84 walk++; 85 continue; 86 } 87 88 // Length of current path segment 89 size_t curpathlen = walk - normal + n; 90 char curpath[curpathlen + 1]; 91 struct stat s; 92 93 // Copy path segment to stat 94 strncpy(curpath, normal, curpathlen); 95 strcpy(curpath + curpathlen, ""); 96 int res = stat(curpath, &s); 97 98 if (res < 0) { 99 if (errno == ENOENT) { 100 DEBUG("Making directory %s\n", curpath); 101 if (mkdir(curpath, 0700) < 0) { 102 fprintf(stderr, "Failed to make directory %s\n", curpath); 103 perror(""); 104 free(normal); 105 return -1; 106 } 107 } else { 108 fprintf(stderr, "Error statting directory %s\n", curpath); 109 perror(""); 110 free(normal); 111 return -1; 112 } 113 } 114 115 // Continue to next path segment 116 walk += n; 117 } 118 119 free(normal); 120 121 return 0; 122 } 123 124 int 125 nullterminate(char **str, size_t *len) 126 { 127 if ((*str)[*len - 1] == '\0') 128 return 0; 129 130 (*len)++; 131 *str = (char*)realloc(*str, *len * sizeof(char)); 132 (*str)[*len - 1] = '\0'; 133 134 return 0; 135 } 136