diff --git a/SOURCES/tar-1.26-directory_with_remove-files.patch b/SOURCES/tar-1.26-directory_with_remove-files.patch new file mode 100644 index 0000000..c622792 --- /dev/null +++ b/SOURCES/tar-1.26-directory_with_remove-files.patch @@ -0,0 +1,3501 @@ +From 4bf4efe97d25784eb5e56c8ee337af3c7866ec34 Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Tue, 24 Sep 2013 14:01:13 +0300 +Subject: [PATCH 01/11] Fix normalize_filename. + +The function did not take into account eventual -C options, which +in particular led to various problems when using -C and --remove-files +together. + +* src/common.h (namebuf_add_dir,namebuf_finish) +(tar_getcwd): New prototypes. +* src/misc.c (namebuf_add_dir,namebuf_finish) +(tar_getcwd): New functions. +(normalize_filename): Use tar_getcwd. +--- + src/common.h | 4 ++++ + src/misc.c | 41 ++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 44 insertions(+), 1 deletion(-) + +diff --git a/src/common.h b/src/common.h +index 16ba401..85a6977 100644 +--- a/src/common.h ++++ b/src/common.h +@@ -603,6 +603,10 @@ typedef struct namebuf *namebuf_t; + namebuf_t namebuf_create (const char *dir); + void namebuf_free (namebuf_t buf); + char *namebuf_name (namebuf_t buf, const char *name); ++void namebuf_add_dir (namebuf_t buf, const char *name); ++char *namebuf_finish (namebuf_t buf); ++ ++char *tar_getcwd (void); + + void code_ns_fraction (int ns, char *p); + char const *code_timespec (struct timespec ts, char *sbuf); +diff --git a/src/misc.c b/src/misc.c +index b75f2ab..f45f79a 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -283,7 +283,7 @@ normalize_filename (const char *name) + getcwd is slow, it might fail, and it does not necessarily + return a canonical name even when it succeeds. Perhaps we + can use dev+ino pairs instead of names? */ +- copy = xgetcwd (); ++ copy = tar_getcwd (); + if (copy) + { + size_t copylen = strlen (copy); +@@ -777,6 +777,21 @@ chdir_do (int i) + } + } + ++char * ++tar_getcwd (void) ++{ ++ static char *cwd; ++ namebuf_t nbuf; ++ int i; ++ ++ if (!cwd) ++ cwd = xgetcwd (); ++ nbuf = namebuf_create (cwd); ++ for (i = 1; i <= chdir_current; i++) ++ namebuf_add_dir (nbuf, wd[i].name); ++ return namebuf_finish (nbuf); ++} ++ + void + close_diag (char const *name) + { +@@ -945,3 +960,27 @@ namebuf_name (namebuf_t buf, const char *name) + + return ret; + } ++ ++void ++namebuf_add_dir (namebuf_t buf, const char *name) ++{ ++ static char dirsep[] = { DIRECTORY_SEPARATOR, 0 }; ++ if (!ISSLASH (buf->buffer[buf->dir_length - 1])) ++ { ++ namebuf_name (buf, dirsep); ++ buf->dir_length++; ++ } ++ namebuf_name (buf, name); ++ buf->dir_length += strlen (name); ++} ++ ++char * ++namebuf_finish (namebuf_t buf) ++{ ++ char *res = buf->buffer; ++ ++ if (ISSLASH (buf->buffer[buf->dir_length - 1])) ++ buf->buffer[buf->dir_length] = 0; ++ free (buf); ++ return res; ++} +-- +2.9.3 + + +From 272e1c879644b3684031acd62c9adb0adc5133b5 Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Wed, 25 Sep 2013 15:58:43 +0300 +Subject: [PATCH 02/11] Improve tar_getcwd + +* src/common.h (tar_getcwd): Return pointer is const. +* src/misc.c (wd) : New member. +(chdir_arg): Initialize cwd. +(tar_getcwd): Use cwd member to cache the result. Take into +account absolute pathnames, +(normalize_filename): Don't free the value +returned from tar_getcwd. +* src/names.c (name_next_elt): Remove leftover call chdir(). +* tests/Makefile.am: Add new tests. +* tests/testsuite.at: Likewise. + +* tests/incr08.at: New testcase. +* tests/remfiles04.at: New testcase. +* tests/remfiles05.at: New testcase. +* tests/remfiles06.at: New testcase. +* tests/remfiles07.at: New testcase. +--- + src/common.h | 2 +- + src/misc.c | 57 +++++++++++++++++++++++------------ + src/names.c | 3 +- + tests/Makefile.am | 5 ++++ + tests/incr08.at | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + tests/remfiles04.at | 53 +++++++++++++++++++++++++++++++++ + tests/remfiles05.at | 60 +++++++++++++++++++++++++++++++++++++ + tests/remfiles06.at | 66 ++++++++++++++++++++++++++++++++++++++++ + tests/remfiles07.at | 63 +++++++++++++++++++++++++++++++++++++++ + tests/testsuite.at | 5 ++++ + 10 files changed, 378 insertions(+), 22 deletions(-) + create mode 100644 tests/incr08.at + create mode 100644 tests/remfiles04.at + create mode 100644 tests/remfiles05.at + create mode 100644 tests/remfiles06.at + create mode 100644 tests/remfiles07.at + +diff --git a/src/common.h b/src/common.h +index 85a6977..99f8552 100644 +--- a/src/common.h ++++ b/src/common.h +@@ -606,7 +606,7 @@ char *namebuf_name (namebuf_t buf, const char *name); + void namebuf_add_dir (namebuf_t buf, const char *name); + char *namebuf_finish (namebuf_t buf); + +-char *tar_getcwd (void); ++const char *tar_getcwd (void); + + void code_ns_fraction (int ns, char *p); + char const *code_timespec (struct timespec ts, char *sbuf); +diff --git a/src/misc.c b/src/misc.c +index f45f79a..2fd5280 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -283,21 +283,20 @@ normalize_filename (const char *name) + getcwd is slow, it might fail, and it does not necessarily + return a canonical name even when it succeeds. Perhaps we + can use dev+ino pairs instead of names? */ +- copy = tar_getcwd (); +- if (copy) +- { +- size_t copylen = strlen (copy); +- bool need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT +- && copylen == 2 && ISSLASH (copy[1])); +- copy = xrealloc (copy, copylen + need_separator + strlen (name) + 1); +- copy[copylen] = DIRECTORY_SEPARATOR; +- strcpy (copy + copylen + need_separator, name); +- } +- else +- WARN ((0, errno, _("Cannot get working directory"))); ++ const char *cwd = tar_getcwd (); ++ size_t copylen; ++ bool need_separator; ++ ++ copylen = strlen (cwd); ++ need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT ++ && copylen == 2 && ISSLASH (cwd[1])); ++ copy = xmalloc (copylen + need_separator + strlen (name) + 1); ++ strcpy (copy, cwd); ++ copy[copylen] = DIRECTORY_SEPARATOR; ++ strcpy (copy + copylen + need_separator, name); + } + +- if (! copy) ++ if (!copy) + copy = xstrdup (name); + normalize_filename_x (copy); + return copy; +@@ -632,7 +631,8 @@ struct wd + { + /* The directory's name. */ + char const *name; +- ++ /* Current working directory; initialized by tar_getcwd */ ++ char *cwd; + /* If nonzero, the file descriptor of the directory, or AT_FDCWD if + the working directory. If zero, the directory needs to be opened + to be used. */ +@@ -687,6 +687,7 @@ chdir_arg (char const *dir) + if (! wd_count) + { + wd[wd_count].name = "."; ++ wd[wd_count].cwd = NULL; + wd[wd_count].fd = AT_FDCWD; + wd_count++; + } +@@ -704,6 +705,7 @@ chdir_arg (char const *dir) + } + + wd[wd_count].name = dir; ++ wd[wd_count].cwd = NULL; + wd[wd_count].fd = 0; + return wd_count++; + } +@@ -777,7 +779,7 @@ chdir_do (int i) + } + } + +-char * ++const char * + tar_getcwd (void) + { + static char *cwd; +@@ -786,10 +788,27 @@ tar_getcwd (void) + + if (!cwd) + cwd = xgetcwd (); +- nbuf = namebuf_create (cwd); +- for (i = 1; i <= chdir_current; i++) +- namebuf_add_dir (nbuf, wd[i].name); +- return namebuf_finish (nbuf); ++ if (!wd) ++ return cwd; ++ ++ if (0 == chdir_current || !wd[chdir_current].cwd) ++ { ++ if (IS_ABSOLUTE_FILE_NAME (wd[chdir_current].name)) ++ return wd[chdir_current].name; ++ ++ if (!wd[0].cwd) ++ wd[0].cwd = cwd; ++ ++ for (i = chdir_current - 1; i > 0; i--) ++ if (wd[i].cwd) ++ break; ++ ++ nbuf = namebuf_create (wd[i].cwd); ++ for (i++; i <= chdir_current; i++) ++ namebuf_add_dir (nbuf, wd[i].name); ++ wd[chdir_current].cwd = namebuf_finish (nbuf); ++ } ++ return wd[chdir_current].cwd; + } + + void +diff --git a/src/names.c b/src/names.c +index 3911f8c..8c3052f 100644 +--- a/src/names.c ++++ b/src/names.c +@@ -351,8 +351,7 @@ name_next_elt (int change_dirs) + + if (change_dirs && ep->type == NELT_CHDIR) + { +- if (chdir (name_buffer) < 0) +- chdir_fatal (name_buffer); ++ chdir_do (chdir_arg (xstrdup (ep->v.name))); + } + else + { +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 228e936..1d10360 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -99,6 +99,7 @@ TESTSUITE_AT = \ + incr05.at\ + incr06.at\ + incr07.at\ ++ incr08.at\ + indexfile.at\ + ignfail.at\ + label01.at\ +@@ -139,6 +140,10 @@ TESTSUITE_AT = \ + remfiles01.at\ + remfiles02.at\ + remfiles03.at\ ++ remfiles04.at\ ++ remfiles05.at\ ++ remfiles06.at\ ++ remfiles07.at\ + same-order01.at\ + same-order02.at\ + shortfile.at\ +diff --git a/tests/incr08.at b/tests/incr08.at +new file mode 100644 +index 0000000..5210d28 +--- /dev/null ++++ b/tests/incr08.at +@@ -0,0 +1,86 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: In tar 1.26 listed-incremental with -C and absolute path ++# would malfunction under certain conditions due to buggy filename ++# normalization. ++# ++# The value returned by normalize_filename() is used to populate the "caname" ++# field in both the "directory" structure in incremen.c and the "name" ++# structure in names.c, and in both cases that field is then used in the ++# "hash" and "compare" functions for the related hash tables. Thus, the ++# fact that the returned value doesn't reflect the operation of previous ++# "-C" options means that it's possible for two different directories to ++# be given the same "caname" value in the hashed structure and thus end up ++# being confused with each other. ++# ++# The bug is triggered when dumping both relative paths after -C and ++# absolute paths that match the process' current working directory. ++# ++# Reported by: Nathan Stratton Treadway ++# References: <20130922192135.GJ32256@shire.ontko.com>, ++# http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00034.html ++ ++AT_SETUP([filename normalization]) ++AT_KEYWORDS([incremental create incr08]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir tartest ++cd tartest ++mkdir foo ++mkdir foo/subdir ++mkdir foo/subdir/dir1 ++mkdir subdir ++mkdir subdir/dir2 ++decho A ++find|sort ++ ++decho B ++DIR=`pwd` ++tar -cvf ../foo.tar --listed-incremental=../foo.snar -C foo . $DIR 2>../err |\ ++ sed "s|$DIR|ABSPATH|" ++sed "s|$DIR|ABSPATH|" ../err >&2 ++], ++[0], ++[A ++. ++./foo ++./foo/subdir ++./foo/subdir/dir1 ++./subdir ++./subdir/dir2 ++B ++./ ++./subdir/ ++./subdir/dir1/ ++ABSPATH/ ++ABSPATH/subdir/ ++ABSPATH/subdir/dir2/ ++], ++[A ++B ++tar: .: Directory is new ++tar: ./subdir: Directory is new ++tar: ./subdir/dir1: Directory is new ++tar: ABSPATH: Directory is new ++tar: ABSPATH/subdir: Directory is new ++tar: ABSPATH/subdir/dir2: Directory is new ++tar: Removing leading `/' from member names ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles04.at b/tests/remfiles04.at +new file mode 100644 +index 0000000..04df45b +--- /dev/null ++++ b/tests/remfiles04.at +@@ -0,0 +1,53 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: Tar 1.26 would remove wrong files when called with ++# --remove-files and -C ++# Reported by: Jörgen Strand ++# References: <9FC79E5CB90CEC47B9647DCAB7BD327A01AD83B452EE@seldmbx02.corpusers.net> ++# http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00024.html ++ ++AT_SETUP([remove-files with -C]) ++AT_KEYWORDS([create remove-files remfiles04]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++echo bar > bar ++echo foobar > foo/bar ++tar -cf foo.tar --remove-files -C foo bar ++echo A ++find . | sort ++echo foobar > foo/bar ++tar -rf foo.tar --remove-files -C foo bar ++echo B ++find . | sort ++], ++[0], ++[A ++. ++./bar ++./foo ++./foo.tar ++B ++. ++./bar ++./foo ++./foo.tar ++],[],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles05.at b/tests/remfiles05.at +new file mode 100644 +index 0000000..04425a7 +--- /dev/null ++++ b/tests/remfiles05.at +@@ -0,0 +1,60 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: Tar 1.26 would remove wrong files when invoked with ++# --listed-incremental and -C ++# Reported by: Nathan Stratton Treadway ++# References: <20130921171234.GG32256@shire.ontko.com>, ++# http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00028.html ++ ++AT_SETUP([incremental and -C]) ++AT_KEYWORDS([incremental create remove-files remfiles05]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++echo bar > bar ++echo foo/bar > foo/bar ++decho A ++find . | sort ++ ++decho B ++tar -cvf foo.tar --listed-incremental=foo.snar --remove-files -C foo bar ++decho C ++find . | sort ++], ++[0], ++[A ++. ++./bar ++./foo ++./foo/bar ++B ++bar ++C ++. ++./bar ++./foo ++./foo.snar ++./foo.tar ++], ++[A ++B ++C ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles06.at b/tests/remfiles06.at +new file mode 100644 +index 0000000..75ddcfa +--- /dev/null ++++ b/tests/remfiles06.at +@@ -0,0 +1,66 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: There was a leftover call to chdir in name_next_elt() in ++# tar 1.26. After commit e3d28d84 this call would confuse the tar_getcwd ++# function. ++# Reported by: Nathan Stratton Treadway ++# References: <20130924145657.GM32256@shire.ontko.com>, ++# http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00045.html ++ ++AT_SETUP([incremental with two -C]) ++AT_KEYWORDS([incremental create remove-files remfiles06]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir tartest ++cd tartest ++mkdir foo ++echo foo/file > foo/file ++mkdir bar ++echo bar/file > bar/file ++decho A ++find|sort ++ ++decho B ++tar -cvf ../foo.tar --remove-files -C foo file -C ../bar file ++ ++decho C ++find|sort ++], ++[0], ++[A ++. ++./bar ++./bar/file ++./foo ++./foo/file ++B ++file ++file ++C ++. ++./bar ++./foo ++], ++[A ++B ++C ++],[],[],[gnu]) ++ ++AT_CLEANUP ++ +diff --git a/tests/remfiles07.at b/tests/remfiles07.at +new file mode 100644 +index 0000000..84ab625 +--- /dev/null ++++ b/tests/remfiles07.at +@@ -0,0 +1,63 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: See remfiles06.at ++# Reported by: Nathan Stratton Treadway ++# References: <20130924185129.GO32256@shire.ontko.com> ++ ++AT_SETUP([incremental with -C to absolute path]) ++AT_KEYWORDS([incremental create remove-files remfiles07]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir tartest ++cd tartest ++mkdir foo ++echo foo/file > foo/file ++mkdir bar ++echo bar/file > bar/file ++decho A ++find|sort ++ ++DIR=`pwd` ++decho B ++tar -cvf ../foo.tar --remove-files -C foo file -C $DIR/bar file ++ ++decho C ++find|sort ++], ++[0], ++[A ++. ++./bar ++./bar/file ++./foo ++./foo/file ++B ++file ++file ++C ++. ++./bar ++./foo ++], ++[A ++B ++C ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/testsuite.at b/tests/testsuite.at +index 10cf26a..5c805e7 100644 +--- a/tests/testsuite.at ++++ b/tests/testsuite.at +@@ -260,6 +260,7 @@ m4_include([incr03.at]) + m4_include([incr05.at]) + m4_include([incr06.at]) + m4_include([incr07.at]) ++m4_include([incr08.at]) + + m4_include([filerem01.at]) + m4_include([filerem02.at]) +@@ -330,6 +331,10 @@ m4_include([grow.at]) + m4_include([remfiles01.at]) + m4_include([remfiles02.at]) + m4_include([remfiles03.at]) ++m4_include([remfiles04.at]) ++m4_include([remfiles05.at]) ++m4_include([remfiles06.at]) ++m4_include([remfiles07.at]) + + m4_include([sigpipe.at]) + +-- +2.9.3 + + +From 0c5f95ca80d507a00825c8e3fd05ed5ad993ce17 Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Thu, 26 Sep 2013 15:41:47 +0300 +Subject: [PATCH 03/11] Use relative addressing in deferred unlinks. + +* src/common.h (tar_dirname): New function. +* src/misc.c (normalize_filename_x): Make extern. +(tar_dirname): New function. +(tar_getcwd): Take into account absoulte pathnames. +* src/unlink.c (deferred_unlink) : New member; keeps the +value of chdir_current at the moment of structure allocation. +(flush_deferred_unlinks): Use chdir_do and relative addressing. +(queue_deferred_unlink): Initialize dir_idx. +* tests/Makefile.am: Add new tests. +* tests/testsuite.at: Add new tests. +* tests/remfiles06.at: Fix description. +* tests/remfiles07.at: Fix description. +* tests/remfiles08.at: New test case. +--- + src/common.h | 2 ++ + src/misc.c | 28 +++++++++++++++++++--------- + src/unlink.c | 27 +++++++++++++++++++++++---- + tests/Makefile.am | 1 + + tests/remfiles06.at | 4 ++-- + tests/remfiles07.at | 4 ++-- + tests/remfiles08.at | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ + tests/testsuite.at | 1 + + 8 files changed, 98 insertions(+), 17 deletions(-) + create mode 100644 tests/remfiles08.at + +diff --git a/src/common.h b/src/common.h +index 99f8552..7d64227 100644 +--- a/src/common.h ++++ b/src/common.h +@@ -596,6 +596,7 @@ void assign_string (char **dest, const char *src); + int unquote_string (char *str); + char *zap_slashes (char *name); + char *normalize_filename (const char *name); ++void normalize_filename_x (char *name); + void replace_prefix (char **pname, const char *samp, size_t slen, + const char *repl, size_t rlen); + char *tar_savedir (const char *name, int must_exist); +@@ -607,6 +608,7 @@ void namebuf_add_dir (namebuf_t buf, const char *name); + char *namebuf_finish (namebuf_t buf); + + const char *tar_getcwd (void); ++const char *tar_dirname (void); + + void code_ns_fraction (int ns, char *p); + char const *code_timespec (struct timespec ts, char *sbuf); +diff --git a/src/misc.c b/src/misc.c +index 2fd5280..c7d51b2 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -229,11 +229,12 @@ zap_slashes (char *name) + } + + /* Normalize FILE_NAME by removing redundant slashes and "." +- components, including redundant trailing slashes. Leave ".." +- alone, as it may be significant in the presence of symlinks and on +- platforms where "/.." != "/". Destructive version: modifies its +- argument. */ +-static void ++ components, including redundant trailing slashes. ++ Leave ".." alone, as it may be significant in the presence ++ of symlinks and on platforms where "/.." != "/". ++ ++ Destructive version: modifies its argument. */ ++void + normalize_filename_x (char *file_name) + { + char *name = file_name + FILE_SYSTEM_PREFIX_LEN (file_name); +@@ -267,8 +268,9 @@ normalize_filename_x (char *file_name) + } + + /* Normalize NAME by removing redundant slashes and "." components, +- including redundant trailing slashes. Return a normalized +- newly-allocated copy. */ ++ including redundant trailing slashes. ++ ++ Return a normalized newly-allocated copy. */ + + char * + normalize_filename (const char *name) +@@ -780,6 +782,12 @@ chdir_do (int i) + } + + const char * ++tar_dirname (void) ++{ ++ return wd[chdir_current].name; ++} ++ ++const char * + tar_getcwd (void) + { + static char *cwd; +@@ -794,8 +802,10 @@ tar_getcwd (void) + if (0 == chdir_current || !wd[chdir_current].cwd) + { + if (IS_ABSOLUTE_FILE_NAME (wd[chdir_current].name)) +- return wd[chdir_current].name; +- ++ { ++ wd[chdir_current].cwd = xstrdup (wd[chdir_current].name); ++ return wd[chdir_current].cwd; ++ } + if (!wd[0].cwd) + wd[0].cwd = cwd; + +diff --git a/src/unlink.c b/src/unlink.c +index b281636..10e0b41 100644 +--- a/src/unlink.c ++++ b/src/unlink.c +@@ -22,7 +22,9 @@ + struct deferred_unlink + { + struct deferred_unlink *next; /* Next unlink in the queue */ +- char *file_name; /* Absolute name of the file to unlink */ ++ int dir_idx; /* Directory index in wd */ ++ char *file_name; /* Name of the file to unlink, relative ++ to dir_idx */ + bool is_dir; /* True if file_name is a directory */ + off_t records_written; /* Number of records written when this + entry got added to the queue */ +@@ -68,16 +70,30 @@ static void + flush_deferred_unlinks (bool force) + { + struct deferred_unlink *p, *prev = NULL; ++ int saved_chdir = chdir_current; + + for (p = dunlink_head; p; ) + { + struct deferred_unlink *next = p->next; ++ + if (force + || records_written > p->records_written + deferred_unlink_delay) + { ++ chdir_do (p->dir_idx); + if (p->is_dir) + { +- if (unlinkat (chdir_fd, p->file_name, AT_REMOVEDIR) != 0) ++ const char *fname; ++ ++ if (p->file_name[0] == 0 || ++ strcmp (p->file_name, ".") == 0) ++ { ++ fname = tar_dirname (); ++ chdir_do (p->dir_idx - 1); ++ } ++ else ++ fname = p->file_name; ++ ++ if (unlinkat (chdir_fd, fname, AT_REMOVEDIR) != 0) + { + switch (errno) + { +@@ -95,7 +111,7 @@ flush_deferred_unlinks (bool force) + } + /* fall through */ + default: +- rmdir_error (p->file_name); ++ rmdir_error (fname); + } + } + } +@@ -120,6 +136,7 @@ flush_deferred_unlinks (bool force) + } + if (!dunlink_head) + dunlink_tail = NULL; ++ chdir_do (saved_chdir); + } + + void +@@ -145,7 +162,9 @@ queue_deferred_unlink (const char *name, bool is_dir) + + p = dunlink_alloc (); + p->next = NULL; +- p->file_name = normalize_filename (name); ++ p->dir_idx = chdir_current; ++ p->file_name = xstrdup (name); ++ normalize_filename_x (p->file_name); + p->is_dir = is_dir; + p->records_written = records_written; + +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 1d10360..29ebab1 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -144,6 +144,7 @@ TESTSUITE_AT = \ + remfiles05.at\ + remfiles06.at\ + remfiles07.at\ ++ remfiles08.at\ + same-order01.at\ + same-order02.at\ + shortfile.at\ +diff --git a/tests/remfiles06.at b/tests/remfiles06.at +index 75ddcfa..c2d9876 100644 +--- a/tests/remfiles06.at ++++ b/tests/remfiles06.at +@@ -22,8 +22,8 @@ + # References: <20130924145657.GM32256@shire.ontko.com>, + # http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00045.html + +-AT_SETUP([incremental with two -C]) +-AT_KEYWORDS([incremental create remove-files remfiles06]) ++AT_SETUP([remove with two -C]) ++AT_KEYWORDS([remove-files remfiles06]) + + AT_TAR_CHECK([ + AT_SORT_PREREQ +diff --git a/tests/remfiles07.at b/tests/remfiles07.at +index 84ab625..742e0a1 100644 +--- a/tests/remfiles07.at ++++ b/tests/remfiles07.at +@@ -19,8 +19,8 @@ + # Reported by: Nathan Stratton Treadway + # References: <20130924185129.GO32256@shire.ontko.com> + +-AT_SETUP([incremental with -C to absolute path]) +-AT_KEYWORDS([incremental create remove-files remfiles07]) ++AT_SETUP([remove with -C to absolute path]) ++AT_KEYWORDS([create remove-files remfiles07]) + + AT_TAR_CHECK([ + AT_SORT_PREREQ +diff --git a/tests/remfiles08.at b/tests/remfiles08.at +new file mode 100644 +index 0000000..54f5de1 +--- /dev/null ++++ b/tests/remfiles08.at +@@ -0,0 +1,48 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: See remfiles06.at ++# Reported by: Nathan Stratton Treadway ++# References: <20130926050634.GW32256@shire.ontko.com> ++ ++AT_SETUP([remove with -C to absolute and relative paths]) ++AT_KEYWORDS([incremental create remove-files remfiles08]) ++ ++AT_TAR_CHECK([ ++mkdir foo ++mkdir bar ++echo foo/foo_file > foo/foo_file ++echo bar/bar_file > bar/bar_file ++decho A ++tar -cvf foo.tar --remove-files -C `pwd`/foo . -C ../bar . ++decho B ++], ++[0], ++[A ++./ ++./foo_file ++./ ++./bar_file ++B ++. ++./foo.tar ++], ++[A ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/testsuite.at b/tests/testsuite.at +index 5c805e7..d468dcf 100644 +--- a/tests/testsuite.at ++++ b/tests/testsuite.at +@@ -335,6 +335,7 @@ m4_include([remfiles04.at]) + m4_include([remfiles05.at]) + m4_include([remfiles06.at]) + m4_include([remfiles07.at]) ++m4_include([remfiles08.at]) + + m4_include([sigpipe.at]) + +-- +2.9.3 + + +From 195c6f2b71f49ecc374ae01e20d7287f24501178 Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Fri, 27 Sep 2013 00:59:18 +0300 +Subject: [PATCH 04/11] Bugfix + +* tests/remfiles08.at: Restore missing find +--- + tests/remfiles08.at | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/remfiles08.at b/tests/remfiles08.at +index 54f5de1..0649e85 100644 +--- a/tests/remfiles08.at ++++ b/tests/remfiles08.at +@@ -30,6 +30,7 @@ echo bar/bar_file > bar/bar_file + decho A + tar -cvf foo.tar --remove-files -C `pwd`/foo . -C ../bar . + decho B ++find + ], + [0], + [A +-- +2.9.3 + + +From 2cce74ec554ec7fca4c3b1d2963beb6a729881fe Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Tue, 1 Oct 2013 21:48:30 +0300 +Subject: [PATCH 05/11] Revamp tar_getcwd/normalize_filename stuff. + +The changes are based on the discussion with Nathan. + +* src/common.h (normalize_filename): Take two arguments. All +callers updated. +(tar_getcwd): Replaced with .. +(tar_getcdpath): New proto. +* src/misc.c (normalize_filename): Take two arguments. +(chdir_arg): Populate cwd along with creating the +structure. +(tar_getcwd): Removed. +(tar_getcdpath): New function. + +* tests/incr09.at: New test case. +* tests/Makefile.am: Add new tests. +* tests/testsuite.at: Likewise. +--- + src/common.h | 4 ++-- + src/incremen.c | 4 ++-- + src/misc.c | 48 ++++++++++++++++---------------------------- + src/names.c | 6 ++---- + tests/Makefile.am | 1 + + tests/incr09.at | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + tests/testsuite.at | 1 + + 7 files changed, 84 insertions(+), 39 deletions(-) + create mode 100644 tests/incr09.at + +diff --git a/src/common.h b/src/common.h +index 7d64227..16b501b 100644 +--- a/src/common.h ++++ b/src/common.h +@@ -595,7 +595,7 @@ void skip_member (void); + void assign_string (char **dest, const char *src); + int unquote_string (char *str); + char *zap_slashes (char *name); +-char *normalize_filename (const char *name); ++char *normalize_filename (int cdidx, const char *name); + void normalize_filename_x (char *name); + void replace_prefix (char **pname, const char *samp, size_t slen, + const char *repl, size_t rlen); +@@ -607,7 +607,7 @@ char *namebuf_name (namebuf_t buf, const char *name); + void namebuf_add_dir (namebuf_t buf, const char *name); + char *namebuf_finish (namebuf_t buf); + +-const char *tar_getcwd (void); ++const char *tar_getcdpath (int); + const char *tar_dirname (void); + + void code_ns_fraction (int ns, char *p); +diff --git a/src/incremen.c b/src/incremen.c +index b2ab5bf..cb12bbc 100644 +--- a/src/incremen.c ++++ b/src/incremen.c +@@ -279,7 +279,7 @@ free_directory (struct directory *dir) + static struct directory * + attach_directory (const char *name) + { +- char *cname = normalize_filename (name); ++ char *cname = normalize_filename (chdir_current, name); + struct directory *dir = make_directory (name, cname); + if (dirtail) + dirtail->next = dir; +@@ -350,7 +350,7 @@ find_directory (const char *name) + return 0; + else + { +- char *caname = normalize_filename (name); ++ char *caname = normalize_filename (chdir_current, name); + struct directory *dir = make_directory (name, caname); + struct directory *ret = hash_lookup (directory_table, dir); + free_directory (dir); +diff --git a/src/misc.c b/src/misc.c +index c7d51b2..280f85c 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -273,7 +273,7 @@ normalize_filename_x (char *file_name) + Return a normalized newly-allocated copy. */ + + char * +-normalize_filename (const char *name) ++normalize_filename (int cdidx, const char *name) + { + char *copy = NULL; + +@@ -285,7 +285,7 @@ normalize_filename (const char *name) + getcwd is slow, it might fail, and it does not necessarily + return a canonical name even when it succeeds. Perhaps we + can use dev+ino pairs instead of names? */ +- const char *cwd = tar_getcwd (); ++ const char *cwd = tar_getcdpath (cdidx); + size_t copylen; + bool need_separator; + +@@ -689,7 +689,7 @@ chdir_arg (char const *dir) + if (! wd_count) + { + wd[wd_count].name = "."; +- wd[wd_count].cwd = NULL; ++ wd[wd_count].cwd = xgetcwd (); + wd[wd_count].fd = AT_FDCWD; + wd_count++; + } +@@ -707,7 +707,14 @@ chdir_arg (char const *dir) + } + + wd[wd_count].name = dir; +- wd[wd_count].cwd = NULL; ++ if (IS_ABSOLUTE_FILE_NAME (wd[wd_count].name)) ++ wd[wd_count].cwd = xstrdup (wd[wd_count].name); ++ else ++ { ++ namebuf_t nbuf = namebuf_create (wd[wd_count - 1].cwd); ++ namebuf_add_dir (nbuf, wd[wd_count].name); ++ wd[wd_count].cwd = namebuf_finish (nbuf); ++ } + wd[wd_count].fd = 0; + return wd_count++; + } +@@ -788,37 +795,16 @@ tar_dirname (void) + } + + const char * +-tar_getcwd (void) ++tar_getcdpath (int idx) + { +- static char *cwd; +- namebuf_t nbuf; +- int i; +- +- if (!cwd) +- cwd = xgetcwd (); + if (!wd) +- return cwd; +- +- if (0 == chdir_current || !wd[chdir_current].cwd) + { +- if (IS_ABSOLUTE_FILE_NAME (wd[chdir_current].name)) +- { +- wd[chdir_current].cwd = xstrdup (wd[chdir_current].name); +- return wd[chdir_current].cwd; +- } +- if (!wd[0].cwd) +- wd[0].cwd = cwd; +- +- for (i = chdir_current - 1; i > 0; i--) +- if (wd[i].cwd) +- break; +- +- nbuf = namebuf_create (wd[i].cwd); +- for (i++; i <= chdir_current; i++) +- namebuf_add_dir (nbuf, wd[i].name); +- wd[chdir_current].cwd = namebuf_finish (nbuf); ++ static char *cwd; ++ if (!cwd) ++ cwd = xgetcwd (); ++ return cwd; + } +- return wd[chdir_current].cwd; ++ return wd[idx].cwd; + } + + void +diff --git a/src/names.c b/src/names.c +index 8c3052f..125f0b5 100644 +--- a/src/names.c ++++ b/src/names.c +@@ -1004,13 +1004,11 @@ collect_and_sort_names (void) + namelist = merge_sort (namelist, num_names, compare_names); + + num_names = 0; +- nametab = hash_initialize (0, 0, +- name_hash, +- name_compare, NULL); ++ nametab = hash_initialize (0, 0, name_hash, name_compare, NULL); + for (name = namelist; name; name = next_name) + { + next_name = name->next; +- name->caname = normalize_filename (name->name); ++ name->caname = normalize_filename (name->change_dir, name->name); + if (prev_name) + { + struct name *p = hash_lookup (nametab, name); +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 29ebab1..b05a151 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -99,6 +99,7 @@ TESTSUITE_AT = \ + incr06.at\ + incr07.at\ + incr08.at\ ++ incr09.at\ + indexfile.at\ + ignfail.at\ + label01.at\ +diff --git a/tests/incr09.at b/tests/incr09.at +new file mode 100644 +index 0000000..b6130a6 +--- /dev/null ++++ b/tests/incr09.at +@@ -0,0 +1,59 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++AT_SETUP([incremental with alternating -C]) ++AT_KEYWORDS([incremental create incr09]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo bar middle ++echo foo/foo_file > foo/foo_file ++echo bar/bar_file > bar/bar_file ++echo middle/file > middle/middle_file ++decho A ++tar -cvf foo.tar --incremental -C foo . -C `pwd` middle -C bar . ++ ++rm foo.tar ++>toplevel_file ++decho B ++tar -cvf foo.tar --incremental -C foo . -C `pwd` toplevel_file -C bar . ++], ++[0], ++[A ++./ ++./ ++middle/ ++./bar_file ++./foo_file ++middle/middle_file ++B ++./ ++./ ++toplevel_file ++./bar_file ++./foo_file ++], ++[A ++tar: .: Directory is new ++tar: middle: Directory is new ++tar: .: Directory is new ++B ++tar: .: Directory is new ++tar: .: Directory is new ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/testsuite.at b/tests/testsuite.at +index d468dcf..a9f2ab6 100644 +--- a/tests/testsuite.at ++++ b/tests/testsuite.at +@@ -260,6 +260,7 @@ m4_include([incr04.at]) + m4_include([incr06.at]) + m4_include([incr07.at]) + m4_include([incr08.at]) ++m4_include([incr09.at]) + + m4_include([filerem01.at]) + m4_include([filerem02.at]) +-- +2.9.3 + + +From 779b02280a9561029d0e459275af3b3a59e521c3 Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Thu, 3 Oct 2013 22:41:04 +0300 +Subject: [PATCH 06/11] Tiny changes. + +* src/misc.c: Fix comments, rename wd.cwd to wd.abspath (Nathan Stratton +Treadway); +* src/tar.c (options): Reword description of the --starting-file and +--preserve-order options. +(decode_options): Both --starting-file and --preserve-order have meaning +only when used together with an archive reading command. (Pavel Raiskup). +--- + src/misc.c | 44 +++++++++++++++++++++++++++++--------------- + src/tar.c | 5 +++-- + 2 files changed, 32 insertions(+), 17 deletions(-) + +diff --git a/src/misc.c b/src/misc.c +index 280f85c..201ed16 100644 +--- a/src/misc.c ++++ b/src/misc.c +@@ -279,21 +279,23 @@ normalize_filename (int cdidx, const char *name) + + if (IS_RELATIVE_FILE_NAME (name)) + { +- /* Set COPY to the absolute file name if possible. ++ /* Set COPY to the absolute path for this name. + + FIXME: There should be no need to get the absolute file name. +- getcwd is slow, it might fail, and it does not necessarily +- return a canonical name even when it succeeds. Perhaps we +- can use dev+ino pairs instead of names? */ +- const char *cwd = tar_getcdpath (cdidx); ++ tar_getcdpath does not return a true "canonical" path, so ++ this following approach may lead to situations where the same ++ file or directory is processed twice under different absolute ++ paths without that duplication being detected. Perhaps we ++ should use dev+ino pairs instead of names? */ ++ const char *cdpath = tar_getcdpath (cdidx); + size_t copylen; + bool need_separator; + +- copylen = strlen (cwd); ++ copylen = strlen (cdpath); + need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT +- && copylen == 2 && ISSLASH (cwd[1])); ++ && copylen == 2 && ISSLASH (cdpath[1])); + copy = xmalloc (copylen + need_separator + strlen (name) + 1); +- strcpy (copy, cwd); ++ strcpy (copy, cdpath); + copy[copylen] = DIRECTORY_SEPARATOR; + strcpy (copy + copylen + need_separator, name); + } +@@ -633,8 +635,10 @@ struct wd + { + /* The directory's name. */ + char const *name; +- /* Current working directory; initialized by tar_getcwd */ +- char *cwd; ++ /* "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). */ ++ char *abspath; + /* If nonzero, the file descriptor of the directory, or AT_FDCWD if + the working directory. If zero, the directory needs to be opened + to be used. */ +@@ -689,7 +693,7 @@ chdir_arg (char const *dir) + if (! wd_count) + { + wd[wd_count].name = "."; +- wd[wd_count].cwd = xgetcwd (); ++ wd[wd_count].abspath = xgetcwd (); + wd[wd_count].fd = AT_FDCWD; + wd_count++; + } +@@ -707,13 +711,16 @@ chdir_arg (char const *dir) + } + + wd[wd_count].name = dir; ++ /* if the given name is an absolute path, then use that path ++ to represent this working directory; otherwise, construct ++ a path based on the previous -C option's absolute path */ + if (IS_ABSOLUTE_FILE_NAME (wd[wd_count].name)) +- wd[wd_count].cwd = xstrdup (wd[wd_count].name); ++ wd[wd_count].abspath = xstrdup (wd[wd_count].name); + else + { +- namebuf_t nbuf = namebuf_create (wd[wd_count - 1].cwd); ++ namebuf_t nbuf = namebuf_create (wd[wd_count - 1].abspath); + namebuf_add_dir (nbuf, wd[wd_count].name); +- wd[wd_count].cwd = namebuf_finish (nbuf); ++ wd[wd_count].abspath = namebuf_finish (nbuf); + } + wd[wd_count].fd = 0; + return wd_count++; +@@ -794,6 +801,13 @@ tar_dirname (void) + return wd[chdir_current].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 ++ process's actual cwd. (Note that in this case IDX is ignored, ++ since it should always be 0.) */ + const char * + tar_getcdpath (int idx) + { +@@ -804,7 +818,7 @@ tar_getcdpath (int idx) + cwd = xgetcwd (); + return cwd; + } +- return wd[idx].cwd; ++ return wd[idx].abspath; + } + + void +diff --git a/src/tar.c b/src/tar.c +index 18277e4..d11daa1 100644 +--- a/src/tar.c ++++ b/src/tar.c +@@ -536,7 +536,8 @@ static struct argp_option options[] = { + {"no-same-permissions", NO_SAME_PERMISSIONS_OPTION, 0, 0, + N_("apply the user's umask when extracting permissions from the archive (default for ordinary users)"), GRID+1 }, + {"preserve-order", 's', 0, 0, +- N_("sort names to extract to match archive"), GRID+1 }, ++ N_("member arguments are listed in the same order as the " ++ "files in the archive"), GRID+1 }, + {"same-order", 0, 0, OPTION_ALIAS, NULL, GRID+1 }, + {"preserve", PRESERVE_OPTION, 0, 0, + N_("same as both -p and -s"), GRID+1 }, +@@ -730,7 +731,7 @@ static struct argp_option options[] = { + {"hard-dereference", HARD_DEREFERENCE_OPTION, 0, 0, + N_("follow hard links; archive and dump the files they refer to"), GRID+1 }, + {"starting-file", 'K', N_("MEMBER-NAME"), 0, +- N_("begin at member MEMBER-NAME in the archive"), GRID+1 }, ++ N_("begin at member MEMBER-NAME when reading the archive"), GRID+1 }, + {"newer", 'N', N_("DATE-OR-FILE"), 0, + N_("only store files newer than DATE-OR-FILE"), GRID+1 }, + {"after-date", 0, 0, OPTION_ALIAS, NULL, GRID+1 }, +-- +2.9.3 + + +From 79f04038e17dec01031113f4ba68f291f22012c3 Mon Sep 17 00:00:00 2001 +From: Nathan Stratton Treadway +Date: Sat, 5 Oct 2013 08:53:08 +0300 +Subject: [PATCH 07/11] Provide comprehensive testcases for various file + removal modes. + +* tests/Makefile.am: Add new testcases. +* tests/testsuite.at: Likewise. +* tests/incr09.at: Add description. +* tests/remfiles04a.at: New file. +* tests/remfiles05.at: Rename to ... +* tests/remfiles04b.at: ... this. +* tests/remfiles04.at: Rename to ... +* tests/remfiles04c.at: ... this. +* tests/remfiles05a.at: New file. +* tests/remfiles05b.at: New file. +* tests/remfiles06.at: Rename to ... +* tests/remfiles05c.at: ... this. +* tests/remfiles06a.at: New file. +* tests/remfiles06b.at: New file. +* tests/remfiles06c.at: New file. +* tests/remfiles07a.at: New file. +* tests/remfiles07b.at: New file. +* tests/remfiles07c.at: New file. +* tests/remfiles08a.at: New file. +* tests/remfiles08b.at: New file. +* tests/remfiles08c.at: New file. +* tests/remfiles08.at: Rename to ... +* tests/remfiles09a.at: ... this. +* tests/remfiles09b.at: New file. +* tests/remfiles07.at: Rename to ... +* tests/remfiles09c.at: ... this. +--- + tests/Makefile.am | 23 ++++++++--- + tests/incr09.at | 8 ++++ + tests/remfiles04a.at | 45 ++++++++++++++++++++++ + tests/remfiles04b.at | 53 +++++++++++++++++++++++++ + tests/{remfiles04.at => remfiles04c.at} | 21 +++++++--- + tests/remfiles05a.at | 64 +++++++++++++++++++++++++++++++ + tests/remfiles05b.at | 55 ++++++++++++++++++++++++++ + tests/{remfiles05.at => remfiles05c.at} | 35 ++++++++++------- + tests/remfiles06.at | 65 ------------------------------- + tests/remfiles06a.at | 56 +++++++++++++++++++++++++++ + tests/remfiles06b.at | 56 +++++++++++++++++++++++++++ + tests/remfiles06c.at | 68 +++++++++++++++++++++++++++++++++ + tests/remfiles07a.at | 56 +++++++++++++++++++++++++++ + tests/remfiles07b.at | 56 +++++++++++++++++++++++++++ + tests/remfiles07c.at | 68 +++++++++++++++++++++++++++++++++ + tests/remfiles08a.at | 56 +++++++++++++++++++++++++++ + tests/remfiles08b.at | 56 +++++++++++++++++++++++++++ + tests/remfiles08c.at | 68 +++++++++++++++++++++++++++++++++ + tests/{remfiles08.at => remfiles09a.at} | 27 +++++++------ + tests/remfiles09b.at | 57 +++++++++++++++++++++++++++ + tests/{remfiles07.at => remfiles09c.at} | 37 ++++++++---------- + tests/testsuite.at | 23 ++++++++--- + 22 files changed, 923 insertions(+), 130 deletions(-) + create mode 100644 tests/remfiles04a.at + create mode 100644 tests/remfiles04b.at + rename tests/{remfiles04.at => remfiles04c.at} (69%) + create mode 100644 tests/remfiles05a.at + create mode 100644 tests/remfiles05b.at + rename tests/{remfiles05.at => remfiles05c.at} (63%) + create mode 100644 tests/remfiles06a.at + create mode 100644 tests/remfiles06b.at + create mode 100644 tests/remfiles06c.at + create mode 100644 tests/remfiles07a.at + create mode 100644 tests/remfiles07b.at + create mode 100644 tests/remfiles07c.at + create mode 100644 tests/remfiles08a.at + create mode 100644 tests/remfiles08b.at + create mode 100644 tests/remfiles08c.at + rename tests/{remfiles08.at => remfiles09a.at} (66%) + create mode 100644 tests/remfiles09b.at + rename tests/{remfiles07.at => remfiles09c.at} (68%) + +diff --git a/tests/Makefile.am b/tests/Makefile.am +index b05a151..cf6f576 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -141,11 +141,24 @@ TESTSUITE_AT = \ + remfiles01.at\ + remfiles02.at\ + remfiles03.at\ +- remfiles04.at\ +- remfiles05.at\ +- remfiles06.at\ +- remfiles07.at\ +- remfiles08.at\ ++ remfiles04a.at\ ++ remfiles04b.at\ ++ remfiles04c.at\ ++ remfiles05a.at\ ++ remfiles05b.at\ ++ remfiles05c.at\ ++ remfiles06a.at\ ++ remfiles06b.at\ ++ remfiles06c.at\ ++ remfiles07a.at\ ++ remfiles07b.at\ ++ remfiles07c.at\ ++ remfiles08a.at\ ++ remfiles08b.at\ ++ remfiles08c.at\ ++ remfiles09a.at\ ++ remfiles09b.at\ ++ remfiles09c.at\ + same-order01.at\ + same-order02.at\ + shortfile.at\ +diff --git a/tests/incr09.at b/tests/incr09.at +index b6130a6..e91fb5a 100644 +--- a/tests/incr09.at ++++ b/tests/incr09.at +@@ -15,6 +15,14 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + ++# Description: For some intermediate versions of tar 1.26.90, ++# tar would fail to correctly cannonicalize archive member names ++# in incremental mode if there was a -C options with an absolute path ++# on the command line without any archive members specified within that ++# directory. (In that case, the canonical name generated for ++# members specified after later -C options wouldn't correctly reflect the ++# previous absolute path.) ++ + AT_SETUP([incremental with alternating -C]) + AT_KEYWORDS([incremental create incr09]) + +diff --git a/tests/remfiles04a.at b/tests/remfiles04a.at +new file mode 100644 +index 0000000..d1e4614 +--- /dev/null ++++ b/tests/remfiles04a.at +@@ -0,0 +1,45 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of a single relative-path -C option, ++# in --create/non-incremental mode. ++# ++ ++AT_SETUP([remove-files with -C:rel in -c/non-incr. mode]) ++AT_KEYWORDS([create remove-files remfiles04 remfiles04a]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++echo bar > bar ++echo foobar > foo/bar ++tar -cf foo.tar --remove-files -C foo bar ++echo A ++find . | sort ++], ++[0], ++[A ++. ++./bar ++./foo ++./foo.tar ++],[],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles04b.at b/tests/remfiles04b.at +new file mode 100644 +index 0000000..3208557 +--- /dev/null ++++ b/tests/remfiles04b.at +@@ -0,0 +1,53 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of a single relative-path -C option, ++# in --create/incremental mode. ++# ++# (Tar 1.26 would remove files in original working directory when called in ++# this manner. [It would follow the -C for archiving the files, but ignore it ++# for removing them afterwards.] ++# ++# Reported by: Nathan Stratton Treadway ++# References: <20130921171234.GG32256@shire.ontko.com>, ++# http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00028.html ++# ) ++ ++AT_SETUP([remove-files with -C:rel in -c/incr. mode]) ++AT_KEYWORDS([create incremental remove-files remfiles04 remfiles04b]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++echo bar > bar ++echo foobar > foo/bar ++tar -cf foo.tar --incremental --remove-files -C foo bar ++echo A ++find . | sort ++], ++[0], ++[A ++. ++./bar ++./foo ++./foo.tar ++],[],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles04.at b/tests/remfiles04c.at +similarity index 69% +rename from tests/remfiles04.at +rename to tests/remfiles04c.at +index 04df45b..a1b6d56 100644 +--- a/tests/remfiles04.at ++++ b/tests/remfiles04c.at +@@ -15,24 +15,32 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-# Description: Tar 1.26 would remove wrong files when called with +-# --remove-files and -C ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of a single relative-path -C option, ++# in --append mode. ++# ++# (Tar 1.26 would remove files in original working directory when called in ++# this manner. [It would follow the -C for archiving the files, but ignore it ++# for removing them afterwards.] ++# + # Reported by: Jörgen Strand + # References: <9FC79E5CB90CEC47B9647DCAB7BD327A01AD83B452EE@seldmbx02.corpusers.net> + # http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00024.html ++# ) + +-AT_SETUP([remove-files with -C]) +-AT_KEYWORDS([create remove-files remfiles04]) ++AT_SETUP([remove-files with -C:rel in -r mode]) ++AT_KEYWORDS([create append remove-files remfiles04 remfiles04c]) + + AT_TAR_CHECK([ + AT_SORT_PREREQ + mkdir foo + echo bar > bar + echo foobar > foo/bar +-tar -cf foo.tar --remove-files -C foo bar ++tar -cf foo.tar -C foo bar + echo A + find . | sort +-echo foobar > foo/bar + tar -rf foo.tar --remove-files -C foo bar + echo B + find . | sort +@@ -43,6 +51,7 @@ find . | sort + ./bar + ./foo + ./foo.tar ++./foo/bar + B + . + ./bar +diff --git a/tests/remfiles05a.at b/tests/remfiles05a.at +new file mode 100644 +index 0000000..4ceec37 +--- /dev/null ++++ b/tests/remfiles05a.at +@@ -0,0 +1,64 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of two relative-path -C options, ++# in --create/non-incremental mode. ++# ++# (This specific case failed during development of tar 1.26.90: ++# There was a leftover call to chdir in name_next_elt() in ++# tar 1.26. After commit e3d28d84 this call would confuse the ++# tar_getcwd function. ++# ++# Reported by: Nathan Stratton Treadway ++# References: <20130924145657.GM32256@shire.ontko.com>, ++# http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00045.html ++# ) ++ ++AT_SETUP([remove-files with -C:rel,rel in -c/non-incr. mode]) ++AT_KEYWORDS([create remove-files remfiles05 remfiles05a]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++decho A ++tar -cvf foo.tar --remove-files -C foo file -C ../bar file ++decho B ++find . | sort ++], ++[0], ++[A ++file ++file ++B ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles05b.at b/tests/remfiles05b.at +new file mode 100644 +index 0000000..d120efd +--- /dev/null ++++ b/tests/remfiles05b.at +@@ -0,0 +1,55 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of two relative-path -C options, ++# in --create/incremental mode. ++# ++ ++AT_SETUP([remove-files with -C:rel,rel in -c/incr. mode]) ++AT_KEYWORDS([create incremental remove-files remfiles05 remfiles05b]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++decho A ++tar -cvf foo.tar --incremental --remove-files -C foo file -C ../bar file ++decho B ++find . | sort ++], ++[0], ++[A ++file ++file ++B ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles05.at b/tests/remfiles05c.at +similarity index 63% +rename from tests/remfiles05.at +rename to tests/remfiles05c.at +index 04425a7..a01b092 100644 +--- a/tests/remfiles05.at ++++ b/tests/remfiles05c.at +@@ -15,25 +15,28 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-# Description: Tar 1.26 would remove wrong files when invoked with +-# --listed-incremental and -C +-# Reported by: Nathan Stratton Treadway +-# References: <20130921171234.GG32256@shire.ontko.com>, +-# http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00028.html ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of two relative-path -C options, ++# in --append mode. ++# + +-AT_SETUP([incremental and -C]) +-AT_KEYWORDS([incremental create remove-files remfiles05]) ++AT_SETUP([remove-files with -C:rel,rel in -r mode]) ++AT_KEYWORDS([create append remove-files remfiles05 remfiles05c]) + + AT_TAR_CHECK([ + AT_SORT_PREREQ + mkdir foo +-echo bar > bar +-echo foo/bar > foo/bar ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++tar -cf foo.tar -C foo file -C ../bar file + decho A + find . | sort +- + decho B +-tar -cvf foo.tar --listed-incremental=foo.snar --remove-files -C foo bar ++tar -rvf foo.tar --remove-files -C foo file -C ../bar file + decho C + find . | sort + ], +@@ -41,15 +44,19 @@ find . | sort + [A + . + ./bar ++./bar/file ++./file + ./foo +-./foo/bar ++./foo.tar ++./foo/file + B +-bar ++file ++file + C + . + ./bar ++./file + ./foo +-./foo.snar + ./foo.tar + ], + [A +diff --git a/tests/remfiles06.at b/tests/remfiles06.at +deleted file mode 100644 +index c2d9876..8b13789 +--- a/tests/remfiles06.at ++++ /dev/null +@@ -1,66 +0,0 @@ +-# Process this file with autom4te to create testsuite. -*- Autotest -*- +-# Test suite for GNU tar. +-# Copyright 2013 Free Software Foundation, Inc. +-# +-# GNU tar 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 of the License, or +-# (at your option) any later version. +-# +-# GNU tar 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 . +- +-# Description: There was a leftover call to chdir in name_next_elt() in +-# tar 1.26. After commit e3d28d84 this call would confuse the tar_getcwd +-# function. +-# Reported by: Nathan Stratton Treadway +-# References: <20130924145657.GM32256@shire.ontko.com>, +-# http://lists.gnu.org/archive/html/bug-tar/2013-09/msg00045.html +- +-AT_SETUP([remove with two -C]) +-AT_KEYWORDS([remove-files remfiles06]) +- +-AT_TAR_CHECK([ +-AT_SORT_PREREQ +-mkdir tartest +-cd tartest +-mkdir foo +-echo foo/file > foo/file +-mkdir bar +-echo bar/file > bar/file +-decho A +-find|sort +- +-decho B +-tar -cvf ../foo.tar --remove-files -C foo file -C ../bar file +- +-decho C +-find|sort +-], +-[0], +-[A +-. +-./bar +-./bar/file +-./foo +-./foo/file +-B +-file +-file +-C +-. +-./bar +-./foo +-], +-[A +-B +-C +-],[],[],[gnu]) +- +-AT_CLEANUP +- +diff --git a/tests/remfiles06a.at b/tests/remfiles06a.at +new file mode 100644 +index 0000000..fe762c1 +--- /dev/null ++++ b/tests/remfiles06a.at +@@ -0,0 +1,56 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of a relative -C option followed by an absolute -C, ++# in --create/non-incremental mode. ++# ++ ++AT_SETUP([remove-files with -C:rel,abs in -c/non-incr. mode]) ++AT_KEYWORDS([create remove-files remfiles06 remfiles06a]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++DIR=`pwd` ++decho A ++tar -cvf foo.tar --remove-files -C foo file -C $DIR/bar file ++decho B ++find . | sort ++], ++[0], ++[A ++file ++file ++B ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles06b.at b/tests/remfiles06b.at +new file mode 100644 +index 0000000..3b867fb +--- /dev/null ++++ b/tests/remfiles06b.at +@@ -0,0 +1,56 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of a relative -C option followed by an absolute -C, ++# in --create/incremental mode. ++# ++ ++AT_SETUP([remove-files with -C:rel,abs in -c/incr. mode]) ++AT_KEYWORDS([create incremental remove-files remfiles06 remfiles06b]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++DIR=`pwd` ++decho A ++tar -cvf foo.tar --incremental --remove-files -C foo file -C $DIR/bar file ++decho B ++find . | sort ++], ++[0], ++[A ++file ++file ++B ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles06c.at b/tests/remfiles06c.at +new file mode 100644 +index 0000000..ad9164d +--- /dev/null ++++ b/tests/remfiles06c.at +@@ -0,0 +1,68 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of a relative -C option followed by an absolute -C, ++# in --append mode. ++# ++ ++AT_SETUP([remove-files with -C:rel,abs in -r mode]) ++AT_KEYWORDS([create append remove-files remfiles06 remfiles06c]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++DIR=`pwd` ++tar -cf foo.tar -C foo file -C $DIR/bar file ++decho A ++find . | sort ++decho B ++tar -rvf foo.tar --remove-files -C foo file -C ../bar file ++decho C ++find . | sort ++], ++[0], ++[A ++. ++./bar ++./bar/file ++./file ++./foo ++./foo.tar ++./foo/file ++B ++file ++file ++C ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++C ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles07a.at b/tests/remfiles07a.at +new file mode 100644 +index 0000000..95f645c +--- /dev/null ++++ b/tests/remfiles07a.at +@@ -0,0 +1,56 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of a relative -C option followed by an absolute -C, ++# in --create/non-incremental mode. ++# ++ ++AT_SETUP([remove-files with -C:rel,abs in -c/non-incr. mode]) ++AT_KEYWORDS([create remove-files remfiles07 remfiles07a]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++DIR=`pwd` ++decho A ++tar -cvf foo.tar --remove-files -C foo file -C $DIR/bar file ++decho B ++find . | sort ++], ++[0], ++[A ++file ++file ++B ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles07b.at b/tests/remfiles07b.at +new file mode 100644 +index 0000000..ca67e5d +--- /dev/null ++++ b/tests/remfiles07b.at +@@ -0,0 +1,56 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of a relative -C option followed by an absolute -C, ++# in --create/incremental mode. ++# ++ ++AT_SETUP([remove-files with -C:rel,abs in -c/incr. mode]) ++AT_KEYWORDS([create incremental remove-files remfiles07 remfiles07b]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++DIR=`pwd` ++decho A ++tar -cvf foo.tar --incremental --remove-files -C foo file -C $DIR/bar file ++decho B ++find . | sort ++], ++[0], ++[A ++file ++file ++B ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles07c.at b/tests/remfiles07c.at +new file mode 100644 +index 0000000..6a5c870 +--- /dev/null ++++ b/tests/remfiles07c.at +@@ -0,0 +1,68 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of a relative -C option followed by an absolute -C, ++# in --append mode. ++# ++ ++AT_SETUP([remove-files with -C:rel,abs in -r mode]) ++AT_KEYWORDS([create append remove-files remfiles07 remfiles07c]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++DIR=`pwd` ++tar -cf foo.tar -C foo file -C $DIR/bar file ++decho A ++find . | sort ++decho B ++tar -rvf foo.tar --remove-files -C foo file -C $DIR/bar file ++decho C ++find . | sort ++], ++[0], ++[A ++. ++./bar ++./bar/file ++./file ++./foo ++./foo.tar ++./foo/file ++B ++file ++file ++C ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++C ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles08a.at b/tests/remfiles08a.at +new file mode 100644 +index 0000000..eadf149 +--- /dev/null ++++ b/tests/remfiles08a.at +@@ -0,0 +1,56 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of an absolute -C option followed by a relative -C, ++# in --create/non-incremental mode. ++# ++ ++AT_SETUP([remove-files with -C:abs,rel in -c/non-incr. mode]) ++AT_KEYWORDS([create remove-files remfiles08 remfiles08a]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++DIR=`pwd` ++decho A ++tar -cvf foo.tar --remove-files -C $DIR/foo file -C ../bar file ++decho B ++find . | sort ++], ++[0], ++[A ++file ++file ++B ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles08b.at b/tests/remfiles08b.at +new file mode 100644 +index 0000000..9faf2bb +--- /dev/null ++++ b/tests/remfiles08b.at +@@ -0,0 +1,56 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of an absolute -C option followed by a relative -C, ++# in --create/incremental mode. ++# ++ ++AT_SETUP([remove-files with -C:abs,rel in -c/incr. mode]) ++AT_KEYWORDS([create incremental remove-files remfiles08 remfiles08b]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++DIR=`pwd` ++decho A ++tar -cvf foo.tar --incremental --remove-files -C $DIR/foo file -C ../bar file ++decho B ++find . | sort ++], ++[0], ++[A ++file ++file ++B ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles08c.at b/tests/remfiles08c.at +new file mode 100644 +index 0000000..a220f4c +--- /dev/null ++++ b/tests/remfiles08c.at +@@ -0,0 +1,68 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: ensure tar correctly respects -C option when deleting ++# files due to the --remove-files option. ++# ++# This case checks the use of an absolute -C option followed by a relative -C, ++# in --append mode. ++# ++ ++AT_SETUP([remove-files with -C:abs,rel in -r mode]) ++AT_KEYWORDS([create append remove-files remfiles08 remfiles08c]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++mkdir bar ++echo file > file ++echo foo/file > foo/file ++echo bar/file > bar/file ++DIR=`pwd` ++tar -cf foo.tar -C $DIR/foo file -C ../bar file ++decho A ++find . | sort ++decho B ++tar -rvf foo.tar --remove-files -C $DIR/foo file -C ../bar file ++decho C ++find . | sort ++], ++[0], ++[A ++. ++./bar ++./bar/file ++./file ++./foo ++./foo.tar ++./foo/file ++B ++file ++file ++C ++. ++./bar ++./file ++./foo ++./foo.tar ++], ++[A ++B ++C ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles08.at b/tests/remfiles09a.at +similarity index 66% +rename from tests/remfiles08.at +rename to tests/remfiles09a.at +index 0649e85..fd28b4f 100644 +--- a/tests/remfiles08.at ++++ b/tests/remfiles09a.at +@@ -15,29 +15,28 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-# Description: See remfiles06.at +-# Reported by: Nathan Stratton Treadway +-# References: <20130926050634.GW32256@shire.ontko.com> ++# Description: check --remove-files operation when archiving/deleting ++# directory trees. ++# ++# This case checks the operation ++# in --create/non-incremental mode. ++# + +-AT_SETUP([remove with -C to absolute and relative paths]) +-AT_KEYWORDS([incremental create remove-files remfiles08]) ++AT_SETUP([remove-files on full directory in -c/non-incr. mode]) ++AT_KEYWORDS([create remove-files remfiles09 remfiles09a]) + + AT_TAR_CHECK([ + mkdir foo +-mkdir bar +-echo foo/foo_file > foo/foo_file +-echo bar/bar_file > bar/bar_file ++echo foo/file > foo/file + decho A +-tar -cvf foo.tar --remove-files -C `pwd`/foo . -C ../bar . ++tar -cvf foo.tar --remove-files foo + decho B +-find ++find . + ], + [0], + [A +-./ +-./foo_file +-./ +-./bar_file ++foo/ ++foo/file + B + . + ./foo.tar +diff --git a/tests/remfiles09b.at b/tests/remfiles09b.at +new file mode 100644 +index 0000000..30cc3ee +--- /dev/null ++++ b/tests/remfiles09b.at +@@ -0,0 +1,57 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Description: check --remove-files operation when archiving/deleting ++# directory trees. ++# ++# This case checks the operation ++# in --create/incremental mode. ++# ++# Note: in tar 1.27, when run in incremental mode tar will attempt to remove ++# the directory before removing the files within that directory, and thus ++# the --remove-files operation will cause tar to abort with an error status. ++# This issue will be fixed in a later version of tar. ++ ++AT_SETUP([remove-files on full directory in -c/incr. mode]) ++AT_KEYWORDS([create incremental remove-files remfiles09 remfiles09b]) ++ ++AT_TAR_CHECK([ ++AT_SORT_PREREQ ++mkdir foo ++echo foo/file > foo/file ++decho A ++tar -cvf foo.tar --incremental --remove-files foo ++TARSTAT=$? ++decho B ++find . ++test $TARSTAT -ne 0 && AT_SKIP_TEST # we expect to fail in tar 1.27 ++], ++[0], ++[A ++foo/ ++foo/file ++B ++. ++./foo ++./foo.tar ++], ++[A ++tar: foo: Directory is new ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/remfiles07.at b/tests/remfiles09c.at +similarity index 68% +rename from tests/remfiles07.at +rename to tests/remfiles09c.at +index 742e0a1..7241608 100644 +--- a/tests/remfiles07.at ++++ b/tests/remfiles09c.at +@@ -15,45 +15,40 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-# Description: See remfiles06.at +-# Reported by: Nathan Stratton Treadway +-# References: <20130924185129.GO32256@shire.ontko.com> ++# Description: check --remove-files operation when archiving/deleting ++# directory trees. ++# ++# This case checks the operation ++# in --append mode. ++# + +-AT_SETUP([remove with -C to absolute path]) +-AT_KEYWORDS([create remove-files remfiles07]) ++AT_SETUP([remove-files on full directory in -r mode]) ++AT_KEYWORDS([create append remove-files remfiles09 remfiles09c]) + + AT_TAR_CHECK([ + AT_SORT_PREREQ +-mkdir tartest +-cd tartest + mkdir foo + echo foo/file > foo/file +-mkdir bar +-echo bar/file > bar/file ++tar -cf foo.tar foo + decho A +-find|sort +- +-DIR=`pwd` ++find . | sort + decho B +-tar -cvf ../foo.tar --remove-files -C foo file -C $DIR/bar file +- ++tar -rvf foo.tar --remove-files foo + decho C +-find|sort ++find . | sort + ], + [0], + [A + . +-./bar +-./bar/file + ./foo ++./foo.tar + ./foo/file + B +-file +-file ++foo/ ++foo/file + C + . +-./bar +-./foo ++./foo.tar + ], + [A + B +diff --git a/tests/testsuite.at b/tests/testsuite.at +index a9f2ab6..1cc425f 100644 +--- a/tests/testsuite.at ++++ b/tests/testsuite.at +@@ -332,11 +332,24 @@ m4_include([grow.at]) + m4_include([remfiles01.at]) + m4_include([remfiles02.at]) + m4_include([remfiles03.at]) +-m4_include([remfiles04.at]) +-m4_include([remfiles05.at]) +-m4_include([remfiles06.at]) +-m4_include([remfiles07.at]) +-m4_include([remfiles08.at]) ++m4_include([remfiles04a.at]) ++m4_include([remfiles04b.at]) ++m4_include([remfiles04c.at]) ++m4_include([remfiles05a.at]) ++m4_include([remfiles05b.at]) ++m4_include([remfiles05c.at]) ++m4_include([remfiles06a.at]) ++m4_include([remfiles06b.at]) ++m4_include([remfiles06c.at]) ++m4_include([remfiles07a.at]) ++m4_include([remfiles07b.at]) ++m4_include([remfiles07c.at]) ++m4_include([remfiles08a.at]) ++m4_include([remfiles08b.at]) ++m4_include([remfiles08c.at]) ++m4_include([remfiles09a.at]) ++m4_include([remfiles09b.at]) ++m4_include([remfiles09c.at]) + + m4_include([sigpipe.at]) + +-- +2.9.3 + + +From c3d32c9c848f1f305cd9aefd9f485cdfbcee51b2 Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Sat, 5 Oct 2013 09:29:55 +0300 +Subject: [PATCH 08/11] Xfail the remfiles09b test. + +* tests/remfiles09b.at: Turn into expected failure. +--- + tests/remfiles09b.at | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tests/remfiles09b.at b/tests/remfiles09b.at +index 30cc3ee..de9b172 100644 +--- a/tests/remfiles09b.at ++++ b/tests/remfiles09b.at +@@ -29,6 +29,8 @@ + AT_SETUP([remove-files on full directory in -c/incr. mode]) + AT_KEYWORDS([create incremental remove-files remfiles09 remfiles09b]) + ++AT_XFAIL_IF(true) # we expect to fail in tar 1.27 ++ + AT_TAR_CHECK([ + AT_SORT_PREREQ + mkdir foo +@@ -38,7 +40,6 @@ tar -cvf foo.tar --incremental --remove-files foo + TARSTAT=$? + decho B + find . +-test $TARSTAT -ne 0 && AT_SKIP_TEST # we expect to fail in tar 1.27 + ], + [0], + [A +-- +2.9.3 + + +From 2c5449cc473b0a9affed02feaf3ad42e5e89bfb5 Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Tue, 29 Apr 2014 14:22:07 -0700 +Subject: [PATCH 09/11] tar: do not dereference NULL pointer with + '--remove-files .' + +Problem reported by Thorsten Hirsch in: +http://lists.gnu.org/archive/html/bug-tar/2014-04/msg00011.html +* src/unlink.c (flush_deferred_unlinks): +Do not attempt to find the parent of "." when "." is +at the top level. +* tests/remfiles10.at: New file. +* tests/Makefile.am (TESTSUITE_AT): +* tests/testsuite.at: Add it. +--- + src/unlink.c | 5 +++-- + tests/Makefile.am | 1 + + tests/remfiles10.at | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/testsuite.at | 1 + + 4 files changed, 51 insertions(+), 2 deletions(-) + create mode 100644 tests/remfiles10.at + +diff --git a/src/unlink.c b/src/unlink.c +index 10e0b41..6e41acc 100644 +--- a/src/unlink.c ++++ b/src/unlink.c +@@ -84,8 +84,9 @@ flush_deferred_unlinks (bool force) + { + const char *fname; + +- if (p->file_name[0] == 0 || +- strcmp (p->file_name, ".") == 0) ++ if (p->dir_idx ++ && (p->file_name[0] == 0 ++ || strcmp (p->file_name, ".") == 0)) + { + fname = tar_dirname (); + chdir_do (p->dir_idx - 1); +diff --git a/tests/Makefile.am b/tests/Makefile.am +index cf6f576..792c83c 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -159,6 +159,7 @@ TESTSUITE_AT = \ + remfiles09a.at\ + remfiles09b.at\ + remfiles09c.at\ ++ remfiles10.at\ + same-order01.at\ + same-order02.at\ + shortfile.at\ +diff --git a/tests/remfiles10.at b/tests/remfiles10.at +new file mode 100644 +index 0000000..b4fe139 +--- /dev/null ++++ b/tests/remfiles10.at +@@ -0,0 +1,46 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2014 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++# Check --remove-files with . ++ ++AT_SETUP([remove-files]) ++AT_KEYWORDS([create remove-files remfiles10]) ++ ++AT_TAR_CHECK([ ++mkdir foo ++echo foo/file > foo/file ++decho A ++(cd foo && tar -cvf ../foo.tar --remove-files .) ++tar_status=$? ++decho B ++find foo ++exit $tar_status ++], ++[2], ++[A ++./ ++./file ++B ++foo ++], ++[A ++tar: .: Cannot rmdir: Invalid argument ++tar: Exiting with failure status due to previous errors ++B ++],[],[],[gnu]) ++ ++AT_CLEANUP +diff --git a/tests/testsuite.at b/tests/testsuite.at +index 1cc425f..1078724 100644 +--- a/tests/testsuite.at ++++ b/tests/testsuite.at +@@ -350,6 +350,7 @@ m4_include([remfiles08c.at]) + m4_include([remfiles09a.at]) + m4_include([remfiles09b.at]) + m4_include([remfiles09c.at]) ++m4_include([remfiles10.at]) + + m4_include([sigpipe.at]) + +-- +2.9.3 + + +From 612e134f4905f479b78b6d7faf9798494697a742 Mon Sep 17 00:00:00 2001 +From: Nathan Stratton Treadway +Date: Sun, 27 Jul 2014 23:27:28 +0300 +Subject: [PATCH 10/11] Restructure the remfiles testsuite. + +--- + tests/remfiles06c.at | 2 +- + tests/remfiles07a.at | 6 +++--- + tests/remfiles07b.at | 6 +++--- + tests/remfiles07c.at | 8 ++++---- + tests/remfiles08a.at | 31 +++++++++++++++---------------- + tests/remfiles08b.at | 38 ++++++++++++++++++++++---------------- + tests/remfiles08c.at | 37 ++++++++++++++++++------------------- + tests/remfiles09a.at | 2 +- + tests/remfiles09b.at | 3 --- + 9 files changed, 67 insertions(+), 66 deletions(-) + +diff --git a/tests/remfiles06c.at b/tests/remfiles06c.at +index ad9164d..abb8e68 100644 +--- a/tests/remfiles06c.at ++++ b/tests/remfiles06c.at +@@ -37,7 +37,7 @@ tar -cf foo.tar -C foo file -C $DIR/bar file + decho A + find . | sort + decho B +-tar -rvf foo.tar --remove-files -C foo file -C ../bar file ++tar -rvf foo.tar --remove-files -C foo file -C $DIR/bar file + decho C + find . | sort + ], +diff --git a/tests/remfiles07a.at b/tests/remfiles07a.at +index 95f645c..5b7df3e 100644 +--- a/tests/remfiles07a.at ++++ b/tests/remfiles07a.at +@@ -18,11 +18,11 @@ + # Description: ensure tar correctly respects -C option when deleting + # files due to the --remove-files option. + # +-# This case checks the use of a relative -C option followed by an absolute -C, ++# This case checks the use of an absolute -C option followed by a relative -C, + # in --create/non-incremental mode. + # + +-AT_SETUP([remove-files with -C:rel,abs in -c/non-incr. mode]) ++AT_SETUP([remove-files with -C:abs,rel in -c/non-incr. mode]) + AT_KEYWORDS([create remove-files remfiles07 remfiles07a]) + + AT_TAR_CHECK([ +@@ -34,7 +34,7 @@ echo foo/file > foo/file + echo bar/file > bar/file + DIR=`pwd` + decho A +-tar -cvf foo.tar --remove-files -C foo file -C $DIR/bar file ++tar -cvf foo.tar --remove-files -C $DIR/foo file -C ../bar file + decho B + find . | sort + ], +diff --git a/tests/remfiles07b.at b/tests/remfiles07b.at +index ca67e5d..0147c5d 100644 +--- a/tests/remfiles07b.at ++++ b/tests/remfiles07b.at +@@ -18,11 +18,11 @@ + # Description: ensure tar correctly respects -C option when deleting + # files due to the --remove-files option. + # +-# This case checks the use of a relative -C option followed by an absolute -C, ++# This case checks the use of an absolute -C option followed by a relative -C, + # in --create/incremental mode. + # + +-AT_SETUP([remove-files with -C:rel,abs in -c/incr. mode]) ++AT_SETUP([remove-files with -C:abs,rel in -c/incr. mode]) + AT_KEYWORDS([create incremental remove-files remfiles07 remfiles07b]) + + AT_TAR_CHECK([ +@@ -34,7 +34,7 @@ echo foo/file > foo/file + echo bar/file > bar/file + DIR=`pwd` + decho A +-tar -cvf foo.tar --incremental --remove-files -C foo file -C $DIR/bar file ++tar -cvf foo.tar --incremental --remove-files -C $DIR/foo file -C ../bar file + decho B + find . | sort + ], +diff --git a/tests/remfiles07c.at b/tests/remfiles07c.at +index 6a5c870..f190539 100644 +--- a/tests/remfiles07c.at ++++ b/tests/remfiles07c.at +@@ -18,11 +18,11 @@ + # Description: ensure tar correctly respects -C option when deleting + # files due to the --remove-files option. + # +-# This case checks the use of a relative -C option followed by an absolute -C, ++# This case checks the use of an absolute -C option followed by a relative -C, + # in --append mode. + # + +-AT_SETUP([remove-files with -C:rel,abs in -r mode]) ++AT_SETUP([remove-files with -C:abs,rel in -r mode]) + AT_KEYWORDS([create append remove-files remfiles07 remfiles07c]) + + AT_TAR_CHECK([ +@@ -33,11 +33,11 @@ echo file > file + echo foo/file > foo/file + echo bar/file > bar/file + DIR=`pwd` +-tar -cf foo.tar -C foo file -C $DIR/bar file ++tar -cf foo.tar -C $DIR/foo file -C ../bar file + decho A + find . | sort + decho B +-tar -rvf foo.tar --remove-files -C foo file -C $DIR/bar file ++tar -rvf foo.tar --remove-files -C $DIR/foo file -C ../bar file + decho C + find . | sort + ], +diff --git a/tests/remfiles08a.at b/tests/remfiles08a.at +index eadf149..1ffffb2 100644 +--- a/tests/remfiles08a.at ++++ b/tests/remfiles08a.at +@@ -15,38 +15,37 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-# Description: ensure tar correctly respects -C option when deleting +-# files due to the --remove-files option. ++# Description: If tar 1.26 was called with the --remove-files option and told ++# to archive (and thus delete) two subdirectories where the second was ++# specified relative to the first, it would be unable to delete the ++# second directory (and its contents), since the relative path would no ++# longer be valid once the first directory was deleted. + # +-# This case checks the use of an absolute -C option followed by a relative -C, ++# This case checks for successful deletion of all archived items + # in --create/non-incremental mode. + # + +-AT_SETUP([remove-files with -C:abs,rel in -c/non-incr. mode]) ++AT_SETUP([remove-files deleting two subdirs in -c/non-incr. mode]) + AT_KEYWORDS([create remove-files remfiles08 remfiles08a]) + + AT_TAR_CHECK([ +-AT_SORT_PREREQ + mkdir foo + mkdir bar +-echo file > file +-echo foo/file > foo/file +-echo bar/file > bar/file +-DIR=`pwd` ++echo foo/foo_file > foo/foo_file ++echo bar/bar_file > bar/bar_file + decho A +-tar -cvf foo.tar --remove-files -C $DIR/foo file -C ../bar file ++tar -cvf foo.tar --remove-files -C foo . -C ../bar . + decho B +-find . | sort ++find . + ], + [0], + [A +-file +-file ++./ ++./foo_file ++./ ++./bar_file + B + . +-./bar +-./file +-./foo + ./foo.tar + ], + [A +diff --git a/tests/remfiles08b.at b/tests/remfiles08b.at +index 9faf2bb..d61c9ab 100644 +--- a/tests/remfiles08b.at ++++ b/tests/remfiles08b.at +@@ -15,41 +15,47 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-# Description: ensure tar correctly respects -C option when deleting +-# files due to the --remove-files option. ++# Description: If tar 1.26 was called with the --remove-files option and told ++# to archive (and thus delete) two subdirectories where the second was ++# specified relative to the first, it would be unable to delete the ++# second directory (and its contents), since the relative path would no ++# longer be valid once the first directory was deleted. + # +-# This case checks the use of an absolute -C option followed by a relative -C, ++# This case checks for successful deletion of all archived items + # in --create/incremental mode. + # ++# Note: tar 1.27 fails this test case due to a more general issue ++# archving-and-removing a full directory tree when run in incremental ++# mode; see remfiles09b.at for that specific test case. + +-AT_SETUP([remove-files with -C:abs,rel in -c/incr. mode]) ++AT_SETUP([remove-files deleting two subdirs in -c/incr. mode]) + AT_KEYWORDS([create incremental remove-files remfiles08 remfiles08b]) + ++AT_XFAIL_IF(true) # we expect to fail in tar 1.27 ++ + AT_TAR_CHECK([ +-AT_SORT_PREREQ + mkdir foo + mkdir bar +-echo file > file +-echo foo/file > foo/file +-echo bar/file > bar/file +-DIR=`pwd` ++echo foo/foo_file > foo/foo_file ++echo bar/bar_file > bar/bar_file + decho A +-tar -cvf foo.tar --incremental --remove-files -C $DIR/foo file -C ../bar file ++tar -cvf foo.tar --incremental --remove-files -C foo . -C ../bar . + decho B +-find . | sort ++find . + ], + [0], + [A +-file +-file ++./ ++./ ++./foo_file ++./bar_file + B + . +-./bar +-./file +-./foo + ./foo.tar + ], + [A ++tar: .: Directory is new ++tar: .: Directory is new + B + ],[],[],[gnu]) + +diff --git a/tests/remfiles08c.at b/tests/remfiles08c.at +index a220f4c..19b18e2 100644 +--- a/tests/remfiles08c.at ++++ b/tests/remfiles08c.at +@@ -15,49 +15,48 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + +-# Description: ensure tar correctly respects -C option when deleting +-# files due to the --remove-files option. ++# Description: If tar 1.26 was called with the --remove-files option and told ++# to archive (and thus delete) two subdirectories where the second was ++# specified relative to the first, it would be unable to delete the ++# second directory (and its contents), since the relative path would no ++# longer be valid once the first directory was deleted. + # +-# This case checks the use of an absolute -C option followed by a relative -C, ++# This case checks for successful deletion of all archived items + # in --append mode. + # + +-AT_SETUP([remove-files with -C:abs,rel in -r mode]) ++AT_SETUP([remove-files deleting two subdirs in -r mode]) + AT_KEYWORDS([create append remove-files remfiles08 remfiles08c]) + + AT_TAR_CHECK([ + AT_SORT_PREREQ + mkdir foo + mkdir bar +-echo file > file +-echo foo/file > foo/file +-echo bar/file > bar/file +-DIR=`pwd` +-tar -cf foo.tar -C $DIR/foo file -C ../bar file ++echo foo/foo_file > foo/foo_file ++echo bar/bar_file > bar/bar_file ++tar -cf foo.tar -C foo . -C ../bar . + decho A + find . | sort + decho B +-tar -rvf foo.tar --remove-files -C $DIR/foo file -C ../bar file ++tar -rvf foo.tar --remove-files -C foo . -C ../bar . + decho C +-find . | sort ++find . + ], + [0], + [A + . + ./bar +-./bar/file +-./file ++./bar/bar_file + ./foo + ./foo.tar +-./foo/file ++./foo/foo_file + B +-file +-file ++./ ++./foo_file ++./ ++./bar_file + C + . +-./bar +-./file +-./foo + ./foo.tar + ], + [A +diff --git a/tests/remfiles09a.at b/tests/remfiles09a.at +index fd28b4f..f4a3bf5 100644 +--- a/tests/remfiles09a.at ++++ b/tests/remfiles09a.at +@@ -31,7 +31,7 @@ echo foo/file > foo/file + decho A + tar -cvf foo.tar --remove-files foo + decho B +-find . ++find . + ], + [0], + [A +diff --git a/tests/remfiles09b.at b/tests/remfiles09b.at +index de9b172..e12fe32 100644 +--- a/tests/remfiles09b.at ++++ b/tests/remfiles09b.at +@@ -32,12 +32,10 @@ AT_KEYWORDS([create incremental remove-files remfiles09 remfiles09b]) + AT_XFAIL_IF(true) # we expect to fail in tar 1.27 + + AT_TAR_CHECK([ +-AT_SORT_PREREQ + mkdir foo + echo foo/file > foo/file + decho A + tar -cvf foo.tar --incremental --remove-files foo +-TARSTAT=$? + decho B + find . + ], +@@ -47,7 +45,6 @@ foo/ + foo/file + B + . +-./foo + ./foo.tar + ], + [A +-- +2.9.3 + + +From 6030b8a2589ff69d9200578e0aecc1f10aedb073 Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Wed, 11 Nov 2015 13:01:45 +0200 +Subject: [PATCH 11/11] Work around unlinkat bug on FreeBSD and GNU/Hurd + +* src/unlink.c (dunlink_insert): New function. +(flush_deferred_unlinks): Skip cwds and nonempty directories +at the first pass. If force is requested, run a second pass +removing them. +(queue_deferred_unlink): Make sure current working directory +entries are sorted in descending order by the value of dir_idx. +This makes sure they will be removed in right order, which works +around unlinkat bug on FreeBSD and GNU/Hurd. +* tests/remfiles08b.at: Remove expected failure. +* tests/remfiles09b.at: Likewise. +--- + src/unlink.c | 91 +++++++++++++++++++++++++++++++++++++++++----------- + tests/remfiles08b.at | 2 -- + tests/remfiles09b.at | 2 -- + 3 files changed, 72 insertions(+), 23 deletions(-) + +diff --git a/src/unlink.c b/src/unlink.c +index 6e41acc..f5fb81d 100644 +--- a/src/unlink.c ++++ b/src/unlink.c +@@ -30,6 +30,10 @@ struct deferred_unlink + entry got added to the queue */ + }; + ++#define IS_CWD(p) \ ++ ((p)->is_dir \ ++ && ((p)->file_name[0] == 0 || strcmp ((p)->file_name, ".") == 0)) ++ + /* The unlink queue */ + static struct deferred_unlink *dunlink_head, *dunlink_tail; + +@@ -59,6 +63,24 @@ dunlink_alloc (void) + } + + static void ++dunlink_insert (struct deferred_unlink *anchor, struct deferred_unlink *p) ++{ ++ if (anchor) ++ { ++ p->next = anchor->next; ++ anchor->next = p; ++ } ++ else ++ { ++ p->next = dunlink_head; ++ dunlink_head = p; ++ } ++ if (!p->next) ++ dunlink_tail = p; ++ dunlink_count++; ++} ++ ++static void + dunlink_reclaim (struct deferred_unlink *p) + { + free (p->file_name); +@@ -84,12 +106,11 @@ flush_deferred_unlinks (bool force) + { + const char *fname; + +- if (p->dir_idx +- && (p->file_name[0] == 0 +- || strcmp (p->file_name, ".") == 0)) ++ if (p->dir_idx && IS_CWD (p)) + { +- fname = tar_dirname (); +- chdir_do (p->dir_idx - 1); ++ prev = p; ++ p = next; ++ continue; + } + else + fname = p->file_name; +@@ -102,15 +123,12 @@ flush_deferred_unlinks (bool force) + /* nothing to worry about */ + break; + case ENOTEMPTY: +- if (!force) +- { +- /* Keep the record in list, in the hope we'll +- be able to remove it later */ +- prev = p; +- p = next; +- continue; +- } +- /* fall through */ ++ /* Keep the record in list, in the hope we'll ++ be able to remove it later */ ++ prev = p; ++ p = next; ++ continue; ++ + default: + rmdir_error (fname); + } +@@ -137,6 +155,34 @@ flush_deferred_unlinks (bool force) + } + if (!dunlink_head) + dunlink_tail = NULL; ++ else if (force) ++ { ++ for (p = dunlink_head; p; ) ++ { ++ struct deferred_unlink *next = p->next; ++ const char *fname; ++ ++ chdir_do (p->dir_idx); ++ if (p->dir_idx && IS_CWD (p)) ++ { ++ fname = tar_dirname (); ++ chdir_do (p->dir_idx - 1); ++ } ++ else ++ fname = p->file_name; ++ ++ if (unlinkat (chdir_fd, fname, AT_REMOVEDIR) != 0) ++ { ++ if (errno != ENOENT) ++ rmdir_error (fname); ++ } ++ dunlink_reclaim (p); ++ dunlink_count--; ++ p = next; ++ } ++ dunlink_head = dunlink_tail = NULL; ++ } ++ + chdir_do (saved_chdir); + } + +@@ -169,10 +215,17 @@ queue_deferred_unlink (const char *name, bool is_dir) + p->is_dir = is_dir; + p->records_written = records_written; + +- if (dunlink_tail) +- dunlink_tail->next = p; ++ if (IS_CWD (p)) ++ { ++ struct deferred_unlink *q, *prev; ++ for (q = dunlink_head, prev = NULL; q; prev = q, q = q->next) ++ if (IS_CWD (q) && q->dir_idx < p->dir_idx) ++ break; ++ if (q) ++ dunlink_insert (prev, p); ++ else ++ dunlink_insert (dunlink_tail, p); ++ } + else +- dunlink_head = p; +- dunlink_tail = p; +- dunlink_count++; ++ dunlink_insert (dunlink_tail, p); + } +diff --git a/tests/remfiles08b.at b/tests/remfiles08b.at +index d61c9ab..4487f83 100644 +--- a/tests/remfiles08b.at ++++ b/tests/remfiles08b.at +@@ -31,8 +31,6 @@ + AT_SETUP([remove-files deleting two subdirs in -c/incr. mode]) + AT_KEYWORDS([create incremental remove-files remfiles08 remfiles08b]) + +-AT_XFAIL_IF(true) # we expect to fail in tar 1.27 +- + AT_TAR_CHECK([ + mkdir foo + mkdir bar +diff --git a/tests/remfiles09b.at b/tests/remfiles09b.at +index e12fe32..4d05aa5 100644 +--- a/tests/remfiles09b.at ++++ b/tests/remfiles09b.at +@@ -29,8 +29,6 @@ + AT_SETUP([remove-files on full directory in -c/incr. mode]) + AT_KEYWORDS([create incremental remove-files remfiles09 remfiles09b]) + +-AT_XFAIL_IF(true) # we expect to fail in tar 1.27 +- + AT_TAR_CHECK([ + mkdir foo + echo foo/file > foo/file +-- +2.9.3 + diff --git a/SOURCES/tar-1.26-keep-directory-symlink.patch b/SOURCES/tar-1.26-keep-directory-symlink.patch new file mode 100644 index 0000000..63f4c77 --- /dev/null +++ b/SOURCES/tar-1.26-keep-directory-symlink.patch @@ -0,0 +1,170 @@ +From c4a4cafaa330793d776b001c272bf19869aac39c Mon Sep 17 00:00:00 2001 +From: Sergey Poznyakoff +Date: Mon, 23 Sep 2013 19:35:29 +0300 +Subject: [PATCH] Changes for compatibility with Slackware installation + scripts. + +* src/buffer.c (short_read): the "Record size" message +is controlled by the WARN_RECORD_SIZE warning_option bit. +* src/common.h (keep_directory_symlink_option): New global. +(WARN_RECORD_SIZE): New constant. +(WARN_VERBOSE_WARNINGS): Add WARN_RECORD_SIZE. +* src/extract.c (extract_dir): If keep_directory_symlink_option is +set, follow symlinks to directories. +* src/suffix.c (compression_suffixes): Add support for txz +suffix. +* src/tar.c (KEEP_DIRECTORY_SYMLINK_OPTION): New constant. +(options): New option --keep-directory-symlink. +(parse_opt): Handle this option. +* src/warning.c: Implement "record-size" warning control. + +* NEWS: Update. +* doc/tar.texi: Document new features. +--- + NEWS | 12 ++++++++++++ + doc/tar.texi | 15 +++++++++++++++ + src/common.h | 2 ++ + src/extract.c | 19 +++++++++++++++++++ + src/tar.c | 8 ++++++++ + 5 files changed, 56 insertions(+) + +diff --git a/NEWS b/NEWS +index 8f3c416..36a27da 100644 +--- a/NEWS ++++ b/NEWS +@@ -6,6 +6,18 @@ Please send GNU tar bug reports to + When creating a PAX-format archive, tar no longer arbitrarily restricts + the size of the representation of a sparse file to be less than 8 GiB. + ++* New command line option --keep-directory-symlink ++ ++By default, if when trying to extract a directory from the archive, ++tar discovers that the corresponding file name already exists and is a ++symbolic link, it first unlinks the entry, and then extracts the directory. ++ ++This option disables this behavior and instructs tar to follow ++symlinks to directories when extracting from the archive. ++ ++It is mainly intended to provide compatibility with the Slackware ++installation scripts. ++ + + version 1.26 - Sergey Poznyakoff, 2011-03-12 + +diff --git a/doc/tar.texi b/doc/tar.texi +index 6bd59c7..fb03b85 100644 +--- a/doc/tar.texi ++++ b/doc/tar.texi +@@ -2923,6 +2923,21 @@ Specifies that @command{tar} should ask the user for confirmation before + performing potentially destructive options, such as overwriting files. + @xref{interactive}. + ++@opsummary{--keep-directory-symlink} ++@item --keep-directory-symlink ++ ++This option changes the behavior of tar when it encounters a symlink ++with the same name as the directory that it is about to extract. By ++default, in this case tar would first remove the symlink and then ++proceed extracting the directory. ++ ++The @option{--keep-directory-symlink} option disables this behavior ++and instructs tar to follow symlinks to directories when extracting ++from the archive. ++ ++It is mainly intended to provide compatibility with the Slackware ++installation scripts. ++ + @opsummary{keep-newer-files} + @item --keep-newer-files + +diff --git a/src/common.h b/src/common.h +index 16ba401..274da01 100644 +--- a/src/common.h ++++ b/src/common.h +@@ -192,6 +192,8 @@ enum old_files + }; + GLOBAL enum old_files old_files_option; + ++GLOBAL bool keep_directory_symlink_option; ++ + /* Specified file name for incremental list. */ + GLOBAL const char *listed_incremental_option; + /* Incremental dump level */ +diff --git a/src/extract.c b/src/extract.c +index 3afb95d..b622a2a 100644 +--- a/src/extract.c ++++ b/src/extract.c +@@ -854,7 +854,21 @@ apply_nonancestor_delayed_set_stat (char const *file_name, bool after_links) + } + + ++static bool ++is_directory_link (const char *file_name) ++{ ++ struct stat st; ++ int e = errno; ++ int res; + ++ res = (fstatat (chdir_fd, file_name, &st, AT_SYMLINK_NOFOLLOW) == 0 && ++ S_ISLNK (st.st_mode) && ++ fstatat (chdir_fd, file_name, &st, 0) == 0 && ++ S_ISDIR (st.st_mode)); ++ errno = e; ++ return res; ++} ++ + /* Extractor functions for various member types */ + + static int +@@ -910,10 +924,15 @@ extract_dir (char *file_name, int typeflag) + + if (errno == EEXIST + && (interdir_made ++ || keep_directory_symlink_option + || old_files_option == DEFAULT_OLD_FILES + || old_files_option == OVERWRITE_OLD_FILES)) + { + struct stat st; ++ ++ if (keep_directory_symlink_option && is_directory_link (file_name)) ++ return 0; ++ + if (deref_stat (file_name, &st) == 0) + { + current_mode = st.st_mode; +diff --git a/src/tar.c b/src/tar.c +index 18277e4..d62ca0e 100644 +--- a/src/tar.c ++++ b/src/tar.c +@@ -290,6 +290,7 @@ enum + IGNORE_COMMAND_ERROR_OPTION, + IGNORE_FAILED_READ_OPTION, + INDEX_FILE_OPTION, ++ KEEP_DIRECTORY_SYMLINK_OPTION, + KEEP_NEWER_FILES_OPTION, + LEVEL_OPTION, + LZIP_OPTION, +@@ -488,6 +489,9 @@ static struct argp_option options[] = { + {"overwrite-dir", OVERWRITE_DIR_OPTION, 0, 0, + N_("overwrite metadata of existing directories when extracting (default)"), + GRID+1 }, ++ {"keep-directory-symlink", KEEP_DIRECTORY_SYMLINK_OPTION, 0, 0, ++ N_("preserve existing symlinks to directories when extracting"), ++ GRID+1 }, + #undef GRID + + #define GRID 40 +@@ -1878,6 +1882,10 @@ parse_opt (int key, char *arg, struct argp_state *state) + ignore_failed_read_option = true; + break; + ++ case KEEP_DIRECTORY_SYMLINK_OPTION: ++ keep_directory_symlink_option = true; ++ break; ++ + case KEEP_NEWER_FILES_OPTION: + old_files_option = KEEP_NEWER_FILES; + break; +-- +2.9.3 + diff --git a/SOURCES/tar-1.26-restore-incremental-backups.patch b/SOURCES/tar-1.26-restore-incremental-backups.patch new file mode 100644 index 0000000..8ff9bc2 --- /dev/null +++ b/SOURCES/tar-1.26-restore-incremental-backups.patch @@ -0,0 +1,250 @@ +diff -urN tar-1.26/src/common.h tar-1.26new/src/common.h +--- tar-1.26/src/common.h 2017-01-24 09:43:08.638550577 +0100 ++++ tar-1.26new/src/common.h 2017-01-23 10:58:19.675411746 +0100 +@@ -598,6 +598,7 @@ + char *normalize_filename (const char *name); + void replace_prefix (char **pname, const char *samp, size_t slen, + const char *repl, size_t rlen); ++char *tar_savedir (const char *name, int must_exist); + + typedef struct namebuf *namebuf_t; + namebuf_t namebuf_create (const char *dir); +diff -urN tar-1.26/src/incremen.c tar-1.26new/src/incremen.c +--- tar-1.26/src/incremen.c 2011-02-16 23:12:16.000000000 +0100 ++++ tar-1.26new/src/incremen.c 2017-01-23 10:58:19.676411754 +0100 +@@ -1580,7 +1580,7 @@ + if (!is_dumpdir (¤t_stat_info)) + return false; + +- current_dir = savedir (directory_name); ++ current_dir = tar_savedir (directory_name, 0); + + if (!current_dir) + /* The directory doesn't exist now. It'll be created. In any +diff -urN tar-1.26/src/misc.c tar-1.26new/src/misc.c +--- tar-1.26/src/misc.c 2011-02-16 23:12:16.000000000 +0100 ++++ tar-1.26new/src/misc.c 2017-01-23 10:58:19.677411762 +0100 +@@ -483,7 +483,7 @@ + + case RECURSIVE_REMOVE_OPTION: + { +- char *directory = savedir (file_name); ++ char *directory = tar_savedir (file_name, 0); + char const *entry; + size_t entrylen; + +@@ -945,3 +945,31 @@ + strcpy (buf->buffer + buf->dir_length, name); + return buf->buffer; + } ++ ++/* Return the filenames in directory NAME, relative to the chdir_fd. ++ If the directory does not exist, report error if MUST_EXIST is ++ true. ++ ++ Return NULL on errors. ++*/ ++char * ++tar_savedir (const char *name, int must_exist) ++{ ++ char *ret = NULL; ++ DIR *dir = NULL; ++ int fd = openat (chdir_fd, name, open_read_flags | O_DIRECTORY); ++ if (fd < 0) ++ { ++ if (!must_exist && errno == ENOENT) ++ return NULL; ++ open_error (name); ++ } ++ else if (! ((dir = fdopendir (fd)) ++ && (ret = streamsavedir (dir)))) ++ savedir_error (name); ++ ++ if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0) ++ savedir_error (name); ++ ++ return ret; ++} +diff -urN tar-1.26/src/update.c tar-1.26new/src/update.c +--- tar-1.26/src/update.c 2017-01-24 09:43:08.620550423 +0100 ++++ tar-1.26new/src/update.c 2017-01-23 12:29:20.410943374 +0100 +@@ -144,16 +144,8 @@ + { + if (S_ISDIR (s.st_mode)) + { +- char *p, *dirp; +- DIR *stream; +- int fd = openat (chdir_fd, name->name, +- open_read_flags | O_DIRECTORY); +- if (fd < 0) +- open_error (name->name); +- else if (! ((stream = fdopendir (fd)) +- && (dirp = streamsavedir (stream)))) +- savedir_error (name->name); +- else ++ char *p, *dirp = tar_savedir (name->name, 1); ++ if (dirp) + { + namebuf_t nbuf = namebuf_create (name->name); + +@@ -166,11 +158,6 @@ + + remname (name); + } +- +- if (stream +- ? closedir (stream) != 0 +- : 0 <= fd && close (fd) != 0) +- savedir_error (name->name); + } + else if (tar_timespec_cmp (get_stat_mtime (&s), + current_stat_info.mtime) +diff -urN tar-1.26/tests/incr07.at tar-1.26new/tests/incr07.at +--- tar-1.26/tests/incr07.at 1970-01-01 01:00:00.000000000 +0100 ++++ tar-1.26new/tests/incr07.at 2017-01-24 09:39:34.305615960 +0100 +@@ -0,0 +1,112 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# Test suite for GNU tar. ++# Copyright 2009, 2013 Free Software Foundation, Inc. ++# ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++# ++# GNU tar 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 . ++ ++AT_SETUP([incremental restores with -C]) ++AT_KEYWORDS([incremental extract incr07]) ++ ++# Tar 1.26 had problems extracting from incremental restores when given ++# the -C option. The code in incremen.c:try_purge_directory and ++# misc.c:remove_any_file was using savedir(), which ignored eventual changes ++# in the current working directory and caused the malfunctioning. ++# ++# The problem was reported by Piotr Rotter on 2013-03-22. ++# ++# This testcase is based on scripts provided by Piotr Rotter and Nathan ++# Stratton Treadway. ++# ++# References: <514C8F56.90900@active24.pl>, ++# http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00036.html, ++# <20130326181922.GZ3732@shire.ontko.com>, ++# http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00042.html, ++# <20130327051828.GA3732@shire.ontko.com>, ++# http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00043.html, ++# <20130327054957.GB3732@shire.ontko.com>, ++# http://lists.gnu.org/archive/html/bug-tar/2013-03/msg00044.html ++ ++AT_TAR_CHECK([ ++mkdir dirA ++echo 'a' > dirA/a ++echo 'a' > dirA/b ++ ++decho C0 ++tar -g test.snar -vcf test.0.tar dirA ++ ++echo 'a' > dirA/c ++decho C1 ++tar -g test.snar -vcf test.1.tar dirA ++ ++rm -f dirA/a ++decho C2 ++tar -g test.snar -vcf test.2.tar dirA ++ ++mkdir ext ++rm -rf dirA ++ ++decho E0 ++tar -g test.snar -vxf test.0.tar -C ext/ ++decho E1 ++tar -g test.snar -vxf test.1.tar -C ext/ ++ ++decho E2 ++tar -g test.snar -vxf test.2.tar -C ext/ ++ ++mkdir ext/dirA/dirB ++touch ext/dirA/dirB/file ++ ++decho E3 ++tar -g test.snar -vxf test.2.tar -C ext/ ++ ++echo FIN ++test -d dirA && echo >&2 "toplevel dirA exists" ++exit 0 ++], ++[0], ++[C0 ++dirA/ ++dirA/a ++dirA/b ++C1 ++dirA/ ++dirA/c ++C2 ++dirA/ ++E0 ++dirA/ ++dirA/a ++dirA/b ++E1 ++dirA/ ++dirA/c ++E2 ++dirA/ ++tar: Deleting `dirA/a' ++E3 ++dirA/ ++tar: Deleting `dirA/dirB' ++FIN ++], ++[C0 ++tar: dirA: Directory is new ++C1 ++C2 ++E0 ++E1 ++E2 ++E3 ++],[],[],[gnu, oldgnu, posix]) ++ ++AT_CLEANUP +diff -urN tar-1.26/tests/Makefile.am tar-1.26new/tests/Makefile.am +--- tar-1.26/tests/Makefile.am 2017-01-24 09:43:08.656550731 +0100 ++++ tar-1.26new/tests/Makefile.am 2017-01-23 10:58:19.678411770 +0100 +@@ -98,6 +98,7 @@ + incr04.at\ + incr05.at\ + incr06.at\ ++ incr07.at\ + indexfile.at\ + ignfail.at\ + label01.at\ +diff -urN tar-1.26/tests/testsuite.at tar-1.26new/tests/testsuite.at +--- tar-1.26/tests/testsuite.at 2017-01-24 09:43:08.656550731 +0100 ++++ tar-1.26new/tests/testsuite.at 2017-01-23 10:58:19.678411770 +0100 +@@ -259,6 +259,7 @@ + m4_include([incr04.at]) + m4_include([incr05.at]) + m4_include([incr06.at]) ++m4_include([incr07.at]) + + m4_include([filerem01.at]) + m4_include([filerem02.at]) +diff -urN tar-1.26/THANKS tar-1.26new/THANKS +--- tar-1.26/THANKS 2017-01-24 09:43:08.636550560 +0100 ++++ tar-1.26new/THANKS 2017-01-23 10:58:19.674411738 +0100 +@@ -397,6 +397,7 @@ + Philippe Defert defert@cern.ch + Piercarlo Grandi piercarl@sabi.demon.co.uk + Pierce Cantrell cantrell@ee.tamu.edu ++Piotr Rotter piotr.rotter@active24.pl + R. Kent Dybvig dyb@cadence.bloomington.in.us + R. Scott Butler butler@prism.es.dupont.com + Rainer Orth ro@TechFak.Uni-Bielefeld.DE diff --git a/SOURCES/tar-1.26-silence-gcc.patch b/SOURCES/tar-1.26-silence-gcc.patch index a2a8f6b..3286a1b 100644 --- a/SOURCES/tar-1.26-silence-gcc.patch +++ b/SOURCES/tar-1.26-silence-gcc.patch @@ -101,19 +101,6 @@ index 273269a..796d7aa 100644 dumpdir_buffer = directory_contents (scan_directory (¤t_stat_info)); -diff --git a/src/update.c b/src/update.c -index 4739e0d..3b28734 100644 ---- a/src/update.c -+++ b/src/update.c -@@ -145,7 +145,7 @@ update_archive (void) - if (S_ISDIR (s.st_mode)) - { - char *p, *dirp; -- DIR *stream; -+ DIR *stream = NULL; /* upstream commit 5bb043350790 */ - int fd = openat (chdir_fd, name->name, - open_read_flags | O_DIRECTORY); - if (fd < 0) diff --git a/tests/genfile.c b/tests/genfile.c index 8541be6..fa480ef 100644 --- a/tests/genfile.c diff --git a/SOURCES/tar-1.26-xattrs-exclude-include-repair.patch b/SOURCES/tar-1.26-xattrs-exclude-include-repair.patch new file mode 100644 index 0000000..7c214aa --- /dev/null +++ b/SOURCES/tar-1.26-xattrs-exclude-include-repair.patch @@ -0,0 +1,121 @@ +diff -urN tar-1.26/src/xattrs.c tar-1.26new/src/xattrs.c +--- tar-1.26/src/xattrs.c 2017-01-10 10:58:11.894958586 +0100 ++++ tar-1.26new/src/xattrs.c 2017-01-10 11:54:23.418221159 +0100 +@@ -436,8 +436,12 @@ + clear_mask_map (&xattrs_setup.excl); + } + +-/* get all xattrs from file given by FILE_NAME or FD (when non-zero). This +- includes all the user.*, security.*, system.*, etc. available domains */ ++static bool xattrs_masked_out (const char *kw, bool archiving); ++ ++/* get xattrs from file given by FILE_NAME or FD (when non-zero) ++ xattrs are checked against the user supplied include/exclude mask ++ if no mask is given this includes all the user.*, security.*, system.*, ++ etc. available domains */ + void + xattrs_xattrs_get (int parentfd, char const *file_name, + struct tar_stat_info *st, int fd) +@@ -482,8 +486,6 @@ + size_t len = strlen (attr); + ssize_t aret = 0; + +- /* Archive all xattrs during creation, decide at extraction time +- * which ones are of interest/use for the target filesystem. */ + while (((fd == 0) + ? ((aret = lgetxattrat (parentfd, file_name, attr, + val, asz)) == -1) +@@ -494,7 +496,10 @@ + } + + if (aret != -1) +- xheader_xattr_add (st, attr, val, aret); ++ { ++ if (!xattrs_masked_out (attr, true)) ++ xheader_xattr_add (st, attr, val, aret); ++ } + else if (errno != ENOATTR) + call_arg_warn ((fd == 0) ? "lgetxattrat" + : "fgetxattr", file_name); +diff -urN tar-1.26/tests/Makefile.am tar-1.26new/tests/Makefile.am +--- tar-1.26/tests/Makefile.am 2017-01-10 10:58:11.894958586 +0100 ++++ tar-1.26new/tests/Makefile.am 2017-01-10 11:53:55.046987231 +0100 +@@ -177,6 +177,7 @@ + xattr03.at\ + xattr04.at\ + xattr05.at\ ++ xattr06.at\ + acls01.at\ + acls02.at\ + acls03.at\ +diff -urN tar-1.26/tests/testsuite.at tar-1.26new/tests/testsuite.at +--- tar-1.26/tests/testsuite.at 2017-01-10 10:58:11.896958604 +0100 ++++ tar-1.26new/tests/testsuite.at 2017-01-10 11:53:55.047987240 +0100 +@@ -338,6 +338,7 @@ + m4_include([xattr03.at]) + m4_include([xattr04.at]) + m4_include([xattr05.at]) ++m4_include([xattr06.at]) + + m4_include([acls01.at]) + m4_include([acls02.at]) +diff -urN tar-1.26/tests/xattr06.at tar-1.26new/tests/xattr06.at +--- tar-1.26/tests/xattr06.at 1970-01-01 01:00:00.000000000 +0100 ++++ tar-1.26new/tests/xattr06.at 2017-01-10 11:54:23.418221159 +0100 +@@ -0,0 +1,56 @@ ++# Process this file with autom4te to create testsuite. -*- Autotest -*- ++# ++# Test suite for GNU tar. ++# Copyright 2012-2014, 2016 Free Software Foundation, Inc. ++ ++# This file is part of GNU tar. ++ ++# GNU tar 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 of the License, or ++# (at your option) any later version. ++ ++# GNU tar 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 . ++# ++# Test description: Test for exclude of xattr during archive creation ++# ++# Relevant mailing list thread: ++# ++# http://lists.gnu.org/archive/html/bug-tar/2016-05/msg00031.html ++ ++AT_SETUP([xattrs: exclude xattrs on create ]) ++AT_KEYWORDS([xattrs xattr06]) ++ ++AT_TAR_CHECK([ ++AT_XATTRS_PREREQ ++ ++mkdir dir ++mkdir output ++genfile --file dir/file ++ ++for attr in excluded incla inclb inclc incl_excluded ++do ++ setfattr -n user.${attr} -v value dir/file || AT_SKIP_TEST ++done ++ ++tar --xattrs-include=user.incl'*' --xattrs-exclude=user.incl_excluded -cf archive.tar -C dir . ++tar -xf archive.tar --xattrs-include=user.incl[[ab]] --xattrs-exclude=user.inclb -C output ++ ++getfattr -d output/file | grep -v \ ++ -e excluded \ ++ -e inclb \ ++ -e inclc > filtered ++getfattr -d output/file > full ++# if they differ then the attribute is still present ++diff filtered full ++], ++[0], ++[]) ++ ++AT_CLEANUP diff --git a/SPECS/tar.spec b/SPECS/tar.spec index f0a3736..7ec80bf 100644 --- a/SPECS/tar.spec +++ b/SPECS/tar.spec @@ -5,7 +5,7 @@ Summary: A GNU file archiving program Name: tar Epoch: 2 Version: 1.26 -Release: 31%{?dist} +Release: 32%{?dist} License: GPLv3+ Group: Applications/Archiving URL: http://www.gnu.org/software/tar/ @@ -128,6 +128,29 @@ Patch19: tar-1.26-default-acls.patch # ~> rhbz#1347396 Patch20: tar-1.26-dont-segfault-with-disabled-selinux.patch +# Restore incremental backups correctly, files were not being removed +# ~> upstream commits: 738fb9c2f44 b6979c7278e f86e0605d0e +# ~> rhbz#1184697 +Patch21: tar-1.26-restore-incremental-backups.patch + +# Fix the behavior of tar when --directory option is used together with +# --remove-files. +# ~> upstream commits: e3d28d84bda b41b004638f f7077dd38b0 d3fd92c6fb2 +# d28eee6b4f1 74ce228f6df 3125d311e17 3de5db2a151 fc58a8bd984 +# fcde08534bd e6fcc73efa7 +# ~> rhbz#1319820 +Patch22: tar-1.26-directory_with_remove-files.patch + +# Repair the ignorance of --xattrs-exclude/include options +# ~> upstream: bb6ddd8e04c and c81a0853bb8 +# ~> rhbz#1341786 +Patch23: tar-1.26-xattrs-exclude-include-repair.patch + +# Intorduce new option "--keep-directory-symlink", backported from version 1.27 +# ~> upstream: 2c06a809180 +# ~> rhbz#1350640 +Patch24: tar-1.26-keep-directory-symlink.patch + # Silence gcc warnings # ~> upstream tar: 17f99bc6f, 5bb0433 # ~> upstream paxutils: 0b3d84a0 @@ -186,6 +209,10 @@ the rmt package on the remote box. %patch18 -p1 -b .sparse-stat-detection %patch19 -p1 -b .default-acls %patch20 -p1 -b .disabled-selinux +%patch21 -p1 -b .incremental-backups +%patch22 -p1 -b .directory +%patch23 -p1 -b .xattrs-exclude-include +%patch24 -p1 -b .keep-directory-symlink %patch999 -p1 -b .silence-gcc autoreconf -v @@ -244,6 +271,13 @@ fi %{_infodir}/tar.info* %changelog +* Tue Feb 28 2017 Tomas Repik - 2:1.26-32 +- restore incremental backups correctly, files were not being removed (rhbz#1184697) +- fix the behavior of tar when --directory option is used together with + --remove-files +- repair the ignorance of --xattrs-exclude/include options (rhbz#1341786) +- Intorduce new option '--keep-directory-symlink' + * Mon Jun 20 2016 Pavel Raiskup - 1.26-31 - avoid double free in selinux code (rhbz#1347396)