Skip to content

Instantly share code, notes, and snippets.

@ChisholmKyle
Last active December 5, 2022 09:13
Show Gist options
  • Save ChisholmKyle/0cbedcd3e64132243a39 to your computer and use it in GitHub Desktop.
Save ChisholmKyle/0cbedcd3e64132243a39 to your computer and use it in GitHub Desktop.
Simple recursive mkdir in C
/* recursive mkdir based on
http://nion.modprobe.de/blog/archives/357-Recursive-directory-creation.html
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#define PATH_MAX_STRING_SIZE 256
/* recursive mkdir */
int mkdir_p(const char *dir, const mode_t mode) {
char tmp[PATH_MAX_STRING_SIZE];
char *p = NULL;
struct stat sb;
size_t len;
/* copy path */
len = strnlen (dir, PATH_MAX_STRING_SIZE);
if (len == 0 || len == PATH_MAX_STRING_SIZE) {
return -1;
}
memcpy (tmp, dir, len);
tmp[len] = '\0';
/* remove trailing slash */
if(tmp[len - 1] == '/') {
tmp[len - 1] = '\0';
}
/* check if path exists and is a directory */
if (stat (tmp, &sb) == 0) {
if (S_ISDIR (sb.st_mode)) {
return 0;
}
}
/* recursive mkdir */
for(p = tmp + 1; *p; p++) {
if(*p == '/') {
*p = 0;
/* test path */
if (stat(tmp, &sb) != 0) {
/* path does not exist - create directory */
if (mkdir(tmp, mode) < 0) {
return -1;
}
} else if (!S_ISDIR(sb.st_mode)) {
/* not a directory */
return -1;
}
*p = '/';
}
}
/* test path */
if (stat(tmp, &sb) != 0) {
/* path does not exist - create directory */
if (mkdir(tmp, mode) < 0) {
return -1;
}
} else if (!S_ISDIR(sb.st_mode)) {
/* not a directory */
return -1;
}
return 0;
}
@kext
Copy link

kext commented Feb 10, 2017

Line 20 must be

len = strlen(dir);

Otherwise the comparison is pointless and if strlen(dir) >= sizeof(tmp) then tmp will not be zero terminated so you can not use strlen on it.

Also you need to include unistd.h in addition to sys/types.h and sys/stat.h for stat.
On the other hand stdio.h is not needed.

@ChisholmKyle
Copy link
Author

Thanks @kext for the feedback (I only just noticed it today haha). Anyways, I fixed the bug and replaced strncpy with strnlen and memcpy so it doesn't needlessly pad the tmp array.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment