1 /* mkdir - make directories */
3 /* See Makefile for compilation details. */
12 #if defined (HAVE_UNISTD_H)
18 #include "bashgetopt.h"
24 #define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
26 extern int parse_symbolic_mode ();
28 static int make_path ();
30 static int original_umask
;
36 int opt
, pflag
, omode
, rval
, octal
, nmode
, parent_mode
, um
;
40 reset_internal_getopt ();
43 while ((opt
= internal_getopt(list
, "m:p")) != -1)
65 omode
= S_IRWXU
| S_IRWXG
| S_IRWXO
; /* a=rwx */
66 else if (ISOCTAL (*mode
)) /* octal number */
68 omode
= read_octal (mode
);
71 builtin_error ("invalid file mode: %s", mode
);
72 return (EXECUTION_FAILURE
);
78 /* initial bits are a=rwx; the mode argument modifies them */
79 omode
= parse_symbolic_mode (mode
, S_IRWXU
| S_IRWXG
| S_IRWXO
);
82 builtin_error ("invalid file mode: %s", mode
);
83 return (EXECUTION_FAILURE
);
88 /* Make the new mode */
89 original_umask
= umask (0);
90 umask (original_umask
);
92 nmode
= (S_IRWXU
| S_IRWXG
| S_IRWXO
) & ~original_umask
;
93 parent_mode
= nmode
| (S_IWRITE
|S_IEXEC
); /* u+wx */
95 /* Adjust new mode based on mode argument */
98 for (rval
= EXECUTION_SUCCESS
, l
= list
; l
; l
= l
->next
)
100 if (pflag
&& make_path (l
->word
->word
, nmode
, parent_mode
))
102 rval
= EXECUTION_FAILURE
;
105 else if (pflag
== 0 && mkdir (l
->word
->word
, nmode
) < 0)
107 builtin_error ("cannot create directory `%s': %s", l
->word
->word
, strerror (errno
));
108 rval
= EXECUTION_FAILURE
;
114 /* Make all the directories leading up to PATH, then create PATH. Note that
115 this changes the process's umask; make sure that all paths leading to a
116 return reset it to ORIGINAL_UMASK */
118 make_path (path
, nmode
, parent_mode
)
120 int nmode
, parent_mode
;
126 if (stat (path
, &sb
) == 0)
128 if (S_ISDIR (sb
.st_mode
) == 0)
130 builtin_error ("`%s': file exists but is not a directory", path
);
134 if (chmod (path
, nmode
))
136 builtin_error ("%s: %s", path
, strerror (errno
));
144 npath
= savestring (path
); /* So we can write to it. */
146 /* Check whether or not we need to do anything with intermediate dirs. */
148 /* Skip leading slashes. */
153 while (p
= strchr (p
, '/'))
156 if (stat (npath
, &sb
) != 0)
158 if (mkdir (npath
, parent_mode
))
160 builtin_error ("cannot create directory `%s': %s", npath
, strerror (errno
));
161 umask (original_umask
);
166 else if (S_ISDIR (sb
.st_mode
) == 0)
168 builtin_error ("`%s': file exists but is not a directory", npath
);
169 umask (original_umask
);
174 *p
++ = '/'; /* restore slash */
179 /* Create the final directory component. */
180 if (stat (npath
, &sb
) && mkdir (npath
, nmode
))
182 builtin_error ("cannot create directory `%s': %s", npath
, strerror (errno
));
183 umask (original_umask
);
188 umask (original_umask
);
193 char *mkdir_doc
[] = {
194 "Make directories. Create the directories named as arguments, in",
195 "the order specified, using mode rwxrwxrwx as modified by the current",
196 "umask (see `help umask'). The -m option causes the file permission",
197 "bits of the final directory to be MODE. The MODE argument may be",
198 "an octal number or a symbolic mode like that used by chmod(1). If",
199 "a symbolic mode is used, the operations are interpreted relative to",
200 "an initial mode of \"a=rwx\". The -p option causes any required",
201 "intermediate directories in PATH to be created. The directories",
202 "are created with permssion bits of rwxrwxrwx as modified by the current",
203 "umask, plus write and search permissions for the owner. mkdir",
204 "returns 0 if the directories are created successfully, and non-zero",
205 "if an error occurs.",
209 struct builtin mkdir_struct
= {
214 "mkdir [-p] [-m mode] directory [directory ...]",