tar: extract permissions for . last

* src/common.h (must_be_dot_or_slash): New decl.
* src/extract.c (mark_after_links): New function, taking code
that used to be in create_placeholder_file.
(create_placeholder_file): Use it.
(delay_set_stat): Always delay setting status for . and /.
* src/misc.c (must_be_dot_or_slash): Now extern.
* tests/extrac12.at: New file.
* tests/Makefile.am (TESTSUITE_AT): Add it.
* tests/testsuite.at: Likewise.
This commit is contained in:
Paul Eggert
2010-09-17 12:28:25 -07:00
parent cecb7ac8e6
commit 6e08ab7694
6 changed files with 71 additions and 16 deletions
+2
View File
@@ -591,6 +591,8 @@ enum { BILLION = 1000000000, LOG10_BILLION = 9 };
enum { TIMESPEC_STRSIZE_BOUND =
UINTMAX_STRSIZE_BOUND + LOG10_BILLION + sizeof "-." - 1 };
bool must_be_dot_or_slash (char const *);
enum remove_option
{
ORDINARY_REMOVE_OPTION,
+27 -15
View File
@@ -361,6 +361,30 @@ set_stat (char const *file_name,
fd, current_mode, current_mode_mask, typeflag, atflag);
}
/* For each entry H in the leading prefix of entries in HEAD that do
not have after_links marked, mark H and fill in its dev and ino
members. Assume HEAD && ! HEAD->after_links. */
static void
mark_after_links (struct delayed_set_stat *head)
{
struct delayed_set_stat *h = head;
do
{
struct stat st;
h->after_links = 1;
if (stat (h->file_name, &st) != 0)
stat_error (h->file_name);
else
{
h->dev = st.st_dev;
h->ino = st.st_ino;
}
}
while ((h = h->next) && ! h->after_links);
}
/* Remember to restore stat attributes (owner, group, mode and times)
for the directory FILE_NAME, using information given in *ST,
once we stop extracting files into that directory.
@@ -408,6 +432,8 @@ delay_set_stat (char const *file_name, struct tar_stat_info const *st,
data->change_dir = chdir_current;
strcpy (data->file_name, file_name);
delayed_set_stat_head = data;
if (must_be_dot_or_slash (file_name))
mark_after_links (data);
}
/* Update the delayed_set_stat info for an intermediate directory
@@ -1033,21 +1059,7 @@ create_placeholder_file (char *file_name, bool is_symlink, bool *interdir_made)
&& strncmp (file_name, h->file_name, h->file_name_len) == 0
&& ISSLASH (file_name[h->file_name_len])
&& (last_component (file_name) == file_name + h->file_name_len + 1))
{
do
{
h->after_links = 1;
if (stat (h->file_name, &st) != 0)
stat_error (h->file_name);
else
{
h->dev = st.st_dev;
h->ino = st.st_ino;
}
}
while ((h = h->next) && ! h->after_links);
}
mark_after_links (h);
return 0;
}
+1 -1
View File
@@ -390,7 +390,7 @@ static char *before_backup_name;
static char *after_backup_name;
/* Return 1 if FILE_NAME is obviously "." or "/". */
static bool
bool
must_be_dot_or_slash (char const *file_name)
{
file_name += FILE_SYSTEM_PREFIX_LEN (file_name);