aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ingmar Vanhassel <ingmar@exherbo.org> 2009-01-05 20:05:50 +0100
committerAvatar Ingmar Vanhassel <ingmar@exherbo.org> 2009-01-09 22:59:13 +0100
commita8ff499710868d8cdb83618acb2670ad737d3582 (patch)
treebef46394455866614ebd9d8ed268e060840d5ae1
parent43294985769794d6959d1f9ac565d63cf9a8f8e8 (diff)
downloadpaludis-a8ff499710868d8cdb83618acb2670ad737d3582.tar.gz
paludis-a8ff499710868d8cdb83618acb2670ad737d3582.tar.xz
Fix an unmerger cornercase.
When unmerging a file whose parent directory got replaced by a file, paludis would throw an unhandled exception. * When calling stat() on '/var/lib/games/emacs/tetris-scores/.keep_app-editors_emacs-22': * Error running stat() on '/var/lib/games/emacs/tetris-scores/.keep_app-editors_emacs-22': Not a directory (paludis::FSError) Patch by Ferdy, testcases by me.
-rw-r--r--paludis/ndbam_unmerger.cc13
-rw-r--r--paludis/repositories/e/vdb_unmerger.cc16
-rw-r--r--paludis/repositories/e/vdb_unmerger_TEST.cc10
-rwxr-xr-xpaludis/repositories/e/vdb_unmerger_TEST_setup.sh4
-rw-r--r--paludis/util/fs_entry.cc2
-rw-r--r--paludis/util/fs_entry_TEST.cc3
-rwxr-xr-xpaludis/util/fs_entry_TEST_setup.sh2
7 files changed, 42 insertions, 8 deletions
diff --git a/paludis/ndbam_unmerger.cc b/paludis/ndbam_unmerger.cc
index 70ac562..d0fd485 100644
--- a/paludis/ndbam_unmerger.cc
+++ b/paludis/ndbam_unmerger.cc
@@ -218,7 +218,9 @@ NDBAMUnmerger::check_file(const FSEntry & f, const std::tr1::shared_ptr<ExtraInf
{
std::tr1::shared_ptr<FileExtraInfo> fie(std::tr1::static_pointer_cast<FileExtraInfo>(ei));
- if (! (_imp->options.root() / f).is_regular_file())
+ if (! (_imp->options.root() / f).exists())
+ display("--- [gone ] " + stringify(f));
+ else if (! (_imp->options.root() / f).is_regular_file())
display("--- [!type] " + stringify(f));
else if ((_imp->options.root() / f).mtime() != fie->_mtime)
display("--- [!time] " + stringify(f));
@@ -247,7 +249,10 @@ NDBAMUnmerger::check_sym(const FSEntry & f, const std::tr1::shared_ptr<ExtraInfo
{
std::tr1::shared_ptr<SymlinkExtraInfo> sie(std::tr1::static_pointer_cast<SymlinkExtraInfo>(ei));
- if (! (_imp->options.root() / f).is_symbolic_link())
+
+ if (! (_imp->options.root() / f).exists())
+ display("--- [gone ] " + stringify(f));
+ else if (! (_imp->options.root() / f).is_symbolic_link())
display("--- [!type] " + stringify(f));
else if ((_imp->options.root() / f).mtime() != sie->_mtime)
display("--- [!time] " + stringify(f));
@@ -268,7 +273,9 @@ NDBAMUnmerger::check_misc(const FSEntry &, const std::tr1::shared_ptr<ExtraInfo>
bool
NDBAMUnmerger::check_dir(const FSEntry & f, const std::tr1::shared_ptr<ExtraInfo> &) const
{
- if (! (_imp->options.root() / f).is_directory())
+ if (! (_imp->options.root() / f).exists())
+ display("--- [gone ] " + stringify(f));
+ else if (! (_imp->options.root() / f).is_directory())
display("--- [!type] " + stringify(f));
else if (DirIterator(_imp->options.root() / f, DirIteratorOptions() + dio_include_dotfiles + dio_first_only) != DirIterator())
display("--- [!empt] " + stringify(f));
diff --git a/paludis/repositories/e/vdb_unmerger.cc b/paludis/repositories/e/vdb_unmerger.cc
index cfb7dcd..f05a7ee 100644
--- a/paludis/repositories/e/vdb_unmerger.cc
+++ b/paludis/repositories/e/vdb_unmerger.cc
@@ -255,7 +255,9 @@ VDBUnmerger::check_file(const FSEntry & f, const std::tr1::shared_ptr<ExtraInfo>
{
std::tr1::shared_ptr<FileExtraInfo> fie(std::tr1::static_pointer_cast<FileExtraInfo>(ei));
- if (! (_imp->options.root() / f).is_regular_file())
+ if (! (_imp->options.root() / f).exists())
+ display("--- [gone ] " + stringify(f));
+ else if (! (_imp->options.root() / f).is_regular_file())
display("--- [!type] " + stringify(f));
else if ((_imp->options.root() / f).mtime() != fie->_mtime)
display("--- [!time] " + stringify(f));
@@ -284,7 +286,9 @@ VDBUnmerger::check_sym(const FSEntry & f, const std::tr1::shared_ptr<ExtraInfo>
{
std::tr1::shared_ptr<SymlinkExtraInfo> sie(std::tr1::static_pointer_cast<SymlinkExtraInfo>(ei));
- if (! (_imp->options.root() / f).is_symbolic_link())
+ if (! (_imp->options.root() / f).exists())
+ display("--- [gone ] " + stringify(f));
+ else if (! (_imp->options.root() / f).is_symbolic_link())
display("--- [!type] " + stringify(f));
else if ((_imp->options.root() / f).mtime() != sie->_mtime)
display("--- [!time] " + stringify(f));
@@ -301,7 +305,9 @@ VDBUnmerger::check_misc(const FSEntry & f, const std::tr1::shared_ptr<ExtraInfo>
{
std::tr1::shared_ptr<MiscExtraInfo> mie(std::tr1::static_pointer_cast<MiscExtraInfo>(ei));
- if ("fif" == mie->_type && ! (_imp->options.root() / f).is_fifo())
+ if (! (_imp->options.root() / f).exists())
+ display("--- [gone ] " + stringify(f));
+ else if ("fif" == mie->_type && ! (_imp->options.root() / f).is_fifo())
display("--- [!type] " + stringify(f));
else if ("dev" == mie->_type && ! (_imp->options.root() / f).is_device())
display("--- [!type] " + stringify(f));
@@ -314,7 +320,9 @@ VDBUnmerger::check_misc(const FSEntry & f, const std::tr1::shared_ptr<ExtraInfo>
bool
VDBUnmerger::check_dir(const FSEntry & f, const std::tr1::shared_ptr<ExtraInfo> &) const
{
- if (! (_imp->options.root() / f).is_directory())
+ if (! (_imp->options.root() / f).exists())
+ display("--- [gone ] " + stringify(f));
+ else if (! (_imp->options.root() / f).is_directory())
display("--- [!type] " + stringify(f));
else if (DirIterator(_imp->options.root() / f, DirIteratorOptions() + dio_include_dotfiles + dio_first_only) != DirIterator())
display("--- [!empt] " + stringify(f));
diff --git a/paludis/repositories/e/vdb_unmerger_TEST.cc b/paludis/repositories/e/vdb_unmerger_TEST.cc
index 7ca2b45..ac6a19e 100644
--- a/paludis/repositories/e/vdb_unmerger_TEST.cc
+++ b/paludis/repositories/e/vdb_unmerger_TEST.cc
@@ -180,6 +180,16 @@ namespace test_cases
}
} test_vdb_unmerger_file_bad_mtime;
+ struct VDBUnmergerTestFileReplacesDirectory : VDBUnmergerTest
+ {
+ VDBUnmergerTestFileReplacesDirectory() : VDBUnmergerTest("file_replaces_dir") { }
+
+ void run()
+ {
+ unmerger.unmerge();
+ }
+ } test_vdb_unmerger_file_replaces_directory;
+
struct VDBUnmergerTestDirOk : VDBUnmergerTest
{
VDBUnmergerTestDirOk() : VDBUnmergerTest("dir_ok") { }
diff --git a/paludis/repositories/e/vdb_unmerger_TEST_setup.sh b/paludis/repositories/e/vdb_unmerger_TEST_setup.sh
index c9fba88..35ce29d 100755
--- a/paludis/repositories/e/vdb_unmerger_TEST_setup.sh
+++ b/paludis/repositories/e/vdb_unmerger_TEST_setup.sh
@@ -44,6 +44,10 @@ make_file "bad_md5sum" "bad_md5sum"
make_file "bad_mtime" "" "123"
echo "obj /file_bad_entry foo" > ../CONTENTS/file_bad_entry
+echo "dir /file_replaces_dir" > ../CONTENTS/file_replaces_dir
+echo "obj /file_replaces_dir/foo 00000000000000000000000 123" >> ../CONTENTS/file_replaces_dir
+> file_replaces_dir
+
mkdir dir_ok
echo "dir /dir_ok" > ../CONTENTS/dir_ok
diff --git a/paludis/util/fs_entry.cc b/paludis/util/fs_entry.cc
index 30ba051..ecea5cd 100644
--- a/paludis/util/fs_entry.cc
+++ b/paludis/util/fs_entry.cc
@@ -404,7 +404,7 @@ FSEntry::_stat() const
_imp->stat_info.reset(new struct stat);
if (0 != lstat(_imp->path.c_str(), _imp->stat_info.get()))
{
- if (errno != ENOENT)
+ if (errno != ENOENT && errno != ENOTDIR)
throw FSError("Error running stat() on '" + stringify(_imp->path) + "': "
+ strerror(errno));
diff --git a/paludis/util/fs_entry_TEST.cc b/paludis/util/fs_entry_TEST.cc
index 6e40b4a..ec1fcfd 100644
--- a/paludis/util/fs_entry_TEST.cc
+++ b/paludis/util/fs_entry_TEST.cc
@@ -189,6 +189,9 @@ namespace test_cases
FSEntry k("fs_entry_TEST_dir/dir_a/file_in_a");
TEST_CHECK_THROWS(k.mkdir(), FSError);
+
+ FSEntry l("fs_entry_TEST_dir/file_a/file_that_triggers_ENOTDIR");
+ TEST_CHECK(! l.exists());
}
} test_fs_entry_behaviour;
diff --git a/paludis/util/fs_entry_TEST_setup.sh b/paludis/util/fs_entry_TEST_setup.sh
index a8efc9a..64134bf 100755
--- a/paludis/util/fs_entry_TEST_setup.sh
+++ b/paludis/util/fs_entry_TEST_setup.sh
@@ -16,6 +16,8 @@ chmod 000 no_perms || exit 10
mkdir dir_a/dir_in_a
+touch file_a || exit 13
+
echo -n '0123456789' > ten_bytes || exit 11
ln -s dir_a/file_in_a symlink_to_file_in_a || exit 12
sleep 1