Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libcmd/mkdir.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1992-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* *
20
***********************************************************************/
21
#pragma prototyped
22
/*
23
* David Korn
24
* AT&T Bell Laboratories
25
*
26
* mkdir
27
*/
28
29
static const char usage[] =
30
"[-?\n@(#)$Id: mkdir (AT&T Research) 2010-04-08 $\n]"
31
USAGE_LICENSE
32
"[+NAME?mkdir - make directories]"
33
"[+DESCRIPTION?\bmkdir\b creates one or more directories. By "
34
"default, the mode of created directories is \ba=rwx\b minus the "
35
"bits set in the \bumask\b(1).]"
36
"[m:mode]:[mode?Set the mode of created directories to \amode\a. "
37
"\amode\a is symbolic or octal mode as in \bchmod\b(1). Relative "
38
"modes assume an initial mode of \ba=rwx\b.]"
39
"[p:parents?Create any missing intermediate pathname components. For "
40
"each dir operand that does not name an existing directory, effects "
41
"equivalent to those caused by the following command shall occur: "
42
"\vmkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode]] "
43
"dir\v where the \b-m\b mode option represents that option supplied to "
44
"the original invocation of \bmkdir\b, if any. Each dir operand that "
45
"names an existing directory shall be ignored without error.]"
46
"[v:verbose?Print a message on the standard error for each created "
47
"directory.]"
48
"\n"
49
"\ndirectory ...\n"
50
"\n"
51
"[+EXIT STATUS?]{"
52
"[+0?All directories created successfully, or the \b-p\b option "
53
"was specified and all the specified directories now exist.]"
54
"[+>0?An error occurred.]"
55
"}"
56
"[+SEE ALSO?\bchmod\b(1), \brmdir\b(1), \bumask\b(1)]"
57
;
58
59
#include <cmd.h>
60
#include <ls.h>
61
62
#define DIRMODE (S_IRWXU|S_IRWXG|S_IRWXO)
63
64
int
65
b_mkdir(int argc, char** argv, Shbltin_t* context)
66
{
67
register char* path;
68
register int n;
69
register mode_t mode = DIRMODE;
70
register mode_t mask = 0;
71
register int mflag = 0;
72
register int pflag = 0;
73
register int vflag = 0;
74
int made;
75
char* part;
76
mode_t dmode;
77
struct stat st;
78
79
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
80
for (;;)
81
{
82
switch (optget(argv, usage))
83
{
84
case 'm':
85
mflag = 1;
86
mode = strperm(opt_info.arg, &part, mode);
87
if (*part)
88
error(ERROR_exit(0), "%s: invalid mode", opt_info.arg);
89
continue;
90
case 'p':
91
pflag = 1;
92
continue;
93
case 'v':
94
vflag = 1;
95
continue;
96
case ':':
97
error(2, "%s", opt_info.arg);
98
break;
99
case '?':
100
error(ERROR_usage(2), "%s", opt_info.arg);
101
break;
102
}
103
break;
104
}
105
argv += opt_info.index;
106
if (error_info.errors || !*argv)
107
error(ERROR_usage(2), "%s", optusage(NiL));
108
mask = umask(0);
109
if (mflag || pflag)
110
{
111
dmode = DIRMODE & ~mask;
112
if (!mflag)
113
mode = dmode;
114
dmode |= S_IWUSR | S_IXUSR;
115
}
116
else
117
{
118
mode &= ~mask;
119
umask(mask);
120
mask = 0;
121
}
122
while (path = *argv++)
123
{
124
if (!mkdir(path, mode))
125
{
126
if (vflag)
127
error(0, "%s: directory created", path);
128
made = 1;
129
}
130
else if (!pflag || !(errno == ENOENT || errno == EEXIST || errno == ENOTDIR))
131
{
132
error(ERROR_system(0), "%s:", path);
133
continue;
134
}
135
else if (errno == EEXIST)
136
continue;
137
else
138
{
139
/*
140
* -p option, preserve intermediates
141
* first eliminate trailing /'s
142
*/
143
144
made = 0;
145
n = strlen(path);
146
while (n > 0 && path[--n] == '/');
147
path[n + 1] = 0;
148
for (part = path, n = *part; n;)
149
{
150
/* skip over slashes */
151
while (*part == '/')
152
part++;
153
/* skip to next component */
154
while ((n = *part) && n != '/')
155
part++;
156
*part = 0;
157
if (mkdir(path, n ? dmode : mode) < 0 && errno != EEXIST && access(path, F_OK) < 0)
158
{
159
error(ERROR_system(0), "%s: cannot create intermediate directory", path);
160
*part = n;
161
break;
162
}
163
if (vflag)
164
error(0, "%s: directory created", path);
165
if (!(*part = n))
166
{
167
made = 1;
168
break;
169
}
170
}
171
}
172
if (made && (mode & (S_ISVTX|S_ISUID|S_ISGID)))
173
{
174
if (stat(path, &st))
175
{
176
error(ERROR_system(0), "%s: cannot stat", path);
177
break;
178
}
179
if ((st.st_mode & (S_ISVTX|S_ISUID|S_ISGID)) != (mode & (S_ISVTX|S_ISUID|S_ISGID)) && chmod(path, mode))
180
{
181
error(ERROR_system(0), "%s: cannot change mode from %s to %s", path, fmtperm(st.st_mode & (S_ISVTX|S_ISUID|S_ISGID)), fmtperm(mode));
182
break;
183
}
184
}
185
}
186
if (mask)
187
umask(mask);
188
return error_info.errors != 0;
189
}
190
191