aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-02-07 10:28:38 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-02-07 10:28:38 +0000
commit0f8f9a6491c4a58497c9b5f436113ea97350868a (patch)
treed6e0f2a199a89551cbe9a9d529ced00a7565656a
parent647c2d567f50671fa83d69e9154dec27f8101940 (diff)
downloadpaludis-0f8f9a6491c4a58497c9b5f436113ea97350868a.tar.gz
paludis-0f8f9a6491c4a58497c9b5f436113ea97350868a.tar.xz
Handle overwrites of strange symlinks correctly. Fixes: Gentoo#165600
-rw-r--r--ebuild/merge.cc44
1 files changed, 38 insertions, 6 deletions
diff --git a/ebuild/merge.cc b/ebuild/merge.cc
index 1df5b86..b7a4439 100644
--- a/ebuild/merge.cc
+++ b/ebuild/merge.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -117,18 +117,28 @@ namespace
dst_dir_str.clear();
cout << ">>> " << std::setw(5) << std::left << "[dir]" << " " <<
- dst_dir_str.substr(root_str.length()) << "/" << dst_dir.basename() << endl;
+ dst_dir_str.substr(root_str.length()) << "/" << dst_dir.basename();
if (dst_dir.is_directory())
- /* nothing */;
+ {
+ cout << " <dir>" << endl;
+ }
else if (dst_dir.is_symbolic_link() && dst_dir.realpath().is_directory())
+ {
Log::get_instance()->message(ll_qa, lc_no_context, "Expected '" + stringify(dst_dir) +
"' to be a directory or non-existent, but found a symlink to a directory");
+ cout << " <sym -> dir>" << endl;
+ }
else if (dst_dir.exists())
+ {
+ cout << " <obj>" << endl;
throw Failure("Expected '" + stringify(dst_dir) +
"' to be a directory or non-existent, but found a file");
+ }
else
{
+ cout << " <new>" << endl;
+
mode_t mode(src_dir.permissions());
#ifdef HAVE_SELINUX
@@ -182,7 +192,10 @@ namespace
dst_dir_str.substr(root_str.length()) << "/" << dst.basename();
if (dst.is_directory())
+ {
+ cout << " <dir>" << endl;
throw Failure("Cannot overwrite directory '" + stringify(dst) + "' with a file");
+ }
else
{
FSEntry real_dst(dst);
@@ -205,6 +218,8 @@ namespace
{
if (dst.is_regular_file())
{
+ cout << " <obj>" << endl;
+
mode_t mode(dst.permissions());
if ((mode & S_ISUID) || (mode & S_ISGID))
{
@@ -213,11 +228,20 @@ namespace
}
FSEntry(dst).unlink();
}
- cout << endl;
+ else if (dst.is_symbolic_link())
+ {
+ cout << " <sym>" << endl;
+ FSEntry(dst).unlink();
+ }
+ else
+ {
+ cout << " <?""?""?>" << endl;
+ FSEntry(dst).unlink();
+ }
}
}
else
- cout << endl;
+ cout << " <new>" << endl;
/* FDHolder must be destroyed before we do the md5 thing, or the
* disk write may not have synced. */
@@ -274,15 +298,21 @@ namespace
dst_dir_str.clear();
cout << ">>> " << std::setw(5) << std::left << "[sym]" << " " <<
- dst_dir_str.substr(root_str.length()) << "/" << dst.basename() << endl;
+ dst_dir_str.substr(root_str.length()) << "/" << dst.basename();
if (dst.exists())
{
if (dst.is_directory())
throw Failure("Can't overwrite directory '" + stringify(dst) +
"' with symlink to '" + src.readlink() + "'");
+ else if (dst.is_symbolic_link())
+ {
+ cout << " <sym>" << endl;
+ FSEntry(dst).unlink();
+ }
else
{
+ cout << " <obj>" << endl;
mode_t mode(dst.permissions());
if ((mode & S_ISUID) || (mode & S_ISGID))
{
@@ -292,6 +322,8 @@ namespace
FSEntry(dst).unlink();
}
}
+ else
+ cout << " <new>" << endl;
#ifdef HAVE_SELINUX
// permissions() on a symlink does weird things, but matchpathcon only cares about the file type,