mirror of
https://github.com/coreutils/coreutils.git
synced 2024-12-12 19:34:40 +08:00
(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).
This commit is contained in:
parent
616a6e5146
commit
153854cc31
112
lib/mkdir-p.c
112
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"
|
||||
|
Loading…
Reference in New Issue
Block a user