diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2005-06-14 23:56:49 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2005-06-14 23:56:49 +0000 |
commit | 153854cc31f33964cfe59d880fc93e649cf874bb (patch) | |
tree | 7b9a6d8e5fb1e34e577ea8822983f4a2c348ff57 | |
parent | 616a6e514699cb160cdedd00367091a7b7b6be01 (diff) | |
download | coreutils-153854cc31f33964cfe59d880fc93e649cf874bb.tar.xz |
(make_dir): Remove. All uses replaced by mkdir.
(make_dir_parents): Last arg is now int * (for errno), not bool *.
Rewrite "mkdir -p" algorithm to avoid the need for "stat"
each time through the loop. Do not diagnose restore_cwd failure;
that is the caller's job (and perhaps the caller does not care).
-rw-r--r-- | lib/mkdir-p.c | 112 |
1 files changed, 29 insertions, 83 deletions
diff --git a/lib/mkdir-p.c b/lib/mkdir-p.c index af31b7afe..a6572a41b 100644 --- a/lib/mkdir-p.c +++ b/lib/mkdir-p.c @@ -49,59 +49,6 @@ #define WX_USR (S_IWUSR | S_IXUSR) -/* Attempt to create directory DIR (aka FULLDIR) with the specified MODE. - If CREATED_DIR_P is non-NULL, set *CREATED_DIR_P if this - function creates DIR and clear it otherwise. Give a diagnostic and - return false if DIR cannot be created or cannot be determined to - exist already. Use FULLDIR in any diagnostic, not DIR. - Note that if DIR already exists, this function returns true - (indicating success) and clears *CREATED_DIR_P. */ - -bool -make_dir (char const *dir, char const *fulldir, mode_t mode, - bool *created_dir_p) -{ - bool ok = true; - bool created_dir; - - created_dir = (mkdir (dir, mode) == 0); - - if (!created_dir) - { - struct stat stats; - int saved_errno = errno; - - /* The mkdir and stat calls below may appear to be reversed. - They are not. It is important to call mkdir first and then to - call stat (to distinguish the three cases) only if mkdir fails. - The alternative to this approach is to `stat' each directory, - then to call mkdir if it doesn't exist. But if some other process - were to create the directory between the stat & mkdir, the mkdir - would fail with EEXIST. */ - - if (stat (dir, &stats)) - { - error (0, saved_errno, _("cannot create directory %s"), - quote (fulldir)); - ok = false; - } - else if (!S_ISDIR (stats.st_mode)) - { - error (0, 0, _("%s exists but is not a directory"), quote (fulldir)); - ok = false; - } - else - { - /* DIR (aka FULLDIR) already exists and is a directory. */ - } - } - - if (created_dir_p) - *created_dir_p = created_dir; - - return ok; -} - /* Ensure that the directory ARG exists. Create any leading directories that don't already exist, with @@ -116,9 +63,10 @@ make_dir (char const *dir, char const *fulldir, mode_t mode, If PRESERVE_EXISTING is true and ARG is an existing directory, then do not attempt to set its permissions and ownership. - Set *DIFFERENT_WORKING_DIR to true if this function has changed the - current working directory and is unable to restore it to its - initial state. Do not change *DIFFERENT_WORKING_DIR otherwise. + Set *CWD_ERRNO to a (nonzero) error number if this + function has changed the current working directory and is unable to + restore it to its initial state. Do not change + *CWD_ERRNO otherwise. Return true iff ARG exists as a directory with the proper ownership and permissions when done. Note that this function returns true @@ -132,7 +80,7 @@ make_dir_parents (char const *arg, gid_t group, bool preserve_existing, char const *verbose_fmt_string, - bool *different_working_dir) + int *cwd_errno) { struct stat stats; bool retval = true; @@ -225,8 +173,6 @@ make_dir_parents (char const *arg, while (true) { - bool newly_created_dir; - /* slash points to the leftmost unprocessed component of dir. */ basename_dir = slash; @@ -240,13 +186,7 @@ make_dir_parents (char const *arg, basename_dir = dir; *slash = '\0'; - if (! make_dir (basename_dir, dir, tmp_mode, &newly_created_dir)) - { - retval = false; - break; - } - - if (newly_created_dir) + if (mkdir (basename_dir, tmp_mode) == 0) { if (verbose_fmt_string) error (0, 0, verbose_fmt_string, quote (dir)); @@ -273,11 +213,22 @@ make_dir_parents (char const *arg, leading_dirs = new; } } + else if (errno == EEXIST) + { + /* A file is already there. Perhaps it is a directory. + If not, it will be diagnosed later. */ + } + else + { + error (0, errno, _("cannot create directory %s"), quote (dir)); + retval = false; + break; + } /* If we were able to save the initial working directory, then we can use chdir to change into each directory before creating an entry in that directory. This avoids making - stat and mkdir process O(n^2) file name components. */ + mkdir process O(n^2) file name components. */ if (do_chdir && chdir (basename_dir) < 0) { error (0, errno, _("cannot chdir to directory %s"), @@ -288,7 +239,7 @@ make_dir_parents (char const *arg, *slash++ = '/'; - /* Avoid unnecessary calls to `stat' when given + /* Avoid unnecessary calls to mkdir when given file names containing multiple adjacent slashes. */ while (*slash == '/') slash++; @@ -304,12 +255,12 @@ make_dir_parents (char const *arg, Create the final component of the file name. */ if (retval) { - bool newly_created_dir; - - if (! make_dir (basename_dir, dir, mode, &newly_created_dir)) - retval = false; - - if (newly_created_dir) + if (mkdir (basename_dir, mode) != 0) + { + error (0, errno, _("cannot create directory %s"), quote (dir)); + retval = false; + } + else { if (verbose_fmt_string) error (0, 0, verbose_fmt_string, quote (dir)); @@ -355,17 +306,12 @@ make_dir_parents (char const *arg, if (do_chdir) { - int saved_errno; - cwd_problem = (restore_cwd (&cwd) != 0); - saved_errno = errno; - free_cwd (&cwd); - - if (cwd_problem) + if (restore_cwd (&cwd) != 0) { - error (0, saved_errno, - _("failed to return to initial working directory")); - *different_working_dir = true; + *cwd_errno = errno; + cwd_problem = true; } + free_cwd (&cwd); } /* If the mode for leading directories didn't include owner "wx" |