Another copy of my dotfiles. Because I don't completely trust GitHub.
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.

135 lines
2.6 KiB

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