aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-02-10 01:54:02 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2009-02-10 01:54:02 +0000
commitadf7d7f87e7701dd5dee402ac396c231489fde1d (patch)
tree4c0adfbef2d913d331182c2379b304628826afbf
parent58d9dd98d1bdfa81b810b9742c3f4cd93f6a5f8f (diff)
parent8772b7a5c74c3254a53e70a922e9e0a2bc1c09c3 (diff)
downloadpaludis-adf7d7f87e7701dd5dee402ac396c231489fde1d.tar.gz
paludis-adf7d7f87e7701dd5dee402ac396c231489fde1d.tar.xz
Merge commit 'git-pioto-org/master' into logging
-rw-r--r--.gitignore2
-rw-r--r--paludis/environments/paludis/paludis_config.cc3
-rw-r--r--paludis/environments/paludis/world.cc11
-rw-r--r--paludis/environments/portage/portage_environment.cc11
-rw-r--r--paludis/hooker_TEST.cc14
-rw-r--r--paludis/merger_TEST.cc16
-rw-r--r--paludis/ndbam.cc6
-rw-r--r--paludis/ndbam_merger.cc13
-rw-r--r--paludis/ndbam_unmerger.cc4
-rw-r--r--paludis/repositories/cran/cran_installed_repository.cc3
-rw-r--r--paludis/repositories/e/check_fetched_files_visitor.cc188
-rw-r--r--paludis/repositories/e/e_installed_repository.cc6
-rw-r--r--paludis/repositories/e/e_installed_repository_id.cc7
-rw-r--r--paludis/repositories/e/e_key.cc6
-rw-r--r--paludis/repositories/e/e_repository.cc15
-rw-r--r--paludis/repositories/e/e_repository_TEST.cc8
-rw-r--r--paludis/repositories/e/e_repository_TEST_ever.cc1
-rw-r--r--paludis/repositories/e/e_repository_news.cc13
-rw-r--r--paludis/repositories/e/ebuild_entries.cc1
-rw-r--r--paludis/repositories/e/ebuild_flat_metadata_cache.cc525
-rw-r--r--paludis/repositories/e/ebuild_flat_metadata_cache_TEST.cc16
-rw-r--r--paludis/repositories/e/ebuild_id.cc1
-rw-r--r--paludis/repositories/e/exndbam_repository.cc10
-rw-r--r--paludis/repositories/e/fetch_visitor_TEST.cc4
-rw-r--r--paludis/repositories/e/qa/changelog.cc6
-rw-r--r--paludis/repositories/e/qa/manifest.cc24
-rw-r--r--paludis/repositories/e/qa/qa_controller.cc8
-rw-r--r--paludis/repositories/e/qa/repo_name.cc6
-rw-r--r--paludis/repositories/e/vdb_merger.cc18
-rw-r--r--paludis/repositories/e/vdb_merger_TEST.cc19
-rw-r--r--paludis/repositories/e/vdb_repository.cc47
-rw-r--r--paludis/repositories/e/vdb_repository_TEST.cc8
-rw-r--r--paludis/repositories/e/vdb_unmerger.cc23
-rw-r--r--paludis/repositories/gems/gems_repository.cc8
-rw-r--r--paludis/repositories/unavailable/unavailable_repository_file.cc8
-rw-r--r--paludis/repositories/unpackaged/installed_id.cc23
-rw-r--r--paludis/repositories/unpackaged/installed_repository.cc18
-rw-r--r--paludis/repositories/unwritten/unwritten_repository_file.cc6
-rw-r--r--paludis/repository_name_cache.cc50
-rw-r--r--paludis/set_file.cc38
-rw-r--r--paludis/set_file_TEST.cc10
-rw-r--r--paludis/sohooks_TEST.cc8
-rw-r--r--paludis/util/config_file.cc21
-rw-r--r--paludis/util/files.m43
-rw-r--r--paludis/util/output_wrapper_TEST.cc3
-rw-r--r--paludis/util/safe_ifstream.cc136
-rw-r--r--paludis/util/safe_ifstream.hh134
-rw-r--r--paludis/util/safe_ifstream_TEST.cc104
-rwxr-xr-xpaludis/util/safe_ifstream_TEST_cleanup.sh9
-rwxr-xr-xpaludis/util/safe_ifstream_TEST_setup.sh17
-rw-r--r--paludis/util/safe_ofstream.cc103
-rw-r--r--paludis/util/safe_ofstream.hh (renamed from paludis/util/fd_output_stream.hh)91
-rw-r--r--paludis/util/safe_ofstream_TEST.cc142
-rwxr-xr-xpaludis/util/safe_ofstream_TEST_cleanup.sh9
-rwxr-xr-xpaludis/util/safe_ofstream_TEST_setup.sh13
-rw-r--r--paludis/util/system.cc6
-rw-r--r--src/clients/accerso/accerso.cc13
-rw-r--r--src/clients/adjutrix/downgrade_check.cc9
-rw-r--r--src/clients/appareo/appareo.cc1
-rw-r--r--src/clients/instruo/instruo.cc13
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc30
-rw-r--r--src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.cc6
-rw-r--r--src/output/console_install_task.cc4
63 files changed, 1374 insertions, 705 deletions
diff --git a/.gitignore b/.gitignore
index 5dda471..2bbf49c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -366,6 +366,8 @@ paludis-*.*.*.tar.bz2
/paludis/util/pretty_print_TEST
/paludis/util/random_TEST
/paludis/util/rmd160_TEST
+/paludis/util/safe_ifstream_TEST
+/paludis/util/safe_ofstream_TEST
/paludis/util/save_TEST
/paludis/util/sha1_TEST
/paludis/util/sha256_TEST
diff --git a/paludis/environments/paludis/paludis_config.cc b/paludis/environments/paludis/paludis_config.cc
index adecc60..157a1f4 100644
--- a/paludis/environments/paludis/paludis_config.cc
+++ b/paludis/environments/paludis/paludis_config.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -54,7 +54,6 @@
#include <tr1/functional>
#include <tr1/unordered_map>
-#include <fstream>
#include <algorithm>
#include <sstream>
#include <list>
diff --git a/paludis/environments/paludis/world.cc b/paludis/environments/paludis/world.cc
index 94e5ee9..f78daca 100644
--- a/paludis/environments/paludis/world.cc
+++ b/paludis/environments/paludis/world.cc
@@ -24,11 +24,11 @@
#include <paludis/util/stringify.hh>
#include <paludis/util/log.hh>
#include <paludis/util/make_named_values.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/set_file.hh>
#include <paludis/user_dep_spec.hh>
#include <paludis/dep_tag.hh>
#include <tr1/functional>
-#include <fstream>
using namespace paludis;
using namespace paludis::paludis_environment;
@@ -103,11 +103,14 @@ World::_add_string_to_world(const std::string & n) const
if (! _imp->maybe_world_file->exists())
{
- std::ofstream f(stringify(*_imp->maybe_world_file).c_str());
- if (! f)
+ try
+ {
+ SafeOFStream f(*_imp->maybe_world_file);
+ }
+ catch (const SafeOFStreamError & e)
{
Log::get_instance()->message("paludis_environment.world.cannot_create", ll_warning, lc_no_context)
- << "Cannot create world file '" << *_imp->maybe_world_file << "'";
+ << "Cannot create world file '" << *_imp->maybe_world_file << "': '" << e.message() << "' (" << e.what() << ")";
return;
}
}
diff --git a/paludis/environments/portage/portage_environment.cc b/paludis/environments/portage/portage_environment.cc
index 7334611..6de6167 100644
--- a/paludis/environments/portage/portage_environment.cc
+++ b/paludis/environments/portage/portage_environment.cc
@@ -38,6 +38,7 @@
#include <paludis/util/tribool.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/standard_output_manager.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/hooker.hh>
#include <paludis/hook.hh>
#include <paludis/mask.hh>
@@ -58,7 +59,6 @@
#include <map>
#include <vector>
#include <list>
-#include <fstream>
#include "config.h"
using namespace paludis;
@@ -904,11 +904,14 @@ PortageEnvironment::_add_string_to_world(const std::string & s) const
if (! _imp->world_file.exists())
{
- std::ofstream f(stringify(_imp->world_file).c_str());
- if (! f)
+ try
+ {
+ SafeOFStream f(_imp->world_file);
+ }
+ catch (const SafeOFStreamError & e)
{
Log::get_instance()->message("portage_environment.world.write_failed", ll_warning, lc_no_context)
- << "Cannot create world file '" << _imp->world_file << "'";
+ << "Cannot create world file '" << _imp->world_file << "': '" << e.message() << "' (" << e.what() << ")";
return;
}
}
diff --git a/paludis/hooker_TEST.cc b/paludis/hooker_TEST.cc
index 17ea9ec..91607ad 100644
--- a/paludis/hooker_TEST.cc
+++ b/paludis/hooker_TEST.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -23,9 +23,9 @@
#include <paludis/environments/test/test_environment.hh>
#include <paludis/util/fs_entry.hh>
#include <paludis/util/make_named_values.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <test/test_runner.hh>
#include <test/test_framework.hh>
-#include <fstream>
#include <iterator>
using namespace test;
@@ -80,7 +80,7 @@ namespace test_cases
TEST_CHECK_EQUAL(result.max_exit_status(), 0);
TEST_CHECK_EQUAL(result.output(), "");
- std::ifstream f(stringify(FSEntry("hooker_TEST_dir/ordering.out")).c_str());
+ SafeIFStream f(FSEntry("hooker_TEST_dir/ordering.out"));
std::string line((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
#ifdef ENABLE_PYTHON_HOOKS
@@ -108,7 +108,7 @@ namespace test_cases
TEST_CHECK_EQUAL(result.max_exit_status(), 123);
TEST_CHECK_EQUAL(result.output(), "");
- std::ifstream f(stringify(FSEntry("hooker_TEST_dir/bad_hooks.out")).c_str());
+ SafeIFStream f(FSEntry("hooker_TEST_dir/bad_hooks.out"));
std::string line((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(line, "one\nthree\n");
@@ -131,7 +131,7 @@ namespace test_cases
TEST_CHECK_EQUAL(result.max_exit_status(), 0);
TEST_CHECK_EQUAL(result.output(), "");
- std::ifstream f(stringify(FSEntry("hooker_TEST_dir/cycles.out")).c_str());
+ SafeIFStream f(FSEntry("hooker_TEST_dir/cycles.out"));
std::string line((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(line, "b\na\ng\nf\ni\n");
@@ -194,7 +194,7 @@ namespace test_cases
TEST_CHECK_EQUAL(result.output(), "");
TEST_CHECK_EQUAL(result.max_exit_status(), 0);
- std::ifstream f(stringify(FSEntry("hooker_TEST_dir/several_output.out")).c_str());
+ SafeIFStream f(FSEntry("hooker_TEST_dir/several_output.out"));
std::string line((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(line, "one\none\none\ntwo\none\ntwo\nthree\n");
@@ -220,7 +220,7 @@ namespace test_cases
TEST_CHECK_EQUAL(result.output(), "two");
TEST_CHECK_EQUAL(result.max_exit_status(), 99);
- std::ifstream f(stringify(FSEntry("hooker_TEST_dir/several_output_bad.out")).c_str());
+ SafeIFStream f(FSEntry("hooker_TEST_dir/several_output_bad.out"));
std::string line((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(line, "one\ntwo\nthree\n");
diff --git a/paludis/merger_TEST.cc b/paludis/merger_TEST.cc
index 5503966..8eabf06 100644
--- a/paludis/merger_TEST.cc
+++ b/paludis/merger_TEST.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -23,10 +23,10 @@
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/dir_iterator.hh>
#include <paludis/util/make_named_values.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/hook.hh>
#include <test/test_framework.hh>
#include <test/test_runner.hh>
-#include <fstream>
#include <iterator>
#include <list>
@@ -375,7 +375,7 @@ namespace test_cases
merger.merge();
TEST_CHECK((root_dir / "file").is_regular_file());
- std::ifstream f(stringify(root_dir / "file").c_str());
+ SafeIFStream f(root_dir / "file");
TEST_CHECK(f);
std::string fs(std::string((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()));
TEST_CHECK_EQUAL(fs, "image contents\n");
@@ -389,7 +389,7 @@ namespace test_cases
void run()
{
TEST_CHECK((root_dir / "file").is_regular_file());
- std::ifstream b(stringify(root_dir / "file").c_str());
+ SafeIFStream b(root_dir / "file");
TEST_CHECK(b);
std::string bs((std::istreambuf_iterator<char>(b)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(bs, "root contents\n");
@@ -398,7 +398,7 @@ namespace test_cases
merger.merge();
TEST_CHECK((root_dir / "file").is_regular_file());
- std::ifstream f(stringify(root_dir / "file").c_str());
+ SafeIFStream f(root_dir / "file");
TEST_CHECK(f);
std::string fs((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(fs, "image contents\n");
@@ -419,19 +419,19 @@ namespace test_cases
merger.merge();
TEST_CHECK((root_dir / "file1").is_regular_file());
- std::ifstream f(stringify(root_dir / "file1").c_str());
+ SafeIFStream f(root_dir / "file1");
TEST_CHECK(f);
std::string fs((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(fs, "image 1 contents\n");
TEST_CHECK((root_dir / "file2").is_regular_file());
- std::ifstream f2(stringify(root_dir / "file2").c_str());
+ SafeIFStream f2(root_dir / "file2");
TEST_CHECK(f2);
std::string fs2((std::istreambuf_iterator<char>(f2)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(fs2, "image 2 contents\n");
TEST_CHECK((root_dir / "file3").is_regular_file());
- std::ifstream f3(stringify(root_dir / "file3").c_str());
+ SafeIFStream f3(root_dir / "file3");
TEST_CHECK(f3);
std::string fs3((std::istreambuf_iterator<char>(f3)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(fs3, "image 3 contents\n");
diff --git a/paludis/ndbam.cc b/paludis/ndbam.cc
index 999befd..206a5f1 100644
--- a/paludis/ndbam.cc
+++ b/paludis/ndbam.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -29,6 +29,7 @@
#include <paludis/util/config_file.hh>
#include <paludis/util/hashes.hh>
#include <paludis/util/make_named_values.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/ndbam.hh>
#include <paludis/package_id.hh>
#include <paludis/metadata_key.hh>
@@ -38,7 +39,6 @@
#include <functional>
#include <vector>
#include <map>
-#include <fstream>
using namespace paludis;
@@ -125,7 +125,7 @@ NDBAM::NDBAM(const FSEntry & l,
(l / "indices" / "categories").mkdir();
(l / "indices" / "packages").mkdir();
(l / "data").mkdir();
- std::ofstream n(stringify(l / "ndbam.conf").c_str());
+ SafeOFStream n(l / "ndbam.conf");
n << "ndbam_format = 1" << std::endl;
n << "repository_format = " << preferred_format << std::endl;
if (! n)
diff --git a/paludis/ndbam_merger.cc b/paludis/ndbam_merger.cc
index 611933e..fc28381 100644
--- a/paludis/ndbam_merger.cc
+++ b/paludis/ndbam_merger.cc
@@ -29,6 +29,8 @@
#include <paludis/util/options.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/output_manager.hh>
+#include <paludis/util/safe_ofstream.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/hook.hh>
#include <paludis/package_id.hh>
#include <paludis/util/md5.hh>
@@ -36,7 +38,6 @@
#include <paludis/package_database.hh>
#include <paludis/ndbam_merger.hh>
#include <paludis/metadata_key.hh>
-#include <fstream>
#include <iomanip>
#include <list>
@@ -49,7 +50,7 @@ namespace paludis
{
NDBAMMergerParams params;
FSEntry realroot;
- std::tr1::shared_ptr<std::ofstream> contents_file;
+ std::tr1::shared_ptr<SafeOFStream> contents_file;
std::list<std::string> config_protect;
std::list<std::string> config_protect_mask;
@@ -150,7 +151,7 @@ NDBAMMerger::record_install_file(const FSEntry & src, const FSEntry & dst_dir, c
tidy_real(stringify((dst_dir / src.basename()).strip_leading(_imp->realroot)));
time_t timestamp((dst_dir / dst_name).mtime());
- std::ifstream infile(stringify(FSEntry(dst_dir / dst_name)).c_str());
+ SafeIFStream infile(FSEntry(dst_dir / dst_name));
if (! infile)
throw MergerError("Cannot read '" + stringify(FSEntry(dst_dir / dst_name)) + "'");
@@ -249,7 +250,7 @@ NDBAMMerger::make_config_protect_name(const FSEntry & src, const FSEntry & dst)
std::string result_name(src.basename());
int n(0);
- std::ifstream our_md5_file(stringify(src).c_str());
+ SafeIFStream our_md5_file(src);
if (! our_md5_file)
throw MergerError("Could not get md5 for '" + stringify((dst / src.basename()).strip_leading(_imp->realroot)) + "'");
MD5 our_md5(our_md5_file);
@@ -261,7 +262,7 @@ NDBAMMerger::make_config_protect_name(const FSEntry & src, const FSEntry & dst)
if ((dst / result_name).is_regular_file_or_symlink_to_regular_file())
{
- std::ifstream other_md5_file(stringify(dst / result_name).c_str());
+ SafeIFStream other_md5_file(dst / result_name);
if (other_md5_file)
{
MD5 other_md5(other_md5_file);
@@ -336,7 +337,7 @@ void
NDBAMMerger::merge()
{
display_override(">>> Merging to " + stringify(_imp->params.root()));
- _imp->contents_file.reset(new std::ofstream(stringify(_imp->params.contents_file()).c_str()));
+ _imp->contents_file.reset(new SafeOFStream(_imp->params.contents_file()));
Merger::merge();
}
diff --git a/paludis/ndbam_unmerger.cc b/paludis/ndbam_unmerger.cc
index 05d3002..a371330 100644
--- a/paludis/ndbam_unmerger.cc
+++ b/paludis/ndbam_unmerger.cc
@@ -38,12 +38,12 @@
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/output_manager.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/metadata_key.hh>
#include <tr1/functional>
#include <list>
#include <map>
#include <vector>
-#include <fstream>
using namespace paludis;
@@ -229,7 +229,7 @@ NDBAMUnmerger::check_file(const FSEntry & f, const std::tr1::shared_ptr<ExtraInf
display("--- [!time] " + stringify(f));
else
{
- std::ifstream md5_file(stringify(_imp->options.root() / f).c_str());
+ SafeIFStream md5_file(_imp->options.root() / f);
if (! md5_file)
{
Log::get_instance()->message("ndbam.unmerger.md5_failed", ll_warning, lc_no_context) << "Cannot get md5 for '" <<
diff --git a/paludis/repositories/cran/cran_installed_repository.cc b/paludis/repositories/cran/cran_installed_repository.cc
index ec4c4f9..397e490 100644
--- a/paludis/repositories/cran/cran_installed_repository.cc
+++ b/paludis/repositories/cran/cran_installed_repository.cc
@@ -49,7 +49,6 @@
#include <tr1/unordered_map>
#include <functional>
#include <algorithm>
-#include <fstream>
using namespace paludis;
@@ -279,7 +278,7 @@ CRANInstalledRepository::do_contents(const Package ID & id) const
return result;
}
- std::ifstream ff(stringify(f).c_str());
+ SafeIFStream ff(f);
if (! ff)
throw ConfigurationError("Could not read '" + stringify(f) + "'");
diff --git a/paludis/repositories/e/check_fetched_files_visitor.cc b/paludis/repositories/e/check_fetched_files_visitor.cc
index 6194391..9f29650 100644
--- a/paludis/repositories/e/check_fetched_files_visitor.cc
+++ b/paludis/repositories/e/check_fetched_files_visitor.cc
@@ -31,6 +31,7 @@
#include <paludis/util/system.hh>
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/fs_entry.hh>
+#include <paludis/util/log.hh>
#include <paludis/util/join.hh>
#include <paludis/util/save.hh>
#include <paludis/util/stringify.hh>
@@ -39,13 +40,13 @@
#include <paludis/util/sha256.hh>
#include <paludis/util/md5.hh>
#include <paludis/util/make_named_values.hh>
-#include <paludis/util/output_manager.hh>
#include <paludis/util/sequence.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/indirect_iterator.hh>
#include <paludis/util/accept_visitor.hh>
+#include <paludis/util/safe_ifstream.hh>
+#include <paludis/util/output_manager.hh>
#include <algorithm>
-#include <fstream>
#include <list>
#include <set>
@@ -187,7 +188,7 @@ CheckFetchedFilesVisitor::check_distfile_manifest(const FSEntry & distfile)
{
case manifest_use:
case manifest_ignore:
- _imp->output_manager->log_message("e.manifest.empty", ll_debug, lc_context) << "Empty or non-existent Manifest file";
+ Log::get_instance()->message("e.manifest.empty", ll_debug, lc_context) << "Empty or non-existent Manifest file";
return true;
case manifest_require:
@@ -215,12 +216,12 @@ CheckFetchedFilesVisitor::check_distfile_manifest(const FSEntry & distfile)
continue;
found = true;
- _imp->output_manager->log_message("e.manifest.size", ll_debug, lc_context)
+ Log::get_instance()->message("e.manifest.size", ll_debug, lc_context)
<< "Actual size = " << distfile.file_size()
<< "; Manifest file size = " << m->size();
if (distfile.file_size() != m->size())
{
- _imp->output_manager->log_message("e.manifest.no_size", ll_debug, lc_context)
+ Log::get_instance()->message("e.manifest.no_size", ll_debug, lc_context)
<< "Malformed Manifest: no file size found";
_imp->output_manager->stdout_stream() << "incorrect size";
_imp->failures->push_back(make_named_values<FetchActionFailure>(
@@ -232,103 +233,106 @@ CheckFetchedFilesVisitor::check_distfile_manifest(const FSEntry & distfile)
return false;
}
- std::ifstream file_stream(stringify(distfile).c_str());
- if (! file_stream)
+ try
{
- _imp->output_manager->stdout_stream() << "unreadable file";
- _imp->failures->push_back(make_named_values<FetchActionFailure>(
- value_for<n::failed_automatic_fetching>(false),
- value_for<n::failed_integrity_checks>("Unreadable file"),
- value_for<n::requires_manual_fetching>(false),
- value_for<n::target_file>(stringify(distfile.basename()))
- ));
- return false;
- }
+ SafeIFStream file_stream(distfile);
- if (! m->rmd160().empty())
- {
- RMD160 rmd160sum(file_stream);
- if (rmd160sum.hexsum() != m->rmd160())
+ if (! m->rmd160().empty())
{
- _imp->output_manager->log_message("e.manifest.rmd160.failure", ll_debug, lc_context)
- << "Malformed Manifest: failed RMD160 checksum";
- _imp->output_manager->stdout_stream() << "failed RMD160";
- _imp->failures->push_back(make_named_values<FetchActionFailure>(
- value_for<n::failed_automatic_fetching>(false),
- value_for<n::failed_integrity_checks>("Failed RMD160 checksum"),
- value_for<n::requires_manual_fetching>(false),
- value_for<n::target_file>(stringify(distfile.basename()))
- ));
- return false;
+ RMD160 rmd160sum(file_stream);
+ if (rmd160sum.hexsum() != m->rmd160())
+ {
+ Log::get_instance()->message("e.manifest.rmd160.failure", ll_debug, lc_context)
+ << "Malformed Manifest: failed RMD160 checksum";
+ _imp->output_manager->stdout_stream() << "failed RMD160";
+ _imp->failures->push_back(make_named_values<FetchActionFailure>(
+ value_for<n::failed_automatic_fetching>(false),
+ value_for<n::failed_integrity_checks>("Failed RMD160 checksum"),
+ value_for<n::requires_manual_fetching>(false),
+ value_for<n::target_file>(stringify(distfile.basename()))
+ ));
+ return false;
+ }
+ Log::get_instance()->message("e.manifest.rmd160.result", ll_debug, lc_context)
+ << "Actual RMD160 = " << rmd160sum.hexsum();
+ file_stream.clear();
+ file_stream.seekg(0, std::ios::beg);
}
- _imp->output_manager->log_message("e.manifest.rmd160.result", ll_debug, lc_context)
- << "Actual RMD160 = " << rmd160sum.hexsum();
- file_stream.clear();
- file_stream.seekg(0, std::ios::beg);
- }
- if (! m->sha1().empty())
- {
- SHA1 sha1sum(file_stream);
- if (sha1sum.hexsum() != m->sha1())
+ if (! m->sha1().empty())
{
- _imp->output_manager->log_message("e.manifest.sha1.failure", ll_debug, lc_context)
- << "Malformed Manifest: failed SHA1 checksum";
- _imp->output_manager->stdout_stream() << "failed SHA1";
- _imp->failures->push_back(make_named_values<FetchActionFailure>(
- value_for<n::failed_automatic_fetching>(false),
- value_for<n::failed_integrity_checks>("Failed SHA1 checksum"),
- value_for<n::requires_manual_fetching>(false),
- value_for<n::target_file>(stringify(distfile.basename()))
- ));
- return false;
+ SHA1 sha1sum(file_stream);
+ if (sha1sum.hexsum() != m->sha1())
+ {
+ Log::get_instance()->message("e.manifest.sha1.failure", ll_debug, lc_context)
+ << "Malformed Manifest: failed SHA1 checksum";
+ _imp->output_manager->stdout_stream() << "failed SHA1";
+ _imp->failures->push_back(make_named_values<FetchActionFailure>(
+ value_for<n::failed_automatic_fetching>(false),
+ value_for<n::failed_integrity_checks>("Failed SHA1 checksum"),
+ value_for<n::requires_manual_fetching>(false),
+ value_for<n::target_file>(stringify(distfile.basename()))
+ ));
+ return false;
+ }
+ Log::get_instance()->message("e.manifest.sha1.result", ll_debug, lc_context)
+ << "Actual SHA1 = " << sha1sum.hexsum();
+ file_stream.clear();
+ file_stream.seekg(0, std::ios::beg);
}
- _imp->output_manager->log_message("e.manifest.sha1.result", ll_debug, lc_context)
- << "Actual SHA1 = " << sha1sum.hexsum();
- file_stream.clear();
- file_stream.seekg(0, std::ios::beg);
- }
- if (! m->sha256().empty())
- {
- SHA256 sha256sum(file_stream);
- if (sha256sum.hexsum() != m->sha256())
+ if (! m->sha256().empty())
{
- _imp->output_manager->log_message("e.manifest.sha256.failure", ll_debug, lc_context)
- << "Malformed Manifest: failed SHA256 checksum";
- _imp->output_manager->stdout_stream() << "failed SHA256";
- _imp->failures->push_back(make_named_values<FetchActionFailure>(
- value_for<n::failed_automatic_fetching>(false),
- value_for<n::failed_integrity_checks>("Failed SHA256 checksum"),
- value_for<n::requires_manual_fetching>(false),
- value_for<n::target_file>(stringify(distfile.basename()))
- ));
- return false;
+ SHA256 sha256sum(file_stream);
+ if (sha256sum.hexsum() != m->sha256())
+ {
+ Log::get_instance()->message("e.manifest.sha256.failure", ll_debug, lc_context)
+ << "Malformed Manifest: failed SHA256 checksum";
+ _imp->output_manager->stdout_stream() << "failed SHA256";
+ _imp->failures->push_back(make_named_values<FetchActionFailure>(
+ value_for<n::failed_automatic_fetching>(false),
+ value_for<n::failed_integrity_checks>("Failed SHA256 checksum"),
+ value_for<n::requires_manual_fetching>(false),
+ value_for<n::target_file>(stringify(distfile.basename()))
+ ));
+ return false;
+ }
+ Log::get_instance()->message("e.manifest.sha256.result", ll_debug, lc_context)
+ << "Actual SHA256 = " << sha256sum.hexsum();
+ file_stream.clear();
+ file_stream.seekg(0, std::ios::beg);
}
- _imp->output_manager->log_message("e.manifest.sha256.result", ll_debug, lc_context)
- << "Actual SHA256 = " << sha256sum.hexsum();
- file_stream.clear();
- file_stream.seekg(0, std::ios::beg);
- }
- if (! m->md5().empty())
- {
- MD5 md5sum(file_stream);
- if (md5sum.hexsum() != m->md5())
+ if (! m->md5().empty())
{
- _imp->output_manager->log_message("e.manifest.md5.failure", ll_debug, lc_context)
- << "Malformed Manifest: failed MD5 checksum";
- _imp->output_manager->stdout_stream() << "failed MD5";
- _imp->failures->push_back(make_named_values<FetchActionFailure>(
+ MD5 md5sum(file_stream);
+ if (md5sum.hexsum() != m->md5())
+ {
+ Log::get_instance()->message("e.manifest.md5.failure", ll_debug, lc_context)
+ << "Malformed Manifest: failed MD5 checksum";
+ _imp->output_manager->stdout_stream() << "failed MD5";
+ _imp->failures->push_back(make_named_values<FetchActionFailure>(
+ value_for<n::failed_automatic_fetching>(false),
+ value_for<n::failed_integrity_checks>("Failed MD5 checksum"),
+ value_for<n::requires_manual_fetching>(false),
+ value_for<n::target_file>(stringify(distfile.basename()))
+ ));
+ return false;
+ }
+ Log::get_instance()->message("e.manifest.md5.result", ll_debug, lc_context)
+ << "Actual MD5 = " << md5sum.hexsum();
+ }
+ }
+ catch (const SafeIFStreamError &)
+ {
+ _imp->output_manager->stdout_stream() << "unreadable file";
+ _imp->failures->push_back(make_named_values<FetchActionFailure>(
value_for<n::failed_automatic_fetching>(false),
- value_for<n::failed_integrity_checks>("Failed MD5 checksum"),
+ value_for<n::failed_integrity_checks>("Unreadable file"),
value_for<n::requires_manual_fetching>(false),
value_for<n::target_file>(stringify(distfile.basename()))
));
- return false;
- }
- _imp->output_manager->log_message("e.manifest.md5.result", ll_debug, lc_context)
- << "Actual MD5 = " << md5sum.hexsum();
+ return false;
}
}
@@ -354,7 +358,7 @@ CheckFetchedFilesVisitor::visit(const FetchableURISpecTree::NodeType<FetchableUR
if (_imp->done.end() != _imp->done.find(node.spec()->filename()))
{
- _imp->output_manager->log_message("e.check_fetched_files.already_checked", ll_debug, lc_context)
+ Log::get_instance()->message("e.check_fetched_files.already_checked", ll_debug, lc_context)
<< "Already checked '" << node.spec()->filename() << "'";
return;
}
@@ -368,7 +372,7 @@ CheckFetchedFilesVisitor::visit(const FetchableURISpecTree::NodeType<FetchableUR
{
if (! _imp->exclude_unmirrorable)
{
- _imp->output_manager->log_message("e.check_fetched_files.requires_manual", ll_debug, lc_context)
+ Log::get_instance()->message("e.check_fetched_files.requires_manual", ll_debug, lc_context)
<< "Manual fetch required for '" << node.spec()->filename() << "'";
_imp->output_manager->stdout_stream() << "requires manual fetch";
_imp->need_nofetch = true;
@@ -382,7 +386,7 @@ CheckFetchedFilesVisitor::visit(const FetchableURISpecTree::NodeType<FetchableUR
}
else
{
- _imp->output_manager->log_message("e.check_fetched_files.does_not_exist", ll_debug, lc_context)
+ Log::get_instance()->message("e.check_fetched_files.does_not_exist", ll_debug, lc_context)
<< "Automatic fetch failed for '" << node.spec()->filename() << "'";
_imp->output_manager->stdout_stream() << "does not exist";
_imp->failures->push_back(make_named_values<FetchActionFailure>(
@@ -395,7 +399,7 @@ CheckFetchedFilesVisitor::visit(const FetchableURISpecTree::NodeType<FetchableUR
}
else if (0 == (_imp->distdir / node.spec()->filename()).file_size())
{
- _imp->output_manager->log_message("e.check_fetched_files.empty", ll_debug, lc_context) << "Empty file for '" << node.spec()->filename() << "'";
+ Log::get_instance()->message("e.check_fetched_files.empty", ll_debug, lc_context) << "Empty file for '" << node.spec()->filename() << "'";
_imp->output_manager->stdout_stream() << "empty file";
_imp->failures->push_back(make_named_values<FetchActionFailure>(
value_for<n::failed_automatic_fetching>(false),
@@ -406,12 +410,12 @@ CheckFetchedFilesVisitor::visit(const FetchableURISpecTree::NodeType<FetchableUR
}
else if (! check_distfile_manifest(_imp->distdir / node.spec()->filename()))
{
- _imp->output_manager->log_message("e.check_fetched_files.failure", ll_debug, lc_context)
+ Log::get_instance()->message("e.check_fetched_files.failure", ll_debug, lc_context)
<< "Manifest check failed for '" << node.spec()->filename() << "'";
}
else
{
- _imp->output_manager->log_message("e.check_fetched_files.success", ll_debug, lc_context) << "Success for '" << node.spec()->filename() << "'";
+ Log::get_instance()->message("e.check_fetched_files.success", ll_debug, lc_context) << "Success for '" << node.spec()->filename() << "'";
_imp->output_manager->stdout_stream() << "ok";
}
diff --git a/paludis/repositories/e/e_installed_repository.cc b/paludis/repositories/e/e_installed_repository.cc
index 2deb155..f385628 100644
--- a/paludis/repositories/e/e_installed_repository.cc
+++ b/paludis/repositories/e/e_installed_repository.cc
@@ -37,6 +37,7 @@
#include <paludis/util/make_named_values.hh>
#include <paludis/util/sequence.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/action.hh>
#include <paludis/package_id.hh>
#include <paludis/metadata_key.hh>
@@ -45,7 +46,6 @@
#include <paludis/hook.hh>
#include <paludis/dep_tag.hh>
#include <paludis/user_dep_spec.hh>
-#include <fstream>
using namespace paludis;
using namespace paludis::erepository;
@@ -224,9 +224,7 @@ EInstalledRepository::get_environment_variable(
if ((ver_dir / var).is_regular_file_or_symlink_to_regular_file())
{
- std::ifstream f(stringify(ver_dir / var).c_str());
- if (! f)
- throw ActionError("Could not read '" + stringify(ver_dir / var) + "'");
+ SafeIFStream f(ver_dir / var);
return strip_trailing_string(
std::string((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()), "\n");
}
diff --git a/paludis/repositories/e/e_installed_repository_id.cc b/paludis/repositories/e/e_installed_repository_id.cc
index 748fc30..0435849 100644
--- a/paludis/repositories/e/e_installed_repository_id.cc
+++ b/paludis/repositories/e/e_installed_repository_id.cc
@@ -41,9 +41,9 @@
#include <paludis/util/mutex.hh>
#include <paludis/util/make_shared_ptr.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/literal_metadata_key.hh>
#include <iterator>
-#include <fstream>
using namespace paludis;
using namespace paludis::erepository;
@@ -53,10 +53,7 @@ namespace
std::string file_contents(const FSEntry & f)
{
Context c("When reading '" + stringify(f) + "':");
- std::ifstream i(stringify(f).c_str());
- if (! i)
- throw ConfigurationError("Cannot open '" + stringify(f) + "' for read");
-
+ SafeIFStream i(f);
return strip_trailing(std::string((std::istreambuf_iterator<char>(i)), std::istreambuf_iterator<char>()), "\r\n");
}
}
diff --git a/paludis/repositories/e/e_key.cc b/paludis/repositories/e/e_key.cc
index d284c63..f756176 100644
--- a/paludis/repositories/e/e_key.cc
+++ b/paludis/repositories/e/e_key.cc
@@ -46,11 +46,11 @@
#include <paludis/environment.hh>
#include <paludis/stringify_formatter-impl.hh>
#include <paludis/dep_spec_flattener.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <tr1/functional>
#include <list>
#include <vector>
-#include <fstream>
using namespace paludis;
using namespace paludis::erepository;
@@ -989,9 +989,7 @@ EContentsKey::value() const
return _imp->value;
}
- std::ifstream ff(stringify(f).c_str());
- if (! ff)
- throw ConfigurationError("Could not read '" + stringify(f) + "'");
+ SafeIFStream ff(f);
std::string line;
unsigned line_number(0);
diff --git a/paludis/repositories/e/e_repository.cc b/paludis/repositories/e/e_repository.cc
index c4ecb0e..7f2deb9 100644
--- a/paludis/repositories/e/e_repository.cc
+++ b/paludis/repositories/e/e_repository.cc
@@ -43,7 +43,9 @@
#include <paludis/util/config_file.hh>
#include <paludis/util/create_iterator-impl.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/distribution.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/dep_spec.hh>
#include <paludis/literal_metadata_key.hh>
#include <paludis/environment.hh>
@@ -91,7 +93,6 @@
#include <algorithm>
#include <vector>
#include <list>
-#include <fstream>
#include <strings.h>
#include <ctype.h>
@@ -1151,8 +1152,7 @@ ERepository::make_manifest(const QualifiedPackageName & qpn)
FSEntry package_dir = _imp->layout->package_directory(qpn);
FSEntry(package_dir / "Manifest").unlink();
- std::ofstream manifest(stringify(FSEntry(package_dir
- / "Manifest")).c_str());
+ SafeOFStream manifest(FSEntry(package_dir / "Manifest"));
if (! manifest)
throw ERepositoryConfigurationError("Couldn't open Manifest for writing.");
@@ -1170,9 +1170,7 @@ ERepository::make_manifest(const QualifiedPackageName & qpn)
filename = stringify(file).substr(stringify(package_dir / "files").length()+1);
}
- std::ifstream file_stream(stringify(file).c_str());
- if (! file_stream)
- throw ERepositoryConfigurationError("Couldn't read " + stringify(file));
+ SafeIFStream file_stream(file);
RMD160 rmd160sum(file_stream);
manifest << file_type << " " << filename << " "
@@ -1213,10 +1211,7 @@ ERepository::make_manifest(const QualifiedPackageName & qpn)
FSEntry f(params().distdir() / *d);
- std::ifstream file_stream(stringify(f).c_str());
- if (! file_stream)
- throw ERepositoryConfigurationError("Couldn't read "
- + stringify(f));
+ SafeIFStream file_stream(f);
RMD160 rmd160sum(file_stream);
manifest << "DIST " << f.basename() << " "
diff --git a/paludis/repositories/e/e_repository_TEST.cc b/paludis/repositories/e/e_repository_TEST.cc
index 2504bdf..773d15b 100644
--- a/paludis/repositories/e/e_repository_TEST.cc
+++ b/paludis/repositories/e/e_repository_TEST.cc
@@ -33,6 +33,7 @@
#include <paludis/util/make_named_values.hh>
#include <paludis/util/set.hh>
#include <paludis/util/standard_output_manager.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/package_id.hh>
#include <paludis/metadata_key.hh>
#include <paludis/action.hh>
@@ -48,7 +49,6 @@
#include <test/test_runner.hh>
#include <tr1/functional>
#include <set>
-#include <fstream>
#include <string>
#include "config.h"
@@ -876,8 +876,8 @@ namespace test_cases
repo->make_manifest(QualifiedPackageName("category/package"));
std::multiset<std::string> made_manifest, reference_manifest;
- std::ifstream made_manifest_stream("e_repository_TEST_dir/repo11/category/package/Manifest"),
- reference_manifest_stream("e_repository_TEST_dir/repo11/Manifest_correct");
+ SafeIFStream made_manifest_stream(FSEntry("e_repository_TEST_dir/repo11/category/package/Manifest")),
+ reference_manifest_stream(FSEntry("e_repository_TEST_dir/repo11/Manifest_correct"));
std::string line;
@@ -888,7 +888,7 @@ namespace test_cases
TEST_CHECK(made_manifest == reference_manifest);
- TEST_CHECK_THROWS(repo->make_manifest(QualifiedPackageName("category/package-b")), ERepositoryConfigurationError);
+ TEST_CHECK_THROWS(repo->make_manifest(QualifiedPackageName("category/package-b")), SafeIFStreamError);
}
} test_e_repository_manifest;
diff --git a/paludis/repositories/e/e_repository_TEST_ever.cc b/paludis/repositories/e/e_repository_TEST_ever.cc
index 0b71d1a..fe3eae6 100644
--- a/paludis/repositories/e/e_repository_TEST_ever.cc
+++ b/paludis/repositories/e/e_repository_TEST_ever.cc
@@ -49,7 +49,6 @@
#include <test/test_runner.hh>
#include <tr1/functional>
#include <set>
-#include <fstream>
#include <string>
#include "config.h"
diff --git a/paludis/repositories/e/e_repository_news.cc b/paludis/repositories/e/e_repository_news.cc
index 03acd64..86c0cfd 100644
--- a/paludis/repositories/e/e_repository_news.cc
+++ b/paludis/repositories/e/e_repository_news.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -32,6 +32,7 @@
#include <paludis/util/sequence.hh>
#include <paludis/util/options.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/distribution.hh>
#include <paludis/elike_package_dep_spec.hh>
#include <paludis/selection.hh>
@@ -39,9 +40,11 @@
#include <paludis/filter.hh>
#include <paludis/filtered_generator.hh>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <set>
#include <ostream>
-#include <fstream>
#include <list>
using namespace paludis;
@@ -188,15 +191,13 @@ ERepositoryNews::update_news() const
if (show)
{
- std::ofstream s(stringify(_imp->skip_file).c_str(),
- std::ios::out | std::ios::app);
+ SafeOFStream s(_imp->skip_file, O_CREAT | O_WRONLY | O_APPEND);
if (! s)
Log::get_instance()->message("e.news.skip_file.append_failure", ll_warning, lc_no_context) <<
"Cannot append to news skip file '" << _imp->skip_file <<
"', skipping news item '" << *d << "'";
- std::ofstream t(stringify(_imp->unread_file).c_str(),
- std::ios::out | std::ios::app);
+ SafeOFStream t(_imp->unread_file, O_CREAT | O_WRONLY | O_APPEND);
if (! t)
Log::get_instance()->message("e.news.unread_file.append_failure", ll_warning, lc_no_context) <<
"Cannot append to unread file '" << _imp->unread_file <<
diff --git a/paludis/repositories/e/ebuild_entries.cc b/paludis/repositories/e/ebuild_entries.cc
index e3a8a6e..ab3ebf3 100644
--- a/paludis/repositories/e/ebuild_entries.cc
+++ b/paludis/repositories/e/ebuild_entries.cc
@@ -58,7 +58,6 @@
#include <paludis/util/make_named_values.hh>
#include <paludis/util/output_manager.hh>
#include <tr1/functional>
-#include <fstream>
#include <list>
#include <set>
#include <sys/types.h>
diff --git a/paludis/repositories/e/ebuild_flat_metadata_cache.cc b/paludis/repositories/e/ebuild_flat_metadata_cache.cc
index e8376cc..d0e7864 100644
--- a/paludis/repositories/e/ebuild_flat_metadata_cache.cc
+++ b/paludis/repositories/e/ebuild_flat_metadata_cache.cc
@@ -25,13 +25,14 @@
#include <paludis/util/set.hh>
#include <paludis/util/destringify.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/safe_ofstream.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/repositories/e/dep_spec_pretty_printer.hh>
#include <paludis/repositories/e/dep_parser.hh>
#include <paludis/repositories/e/dependencies_rewriter.hh>
#include <paludis/stringify_formatter.hh>
#include <paludis/repositories/e/eapi.hh>
#include <tr1/functional>
-#include <fstream>
#include <set>
#include <map>
#include <list>
@@ -292,315 +293,313 @@ EbuildFlatMetadataCache::load(const std::tr1::shared_ptr<const EbuildID> & id)
Context context("When loading version metadata from '" + stringify(_imp->filename) + "':");
- std::ifstream cache(stringify(_imp->filename).c_str());
-
- if (cache)
+ if (! _imp->filename.exists())
{
- std::vector<std::string> lines;
- std::string line;
- while (std::getline(cache, line))
- lines.push_back(line);
+ Log::get_instance()->message("e.cache.failure", _imp->silent ? ll_debug : ll_warning, lc_no_context)
+ << "Couldn't use the cache file at '" << _imp->filename << "': " << std::strerror(errno);
+ return false;
+ }
- try
+ SafeIFStream cache(_imp->filename);
+
+ std::vector<std::string> lines;
+ std::string line;
+ while (std::getline(cache, line))
+ lines.push_back(line);
+
+ try
+ {
+ std::map<std::string, std::string> keys;
+ std::string duplicate;
+ for (std::vector<std::string>::const_iterator it(lines.begin()),
+ it_end(lines.end()); it_end != it; ++it)
{
- std::map<std::string, std::string> keys;
- std::string duplicate;
- for (std::vector<std::string>::const_iterator it(lines.begin()),
- it_end(lines.end()); it_end != it; ++it)
+ std::string::size_type equals(it->find('='));
+ if (std::string::npos == equals)
{
- std::string::size_type equals(it->find('='));
- if (std::string::npos == equals)
- {
- Log::get_instance()->message("e.cache.flat_hash.not", ll_debug, lc_context)
- << "cache file lacks = on line " << ((it - lines.begin()) + 1) << ", assuming flat_list";
- return load_flat_list(id, lines, _imp.get());
- }
-
- if (! keys.insert(std::make_pair(it->substr(0, equals), it->substr(equals + 1))).second)
- duplicate = it->substr(0, equals);
+ Log::get_instance()->message("e.cache.flat_hash.not", ll_debug, lc_context)
+ << "cache file lacks = on line " << ((it - lines.begin()) + 1) << ", assuming flat_list";
+ return load_flat_list(id, lines, _imp.get());
}
- Context ctx("When loading flat_hash format cache file:");
+ if (! keys.insert(std::make_pair(it->substr(0, equals), it->substr(equals + 1))).second)
+ duplicate = it->substr(0, equals);
+ }
- if (! duplicate.empty())
- {
- Log::get_instance()->message("e.cache.flat_hash.broken", ll_warning, lc_context)
- << "cache file contains duplicate key '" << duplicate << "'";
- return false;
- }
+ Context ctx("When loading flat_hash format cache file:");
- std::map<std::string, std::string>::const_iterator eapi(keys.find("EAPI"));
- if (keys.end() == eapi)
- {
- Log::get_instance()->message("e.cache.flat_hash.broken", ll_warning, lc_context)
- << "cache file contains no 'EAPI' key";
- return false;
- }
- id->set_eapi(eapi->second);
+ if (! duplicate.empty())
+ {
+ Log::get_instance()->message("e.cache.flat_hash.broken", ll_warning, lc_context)
+ << "cache file contains duplicate key '" << duplicate << "'";
+ return false;
+ }
+
+ std::map<std::string, std::string>::const_iterator eapi(keys.find("EAPI"));
+ if (keys.end() == eapi)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.broken", ll_warning, lc_context)
+ << "cache file contains no 'EAPI' key";
+ return false;
+ }
+ id->set_eapi(eapi->second);
+
+ if (id->eapi()->supported())
+ {
+ const EAPIEbuildMetadataVariables & m(*id->eapi()->supported()->ebuild_metadata_variables());
+ std::vector<std::string> inherited;
- if (id->eapi()->supported())
{
- const EAPIEbuildMetadataVariables & m(*id->eapi()->supported()->ebuild_metadata_variables());
- std::vector<std::string> inherited;
+ std::map<std::string, std::string>::const_iterator mtime_it(keys.find("_mtime_"));
+ std::time_t cache_time(keys.end() == mtime_it ? _imp->filename.mtime() : destringify<std::time_t>(mtime_it->second));
+ bool ok(_imp->ebuild.mtime() == cache_time);
+ if (! ok)
+ Log::get_instance()->message("e.cache.flat_hash.mtime", ll_debug, lc_context)
+ << "ebuild has mtime " << _imp->ebuild.mtime() << ", but expected " << cache_time;
+ if (ok && id->eapi()->supported()->ebuild_options()->support_eclasses())
{
- std::map<std::string, std::string>::const_iterator mtime_it(keys.find("_mtime_"));
- std::time_t cache_time(keys.end() == mtime_it ? _imp->filename.mtime() : destringify<std::time_t>(mtime_it->second));
- bool ok(_imp->ebuild.mtime() == cache_time);
- if (! ok)
- Log::get_instance()->message("e.cache.flat_hash.mtime", ll_debug, lc_context)
- << "ebuild has mtime " << _imp->ebuild.mtime() << ", but expected " << cache_time;
-
- if (ok && id->eapi()->supported()->ebuild_options()->support_eclasses())
+ std::vector<std::string> eclasses;
+ tokenise<delim_kind::AnyOfTag, delim_mode::DelimiterTag>(keys["_eclasses_"], "\t", "", std::back_inserter(eclasses));
+ FSEntry eclassdir((id->repository()->location_key()->value() / "eclass").realpath_if_exists());
+ for (std::vector<std::string>::const_iterator it(eclasses.begin()),
+ it_end(eclasses.end()); it_end != it; ++it)
{
- std::vector<std::string> eclasses;
- tokenise<delim_kind::AnyOfTag, delim_mode::DelimiterTag>(keys["_eclasses_"], "\t", "", std::back_inserter(eclasses));
- FSEntry eclassdir((id->repository()->location_key()->value() / "eclass").realpath_if_exists());
- for (std::vector<std::string>::const_iterator it(eclasses.begin()),
- it_end(eclasses.end()); it_end != it; ++it)
+ std::string eclass_name(*it);
+ inherited.push_back(eclass_name);
+ if (eclasses.end() == ++it)
{
- std::string eclass_name(*it);
- inherited.push_back(eclass_name);
- if (eclasses.end() == ++it)
- {
- Log::get_instance()->message("e.cache.flat_hash.eclass.truncated", ll_warning, lc_context)
- << "_eclasses_ entry is incomplete";
- return false;
- }
- FSEntry eclass_dir(std::string::npos != it->find('/') ? *(it++) : eclassdir);
- if (eclasses.end() == it)
- {
- Log::get_instance()->message("e.cache.flat_hash.eclass.truncated", ll_warning, lc_context)
- << "_eclasses_ entry is incomplete";
- return false;
- }
- std::time_t eclass_mtime(destringify<std::time_t>(*it));
-
- const FSEntry * eclass(_imp->eclass_mtimes->eclass(eclass_name));
- if (eclass)
- Log::get_instance()->message("e.cache.flat_hash.eclass.path", ll_debug, lc_context)
- << "Cache-requested eclass '" << eclass_name << "' maps to '" << *eclass << "'";
-
- if (! eclass)
- {
- Log::get_instance()->message("e.cache.flat_hash.eclass.missing", ll_debug, lc_context)
- << "Can't find cache-requested eclass '" << eclass_name << "'";
- ok = false;
- }
-
- else if (eclass->dirname() != eclass_dir)
- {
- Log::get_instance()->message("e.cache.flat_hash.eclass.wrong_location", ll_debug, lc_context)
- << "Cache-requested eclass '" << eclass_name << "' was found at '"
- << eclass->dirname() << "', but expected '" << eclass_dir << "'";
- ok = false;
- }
-
- else if (eclass->mtime() != eclass_mtime)
- {
- Log::get_instance()->message("e.cache.flat_hash.eclass.wrong_mtime", ll_debug, lc_context)
- << "Cache-requested eclass '" << eclass_name << "' has mtime "
- << eclass->mtime() << ", but expected " << eclass_mtime;
- ok = false;
- }
-
- if (! ok)
- break;
+ Log::get_instance()->message("e.cache.flat_hash.eclass.truncated", ll_warning, lc_context)
+ << "_eclasses_ entry is incomplete";
+ return false;
}
- }
+ FSEntry eclass_dir(std::string::npos != it->find('/') ? *(it++) : eclassdir);
+ if (eclasses.end() == it)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.eclass.truncated", ll_warning, lc_context)
+ << "_eclasses_ entry is incomplete";
+ return false;
+ }
+ std::time_t eclass_mtime(destringify<std::time_t>(*it));
- else if (ok && id->eapi()->supported()->ebuild_options()->support_exlibs())
- {
- std::vector<std::string> exlibs;
- tokenise<delim_kind::AnyOfTag, delim_mode::DelimiterTag>(keys["_exlibs_"], "\t", "", std::back_inserter(exlibs));
- for (std::vector<std::string>::const_iterator it(exlibs.begin()),
- it_end(exlibs.end()); it_end != it; ++it)
+ const FSEntry * eclass(_imp->eclass_mtimes->eclass(eclass_name));
+ if (eclass)
+ Log::get_instance()->message("e.cache.flat_hash.eclass.path", ll_debug, lc_context)
+ << "Cache-requested eclass '" << eclass_name << "' maps to '" << *eclass << "'";
+
+ if (! eclass)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.eclass.missing", ll_debug, lc_context)
+ << "Can't find cache-requested eclass '" << eclass_name << "'";
+ ok = false;
+ }
+
+ else if (eclass->dirname() != eclass_dir)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.eclass.wrong_location", ll_debug, lc_context)
+ << "Cache-requested eclass '" << eclass_name << "' was found at '"
+ << eclass->dirname() << "', but expected '" << eclass_dir << "'";
+ ok = false;
+ }
+
+ else if (eclass->mtime() != eclass_mtime)
{
- std::string exlib_name(*it);
- inherited.push_back(exlib_name);
- if (exlibs.end() == ++it)
- {
- Log::get_instance()->message("e.cache.flat_hash.exlib.truncated", ll_warning, lc_context)
- << "_exlibs_ entry is incomplete";
- return false;
- }
- FSEntry exlib_dir(*it);
- if (exlibs.end() == ++it)
- {
- Log::get_instance()->message("e.cache.flat_hash.exlibs.truncated", ll_warning, lc_context)
- << "_exlibs_ entry is incomplete";
- return false;
- }
- std::time_t exlib_mtime(destringify<std::time_t>(*it));
-
- const FSEntry * exlib(_imp->eclass_mtimes->exlib(exlib_name, id->name()));
- if (exlib)
- Log::get_instance()->message("e.cache.flat_hash.exlib.path", ll_debug, lc_context)
- << "Cache-requested exlib '" << exlib_name << "' maps to '" << *exlib << "'";
-
- if (! exlib)
- {
- Log::get_instance()->message("e.cache.flat_hash.exlib.missing", ll_debug, lc_context)
- << "Can't find cache-requested exlib '" << exlib_name << "'";
- ok = false;
- }
-
- else if (exlib->dirname() != exlib_dir)
- {
- Log::get_instance()->message("e.cache.flat_hash.exlib.wrong_location", ll_debug, lc_context)
- << "Cache-requested exlib '" << exlib_name << "' was found at '"
- << exlib->dirname() << "', but expected '" << exlib_dir << "'";
- ok = false;
- }
-
- else if (exlib->mtime() != exlib_mtime)
- {
- Log::get_instance()->message("e.cache.flat_hash.exlib.wrong_mtime", ll_debug, lc_context)
- << "Cache-requested exlib '" << exlib_name << "' has mtime "
- << exlib->mtime() << ", but expected " << exlib_mtime;
- ok = false;
- }
-
- if (! ok)
- break;
+ Log::get_instance()->message("e.cache.flat_hash.eclass.wrong_mtime", ll_debug, lc_context)
+ << "Cache-requested eclass '" << eclass_name << "' has mtime "
+ << eclass->mtime() << ", but expected " << eclass_mtime;
+ ok = false;
}
+
+ if (! ok)
+ break;
}
+ }
- if (! ok)
+ else if (ok && id->eapi()->supported()->ebuild_options()->support_exlibs())
+ {
+ std::vector<std::string> exlibs;
+ tokenise<delim_kind::AnyOfTag, delim_mode::DelimiterTag>(keys["_exlibs_"], "\t", "", std::back_inserter(exlibs));
+ for (std::vector<std::string>::const_iterator it(exlibs.begin()),
+ it_end(exlibs.end()); it_end != it; ++it)
{
- Log::get_instance()->message("e.cache.stale", ll_warning, lc_no_context)
- << "Stale cache file at '" << _imp->filename << "'";
- return false;
+ std::string exlib_name(*it);
+ inherited.push_back(exlib_name);
+ if (exlibs.end() == ++it)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.exlib.truncated", ll_warning, lc_context)
+ << "_exlibs_ entry is incomplete";
+ return false;
+ }
+ FSEntry exlib_dir(*it);
+ if (exlibs.end() == ++it)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.exlibs.truncated", ll_warning, lc_context)
+ << "_exlibs_ entry is incomplete";
+ return false;
+ }
+ std::time_t exlib_mtime(destringify<std::time_t>(*it));
+
+ const FSEntry * exlib(_imp->eclass_mtimes->exlib(exlib_name, id->name()));
+ if (exlib)
+ Log::get_instance()->message("e.cache.flat_hash.exlib.path", ll_debug, lc_context)
+ << "Cache-requested exlib '" << exlib_name << "' maps to '" << *exlib << "'";
+
+ if (! exlib)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.exlib.missing", ll_debug, lc_context)
+ << "Can't find cache-requested exlib '" << exlib_name << "'";
+ ok = false;
+ }
+
+ else if (exlib->dirname() != exlib_dir)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.exlib.wrong_location", ll_debug, lc_context)
+ << "Cache-requested exlib '" << exlib_name << "' was found at '"
+ << exlib->dirname() << "', but expected '" << exlib_dir << "'";
+ ok = false;
+ }
+
+ else if (exlib->mtime() != exlib_mtime)
+ {
+ Log::get_instance()->message("e.cache.flat_hash.exlib.wrong_mtime", ll_debug, lc_context)
+ << "Cache-requested exlib '" << exlib_name << "' has mtime "
+ << exlib->mtime() << ", but expected " << exlib_mtime;
+ ok = false;
+ }
+
+ if (! ok)
+ break;
}
}
- if (! m.dependencies()->name().empty())
+ if (! ok)
{
- DependenciesRewriter rewriter;
- parse_depend(keys[m.dependencies()->name()], _imp->env, id, *id->eapi())->root()->accept(rewriter);
- id->load_build_depend(m.dependencies()->name() + ".DEPEND", m.dependencies()->description() + " (build)", rewriter.depend());
- id->load_run_depend(m.dependencies()->name() + ".RDEPEND", m.dependencies()->description() + " (run)", rewriter.rdepend());
- id->load_post_depend(m.dependencies()->name() + ".PDEPEND", m.dependencies()->description() + " (post)", rewriter.pdepend());
+ Log::get_instance()->message("e.cache.stale", ll_warning, lc_no_context)
+ << "Stale cache file at '" << _imp->filename << "'";
+ return false;
}
+ }
- if (! m.build_depend()->name().empty())
- id->load_build_depend(m.build_depend()->name(), m.build_depend()->description(), keys[m.build_depend()->name()]);
+ if (! m.dependencies()->name().empty())
+ {
+ DependenciesRewriter rewriter;
+ parse_depend(keys[m.dependencies()->name()], _imp->env, id, *id->eapi())->root()->accept(rewriter);
+ id->load_build_depend(m.dependencies()->name() + ".DEPEND", m.dependencies()->description() + " (build)", rewriter.depend());
+ id->load_run_depend(m.dependencies()->name() + ".RDEPEND", m.dependencies()->description() + " (run)", rewriter.rdepend());
+ id->load_post_depend(m.dependencies()->name() + ".PDEPEND", m.dependencies()->description() + " (post)", rewriter.pdepend());
+ }
- if (! m.run_depend()->name().empty())
- id->load_run_depend(m.run_depend()->name(), m.run_depend()->description(), keys[m.run_depend()->name()]);
+ if (! m.build_depend()->name().empty())
+ id->load_build_depend(m.build_depend()->name(), m.build_depend()->description(), keys[m.build_depend()->name()]);
- id->load_slot(m.slot(), keys[m.slot()->name()]);
+ if (! m.run_depend()->name().empty())
+ id->load_run_depend(m.run_depend()->name(), m.run_depend()->description(), keys[m.run_depend()->name()]);
- if (! m.src_uri()->name().empty())
- id->load_src_uri(m.src_uri(), keys[m.src_uri()->name()]);
+ id->load_slot(m.slot(), keys[m.slot()->name()]);
- if (! m.restrictions()->name().empty())
- id->load_restrict(m.restrictions(), keys[m.restrictions()->name()]);
+ if (! m.src_uri()->name().empty())
+ id->load_src_uri(m.src_uri(), keys[m.src_uri()->name()]);
- if (! m.properties()->name().empty())
- id->load_properties(m.properties(), keys[m.properties()->name()]);
+ if (! m.restrictions()->name().empty())
+ id->load_restrict(m.restrictions(), keys[m.restrictions()->name()]);
- if (! m.homepage()->name().empty())
- id->load_homepage(m.homepage()->name(), m.homepage()->description(), keys[m.homepage()->name()]);
+ if (! m.properties()->name().empty())
+ id->load_properties(m.properties(), keys[m.properties()->name()]);
- if (! m.license()->name().empty())
- id->load_license(m.license(), keys[m.license()->name()]);
+ if (! m.homepage()->name().empty())
+ id->load_homepage(m.homepage()->name(), m.homepage()->description(), keys[m.homepage()->name()]);
- if (! m.short_description()->name().empty())
- id->load_short_description(m.short_description()->name(),
- m.short_description()->description(),
- keys[m.short_description()->name()]);
+ if (! m.license()->name().empty())
+ id->load_license(m.license(), keys[m.license()->name()]);
- if (! m.long_description()->name().empty())
- {
- std::string value(keys[m.long_description()->name()]);
- if (! value.empty())
- id->load_long_description(m.long_description()->name(),
- m.long_description()->description(), value);
- }
+ if (! m.short_description()->name().empty())
+ id->load_short_description(m.short_description()->name(),
+ m.short_description()->description(),
+ keys[m.short_description()->name()]);
- if (! m.keywords()->name().empty())
- id->load_keywords(m.keywords()->name(), m.keywords()->description(), keys[m.keywords()->name()]);
+ if (! m.long_description()->name().empty())
+ {
+ std::string value(keys[m.long_description()->name()]);
+ if (! value.empty())
+ id->load_long_description(m.long_description()->name(),
+ m.long_description()->description(), value);
+ }
- if (! m.inherited()->name().empty())
- id->load_inherited(m.inherited()->name(), m.inherited()->description(), join(inherited.begin(), inherited.end(), " "));
+ if (! m.keywords()->name().empty())
+ id->load_keywords(m.keywords()->name(), m.keywords()->description(), keys[m.keywords()->name()]);
- if (! m.defined_phases()->name().empty())
- if (! keys[m.defined_phases()->name()].empty())
- id->load_defined_phases(m.defined_phases()->name(), m.defined_phases()->description(), keys[m.defined_phases()->name()]);
+ if (! m.inherited()->name().empty())
+ id->load_inherited(m.inherited()->name(), m.inherited()->description(), join(inherited.begin(), inherited.end(), " "));
- if (! m.iuse()->name().empty())
- id->load_iuse(m.iuse()->name(), m.iuse()->description(), keys[m.iuse()->name()]);
+ if (! m.defined_phases()->name().empty())
+ if (! keys[m.defined_phases()->name()].empty())
+ id->load_defined_phases(m.defined_phases()->name(), m.defined_phases()->description(), keys[m.defined_phases()->name()]);
- if (! m.myoptions()->name().empty())
- id->load_myoptions(m.myoptions()->name(), m.myoptions()->description(), keys[m.myoptions()->name()]);
+ if (! m.iuse()->name().empty())
+ id->load_iuse(m.iuse()->name(), m.iuse()->description(), keys[m.iuse()->name()]);
- if (! m.pdepend()->name().empty())
- id->load_post_depend(m.pdepend()->name(), m.pdepend()->description(), keys[m.pdepend()->name()]);
+ if (! m.myoptions()->name().empty())
+ id->load_myoptions(m.myoptions()->name(), m.myoptions()->description(), keys[m.myoptions()->name()]);
- if (! m.provide()->name().empty())
- id->load_provide(m.provide()->name(), m.provide()->description(), keys[m.provide()->name()]);
+ if (! m.pdepend()->name().empty())
+ id->load_post_depend(m.pdepend()->name(), m.pdepend()->description(), keys[m.pdepend()->name()]);
- if (! m.use()->name().empty())
- id->load_use(m.use()->name(), m.use()->description(), keys[m.use()->name()]);
+ if (! m.provide()->name().empty())
+ id->load_provide(m.provide()->name(), m.provide()->description(), keys[m.provide()->name()]);
- if (! m.upstream_changelog()->name().empty())
- {
- std::string value(keys[m.upstream_changelog()->name()]);
- if (! value.empty())
- id->load_upstream_changelog(m.upstream_changelog()->name(),
- m.upstream_changelog()->description(), value);
- }
+ if (! m.use()->name().empty())
+ id->load_use(m.use()->name(), m.use()->description(), keys[m.use()->name()]);
- if (! m.upstream_documentation()->name().empty())
- {
- std::string value(keys[m.upstream_documentation()->name()]);
- if (! value.empty())
- id->load_upstream_documentation(m.upstream_documentation()->name(),
- m.upstream_documentation()->description(), value);
- }
+ if (! m.upstream_changelog()->name().empty())
+ {
+ std::string value(keys[m.upstream_changelog()->name()]);
+ if (! value.empty())
+ id->load_upstream_changelog(m.upstream_changelog()->name(),
+ m.upstream_changelog()->description(), value);
+ }
- if (! m.upstream_release_notes()->name().empty())
- {
- std::string value(keys[m.upstream_release_notes()->name()]);
- if (! value.empty())
- id->load_upstream_release_notes(m.upstream_release_notes()->name(),
- m.upstream_release_notes()->description(), value);
- }
+ if (! m.upstream_documentation()->name().empty())
+ {
+ std::string value(keys[m.upstream_documentation()->name()]);
+ if (! value.empty())
+ id->load_upstream_documentation(m.upstream_documentation()->name(),
+ m.upstream_documentation()->description(), value);
+ }
- if (! m.bugs_to()->name().empty())
- {
- std::string value(keys[m.bugs_to()->name()]);
- if (! value.empty())
- id->load_bugs_to(m.bugs_to(), value);
- }
+ if (! m.upstream_release_notes()->name().empty())
+ {
+ std::string value(keys[m.upstream_release_notes()->name()]);
+ if (! value.empty())
+ id->load_upstream_release_notes(m.upstream_release_notes()->name(),
+ m.upstream_release_notes()->description(), value);
+ }
- if (! m.remote_ids()->name().empty())
- {
- std::string value(keys[m.remote_ids()->name()]);
- if (! value.empty())
- id->load_remote_ids(m.remote_ids(), value);
- }
+ if (! m.bugs_to()->name().empty())
+ {
+ std::string value(keys[m.bugs_to()->name()]);
+ if (! value.empty())
+ id->load_bugs_to(m.bugs_to(), value);
}
- Log::get_instance()->message("e.cache.success", ll_debug, lc_context) << "Successfully loaded cache file";
- return true;
- }
- catch (const InternalError &)
- {
- throw;
- }
- catch (const Exception & e)
- {
- Log::get_instance()->message("e.cache.failure", ll_warning, lc_no_context) << "Not using cache file at '"
- << _imp->filename << "' due to exception '" << e.message() << "' (" << e.what() << ")";
- return false;
+ if (! m.remote_ids()->name().empty())
+ {
+ std::string value(keys[m.remote_ids()->name()]);
+ if (! value.empty())
+ id->load_remote_ids(m.remote_ids(), value);
+ }
}
+
+ Log::get_instance()->message("e.cache.success", ll_debug, lc_context) << "Successfully loaded cache file";
+ return true;
}
- else
+ catch (const InternalError &)
{
- Log::get_instance()->message("e.cache.failure", _imp->silent ? ll_debug : ll_warning, lc_no_context)
- << "Couldn't use the cache file at '" << _imp->filename << "': " << std::strerror(errno);
+ throw;
+ }
+ catch (const Exception & e)
+ {
+ Log::get_instance()->message("e.cache.failure", ll_warning, lc_no_context) << "Not using cache file at '"
+ << _imp->filename << "' due to exception '" << e.message() << "' (" << e.what() << ")";
return false;
}
}
@@ -789,19 +788,19 @@ EbuildFlatMetadataCache::save(const std::tr1::shared_ptr<const EbuildID> & id)
return;
}
- std::ofstream cache_file(stringify(_imp->filename).c_str());
-
- if (cache_file)
+ try
{
- cache_file << cache.str();
- cache_file.close();
+ {
+ SafeOFStream cache_file(_imp->filename);
+ cache_file << cache.str();
+ }
struct ::utimbuf times = { _imp->ebuild.mtime(), _imp->ebuild.mtime() };
_imp->filename.utime(&times);
}
- else
+ catch (const SafeOFStreamError & e)
{
Log::get_instance()->message("e.cache.save.failure", ll_warning, lc_no_context) << "Couldn't write cache file to '"
- << _imp->filename << "': " << std::strerror(errno);
+ << _imp->filename << "': " << e.message() + " (" + e.what() + ")";
}
}
diff --git a/paludis/repositories/e/ebuild_flat_metadata_cache_TEST.cc b/paludis/repositories/e/ebuild_flat_metadata_cache_TEST.cc
index 53441c7..fdb5dd8 100644
--- a/paludis/repositories/e/ebuild_flat_metadata_cache_TEST.cc
+++ b/paludis/repositories/e/ebuild_flat_metadata_cache_TEST.cc
@@ -31,9 +31,11 @@
#include <paludis/util/set.hh>
#include <paludis/util/simple_visitor_cast.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/safe_ifstream.hh>
+#include <paludis/util/fs_entry.hh>
#include <test/test_framework.hh>
#include <test/test_runner.hh>
-#include <fstream>
+#include <iterator>
using namespace test;
using namespace paludis;
@@ -1079,8 +1081,8 @@ namespace test_cases
std::string contents(const std::string & filename)
{
- std::ifstream s(filename.c_str());
- return std::string(std::istreambuf_iterator<char>(s), std::istreambuf_iterator<char>());
+ SafeIFStream s(FSEntry(filename).realpath());
+ return std::string((std::istreambuf_iterator<char>(s)), std::istreambuf_iterator<char>());
}
void run()
@@ -1115,8 +1117,8 @@ namespace test_cases
std::string contents(const std::string & filename)
{
- std::ifstream s(filename.c_str());
- return std::string(std::istreambuf_iterator<char>(s), std::istreambuf_iterator<char>());
+ SafeIFStream s(FSEntry(filename).realpath());
+ return std::string((std::istreambuf_iterator<char>(s)), std::istreambuf_iterator<char>());
}
void run()
@@ -1153,8 +1155,8 @@ namespace test_cases
std::string contents(const std::string & filename)
{
- std::ifstream s(filename.c_str());
- return std::string(std::istreambuf_iterator<char>(s), std::istreambuf_iterator<char>());
+ SafeIFStream s(FSEntry(filename).realpath());
+ return std::string((std::istreambuf_iterator<char>(s)), std::istreambuf_iterator<char>());
}
void run()
diff --git a/paludis/repositories/e/ebuild_id.cc b/paludis/repositories/e/ebuild_id.cc
index bec57ed..9a39e91 100644
--- a/paludis/repositories/e/ebuild_id.cc
+++ b/paludis/repositories/e/ebuild_id.cc
@@ -53,7 +53,6 @@
#include <set>
#include <iterator>
-#include <fstream>
using namespace paludis;
using namespace paludis::erepository;
diff --git a/paludis/repositories/e/exndbam_repository.cc b/paludis/repositories/e/exndbam_repository.cc
index bd37e7a..f6f187c 100644
--- a/paludis/repositories/e/exndbam_repository.cc
+++ b/paludis/repositories/e/exndbam_repository.cc
@@ -37,6 +37,7 @@
#include <paludis/util/system.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/output_manager.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/distribution.hh>
#include <paludis/environment.hh>
#include <paludis/ndbam.hh>
@@ -47,7 +48,6 @@
#include <paludis/action.hh>
#include <paludis/literal_metadata_key.hh>
#include <tr1/functional>
-#include <fstream>
using namespace paludis;
using namespace paludis::erepository;
@@ -355,10 +355,10 @@ ExndbamRepository::merge(const MergeParams & m)
/* load CONFIG_PROTECT, CONFIG_PROTECT_MASK back */
std::string config_protect, config_protect_mask;
{
- std::ifstream c(stringify(target_ver_dir / "CONFIG_PROTECT").c_str());
+ SafeIFStream c(target_ver_dir / "CONFIG_PROTECT");
config_protect = std::string((std::istreambuf_iterator<char>(c)), std::istreambuf_iterator<char>());
- std::ifstream c_m(stringify(target_ver_dir / "CONFIG_PROTECT_MASK").c_str());
+ SafeIFStream c_m(target_ver_dir / "CONFIG_PROTECT_MASK");
config_protect_mask = std::string((std::istreambuf_iterator<char>(c_m)), std::istreambuf_iterator<char>());
}
@@ -450,11 +450,11 @@ ExndbamRepository::perform_uninstall(const std::tr1::shared_ptr<const ERepositor
/* load CONFIG_PROTECT, CONFIG_PROTECT_MASK from vdb, supplement with env */
std::string config_protect, config_protect_mask;
{
- std::ifstream c(stringify(ver_dir / "CONFIG_PROTECT").c_str());
+ SafeIFStream c(ver_dir / "CONFIG_PROTECT");
config_protect = std::string((std::istreambuf_iterator<char>(c)), std::istreambuf_iterator<char>()) +
" " + getenv_with_default("CONFIG_PROTECT", "");
- std::ifstream c_m(stringify(ver_dir / "CONFIG_PROTECT_MASK").c_str());
+ SafeIFStream c_m(ver_dir / "CONFIG_PROTECT_MASK");
config_protect_mask = std::string((std::istreambuf_iterator<char>(c_m)), std::istreambuf_iterator<char>()) +
" " + getenv_with_default("CONFIG_PROTECT_MASK", "");
}
diff --git a/paludis/repositories/e/fetch_visitor_TEST.cc b/paludis/repositories/e/fetch_visitor_TEST.cc
index 554fe82..18c60dd 100644
--- a/paludis/repositories/e/fetch_visitor_TEST.cc
+++ b/paludis/repositories/e/fetch_visitor_TEST.cc
@@ -26,6 +26,7 @@
#include <paludis/util/sequence.hh>
#include <paludis/util/make_shared_ptr.hh>
#include <paludis/util/standard_output_manager.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/package_database.hh>
#include <paludis/user_dep_spec.hh>
#include <paludis/generator.hh>
@@ -34,7 +35,6 @@
#include <paludis/selection.hh>
#include <test/test_runner.hh>
#include <test/test_framework.hh>
-#include <fstream>
#include <iterator>
using namespace test;
@@ -67,7 +67,7 @@ namespace test_cases
parse_fetchable_uri("file:///" + stringify(FSEntry("fetch_visitor_TEST_dir/in/input1").realpath()), &env, id, *eapi)->root()->accept(v);
TEST_CHECK(FSEntry("fetch_visitor_TEST_dir/out/input1").is_regular_file());
- std::ifstream f(stringify(FSEntry("fetch_visitor_TEST_dir/out/input1")).c_str());
+ SafeIFStream f(FSEntry("fetch_visitor_TEST_dir/out/input1"));
TEST_CHECK(f);
std::string s((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(s, "contents of one\n");
diff --git a/paludis/repositories/e/qa/changelog.cc b/paludis/repositories/e/qa/changelog.cc
index 90e2b3b..269d0ea 100644
--- a/paludis/repositories/e/qa/changelog.cc
+++ b/paludis/repositories/e/qa/changelog.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2008 Ciaran McCreesh
+ * Copyright (c) 2006, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -22,7 +22,7 @@
#include <paludis/util/fs_entry.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/log.hh>
-#include <fstream>
+#include <paludis/util/safe_ifstream.hh>
using namespace paludis;
@@ -46,7 +46,7 @@ paludis::erepository::changelog_check(
reporter.message(QAMessage(f, qaml_normal, name, "Not a regular file"));
else
{
- std::ifstream ff(stringify(f).c_str());
+ SafeIFStream ff(f);
do
{
if (! ff)
diff --git a/paludis/repositories/e/qa/manifest.cc b/paludis/repositories/e/qa/manifest.cc
index c5bd695..b6ddd5a 100644
--- a/paludis/repositories/e/qa/manifest.cc
+++ b/paludis/repositories/e/qa/manifest.cc
@@ -32,10 +32,10 @@
#include <paludis/util/sha256.hh>
#include <paludis/util/rmd160.hh>
#include <paludis/util/md5.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/repositories/e/e_repository.hh>
#include <paludis/repositories/e/layout.hh>
#include <paludis/repositories/e/manifest2_reader.hh>
-#include <fstream>
#include <set>
#include <map>
@@ -148,7 +148,7 @@ namespace
if (! entry.sha1().empty())
{
- std::ifstream s(stringify(file).c_str());
+ SafeIFStream s(file);
SHA1 sha1(s);
if (entry.sha1() != sha1.hexsum())
reporter.message(QAMessage(file, qaml_normal, name, "File SHA1 is '" + sha1.hexsum() + "', but Manifest lists '" + entry.sha1() + "'"));
@@ -157,7 +157,7 @@ namespace
if (! entry.sha256().empty())
{
- std::ifstream s(stringify(file).c_str());
+ SafeIFStream s(file);
SHA256 sha256(s);
if (entry.sha256() != sha256.hexsum())
reporter.message(QAMessage(file, qaml_normal, name, "File SHA256 is '" + sha256.hexsum() + "', but Manifest lists '" + entry.sha256() + "'"));
@@ -166,7 +166,7 @@ namespace
if (! entry.rmd160().empty())
{
- std::ifstream s(stringify(file).c_str());
+ SafeIFStream s(file);
RMD160 rmd160(s);
if (entry.rmd160() != rmd160.hexsum())
reporter.message(QAMessage(file, qaml_normal, name, "File RMD160 is '" + rmd160.hexsum() + "', but Manifest lists '" + entry.rmd160() + "'"));
@@ -175,7 +175,7 @@ namespace
if (! entry.md5().empty())
{
- std::ifstream s(stringify(file).c_str());
+ SafeIFStream s(file);
MD5 md5(s);
if (entry.md5() != md5.hexsum())
reporter.message(QAMessage(file, qaml_normal, name, "File MD5 is '" + md5.hexsum() + "', but Manifest lists '" + entry.md5() + "'"));
@@ -258,16 +258,18 @@ paludis::erepository::manifest_check(
bool is_signed(false);
{
- std::ifstream ff(stringify(manifest).c_str());
- if (! ff)
+ try
+ {
+ SafeIFStream ff(manifest);
+ std::string s;
+ if (std::getline(ff, s))
+ is_signed = (0 == s.compare("-----BEGIN PGP SIGNED MESSAGE-----"));
+ }
+ catch (const SafeIFStreamError &)
{
reporter.message(QAMessage(manifest, qaml_normal, name, "Can't read Manifest file"));
return true;
}
-
- std::string s;
- if (std::getline(ff, s))
- is_signed = (0 == s.compare("-----BEGIN PGP SIGNED MESSAGE-----"));
}
if (is_signed)
diff --git a/paludis/repositories/e/qa/qa_controller.cc b/paludis/repositories/e/qa/qa_controller.cc
index 31187ec..eb208b8 100644
--- a/paludis/repositories/e/qa/qa_controller.cc
+++ b/paludis/repositories/e/qa/qa_controller.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -31,10 +31,10 @@
#include <paludis/util/action_queue.hh>
#include <paludis/util/dir_iterator.hh>
#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/qa.hh>
#include <paludis/metadata_key.hh>
#include <tr1/functional>
-#include <fstream>
#include <unistd.h>
#include <algorithm>
#include <list>
@@ -229,7 +229,7 @@ QAController::_check_eclasses(const FSEntry & dir, const std::string & type)
for (DirIterator it(dir), it_end; it_end != it; ++it)
if (is_file_with_extension(*it, type, IsFileWithOptions()))
{
- std::ifstream f(stringify(*it).c_str());
+ SafeIFStream f(*it);
std::string content((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
if (! f)
@@ -355,7 +355,7 @@ QAController::_check_id(const std::tr1::shared_ptr<const PackageID> & i)
_1, i->fs_location_key()->value(), std::tr1::ref(_imp->reporter),
_imp->env, _imp->repo, std::tr1::static_pointer_cast<const ERepositoryID>(i))));
- std::ifstream f(stringify(i->fs_location_key()->value()).c_str());
+ SafeIFStream f(i->fs_location_key()->value());
std::string content((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
if (! f)
_imp->reporter.message(
diff --git a/paludis/repositories/e/qa/repo_name.cc b/paludis/repositories/e/qa/repo_name.cc
index a8a91b9..85ddf69 100644
--- a/paludis/repositories/e/qa/repo_name.cc
+++ b/paludis/repositories/e/qa/repo_name.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -20,9 +20,9 @@
#include "repo_name.hh"
#include <paludis/util/fs_entry.hh>
#include <paludis/util/stringify.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/repository.hh>
#include <paludis/qa.hh>
-#include <fstream>
using namespace paludis;
using namespace paludis::erepository;
@@ -37,7 +37,7 @@ paludis::erepository::repo_name_check(
reporter.message(QAMessage(dir / "profiles" / "repo_name", qaml_normal, name, "No 'profiles/repo_name' file"));
else
{
- std::ifstream f(stringify(dir / "profiles" / "repo_name").c_str());
+ SafeIFStream f(dir / "profiles" / "repo_name");
if (! f)
reporter.message(QAMessage(dir / "profiles" / "repo_name", qaml_normal, name, "repo_name file unreadable"));
else
diff --git a/paludis/repositories/e/vdb_merger.cc b/paludis/repositories/e/vdb_merger.cc
index 95556cd..af4af9b 100644
--- a/paludis/repositories/e/vdb_merger.cc
+++ b/paludis/repositories/e/vdb_merger.cc
@@ -30,13 +30,14 @@
#include <paludis/util/options.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/output_manager.hh>
+#include <paludis/util/safe_ofstream.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/hook.hh>
#include <paludis/package_id.hh>
#include <paludis/util/md5.hh>
#include <paludis/environment.hh>
#include <paludis/package_database.hh>
#include <paludis/metadata_key.hh>
-#include <fstream>
#include <iomanip>
#include <list>
@@ -49,7 +50,7 @@ namespace paludis
{
VDBMergerParams params;
FSEntry realroot;
- std::tr1::shared_ptr<std::ofstream> contents_file;
+ std::tr1::shared_ptr<SafeOFStream> contents_file;
std::list<std::string> config_protect;
std::list<std::string> config_protect_mask;
@@ -137,7 +138,7 @@ VDBMerger::record_install_file(const FSEntry & src, const FSEntry & dst_dir, con
tidy_real(stringify((dst_dir / src.basename()).strip_leading(_imp->realroot)));
time_t timestamp((dst_dir / dst_name).mtime());
- std::ifstream infile(stringify(FSEntry(dst_dir / dst_name)).c_str());
+ SafeIFStream infile(FSEntry(dst_dir / dst_name));
if (! infile)
throw MergerError("Cannot read '" + stringify(FSEntry(dst_dir / dst_name)) + "'");
@@ -230,7 +231,7 @@ VDBMerger::make_config_protect_name(const FSEntry & src, const FSEntry & dst)
std::string result_name(src.basename());
int n(0);
- std::ifstream our_md5_file(stringify(src).c_str());
+ SafeIFStream our_md5_file(src);
if (! our_md5_file)
throw MergerError("Could not get md5 for '" + stringify((dst / src.basename()).strip_leading(_imp->realroot)) + "'");
MD5 our_md5(our_md5_file);
@@ -242,13 +243,16 @@ VDBMerger::make_config_protect_name(const FSEntry & src, const FSEntry & dst)
if ((dst / result_name).is_regular_file_or_symlink_to_regular_file())
{
- std::ifstream other_md5_file(stringify(dst / result_name).c_str());
- if (other_md5_file)
+ try
{
+ SafeIFStream other_md5_file(dst / result_name);
MD5 other_md5(other_md5_file);
if (our_md5.hexsum() == other_md5.hexsum())
break;
}
+ catch (const SafeIFStreamError &)
+ {
+ }
}
std::stringstream s;
@@ -263,7 +267,7 @@ void
VDBMerger::merge()
{
display_override(">>> Merging to " + stringify(_imp->params.root()));
- _imp->contents_file.reset(new std::ofstream(stringify(_imp->params.contents_file()).c_str()));
+ _imp->contents_file.reset(new SafeOFStream(_imp->params.contents_file()));
Merger::merge();
}
diff --git a/paludis/repositories/e/vdb_merger_TEST.cc b/paludis/repositories/e/vdb_merger_TEST.cc
index 5f129a0..67637e3 100644
--- a/paludis/repositories/e/vdb_merger_TEST.cc
+++ b/paludis/repositories/e/vdb_merger_TEST.cc
@@ -24,9 +24,9 @@
#include <paludis/util/make_named_values.hh>
#include <paludis/util/make_shared_ptr.hh>
#include <paludis/util/standard_output_manager.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <test/test_framework.hh>
#include <test/test_runner.hh>
-#include <fstream>
using namespace paludis;
using namespace test;
@@ -105,13 +105,18 @@ namespace test_cases
if (! f.is_regular_file())
return "";
- std::ifstream stream(stringify(f).c_str());
- if (! stream)
- return "";
+ try
+ {
+ SafeIFStream stream(f);
- std::string contents;
- stream >> contents;
- return contents;
+ std::string contents;
+ stream >> contents;
+ return contents;
+ }
+ catch (const SafeIFStreamError &)
+ {
+ return "";
+ }
}
void run()
diff --git a/paludis/repositories/e/vdb_repository.cc b/paludis/repositories/e/vdb_repository.cc
index 011802d..dd4058f 100644
--- a/paludis/repositories/e/vdb_repository.cc
+++ b/paludis/repositories/e/vdb_repository.cc
@@ -70,10 +70,10 @@
#include <paludis/util/hashes.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/output_manager.hh>
-
+#include <paludis/util/safe_ifstream.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <tr1/unordered_map>
#include <tr1/functional>
-#include <fstream>
#include <functional>
#include <algorithm>
#include <vector>
@@ -409,11 +409,11 @@ VDBRepository::perform_uninstall(const std::tr1::shared_ptr<const ERepositoryID>
/* load CONFIG_PROTECT, CONFIG_PROTECT_MASK from vdb, supplement with env */
std::string config_protect, config_protect_mask;
{
- std::ifstream c(stringify(pkg_dir / "CONFIG_PROTECT").c_str());
+ SafeIFStream c(pkg_dir / "CONFIG_PROTECT");
config_protect = std::string((std::istreambuf_iterator<char>(c)), std::istreambuf_iterator<char>()) +
" " + getenv_with_default("CONFIG_PROTECT", "");
- std::ifstream c_m(stringify(pkg_dir / "CONFIG_PROTECT_MASK").c_str());
+ SafeIFStream c_m(pkg_dir / "CONFIG_PROTECT_MASK");
config_protect_mask = std::string((std::istreambuf_iterator<char>(c_m)), std::istreambuf_iterator<char>()) +
" " + getenv_with_default("CONFIG_PROTECT_MASK", "");
}
@@ -563,7 +563,7 @@ VDBRepository::load_provided_using_cache() const
return false;
}
- std::ifstream provides_cache(stringify(_imp->params.provides_cache()).c_str());
+ SafeIFStream provides_cache(_imp->params.provides_cache());
std::string version;
std::getline(provides_cache, version);
@@ -715,25 +715,28 @@ VDBRepository::write_provides_cache() const
{
Context context("When saving provides cache to '" + stringify(_imp->params.provides_cache()) + "':");
- std::ofstream f(stringify(_imp->params.provides_cache()).c_str());
- if (! f)
+ try
{
- Log::get_instance()->message("e.vdb.provides.write_failed", ll_warning, lc_context) << "Cannot write to '" <<
- _imp->params.provides_cache() << "': " << std::strerror(errno);
- return;
- }
+ SafeOFStream f(_imp->params.provides_cache());
- f << "paludis-3" << std::endl;
- f << name() << std::endl;
+ f << "paludis-3" << std::endl;
+ f << name() << std::endl;
- for (ProvidesMap::const_iterator it(_imp->provides_map->begin()),
- it_end(_imp->provides_map->end()); it_end != it; ++it)
+ for (ProvidesMap::const_iterator it(_imp->provides_map->begin()),
+ it_end(_imp->provides_map->end()); it_end != it; ++it)
+ {
+ f << it->first.first << " " << it->first.second;
+ for (Sequence<QualifiedPackageName>::ConstIterator it2(it->second->begin()),
+ it2_end(it->second->end()); it2_end != it2; ++it2)
+ f << " " << *it2;
+ f << std::endl;
+ }
+ }
+ catch (const SafeOFStreamError & e)
{
- f << it->first.first << " " << it->first.second;
- for (Sequence<QualifiedPackageName>::ConstIterator it2(it->second->begin()),
- it2_end(it->second->end()); it2_end != it2; ++it2)
- f << " " << *it2;
- f << std::endl;
+ Log::get_instance()->message("e.vdb.provides.write_failed", ll_warning, lc_context) << "Cannot write to '" <<
+ _imp->params.provides_cache() << "': '" << e.message() << "' (" << e.what() << ")";
+ return;
}
}
@@ -825,10 +828,10 @@ VDBRepository::merge(const MergeParams & m)
/* load CONFIG_PROTECT, CONFIG_PROTECT_MASK from vdb */
std::string config_protect, config_protect_mask;
{
- std::ifstream c(stringify(tmp_vdb_dir / "CONFIG_PROTECT").c_str());
+ SafeIFStream c(tmp_vdb_dir / "CONFIG_PROTECT");
config_protect = std::string((std::istreambuf_iterator<char>(c)), std::istreambuf_iterator<char>());
- std::ifstream c_m(stringify(tmp_vdb_dir / "CONFIG_PROTECT_MASK").c_str());
+ SafeIFStream c_m(tmp_vdb_dir / "CONFIG_PROTECT_MASK");
config_protect_mask = std::string((std::istreambuf_iterator<char>(c_m)), std::istreambuf_iterator<char>());
}
diff --git a/paludis/repositories/e/vdb_repository_TEST.cc b/paludis/repositories/e/vdb_repository_TEST.cc
index 9f07aa9..6be75bd 100644
--- a/paludis/repositories/e/vdb_repository_TEST.cc
+++ b/paludis/repositories/e/vdb_repository_TEST.cc
@@ -28,6 +28,7 @@
#include <paludis/util/dir_iterator.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/standard_output_manager.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/generator.hh>
#include <paludis/filter.hh>
#include <paludis/filtered_generator.hh>
@@ -41,7 +42,6 @@
#include <test/test_runner.hh>
#include <tr1/functional>
#include <algorithm>
-#include <fstream>
#include <functional>
#include <iterator>
#include <vector>
@@ -827,7 +827,7 @@ namespace test_cases
std::string read_file(const FSEntry & f)
{
- std::ifstream s(stringify(f).c_str());
+ SafeIFStream s(f);
std::stringstream ss;
std::copy(std::istreambuf_iterator<char>(s), std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(ss));
@@ -914,7 +914,7 @@ namespace test_cases
std::string read_file(const FSEntry & f)
{
- std::ifstream s(stringify(f).c_str());
+ SafeIFStream s(f);
std::stringstream ss;
std::copy(std::istreambuf_iterator<char>(s), std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(ss));
@@ -1159,7 +1159,7 @@ namespace test_cases
std::string read_file(const FSEntry & f)
{
- std::ifstream s(stringify(f).c_str());
+ SafeIFStream s(f);
std::stringstream ss;
std::copy(std::istreambuf_iterator<char>(s), std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(ss));
diff --git a/paludis/repositories/e/vdb_unmerger.cc b/paludis/repositories/e/vdb_unmerger.cc
index cbadede..c5d1ef0 100644
--- a/paludis/repositories/e/vdb_unmerger.cc
+++ b/paludis/repositories/e/vdb_unmerger.cc
@@ -40,11 +40,11 @@ using namespace paludis;
#include <paludis/util/strip.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/output_manager.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <list>
#include <map>
#include <vector>
-#include <fstream>
namespace paludis
{
@@ -205,7 +205,7 @@ VDBUnmerger::make_tidy(const FSEntry & f) const
void
VDBUnmerger::populate_unmerge_set()
{
- std::ifstream c(stringify(_imp->options.contents_file()).c_str());
+ SafeIFStream c(_imp->options.contents_file());
if (! c)
throw VDBUnmergerError("Cannot read '" + stringify(_imp->options.contents_file()) + "'");
@@ -266,19 +266,22 @@ VDBUnmerger::check_file(const FSEntry & f, const std::tr1::shared_ptr<ExtraInfo>
display("--- [!time] " + stringify(f));
else
{
- std::ifstream md5_file(stringify(_imp->options.root() / f).c_str());
- if (! md5_file)
+ try
+ {
+ SafeIFStream md5_file(_imp->options.root() / f);
+ if (MD5(md5_file).hexsum() != fie->_md5sum)
+ display("--- [!md5 ] " + stringify(f));
+ else if (config_protected(_imp->options.root() / f))
+ display("--- [cfgpr] " + stringify(f));
+ else
+ return true;
+ }
+ catch (const SafeIFStreamError &)
{
Log::get_instance()->message("e.vdb.contents.md5_failed", ll_warning, lc_no_context)
<< "Cannot get md5 for '" << (_imp->options.root() / f) << "'";
display("--- [!md5?] " + stringify(f));
}
- else if (MD5(md5_file).hexsum() != fie->_md5sum)
- display("--- [!md5 ] " + stringify(f));
- else if (config_protected(_imp->options.root() / f))
- display("--- [cfgpr] " + stringify(f));
- else
- return true;
}
return false;
diff --git a/paludis/repositories/gems/gems_repository.cc b/paludis/repositories/gems/gems_repository.cc
index a272ac3..d021eb9 100644
--- a/paludis/repositories/gems/gems_repository.cc
+++ b/paludis/repositories/gems/gems_repository.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -33,13 +33,13 @@
#include <paludis/util/mutex.hh>
#include <paludis/util/hashes.hh>
#include <paludis/util/make_named_values.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/action.hh>
#include <paludis/metadata_key.hh>
#include <paludis/literal_metadata_key.hh>
#include <paludis/distribution.hh>
#include <paludis/environment.hh>
#include <tr1/unordered_map>
-#include <fstream>
using namespace paludis;
@@ -243,9 +243,7 @@ GemsRepository::need_ids() const
Context context("When loading gems yaml file:");
- std::ifstream yaml_file(stringify(_imp->params.location() / "yaml").c_str());
- if (! yaml_file)
- throw ConfigurationError("Gems yaml file '" + stringify(_imp->params.location() / "yaml") + "' not readable");
+ SafeIFStream yaml_file(_imp->params.location() / "yaml");
std::string output((std::istreambuf_iterator<char>(yaml_file)), std::istreambuf_iterator<char>());
yaml::Document master_doc(output);
diff --git a/paludis/repositories/unavailable/unavailable_repository_file.cc b/paludis/repositories/unavailable/unavailable_repository_file.cc
index dc406e0..8c395e6 100644
--- a/paludis/repositories/unavailable/unavailable_repository_file.cc
+++ b/paludis/repositories/unavailable/unavailable_repository_file.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2008 Ciaran McCreesh
+ * Copyright (c) 2008, 2009 Ciaran McCreesh
*
* 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
@@ -25,11 +25,11 @@
#include <paludis/util/log.hh>
#include <paludis/util/simple_parser.hh>
#include <paludis/util/make_named_values.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/name.hh>
#include <paludis/version_spec.hh>
#include <paludis/literal_metadata_key.hh>
#include <list>
-#include <fstream>
using namespace paludis;
using namespace paludis::unavailable_repository;
@@ -69,9 +69,7 @@ UnavailableRepositoryFile::end() const
void
UnavailableRepositoryFile::_load(const FSEntry & f)
{
- std::ifstream file(stringify(f).c_str());
- if (! file)
- throw UnavailableRepositoryConfigurationError("Cannot read '" + stringify(f) + "'");
+ SafeIFStream file(f);
std::string line;
while (std::getline(file, line))
diff --git a/paludis/repositories/unpackaged/installed_id.cc b/paludis/repositories/unpackaged/installed_id.cc
index 097c2f2..f9f5d36 100644
--- a/paludis/repositories/unpackaged/installed_id.cc
+++ b/paludis/repositories/unpackaged/installed_id.cc
@@ -33,6 +33,7 @@
#include <paludis/util/hashes.hh>
#include <paludis/util/make_named_values.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/name.hh>
#include <paludis/version_spec.hh>
#include <paludis/package_database.hh>
@@ -42,7 +43,6 @@
#include <paludis/literal_metadata_key.hh>
#include <paludis/action.hh>
#include <tr1/functional>
-#include <fstream>
using namespace paludis;
using namespace paludis::unpackaged_repositories;
@@ -209,12 +209,9 @@ namespace
Lock l(_mutex);
if (_v)
return *_v;
- std::ifstream f(stringify(_f).c_str());
- if (! f)
- {
- Context context("When reading '" + stringify(_f) + "' as an InstalledUnpackagedStringKey:");
- throw FSError("Couldn't open '" + stringify(_f) + "' for read");
- }
+
+ Context context("When reading '" + stringify(_f) + "' as an InstalledUnpackagedStringKey:");
+ SafeIFStream f(_f);
_v.reset(new std::string(
strip_trailing(std::string((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()), "\n")));
return *_v;
@@ -271,12 +268,7 @@ namespace
for (FSEntrySequence::ConstIterator a(_f.begin()), a_end(_f.end()) ;
a != a_end ; ++a)
{
- std::ifstream f(stringify(*a).c_str());
- if (! f)
- {
- Context context("When reading '" + stringify(*a) + "' as an InstalledUnpackagedStringKey:");
- throw FSError("Couldn't open '" + stringify(*a) + "' for read");
- }
+ SafeIFStream f(*a);
_v->insert(strip_trailing(std::string((std::istreambuf_iterator<char>(f)),
std::istreambuf_iterator<char>()), "\n"));
}
@@ -340,10 +332,7 @@ namespace
Context context("When reading '" + stringify(_f) + "' as an InstalledUnpackagedDependencyKey:");
- std::ifstream f(stringify(_f).c_str());
- if (! f)
- throw FSError("Couldn't open '" + stringify(_f) + "' for read");
-
+ SafeIFStream f(_f);
_v = DepParser::parse(_env, strip_trailing(
std::string((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()), "\n"));
return _v;
diff --git a/paludis/repositories/unpackaged/installed_repository.cc b/paludis/repositories/unpackaged/installed_repository.cc
index 9eceab1..f8be695 100644
--- a/paludis/repositories/unpackaged/installed_repository.cc
+++ b/paludis/repositories/unpackaged/installed_repository.cc
@@ -34,13 +34,13 @@
#include <paludis/util/make_named_values.hh>
#include <paludis/util/indirect_iterator.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/stringify_formatter.hh>
#include <paludis/action.hh>
#include <paludis/environment.hh>
#include <paludis/dep_tag.hh>
#include <paludis/metadata_key.hh>
#include <paludis/literal_metadata_key.hh>
-#include <fstream>
#include <sstream>
#include <sys/time.h>
@@ -321,36 +321,28 @@ InstalledUnpackagedRepository::merge(const MergeParams & m)
target_ver_dir.mkdir();
{
- std::ofstream source_repository_file(stringify(target_ver_dir / "source_repository").c_str());
+ SafeOFStream source_repository_file(target_ver_dir / "source_repository");
source_repository_file << m.package_id()->repository()->name() << std::endl;
- if (! source_repository_file)
- throw InstallActionError("Could not write to '" + stringify(target_ver_dir / "source_repository") + "'");
}
if (m.package_id()->short_description_key())
{
- std::ofstream description_file(stringify(target_ver_dir / "description").c_str());
+ SafeOFStream description_file(target_ver_dir / "description");
description_file << m.package_id()->short_description_key()->value() << std::endl;
- if (! description_file)
- throw InstallActionError("Could not write to '" + stringify(target_ver_dir / "description") + "'");
}
if (m.package_id()->build_dependencies_key())
{
- std::ofstream build_dependencies_file(stringify(target_ver_dir / "build_dependencies").c_str());
+ SafeOFStream build_dependencies_file(target_ver_dir / "build_dependencies");
StringifyFormatter f;
build_dependencies_file << m.package_id()->build_dependencies_key()->pretty_print_flat(f) << std::endl;
- if (! build_dependencies_file)
- throw InstallActionError("Could not write to '" + stringify(target_ver_dir / "build_dependencies") + "'");
}
if (m.package_id()->run_dependencies_key())
{
- std::ofstream run_dependencies_file(stringify(target_ver_dir / "run_dependencies").c_str());
+ SafeOFStream run_dependencies_file(target_ver_dir / "run_dependencies");
StringifyFormatter f;
run_dependencies_file << m.package_id()->run_dependencies_key()->pretty_print_flat(f) << std::endl;
- if (! run_dependencies_file)
- throw InstallActionError("Could not write to '" + stringify(target_ver_dir / "run_dependencies") + "'");
}
NDBAMMerger merger(
diff --git a/paludis/repositories/unwritten/unwritten_repository_file.cc b/paludis/repositories/unwritten/unwritten_repository_file.cc
index d0e2860..8f48e90 100644
--- a/paludis/repositories/unwritten/unwritten_repository_file.cc
+++ b/paludis/repositories/unwritten/unwritten_repository_file.cc
@@ -28,6 +28,7 @@
#include <paludis/util/tokeniser.hh>
#include <paludis/util/make_shared_ptr.hh>
#include <paludis/util/join.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/name.hh>
#include <paludis/version_spec.hh>
#include <paludis/literal_metadata_key.hh>
@@ -35,7 +36,6 @@
#include <paludis/dep_spec.hh>
#include <paludis/formatter.hh>
#include <list>
-#include <fstream>
using namespace paludis;
using namespace paludis::unwritten_repository;
@@ -158,9 +158,7 @@ namespace
void
UnwrittenRepositoryFile::_load(const FSEntry & f)
{
- std::ifstream file(stringify(f).c_str());
- if (! file)
- throw UnwrittenRepositoryConfigurationError("Cannot read '" + stringify(f) + "'");
+ SafeIFStream file(f);
std::string line;
while (std::getline(file, line))
diff --git a/paludis/repository_name_cache.cc b/paludis/repository_name_cache.cc
index 58a3b32..07498af 100644
--- a/paludis/repository_name_cache.cc
+++ b/paludis/repository_name_cache.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -29,10 +29,11 @@
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/wrapped_output_iterator.hh>
#include <paludis/util/hashes.hh>
+#include <paludis/util/safe_ofstream.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <tr1/unordered_map>
#include <tr1/memory>
#include <set>
-#include <fstream>
#include <cstring>
#include <cerrno>
@@ -82,7 +83,7 @@ Implementation<RepositoryNameCache>::find(const PackageNamePart & p) const
{
if (location.is_directory() && (location / "_VERSION_").exists())
{
- std::ifstream vvf(stringify(location / "_VERSION_").c_str());
+ SafeIFStream vvf(location / "_VERSION_");
std::string line;
std::getline(vvf, line);
if (line != "paludis-2")
@@ -132,10 +133,7 @@ Implementation<RepositoryNameCache>::find(const PackageNamePart & p) const
FSEntry ff(location / stringify(p));
if (ff.exists())
{
- std::ifstream f(stringify(ff).c_str());
- if (! f)
- Log::get_instance()->message("repository.names_cache.read_failed", ll_warning, lc_context)
- << "Cannot read '" << ff << "': " << std::strerror(errno);
+ SafeIFStream f(ff);
std::string line;
while (std::getline(f, line))
r->second.insert(CategoryNamePart(line));
@@ -163,17 +161,20 @@ Implementation<RepositoryNameCache>::update(const PackageNamePart & p, NameCache
return;
}
- std::ofstream f(stringify(ff).c_str());
- if (! f)
+ try
+ {
+ SafeOFStream f(ff);
+
+ for (std::set<CategoryNamePart>::const_iterator it(r->second.begin()),
+ it_end(r->second.end()); it_end != it; ++it)
+ f << *it << std::endl;
+ }
+ catch (const SafeOFStreamError & e)
{
Log::get_instance()->message("repository.names_cache.write_failed", ll_warning, lc_context)
- << "Cannot write '" << ff << "': " << std::strerror(errno);
+ << "Cannot write '" << ff << "': '" << e.message() << "' (" << e.what() << ")";
return;
}
-
- for (std::set<CategoryNamePart>::const_iterator it(r->second.begin()),
- it_end(r->second.end()); it_end != it; ++it)
- f << *it << std::endl;
}
RepositoryNameCache::RepositoryNameCache(
@@ -242,25 +243,30 @@ RepositoryNameCache::regenerate_cache() const
for (std::tr1::unordered_map<std::string, std::string, Hash<std::string> >::const_iterator e(m.begin()), e_end(m.end()) ;
e != e_end ; ++e)
{
- std::ofstream f(stringify(_imp->location / stringify(e->first)).c_str());
- if (! f)
+ try
+ {
+ SafeOFStream f(_imp->location / stringify(e->first));
+ f << e->second;
+ }
+ catch (const SafeOFStreamError & ee)
{
Log::get_instance()->message("repository.names_cache.write_failed", ll_warning, lc_context)
- << "Cannot write to '" << _imp->location << "': " << std::strerror(errno);
+ << "Cannot write to '" << _imp->location << "': '" << ee.message() << "' (" << ee.what() << ")";
continue;
}
- f << e->second;
}
- std::ofstream f(stringify(_imp->location / "_VERSION_").c_str());
- if (f)
+ try
{
+ SafeOFStream f(_imp->location / "_VERSION_");;
f << "paludis-2" << std::endl;
f << _imp->repo->name() << std::endl;
}
- else
+ catch (const SafeOFStreamError & e)
+ {
Log::get_instance()->message("repository.names_cache.write_failed", ll_warning, lc_context)
- << "Cannot write to '" << _imp->location << "': " << std::strerror(errno);
+ << "Cannot write to '" << _imp->location << "': '" << e.message() << "' (" << e.what() << ")";
+ }
}
void
diff --git a/paludis/set_file.cc b/paludis/set_file.cc
index ba9dd34..8b1edf4 100644
--- a/paludis/set_file.cc
+++ b/paludis/set_file.cc
@@ -27,6 +27,7 @@
#include <paludis/util/mutex.hh>
#include <paludis/util/config_file.hh>
#include <paludis/util/system.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/environment.hh>
#include <paludis/package_database.hh>
#include <paludis/selection.hh>
@@ -35,7 +36,6 @@
#include <paludis/filtered_generator.hh>
#include <list>
#include <vector>
-#include <fstream>
#include <algorithm>
using namespace paludis;
@@ -401,13 +401,19 @@ SimpleHandler::rewrite() const
Context context("When rewriting simple set file '" + stringify(_p.file_name()) + "':");
- std::ofstream f(stringify(_p.file_name()).c_str());
- if (! f)
- throw SetFileError(_p.file_name(), "Cannot write to '" + stringify(_p.file_name()) + "'");
+ try
+ {
+ SafeOFStream f(_p.file_name());
- for (std::list<std::string>::const_iterator i(_lines.begin()), i_end(_lines.end()) ;
- i != i_end ; ++i)
- f << *i << std::endl;
+ for (std::list<std::string>::const_iterator i(_lines.begin()), i_end(_lines.end()) ;
+ i != i_end ; ++i)
+ f << *i << std::endl;
+ }
+ catch (const SafeOFStreamError & e)
+ {
+ throw SetFileError(_p.file_name(), "Cannot write to '" + stringify(_p.file_name()) + "': '" + e.message() + "' ("
+ + e.what() + ")");
+ }
}
PaludisConfHandler::PaludisConfHandler(const SetFileParams & p) :
@@ -473,13 +479,19 @@ PaludisConfHandler::rewrite() const
Lock l(_mutex);
- std::ofstream f(stringify(_p.file_name()).c_str());
- if (! f)
- throw SetFileError(_p.file_name(), "Cannot write to '" + stringify(_p.file_name()) + "'");
+ try
+ {
+ SafeOFStream f(_p.file_name());
- for (std::list<std::string>::const_iterator i(_lines.begin()), i_end(_lines.end()) ;
- i != i_end ; ++i)
- f << *i << std::endl;
+ for (std::list<std::string>::const_iterator i(_lines.begin()), i_end(_lines.end()) ;
+ i != i_end ; ++i)
+ f << *i << std::endl;
+ }
+ catch (const SafeOFStreamError & e)
+ {
+ throw SetFileError(_p.file_name(), "Cannot write to '" + stringify(_p.file_name()) + "': '" + e.message() + "' ("
+ + e.what() + ")");
+ }
}
PaludisBashHandler::PaludisBashHandler(const SetFileParams & p) :
diff --git a/paludis/set_file_TEST.cc b/paludis/set_file_TEST.cc
index eeea8d9..dbc703f 100644
--- a/paludis/set_file_TEST.cc
+++ b/paludis/set_file_TEST.cc
@@ -25,7 +25,7 @@
#include <paludis/dep_spec.hh>
#include <paludis/user_dep_spec.hh>
#include <paludis/environments/test/test_environment.hh>
-#include <fstream>
+#include <paludis/util/safe_ifstream.hh>
using namespace test;
using namespace paludis;
@@ -93,7 +93,7 @@ namespace test_cases
f.rewrite();
{
- std::ifstream ff("set_file_TEST_dir/simple1");
+ SafeIFStream ff(FSEntry("set_file_TEST_dir/simple1"));
TEST_CHECK(ff);
std::string g((std::istreambuf_iterator<char>(ff)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(g, "# this is a comment\n\nfoo/bar\n>=bar/baz-1.23\n\n# the end\nmoo/oink\n");
@@ -111,7 +111,7 @@ namespace test_cases
f.rewrite();
{
- std::ifstream ff("set_file_TEST_dir/simple1");
+ SafeIFStream ff(FSEntry("set_file_TEST_dir/simple1"));
TEST_CHECK(ff);
std::string g((std::istreambuf_iterator<char>(ff)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(g, "# this is a comment\n\nfoo/bar\n\n# the end\nmoo/oink\n");
@@ -162,7 +162,7 @@ namespace test_cases
f.rewrite();
{
- std::ifstream ff("set_file_TEST_dir/paludisconf1");
+ SafeIFStream ff(FSEntry("set_file_TEST_dir/paludisconf1"));
TEST_CHECK(ff);
std::string g((std::istreambuf_iterator<char>(ff)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(g, "# this is a comment\n\n? foo/bar\n* >=bar/baz-1.23\n\n* set\n? settee\n\n# the end\n* moo/oink\n* couch\n");
@@ -181,7 +181,7 @@ namespace test_cases
f.rewrite();
{
- std::ifstream ff("set_file_TEST_dir/paludisconf1");
+ SafeIFStream ff(FSEntry("set_file_TEST_dir/paludisconf1"));
TEST_CHECK(ff);
std::string g((std::istreambuf_iterator<char>(ff)), std::istreambuf_iterator<char>());
TEST_CHECK_EQUAL(g, "# this is a comment\n\n? foo/bar\n\n? settee\n\n# the end\n* moo/oink\n* couch\n");
diff --git a/paludis/sohooks_TEST.cc b/paludis/sohooks_TEST.cc
index 727698f..e8f981f 100644
--- a/paludis/sohooks_TEST.cc
+++ b/paludis/sohooks_TEST.cc
@@ -23,7 +23,11 @@
#include <paludis/util/graph-impl.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/make_named_values.hh>
-#include <fstream>
+#include <paludis/util/safe_ofstream.hh>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
using namespace paludis;
@@ -44,7 +48,7 @@ namespace
HookResult
ordering_run(const Environment *, const Hook &)
{
- std::ofstream f("hooker_TEST_dir/ordering.out", std::ios_base::app);
+ SafeOFStream f(FSEntry("hooker_TEST_dir/ordering.out"), O_CREAT | O_WRONLY | O_APPEND);
f << "sohook" << std::endl;
return make_named_values<HookResult>(value_for<n::max_exit_status>(0), value_for<n::output>(""));
}
diff --git a/paludis/util/config_file.cc b/paludis/util/config_file.cc
index 194ce2f..5604782 100644
--- a/paludis/util/config_file.cc
+++ b/paludis/util/config_file.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008, 2009 Ciaran McCreesh
* Copyright (c) 2006 Danny van Dyk
*
* This file is part of the Paludis package manager. Paludis is free software;
@@ -27,8 +27,8 @@
#include <paludis/util/options.hh>
#include <paludis/util/simple_parser.hh>
#include <paludis/util/log.hh>
+#include <paludis/util/safe_ifstream.hh>
-#include <fstream>
#include <istream>
#include <list>
#include <map>
@@ -61,12 +61,17 @@ namespace paludis
Implementation(const FSEntry & f) :
filename(stringify(f))
{
- std::ifstream ff(stringify(f).c_str());
- if (! ff)
- throw ConfigFileError(filename, "Could not read file");
- std::tr1::shared_ptr<std::string> t(new std::string);
- std::copy((std::istreambuf_iterator<char>(ff)), std::istreambuf_iterator<char>(), std::back_inserter(*t));
- text = t;
+ try
+ {
+ SafeIFStream ff(f);
+ std::tr1::shared_ptr<std::string> t(new std::string);
+ std::copy((std::istreambuf_iterator<char>(ff)), std::istreambuf_iterator<char>(), std::back_inserter(*t));
+ text = t;
+ }
+ catch (const SafeIFStreamError & e)
+ {
+ throw ConfigFileError(filename, "Error reading file: '" + e.message() + "' (" + e.what() + ")");
+ }
}
Implementation(const std::string & s) :
diff --git a/paludis/util/files.m4 b/paludis/util/files.m4
index 6fce62c..44526f4 100644
--- a/paludis/util/files.m4
+++ b/paludis/util/files.m4
@@ -24,7 +24,6 @@ add(`deferred_construction_ptr', `hh', `cc', `fwd', `test')
add(`dir_iterator', `hh', `cc', `fwd', `se', `test', `testscript')
add(`exception', `hh', `cc')
add(`fast_unique_copy', `hh', `test')
-add(`fd_output_stream', `hh')
add(`forward_parallel_for_each', `hh', `test')
add(`fs_entry', `hh', `cc', `fwd', `test', `testscript')
add(`fd_holder', `hh')
@@ -55,6 +54,8 @@ add(`private_implementation_pattern', `hh', `impl')
add(`random', `hh', `cc', `test')
add(`remove_shared_ptr', `hh')
add(`rmd160', `hh', `cc', `test')
+add(`safe_ifstream', `hh', `cc', `test', `testscript')
+add(`safe_ofstream', `hh', `cc', `test', `testscript')
add(`save', `hh', `test')
add(`select', `hh')
add(`sequence', `hh', `fwd', `impl', `cc')
diff --git a/paludis/util/output_wrapper_TEST.cc b/paludis/util/output_wrapper_TEST.cc
index e9da796..b6ff3cf 100644
--- a/paludis/util/output_wrapper_TEST.cc
+++ b/paludis/util/output_wrapper_TEST.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2007 Ciaran McCreesh
+ * Copyright (c) 2007, 2009 Ciaran McCreesh
*
* 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
@@ -23,7 +23,6 @@
#include <paludis/util/system.hh>
#include <paludis/util/join.hh>
-#include <fstream>
#include <iterator>
#include <set>
diff --git a/paludis/util/safe_ifstream.cc b/paludis/util/safe_ifstream.cc
new file mode 100644
index 0000000..50d28b5
--- /dev/null
+++ b/paludis/util/safe_ifstream.cc
@@ -0,0 +1,136 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/util/safe_ifstream.hh>
+#include <paludis/util/stringify.hh>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <cstring>
+#include <errno.h>
+
+using namespace paludis;
+
+SafeIFStreamBuf::SafeIFStreamBuf(const int f) :
+ fd(f)
+{
+ setg(buffer + lookbehind_size, buffer + lookbehind_size, buffer + lookbehind_size);
+ underflow();
+}
+
+SafeIFStreamBuf::int_type
+SafeIFStreamBuf::underflow()
+{
+ if (gptr() < egptr())
+ return traits_type::to_int_type(*gptr());
+
+ int n_putback = gptr() - eback();
+ if (n_putback > lookbehind_size)
+ n_putback = lookbehind_size;
+
+ std::memmove(buffer + (lookbehind_size - n_putback), gptr() - n_putback, n_putback);
+
+ int n_read(read(fd, buffer + lookbehind_size, buffer_size - lookbehind_size));
+ if (-1 == n_read)
+ throw SafeIFStreamError("Error reading from fd " + stringify(fd) + ": " + strerror(errno));
+ else if (0 == n_read)
+ return traits_type::eof();
+
+ setg(buffer + (lookbehind_size - n_putback), buffer + lookbehind_size, buffer + lookbehind_size + n_read);
+ return traits_type::to_int_type(*gptr());
+}
+
+SafeIFStreamBuf::pos_type
+SafeIFStreamBuf::seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode)
+{
+ off_t result;
+ if (dir == std::ios_base::beg)
+ result = lseek(fd, off, SEEK_SET);
+ else if (dir == std::ios_base::cur)
+ result = lseek(fd, off, SEEK_CUR);
+ else if (dir == std::ios_base::end)
+ result = lseek(fd, off, SEEK_END);
+ else
+ throw SafeIFStreamError("Got bad std::ios_base::seekdir");
+
+ if (-1 == result)
+ throw SafeIFStreamError("Error seeking to offset with fd " + stringify(fd) + ": " + strerror(errno));
+
+ setg(buffer + lookbehind_size, buffer + lookbehind_size, buffer + lookbehind_size);
+ return result;
+}
+
+SafeIFStreamBuf::pos_type
+SafeIFStreamBuf::seekpos(pos_type p, std::ios_base::openmode)
+{
+ off_t result(lseek(fd, p, SEEK_SET));
+ if (-1 == result)
+ throw SafeIFStreamError("Error seeking with fd " + stringify(fd) + ": " + strerror(errno));
+
+ setg(buffer + lookbehind_size, buffer + lookbehind_size, buffer + lookbehind_size);
+ return p;
+}
+
+SafeIFStreamBase::SafeIFStreamBase(const int f) :
+ buf(f)
+{
+}
+
+namespace
+{
+ int open_fsentry(const FSEntry & e)
+ {
+ Context context("When opening '" + stringify(e) + "' for read:");
+
+ int result(open(stringify(e).c_str(), O_RDONLY));
+ if (-1 == result)
+ throw SafeIFStreamError("Could not open '" + stringify(e) + "': " + strerror(errno));
+
+ return result;
+ }
+}
+
+SafeIFStream::SafeIFStream(const int f) :
+ SafeIFStreamBase(f),
+ std::istream(&buf),
+ _close(false)
+{
+}
+
+SafeIFStream::SafeIFStream(const FSEntry & e) :
+ SafeIFStreamBase(open_fsentry(e)),
+ std::istream(&buf),
+ _close(true)
+{
+}
+
+SafeIFStream::~SafeIFStream()
+{
+ if (_close)
+ ::close(buf.fd);
+}
+
+SafeIFStreamError::SafeIFStreamError(const std::string & s) throw () :
+ Exception(s)
+{
+}
+
+
diff --git a/paludis/util/safe_ifstream.hh b/paludis/util/safe_ifstream.hh
new file mode 100644
index 0000000..37803e6
--- /dev/null
+++ b/paludis/util/safe_ifstream.hh
@@ -0,0 +1,134 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_PALUDIS_UTIL_SAFE_IFSTREAM_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_SAFE_IFSTREAM_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/fs_entry-fwd.hh>
+#include <istream>
+
+/** \file
+ * Declarations for SafeIFStream.
+ *
+ * \ingroup g_fs
+ *
+ * \section Examples
+ *
+ * - None at this time.
+ */
+
+namespace paludis
+{
+ /**
+ * Input stream buffer class that can be opened via an FD, and that doesn't
+ * do retarded things when given a non-file.
+ *
+ * See \ref TCppSL Ch. 13.13 for what we're doing here. The buffer code is
+ * based upon the "io/inbuf1.hpp" example in section 13.13.3.
+ *
+ * \ingroup g_fs
+ * \since 0.34.3
+ */
+ class PALUDIS_VISIBLE SafeIFStreamBuf :
+ public std::streambuf
+ {
+ protected:
+ static const int lookbehind_size = 16;
+ static const int buffer_size = 512 + lookbehind_size;
+ char buffer[buffer_size];
+
+ virtual int_type underflow();
+ virtual pos_type seekoff(off_type, std::ios_base::seekdir, std::ios_base::openmode);
+ virtual pos_type seekpos(pos_type, std::ios_base::openmode);
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ SafeIFStreamBuf(const int f);
+
+ ///\}
+
+ /// Our file descriptor.
+ int fd;
+ };
+
+ /**
+ * Member from base initialisation for SafeIFStream.
+ *
+ * \ingroup g_fs
+ * \since 0.34.3
+ */
+ class PALUDIS_VISIBLE SafeIFStreamBase
+ {
+ protected:
+ /// Our buffer.
+ SafeIFStreamBuf buf;
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ SafeIFStreamBase(const int fd);
+
+ ///\}
+ };
+
+ /**
+ * Input stream buffer class that can be opened via an FD, and that doesn't
+ * do retarded things when given a non-file.
+ *
+ * \ingroup g_fs
+ * \since 0.34.3
+ */
+ class PALUDIS_VISIBLE SafeIFStream :
+ protected SafeIFStreamBase,
+ public std::istream
+ {
+ private:
+ const bool _close;
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ SafeIFStream(const int fd);
+ SafeIFStream(const FSEntry &);
+ ~SafeIFStream();
+
+ ///\}
+ };
+
+ /**
+ * Thrown by SafeIFStream if an error occurs.
+ *
+ * \ingroup g_fs
+ * \since 0.34.3
+ */
+ class PALUDIS_VISIBLE SafeIFStreamError :
+ public Exception
+ {
+ public:
+ SafeIFStreamError(const std::string &) throw ();
+ };
+}
+
+#endif
diff --git a/paludis/util/safe_ifstream_TEST.cc b/paludis/util/safe_ifstream_TEST.cc
new file mode 100644
index 0000000..ab3ed17
--- /dev/null
+++ b/paludis/util/safe_ifstream_TEST.cc
@@ -0,0 +1,104 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/util/safe_ifstream.hh>
+#include <paludis/util/fs_entry.hh>
+#include <test/test_runner.hh>
+#include <test/test_framework.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace test_cases
+{
+ struct ExistingTest : TestCase
+ {
+ ExistingTest() : TestCase("existing file") { }
+
+ void run()
+ {
+ SafeIFStream s(FSEntry::cwd() / "safe_ifstream_TEST_dir" / "existing");
+ TEST_CHECK(s);
+ std::string t;
+ s >> t;
+ TEST_CHECK(s);
+ TEST_CHECK_EQUAL(t, "first");
+ s >> t;
+ TEST_CHECK_EQUAL(t, std::string(1000, 'x'));
+
+ s.clear();
+ s.seekg(0, std::ios::beg);
+
+ TEST_CHECK(s);
+ s >> t;
+ TEST_CHECK(s);
+ TEST_CHECK_EQUAL(t, "first");
+ s >> t;
+ TEST_CHECK_EQUAL(t, std::string(1000, 'x'));
+ }
+ } test_existing;
+
+ struct ExistingSymTest : TestCase
+ {
+ ExistingSymTest() : TestCase("existing sym") { }
+
+ void run()
+ {
+ SafeIFStream s(FSEntry::cwd() / "safe_ifstream_TEST_dir" / "existing");
+ TEST_CHECK(s);
+ std::string t;
+ s >> t;
+ TEST_CHECK(s);
+ TEST_CHECK_EQUAL(t, "first");
+ s >> t;
+ TEST_CHECK_EQUAL(t, std::string(1000, 'x'));
+ }
+ } test_existing_sym;
+
+ struct ExistingDirTest : TestCase
+ {
+ ExistingDirTest() : TestCase("existing dir") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(SafeIFStream(FSEntry::cwd() / "safe_ifstream_TEST_dir" / "existing_dir"), SafeIFStreamError);
+ }
+ } test_existing_dir;
+
+ struct ExistingPermTest : TestCase
+ {
+ ExistingPermTest() : TestCase("existing unreadable file") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(SafeIFStream(FSEntry::cwd() / "safe_ifstream_TEST_dir" / "existing_perm"), SafeIFStreamError);
+ }
+ } test_existing_perm;
+
+ struct ExistingNoentTest : TestCase
+ {
+ ExistingNoentTest() : TestCase("no such file") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(SafeIFStream(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "noent"), SafeIFStreamError);
+ }
+ } test_existing_noent;
+}
+
diff --git a/paludis/util/safe_ifstream_TEST_cleanup.sh b/paludis/util/safe_ifstream_TEST_cleanup.sh
new file mode 100755
index 0000000..62053f3
--- /dev/null
+++ b/paludis/util/safe_ifstream_TEST_cleanup.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d safe_ifstream_TEST_dir ] ; then
+ rm -fr safe_ifstream_TEST_dir
+else
+ true
+fi
+
diff --git a/paludis/util/safe_ifstream_TEST_setup.sh b/paludis/util/safe_ifstream_TEST_setup.sh
new file mode 100755
index 0000000..3f37157
--- /dev/null
+++ b/paludis/util/safe_ifstream_TEST_setup.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir safe_ifstream_TEST_dir || exit 2
+cd safe_ifstream_TEST_dir || exit 3
+
+echo first > existing
+for (( a = 0 ; a < 1000 ; ++a )) ; do
+ echo -n x >> existing
+done
+echo >> existing
+
+mkdir existing_dir
+ln -s existing_sym_target existing
+touch existing_perm
+chmod a-rw existing_perm
+
diff --git a/paludis/util/safe_ofstream.cc b/paludis/util/safe_ofstream.cc
new file mode 100644
index 0000000..a715924
--- /dev/null
+++ b/paludis/util/safe_ofstream.cc
@@ -0,0 +1,103 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/util/safe_ofstream.hh>
+#include <paludis/util/stringify.hh>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+using namespace paludis;
+
+SafeOFStreamBuf::SafeOFStreamBuf(const int f) :
+ fd(f)
+{
+}
+
+SafeOFStreamBuf::int_type
+SafeOFStreamBuf::overflow(int_type c)
+{
+ if (c != traits_type::eof())
+ {
+ char z = c;
+ if (1 != write(fd, &z, 1))
+ return traits_type::eof();
+ }
+ return c;
+}
+
+std::streamsize
+SafeOFStreamBuf::xsputn(const char * s, std::streamsize num)
+{
+ return write(fd, s, num);
+}
+
+SafeOFStreamBase::SafeOFStreamBase(const int f) :
+ buf(f)
+{
+}
+
+namespace
+{
+ int check_open_fsentry(const FSEntry & e, int open_flags)
+ {
+ Context context("When opening '" + stringify(e) + "' for write:");
+
+ if (-1 == open_flags)
+ open_flags = O_CREAT | O_TRUNC | O_WRONLY;
+
+ int result(open(stringify(e).c_str(), open_flags, 0644));
+ if (-1 == result)
+ throw SafeOFStreamError("Could not open '" + stringify(e) + "': " + strerror(errno));
+
+ return result;
+ }
+}
+
+SafeOFStream::SafeOFStream(const int f) :
+ SafeOFStreamBase(f),
+ std::ostream(&buf),
+ _close(false)
+{
+}
+
+SafeOFStream::SafeOFStream(const FSEntry & e, const int open_flags) :
+ SafeOFStreamBase(check_open_fsentry(e, open_flags)),
+ std::ostream(&buf),
+ _close(true)
+{
+}
+
+SafeOFStream::~SafeOFStream()
+{
+ if (_close)
+ ::close(buf.fd);
+
+ if (! *this)
+ throw SafeOFStreamError("Write to fd " + stringify(buf.fd) + " failed");
+}
+
+SafeOFStreamError::SafeOFStreamError(const std::string & s) throw () :
+ Exception(s)
+{
+}
+
diff --git a/paludis/util/fd_output_stream.hh b/paludis/util/safe_ofstream.hh
index ab818c4..14f7f57 100644
--- a/paludis/util/fd_output_stream.hh
+++ b/paludis/util/safe_ofstream.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -17,15 +17,16 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef PALUDIS_GUARD_PALUDIS_UTIL_FD_OUTPUT_STREAM_HH
-#define PALUDIS_GUARD_PALUDIS_UTIL_FD_OUTPUT_STREAM_HH 1
+#ifndef PALUDIS_GUARD_PALUDIS_UTIL_SAFE_OFSTREAM_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_SAFE_OFSTREAM_HH 1
+#include <paludis/util/attributes.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/fs_entry-fwd.hh>
#include <ostream>
-#include <unistd.h>
-#include <cstdio>
/** \file
- * Declarations for FDOutputStreamBuf.
+ * Declarations for SafeOFStream.
*
* \ingroup g_fs
*
@@ -37,95 +38,95 @@
namespace paludis
{
/**
- * Output stream buffer class that's opened via an FD.
+ * Output stream buffer class that can be opened via an FD, and that doesn't
+ * do retarded things when given a non-file.
*
* See \ref TCppSL Ch. 13.13 for what we're doing here. The buffer code is
* based upon the "io/outbuf2.hpp" example in section 13.13.3.
*
* \ingroup g_fs
- * \nosubgrouping
+ * \since 0.34.3
*/
- class PALUDIS_VISIBLE FDOutputStreamBuf :
+ class PALUDIS_VISIBLE SafeOFStreamBuf :
public std::streambuf
{
protected:
- /// Our file descriptor.
- int fd;
-
virtual int_type
- overflow(int_type c)
- {
- if (c != traits_type::eof())
- {
- char z = c;
- if (1 != write(fd, &z, 1))
- return traits_type::eof();
- }
- return c;
- }
+ overflow(int_type c);
virtual std::streamsize
- xsputn(const char * s, std::streamsize num)
- {
- return write(fd, s, num);
- }
+ xsputn(const char * s, std::streamsize num);
public:
///\name Basic operations
///\{
- FDOutputStreamBuf(const int f) :
- fd(f)
- {
- }
+ SafeOFStreamBuf(const int f);
///\}
+
+ /// Our file descriptor.
+ int fd;
};
/**
- * Member from base initialisation for FDOutputStream.
+ * Member from base initialisation for SafeOFStream.
*
* \ingroup g_fs
+ * \since 0.34.3
*/
- class PALUDIS_VISIBLE FDOutputStreamBase
+ class PALUDIS_VISIBLE SafeOFStreamBase
{
protected:
/// Our buffer.
- FDOutputStreamBuf buf;
+ SafeOFStreamBuf buf;
public:
///\name Basic operations
///\{
- FDOutputStreamBase(const int fd) :
- buf(fd)
- {
- }
+ SafeOFStreamBase(const int fd);
///\}
};
/**
- * Output stream buffer class that's opened via an FD.
+ * Output stream buffer class that can be opened via an FD, and that doesn't
+ * do retarded things when given a non-file.
*
* \ingroup g_fs
+ * \since 0.34.3
*/
- class PALUDIS_VISIBLE FDOutputStream :
- protected FDOutputStreamBase,
+ class PALUDIS_VISIBLE SafeOFStream :
+ protected SafeOFStreamBase,
public std::ostream
{
+ private:
+ const bool _close;
+
public:
///\name Basic operations
///\{
- FDOutputStream(const int fd) :
- FDOutputStreamBase(fd),
- std::ostream(&buf)
- {
- }
+ SafeOFStream(const int fd);
+ SafeOFStream(const FSEntry &, const int open_flags = -1);
+ ~SafeOFStream();
///\}
};
+
+ /**
+ * Thrown by SafeOFStream if an error occurs.
+ *
+ * \ingroup g_fs
+ * \since 0.34.3
+ */
+ class PALUDIS_VISIBLE SafeOFStreamError :
+ public Exception
+ {
+ public:
+ SafeOFStreamError(const std::string &) throw ();
+ };
}
#endif
diff --git a/paludis/util/safe_ofstream_TEST.cc b/paludis/util/safe_ofstream_TEST.cc
new file mode 100644
index 0000000..720d823
--- /dev/null
+++ b/paludis/util/safe_ofstream_TEST.cc
@@ -0,0 +1,142 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2009 Ciaran McCreesh
+ *
+ * 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
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/util/safe_ofstream.hh>
+#include <paludis/util/fs_entry.hh>
+#include <test/test_runner.hh>
+#include <test/test_framework.hh>
+
+using namespace test;
+using namespace paludis;
+
+namespace test_cases
+{
+ struct NewTest : TestCase
+ {
+ NewTest() : TestCase("new file") { }
+
+ void run()
+ {
+ SafeOFStream s(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "new");
+ TEST_CHECK(s);
+ s << "foo";
+ TEST_CHECK(s);
+ }
+
+ bool repeatable() const
+ {
+ return false;
+ }
+ } test_new;
+
+ struct ExistingTest : TestCase
+ {
+ ExistingTest() : TestCase("existing file") { }
+
+ void run()
+ {
+ SafeOFStream s(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "existing");
+ TEST_CHECK(s);
+ s << "foo";
+ TEST_CHECK(s);
+ }
+
+ bool repeatable() const
+ {
+ return false;
+ }
+ } test_existing;
+
+ struct ExistingSymTest : TestCase
+ {
+ ExistingSymTest() : TestCase("existing sym") { }
+
+ void run()
+ {
+ SafeOFStream s(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "existing_sym");
+ TEST_CHECK(s);
+ s << "foo";
+ TEST_CHECK(s);
+ }
+
+ bool repeatable() const
+ {
+ return false;
+ }
+ } test_existing_sym;
+
+ struct ExistingDirTest : TestCase
+ {
+ ExistingDirTest() : TestCase("existing dir") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(SafeOFStream(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "existing_dir"), SafeOFStreamError);
+ }
+
+ bool repeatable() const
+ {
+ return false;
+ }
+ } test_existing_dir;
+
+ struct ExistingPermTest : TestCase
+ {
+ ExistingPermTest() : TestCase("existing unwriteable file") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(SafeOFStream(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "existing_perm"), SafeOFStreamError);
+ }
+
+ bool repeatable() const
+ {
+ return false;
+ }
+ } test_existing_perm;
+
+ struct WriteFailTest : TestCase
+ {
+ WriteFailTest() : TestCase("write fail") { }
+
+ void run()
+ {
+ bool threw(false);
+ try
+ {
+ SafeOFStream s(FSEntry("/dev/full"));
+ TEST_CHECK(s);
+ s << "foo";
+ TEST_CHECK(! s);
+ }
+ catch (const SafeOFStreamError &)
+ {
+ threw = true;
+ }
+
+ TEST_CHECK(threw);
+ }
+
+ bool repeatable() const
+ {
+ return false;
+ }
+ } test_existing_write_fail;
+}
+
diff --git a/paludis/util/safe_ofstream_TEST_cleanup.sh b/paludis/util/safe_ofstream_TEST_cleanup.sh
new file mode 100755
index 0000000..54d11d9
--- /dev/null
+++ b/paludis/util/safe_ofstream_TEST_cleanup.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d safe_ofstream_TEST_dir ] ; then
+ rm -fr safe_ofstream_TEST_dir
+else
+ true
+fi
+
diff --git a/paludis/util/safe_ofstream_TEST_setup.sh b/paludis/util/safe_ofstream_TEST_setup.sh
new file mode 100755
index 0000000..64a4c72
--- /dev/null
+++ b/paludis/util/safe_ofstream_TEST_setup.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir safe_ofstream_TEST_dir || exit 2
+cd safe_ofstream_TEST_dir || exit 3
+
+touch existing
+mkdir existing_dir
+touch existing_sym_target
+ln -s existing_sym_target existing_sym
+touch existing_perm
+chmod a-rw existing_perm
+
diff --git a/paludis/util/system.cc b/paludis/util/system.cc
index e8eb10f..bbd14cb 100644
--- a/paludis/util/system.cc
+++ b/paludis/util/system.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007, 2008 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2008, 2009 Ciaran McCreesh
*
* 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
@@ -27,7 +27,7 @@
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/util/destringify.hh>
#include <paludis/util/strip.hh>
-#include <paludis/util/fd_output_stream.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/util/pipe.hh>
#include <sys/utsname.h>
@@ -575,7 +575,7 @@ paludis::run_command(const Command & cmd)
}
{
- FDOutputStream stream(internal_command_reader->write_fd());
+ SafeOFStream stream(internal_command_reader->write_fd());
stream << "EXIT " << ret << std::endl;
}
}
diff --git a/src/clients/accerso/accerso.cc b/src/clients/accerso/accerso.cc
index f1dfc4c..c4a3cfc 100644
--- a/src/clients/accerso/accerso.cc
+++ b/src/clients/accerso/accerso.cc
@@ -32,6 +32,7 @@
#include <paludis/util/make_named_values.hh>
#include <paludis/util/make_shared_ptr.hh>
#include <paludis/util/standard_output_manager.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/environments/no_config/no_config_environment.hh>
#include <paludis/selection.hh>
#include <paludis/generator.hh>
@@ -41,7 +42,6 @@
#include <cstdlib>
#include <tr1/functional>
#include <iostream>
-#include <fstream>
#include <map>
using namespace paludis;
@@ -203,16 +203,9 @@ main(int argc, char *argv[])
std::cout << std::endl;
- std::tr1::shared_ptr<std::ofstream> outf;
+ std::tr1::shared_ptr<SafeOFStream> outf;
if (CommandLine::get_instance()->a_report_file.specified())
- {
- outf.reset(new std::ofstream(CommandLine::get_instance()->a_report_file.argument().c_str()));
- if (! *outf)
- {
- std::cerr << "Cannot write to " << CommandLine::get_instance()->a_report_file.argument() << std::endl;
- return EXIT_FAILURE;
- }
- }
+ outf.reset(new SafeOFStream(FSEntry(CommandLine::get_instance()->a_report_file.argument())));
std::ostream & out(outf ? *outf : cout);
diff --git a/src/clients/adjutrix/downgrade_check.cc b/src/clients/adjutrix/downgrade_check.cc
index fca21f9..f2525d3 100644
--- a/src/clients/adjutrix/downgrade_check.cc
+++ b/src/clients/adjutrix/downgrade_check.cc
@@ -27,6 +27,8 @@
#include <paludis/util/make_shared_ptr.hh>
#include <paludis/util/named_value.hh>
#include <paludis/util/make_named_values.hh>
+#include <paludis/util/safe_ofstream.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <paludis/package_id.hh>
#include <paludis/user_dep_spec.hh>
#include <paludis/generator.hh>
@@ -34,7 +36,6 @@
#include <paludis/filtered_generator.hh>
#include <paludis/selection.hh>
#include <paludis/metadata_key.hh>
-#include <fstream>
#include <iostream>
#include <vector>
#include <map>
@@ -186,7 +187,7 @@ do_build_downgrade_check_list(NoConfigEnvironment & env)
(*env.main_repository()).e_interface()->set_profile(p);
std::string n(make_filename(p, i));
std::cerr << "Generating " << n << "..." << std::endl;
- std::ofstream f(stringify(output_dir / n).c_str());
+ SafeOFStream f(output_dir / n);
exit_status |= build_one_list(env, f);
}
}
@@ -223,8 +224,8 @@ do_downgrade_check(NoConfigEnvironment & env)
{
std::cerr << "Checking " << n << "..." << std::endl;
- std::ifstream f1(stringify(before_dir / n).c_str());
- std::ifstream f2(stringify(after_dir / n).c_str());
+ SafeIFStream f1(before_dir / n);
+ SafeIFStream f2(after_dir / n);
exit_status |= check_one_list(env, f1, f2, results, desc);
}
diff --git a/src/clients/appareo/appareo.cc b/src/clients/appareo/appareo.cc
index e4a820d..319b9f4 100644
--- a/src/clients/appareo/appareo.cc
+++ b/src/clients/appareo/appareo.cc
@@ -42,7 +42,6 @@
#include <paludis/package_database.hh>
#include <tr1/functional>
#include <iostream>
-#include <fstream>
#include <map>
using namespace paludis;
diff --git a/src/clients/instruo/instruo.cc b/src/clients/instruo/instruo.cc
index 4bfa4e4..6e8259d 100644
--- a/src/clients/instruo/instruo.cc
+++ b/src/clients/instruo/instruo.cc
@@ -39,12 +39,12 @@
#include <paludis/util/mutex.hh>
#include <paludis/util/thread_pool.hh>
#include <paludis/util/destringify.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/environments/no_config/no_config_environment.hh>
#include <paludis/package_database.hh>
#include <paludis/metadata_key.hh>
#include <tr1/functional>
#include <iostream>
-#include <fstream>
#include <map>
using namespace paludis;
@@ -352,16 +352,9 @@ main(int argc, char *argv[])
std::cout << std::endl;
- std::tr1::shared_ptr<std::ofstream> outf;
+ std::tr1::shared_ptr<SafeOFStream> outf;
if (CommandLine::get_instance()->a_report_file.specified())
- {
- outf.reset(new std::ofstream(CommandLine::get_instance()->a_report_file.argument().c_str()));
- if (! *outf)
- {
- std::cerr << "Cannot write to " << CommandLine::get_instance()->a_report_file.argument() << std::endl;
- return EXIT_FAILURE;
- }
- }
+ outf.reset(new SafeOFStream(FSEntry(CommandLine::get_instance()->a_report_file.argument())));
std::ostream & out(outf ? *outf : cout);
diff --git a/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc b/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc
index 1734713..b6d962f 100644
--- a/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc
+++ b/src/clients/reconcilio/broken_linkage_finder/elf_linkage_checker.cc
@@ -36,11 +36,11 @@
#include <paludis/util/member_iterator-impl.hh>
#include <paludis/util/simple_visitor_cast.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <algorithm>
#include <cerrno>
#include <cstring>
-#include <fstream>
#include <map>
#include <set>
#include <vector>
@@ -125,7 +125,7 @@ namespace paludis
std::vector<FSEntry> extra_lib_dirs;
- template <typename> bool check_elf(const FSEntry &, std::ifstream &);
+ template <typename> bool check_elf(const FSEntry &, std::istream &);
void handle_library(const FSEntry &, const ElfArchitecture &);
template <typename> bool check_extra_elf(const FSEntry &, std::istream &, std::set<ElfArchitecture> &);
@@ -155,16 +155,13 @@ ElfLinkageChecker::check_file(const FSEntry & file)
file.has_permission(fs_ug_owner, fs_perm_execute)))
return false;
- std::ifstream stream(stringify(file).c_str());
- if (! stream)
- throw FSError("Error opening file '" + stringify(file) + "': " + std::strerror(errno));
-
+ SafeIFStream stream(file);
return _imp->check_elf<Elf32Type>(file, stream) || _imp->check_elf<Elf64Type>(file, stream);
}
template <typename ElfType_>
bool
-Implementation<ElfLinkageChecker>::check_elf(const FSEntry & file, std::ifstream & stream)
+Implementation<ElfLinkageChecker>::check_elf(const FSEntry & file, std::istream & stream)
{
if (! ElfObject<ElfType_>::is_valid_elf(stream))
return false;
@@ -312,18 +309,21 @@ ElfLinkageChecker::need_breakage_added(
continue;
}
- std::ifstream stream(stringify(file).c_str());
- if (! stream)
+ try
+ {
+ SafeIFStream stream(file);
+
+ if (! (_imp->check_extra_elf<Elf32Type>(file, stream, missing_it->second) ||
+ _imp->check_extra_elf<Elf64Type>(file, stream, missing_it->second)))
+ Log::get_instance()->message("reconcilio.broken_linkage_finder.not_an_elf", ll_debug, lc_no_context)
+ << "'" << file << "' is not an ELF file";
+ }
+ catch (const SafeIFStreamError & e)
{
Log::get_instance()->message("reconcilio.broken_linkage_finder.failure", ll_warning, lc_no_context)
- << "Error opening '" << file << "': " << std::strerror(errno);
+ << "Error opening '" << file << "': '" << e.message() << "' (" << e.what() << ")";
continue;
}
-
- if (! (_imp->check_extra_elf<Elf32Type>(file, stream, missing_it->second) ||
- _imp->check_extra_elf<Elf64Type>(file, stream, missing_it->second)))
- Log::get_instance()->message("reconcilio.broken_linkage_finder.not_an_elf", ll_debug, lc_no_context)
- << "'" << file << "' is not an ELF file";
}
}
diff --git a/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.cc b/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.cc
index 307b721..7c218fd 100644
--- a/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.cc
+++ b/src/clients/reconcilio/broken_linkage_finder/libtool_linkage_checker.cc
@@ -29,11 +29,11 @@
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/tokeniser.hh>
+#include <paludis/util/safe_ifstream.hh>
#include <algorithm>
#include <cstring>
#include <cerrno>
-#include <fstream>
#include <functional>
#include <vector>
@@ -90,9 +90,7 @@ LibtoolLinkageChecker::check_file(const FSEntry & file)
Context ctx("When checking '" + stringify(file) + "' as a libtool library:");
- std::ifstream stream(stringify(file).c_str());
- if (! stream)
- throw FSError("Error opening file '" + stringify(file) + "': " + std::strerror(errno));
+ SafeIFStream stream(file);
KeyValueConfigFileOptions opts;
opts += kvcfo_disallow_space_around_equals;
diff --git a/src/output/console_install_task.cc b/src/output/console_install_task.cc
index 677d798..01e620d 100644
--- a/src/output/console_install_task.cc
+++ b/src/output/console_install_task.cc
@@ -29,7 +29,7 @@
#include <paludis/util/mutex.hh>
#include <paludis/util/join.hh>
#include <paludis/util/set-impl.hh>
-#include <paludis/util/fd_output_stream.hh>
+#include <paludis/util/safe_ofstream.hh>
#include <paludis/util/system.hh>
#include <paludis/util/iterator_funcs.hh>
#include <paludis/util/simple_visitor_cast.hh>
@@ -1834,7 +1834,7 @@ ConsoleInstallTask::show_resume_command(const std::string & resume_command_templ
if (-1 != fd)
{
::fchmod(fd, 0644);
- FDOutputStream resume_command_file(fd);
+ SafeOFStream resume_command_file(fd);
resume_command_file << resume_command << endl;
if (resume_command_file)