mirror of
https://git.savannah.gnu.org/git/tar.git
synced 2026-08-16 22:36:05 +00:00
Go back to simpler chdir_arg API
* src/misc.c (add_wd, ensure_wd): New functions, replacing ... (grow_wd): .. this function, for clarity. All uses changed. (chdir_arg): Omit 2nd arg, to keep callers simpler. All uses changed. Instead of being recursive, be iterative; this is part of the simplification.
This commit is contained in:
+1
-1
@@ -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, bool one_top_level);
|
||||
idx_t chdir_arg (char const *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 *);
|
||||
|
||||
+45
-42
@@ -1015,65 +1015,69 @@ chdir_count (void)
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Grow the WD table by at least one entry. */
|
||||
/* Add DIR to the WD table. If one_top_level_dir, add that too.
|
||||
There must already be room.
|
||||
DFD is either AT_FDWD for the initial "." entry,
|
||||
or 0 meaning the file descriptor is not open yet. */
|
||||
static void
|
||||
grow_wd (void)
|
||||
add_wd (char const *dir, int dfd)
|
||||
{
|
||||
wd = xpalloc (wd, &wd_alloc, wd_alloc ? 1 : 2, -1, sizeof *wd);
|
||||
wd[wd_count].name = dir;
|
||||
wd[wd_count].abspath = NULL;
|
||||
wd[wd_count].fd = dfd;
|
||||
wd[wd_count].id.err = -1;
|
||||
wd[wd_count].one_top_level = false;
|
||||
wd_count++;
|
||||
|
||||
if (! wd_count)
|
||||
if (one_top_level_dir)
|
||||
{
|
||||
wd[wd_count].name = ".";
|
||||
wd[wd_count].name = one_top_level_dir;
|
||||
wd[wd_count].abspath = NULL;
|
||||
wd[wd_count].fd = AT_FDCWD;
|
||||
wd[wd_count].fd = 0;
|
||||
wd[wd_count].id.err = -1;
|
||||
wd[wd_count].one_top_level = false;
|
||||
wd[wd_count].one_top_level = true;
|
||||
wd_count++;
|
||||
if (one_top_level_dir)
|
||||
{
|
||||
wd[wd_count].name = one_top_level_dir;
|
||||
wd[wd_count].abspath = NULL;
|
||||
wd[wd_count].fd = 0;
|
||||
wd[wd_count].id.err = -1;
|
||||
wd[wd_count].one_top_level = true;
|
||||
wd_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure that WD exists, with an initial "." entry. */
|
||||
static void
|
||||
ensure_wd (void)
|
||||
{
|
||||
if (!wd)
|
||||
{
|
||||
/* This must be at least 1 + !!top_level_dir. Make it 4, to lessen
|
||||
reallocation effort when -C and --one-top-level are both used. */
|
||||
int n_incr_min = 4;
|
||||
|
||||
wd = xpalloc (NULL, &wd_alloc, n_incr_min, -1, sizeof *wd);
|
||||
add_wd (".", AT_FDCWD);
|
||||
}
|
||||
}
|
||||
|
||||
/* DIR is the operand of a -C option; add it to vector of chdir targets,
|
||||
and return the index of its location. */
|
||||
and return the index of its location. If --one-top-level-dir, add
|
||||
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, bool one_top_level)
|
||||
chdir_arg (char const *dir)
|
||||
{
|
||||
if (one_top_level)
|
||||
chdir_arg (dir, false);
|
||||
if (wd_count == wd_alloc)
|
||||
grow_wd ();
|
||||
ensure_wd ();
|
||||
|
||||
/* Optimize the common special case of the working directory,
|
||||
or the working directory as a prefix. */
|
||||
if (dir[0])
|
||||
{
|
||||
dir += dotslashlen (dir);
|
||||
if (! dir[dir[0] == '.'])
|
||||
{
|
||||
if (wd[wd_count - 1].one_top_level == one_top_level)
|
||||
return wd_count - 1;
|
||||
else
|
||||
return wd_count - 2;
|
||||
}
|
||||
if (!dir[dir[0] == '.'])
|
||||
return wd_count - 1;
|
||||
}
|
||||
|
||||
if (one_top_level)
|
||||
dir = one_top_level_dir;
|
||||
|
||||
wd[wd_count].name = dir;
|
||||
wd[wd_count].abspath = NULL;
|
||||
wd[wd_count].fd = 0;
|
||||
wd[wd_count].id.err = -1;
|
||||
wd[wd_count].one_top_level = one_top_level;
|
||||
return wd_count++;
|
||||
ptrdiff_t shortage = 1 + !!one_top_level_dir - (wd_alloc - wd_count);
|
||||
if (0 < shortage)
|
||||
wd = xpalloc (wd, &wd_alloc, shortage, -1, sizeof *wd);
|
||||
add_wd (dir, 0);
|
||||
return wd_count - 1;
|
||||
}
|
||||
|
||||
/* Index of current directory. */
|
||||
@@ -1202,8 +1206,7 @@ chdir_do (idx_t i, bool create)
|
||||
struct chdir_id
|
||||
chdir_id (void)
|
||||
{
|
||||
if (!wd)
|
||||
grow_wd ();
|
||||
ensure_wd ();
|
||||
|
||||
struct wd *curr = &wd[chdir_current];
|
||||
if (curr->id.err < 0)
|
||||
@@ -1418,8 +1421,8 @@ transform_top_level (const char *name)
|
||||
/* Return the absolute path that represents the working
|
||||
directory referenced by IDX.
|
||||
|
||||
If wd is empty, then there were no -C options given, and
|
||||
chdir_args() has never been called, so we simply return the
|
||||
If wd is empty, then no -C options were given, and
|
||||
chdir_arg has never been called, so simply return the
|
||||
process's actual cwd. (Note that in this case IDX is ignored,
|
||||
since it should always be 0.) */
|
||||
static const char *
|
||||
|
||||
+4
-5
@@ -875,7 +875,7 @@ static idx_t name_buffer_length; /* allocated length of name_buffer */
|
||||
void
|
||||
name_init (void)
|
||||
{
|
||||
chdir_do (chdir_arg (".", !!one_top_level_dir), false);
|
||||
chdir_do (chdir_arg ("."), false);
|
||||
name_list_adjust ();
|
||||
}
|
||||
|
||||
@@ -1119,8 +1119,7 @@ name_next_elt (bool change_dirs)
|
||||
case NELT_CHDIR:
|
||||
if (change_dirs)
|
||||
{
|
||||
chdir_do (chdir_arg (xstrdup (ep->v.name), !!one_top_level_dir),
|
||||
false);
|
||||
chdir_do (chdir_arg (xstrdup (ep->v.name)), false);
|
||||
name_list_advance ();
|
||||
break;
|
||||
}
|
||||
@@ -1183,7 +1182,7 @@ name_gather (void)
|
||||
static idx_t change_dir;
|
||||
|
||||
while ((ep = name_next_elt (false)) && ep->type == NELT_CHDIR)
|
||||
change_dir = chdir_arg (xstrdup (ep->v.name), !!one_top_level_dir);
|
||||
change_dir = chdir_arg (xstrdup (ep->v.name));
|
||||
|
||||
if (ep)
|
||||
{
|
||||
@@ -1212,7 +1211,7 @@ name_gather (void)
|
||||
{
|
||||
idx_t change_dir0 = change_dir;
|
||||
while ((ep = name_next_elt (false)) && ep->type == NELT_CHDIR)
|
||||
change_dir = chdir_arg (xstrdup (ep->v.name), !!one_top_level_dir);
|
||||
change_dir = chdir_arg (xstrdup (ep->v.name));
|
||||
|
||||
if (ep)
|
||||
addname (ep->v.name, change_dir, true, NULL);
|
||||
|
||||
Reference in New Issue
Block a user