user/mkdir.c
About this file
mkdir name ... creates one empty directory for each name: mkdir d makes d,
containing only the entries . (itself) and .. (its parent). The whole job is done by
one system call per name, mkdir, whose kernel side is sys_mkdir. That
calls create with type T_DIR, which allocates an inode, adds the .
and .. entries, and links the new directory into its parent, all inside one file
system transaction so a crash cannot leave a half-made directory.
Read before: user/cat.c (argument handling). Read next: user/rm.c and
user/ln.c, which have the same shape.
Headers
user/user.h declares mkdir; kernel/types.h must come first because
user.h uses its types. kernel/stat.h is not used.
At least one name is required
argv[0] is the program name, so argc < 2 means no directory was named.
The usage message goes to standard error and the program
exits with status 1 (exit status).
Create each directory, stopping at the first failure
For each name, the mkdir stub in user/usys.S traps into the kernel, which runs
sys_mkdir. It returns -1 if the name already exists (as anything: file,
directory or device), if the parent directory does not exist or has been removed, if
the parent already has the maximum number of links (NLINK_MAX), or if the
disk has no free inode.
On failure the program prints which name failed and breaks out of the loop, so the
names after it are not attempted. It then falls through to exit(0): the
exit status is 0 even though something failed. A script (or another program
checking wait’s status) could not tell. Unix mkdir reports the error, continues
with the remaining names and exits with a non-zero status.
Ask the kernel to create directory argv[i] (sys_mkdir →
create). The path may be relative to the current directory or absolute.
Name the directory that could not be created, on standard error.
Stop: the remaining names are skipped.
Exit with status 0, even after a failure.