1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
# mkdir — Make Directories
## Overview
`mkdir` creates directories with specified permissions. It shares the
`mode_compile()` / `mode_apply()` engine with `chmod` for parsing
symbolic and numeric mode specifications. With `-p`, it creates all
missing intermediate directories.
**Source**: `mkdir/mkdir.c`, `mkdir/mode.c`, `mkdir/mode.h` (shared with chmod)
**Origin**: BSD 4.4, University of California, Berkeley
**License**: BSD-3-Clause
## Synopsis
```
mkdir [-pv] [-m mode] directory ...
```
## Options
| Flag | Description |
|------|-------------|
| `-m mode` | Set permissions (numeric or symbolic) |
| `-p` | Create parent directories as needed |
| `-v` | Print each directory as it is created |
## Source Analysis
### Functions
| Function | Purpose |
|----------|---------|
| `main()` | Parse options and iterate over arguments |
| `create_single_path()` | Create one directory (no `-p`) |
| `create_parents_path()` | Create directory with parents (`-p`) |
| `create_component()` | Create a single path component |
| `mkdir_with_umask()` | Atomically apply umask during `mkdir(2)` |
| `existing_directory()` | Check if a path already exists as a directory |
| `current_umask()` | Atomically read the current umask |
| `mode_compile()` | Parse mode string to command array (shared) |
| `mode_apply()` | Apply compiled mode to existing permissions |
### Simple Creation
```c
static int
create_single_path(const char *path, mode_t mode)
{
if (mkdir(path, mode) < 0) {
error_errno("cannot create directory '%s'", path);
return 1;
}
/* If explicit mode was specified, chmod to override umask */
if (explicit_mode) {
if (chmod(path, mode) < 0) {
error_errno("cannot set permissions on '%s'", path);
return 1;
}
}
if (verbose)
printf("mkdir: created directory '%s'\n", path);
return 0;
}
```
### Parent Directory Creation
```c
static int
create_parents_path(const char *path, mode_t mode,
mode_t intermediate_mode)
{
char *buf = strdup(path);
char *p = buf;
/* Skip leading slashes */
while (*p == '/') p++;
/* Create each component */
while (*p) {
char *slash = strchr(p, '/');
if (slash) *slash = '\0';
if (!existing_directory(buf)) {
if (mkdir_with_umask(buf, intermediate_mode) < 0) {
if (errno != EEXIST) {
error_errno("cannot create '%s'", buf);
return 1;
}
}
if (verbose)
printf("mkdir: created directory '%s'\n", buf);
}
if (slash) {
*slash = '/';
p = slash + 1;
} else {
break;
}
}
/* Apply final mode to the leaf directory */
if (chmod(buf, mode) < 0) { ... }
return 0;
}
```
### Atomic Umask Handling
To prevent race conditions when setting permissions:
```c
static mode_t
current_umask(void)
{
/* Atomically read umask by setting and restoring */
mode_t mask = umask(0);
umask(mask);
return mask;
}
static int
mkdir_with_umask(const char *path, mode_t mode)
{
/* Use more restrictive intermediate perms:
* u+wx so the creator can write subdirs */
mode_t old = umask(0);
int ret = mkdir(path, mode);
umask(old);
return ret;
}
```
Intermediate directories are created with `0300 | mode` to ensure the
creating user always has write and execute access to create children,
even if the specified mode is more restrictive.
### Mode Compilation (Shared with chmod)
```c
/* Numeric modes */
mkdir -m 755 mydir
/* → mode_compile("755") returns compiled bitcmd array */
/* Symbolic modes */
mkdir -m u=rwx,g=rx,o=rx mydir
/* → mode_compile("u=rwx,g=rx,o=rx") */
/* Default mode */
/* 0777 & ~umask (typically 0755) */
```
## System Calls Used
| Syscall | Purpose |
|---------|---------|
| `mkdir(2)` | Create directory |
| `chmod(2)` | Set final permissions |
| `umask(2)` | Read/set file creation mask |
| `stat(2)` | Check if path exists |
## Examples
```sh
# Simple directory
mkdir mydir
# With specific permissions
mkdir -m 700 private_dir
# Create parent directories
mkdir -p /opt/myapp/lib/plugins
# Verbose
mkdir -pv a/b/c
# mkdir: created directory 'a'
# mkdir: created directory 'a/b'
# mkdir: created directory 'a/b/c'
# Symbolic mode
mkdir -m u=rwx,g=rx,o= restricted_dir
```
## Exit Codes
| Code | Meaning |
|------|---------|
| 0 | All directories created successfully |
| 1 | Error creating one or more directories |
|