Unix Tools

Implementations of common Unix command-line utilities written in C.


unix-tools / mkdir.c

mkdir.c raw | download
1#define _POSIX_C_SOURCE 200809L
2#include <sys/stat.h>
3#include <unistd.h>
4#include <errno.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9static int
10makedir(const char *name, mode_t mode, int parents)
11{
12 struct stat st;
13 if (mkdir(name, mode) == 0) return 0;
14 if (parents && errno == EEXIST) {
15 if (stat(name, &st) < 0) { perror(name); return 1; }
16 if (S_ISDIR(st.st_mode)) return 0;
17 errno = ENOTDIR;
18 }
19 perror(name);
20 return 1;
21}
22
23static int
24mkdirp(char *name, mode_t mode, mode_t parent_mode)
25{
26 char *p;
27 if (!*name) { errno = ENOENT; perror(name); return 1; }
28 for (p = name + 1; *p; ++p) {
29 int status;
30 if (*p != '/' || p[-1] == '/') continue;
31 *p = '\0';
32 status = makedir(name, parent_mode, 1);
33 *p = '/';
34 if (status) return 1;
35 }
36 return makedir(name, mode, 1);
37}
38
39int
40main(int argc, char **argv)
41{
42 mode_t mode = 0777;
43 mode_t parent_mode = 0777;
44 int option, parents = 0, explicit_mode = 0, status = 0;
45 while ((option = getopt(argc, argv, "pm:")) != -1) {
46 if (option == 'p') parents = 1;
47 else if (option == 'm') {
48 char *end;
49 unsigned long n;
50 errno = 0;
51 n = strtoul(optarg, &end, 8);
52 if (errno || !*optarg || *end || optarg[0] == '-' || n > 0777) goto usage;
53 mode = (mode_t)n;
54 explicit_mode = 1;
55 } else goto usage;
56 }
57 if (optind == argc) goto usage;
58 if (explicit_mode) parent_mode = (0777 & ~umask(0)) | 0300;
59 for (; optind < argc; ++optind)
60 status |= parents ? mkdirp(argv[optind], mode, parent_mode) : makedir(argv[optind], mode, 0);
61 return status;
62usage:
63 fprintf(stderr, "usage: %s [-p] [-m mode] dir...\n", argv[0]);
64 return 1;
65}