88802f3 |
Jamozed |
2020-09-26 00:40:39 |
0
|
// mkdir.c, version 1.0.4 |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
1
|
// OMKOV coreutils implementation of POSIX mkdir |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
2
|
// Copyright (C) 2020, Jakob Wakeling |
e2140ec |
Jamozed |
2022-03-06 15:27:45 |
3
|
// MIT Licence |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
4
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
5
|
/* |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
6
|
TODO Cleanup p flag handling |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
7
|
TODO Handle copying permissions |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
8
|
*/ |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
9
|
|
b181413 |
Jamozed |
2022-02-05 22:32:00 |
10
|
#include "util/error.h" |
b181413 |
Jamozed |
2022-02-05 22:32:00 |
11
|
#include "util/mode.h" |
b181413 |
Jamozed |
2022-02-05 22:32:00 |
12
|
#include "util/optget.h" |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
13
|
|
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
14
|
#include <sys/stat.h> |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
15
|
|
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
16
|
#include <errno.h> |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
17
|
#include <stdbool.h> |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
18
|
#include <stdio.h> |
bcc3fa8 |
Jamozed |
2020-11-13 00:11:41 |
19
|
#include <stdlib.h> |
76371b7 |
Jamozed |
2020-07-06 22:52:45 |
20
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
21
|
#define VERSION "1.0.4" |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
22
|
|
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
23
|
static struct lop lops[] = { |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
24
|
{ "help", ARG_NUL, 256 }, |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
25
|
{ "version", ARG_NUL, 257 }, |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
26
|
{ NULL, 0, 0 } |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
27
|
}; |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
28
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
29
|
static char *mopt; |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
30
|
static bool pflag; |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
31
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
32
|
static mode_t mask; |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
33
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
34
|
static inline int makedir(const char *path, chmod_t *m); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
35
|
|
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
36
|
static void hlp(void); |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
37
|
static void ver(void); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
38
|
|
76371b7 |
Jamozed |
2020-07-06 22:52:45 |
39
|
int main(int ac, char *av[]) { A0 = av[0]; |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
40
|
struct opt opt = OPTGET_INIT; opt.str = "m:p"; opt.lops = lops; |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
41
|
for (int o; (o = optget(&opt, av, 1)) != -1;) switch (o) { |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
42
|
case 'm': { mopt = opt.arg; break; } |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
43
|
case 'p': { pflag = true; break; } |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
44
|
case 256: { hlp(); return 0; } |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
45
|
case 257: { ver(); return 0; } |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
46
|
default: { return 1; } |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
47
|
} |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
48
|
|
76371b7 |
Jamozed |
2020-07-06 22:52:45 |
49
|
if (opt.ind == ac) { error(1, "missing operand"); } |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
50
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
51
|
chmod_t *m = NULL; if (mopt) { |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
52
|
mask = umask(0); m = strmode(mopt); |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
53
|
if (!m) { error(1, "%s: invalid mode", mopt); } |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
54
|
} |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
55
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
56
|
bool warned = false; |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
57
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
58
|
for (char **p = &av[opt.ind]; *p; ++p) { |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
59
|
if (pflag) { // Create directory hierarchy if p flag is set |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
60
|
char *q = *p; for (; *q == '/'; ++q) {} |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
61
|
for (; *q; ++q) { |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
62
|
if (*q != '/' || *(q + 1) == '/') { continue; } *q = 0; |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
63
|
if (mkdir(*p, (S_IWUSR | S_IXUSR | ~mask) & 0777) && |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
64
|
errno != EEXIST) { |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
65
|
warn("%s: %s", *p, serr()); continue; |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
66
|
} *q = '/'; |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
67
|
} |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
68
|
} |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
69
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
70
|
if (makedir(*p, m)) { warn("%s: %s", *p, serr()); warned = true; } |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
71
|
} |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
72
|
|
72364dd |
Jamozed |
2020-11-17 01:23:57 |
73
|
free(m); return warned; |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
74
|
} |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
75
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
76
|
/* Make directory with specified permissions */ |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
77
|
static inline int makedir(const char *path, chmod_t *m) { |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
78
|
// If no chmod is given, use default mode |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
79
|
if (!m) { if (mkdir(path, 0777)) { return 1; } return 0; } |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
80
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
81
|
// Create directory with no permissions |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
82
|
if (mkdir(path, 0)) { return 1; } mode_t mode = 0777; |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
83
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
84
|
// Handle each chmod_t |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
85
|
for (int i = 0;; ++i) switch (m[i].flag) { |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
86
|
case MF_NORM: case MF_XIFX: { |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
87
|
// If ref is null, use the file mode creation mask |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
88
|
if (!m[i].ref) { m[i].ref = M_ALL & ~mask; } |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
89
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
90
|
switch (m[i].op) { |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
91
|
case '+': { mode |= m[i].ref & m[i].mod; break; } |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
92
|
case '-': { mode &= (~(m[i].ref & m[i].mod) & 07777); break; } |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
93
|
case '=': { mode &= ~m[i].ref; mode |= m[i].ref & m[i].mod; break; } |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
94
|
} |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
95
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
96
|
// If the XIFX flag is set, set execute permission |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
97
|
if (m[i].flag == MF_XIFX) { mode |= m[i].ref & M_EX; } break; |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
98
|
} |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
99
|
case MF_COPY: { /* TODO */ } |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
100
|
case MF_NULL: { goto end; } |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
101
|
} end:; |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
102
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
103
|
// Set permissions of directory to the calculated mode |
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
104
|
if (chmod(path, mode)) { return 1; } return 0; |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
105
|
} |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
106
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
107
|
/* Print help information */ |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
108
|
static void hlp(void) { |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
109
|
puts("mkdir - make directories\n"); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
110
|
puts("usage: mkdir [-p] [-m mode] dir...\n"); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
111
|
puts("options:"); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
112
|
puts(" -p Create all parent directories as required"); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
113
|
puts(" -m mode Set the file mode of the created directory"); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
114
|
puts(" --help Display help information"); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
115
|
puts(" --version Display version information"); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
116
|
} |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
117
|
|
88802f3 |
Jamozed |
2020-09-26 00:40:39 |
118
|
/* Print version information */ |
30cf081 |
Jamozed |
2020-08-28 23:01:02 |
119
|
static void ver(void) { |
76371b7 |
Jamozed |
2020-07-06 22:52:45 |
120
|
puts("OMKOV coreutils mkdir, version " VERSION); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
121
|
puts("Copyright (C) 2020, Jakob Wakeling"); |
e2140ec |
Jamozed |
2022-03-06 15:27:45 |
122
|
puts("MIT Licence (https://opensource.org/licenses/MIT)"); |
d3522e7 |
Jamozed |
2020-06-26 18:42:30 |
123
|
} |
|
|
|
124
|
|