Awhile back I wrote a function to recursively create directories in C. It used a string builder to split the parts and rebuild the path.
The way mkdir works is by taking a single directory that does not exist and creates it.
If there are multiple path parts that don’t exit it will error. Hence needing to split
the string into parts and create each part of the path separately. Earlier parts of the
path must exist before trying to add a later part.
For a project I was working on I needed to recursively make directories but I wasn’t able to utilize the string builder. So I wrote a version without it.
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
# include <Windows.h>
#else
# include <sys/stat.h>
#endif
#ifdef _WIN32
const char SEP = '\\';
#else
const char SEP = '/';
#endif
bool recurse_mkdir(const char *dirname)
{
const char *p;
char *temp;
bool ret = true;
temp = calloc(1, strlen(dirname)+1);
/* Skip Windows drive letter. */
#ifdef _WIN32
if ((p = strchr(dirname, ':') != NULL) {
p++;
} else {
#endif
p = dirname;
#ifdef _WIN32
}
#endif
while ((p = strchr(p, SEP)) != NULL) {
/* Skip empty elements. Could be a Windows UNC path or
just multiple separators which is okay. */
if (p != dirname && *(p-1) == SEP) {
p++;
continue;
}
/* Put the path up to this point into a temporary to
pass to the make directory function. */
memcpy(temp, dirname, p-dirname);
temp[p-dirname] = '\0';
p++;
#ifdef _WIN32
if (CreateDirectory(temp, NULL) == FALSE) {
if (GetLastError() != ERROR_ALREADY_EXISTS) {
ret = false;
break;
}
}
#else
if (mkdir(temp, 0774) != 0) {
if (errno != EEXIST) {
ret = false;
break;
}
}
#endif
}
free(temp);
return ret;
}
This version is similar but uses strchr to search for parts and a memcpy to a temporary
buffer to hold the path segment. The temporary is necessary because CreateDirectory
and mkdir take NULL terminated string, so we can’t pass a sub string directly.
Just like the previous version it will continue processing if it encounters a
directory that already exists. Also, it only returns false on error so the caller
needs to check GetLastError or errno themselves if they want a detailed reason.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.