137 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#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;
 | 
						|
}
 | 
						|
 |