From 643a8844a578ff146cfe746fe6091d29502b6c40 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sat, 3 Nov 2012 13:31:48 +0200 Subject: [PATCH] Fix creation of incremental archives when a subdirectory becomes a mountpoint. When used with --listed-incrfental and --one-file-system, tar was unable to cope with directories that had once been part of the dumped system and became separate mount points afterwards. The bug has been reported and a fix proposed by Nathan Stratton Treadway. * src/incremen.c (procdir): If one_file_system_option is in effect, clear out dumpdir info from the directory. * tests/Makefile.am: Add new testcase. * tests/listed05.at: New testcase. * tests/testsuite.at (AT_PRIVILEGED_PREREQ): New macro. include listed05.at. * THANKS: Update. --- THANKS | 1 + src/incremen.c | 34 ++++++++++++++------- tests/Makefile.am | 1 + tests/listed05.at | 76 ++++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 11 +++++++ 5 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 tests/listed05.at diff --git a/THANKS b/THANKS index 0364c50..f9e468d 100644 --- a/THANKS +++ b/THANKS @@ -358,6 +358,7 @@ Milan Hodoscek milan@kihp6.ki.si Minh Tran-Le tranle@intellicorp.com Mitsuaki Masuhara masuhara@mcprv.mec.mei.co.jp Nate Eldredge nate@cs.hmc.edu +Nathan Stratton Treadway nathanst+bugtar@ontko.com Neil Faulks neil@dcs.kcl.ac.uk Neil Jerram nj104@cus.cam.ac.uk Nelson H.F. Beebe beebe@math.utah.edu diff --git a/src/incremen.c b/src/incremen.c index 04b946f..d5bc1e4 100644 --- a/src/incremen.c +++ b/src/incremen.c @@ -446,7 +446,8 @@ procdir (const char *name_buffer, struct tar_stat_info *st, struct directory *directory; struct stat *stat_data = &st->stat; bool nfs = NFS_FILE_STAT (*stat_data); - + bool perhaps_renamed = false; + if ((directory = find_directory (name_buffer)) != NULL) { if (DIR_IS_INITED (directory)) @@ -500,9 +501,7 @@ procdir (const char *name_buffer, struct tar_stat_info *st, } else { - WARNOPT (WARN_RENAME_DIRECTORY, - (0, 0, _("%s: Directory has been renamed"), - quotearg_colon (name_buffer))); + perhaps_renamed = true; directory->children = ALL_CHILDREN; directory->device_number = stat_data->st_dev; directory->inode_number = stat_data->st_ino; @@ -560,13 +559,21 @@ procdir (const char *name_buffer, struct tar_stat_info *st, if (one_file_system_option && st->parent && stat_data->st_dev != st->parent->stat.st_dev) - /* FIXME: - WARNOPT (WARN_XDEV, - (0, 0, - _("%s: directory is on a different filesystem; not dumped"), - quotearg_colon (directory->name))); - */ - directory->children = NO_CHILDREN; + { + WARNOPT (WARN_XDEV, + (0, 0, + _("%s: directory is on a different filesystem; not dumped"), + quotearg_colon (directory->name))); + directory->children = NO_CHILDREN; + /* If there is any dumpdir info in that directory, remove it */ + if (directory->dump) + { + dumpdir_free (directory->dump); + directory->dump = NULL; + } + perhaps_renamed = false; + } + else if (flag & PD_FORCE_CHILDREN) { directory->children = PD_CHILDREN(flag); @@ -574,6 +581,11 @@ procdir (const char *name_buffer, struct tar_stat_info *st, *entry = 'N'; } + if (perhaps_renamed) + WARNOPT (WARN_RENAME_DIRECTORY, + (0, 0, _("%s: Directory has been renamed"), + quotearg_colon (name_buffer))); + DIR_SET_FLAG (directory, DIRF_INIT); if (directory->children != NO_CHILDREN) diff --git a/tests/Makefile.am b/tests/Makefile.am index 4601e0e..47afea1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -114,6 +114,7 @@ TESTSUITE_AT = \ listed02.at\ listed03.at\ listed04.at\ + listed05.at\ long01.at\ longv7.at\ lustar01.at\ diff --git a/tests/listed05.at b/tests/listed05.at new file mode 100644 index 0000000..ea851ed --- /dev/null +++ b/tests/listed05.at @@ -0,0 +1,76 @@ +# Process this file with autom4te to create testsuite. -*- Autotest -*- +# +# Test suite for GNU tar. +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Tar up to 1.26 was unable to cope with directories that had once +# been part of the dumped system and became separate mount points +# afterwards. The bug has been reported by Nathan Stratton Treadway, +# who also proposed a fix and a testcase, on which the present one is +# built. +# Reported-by: Nathan Stratton Treadway +# Last-Affected-Version: 1.26 +# References: <20120527212417.GR2654@shire.ontko.com> +# http://lists.gnu.org/archive/html/bug-tar/2012-05/msg00022.html + +# This testcase is Linux-specific and requires root privileges. + +AT_SETUP([--listed-incremental and remounted directories]) +AT_KEYWORDS([listed incremental listed05]) + +AT_TAR_CHECK([ +AT_PRIVILEGED_PREREQ +options="-C tartest --create --one-file-system --verbose" +rm -rf archive-[01].snar archive-[01].tar tartest subdir + +# Create initial structure +mkdir tartest +echo "hi" > tartest/top-level-file +mkdir tartest/subdir +echo "hi" > tartest/subdir/subdir-file + +echo "# Level 0" +tar $options --file archive-0.tar --listed-incremental=archive-0.snar . + +echo "# Remount" +mv tartest/subdir . +mkdir tartest/subdir +mount -t ramfs none tartest/subdir || AT_SKIP_TEST +tar -C subdir -c -f - . | tar -C tartest/subdir -x -f - + +echo "# Level 1" +cp archive-0.snar archive-1.snar +tar $options --file archive-1.tar --listed-incremental=archive-1.snar . + +umount tartest/subdir +], +[0], +[# Level 0 +./ +./subdir/ +./top-level-file +./subdir/subdir-file +# Remount +# Level 1 +./ +./subdir/ +], +[tar: .: Directory is new +tar: ./subdir: Directory is new +tar: ./subdir: directory is on a different filesystem; not dumped +],[],[],[gnu]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index 97f5e41..d5c6023 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -103,6 +103,16 @@ rm -f $[]$ test $result -eq 0 && AT_SKIP_TEST ]) +dnl AT_PRIVILEGED_PREREQ - Skip test if not running at root privileges +m4_define([AT_PRIVILEGED_PREREQ],[ +echo "test" > $[]$ +chmod 0 $[]$ +cat $[]$ > /dev/null 2>&1 +result=$? +rm -f $[]$ +test $result -eq 0 || AT_SKIP_TEST +]) + m4_define([AT_TAR_MKHIER],[ install-sh -d $1 >/dev/null dnl m4_if([$2],,,&& genfile --file [$1]/[$2]) || AT_SKIP_TEST]) @@ -186,6 +196,7 @@ m4_include([listed01.at]) m4_include([listed02.at]) m4_include([listed03.at]) m4_include([listed04.at]) +m4_include([listed05.at]) m4_include([incr03.at]) m4_include([incr04.at]) m4_include([incr05.at]) -- 2.45.2