1 /* mkdir-p.c -- Ensure that a directory and its parents exist.
3 Copyright (C) 1990, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
4 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
20 /* Written by David MacKenzie <djm@gnu.ai.mit.edu> and Jim Meyering. */
31 #include <sys/types.h>
40 #define _(msgid) gettext (msgid)
42 #include "chdir-safer.h"
49 #include "stat-macros.h"
51 /* Ensure that the directory ARG exists.
53 Create any leading directories that don't already exist, with
54 permissions PARENT_MODE.
55 If the last element of ARG does not exist, create it as
56 a new directory with permissions MODE.
57 If OWNER and GROUP are non-negative, use them to set the UID and GID of
58 any created directories.
59 If VERBOSE_FMT_STRING is nonzero, use it as a printf format
60 string for printing a message after successfully making a directory,
61 with the name of the directory that was just made as an argument.
62 If PRESERVE_EXISTING is true and ARG is an existing directory,
63 then do not attempt to set its permissions and ownership.
65 Set *CWD_ERRNO to a (nonzero) error number if this
66 function has changed the current working directory and is unable to
67 restore it to its initial state. Do not change
70 Return true iff ARG exists as a directory with the proper ownership
71 and permissions when done. Note that this function returns true
72 even when it fails to return to the initial working directory. */
75 make_dir_parents (char const *arg,
80 bool preserve_existing,
81 char const *verbose_fmt_string,
86 bool do_chdir = false; /* Whether to chdir before each mkdir. */
88 bool cwd_problem = false;
89 char const *fixup_permissions_dir = NULL;
90 char const *full_dir = arg;
95 struct ptr_list *next;
97 struct ptr_list *leading_dirs = NULL;
99 if (stat (arg, &stats) == 0)
101 if (! S_ISDIR (stats.st_mode))
103 error (0, 0, _("%s exists but is not a directory"), quote (arg));
107 if (!preserve_existing)
108 fixup_permissions_dir = arg;
110 else if (errno != ENOENT || !*arg)
112 error (0, errno, "%s", quote (arg));
118 mode_t tmp_mode; /* Initial perms for leading dirs. */
119 bool re_protect; /* Should leading dirs be unwritable? */
123 /* Temporarily relax umask in case it's overly restrictive. */
124 mode_t oldmask = umask (0);
126 /* Make a copy of ARG that we can scribble NULs on. */
127 dir = alloca (strlen (arg) + 1);
129 strip_trailing_slashes (dir);
132 /* If leading directories shouldn't be readable, writable or executable,
133 or should have set[ug]id or sticky bits set and we are setting
134 their owners, we need to fix their permissions after making them. */
135 if (((parent_mode & S_IRWXU) != S_IRWXU)
136 || ((owner != (uid_t) -1 || group != (gid_t) -1)
137 && (parent_mode & (S_ISUID | S_ISGID | S_ISVTX)) != 0))
144 tmp_mode = parent_mode;
148 /* If we can record the current working directory, we may be able
149 to do the chdir optimization. */
150 do_chdir = (save_cwd (&cwd) == 0);
152 /* If we've saved the cwd and DIR is an absolute file name,
153 we must chdir to `/' in order to enable the chdir optimization.
154 So if chdir ("/") fails, turn off the optimization. */
155 if (do_chdir && dir[0] == '/')
157 /* POSIX says "//" might be special, so chdir to "//" if the
158 file name starts with exactly two slashes. */
159 char const *root = "//" + (dir[1] != '/' || dir[2] == '/');
160 if (chdir (root) != 0)
169 /* Skip over leading slashes. */
170 while (*slash == '/')
175 bool dir_known_to_exist;
178 /* slash points to the leftmost unprocessed component of dir. */
179 basename_dir = slash;
181 slash = strchr (slash, '/');
185 /* If we're *not* doing chdir before each mkdir, then we have to refer
186 to the target using the full (multi-component) directory name. */
191 dir_known_to_exist = (mkdir (basename_dir, tmp_mode) == 0);
194 if (dir_known_to_exist)
196 if (verbose_fmt_string)
197 error (0, 0, verbose_fmt_string, quote (dir));
199 if ((owner != (uid_t) -1 || group != (gid_t) -1)
200 && lchown (basename_dir, owner, group)
201 #if defined AFS && defined EPERM
206 error (0, errno, _("cannot change owner and/or group of %s"),
214 struct ptr_list *new = alloca (sizeof *new);
215 new->dirname_end = slash;
216 new->next = leading_dirs;
221 /* If we were able to save the initial working directory,
222 then we can use chdir to change into each directory before
223 creating an entry in that directory. This avoids making
224 mkdir process O(n^2) file name components. */
227 /* If we know that basename_dir is a directory (because we've
228 just created it), then ensure that when we change to it,
229 that final component is not a symlink. Otherwise, we must
230 accept the possibility that basename_dir is a preexisting
231 symlink-to-directory and chdir through the symlink. */
232 if ((dir_known_to_exist
233 ? chdir_no_follow (basename_dir)
234 : chdir (basename_dir)) == 0)
235 dir_known_to_exist = true;
236 else if (dir_known_to_exist)
238 error (0, errno, _("cannot chdir to directory %s"),
244 else if (!dir_known_to_exist)
245 dir_known_to_exist = (stat (basename_dir, &stats) == 0
246 && S_ISDIR (stats.st_mode));
248 if (!dir_known_to_exist)
250 error (0, mkdir_errno, _("cannot create directory %s"),
258 /* Avoid unnecessary calls to mkdir when given
259 file names containing multiple adjacent slashes. */
260 while (*slash == '/')
267 /* Done creating leading directories. Restore original umask. */
270 /* We're done making leading directories.
271 Create the final component of the file name. */
274 bool dir_known_to_exist = (mkdir (basename_dir, mode) == 0);
275 int mkdir_errno = errno;
278 if ( ! dir_known_to_exist)
279 dir_known_to_exist = (stat (basename_dir, &sbuf) == 0
280 && S_ISDIR (sbuf.st_mode));
282 if ( ! dir_known_to_exist)
284 error (0, mkdir_errno,
285 _("cannot create directory %s"), quote (dir));
290 if (verbose_fmt_string)
291 error (0, 0, verbose_fmt_string, quote (dir));
292 fixup_permissions_dir = basename_dir;
297 if (fixup_permissions_dir)
299 /* chown must precede chmod because on some systems,
300 chown clears the set[ug]id bits for non-superusers,
301 resulting in incorrect permissions.
302 On System V, users can give away files with chown and then not
303 be able to chmod them. So don't give files away. */
305 if (owner != (uid_t) -1 || group != (gid_t) -1)
307 if (lchown (fixup_permissions_dir, owner, group) != 0
313 error (0, errno, _("cannot change owner and/or group of %s"),
319 /* The above chown may have turned off some permission bits in MODE.
320 Another reason we may have to use chmod here is that mkdir(2) is
321 required to honor only the file permission bits. In particular,
322 it need not honor the `special' bits, so if MODE includes any
323 special bits, set them here. */
324 if ((mode & ~S_IRWXUGO) && lchmod (fixup_permissions_dir, mode) != 0)
326 error (0, errno, _("cannot change permissions of %s"),
334 if (restore_cwd (&cwd) != 0)
342 /* If the mode for leading directories didn't include owner "wx"
343 privileges, reset their protections to the correct value. */
344 for (; leading_dirs != NULL; leading_dirs = leading_dirs->next)
346 leading_dirs->dirname_end[0] = '\0';
347 if ((cwd_problem && *full_dir != '/')
348 || lchmod (full_dir, parent_mode) != 0)
350 error (0, (cwd_problem ? 0 : errno),
351 _("cannot change permissions of %s"), quote (full_dir));