* src/extract.c (make_directories): New arg JUST_PARENT.
All callers changed.
* src/misc.c (struct wd.name, add_wd, chdir_arg):
Use char *, not char const *, to let make_directories
temporarily alter slashes. All uses changed.
(chdir_do): Do not create a new name with trailing "/."
because make_directories no longer needs this.
extern dev_t root_device;
void extr_init (void);
-int make_directories (char *file_name);
+int make_directories (char *file_name, bool just_parent);
void extract_archive (void);
void extract_finish (void);
bool rename_directory (char *src, char *dst);
enum { BADFD = AT_FDCWD == -1 ? -2 : -1 };
extern idx_t chdir_current;
-idx_t chdir_arg (char const *dir);
+idx_t chdir_arg (char *dir);
void chdir_do (idx_t dir, bool create);
struct chdir_id { int err; dev_t st_dev; ino_t st_ino; } chdir_id (void);
struct fdbase fdbase (char const *);
}
}
-/* Ensure that FILE_NAME's parent is a directory by creating the
- directory and ancestors as needed.
+/* Ensure that FILE_NAME is a directory by creating it and ancestors as needed.
+ If JUST_PARENT do so for FILE_NAME's parent directory, not FILE_NAME itself.
Do not overwrite existing files.
Possibly temporarily modify FILE_NAME if it contains slashes,
but restore FILE_NAME before returning.
some other process), zero if a directory is already there, and
negative (issuing a diagnostic) otherwise. */
int
-make_directories (char *file_name)
+make_directories (char *file_name, bool just_parent)
{
char *cursor0 = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
char *cursor; /* points into the file name */
int parent_errno;
int result = 0;
- for (cursor = cursor0; *cursor; cursor++)
+ for (cursor = cursor0; ; cursor++)
{
mode_t mode;
mode_t desired_mode;
int status;
- if (! ISSLASH (*cursor))
- continue;
-
- /* Avoid mkdir of empty string, if leading or double '/'. */
-
- if (cursor == cursor0 || ISSLASH (cursor[-1]))
- continue;
-
- /* Avoid mkdir where last part of file name is "." or "..". */
+ char c = *cursor;
+ if (! ISSLASH (c))
+ {
+ if (c)
+ continue;
+ if (just_parent)
+ break;
+ }
- if (cursor[-1] == '.'
- && (cursor == cursor0 + 1 || ISSLASH (cursor[-2])
- || (cursor[-2] == '.'
- && (cursor == cursor0 + 2 || ISSLASH (cursor[-3])))))
- continue;
+ /* Avoid mkdir of empty string (if leading or double slash),
+ or where last part of file name is "." or "..". */
+ if (cursor == cursor0 || ISSLASH (cursor[-1])
+ || (cursor[-1] == '.'
+ && (cursor == cursor0 + 1 || ISSLASH (cursor[-2])
+ || (cursor[-2] == '.'
+ && (cursor == cursor0 + 2 || ISSLASH (cursor[-3]))))))
+ {
+ if (c)
+ continue;
+ break;
+ }
- char c = *cursor;
*cursor = '\0'; /* truncate the name there */
desired_mode = MODE_RWX & ~ newdir_umask;
mode = desired_mode | (we_are_root ? 0 : MODE_WXUSR);
break;
}
+ if (!c)
+ break;
*cursor = c;
}
case ENOENT:
/* Attempt creating missing intermediate directories. */
- if (0 < make_directories (file_name))
+ if (0 < make_directories (file_name, true))
return RECOVER_OK;
break;
switch (e)
{
case ENOENT:
- if (0 <= make_directories (dst))
+ if (0 <= make_directories (dst, true))
{
f = fdbase (dst);
if (f.fd != BADFD
struct wd
{
/* The directory's name. */
- char const *name;
+ char *name;
/* "Absolute" path representing this directory; in the contrast to
the real absolute pathname, it can contain /../ components (see
normalize_filename_x for the reason of it). It is NULL if the
DFD is either AT_FDWD for the initial "." entry,
or 0 meaning the file descriptor is not open yet. */
static void
-add_wd (char const *dir, int dfd)
+add_wd (char *dir, int dfd)
{
wd[wd_count].name = dir;
wd[wd_count].abspath = NULL;
int n_incr_min = 4;
wd = xpalloc (NULL, &wd_alloc, n_incr_min, -1, sizeof *wd);
- add_wd (".", AT_FDCWD);
+ add_wd ((char *) ".", AT_FDCWD);
}
}
two targets to the vector. However, if DIR is "." or an equivalent,
just reuse the last item in the vector. */
idx_t
-chdir_arg (char const *dir)
+chdir_arg (char *dir)
{
ensure_wd ();
{
if (create)
{
- char *dir_with_dot;
struct open_how saved_open_searchdir_how = open_searchdir_how;
/* Don't use O_BENEATH during creation of the
directory. The one-top-level directory is
allowed to be given as an absolute path. */
open_searchdir_how.resolve = 0;
- /* Append a dot. make_directories creates
- directories up to and excluding the last
- component of the path. So, in order to create
- "a/b", we need to pass "a/b/." to it. */
- {
- namebuf_t nbuf = namebuf_create (curr->name);
- namebuf_add_dir (nbuf, ".");
- dir_with_dot = namebuf_finish (nbuf);
- }
- if (0 <= make_directories (dir_with_dot))
+ if (0 <= make_directories (curr->name, false))
/* Directory created, retry */
fd = openat (chdir_fd, curr->name,
open_searchdir_how.flags & ~O_NOFOLLOW);
open_searchdir_how = saved_open_searchdir_how;
- free (dir_with_dot);
/* Either the creation or open failed */
if (fd < 0)
open_fatal (curr->name);
void
name_init (void)
{
- chdir_do (chdir_arg ("."), false);
+ chdir_do (chdir_arg ((char *) "."), false);
name_list_adjust ();
}
\f