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