From: Paul Eggert Date: Fri, 17 Sep 2010 19:25:55 +0000 (-0700) Subject: tar: extract permissions for . last X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=6e08ab76949954eccd059db0d5da90e011a11c27;p=chaz%2Ftar 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. --- diff --git a/src/common.h b/src/common.h index e0d8eb7..d0e3484 100644 --- a/src/common.h +++ b/src/common.h @@ -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, diff --git a/src/extract.c b/src/extract.c index 1f45593..46ee678 100644 --- a/src/extract.c +++ b/src/extract.c @@ -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; } diff --git a/src/misc.c b/src/misc.c index 64b1b2b..f1ebdd4 100644 --- a/src/misc.c +++ b/src/misc.c @@ -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); diff --git a/tests/Makefile.am b/tests/Makefile.am index ea1c6ae..5cfd847 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -78,6 +78,7 @@ TESTSUITE_AT = \ extrac09.at\ extrac10.at\ extrac11.at\ + extrac12.at\ filerem01.at\ filerem02.at\ gzip.at\ diff --git a/tests/extrac12.at b/tests/extrac12.at new file mode 100644 index 0000000..4c5962e --- /dev/null +++ b/tests/extrac12.at @@ -0,0 +1,39 @@ +# Process this file with autom4te to create testsuite. -*- Autotest -*- + +# Test suite for GNU tar. +# Copyright (C) 2010 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# written by Paul Eggert + +# Check that 'tar' extracts permissions on the working directory last. + +AT_SETUP([extract dot permissions]) +AT_KEYWORDS([extract extrac12]) + +AT_TAR_CHECK([ +mkdir src dst +echo file1 >src/file1 +echo file2 >src/file2 +chmod a-w src + +tar --no-recursion -cf archive.tar -C src . ./file1 file2 && +tar -xf archive.tar -C dst && +cmp src/file1 dst/file1 && +cmp src/file2 dst/file2 +], +[0],[],[],[],[],[gnu]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index 2b2bd6b..dc7a603 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -150,6 +150,7 @@ m4_include([extrac08.at]) m4_include([extrac09.at]) m4_include([extrac10.at]) m4_include([extrac11.at]) +m4_include([extrac12.at]) m4_include([label01.at]) m4_include([label02.at])