summaryrefslogtreecommitdiff
path: root/lib/makepath.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1997-07-09 18:02:07 +0000
committerJim Meyering <jim@meyering.net>1997-07-09 18:02:07 +0000
commitd68871bdec53faa6bf491bd12f6eb98da596234c (patch)
tree755299c419a198d3309495d450c175f496dd730a /lib/makepath.c
parent6b544d3d8a538586e58a87b1e7fbc3fe9754b029 (diff)
downloadcoreutils-d68871bdec53faa6bf491bd12f6eb98da596234c.tar.xz
(make_path): Chdir to `/' before starting if necessary.
Call save_cwd before while loop rather than from first iteration inside it.
Diffstat (limited to 'lib/makepath.c')
-rw-r--r--lib/makepath.c32
1 files changed, 17 insertions, 15 deletions
diff --git a/lib/makepath.c b/lib/makepath.c
index 17844318a..4218e90c6 100644
--- a/lib/makepath.c
+++ b/lib/makepath.c
@@ -87,7 +87,7 @@ void strip_trailing_slashes ();
{ \
/* We're done operating on basename_dir. \
Restore working directory. */ \
- if (saved_cwd) \
+ if (do_chdir) \
{ \
int fail = restore_cwd (&cwd, NULL, NULL); \
free_cwd (&cwd); \
@@ -159,10 +159,9 @@ make_path (argpath, mode, parent_mode, owner, group, preserve_existing,
struct ptr_list *next;
};
struct ptr_list *p, *leading_dirs = NULL;
- int saved_cwd = 0;
+ int do_chdir; /* Whether to chdir before each mkdir. */
struct saved_cwd cwd;
char *basename_dir;
- int first_subdir = 1;
char *dirpath;
/* Temporarily relax umask in case it's overly restrictive. */
@@ -189,6 +188,16 @@ make_path (argpath, mode, parent_mode, owner, group, preserve_existing,
re_protect = 0;
}
+ /* If we can record the current working directory, we may be able
+ to do the chdir optimization. */
+ do_chdir = !save_cwd (&cwd);
+
+ /* If we've saved the cwd and DIRPATH is an absolute pathname,
+ we must chdir to `/' in order to enable the chdir optimization.
+ So if chdir ("/") fails, turn off the optimization. */
+ if (do_chdir && *dirpath == '/' && chdir ("/") < 0)
+ do_chdir = 0;
+
slash = dirpath;
/* Skip over leading slashes. */
@@ -204,16 +213,9 @@ make_path (argpath, mode, parent_mode, owner, group, preserve_existing,
if (slash == NULL)
break;
- if (first_subdir)
- {
- first_subdir = 0;
- saved_cwd = !save_cwd (&cwd);
- }
-
- /* If save_cwd could not record the current directory, then don't
- do the chdir optimization and resort to using full pathnames. */
-
- if (!saved_cwd)
+ /* If we're *not* doing chdir before each mkdir, then we have to refer
+ to the target using the full (multi-component) directory name. */
+ if (!do_chdir)
basename_dir = dirpath;
*slash = '\0';
@@ -265,7 +267,7 @@ make_path (argpath, mode, parent_mode, owner, group, preserve_existing,
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. */
- if (saved_cwd && chdir (basename_dir) < 0)
+ if (do_chdir && chdir (basename_dir) < 0)
{
error (0, errno, "cannot chdir to directory, %s", dirpath);
CLEANUP;
@@ -280,7 +282,7 @@ make_path (argpath, mode, parent_mode, owner, group, preserve_existing,
slash++;
}
- if (!saved_cwd)
+ if (!do_chdir)
basename_dir = dirpath;
/* We're done making leading directories.