mirror of
https://git.savannah.gnu.org/git/tar.git
synced 2026-08-17 06:46:05 +00:00
Avoid need to append "/." for make_directories
* 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.
This commit is contained in:
+2
-2
@@ -558,7 +558,7 @@ void verify_volume (void);
|
||||
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);
|
||||
@@ -782,7 +782,7 @@ idx_t blocking_write (int fd, void const *buf, idx_t count);
|
||||
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 *);
|
||||
|
||||
+29
-22
@@ -770,8 +770,8 @@ fixup_delayed_set_stat (char const *src, char const *dst)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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.
|
||||
@@ -779,7 +779,7 @@ fixup_delayed_set_stat (char const *src, char const *dst)
|
||||
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 */
|
||||
@@ -787,29 +787,34 @@ make_directories (char *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 "..". */
|
||||
|
||||
if (cursor[-1] == '.'
|
||||
&& (cursor == cursor0 + 1 || ISSLASH (cursor[-2])
|
||||
|| (cursor[-2] == '.'
|
||||
&& (cursor == cursor0 + 2 || ISSLASH (cursor[-3])))))
|
||||
continue;
|
||||
|
||||
char c = *cursor;
|
||||
if (! ISSLASH (c))
|
||||
{
|
||||
if (c)
|
||||
continue;
|
||||
if (just_parent)
|
||||
break;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
*cursor = '\0'; /* truncate the name there */
|
||||
desired_mode = MODE_RWX & ~ newdir_umask;
|
||||
mode = desired_mode | (we_are_root ? 0 : MODE_WXUSR);
|
||||
@@ -846,6 +851,8 @@ make_directories (char *file_name)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!c)
|
||||
break;
|
||||
*cursor = c;
|
||||
}
|
||||
|
||||
@@ -982,7 +989,7 @@ maybe_recoverable (char *file_name, bool regular, bool *interdir_made)
|
||||
|
||||
case ENOENT:
|
||||
/* Attempt creating missing intermediate directories. */
|
||||
if (0 < make_directories (file_name))
|
||||
if (0 < make_directories (file_name, true))
|
||||
return RECOVER_OK;
|
||||
break;
|
||||
|
||||
@@ -2086,7 +2093,7 @@ rename_directory (char *src, char *dst)
|
||||
switch (e)
|
||||
{
|
||||
case ENOENT:
|
||||
if (0 <= make_directories (dst))
|
||||
if (0 <= make_directories (dst, true))
|
||||
{
|
||||
f = fdbase (dst);
|
||||
if (f.fd != BADFD
|
||||
|
||||
+5
-16
@@ -959,7 +959,7 @@ set_file_atime (int fd, int parentfd, char const *file, struct timespec atime)
|
||||
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
|
||||
@@ -1020,7 +1020,7 @@ chdir_count (void)
|
||||
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;
|
||||
@@ -1051,7 +1051,7 @@ ensure_wd (void)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1060,7 +1060,7 @@ ensure_wd (void)
|
||||
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 ();
|
||||
|
||||
@@ -1124,27 +1124,16 @@ chdir_do (idx_t i, bool create)
|
||||
{
|
||||
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);
|
||||
|
||||
+1
-1
@@ -875,7 +875,7 @@ static idx_t name_buffer_length; /* allocated length of name_buffer */
|
||||
void
|
||||
name_init (void)
|
||||
{
|
||||
chdir_do (chdir_arg ("."), false);
|
||||
chdir_do (chdir_arg ((char *) "."), false);
|
||||
name_list_adjust ();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user