source: vendor/bash/3.1-p17/examples/loadables/mkdir.c

Last change on this file was 3231, checked in by bird, 18 years ago

eol style.

  • Property svn:eol-style set to native
File size: 5.0 KB
Line 
1/* mkdir - make directories */
2
3/* See Makefile for compilation details. */
4
5#include <config.h>
6
7#include "bashtypes.h"
8#include "posixstat.h"
9#include <errno.h>
10#include <stdio.h>
11#include "bashansi.h"
12#if defined (HAVE_UNISTD_H)
13# include <unistd.h>
14#endif
15
16#include "builtins.h"
17#include "shell.h"
18#include "bashgetopt.h"
19
20#if !defined (errno)
21extern int errno;
22#endif
23
24#define ISOCTAL(c) ((c) >= '0' && (c) <= '7')
25
26extern int parse_symbolic_mode ();
27
28static int make_path ();
29
30static int original_umask;
31
32int
33mkdir_builtin (list)
34 WORD_LIST *list;
35{
36 int opt, pflag, omode, rval, octal, nmode, parent_mode, um;
37 char *mode;
38 WORD_LIST *l;
39
40 reset_internal_getopt ();
41 pflag = 0;
42 mode = (char *)NULL;
43 while ((opt = internal_getopt(list, "m:p")) != -1)
44 switch (opt)
45 {
46 case 'p':
47 pflag = 1;
48 break;
49 case 'm':
50 mode = list_optarg;
51 break;
52 default:
53 builtin_usage();
54 return (EX_USAGE);
55 }
56 list = loptend;
57
58 if (list == 0)
59 {
60 builtin_usage ();
61 return (EX_USAGE);
62 }
63
64 if (mode == NULL)
65 omode = S_IRWXU | S_IRWXG | S_IRWXO; /* a=rwx */
66 else if (ISOCTAL (*mode)) /* octal number */
67 {
68 omode = read_octal (mode);
69 if (omode < 0)
70 {
71 builtin_error ("invalid file mode: %s", mode);
72 return (EXECUTION_FAILURE);
73 }
74 octal = 1;
75 }
76 else if (mode)
77 {
78 /* initial bits are a=rwx; the mode argument modifies them */
79 omode = parse_symbolic_mode (mode, S_IRWXU | S_IRWXG | S_IRWXO);
80 if (omode < 0)
81 {
82 builtin_error ("invalid file mode: %s", mode);
83 return (EXECUTION_FAILURE);
84 }
85 octal = 0;
86 }
87
88 /* Make the new mode */
89 original_umask = umask (0);
90 umask (original_umask);
91
92 nmode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~original_umask;
93 parent_mode = nmode | (S_IWRITE|S_IEXEC); /* u+wx */
94
95 /* Adjust new mode based on mode argument */
96 nmode &= omode;
97
98 for (rval = EXECUTION_SUCCESS, l = list; l; l = l->next)
99 {
100 if (pflag && make_path (l->word->word, nmode, parent_mode))
101 {
102 rval = EXECUTION_FAILURE;
103 continue;
104 }
105 else if (pflag == 0 && mkdir (l->word->word, nmode) < 0)
106 {
107 builtin_error ("cannot create directory `%s': %s", l->word->word, strerror (errno));
108 rval = EXECUTION_FAILURE;
109 }
110 }
111 return rval;
112}
113
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 */
117static int
118make_path (path, nmode, parent_mode)
119 char *path;
120 int nmode, parent_mode;
121{
122 int oumask;
123 struct stat sb;
124 char *p, *npath;
125
126 if (stat (path, &sb) == 0)
127 {
128 if (S_ISDIR (sb.st_mode) == 0)
129 {
130 builtin_error ("`%s': file exists but is not a directory", path);
131 return 1;
132 }
133
134 if (chmod (path, nmode))
135 {
136 builtin_error ("%s: %s", path, strerror (errno));
137 return 1;
138 }
139
140 return 0;
141 }
142
143 oumask = umask (0);
144 npath = savestring (path); /* So we can write to it. */
145
146 /* Check whether or not we need to do anything with intermediate dirs. */
147
148 /* Skip leading slashes. */
149 p = npath;
150 while (*p == '/')
151 p++;
152
153 while (p = strchr (p, '/'))
154 {
155 *p = '\0';
156 if (stat (npath, &sb) != 0)
157 {
158 if (mkdir (npath, parent_mode))
159 {
160 builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
161 umask (original_umask);
162 free (npath);
163 return 1;
164 }
165 }
166 else if (S_ISDIR (sb.st_mode) == 0)
167 {
168 builtin_error ("`%s': file exists but is not a directory", npath);
169 umask (original_umask);
170 free (npath);
171 return 1;
172 }
173
174 *p++ = '/'; /* restore slash */
175 while (*p == '/')
176 p++;
177 }
178
179 /* Create the final directory component. */
180 if (stat (npath, &sb) && mkdir (npath, nmode))
181 {
182 builtin_error ("cannot create directory `%s': %s", npath, strerror (errno));
183 umask (original_umask);
184 free (npath);
185 return 1;
186 }
187
188 umask (original_umask);
189 free (npath);
190 return 0;
191}
192
193char *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.",
206 (char *)NULL
207};
208
209struct builtin mkdir_struct = {
210 "mkdir",
211 mkdir_builtin,
212 BUILTIN_ENABLED,
213 mkdir_doc,
214 "mkdir [-p] [-m mode] directory [directory ...]",
215 0
216};
Note: See TracBrowser for help on using the repository browser.