Recursive mkdir() system call on Unix Recursive mkdir() system call on Unix unix unix

Recursive mkdir() system call on Unix


There is not a system call to do it for you, unfortunately. I'm guessing that's because there isn't a way to have really well-defined semantics for what should happen in error cases. Should it leave the directories that have already been created? Delete them? What if the deletions fail? And so on...

It is pretty easy to roll your own, however, and a quick google for 'recursive mkdir' turned up a number of solutions. Here's one that was near the top:

http://nion.modprobe.de/blog/archives/357-Recursive-directory-creation.html

static void _mkdir(const char *dir) {    char tmp[256];    char *p = NULL;    size_t len;    snprintf(tmp, sizeof(tmp),"%s",dir);    len = strlen(tmp);    if (tmp[len - 1] == '/')        tmp[len - 1] = 0;    for (p = tmp + 1; *p; p++)        if (*p == '/') {            *p = 0;            mkdir(tmp, S_IRWXU);            *p = '/';        }    mkdir(tmp, S_IRWXU);}


hmm I thought that mkdir -p does that?

mkdir -p this/is/a/full/path/of/stuff


Here is my solution. By calling the function below you ensure that all dirs leading to the file path specified exist. Note that file_path argument is not directory name here but rather a path to a file that you are going to create after calling mkpath().

Eg., mkpath("/home/me/dir/subdir/file.dat", 0755) shall create /home/me/dir/subdir if it does not exist. mkpath("/home/me/dir/subdir/", 0755) does the same.

Works with relative paths as well.

Returns -1 and sets errno in case of an error.

int mkpath(char* file_path, mode_t mode) {    assert(file_path && *file_path);    for (char* p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) {        *p = '\0';        if (mkdir(file_path, mode) == -1) {            if (errno != EEXIST) {                *p = '/';                return -1;            }        }        *p = '/';    }    return 0;}

Note that file_path is modified during the action but gets restored afterwards. Therefore file_path is not strictly const.