A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
The POSIX mkdir function creates a single directory. It lives in sys/stat.h and sys/types.h, not in the C standard library. That means it is not portable to Windows without a compatibility shim. It takes two arguments: the path and a mode bitmask that sets permissions. The mode is filtered through the process umask, so the permissions you request are not always the permissions you get. This surprises people who set 0777 and wonder why the directory ends up as 0755.
#include <stdio.h>#include <sys/stat.h>#include <sys/types.h>#include <errno.h>#include <string.h>int main(void) {const char *dir = "output_data";int result = mkdir(dir, 0755);if (result == 0) {printf("Created directory: %s\n", dir);} else if (errno == EEXIST) {printf("Directory already exists: %s\n", dir);} else {printf("mkdir failed: %s\n", strerror(errno));return 1;}return 0;}
The permissions show drwxr-xr-x, which is 0755. We requested 0755 and the umask did not strip anything because the default umask is typically 0022. If the umask were 0077, the result would be 0700 regardless of what we passed. The formula is: actual_permissions = requested_mode & ~umask. You can check your umask by running umask in a shell.
Calling mkdir("a/b/c", 0755) fails if a/b does not already exist. There is no recursive flag. You get ENOENT. If you need mkdir -p behavior, you must walk the path component by component, creating each level and ignoring EEXIST errors. This is a common utility function in C projects.
#include <stdio.h>#include <sys/stat.h>#include <errno.h>#include <string.h>int mkdir_recursive(const char *path, mode_t mode) {char tmp[256];strncpy(tmp, path, sizeof(tmp) - 1);tmp[sizeof(tmp) - 1] = '\0';for (char *p = tmp + 1; *p; p++) {if (*p == '/') {*p = '\0';if (mkdir(tmp, mode) != 0 && errno != EEXIST) {return -1;}*p = '/';}}if (mkdir(tmp, mode) != 0 && errno != EEXIST) {return -1;}return 0;}int main(void) {if (mkdir_recursive("data/reports/2026/august", 0755) == 0) {printf("Nested directories created.\n");} else {perror("mkdir_recursive");}return 0;}
mkdir is a POSIX function, not standard C. On Windows, the equivalent is _mkdir from direct.h, which takes only a path and no mode argument. We cover that in the next lesson. For cross-platform code, you will need an #ifdef guard or a portability wrapper. Next: the Windows variant.
Finish the lesson once you have worked through the material. This awards ★ 20 XP.