aboutsummaryrefslogtreecommitdiff
path: root/paludis/util
diff options
context:
space:
mode:
Diffstat (limited to 'paludis/util')
-rw-r--r--paludis/util/config_file.cc8
-rw-r--r--paludis/util/config_file.hh6
-rw-r--r--paludis/util/config_file_TEST.cc15
-rw-r--r--paludis/util/dir_iterator.hh136
-rw-r--r--paludis/util/dir_iterator.se21
-rw-r--r--paludis/util/dir_iterator_TEST.cc105
-rw-r--r--paludis/util/files.m48
-rw-r--r--paludis/util/fs_entry-fwd.hh87
-rw-r--r--paludis/util/fs_entry.cc748
-rw-r--r--paludis/util/fs_entry.hh404
-rw-r--r--paludis/util/fs_entry_TEST.cc442
-rw-r--r--paludis/util/fs_error.cc30
-rw-r--r--paludis/util/fs_error.hh48
-rw-r--r--paludis/util/fs_iterator-fwd.hh (renamed from paludis/util/dir_iterator-fwd.hh)28
-rw-r--r--paludis/util/fs_iterator.cc (renamed from paludis/util/dir_iterator.cc)108
-rw-r--r--paludis/util/fs_iterator.hh63
-rw-r--r--paludis/util/fs_iterator.se21
-rw-r--r--paludis/util/fs_iterator_TEST.cc93
-rwxr-xr-xpaludis/util/fs_iterator_TEST_cleanup.sh (renamed from paludis/util/dir_iterator_TEST_cleanup.sh)4
-rwxr-xr-xpaludis/util/fs_iterator_TEST_setup.sh (renamed from paludis/util/dir_iterator_TEST_setup.sh)4
-rw-r--r--paludis/util/fs_path-fwd.hh53
-rw-r--r--paludis/util/fs_path.cc439
-rw-r--r--paludis/util/fs_path.hh194
-rw-r--r--paludis/util/fs_path.se19
-rw-r--r--paludis/util/fs_path_TEST.cc152
-rwxr-xr-xpaludis/util/fs_path_TEST_cleanup.sh (renamed from paludis/util/fs_entry_TEST_cleanup.sh)4
-rwxr-xr-xpaludis/util/fs_path_TEST_setup.sh (renamed from paludis/util/fs_entry_TEST_setup.sh)4
-rw-r--r--paludis/util/fs_stat-fwd.hh28
-rw-r--r--paludis/util/fs_stat.cc197
-rw-r--r--paludis/util/fs_stat.hh106
-rw-r--r--paludis/util/fs_stat_TEST.cc299
-rwxr-xr-xpaludis/util/fs_stat_TEST_cleanup.sh9
-rwxr-xr-xpaludis/util/fs_stat_TEST_setup.sh23
-rw-r--r--paludis/util/hashes.cc5
-rw-r--r--paludis/util/hashes.hh6
-rw-r--r--paludis/util/is_file_with_extension.cc12
-rw-r--r--paludis/util/is_file_with_extension.hh16
-rw-r--r--paludis/util/is_file_with_extension_TEST.cc15
-rw-r--r--paludis/util/process.cc4
-rw-r--r--paludis/util/process.hh4
-rw-r--r--paludis/util/process_TEST.cc4
-rw-r--r--paludis/util/realpath.cc32
-rw-r--r--paludis/util/realpath.hh8
-rw-r--r--paludis/util/realpath_TEST.cc47
-rw-r--r--paludis/util/safe_ifstream.cc21
-rw-r--r--paludis/util/safe_ifstream.hh4
-rw-r--r--paludis/util/safe_ifstream_TEST.cc14
-rw-r--r--paludis/util/safe_ofstream.cc20
-rw-r--r--paludis/util/safe_ofstream.hh4
-rw-r--r--paludis/util/safe_ofstream_TEST.cc16
-rw-r--r--paludis/util/system_TEST.cc1
-rw-r--r--paludis/util/wildcard_expander.cc21
-rw-r--r--paludis/util/wildcard_expander.hh11
-rw-r--r--paludis/util/wildcard_expander_TEST.cc8
54 files changed, 2002 insertions, 2177 deletions
diff --git a/paludis/util/config_file.cc b/paludis/util/config_file.cc
index 38baf5b..94d4797 100644
--- a/paludis/util/config_file.cc
+++ b/paludis/util/config_file.cc
@@ -20,7 +20,7 @@
#include <paludis/util/config_file.hh>
#include <paludis/util/exception.hh>
-#include <paludis/util/fs_entry.hh>
+#include <paludis/util/fs_path.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
#include <paludis/util/pimp-impl.hh>
@@ -73,7 +73,7 @@ namespace paludis
std::string filename;
std::shared_ptr<const std::string> text;
- Imp(const FSEntry & f) :
+ Imp(const FSPath & f) :
filename(stringify(f))
{
try
@@ -109,7 +109,7 @@ namespace paludis
};
}
-ConfigFile::Source::Source(const FSEntry & f) :
+ConfigFile::Source::Source(const FSPath & f) :
Pimp<ConfigFile::Source>(f)
{
}
@@ -640,7 +640,7 @@ KeyValueConfigFile::KeyValueConfigFile(
}
Context local_context("When following 'source '" + filename + "' statement:");
- KeyValueConfigFile kv(FSEntry(filename), o,
+ KeyValueConfigFile kv(FSPath(filename), o,
std::bind(&default_from_kv, std::cref(*this), std::placeholders::_1, std::placeholders::_2), i);
for (KeyValueConfigFile::ConstIterator k(kv.begin()), k_end(kv.end()) ;
k != k_end ; ++k)
diff --git a/paludis/util/config_file.hh b/paludis/util/config_file.hh
index afa4b57..10ec112 100644
--- a/paludis/util/config_file.hh
+++ b/paludis/util/config_file.hh
@@ -26,7 +26,7 @@
#include <paludis/util/pimp.hh>
#include <paludis/util/options-fwd.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
-#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/util/fs_path-fwd.hh>
#include <iosfwd>
#include <string>
@@ -82,7 +82,7 @@ namespace paludis
* Base class for configuration files.
*
* Data is read in from a ConfigFile::Source instance, which can be created from
- * an FSEntry, a std::istream or a string.
+ * an FSPath, a std::istream or a string.
*
* \see KeyValueConfigFile
* \see LineConfigFile
@@ -107,7 +107,7 @@ namespace paludis
///\name Basic operations
///\{
- Source(const FSEntry &);
+ Source(const FSPath &);
Source(const std::string &);
Source(std::istream &);
diff --git a/paludis/util/config_file_TEST.cc b/paludis/util/config_file_TEST.cc
index 810ad2e..217aebe 100644
--- a/paludis/util/config_file_TEST.cc
+++ b/paludis/util/config_file_TEST.cc
@@ -18,7 +18,8 @@
*/
#include <paludis/util/config_file.hh>
-#include <paludis/util/fs_entry.hh>
+#include <paludis/util/fs_path.hh>
+#include <paludis/util/fs_stat.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/system.hh>
#include <paludis/util/map.hh>
@@ -138,21 +139,21 @@ namespace test_cases
void run()
{
- FSEntry ff("config_file_TEST_dir/config_file");
- TEST_CHECK(ff.is_regular_file());
+ FSPath ff("config_file_TEST_dir/config_file");
+ TEST_CHECK(ff.stat().is_regular_file());
LineConfigFile f(ff, { });
TEST_CHECK_EQUAL(std::distance(f.begin(), f.end()), 1);
TEST_CHECK_EQUAL(*f.begin(), "I am a fish.");
- FSEntry ff2("config_file_TEST_dir/not_a_config_file");
- TEST_CHECK(! ff2.exists());
+ FSPath ff2("config_file_TEST_dir/not_a_config_file");
+ TEST_CHECK(! ff2.stat().exists());
LineConfigFile * f2(0);
TEST_CHECK_THROWS(f2 = new LineConfigFile(ff2, { }), ConfigFileError);
if (0 != geteuid())
{
- FSEntry ff3("config_file_TEST_dir/unreadable_file");
- TEST_CHECK(ff3.is_regular_file());
+ FSPath ff3("config_file_TEST_dir/unreadable_file");
+ TEST_CHECK(ff3.stat().is_regular_file());
LineConfigFile * f3(0);
TEST_CHECK_THROWS(f3 = new LineConfigFile(ff3, { }), ConfigFileError);
}
diff --git a/paludis/util/dir_iterator.hh b/paludis/util/dir_iterator.hh
deleted file mode 100644
index 7b2a83f..0000000
--- a/paludis/util/dir_iterator.hh
+++ /dev/null
@@ -1,136 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010 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_DIR_ITERATOR_HH
-#define PALUDIS_GUARD_PALUDIS_DIR_ITERATOR_HH 1
-
-#include <paludis/util/dir_iterator-fwd.hh>
-#include <paludis/util/fs_entry.hh>
-#include <paludis/util/options.hh>
-#include <paludis/util/pimp.hh>
-#include <iterator>
-
-/** \file
- * Declarations for DirIterator.
- *
- * \ingroup g_fs
- *
- * \section Examples
- *
- * - None at this time.
- */
-
-namespace paludis
-{
- /**
- * Raised when a directory open fails.
- *
- * \ingroup g_fs
- * \ingroup g_exceptions
- * \nosubgrouping
- */
- class PALUDIS_VISIBLE DirOpenError :
- public FSError
- {
- public:
- ///\name Basic operations
- ///\{
-
- DirOpenError(const FSEntry & location, const int errno_value) throw ();
-
- ///\}
- };
-
- /**
- * An iterator that iterates over the contents of a directory.
- *
- * \ingroup g_fs
- * \nosubgrouping
- */
- class PALUDIS_VISIBLE DirIterator :
- private Pimp<DirIterator>
- {
- public:
- ///\name Standard library typedefs
- ///\{
-
- typedef FSEntry value_type;
- typedef const FSEntry & reference;
- typedef const FSEntry * pointer;
- typedef std::ptrdiff_t difference_type;
- typedef std::forward_iterator_tag iterator_category;
-
- ///\}
-
- ///\name Basic operations
- ///\{
-
- /**
- * Constructor, to an FSEntry which must be a directory, with an
- * option to not ignore dotfiles and an option to do inodesort.
- */
- explicit DirIterator(const FSEntry &, const DirIteratorOptions & = DirIteratorOptions());
-
- DirIterator(const DirIterator &);
-
- /**
- * Constructor, creates an end() iterator.
- */
- DirIterator();
-
- ~DirIterator();
-
- DirIterator & operator= (const DirIterator &);
-
- ///\}
-
- ///\name Dereference operators
- ///\{
-
- const FSEntry & operator* () const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- const FSEntry * operator-> () const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- ///\}
-
- ///\name Increment, decrement operators
- ///\{
-
- DirIterator & operator++ ();
- DirIterator operator++ (int);
-
- ///\}
-
- ///\name Comparison operators
- ///\{
-
- bool operator== (const DirIterator &) const
- PALUDIS_ATTRIBUTE((warn_unused_result));
- bool operator!= (const DirIterator &) const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- ///\}
- };
-
- extern template class Pimp<DirIterator>;
-}
-
-#endif
diff --git a/paludis/util/dir_iterator.se b/paludis/util/dir_iterator.se
deleted file mode 100644
index 2d0088a..0000000
--- a/paludis/util/dir_iterator.se
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/bin/env bash
-# vim: set sw=4 sts=4 et ft=sh :
-
-make_enum_DirIteratorOption()
-{
- prefix dio
-
- key dio_include_dotfiles "Skip files whose name start with a dot"
- key dio_inode_sort "Return items sorted by inode number"
- key dio_first_only "Return the first item only"
-
- doxygen_comment << "END"
- /**
- * Options for a DirIterator.
- *
- * \see DirIterator
- * \see DirIteratorOptions
- * \ingroup g_fs
- */
-END
-}
diff --git a/paludis/util/dir_iterator_TEST.cc b/paludis/util/dir_iterator_TEST.cc
deleted file mode 100644
index 7b87ee9..0000000
--- a/paludis/util/dir_iterator_TEST.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2006 Mark Loeser
- *
- * 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/dir_iterator.hh>
-#include <paludis/util/options.hh>
-#include <test/test_framework.hh>
-#include <test/test_runner.hh>
-
-using namespace paludis;
-using namespace test;
-
-/** \file
- * Test cases for dir_iterator.hh.
- *
- * \ingroup grptestcases
- */
-
-namespace test_cases
-{
- /**
- * \test Test DirIterator construction and manipulation.
- *
- * \ingroup grptestcases
- */
- struct DirIteratorManipulationTest : TestCase
- {
- DirIteratorManipulationTest() : TestCase("construction and manipulation") { }
-
- void run()
- {
- TEST_CHECK_THROWS(DirIterator(FSEntry("/i/dont/exist/")), DirOpenError);
-
- DirIterator iter(FSEntry("dir_iterator_TEST_dir"));
- DirIterator iter1(iter);
- TEST_CHECK(iter == iter1);
- TEST_CHECK(!(iter != iter1));
- }
- } test_dir_iterator_manipulation;
-
- /**
- * \test Test DirIterator iterating abilities
- *
- * \ingroup grptestcases
- */
- struct DirIteratorIterateTest : TestCase
- {
- DirIteratorIterateTest() : TestCase("iterate") {}
-
- void run()
- {
- DirIterator iter(FSEntry("dir_iterator_TEST_dir"));
- DirIterator iter1(FSEntry("dir_iterator_TEST_dir"));
- DirIterator iter2(FSEntry("dir_iterator_TEST_dir"), { dio_include_dotfiles });
- DirIterator iter3(FSEntry("dir_iterator_TEST_dir"), { dio_inode_sort });
-
- TEST_CHECK(iter != DirIterator());
- TEST_CHECK(DirIterator() != iter);
-
- TEST_CHECK_EQUAL(iter->basename(), "file1");
- TEST_CHECK(++iter != DirIterator());
- TEST_CHECK_EQUAL(iter->basename(), "file2");
- TEST_CHECK(++iter != DirIterator());
- TEST_CHECK_EQUAL(iter->basename(), "file4");
- TEST_CHECK(++iter == DirIterator());
- TEST_CHECK(DirIterator() == iter);
-
- while (iter1 != DirIterator())
- ++iter1;
- TEST_CHECK(iter1 == DirIterator());
- TEST_CHECK(iter == iter1);
-
- TEST_CHECK_EQUAL(iter2->basename(), ".file3");
- TEST_CHECK(++iter2 != DirIterator());
- TEST_CHECK_EQUAL(iter2->basename(), "file1");
- TEST_CHECK(++iter2 != DirIterator());
- TEST_CHECK_EQUAL(iter2->basename(), "file2");
- TEST_CHECK(++iter2 != DirIterator());
- TEST_CHECK_EQUAL(iter2->basename(), "file4");
- TEST_CHECK(++iter2 == DirIterator());
- TEST_CHECK(DirIterator() == iter2);
- TEST_CHECK(iter2 == DirIterator());
-
- TEST_CHECK(iter1 == iter2);
- TEST_CHECK(iter2 == iter1);
-
- TEST_CHECK_EQUAL(std::distance(iter3, DirIterator()), 3);
- }
- } test_dir_iterator_iterate;
-}
diff --git a/paludis/util/files.m4 b/paludis/util/files.m4
index e771734..e7aca68 100644
--- a/paludis/util/files.m4
+++ b/paludis/util/files.m4
@@ -24,7 +24,6 @@ add(`create_iterator', `hh', `fwd', `impl', `test')
add(`damerau_levenshtein', `hh', `cc', `test')
add(`destringify', `hh', `cc', `test')
add(`deferred_construction_ptr', `hh', `cc', `fwd', `test')
-add(`dir_iterator', `hh', `cc', `fwd', `se', `test', `testscript')
add(`discard_output_stream', `hh', `cc')
add(`elf', `hh', `cc')
add(`elf_dynamic_section', `hh', `cc')
@@ -37,9 +36,12 @@ add(`exception', `hh', `cc')
add(`executor', `hh', `cc', `fwd')
add(`extract_host_from_url', `hh', `cc', `fwd', `test')
add(`fast_unique_copy', `hh', `test')
-add(`forward_parallel_for_each', `hh', `test')
-add(`fs_entry', `hh', `cc', `fwd', `test', `testscript')
add(`fd_holder', `hh')
+add(`forward_parallel_for_each', `hh', `test')
+add(`fs_iterator', `hh', `cc', `fwd', `se', `test', `testscript')
+add(`fs_error', `hh', `cc')
+add(`fs_path', `hh', `cc', `fwd', `se', `test', `testscript')
+add(`fs_stat', `hh', `cc', `fwd', `test', `testscript')
add(`graph', `hh', `cc', `fwd', `impl', `test')
add(`hashes', `hh', `cc')
add(`iterator_funcs', `hh', `test')
diff --git a/paludis/util/fs_entry-fwd.hh b/paludis/util/fs_entry-fwd.hh
deleted file mode 100644
index 5f9da7f..0000000
--- a/paludis/util/fs_entry-fwd.hh
+++ /dev/null
@@ -1,87 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh
- * Copyright (c) 2006 Mark Loeser
- *
- * 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_FS_ENTRY_FWD_HH
-#define PALUDIS_GUARD_PALUDIS_UTIL_FS_ENTRY_FWD_HH 1
-
-#include <iosfwd>
-#include <paludis/util/attributes.hh>
-#include <paludis/util/set-fwd.hh>
-#include <paludis/util/sequence-fwd.hh>
-
-/** \file
- * Forward declarations for paludis/util/fs_entry.hh .
- *
- * \ingroup g_fs
- */
-
-namespace paludis
-{
- class FSError;
-
- /**
- * File permissions used by FSEntry.
- *
- * \ingroup g_fs
- */
- enum FSPermission
- {
- fs_perm_read, ///< read permission on file
- fs_perm_write, ///< write permission on file
- fs_perm_execute ///< execute permission on file
- };
-
- /**
- * User classes used by FSEntry.
- *
- * \ingroup g_fs
- */
- enum FSUserGroup
- {
- fs_ug_owner, ///< owner permission
- fs_ug_group, ///< group permission
- fs_ug_others ///< others permission
- };
-
- class FSEntry;
-
- /**
- * An FSEntry can be written to an ostream.
- *
- * \ingroup g_fs
- */
- std::ostream & operator<< (std::ostream & s, const FSEntry & f) PALUDIS_VISIBLE;
-
- /**
- * A sequence of FSEntry instances.
- *
- * \ingroup g_fs
- */
- typedef Sequence<FSEntry> FSEntrySequence;
-
- /**
- * A set of FSEntry instances.
- *
- * \ingroup g_fs
- */
- typedef Set<FSEntry> FSEntrySet;
-}
-
-#endif
diff --git a/paludis/util/fs_entry.cc b/paludis/util/fs_entry.cc
deleted file mode 100644
index ec9f8bc..0000000
--- a/paludis/util/fs_entry.cc
+++ /dev/null
@@ -1,748 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh
- * Copyright (c) 2006 Mark Loeser
- * Copyright (c) 2008 Fernando J. Pereda
- *
- * 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/exception.hh>
-#include <paludis/util/fs_entry.hh>
-#include <paludis/util/log.hh>
-#include <paludis/util/mutex.hh>
-#include <paludis/util/stringify.hh>
-#include <paludis/util/sequence.hh>
-#include <paludis/util/sequence-impl.hh>
-#include <paludis/util/set.hh>
-#include <paludis/util/set-impl.hh>
-#include <paludis/util/timestamp.hh>
-#include <paludis/util/wrapped_forward_iterator.hh>
-#include <paludis/util/wrapped_forward_iterator-impl.hh>
-#include <paludis/util/wrapped_output_iterator.hh>
-#include <paludis/util/wrapped_output_iterator-impl.hh>
-
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <utime.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <cstring>
-#include <cstdlib>
-#include <cstdio>
-
-#include "config.h"
-
-/** \file
- * Imp of paludis::FSEntry.
- *
- * \ingroup grpfilesystem
- */
-
-using namespace paludis;
-
-FSError::FSError(const std::string & our_message) throw () :
- Exception(our_message)
-{
-}
-
-namespace paludis
-{
- enum CheckedInfo
- {
- ifse_none,
- ifse_exists,
- ifse_type,
- ifse_full,
- ifse_max
- };
-
- template <>
- struct Imp<FSEntry>
- {
- std::string path;
-
- mutable Mutex mutex;
- mutable std::shared_ptr<struct ::stat> stat_info;
- mutable bool exists;
- mutable CheckedInfo checked;
-
- Imp(const std::string & p) :
- path(p),
- exists(false),
- checked(ifse_none)
- {
- }
-
- Imp(const std::string & p, unsigned char d_type) :
- path(p),
- exists(true),
- checked(ifse_exists)
- {
-#ifdef HAVE_DIRENT_DTYPE
- if (DT_UNKNOWN != d_type)
- {
- stat_info = std::make_shared<struct ::stat>();
- stat_info->st_mode = DTTOIF(d_type);
- checked = ifse_type;
- }
-#endif
- }
-
- };
-}
-
-FSEntry::FSEntry(const std::string & path) :
- Pimp<FSEntry>(path)
-{
- _normalise();
-}
-
-FSEntry::FSEntry(const FSEntry & other) :
- Pimp<FSEntry>(other._imp->path)
-{
- Lock l(other._imp->mutex);
- _imp->stat_info = other._imp->stat_info;
- _imp->exists = other._imp->exists;
- _imp->checked = other._imp->checked;
-}
-
-FSEntry::FSEntry(const std::string & path, unsigned char d_type) :
- Pimp<FSEntry>(path, d_type)
-{
- _normalise();
-}
-
-FSEntry::~FSEntry()
-{
-}
-
-const FSEntry &
-FSEntry::operator= (const FSEntry & other)
-{
- Lock l(other._imp->mutex);
- _imp->path = other._imp->path;
- _imp->stat_info = other._imp->stat_info;
- _imp->exists = other._imp->exists;
- _imp->checked = other._imp->checked;
-
- return *this;
-}
-
-const FSEntry &
-FSEntry::operator/= (const FSEntry & rhs)
-{
- if (rhs._imp->path == "/")
- return *this;
-
- if (_imp->path.empty() || '/' != _imp->path.at(_imp->path.length() - 1))
- _imp->path.append("/");
-
- if (! rhs._imp->path.empty())
- {
- if ('/' == rhs._imp->path.at(0))
- _imp->path.append(rhs._imp->path.substr(1));
- else
- _imp->path.append(rhs._imp->path);
- }
-
- _imp->checked = ifse_none;
- _imp->exists = false;
- _imp->stat_info.reset();
-
- return *this;
-}
-
-FSEntry
-FSEntry::operator/ (const std::string & rhs) const
-{
- return *this / FSEntry(rhs);
-}
-
-bool
-FSEntry::operator< (const FSEntry & other) const
-{
- return _imp->path < other._imp->path;
-}
-
-bool
-FSEntry::operator== (const FSEntry & other) const
-{
- return _imp->path == other._imp->path;
-}
-
-bool
-FSEntry::exists() const
-{
- if (_imp->checked < ifse_exists)
- _stat();
-
- return _imp->exists;
-}
-
-bool
-FSEntry::is_directory() const
-{
- if (_imp->checked < ifse_type)
- _stat();
-
- if (_imp->exists)
- return S_ISDIR((*_imp->stat_info).st_mode);
-
- return false;
-}
-
-bool
-FSEntry::is_directory_or_symlink_to_directory() const
-{
- if (_imp->checked < ifse_type)
- _stat();
-
- if (_imp->exists)
- return S_ISDIR((*_imp->stat_info).st_mode) ||
- (is_symbolic_link() && realpath_if_exists().is_directory());
-
- return false;
-}
-
-bool
-FSEntry::is_fifo() const
-{
- if (_imp->checked < ifse_type)
- _stat();
-
- if (_imp->exists)
- return S_ISFIFO((*_imp->stat_info).st_mode);
-
- return false;
-}
-
-bool
-FSEntry::is_device() const
-{
- if (_imp->checked < ifse_type)
- _stat();
-
- if (_imp->exists)
- return S_ISBLK((*_imp->stat_info).st_mode) || S_ISCHR((*_imp->stat_info).st_mode);
-
- return false;
-}
-
-bool
-FSEntry::is_regular_file() const
-{
- if (_imp->checked < ifse_type)
- _stat();
-
- if (_imp->exists)
- return S_ISREG((*_imp->stat_info).st_mode);
-
- return false;
-}
-
-bool
-FSEntry::is_regular_file_or_symlink_to_regular_file() const
-{
- if (_imp->checked < ifse_type)
- _stat();
-
- if (_imp->exists)
- return S_ISREG((*_imp->stat_info).st_mode) ||
- (is_symbolic_link() && realpath_if_exists().is_regular_file());
-
- return false;
-}
-
-bool
-FSEntry::is_symbolic_link() const
-{
- if (_imp->checked < ifse_type)
- _stat();
-
- if (_imp->exists)
- return S_ISLNK((*_imp->stat_info).st_mode);
-
- return false;
-}
-
-
-bool
-FSEntry::has_permission(const FSUserGroup & user_group, const FSPermission & fs_perm) const
-{
- Context context("When checking permissions on '" + stringify(_imp->path) + "':");
-
- _stat();
-
- if (! _imp->exists)
- throw FSError("Filesystem entry '" + _imp->path + "' does not exist");
-
- switch (user_group)
- {
- case fs_ug_owner:
- {
- switch (fs_perm)
- {
- case fs_perm_read:
- return (*_imp->stat_info).st_mode & S_IRUSR;
- case fs_perm_write:
- return (*_imp->stat_info).st_mode & S_IWUSR;
- case fs_perm_execute:
- return (*_imp->stat_info).st_mode & S_IXUSR;
- }
- throw InternalError(PALUDIS_HERE, "Unhandled FSPermission");
- }
- case fs_ug_group:
- {
- switch (fs_perm)
- {
- case fs_perm_read:
- return (*_imp->stat_info).st_mode & S_IRGRP;
- case fs_perm_write:
- return (*_imp->stat_info).st_mode & S_IWGRP;
- case fs_perm_execute:
- return (*_imp->stat_info).st_mode & S_IXGRP;
- }
- throw InternalError(PALUDIS_HERE, "Unhandled FSPermission");
- }
- case fs_ug_others:
- {
- switch (fs_perm)
- {
- case fs_perm_read:
- return (*_imp->stat_info).st_mode & S_IROTH;
- case fs_perm_write:
- return (*_imp->stat_info).st_mode & S_IWOTH;
- case fs_perm_execute:
- return (*_imp->stat_info).st_mode & S_IXOTH;
- }
- throw InternalError(PALUDIS_HERE, "Unhandled FSPermission");
- }
- }
-
- throw InternalError(PALUDIS_HERE, "Unhandled FSUserGroup");
-}
-
-mode_t
-FSEntry::permissions() const
-{
- Context context("When fetching permissions for '" + stringify(_imp->path) + "':");
-
- _stat();
-
- if (! _imp->exists)
- throw FSError("Filesystem entry '" + _imp->path + "' does not exist");
-
- return _imp->stat_info->st_mode;
-}
-
-void
-FSEntry::_normalise()
-{
- try
- {
- if (std::string::npos != _imp->path.find("//"))
- {
- std::string new_path;
- std::string::size_type p(0);
- while (p < _imp->path.length())
- {
- if ('/' == _imp->path[p])
- {
- new_path += '/';
- while (++p < _imp->path.length())
- if ('/' != _imp->path[p])
- break;
- }
- else
- new_path += _imp->path[p++];
- }
- _imp->path = new_path;
- }
-
- if (! _imp->path.empty())
- if ('/' == _imp->path.at(_imp->path.length() - 1))
- _imp->path.erase(_imp->path.length() - 1);
- if (_imp->path.empty())
- _imp->path = "/";
- }
- catch (const std::exception & e)
- {
- Context c("When normalising FSEntry path '" + _imp->path + "':");
- throw InternalError(PALUDIS_HERE,
- "caught std::exception '" + stringify(e.what()) + "'");
- }
-}
-
-void
-FSEntry::_stat() const
-{
- Lock l(_imp->mutex);
- if (_imp->checked == ifse_full)
- return;
-
- Context context("When calling stat() on '" + stringify(_imp->path) + "':");
-
- _imp->stat_info = std::make_shared<struct stat>();
- if (0 != lstat(_imp->path.c_str(), _imp->stat_info.get()))
- {
- if (errno != ENOENT && errno != ENOTDIR)
- throw FSError("Error running stat() on '" + stringify(_imp->path) + "': "
- + strerror(errno));
-
- _imp->exists = false;
- _imp->stat_info.reset();
- }
- else
- _imp->exists = true;
-
- _imp->checked = ifse_full;
-}
-
-std::string
-FSEntry::basename() const
-{
- if (_imp->path == "/")
- return _imp->path;
-
- return _imp->path.substr(_imp->path.rfind('/') + 1);
-}
-
-FSEntry
-FSEntry::strip_leading(const FSEntry & f) const
-{
- std::string root(stringify(f));
-
- if (root == "/")
- root.clear();
- if (0 != _imp->path.compare(0, root.length(), root))
- throw FSError("Can't strip leading '" + root + "' from FSEntry '" + _imp->path + "'");
- return FSEntry(_imp->path.substr(root.length()));
-}
-
-FSEntry
-FSEntry::dirname() const
-{
- if (_imp->path == "/")
- return FSEntry(_imp->path);
-
- return FSEntry(_imp->path.substr(0, _imp->path.rfind('/')));
-}
-
-FSEntry
-FSEntry::realpath() const
-{
- Context context("When fetching realpath of '" + stringify(_imp->path) + "':");
-
-#ifdef HAVE_CANONICALIZE_FILE_NAME
- char * r(canonicalize_file_name(_imp->path.c_str()));
- if (! r)
- throw FSError("Could not resolve path '" + _imp->path + "'");
- FSEntry result(r);
- std::free(r);
- return result;
-#else
- char r[PATH_MAX + 1];
- std::memset(r, 0, PATH_MAX + 1);
- if (! exists())
- throw FSError("Could not resolve path '" + _imp->path + "'");
- if (! ::realpath(_imp->path.c_str(), r))
- throw FSError("Could not resolve path '" + _imp->path + "'");
- FSEntry result(r);
- if (! result.exists())
- throw FSError("Could not resolve path '" + _imp->path + "'");
- return result;
-#endif
-}
-
-FSEntry
-FSEntry::realpath_if_exists() const
-{
- Context context("When fetching realpath of '" + stringify(_imp->path) + "', if it exists:");
-
-#ifdef HAVE_CANONICALIZE_FILE_NAME
- char * r(canonicalize_file_name(_imp->path.c_str()));
- if (! r)
- return *this;
- FSEntry result(r);
- std::free(r);
- return result;
-#else
- char r[PATH_MAX + 1];
- std::memset(r, 0, PATH_MAX + 1);
- if (! exists())
- return *this;
- if (! ::realpath(_imp->path.c_str(), r))
- return *this;
- FSEntry result(r);
- if (! result.exists())
- return *this;
- return result;
-#endif
-}
-
-FSEntry
-FSEntry::cwd()
-{
- char r[PATH_MAX + 1];
- std::memset(r, 0, PATH_MAX + 1);
- if (! ::getcwd(r, PATH_MAX))
- throw FSError("Could not get current working directory");
- return FSEntry(r);
-}
-
-std::ostream &
-paludis::operator<< (std::ostream & s, const FSEntry & f)
-{
- s << f._imp->path;
- return s;
-}
-
-Timestamp
-FSEntry::ctim() const
-{
- _stat();
-
- if (! _imp->exists)
- {
- Context context("When fetching ctime of '" + stringify(_imp->path) + "':");
- throw FSError("Filesystem entry '" + _imp->path + "' does not exist");
- }
-
- return Timestamp((*_imp->stat_info).st_ctim);
-}
-
-Timestamp
-FSEntry::mtim() const
-{
- _stat();
-
- if (! _imp->exists)
- {
- Context context("When fetching mtime of '" + stringify(_imp->path) + "':");
- throw FSError("Filesystem entry '" + _imp->path + "' does not exist");
- }
-
- return Timestamp((*_imp->stat_info).st_mtim);
-}
-
-off_t
-FSEntry::file_size() const
-{
- _stat();
-
- if (! _imp->exists)
- throw FSError("Filesystem entry '" + _imp->path + "' does not exist");
-
- if (! is_regular_file())
- throw FSError("file_size called on non-regular file '" + _imp->path + "'");
-
- return _imp->stat_info->st_size;
-}
-
-bool
-FSEntry::mkdir(mode_t mode)
-{
- if (0 == ::mkdir(_imp->path.c_str(), mode))
- return true;
-
- int e(errno);
- if (e == EEXIST)
- {
- if (is_directory())
- return false;
- throw FSError("mkdir '" + _imp->path + "' failed: target exists and is not a directory");
- }
- else
- throw FSError("mkdir '" + _imp->path + "' failed: " + ::strerror(e));
-}
-
-bool
-FSEntry::symlink(const std::string & target)
-{
- if (0 == ::symlink(target.c_str(), _imp->path.c_str()))
- return true;
-
- int e(errno);
- if (e == EEXIST)
- {
- if (is_symbolic_link() && target == readlink())
- return false;
- throw FSError("symlink '" + _imp->path + "' to '" + target + "' failed: target exists");
- }
- else
- throw FSError("symlink '" + _imp->path + "' to '" + target + "' failed: " + ::strerror(e));
-}
-
-bool
-FSEntry::unlink()
-{
-#ifdef HAVE_LCHFLAGS
- if (0 != ::lchflags(_imp->path.c_str(), 0))
- {
- int e(errno);
- if (e != ENOENT)
- throw FSError("lchflags for unlink '" + _imp->path + "' failed: " + ::strerror(e));
- }
-#endif
-
- if (0 == ::unlink(_imp->path.c_str()))
- return true;
-
- int e(errno);
- if (e == ENOENT)
- return false;
- else
- throw FSError("unlink '" + _imp->path + "' failed: " + ::strerror(e));
-}
-
-bool
-FSEntry::rmdir()
-{
- if (0 == ::rmdir(_imp->path.c_str()))
- return true;
-
- int e(errno);
- if (e == ENOENT)
- return false;
- else
- throw FSError("rmdir '" + _imp->path + "' failed: " + ::strerror(e));
-}
-
-bool
-FSEntry::utime(const Timestamp & t)
-{
- Context context("When setting utime for '" + stringify(_imp->path) + "':");
-
-#ifdef HAVE_UTIMENSAT
- static bool utimensat_works(true);
-
- if (utimensat_works)
- {
- struct timespec ts[2] = { t.as_timespec(), t.as_timespec() };
- if (0 == ::utimensat(AT_FDCWD, _imp->path.c_str(), ts, 0))
- return true;
-
- int e(errno);
- if (e == ENOENT)
- return false;
- else if (e == ENOSYS)
- {
- utimensat_works = false;
- Log::get_instance()->message("util.fs_entry.utime.utimensat_unimplemented", ll_debug, lc_context)
- << "utimensat(2) not implemented by this kernel, using utimes(2)";
- }
- else
- throw FSError("utimensat '" + _imp->path + "' failed: " + ::strerror(e));
- }
-#endif
-
- struct timeval tv[2] = { t.as_timeval(), t.as_timeval() };
- if (0 == ::utimes(_imp->path.c_str(), tv))
- return true;
-
- int e(errno);
- if (e == ENOENT)
- return false;
- else
- throw FSError("utimes '" + _imp->path + "' failed: " + ::strerror(e));
-}
-
-std::string
-FSEntry::readlink() const
-{
- char buf[PATH_MAX + 1];
- std::memset(buf, 0, PATH_MAX + 1);
- if (-1 == ::readlink(_imp->path.c_str(), buf, PATH_MAX))
- throw FSError("readlink '" + _imp->path + "' failed: " + ::strerror(errno));
- return buf;
-}
-
-void
-FSEntry::chown(const uid_t new_owner, const gid_t new_group)
-{
- if (0 != ::chown(_imp->path.c_str(), new_owner, new_group))
- throw FSError("chown '" + _imp->path + "' to '" + stringify(new_owner) + "', '"
- + stringify(new_group) + "' failed: " + ::strerror(errno));
-}
-
-void
-FSEntry::lchown(const uid_t new_owner, const gid_t new_group)
-{
- if (0 != ::lchown(_imp->path.c_str(), new_owner, new_group))
- throw FSError("lchown '" + _imp->path + "' to '" + stringify(new_owner) + "', '"
- + stringify(new_group) + "' failed: " + ::strerror(errno));
-}
-
-void
-FSEntry::chmod(const mode_t mode)
-{
- if (0 != ::chmod(_imp->path.c_str(), mode))
- throw FSError("chmod '" + _imp->path + "' failed: " + ::strerror(errno));
-}
-
-uid_t
-FSEntry::owner() const
-{
- _stat();
-
- if (! _imp->exists)
- throw FSError("Filesystem entry '" + _imp->path + "' does not exist");
-
- return _imp->stat_info->st_uid;
-}
-
-gid_t
-FSEntry::group() const
-{
- _stat();
-
- if (! _imp->exists)
- throw FSError("Filesystem entry '" + _imp->path + "' does not exist");
-
- return _imp->stat_info->st_gid;
-}
-
-void
-FSEntry::rename(const FSEntry & new_name)
-{
- if (0 != std::rename(_imp->path.c_str(), new_name._imp->path.c_str()))
- throw FSError("rename('" + stringify(_imp->path) + "', '" + stringify(new_name._imp->path) + "') failed: " +
- ::strerror(errno));
-}
-
-std::pair<dev_t, ino_t>
-FSEntry::lowlevel_id() const
-{
- _stat();
-
- if (! _imp->exists)
- throw FSError("Filesystem entry '" + _imp->path + "' does not exist");
-
- return std::make_pair(_imp->stat_info->st_dev, _imp->stat_info->st_ino);
-}
-
-template class Sequence<FSEntry>;
-template class WrappedForwardIterator<Sequence<FSEntry>::ConstIteratorTag, const FSEntry>;
-template class WrappedForwardIterator<Sequence<FSEntry>::ReverseConstIteratorTag, const FSEntry>;
-template class WrappedOutputIterator<Sequence<FSEntry>::InserterTag, FSEntry>;
-
-template class Set<FSEntry>;
-template class WrappedForwardIterator<Set<FSEntry>::ConstIteratorTag, const FSEntry>;
-
diff --git a/paludis/util/fs_entry.hh b/paludis/util/fs_entry.hh
deleted file mode 100644
index 370868c..0000000
--- a/paludis/util/fs_entry.hh
+++ /dev/null
@@ -1,404 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh
- * Copyright (c) 2006 Mark Loeser
- *
- * 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_FS_ENTRY_HH
-#define PALUDIS_GUARD_PALUDIS_FS_ENTRY_HH 1
-
-#include <paludis/util/fs_entry-fwd.hh>
-#include <paludis/util/exception.hh>
-#include <paludis/util/operators.hh>
-#include <paludis/util/pimp.hh>
-#include <paludis/util/timestamp-fwd.hh>
-#include <string>
-#include <memory>
-#include <iosfwd>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <ctime>
-
-/** \file
- * Declarations for FSEntry.
- *
- * \ingroup g_fs
- *
- * \section Examples
- *
- * - None at this time.
- */
-
-struct stat;
-struct utimbuf;
-
-namespace paludis
-{
- /**
- * Generic filesystem error class.
- *
- * \ingroup g_exceptions
- * \ingroup g_fs
- * \nosubgrouping
- */
- class PALUDIS_VISIBLE FSError :
- public Exception
- {
- public:
- ///\name Basic operations
- ///\{
-
- FSError(const std::string & message) throw ();
-
- ///\}
- };
-
- /**
- * Represents an entry (which may or may not exist) in the filesystem.
- *
- * \ingroup g_fs
- */
- class PALUDIS_VISIBLE FSEntry :
- public relational_operators::HasRelationalOperators,
- public arithmetic_operators::HasArithmeticOperators,
- private Pimp<FSEntry>
- {
- friend std::ostream & operator<< (std::ostream & s, const FSEntry & f);
- friend class DirIterator;
-
- private:
- void _normalise();
-
- /**
- * Runs lstat() on the current path if we have not done so already.
- * Note: lstat() will give information on the symlink itself, and not what
- * the link points to, which is how stat() works.
- */
- void _stat() const;
-
- FSEntry(const std::string & path, unsigned char d_type);
-
- public:
- ///\name Basic operations
- ///\{
-
- FSEntry(const std::string & path);
-
- FSEntry(const FSEntry & other);
-
- ~FSEntry();
-
- const FSEntry & operator= (const FSEntry & other);
-
- ///\}
-
- ///\name Modification operations
- ///\{
-
- /**
- * Append another FSEntry.
- */
- const FSEntry & operator/= (const FSEntry & rhs);
-
- /**
- * Append another path.
- */
- const FSEntry & operator/= (const std::string & rhs)
- {
- return operator/= (FSEntry(rhs));
- }
-
- /**
- * Join with another path.
- */
- FSEntry operator/ (const std::string & rhs) const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- ///\}
-
-
- ///\name Comparison operators
- ///\{
-
- bool operator< (const FSEntry &) const;
- bool operator== (const FSEntry &) const;
-
- ///\}
-
- /**
- * Return the last part of our path (eg '/foo/bar' => 'bar').
- */
- std::string basename() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Return the path without a given prefix (eg '/foo/bar/baz'->strip_leading('/foo') => '/bar/baz').
- */
- FSEntry strip_leading(const FSEntry & prefix) const;
-
- /**
- * Return the first part of our path (eg '/foo/bar' => '/foo').
- */
- FSEntry dirname() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
-
- ///\}
-
- ///\name Filesystem queries
- ///\{
-
- /**
- * Does a filesystem entry exist at our location?
- */
- bool exists() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Does a filesystem entry exist at our location, and if it does,
- * is it a directory?
- */
- bool is_directory() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Does a filesystem entry exist at our location, and if it does,
- * is it a directory?
- */
- bool is_directory_or_symlink_to_directory() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Does a filesystem entry exist at our location, and if it does,
- * is it a regular file?
- */
- bool is_regular_file() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Does a filesystem entry exist at our location, and if it does,
- * is it a regular file?
- */
- bool is_regular_file_or_symlink_to_regular_file() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Does a filesystem entry exist at our location, and if it does,
- * is it a symbolic link?
- */
- bool is_symbolic_link() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Whether we exist and are a device file.
- */
- bool is_device() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Whether we exist and are a fifo.
- */
- bool is_fifo() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Check if filesystem entry has `perm` for `user_group`.
- *
- * \exception FSError if there was a problem accessing the filesystem entry
- */
- bool has_permission(const FSUserGroup & user_group, const FSPermission & fs_perm) const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Return the permissions for our item.
- *
- * \exception FSError if there was a problem accessing the filesystem entry
- */
- mode_t permissions() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Return the canonicalised version of our path.
- */
- FSEntry realpath() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Return the canonicalised version of our path, if it exists, or
- * ourself if it doesn't.
- */
- FSEntry realpath_if_exists() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Return our destination, if we are a symlink.
- *
- * \exception FSError if we are not a symlink, or if the system call
- * fails.
- */
- std::string readlink() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Return the time the inode for the filesystem entry was last modified
- *
- * \exception FSError if there was a problem accessing the filesystem entry
- * \since 0.43
- */
- Timestamp ctim() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Return the time the filesystem entry was last modified
- *
- * \exception FSError if there was a problem accessing the filesystem entry
- * \since 0.43
- */
- Timestamp mtim() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Return the size of our file, in bytes.
- *
- * \exception FSError if we don't have a size.
- */
- off_t file_size() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Fetch our owner.
- *
- * \exception FSError If we don't exist or the stat call fails.
- */
- uid_t owner() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Fetch our group.
- *
- * \exception FSError If we don't exist or the stat call fails.
- */
- gid_t group() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Return the current working directory
- */
- static FSEntry cwd()
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- /**
- * Return an unique low-level id for this entry
- */
- std::pair<dev_t, ino_t> lowlevel_id() const
- PALUDIS_ATTRIBUTE((warn_unused_result));
-
- ///\}
-
- ///\name Filesystem operations
- ///\{
-
- /**
- * Try to make a directory.
- *
- * \return True, if we succeeded, and false if the directory
- * already exists and is a directory.
- *
- * \exception FSError If an error other than the directory already
- * existing occurs.
- */
- bool mkdir(const mode_t mode = 0755);
-
- /**
- * Try to make a symlink.
- *
- * \return True, if we succeeded, and false if the target already
- * exists and is a symlink to the same target.
- *
- * \exception FSError If an error other than the symlink already
- * existing occurs, or if the symlink exists and points elsewhere.
- */
- bool symlink(const std::string & target);
-
- /**
- * Try to unlink.
- *
- * \return True, if we succeeded, and false if we don't exist
- * already.
- *
- * \exception FSError If an error other than us already not
- * existing occurs.
- */
- bool unlink();
-
- /**
- * Try to rmdir.
- *
- * \return True, if we succeeded, and false if we don't exist
- * already.
- *
- * \exception FSError If an error other than us already not
- * existing occurs.
- */
- bool rmdir();
-
- /**
- * Try to set atime and mtime
- *
- * \return True, if we succeeded, and false if we don't exist
- * already.
- *
- * \exception FSError If an error other than us already not
- * existing ocurrs.
- *
- * \since 0.44 takes a Timestamp
- */
- bool utime(const Timestamp &);
-
- /**
- * Change our ownership, following symlinks.
- *
- * \exception FSError If the chown failed.
- */
- void chown(const uid_t owner, const gid_t group = static_cast<gid_t>(-1));
-
- /**
- * Change our ownership, not following symlinks.
- *
- * \exception FSError If the lchown failed.
- */
- void lchown(const uid_t owner, const gid_t group = static_cast<gid_t>(-1));
-
- /**
- * Change our permissions.
- *
- * \exception FSError If the chmod failed.
- */
- void chmod(const mode_t mode);
-
- /**
- * Rename ourself (will not work across mount points).
- *
- * \exception FSError If the rename failed.
- */
- void rename(const FSEntry & new_name);
-
- ///\}
- };
-}
-
-#endif
diff --git a/paludis/util/fs_entry_TEST.cc b/paludis/util/fs_entry_TEST.cc
deleted file mode 100644
index e70c4a6..0000000
--- a/paludis/util/fs_entry_TEST.cc
+++ /dev/null
@@ -1,442 +0,0 @@
-/* vim: set sw=4 sts=4 et foldmethod=syntax : */
-
-/*
- * Copyright (c) 2005, 2006, 2007, 2008, 2009 Ciaran McCreesh
- * Copyright (c) 2006 Mark Loeser
- *
- * 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/fs_entry.hh>
-#include <paludis/util/log.hh>
-#include <paludis/util/timestamp.hh>
-#include <test/test_framework.hh>
-#include <test/test_runner.hh>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <ctime>
-
-using namespace paludis;
-using namespace test;
-
-/** \file
- * Test cases for fs_entry.hh.
- *
- * \todo this is nowhere near complete.
- *
- * \ingroup grpfilesystem
- */
-
-namespace test_cases
-{
- /**
- * \test Test FSEntry ctime and mtime methods
- *
- * \ingroup grpfilesystem
- */
- struct FSEntryTime : TestCase
- {
- FSEntryTime() : TestCase("ctime and mtime") {}
-
- bool repeatable() const
- {
- return false;
- }
-
- void run()
- {
- FSEntry a("fs_entry_TEST_dir");
- FSEntry b("fs_entry_TEST_dir/no_perms");
- FSEntry c("fs_entry_TEST_dir/no_such_file");
- FSEntry d("fs_entry_TEST_dir/dir_a/dir_in_a");
-
-#if !defined(__FreeBSD__)
- TEST_CHECK(a.ctim() < Timestamp::now());
- TEST_CHECK(a.mtim() < Timestamp::now());
-#endif
- TEST_CHECK(b.ctim() < Timestamp::now());
- TEST_CHECK(b.mtim() < Timestamp::now());
- TEST_CHECK(d.ctim() < Timestamp::now());
- TEST_CHECK(d.mtim() < Timestamp::now());
-
- TEST_CHECK(b.mtim() < b.ctim());
- TEST_CHECK(d.mtim() == d.ctim());
-
- TEST_CHECK_THROWS(Timestamp PALUDIS_ATTRIBUTE((unused)) x = c.ctim(), FSError);
- TEST_CHECK_THROWS(Timestamp PALUDIS_ATTRIBUTE((unused)) x = c.mtim(), FSError);
- }
- } test_fs_entry_time;
-
- /**
- * \test Test FSEntry construction and manipulation.
- *
- * \ingroup grpfilesystem
- */
- struct FSEntryManipulationTest : TestCase
- {
- FSEntryManipulationTest() : TestCase("construction and manipulation") { }
-
- void run()
- {
- FSEntry f("/foo/bar");
- FSEntry c(f);
- TEST_CHECK_EQUAL(f, FSEntry("/foo/bar"));
- TEST_CHECK_EQUAL(c, FSEntry("/foo/bar"));
- f = FSEntry("/baz");
- TEST_CHECK_EQUAL(f, FSEntry("/baz"));
- TEST_CHECK_EQUAL(c, FSEntry("/foo/bar"));
- c /= "moo";
- TEST_CHECK_EQUAL(f, FSEntry("/baz"));
- TEST_CHECK_EQUAL(c, FSEntry("/foo/bar/moo"));
- f = c / f;
- TEST_CHECK_EQUAL(f, FSEntry("/foo/bar/moo/baz"));
- TEST_CHECK_EQUAL(c, FSEntry("/foo/bar/moo"));
-
- f = FSEntry::cwd();
-
- TEST_CHECK_EQUAL(f, f / FSEntry("/"));
- }
- } test_fs_entry_manipulation;
-
- /**
- * \test Test FSEntry behavior.
- *
- * \ingroup grpfilesystem
- */
- struct FSEntryRealpathTest : TestCase
- {
- FSEntryRealpathTest() : TestCase("behavior") { }
-
- bool repeatable() const
- {
- return false;
- }
-
- void run()
- {
- FSEntry d("fs_entry_TEST_dir");
- TEST_CHECK(d.is_directory());
-
- d /= "all_perms";
- TEST_CHECK(d.is_regular_file());
-
- FSEntry e("fs_entry_TEST_dir/nosuchfile");
- TEST_CHECK(! e.is_regular_file());
- d = e;
- TEST_CHECK(! d.is_regular_file());
- TEST_CHECK(! d.exists());
- TEST_CHECK_THROWS(e.readlink(), FSError);
-
- d = FSEntry("fs_entry_TEST_dir/all_perms");
- TEST_CHECK(! e.is_regular_file());
- TEST_CHECK(d.is_regular_file());
- TEST_CHECK(d.exists());
-
- d = FSEntry("fs_entry_TEST_dir/symlink_to_dir_a");
- TEST_CHECK(d.is_symbolic_link());
- TEST_CHECK(! d.is_directory());
- TEST_CHECK(d.is_directory_or_symlink_to_directory());
- TEST_CHECK(! d.is_regular_file());
- TEST_CHECK(! d.is_regular_file_or_symlink_to_regular_file());
-
- e = FSEntry("fs_entry_TEST_dir/doesnotexist_symlink");
- TEST_CHECK(e.is_symbolic_link());
- TEST_CHECK(e.exists());
- TEST_CHECK(! e.is_directory());
- TEST_CHECK(! e.is_directory_or_symlink_to_directory());
- TEST_CHECK(! e.is_regular_file());
- TEST_CHECK(! e.is_regular_file_or_symlink_to_regular_file());
-
- FSEntry f("fs_entry_TEST_dir/symlink_to_dir_a/file_in_a");
- TEST_CHECK(f.is_regular_file());
- TEST_CHECK(! f.is_symbolic_link());
- FSEntry r(f.realpath());
- TEST_CHECK(r.is_regular_file());
- std::string g("fs_entry_TEST_dir/dir_a/file_in_a");
- TEST_CHECK_EQUAL(stringify(r).substr(stringify(r).length() - g.length()), g);
-
- FSEntry h("fs_entry_TEST_dir/symlink_to_file_in_a");
- TEST_CHECK(h.is_symbolic_link());
- TEST_CHECK(! h.is_regular_file());
- TEST_CHECK(h.is_regular_file_or_symlink_to_regular_file());
- TEST_CHECK_EQUAL(h.readlink(), "dir_a/file_in_a");
-
- FSEntry i("fs_entry_TEST_dir/dir_to_make");
- TEST_CHECK(i.mkdir());
- TEST_CHECK(! i.mkdir());
- TEST_CHECK(i.rmdir());
- FSEntry j("fs_entry_TEST_dir/dir_to_make");
- TEST_CHECK(! j.exists());
- TEST_CHECK(! j.is_directory());
-
- FSEntry k("fs_entry_TEST_dir/dir_a/file_in_a");
- TEST_CHECK_THROWS(k.mkdir(), FSError);
-
- FSEntry l("fs_entry_TEST_dir/file_a/file_that_triggers_ENOTDIR");
- TEST_CHECK(! l.exists());
- }
- } test_fs_entry_behaviour;
-
- /**
- * \test Test FSEntry has_permission methods.
- *
- * \ingroup grpfilesystem
- */
- struct FSEntryHasPermission: TestCase
- {
- FSEntryHasPermission() : TestCase("has_permission") {}
-
- void run()
- {
- FSEntry a("fs_entry_TEST_dir/all_perms");
- FSEntry b("fs_entry_TEST_dir/no_perms");
- FSEntry c("fs_entry_TEST_dir/no_such_file");
-
- TEST_CHECK(a.has_permission(fs_ug_owner, fs_perm_read));
- TEST_CHECK(a.has_permission(fs_ug_owner, fs_perm_write));
- TEST_CHECK(a.has_permission(fs_ug_owner, fs_perm_execute));
- TEST_CHECK(a.has_permission(fs_ug_group, fs_perm_read));
- TEST_CHECK(a.has_permission(fs_ug_group, fs_perm_write));
- TEST_CHECK(a.has_permission(fs_ug_group, fs_perm_execute));
- TEST_CHECK(a.has_permission(fs_ug_others, fs_perm_read));
- TEST_CHECK(a.has_permission(fs_ug_others, fs_perm_write));
- TEST_CHECK(a.has_permission(fs_ug_others, fs_perm_execute));
-
- TEST_CHECK(!b.has_permission(fs_ug_owner, fs_perm_read));
- TEST_CHECK(!b.has_permission(fs_ug_owner, fs_perm_write));
- TEST_CHECK(!b.has_permission(fs_ug_owner, fs_perm_execute));
- TEST_CHECK(!b.has_permission(fs_ug_group, fs_perm_read));
- TEST_CHECK(!b.has_permission(fs_ug_group, fs_perm_write));
- TEST_CHECK(!b.has_permission(fs_ug_group, fs_perm_execute));
- TEST_CHECK(!b.has_permission(fs_ug_others, fs_perm_read));
- TEST_CHECK(!b.has_permission(fs_ug_others, fs_perm_write));
- TEST_CHECK(!b.has_permission(fs_ug_others, fs_perm_execute));
-
- TEST_CHECK_THROWS(bool PALUDIS_ATTRIBUTE((unused)) x =
- c.has_permission(fs_ug_owner, fs_perm_read), FSError);
- }
- } test_fs_entry_permission;
-
- /**
- * \test Test FSEntry file_size
- *
- * \ingroup grpfilesystem
- */
- struct FSEntryFileSize : TestCase
- {
- FSEntryFileSize() : TestCase("file size") {}
-
- void run()
- {
- FSEntry f("fs_entry_TEST_dir/ten_bytes");
- FSEntry d("fs_entry_TEST_dir/dir_a");
- FSEntry e("fs_entry_TEST_dir/no_such_file");
-
- TEST_CHECK_EQUAL(f.file_size(), 10);
- TEST_CHECK_THROWS(size_t PALUDIS_ATTRIBUTE((unused)) x = d.file_size(), FSError);
- TEST_CHECK_THROWS(size_t PALUDIS_ATTRIBUTE((unused)) x = e.file_size(), FSError);
- }
- } test_fs_entry_size;
-
- struct FSEntrySymlink : TestCase
- {
- FSEntrySymlink() : TestCase("symlink") {}
-
- void run()
- {
- FSEntry f("fs_entry_TEST_dir/new_sym");
- TEST_CHECK(f.symlink("the_target"));
- TEST_CHECK(f.is_symbolic_link());
- TEST_CHECK_EQUAL(f.readlink(), "the_target");
- f.unlink();
- }
- } test_fs_symlink;
-
- /**
- * \test Test FSEntry basename and dirname methods
- *
- * \ingroup grpfilesystem
- */
- struct FSEntryBaseDirName : TestCase
- {
- FSEntryBaseDirName() : TestCase("basename and dirname") {}
-
- void run()
- {
- FSEntry a("/foo/bar");
- FSEntry b("/moo/went/the/cow");
- FSEntry c("/");
- FSEntry d(".");
- FSEntry e("..");
-
- TEST_CHECK(a.basename() == "bar");
- TEST_CHECK(stringify(a.dirname()) == "/foo");
- TEST_CHECK(b.basename() == "cow");
- TEST_CHECK(stringify(b.dirname()) == "/moo/went/the");
- TEST_CHECK(c.basename() == "/");
- TEST_CHECK(stringify(c.dirname()) == "/");
- TEST_CHECK(d.basename() == ".");
- TEST_CHECK(stringify(d.dirname()) == ".");
- TEST_CHECK(e.basename() == "..");
- TEST_CHECK(stringify(e.dirname()) == "..");
- }
- } test_fs_entry_dir_base_name;
-
- /**
- * \test Test FSEntry strip_leading method
- *
- * \ingroup grpfilesystem
- */
- struct FSEntryStripLeading : TestCase
- {
- FSEntryStripLeading() : TestCase("strip_leading") {}
-
- void run()
- {
- FSEntry root1("/stairway/to/heaven/");
- FSEntry root2("");
- FSEntry root3("/");
-
- FSEntry a(root1);
- FSEntry b(root1 / "usr" / "share");
- FSEntry c(root2 / "my" / "directory");
- FSEntry d(root3 / "my" / "directory");
-
- TEST_CHECK(stringify(a.strip_leading(root1)) == "/");
- TEST_CHECK(stringify(b.strip_leading(root1)) == "/usr/share");
- TEST_CHECK(stringify(c.strip_leading(root2)) == "/my/directory");
- TEST_CHECK(stringify(d.strip_leading(root3)) == "/my/directory");
- }
- } test_fs_entry_strip_leading;
-
- /**
- * \test Test FSEntry chmod, chown and permissions methods
- *
- * \ingroup grpfilesystem
- */
- struct FSEntryChangePerms : TestCase
- {
- FSEntryChangePerms() : TestCase("chmod, chown and permissions") {}
-
- void run()
- {
- FSEntry a("fs_entry_TEST_dir/no_perms");
-
- uid_t my_uid = geteuid();
- a.chown(my_uid);
- TEST_CHECK_EQUAL(a.owner(), my_uid);
-
- mode_t all_perms(S_IRUSR | S_IWUSR | S_IXUSR |
- S_IRGRP | S_IWGRP | S_IXGRP |
- S_IROTH | S_IWOTH | S_IXOTH);
- a.chmod(all_perms);
-
- FSEntry b("fs_entry_TEST_dir/no_perms");
-
- TEST_CHECK_EQUAL(static_cast<mode_t>(b.permissions() & 0xFFF), all_perms);
-
- mode_t no_perms(0);
- b.chmod(no_perms);
-
- FSEntry c("fs_entry_TEST_dir/no_perms");
- TEST_CHECK_EQUAL(static_cast<mode_t>(c.permissions() & 0xFFF), no_perms);
-
- FSEntry d("fs_entry_TEST_dir/i_dont_exist");
-
- TEST_CHECK_THROWS(mode_t PALUDIS_ATTRIBUTE((unused)) x = d.permissions(), FSError);
- TEST_CHECK_THROWS(d.chmod(all_perms), FSError);
- TEST_CHECK_THROWS(d.chown(static_cast<uid_t>(-1)), FSError);
- TEST_CHECK_THROWS(uid_t PALUDIS_ATTRIBUTE((unused)) x = d.owner(), FSError);
- TEST_CHECK_THROWS(gid_t PALUDIS_ATTRIBUTE((unused)) x = d.group(), FSError);
-
- if (0 == my_uid)
- {
- struct passwd *pw = getpwent();
-
- if (! pw)
- throw InternalError(PALUDIS_HERE, "getpwent returned NULL");
-
- std::string my_file("fs_entry_TEST_dir/all_perms");
- FSEntry e(my_file);
-
- uid_t my_owner = e.owner();
- gid_t my_group = e.group();
-
- if (pw->pw_uid == my_owner)
- {
- pw = getpwent();
-
- if (! pw)
- throw InternalError(PALUDIS_HERE, "getpwent returned NULL");
- }
-
- uid_t new_owner(pw->pw_uid);
-
- e.chown(new_owner);
-
- TEST_CHECK_EQUAL(FSEntry(my_file).owner(), new_owner);
- TEST_CHECK_EQUAL(FSEntry(my_file).group(), my_group);
-
- gid_t new_group(pw->pw_gid);
-
- endpwent();
-
- e.chown(static_cast<uid_t>(-1), new_group);
-
- TEST_CHECK_EQUAL(FSEntry(my_file).owner(), new_owner);
- TEST_CHECK_EQUAL(FSEntry(my_file).group(), new_group);
-
- e.chown(static_cast<uid_t>(-1));
-
- TEST_CHECK_EQUAL(FSEntry(my_file).owner(), new_owner);
- TEST_CHECK_EQUAL(FSEntry(my_file).group(), new_group);
-
- e.chown(my_owner, my_group);
-
- TEST_CHECK_EQUAL(FSEntry(my_file).owner(), my_owner);
- TEST_CHECK_EQUAL(FSEntry(my_file).group(), my_group);
- }
- else
- {
- FSEntry e("fs_entry_TEST_dir/all_perms");
-
- TEST_CHECK_THROWS(e.chown(0, 0), FSError);
- }
- }
- } test_fs_entry_change_perms;
-
- /**
- * \test Test operator<<
- *
- * \ingroup grpfilesystem
- */
- struct FSEntryToOstreamOperator : TestCase
- {
- FSEntryToOstreamOperator() : TestCase("operator<<") {}
-
- void run()
- {
- std::string n("fs_entry_TEST_dir/no_perms");
- std::ostringstream s;
- FSEntry a(n);
-
- s << a;
-
- TEST_CHECK_EQUAL(s.str(), n);
- }
- } test_fs_entry_to_ostream_operator;
-}
-
diff --git a/paludis/util/fs_error.cc b/paludis/util/fs_error.cc
new file mode 100644
index 0000000..cabcc06
--- /dev/null
+++ b/paludis/util/fs_error.cc
@@ -0,0 +1,30 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh
+ * Copyright (c) 2006 Mark Loeser
+ * Copyright (c) 2008 Fernando J. Pereda
+ *
+ * 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/fs_error.hh>
+
+using namespace paludis;
+
+FSError::FSError(const std::string & our_message) throw () :
+ Exception(our_message)
+{
+}
+
diff --git a/paludis/util/fs_error.hh b/paludis/util/fs_error.hh
new file mode 100644
index 0000000..352a3c1
--- /dev/null
+++ b/paludis/util/fs_error.hh
@@ -0,0 +1,48 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh
+ * Copyright (c) 2006 Mark Loeser
+ *
+ * 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_FS_ERROR_HH
+#define PALUDIS_GUARD_PALUDIS_FS_ERROR_HH 1
+
+#include <paludis/util/exception.hh>
+
+namespace paludis
+{
+ /**
+ * Generic filesystem error class.
+ *
+ * \ingroup g_exceptions
+ * \ingroup g_fs
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE FSError :
+ public Exception
+ {
+ public:
+ ///\name Basic operations
+ ///\{
+
+ FSError(const std::string & message) throw ();
+
+ ///\}
+ };
+}
+
+#endif
diff --git a/paludis/util/dir_iterator-fwd.hh b/paludis/util/fs_iterator-fwd.hh
index 32a006c..2c8e433 100644
--- a/paludis/util/dir_iterator-fwd.hh
+++ b/paludis/util/fs_iterator-fwd.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2008 Ciaran McCreesh
+ * Copyright (c) 2010 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,27 +17,23 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef PALUDIS_GUARD_PALUDIS_UTIL_DIR_ITERATOR_FWD_HH
-#define PALUDIS_GUARD_PALUDIS_UTIL_DIR_ITERATOR_FWD_HH 1
+#ifndef PALUDIS_GUARD_PALUDIS_UTIL_FS_ITERATOR_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_FS_ITERATOR_FWD_HH 1
-#include <paludis/util/attributes.hh>
#include <paludis/util/options-fwd.hh>
+#include <paludis/util/attributes.hh>
#include <iosfwd>
namespace paludis
{
-#include <paludis/util/dir_iterator-se.hh>
-
- /**
- * Options for a DirIterator.
- *
- * \see DirIteratorOption
- * \see DirIterator
- */
- typedef Options<DirIteratorOption> DirIteratorOptions;
-
- class DirOpenError;
- class DirIterator;
+ struct FSIterator;
+
+#include <paludis/util/fs_iterator-se.hh>
+
+ typedef Options<FSIteratorOption> FSIteratorOptions;
+
+ bool operator== (const FSIterator &, const FSIterator &) PALUDIS_VISIBLE;
+ bool operator!= (const FSIterator &, const FSIterator &) PALUDIS_VISIBLE;
}
#endif
diff --git a/paludis/util/dir_iterator.cc b/paludis/util/fs_iterator.cc
index 4021082..b7db239 100644
--- a/paludis/util/dir_iterator.cc
+++ b/paludis/util/fs_iterator.cc
@@ -18,11 +18,15 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <dirent.h>
-#include <paludis/util/dir_iterator.hh>
+#include <paludis/util/fs_iterator.hh>
+#include <paludis/util/fs_path.hh>
+#include <paludis/util/fs_error.hh>
#include <paludis/util/stringify.hh>
+#include <paludis/util/exception.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/util/options.hh>
+
+#include <dirent.h>
#include <sys/types.h>
#include <functional>
#include <set>
@@ -33,20 +37,14 @@
using namespace paludis;
-#include <paludis/util/dir_iterator-se.cc>
+#include <paludis/util/fs_iterator-se.cc>
-typedef std::multiset<std::pair<ino_t, FSEntry>, std::function<bool (std::pair<ino_t, FSEntry>, std::pair<ino_t, FSEntry>)> > EntrySet;
-template class Pimp<DirIterator>;
+typedef std::multiset<std::pair<ino_t, FSPath>, std::function<bool (std::pair<ino_t, FSPath>, std::pair<ino_t, FSPath>)> > EntrySet;
namespace paludis
{
- /**
- * Imp data for DirIterator.
- *
- * \ingroup grpfilesystem
- */
template<>
- struct Imp<DirIterator>
+ struct Imp<FSIterator>
{
std::shared_ptr<EntrySet> items;
EntrySet::iterator iter;
@@ -57,62 +55,49 @@ namespace paludis
}
};
- bool compare_inode(const std::pair<ino_t, FSEntry> & a, const std::pair<ino_t, FSEntry> & b)
+ bool compare_inode(const std::pair<ino_t, FSPath> & a, const std::pair<ino_t, FSPath> & b)
{
return a.first < b.first;
}
- bool compare_name(const std::pair<ino_t, FSEntry> & a, const std::pair<ino_t, FSEntry> & b)
+ bool compare_name(const std::pair<ino_t, FSPath> & a, const std::pair<ino_t, FSPath> & b)
{
- return a.second < b.second;
+ return FSPathComparator()(a.second, b.second);
}
}
-DirOpenError::DirOpenError(const FSEntry & location, const int errno_value) throw () :
- FSError("Error opening directory '" + stringify(location) + "': " + std::strerror(errno_value))
-{
-}
-
-DirIterator::DirIterator(const FSEntry & base, const DirIteratorOptions & options) :
- Pimp<DirIterator>(std::shared_ptr<EntrySet>())
+FSIterator::FSIterator(const FSPath & base, const FSIteratorOptions & options) :
+ Pimp<FSIterator>(std::shared_ptr<EntrySet>())
{
using namespace std::placeholders;
- if (options[dio_inode_sort])
+ if (options[fsio_inode_sort])
_imp->items = std::make_shared<EntrySet>(&compare_inode);
else
_imp->items = std::make_shared<EntrySet>(&compare_name);
DIR * d(opendir(stringify(base).c_str()));
if (0 == d)
- throw DirOpenError(base, errno);
+ throw FSError("Error opening directory '" + stringify(base) + "'");
struct dirent * de;
while (0 != ((de = readdir(d))))
- if (! options[dio_include_dotfiles])
+ if (! options[fsio_include_dotfiles])
{
if ('.' != de->d_name[0])
{
-#ifdef HAVE_DIRENT_DTYPE
- FSEntry f(stringify(base / std::string(de->d_name)), de->d_type);
-#else
- FSEntry f(stringify(base / std::string(de->d_name)), 0);
-#endif
+ FSPath f(stringify(base / std::string(de->d_name)));
_imp->items->insert(std::make_pair(de->d_ino, f));
- if (options[dio_first_only])
+ if (options[fsio_first_only])
break;
}
}
else if (! (de->d_name[0] == '.' &&
(de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0'))))
{
-#ifdef HAVE_DIRENT_DTYPE
- FSEntry f(stringify(base / std::string(de->d_name)), de->d_type);
-#else
- FSEntry f(stringify(base / std::string(de->d_name)), 0);
-#endif
+ FSPath f(stringify(base / std::string(de->d_name)));
_imp->items->insert(std::make_pair(de->d_ino, f));
- if (options[dio_first_only])
+ if (options[fsio_first_only])
break;
}
@@ -121,24 +106,24 @@ DirIterator::DirIterator(const FSEntry & base, const DirIteratorOptions & option
closedir(d);
}
-DirIterator::DirIterator(const DirIterator & other) :
- Pimp<DirIterator>(other._imp->items)
+FSIterator::FSIterator(const FSIterator & other) :
+ Pimp<FSIterator>(other._imp->items)
{
_imp->iter = other._imp->iter;
}
-DirIterator::DirIterator() :
- Pimp<DirIterator>(std::shared_ptr<EntrySet>(std::make_shared<EntrySet>(&compare_name)))
+FSIterator::FSIterator() :
+ Pimp<FSIterator>(std::shared_ptr<EntrySet>(std::make_shared<EntrySet>(&compare_name)))
{
_imp->iter = _imp->items->end();
}
-DirIterator::~DirIterator()
+FSIterator::~FSIterator()
{
}
-DirIterator &
-DirIterator::operator= (const DirIterator & other)
+FSIterator &
+FSIterator::operator= (const FSIterator & other)
{
if (this != &other)
{
@@ -148,52 +133,53 @@ DirIterator::operator= (const DirIterator & other)
return *this;
}
-const FSEntry &
-DirIterator::operator* () const
+const FSPath &
+FSIterator::operator* () const
{
return _imp->iter->second;
}
-const FSEntry *
-DirIterator::operator-> () const
+const FSPath *
+FSIterator::operator-> () const
{
return &_imp->iter->second;
}
-DirIterator &
-DirIterator::operator++ ()
+FSIterator &
+FSIterator::operator++ ()
{
++_imp->iter;
return *this;
}
-DirIterator
-DirIterator::operator++ (int)
+FSIterator
+FSIterator::operator++ (int)
{
- DirIterator c(*this);
+ FSIterator c(*this);
_imp->iter++;
return c;
}
bool
-DirIterator::operator== (const DirIterator & other) const
+paludis::operator== (const FSIterator & me, const FSIterator & other)
{
if (other._imp->iter == other._imp->items->end())
- return _imp->iter == _imp->items->end();
+ return me._imp->iter == me._imp->items->end();
- if (_imp->iter == _imp->items->end())
+ if (me._imp->iter == me._imp->items->end())
return other._imp->iter == other._imp->items->end();
- if (other._imp->items != _imp->items)
- throw InternalError(PALUDIS_HERE,
- "comparing two different DirIterators.");
+ if (other._imp->items != me._imp->items)
+ throw InternalError(PALUDIS_HERE, "comparing two different FSIterators.");
- return other._imp->iter == _imp->iter;
+ return other._imp->iter == me._imp->iter;
}
bool
-DirIterator::operator!= (const DirIterator & other) const
+paludis::operator!= (const FSIterator & me, const FSIterator & other)
{
- return ! operator== (other);
+ return ! operator== (me, other);
}
+template class Pimp<FSIterator>;
+
diff --git a/paludis/util/fs_iterator.hh b/paludis/util/fs_iterator.hh
new file mode 100644
index 0000000..080d9a6
--- /dev/null
+++ b/paludis/util/fs_iterator.hh
@@ -0,0 +1,63 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010 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_FS_ITERATOR_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_FS_ITERATOR_HH 1
+
+#include <paludis/util/fs_iterator-fwd.hh>
+#include <paludis/util/fs_path-fwd.hh>
+#include <paludis/util/options-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/pimp.hh>
+#include <iterator>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE FSIterator :
+ private Pimp<FSIterator>
+ {
+ friend bool operator== (const FSIterator &, const FSIterator &);
+
+ public:
+ explicit FSIterator();
+ FSIterator(const FSPath &, const FSIteratorOptions &);
+
+ FSIterator(const FSIterator &);
+
+ FSIterator & operator= (const FSIterator &);
+
+ ~FSIterator();
+
+ typedef const FSPath & value_type;
+ typedef const FSPath & reference;
+ typedef const FSPath * pointer;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::forward_iterator_tag iterator_category;
+
+ FSIterator & operator++ ();
+ FSIterator operator++ (int);
+
+ pointer operator-> () const;
+ reference operator* () const;
+ };
+
+ extern template class Pimp<FSIterator>;
+}
+
+#endif
diff --git a/paludis/util/fs_iterator.se b/paludis/util/fs_iterator.se
new file mode 100644
index 0000000..6cbf44b
--- /dev/null
+++ b/paludis/util/fs_iterator.se
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+# vim: set sw=4 sts=4 et ft=sh :
+
+make_enum_FSIteratorOption()
+{
+ prefix fsio
+
+ key fsio_include_dotfiles "Skip files whose name start with a dot"
+ key fsio_inode_sort "Return items sorted by inode number"
+ key fsio_first_only "Return the first item only"
+
+ doxygen_comment << "END"
+ /**
+ * Options for an FSIterator.
+ *
+ * \see FSIterator
+ * \see FSIteratorOptions
+ * \ingroup g_fs
+ */
+END
+}
diff --git a/paludis/util/fs_iterator_TEST.cc b/paludis/util/fs_iterator_TEST.cc
new file mode 100644
index 0000000..cf73061
--- /dev/null
+++ b/paludis/util/fs_iterator_TEST.cc
@@ -0,0 +1,93 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2006 Mark Loeser
+ * Copyright (c) 2010 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/fs_iterator.hh>
+#include <paludis/util/fs_path.hh>
+#include <paludis/util/fs_error.hh>
+#include <paludis/util/options.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+
+using namespace paludis;
+using namespace test;
+
+namespace test_cases
+{
+ struct FSIteratorManipulationTest : TestCase
+ {
+ FSIteratorManipulationTest() : TestCase("construction and manipulation") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(FSIterator(FSPath("/i/dont/exist/"), { }), FSError);
+
+ FSIterator iter(FSPath("fs_iterator_TEST_dir"), { });
+ FSIterator iter1(iter);
+ TEST_CHECK(iter == iter1);
+ TEST_CHECK(!(iter != iter1));
+ }
+ } test_fs_iterator_manipulation;
+
+ struct FSIteratorIterateTest : TestCase
+ {
+ FSIteratorIterateTest() : TestCase("iterate") {}
+
+ void run()
+ {
+ FSIterator iter(FSPath("fs_iterator_TEST_dir"), { });
+ FSIterator iter1(FSPath("fs_iterator_TEST_dir"), { });
+ FSIterator iter2(FSPath("fs_iterator_TEST_dir"), { fsio_include_dotfiles });
+ FSIterator iter3(FSPath("fs_iterator_TEST_dir"), { fsio_inode_sort });
+
+ TEST_CHECK(iter != FSIterator());
+ TEST_CHECK(FSIterator() != iter);
+
+ TEST_CHECK_EQUAL(iter->basename(), "file1");
+ TEST_CHECK(++iter != FSIterator());
+ TEST_CHECK_EQUAL(iter->basename(), "file2");
+ TEST_CHECK(++iter != FSIterator());
+ TEST_CHECK_EQUAL(iter->basename(), "file4");
+ TEST_CHECK(++iter == FSIterator());
+ TEST_CHECK(FSIterator() == iter);
+
+ while (iter1 != FSIterator())
+ ++iter1;
+ TEST_CHECK(iter1 == FSIterator());
+ TEST_CHECK(iter == iter1);
+
+ TEST_CHECK_EQUAL(iter2->basename(), ".file3");
+ TEST_CHECK(++iter2 != FSIterator());
+ TEST_CHECK_EQUAL(iter2->basename(), "file1");
+ TEST_CHECK(++iter2 != FSIterator());
+ TEST_CHECK_EQUAL(iter2->basename(), "file2");
+ TEST_CHECK(++iter2 != FSIterator());
+ TEST_CHECK_EQUAL(iter2->basename(), "file4");
+ TEST_CHECK(++iter2 == FSIterator());
+ TEST_CHECK(FSIterator() == iter2);
+ TEST_CHECK(iter2 == FSIterator());
+
+ TEST_CHECK(iter1 == iter2);
+ TEST_CHECK(iter2 == iter1);
+
+ TEST_CHECK_EQUAL(std::distance(iter3, FSIterator()), 3);
+ }
+ } test_fs_iterator_iterate;
+}
+
diff --git a/paludis/util/dir_iterator_TEST_cleanup.sh b/paludis/util/fs_iterator_TEST_cleanup.sh
index aeb0909..6698c21 100755
--- a/paludis/util/dir_iterator_TEST_cleanup.sh
+++ b/paludis/util/fs_iterator_TEST_cleanup.sh
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
# vim: set ft=sh sw=4 sts=4 et :
-if [ -d dir_iterator_TEST_dir ] ; then
- rm -fr dir_iterator_TEST_dir
+if [ -d fs_iterator_TEST_dir ] ; then
+ rm -fr fs_iterator_TEST_dir
else
true
fi
diff --git a/paludis/util/dir_iterator_TEST_setup.sh b/paludis/util/fs_iterator_TEST_setup.sh
index 15a4641..64970d0 100755
--- a/paludis/util/dir_iterator_TEST_setup.sh
+++ b/paludis/util/fs_iterator_TEST_setup.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# vim: set ft=sh sw=4 sts=4 et :
-mkdir dir_iterator_TEST_dir || exit 2
-cd dir_iterator_TEST_dir || exit 3
+mkdir fs_iterator_TEST_dir || exit 2
+cd fs_iterator_TEST_dir || exit 3
touch file1 file2 .file3 || exit 4
ln file1 file4 || cp file1 file4 || exit 5
diff --git a/paludis/util/fs_path-fwd.hh b/paludis/util/fs_path-fwd.hh
new file mode 100644
index 0000000..5378d3e
--- /dev/null
+++ b/paludis/util/fs_path-fwd.hh
@@ -0,0 +1,53 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_FS_PATH_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_FS_PATH_FWD_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/util/sequence-fwd.hh>
+#include <paludis/util/set-fwd.hh>
+#include <paludis/util/options-fwd.hh>
+#include <iosfwd>
+
+namespace paludis
+{
+ struct FSPath;
+ struct FSPathComparator;
+
+ typedef Sequence<FSPath> FSPathSequence;
+
+ typedef Set<FSPath, FSPathComparator> FSPathSet;
+
+ /**
+ * An FSPath can be written to an ostream.
+ *
+ * \ingroup g_fs
+ */
+ std::ostream & operator<< (std::ostream & s, const FSPath & f) PALUDIS_VISIBLE;
+
+ bool operator== (const FSPath &, const FSPath &) PALUDIS_VISIBLE;
+ bool operator!= (const FSPath &, const FSPath &) PALUDIS_VISIBLE;
+
+#include <paludis/util/fs_path-se.hh>
+
+ typedef Options<FSPathMkdirOption> FSPathMkdirOptions;
+}
+
+#endif
diff --git a/paludis/util/fs_path.cc b/paludis/util/fs_path.cc
new file mode 100644
index 0000000..43d28fb
--- /dev/null
+++ b/paludis/util/fs_path.cc
@@ -0,0 +1,439 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/fs_path.hh>
+#include <paludis/util/fs_error.hh>
+#include <paludis/util/fs_stat.hh>
+#include <paludis/util/pimp-impl.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/timestamp.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/sequence-impl.hh>
+#include <paludis/util/set-impl.hh>
+#include <paludis/util/wrapped_output_iterator-impl.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+
+#include <string>
+#include <climits>
+#include <cstdlib>
+#include <cstring>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "config.h"
+
+using namespace paludis;
+
+namespace paludis
+{
+ template <>
+ struct Imp<FSPath>
+ {
+ std::string path;
+
+ Imp(const std::string & p) :
+ path(p)
+ {
+ }
+ };
+}
+
+FSPath::FSPath(const std::string & path) :
+ Pimp<FSPath>(path)
+{
+ _normalise();
+}
+
+FSPath::FSPath(const FSPath & other) :
+ Pimp<FSPath>(other._imp->path)
+{
+}
+
+FSPath::~FSPath() = default;
+
+FSStat
+FSPath::stat() const
+{
+ return FSStat(*this);
+}
+
+FSPath &
+FSPath::operator= (const FSPath & other)
+{
+ _imp->path = other._imp->path;
+ return *this;
+}
+
+FSPath &
+FSPath::operator/= (const FSPath & rhs)
+{
+ if (rhs._imp->path == "/")
+ return *this;
+
+ if (_imp->path.empty() || '/' != _imp->path.at(_imp->path.length() - 1))
+ _imp->path.append("/");
+
+ if (! rhs._imp->path.empty())
+ {
+ if ('/' == rhs._imp->path.at(0))
+ _imp->path.append(rhs._imp->path.substr(1));
+ else
+ _imp->path.append(rhs._imp->path);
+ }
+
+ return *this;
+}
+
+FSPath &
+FSPath::operator/= (const std::string & rhs)
+{
+ return operator/= (FSPath(rhs));
+}
+
+FSPath
+FSPath::operator/ (const FSPath & rhs) const
+{
+ FSPath result(*this);
+ result /= rhs;
+ return result;
+}
+
+FSPath
+FSPath::operator/ (const std::string & rhs) const
+{
+ return *this / FSPath(rhs);
+}
+
+bool
+paludis::operator== (const FSPath & me, const FSPath & other)
+{
+ return me._imp->path == other._imp->path;
+}
+
+bool
+paludis::operator!= (const FSPath & me, const FSPath & other)
+{
+ return ! operator== (me, other);
+}
+
+void
+FSPath::_normalise()
+{
+ try
+ {
+ if (std::string::npos != _imp->path.find("//"))
+ {
+ std::string new_path;
+ std::string::size_type p(0);
+ while (p < _imp->path.length())
+ {
+ if ('/' == _imp->path[p])
+ {
+ new_path += '/';
+ while (++p < _imp->path.length())
+ if ('/' != _imp->path[p])
+ break;
+ }
+ else
+ new_path += _imp->path[p++];
+ }
+ _imp->path = new_path;
+ }
+
+ if (! _imp->path.empty())
+ if ('/' == _imp->path.at(_imp->path.length() - 1))
+ _imp->path.erase(_imp->path.length() - 1);
+ if (_imp->path.empty())
+ _imp->path = "/";
+ }
+ catch (const std::exception & e)
+ {
+ Context c("When normalising FSPath path '" + _imp->path + "':");
+ throw InternalError(PALUDIS_HERE,
+ "caught std::exception '" + stringify(e.what()) + "'");
+ }
+}
+
+const std::string
+FSPath::basename() const
+{
+ if (_imp->path == "/")
+ return _imp->path;
+
+ return _imp->path.substr(_imp->path.rfind('/') + 1);
+}
+
+FSPath
+FSPath::strip_leading(const FSPath & f) const
+{
+ std::string root(stringify(f));
+
+ if (root == "/")
+ root.clear();
+ if (0 != _imp->path.compare(0, root.length(), root))
+ throw FSError("Can't strip leading '" + root + "' from FSPath '" + _imp->path + "'");
+ return FSPath(_imp->path.substr(root.length()));
+}
+
+FSPath
+FSPath::dirname() const
+{
+ if (_imp->path == "/")
+ return FSPath(_imp->path);
+
+ return FSPath(_imp->path.substr(0, _imp->path.rfind('/')));
+}
+
+FSPath
+FSPath::realpath() const
+{
+ Context context("When fetching realpath of '" + stringify(_imp->path) + "':");
+
+#ifdef HAVE_CANONICALIZE_FILE_NAME
+ char * r(canonicalize_file_name(_imp->path.c_str()));
+ if (! r)
+ throw FSError("Could not resolve path '" + _imp->path + "'");
+ FSPath result(r);
+ std::free(r);
+ return result;
+#else
+ char r[PATH_MAX + 1];
+ std::memset(r, 0, PATH_MAX + 1);
+ if (! exists())
+ throw FSError("Could not resolve path '" + _imp->path + "'");
+ if (! ::realpath(_imp->path.c_str(), r))
+ throw FSError("Could not resolve path '" + _imp->path + "'");
+ FSPath result(r);
+ if (! result.exists())
+ throw FSError("Could not resolve path '" + _imp->path + "'");
+ return result;
+#endif
+}
+
+FSPath
+FSPath::realpath_if_exists() const
+{
+ Context context("When fetching realpath of '" + stringify(_imp->path) + "', if it exists:");
+
+#ifdef HAVE_CANONICALIZE_FILE_NAME
+ char * r(canonicalize_file_name(_imp->path.c_str()));
+ if (! r)
+ return *this;
+ FSPath result(r);
+ std::free(r);
+ return result;
+#else
+ char r[PATH_MAX + 1];
+ std::memset(r, 0, PATH_MAX + 1);
+ if (! exists())
+ return *this;
+ if (! ::realpath(_imp->path.c_str(), r))
+ return *this;
+ FSPath result(r);
+ if (! result.exists())
+ return *this;
+ return result;
+#endif
+}
+
+FSPath
+FSPath::cwd()
+{
+ char r[PATH_MAX + 1];
+ std::memset(r, 0, PATH_MAX + 1);
+ if (! ::getcwd(r, PATH_MAX))
+ throw FSError("Could not get current working directory");
+ return FSPath(r);
+}
+
+std::ostream &
+paludis::operator<< (std::ostream & s, const FSPath & f)
+{
+ s << f._imp->path;
+ return s;
+}
+
+bool
+FSPath::mkdir(const mode_t mode, const FSPathMkdirOptions & options) const
+{
+ if (0 == ::mkdir(_imp->path.c_str(), mode))
+ return true;
+
+ int e(errno);
+ if (e == EEXIST && options[fspmkdo_ok_if_exists])
+ {
+ if (stat().is_directory())
+ return false;
+ throw FSError("mkdir '" + _imp->path + "' failed: target exists and is not a directory");
+ }
+ else
+ throw FSError("mkdir '" + _imp->path + "' failed: " + ::strerror(e));
+}
+
+bool
+FSPath::symlink(const std::string & target) const
+{
+ if (0 == ::symlink(target.c_str(), _imp->path.c_str()))
+ return true;
+
+ int e(errno);
+ if (e == EEXIST)
+ {
+ if (stat().is_symlink() && target == readlink())
+ return false;
+ throw FSError("symlink '" + _imp->path + "' to '" + target + "' failed: target exists");
+ }
+ else
+ throw FSError("symlink '" + _imp->path + "' to '" + target + "' failed: " + ::strerror(e));
+}
+
+bool
+FSPath::unlink() const
+{
+#ifdef HAVE_LCHFLAGS
+ if (0 != ::lchflags(_imp->path.c_str(), 0))
+ {
+ int e(errno);
+ if (e != ENOENT)
+ throw FSError("lchflags for unlink '" + _imp->path + "' failed: " + ::strerror(e));
+ }
+#endif
+
+ if (0 == ::unlink(_imp->path.c_str()))
+ return true;
+
+ int e(errno);
+ if (e == ENOENT)
+ return false;
+ else
+ throw FSError("unlink '" + _imp->path + "' failed: " + ::strerror(e));
+}
+
+bool
+FSPath::rmdir() const
+{
+ if (0 == ::rmdir(_imp->path.c_str()))
+ return true;
+
+ int e(errno);
+ if (e == ENOENT)
+ return false;
+ else
+ throw FSError("rmdir '" + _imp->path + "' failed: " + ::strerror(e));
+}
+
+bool
+FSPath::utime(const Timestamp & t) const
+{
+ Context context("When setting utime for '" + stringify(_imp->path) + "':");
+
+#ifdef HAVE_UTIMENSAT
+ static bool utimensat_works(true);
+
+ if (utimensat_works)
+ {
+ struct timespec ts[2] = { t.as_timespec(), t.as_timespec() };
+ if (0 == ::utimensat(AT_FDCWD, _imp->path.c_str(), ts, 0))
+ return true;
+
+ int e(errno);
+ if (e == ENOENT)
+ return false;
+ else if (e == ENOSYS)
+ {
+ utimensat_works = false;
+ Log::get_instance()->message("util.fs_entry.utime.utimensat_unimplemented", ll_debug, lc_context)
+ << "utimensat(2) not implemented by this kernel, using utimes(2)";
+ }
+ else
+ throw FSError("utimensat '" + _imp->path + "' failed: " + ::strerror(e));
+ }
+#endif
+
+ struct timeval tv[2] = { t.as_timeval(), t.as_timeval() };
+ if (0 == ::utimes(_imp->path.c_str(), tv))
+ return true;
+
+ int e(errno);
+ if (e == ENOENT)
+ return false;
+ else
+ throw FSError("utimes '" + _imp->path + "' failed: " + ::strerror(e));
+}
+
+std::string
+FSPath::readlink() const
+{
+ char buf[PATH_MAX + 1];
+ std::memset(buf, 0, PATH_MAX + 1);
+ if (-1 == ::readlink(_imp->path.c_str(), buf, PATH_MAX))
+ throw FSError("readlink '" + _imp->path + "' failed: " + ::strerror(errno));
+ return buf;
+}
+
+void
+FSPath::chown(const uid_t new_owner, const gid_t new_group) const
+{
+ if (0 != ::chown(_imp->path.c_str(), new_owner, new_group))
+ throw FSError("chown '" + _imp->path + "' to '" + stringify(new_owner) + "', '"
+ + stringify(new_group) + "' failed: " + ::strerror(errno));
+}
+
+void
+FSPath::lchown(const uid_t new_owner, const gid_t new_group) const
+{
+ if (0 != ::lchown(_imp->path.c_str(), new_owner, new_group))
+ throw FSError("lchown '" + _imp->path + "' to '" + stringify(new_owner) + "', '"
+ + stringify(new_group) + "' failed: " + ::strerror(errno));
+}
+
+void
+FSPath::chmod(const mode_t mode) const
+{
+ if (0 != ::chmod(_imp->path.c_str(), mode))
+ throw FSError("chmod '" + _imp->path + "' failed: " + ::strerror(errno));
+}
+
+void
+FSPath::rename(const FSPath & new_name) const
+{
+ if (0 != std::rename(_imp->path.c_str(), new_name._imp->path.c_str()))
+ throw FSError("rename('" + stringify(_imp->path) + "', '" + stringify(new_name._imp->path) + "') failed: " +
+ ::strerror(errno));
+}
+
+bool
+FSPathComparator::operator() (const FSPath & a, const FSPath & b) const
+{
+ return stringify(a) < stringify(b);
+}
+
+template class Sequence<FSPath>;
+template class WrappedForwardIterator<Sequence<FSPath>::ConstIteratorTag, const FSPath>;
+template class WrappedForwardIterator<Sequence<FSPath>::ReverseConstIteratorTag, const FSPath>;
+template class WrappedOutputIterator<Sequence<FSPath>::InserterTag, FSPath>;
+
+template class Set<FSPath, FSPathComparator>;
+template class WrappedForwardIterator<Set<FSPath, FSPathComparator>::ConstIteratorTag, const FSPath>;
+
+template class Pimp<FSPath>;
+
diff --git a/paludis/util/fs_path.hh b/paludis/util/fs_path.hh
new file mode 100644
index 0000000..6147c14
--- /dev/null
+++ b/paludis/util/fs_path.hh
@@ -0,0 +1,194 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh
+ * Copyright (c) 2006 Mark Loeser
+ * Copyright (c) 2008 Fernando J. Pereda
+ *
+ * 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_FS_PATH_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_FS_PATH_HH 1
+
+#include <paludis/util/fs_path-fwd.hh>
+#include <paludis/util/fs_stat-fwd.hh>
+#include <paludis/util/timestamp-fwd.hh>
+#include <paludis/util/pimp.hh>
+#include <sys/stat.h>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE FSPath :
+ private Pimp<FSPath>
+ {
+ friend std::ostream & paludis::operator<< (std::ostream & s, const FSPath & f);
+ friend bool operator== (const FSPath &, const FSPath &);
+
+ private:
+ void _normalise();
+
+ public:
+ explicit FSPath(const std::string &);
+
+ FSPath(const FSPath &);
+
+ FSPath & operator= (const FSPath &);
+
+ ~FSPath();
+
+ FSStat stat() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ FSPath operator/ (const std::string &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ FSPath operator/ (const FSPath &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ FSPath & operator/= (const std::string &);
+ FSPath & operator/= (const FSPath &);
+
+ /**
+ * Return the last part of our path (eg '/foo/bar' => 'bar').
+ */
+ const std::string basename() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return the first part of our path (eg '/foo/bar' => '/foo').
+ */
+ FSPath dirname() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return the canonicalised version of our path.
+ */
+ FSPath realpath() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return the canonicalised version of our path, if it exists, or
+ * ourself if it doesn't.
+ */
+ FSPath realpath_if_exists() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return the path without a given prefix (eg '/foo/bar/baz'->strip_leading('/foo') => '/bar/baz').
+ */
+ FSPath strip_leading(const FSPath & prefix) const;
+
+ /**
+ * Try to make a directory.
+ *
+ * \return True, if we succeeded, and false if the directory
+ * already exists and is a directory and options includes
+ * fspmkdo_ok_if_exists.
+ *
+ * \exception FSError If an error other than the directory already
+ * existing occurs, or if the directory already exists and
+ * options does not include fspmkdo_ok_if_exists.
+ */
+ bool mkdir(const mode_t mode, const FSPathMkdirOptions &) const;
+
+ /**
+ * Try to make a symlink.
+ *
+ * \return True, if we succeeded, and false if the target already
+ * exists and is a symlink to the same target.
+ *
+ * \exception FSError If an error other than the symlink already
+ * existing occurs, or if the symlink exists and points elsewhere.
+ */
+ bool symlink(const std::string & target) const;
+
+ /**
+ * Try to unlink.
+ *
+ * \return True, if we succeeded, and false if we don't exist
+ * already.
+ *
+ * \exception FSError If an error other than us already not
+ * existing occurs.
+ */
+ bool unlink() const;
+
+ /**
+ * Try to rmdir.
+ *
+ * \return True, if we succeeded, and false if we don't exist
+ * already.
+ *
+ * \exception FSError If an error other than us already not
+ * existing occurs.
+ */
+ bool rmdir() const;
+
+ /**
+ * Change our ownership, following symlinks.
+ *
+ * \exception FSError If the chown failed.
+ */
+ void chown(const uid_t owner, const gid_t group) const;
+
+ /**
+ * Change our ownership, not following symlinks.
+ *
+ * \exception FSError If the lchown failed.
+ */
+ void lchown(const uid_t owner, const gid_t group) const;
+
+ /**
+ * Change our permissions.
+ *
+ * \exception FSError If the chmod failed.
+ */
+ void chmod(const mode_t mode) const;
+
+ /**
+ * Try to set atime and mtime
+ *
+ * \return True, if we succeeded, and false if we don't exist
+ * already.
+ *
+ * \exception FSError If an error other than us already not
+ * existing ocurrs.
+ */
+ bool utime(const Timestamp &) const;
+
+ /**
+ * Return our destination, if we are a symlink.
+ *
+ * \exception FSError if we are not a symlink, or if the system call
+ * fails.
+ */
+ std::string readlink() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Rename ourself (will not work across mount points).
+ *
+ * \exception FSError If the rename failed.
+ */
+ void rename(const FSPath & new_name) const;
+
+ /**
+ * Return the current working directory
+ */
+ static FSPath cwd() PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ class PALUDIS_VISIBLE FSPathComparator
+ {
+ public:
+ bool operator() (const FSPath &, const FSPath &) const;
+ };
+
+ extern template class Pimp<FSPath>;
+}
+
+#endif
diff --git a/paludis/util/fs_path.se b/paludis/util/fs_path.se
new file mode 100644
index 0000000..22cf4f0
--- /dev/null
+++ b/paludis/util/fs_path.se
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+# vim: set sw=4 sts=4 et ft=sh :
+
+make_enum_FSPathMkdirOption()
+{
+ prefix fspmkdo
+
+ key fspmkdo_ok_if_exists "It's ok if we already exist and are a directory"
+
+ doxygen_comment << "END"
+ /**
+ * Options for FSPath::mkdir.
+ *
+ * \see FSPath::mkdir
+ * \see FSPathMkdirOptions
+ * \ingroup g_fs
+ */
+END
+}
diff --git a/paludis/util/fs_path_TEST.cc b/paludis/util/fs_path_TEST.cc
new file mode 100644
index 0000000..9cae029
--- /dev/null
+++ b/paludis/util/fs_path_TEST.cc
@@ -0,0 +1,152 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh
+ * Copyright (c) 2006 Mark Loeser
+ *
+ * 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/fs_path.hh>
+#include <paludis/util/fs_error.hh>
+#include <paludis/util/timestamp.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <ctime>
+
+using namespace paludis;
+using namespace test;
+
+namespace test_cases
+{
+ struct FSPathManipulationTest : TestCase
+ {
+ FSPathManipulationTest() : TestCase("construction and manipulation") { }
+
+ void run()
+ {
+ FSPath f("/foo/bar");
+ FSPath c(f);
+ TEST_CHECK_EQUAL(f, FSPath("/foo/bar"));
+ TEST_CHECK_EQUAL(c, FSPath("/foo/bar"));
+ f = FSPath("/baz");
+ TEST_CHECK_EQUAL(f, FSPath("/baz"));
+ TEST_CHECK_EQUAL(c, FSPath("/foo/bar"));
+ c /= "moo";
+ TEST_CHECK_EQUAL(f, FSPath("/baz"));
+ TEST_CHECK_EQUAL(c, FSPath("/foo/bar/moo"));
+ f = c / f;
+ TEST_CHECK_EQUAL(f, FSPath("/foo/bar/moo/baz"));
+ TEST_CHECK_EQUAL(c, FSPath("/foo/bar/moo"));
+
+ f = FSPath::cwd();
+
+ TEST_CHECK_EQUAL(f, f / FSPath("/"));
+ }
+ } test_fs_path_manipulation;
+
+ struct FSPathRealpathTest : TestCase
+ {
+ FSPathRealpathTest() : TestCase("realpath") { }
+
+ void run()
+ {
+ FSPath f("fs_path_TEST_dir/symlink_to_dir_a/file_in_a");
+ FSPath r(f.realpath());
+ std::string g("fs_path_TEST_dir/dir_a/file_in_a");
+ TEST_CHECK_EQUAL(stringify(r).substr(stringify(r).length() - g.length()), g);
+ }
+ } test_fs_path_realpath;
+
+ struct FSPathSymlink : TestCase
+ {
+ FSPathSymlink() : TestCase("symlink") {}
+
+ void run()
+ {
+ FSPath f("fs_path_TEST_dir/new_sym");
+ TEST_CHECK(f.symlink("the_target"));
+ TEST_CHECK_EQUAL(f.readlink(), "the_target");
+ f.unlink();
+ }
+ } test_fs_symlink;
+
+ struct FSPathBaseDirName : TestCase
+ {
+ FSPathBaseDirName() : TestCase("basename and dirname") {}
+
+ void run()
+ {
+ FSPath a("/foo/bar");
+ FSPath b("/moo/went/the/cow");
+ FSPath c("/");
+ FSPath d(".");
+ FSPath e("..");
+
+ TEST_CHECK(a.basename() == "bar");
+ TEST_CHECK(stringify(a.dirname()) == "/foo");
+ TEST_CHECK(b.basename() == "cow");
+ TEST_CHECK(stringify(b.dirname()) == "/moo/went/the");
+ TEST_CHECK(c.basename() == "/");
+ TEST_CHECK(stringify(c.dirname()) == "/");
+ TEST_CHECK(d.basename() == ".");
+ TEST_CHECK(stringify(d.dirname()) == ".");
+ TEST_CHECK(e.basename() == "..");
+ TEST_CHECK(stringify(e.dirname()) == "..");
+ }
+ } test_fs_path_dir_base_name;
+
+ struct FSPathStripLeading : TestCase
+ {
+ FSPathStripLeading() : TestCase("strip_leading") {}
+
+ void run()
+ {
+ FSPath root1("/stairway/to/heaven/");
+ FSPath root2("");
+ FSPath root3("/");
+
+ FSPath a(root1);
+ FSPath b(root1 / "usr" / "share");
+ FSPath c(root2 / "my" / "directory");
+ FSPath d(root3 / "my" / "directory");
+
+ TEST_CHECK(stringify(a.strip_leading(root1)) == "/");
+ TEST_CHECK(stringify(b.strip_leading(root1)) == "/usr/share");
+ TEST_CHECK(stringify(c.strip_leading(root2)) == "/my/directory");
+ TEST_CHECK(stringify(d.strip_leading(root3)) == "/my/directory");
+ }
+ } test_fs_path_strip_leading;
+
+ struct FSPathToOstreamOperator : TestCase
+ {
+ FSPathToOstreamOperator() : TestCase("operator<<") {}
+
+ void run()
+ {
+ std::string n("fs_path_TEST_dir/no_perms");
+ std::ostringstream s;
+ FSPath a(n);
+
+ s << a;
+
+ TEST_CHECK_EQUAL(s.str(), n);
+ }
+ } test_fs_path_to_ostream_operator;
+}
+
diff --git a/paludis/util/fs_entry_TEST_cleanup.sh b/paludis/util/fs_path_TEST_cleanup.sh
index ed04a55..129b846 100755
--- a/paludis/util/fs_entry_TEST_cleanup.sh
+++ b/paludis/util/fs_path_TEST_cleanup.sh
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
# vim: set ft=sh sw=4 sts=4 et :
-if [ -d fs_entry_TEST_dir ] ; then
- rm -fr fs_entry_TEST_dir
+if [ -d fs_path_TEST_dir ] ; then
+ rm -fr fs_path_TEST_dir
else
true
fi
diff --git a/paludis/util/fs_entry_TEST_setup.sh b/paludis/util/fs_path_TEST_setup.sh
index 64134bf..f54d01d 100755
--- a/paludis/util/fs_entry_TEST_setup.sh
+++ b/paludis/util/fs_path_TEST_setup.sh
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
# vim: set ft=sh sw=4 sts=4 et :
-mkdir fs_entry_TEST_dir || exit 2
-cd fs_entry_TEST_dir || exit 3
+mkdir fs_path_TEST_dir || exit 2
+cd fs_path_TEST_dir || exit 3
mkdir dir_a || exit 4
ln -s dir_a symlink_to_dir_a || exit 5
ln -s doesnotexist doesnotexist_symlink || exit 5
diff --git a/paludis/util/fs_stat-fwd.hh b/paludis/util/fs_stat-fwd.hh
new file mode 100644
index 0000000..ba2c949
--- /dev/null
+++ b/paludis/util/fs_stat-fwd.hh
@@ -0,0 +1,28 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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_FS_STAT_FWD_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_FS_STAT_FWD_HH 1
+
+namespace paludis
+{
+ struct FSStat;
+}
+
+#endif
diff --git a/paludis/util/fs_stat.cc b/paludis/util/fs_stat.cc
new file mode 100644
index 0000000..4c9aff3
--- /dev/null
+++ b/paludis/util/fs_stat.cc
@@ -0,0 +1,197 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2010 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/fs_stat.hh>
+#include <paludis/util/fs_error.hh>
+#include <paludis/util/fs_path.hh>
+#include <paludis/util/pimp-impl.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/timestamp.hh>
+
+#include <string>
+#include <cerrno>
+#include <cstring>
+
+using namespace paludis;
+
+namespace paludis
+{
+ template <>
+ struct Imp<FSStat>
+ {
+ FSPath path;
+ bool exists;
+ struct stat st;
+
+ Imp(const FSPath & p, bool x, const struct stat & s) :
+ path(p),
+ exists(x),
+ st(s)
+ {
+ }
+
+ Imp(const FSPath & p) :
+ path(p),
+ exists(false)
+ {
+ if (0 != lstat(stringify(p).c_str(), &st))
+ {
+ if (errno != ENOENT && errno != ENOTDIR)
+ throw FSError("Error running stat() on '" + stringify(p) + "': " + strerror(errno));
+ }
+ else
+ exists = true;
+ }
+ };
+}
+
+
+FSStat::FSStat(const FSPath & p) :
+ Pimp<FSStat>(p)
+{
+}
+
+FSStat::FSStat(const FSStat & p) :
+ Pimp<FSStat>(p._imp->path, p._imp->exists, p._imp->st)
+{
+}
+
+FSStat &
+FSStat::operator= (const FSStat & p)
+{
+ if (&p != this)
+ {
+ _imp->exists = p._imp->exists;
+ _imp->st = p._imp->st;
+ }
+ return *this;
+}
+
+FSStat::~FSStat() = default;
+
+bool
+FSStat::exists() const
+{
+ return _imp->exists;
+}
+
+bool
+FSStat::is_regular_file() const
+{
+ return _imp->exists && S_ISREG(_imp->st.st_mode);
+}
+
+bool
+FSStat::is_regular_file_or_symlink_to_regular_file() const
+{
+ return _imp->exists && (S_ISREG(_imp->st.st_mode) || (is_symlink() && _imp->path.realpath_if_exists().stat().is_regular_file()));
+}
+
+bool
+FSStat::is_directory() const
+{
+ return _imp->exists && S_ISDIR(_imp->st.st_mode);
+}
+
+bool
+FSStat::is_directory_or_symlink_to_directory() const
+{
+ return _imp->exists && (S_ISDIR(_imp->st.st_mode) || (is_symlink() && _imp->path.realpath_if_exists().stat().is_directory()));
+}
+
+bool
+FSStat::is_symlink() const
+{
+ return _imp->exists && (S_ISLNK(_imp->st.st_mode));
+}
+
+uid_t
+FSStat::owner() const
+{
+ if (! _imp->exists)
+ throw FSError("Filesystem entry '" + stringify(_imp->path) + "' does not exist");
+ return _imp->st.st_uid;
+}
+
+gid_t
+FSStat::group() const
+{
+ if (! _imp->exists)
+ throw FSError("Filesystem entry '" + stringify(_imp->path) + "' does not exist");
+ return _imp->st.st_gid;
+}
+
+Timestamp
+FSStat::ctim() const
+{
+ if (! _imp->exists)
+ {
+ Context context("When fetching ctime of '" + stringify(_imp->path) + "':");
+ throw FSError("Filesystem entry '" + stringify(_imp->path) + "' does not exist");
+ }
+
+ return Timestamp(_imp->st.st_ctim);
+}
+
+Timestamp
+FSStat::mtim() const
+{
+ if (! _imp->exists)
+ {
+ Context context("When fetching mtime of '" + stringify(_imp->path) + "':");
+ throw FSError("Filesystem entry '" + stringify(_imp->path) + "' does not exist");
+ }
+
+ return Timestamp(_imp->st.st_mtim);
+}
+
+mode_t
+FSStat::permissions() const
+{
+ Context context("When fetching permissions for '" + stringify(_imp->path) + "':");
+
+ if (! _imp->exists)
+ throw FSError("Filesystem entry '" + stringify(_imp->path) + "' does not exist");
+
+ return _imp->st.st_mode;
+}
+
+off_t
+FSStat::file_size() const
+{
+ if (! _imp->exists)
+ throw FSError("Filesystem entry '" + stringify(_imp->path) + "' does not exist");
+
+ if (! is_regular_file())
+ throw FSError("file_size called on non-regular file '" + stringify(_imp->path) + "'");
+
+ return _imp->st.st_size;
+}
+
+std::pair<dev_t, ino_t>
+FSStat::lowlevel_id() const
+{
+ if (! _imp->exists)
+ throw FSError("Filesystem entry '" + stringify(_imp->path) + "' does not exist");
+
+ return std::make_pair(_imp->st.st_dev, _imp->st.st_ino);
+}
+
+template class Pimp<FSStat>;
+
diff --git a/paludis/util/fs_stat.hh b/paludis/util/fs_stat.hh
new file mode 100644
index 0000000..328ca8e
--- /dev/null
+++ b/paludis/util/fs_stat.hh
@@ -0,0 +1,106 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh
+ * Copyright (c) 2006 Mark Loeser
+ * Copyright (c) 2008 Fernando J. Pereda
+ *
+ * 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_FS_STAT_HH
+#define PALUDIS_GUARD_PALUDIS_UTIL_FS_STAT_HH 1
+
+#include <paludis/util/fs_stat-fwd.hh>
+#include <paludis/util/fs_path-fwd.hh>
+#include <paludis/util/pimp.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/timestamp-fwd.hh>
+#include <utility>
+#include <sys/stat.h>
+
+namespace paludis
+{
+ class PALUDIS_VISIBLE FSStat :
+ private Pimp<FSStat>
+ {
+ public:
+ explicit FSStat(const FSPath &);
+
+ FSStat(const FSStat &);
+
+ FSStat & operator= (const FSStat &);
+
+ ~FSStat();
+
+ bool exists() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ bool is_regular_file() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ bool is_regular_file_or_symlink_to_regular_file() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ bool is_directory() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ bool is_directory_or_symlink_to_directory() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ bool is_symlink() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return the time the inode for the filesystem entry was last modified
+ *
+ * \exception FSError if there was a problem accessing the filesystem entry
+ */
+ Timestamp ctim() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return the time the filesystem entry was last modified
+ *
+ * \exception FSError if there was a problem accessing the filesystem entry
+ */
+ Timestamp mtim() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return the permissions for our item.
+ *
+ * \exception FSError if there was a problem accessing the filesystem entry
+ */
+ mode_t permissions() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return the size of our file, in bytes.
+ *
+ * \exception FSError if we don't have a size.
+ */
+ off_t file_size() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Fetch our owner.
+ *
+ * \exception FSError If we don't exist or the stat call fails.
+ */
+ uid_t owner() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Fetch our group.
+ *
+ * \exception FSError If we don't exist or the stat call fails.
+ */
+ gid_t group() const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /**
+ * Return an unique low-level id for this entry
+ */
+ std::pair<dev_t, ino_t> lowlevel_id() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+
+ extern template class Pimp<FSStat>;
+}
+
+#endif
diff --git a/paludis/util/fs_stat_TEST.cc b/paludis/util/fs_stat_TEST.cc
new file mode 100644
index 0000000..f7d5d89
--- /dev/null
+++ b/paludis/util/fs_stat_TEST.cc
@@ -0,0 +1,299 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010 Ciaran McCreesh
+ * Copyright (c) 2006 Mark Loeser
+ *
+ * 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/fs_path.hh>
+#include <paludis/util/fs_error.hh>
+#include <paludis/util/fs_stat.hh>
+#include <paludis/util/log.hh>
+#include <paludis/util/timestamp.hh>
+#include <paludis/util/options.hh>
+#include <test/test_framework.hh>
+#include <test/test_runner.hh>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <ctime>
+
+using namespace paludis;
+using namespace test;
+
+namespace test_cases
+{
+ struct FSPathTime : TestCase
+ {
+ FSPathTime() : TestCase("ctime and mtime") {}
+
+ bool repeatable() const
+ {
+ return false;
+ }
+
+ void run()
+ {
+ FSPath a("fs_stat_TEST_dir");
+ FSPath b("fs_stat_TEST_dir/no_perms");
+ FSPath c("fs_stat_TEST_dir/no_such_file");
+ FSPath d("fs_stat_TEST_dir/dir_a/dir_in_a");
+
+ FSStat a_stat(a);
+ FSStat b_stat(b);
+ FSStat c_stat(c);
+ FSStat d_stat(d);
+
+#if !defined(__FreeBSD__)
+ TEST_CHECK(a_stat.ctim() < Timestamp::now());
+ TEST_CHECK(a_stat.mtim() < Timestamp::now());
+#endif
+ TEST_CHECK(b_stat.ctim() < Timestamp::now());
+ TEST_CHECK(b_stat.mtim() < Timestamp::now());
+ TEST_CHECK(d_stat.ctim() < Timestamp::now());
+ TEST_CHECK(d_stat.mtim() < Timestamp::now());
+
+ TEST_CHECK_THROWS(Timestamp PALUDIS_ATTRIBUTE((unused)) x = c_stat.ctim(), FSError);
+ TEST_CHECK_THROWS(Timestamp PALUDIS_ATTRIBUTE((unused)) x = c_stat.mtim(), FSError);
+
+ TEST_CHECK(b_stat.mtim() < b_stat.ctim());
+ TEST_CHECK(d_stat.mtim() == d_stat.ctim());
+ }
+ } test_fs_stat_time;
+
+ struct FSPathManipulationTest : TestCase
+ {
+ FSPathManipulationTest() : TestCase("construction and manipulation") { }
+
+ void run()
+ {
+ FSPath f("/foo/bar");
+ FSPath c(f);
+ TEST_CHECK_EQUAL(f, FSPath("/foo/bar"));
+ TEST_CHECK_EQUAL(c, FSPath("/foo/bar"));
+ f = FSPath("/baz");
+ TEST_CHECK_EQUAL(f, FSPath("/baz"));
+ TEST_CHECK_EQUAL(c, FSPath("/foo/bar"));
+ c /= "moo";
+ TEST_CHECK_EQUAL(f, FSPath("/baz"));
+ TEST_CHECK_EQUAL(c, FSPath("/foo/bar/moo"));
+ f = c / f;
+ TEST_CHECK_EQUAL(f, FSPath("/foo/bar/moo/baz"));
+ TEST_CHECK_EQUAL(c, FSPath("/foo/bar/moo"));
+
+ f = FSPath::cwd();
+
+ TEST_CHECK_EQUAL(f, f / FSPath("/"));
+ }
+ } test_fs_stat_manipulation;
+
+ struct FSPathRealpathTest : TestCase
+ {
+ FSPathRealpathTest() : TestCase("behavior") { }
+
+ bool repeatable() const
+ {
+ return false;
+ }
+
+ void run()
+ {
+ FSPath d("fs_stat_TEST_dir");
+ TEST_CHECK(d.stat().is_directory());
+
+ d /= "all_perms";
+ TEST_CHECK(d.stat().is_regular_file());
+
+ FSPath e("fs_stat_TEST_dir/nosuchfile");
+ TEST_CHECK(! e.stat().is_regular_file());
+ d = e;
+ TEST_CHECK(! d.stat().is_regular_file());
+ TEST_CHECK(! d.stat().exists());
+ TEST_CHECK_THROWS(e.readlink(), FSError);
+
+ d = FSPath("fs_stat_TEST_dir/all_perms");
+ TEST_CHECK(! e.stat().is_regular_file());
+ TEST_CHECK(d.stat().is_regular_file());
+ TEST_CHECK(d.stat().exists());
+
+ d = FSPath("fs_stat_TEST_dir/symlink_to_dir_a");
+ TEST_CHECK(d.stat().is_symlink());
+ TEST_CHECK(! d.stat().is_directory());
+ TEST_CHECK(d.stat().is_directory_or_symlink_to_directory());
+ TEST_CHECK(! d.stat().is_regular_file());
+ TEST_CHECK(! d.stat().is_regular_file_or_symlink_to_regular_file());
+
+ e = FSPath("fs_stat_TEST_dir/doesnotexist_symlink");
+ TEST_CHECK(e.stat().is_symlink());
+ TEST_CHECK(e.stat().exists());
+ TEST_CHECK(! e.stat().is_directory());
+ TEST_CHECK(! e.stat().is_directory_or_symlink_to_directory());
+ TEST_CHECK(! e.stat().is_regular_file());
+ TEST_CHECK(! e.stat().is_regular_file_or_symlink_to_regular_file());
+
+ FSPath f("fs_stat_TEST_dir/symlink_to_dir_a/file_in_a");
+ TEST_CHECK(f.stat().is_regular_file());
+ TEST_CHECK(! f.stat().is_symlink());
+ FSPath r(f.realpath());
+ TEST_CHECK(r.stat().is_regular_file());
+ std::string g("fs_stat_TEST_dir/dir_a/file_in_a");
+ TEST_CHECK_EQUAL(stringify(r).substr(stringify(r).length() - g.length()), g);
+
+ FSPath h("fs_stat_TEST_dir/symlink_to_file_in_a");
+ TEST_CHECK(h.stat().is_symlink());
+ TEST_CHECK(! h.stat().is_regular_file());
+ TEST_CHECK(h.stat().is_regular_file_or_symlink_to_regular_file());
+ TEST_CHECK_EQUAL(h.readlink(), "dir_a/file_in_a");
+
+ FSPath i("fs_stat_TEST_dir/dir_to_make");
+ TEST_CHECK(i.mkdir(0755, { fspmkdo_ok_if_exists }));
+ TEST_CHECK(! i.mkdir(0755, { fspmkdo_ok_if_exists }));
+ TEST_CHECK(i.rmdir());
+ FSPath j("fs_stat_TEST_dir/dir_to_make");
+ TEST_CHECK(! j.stat().exists());
+ TEST_CHECK(! j.stat().is_directory());
+
+ FSPath k("fs_stat_TEST_dir/dir_a/file_in_a");
+ TEST_CHECK_THROWS(k.mkdir(0755, { fspmkdo_ok_if_exists }), FSError);
+
+ FSPath l("fs_stat_TEST_dir/file_a/file_that_triggers_ENOTDIR");
+ TEST_CHECK(! l.stat().exists());
+ }
+ } test_fs_stat_behaviour;
+
+ struct FSPathFileSize : TestCase
+ {
+ FSPathFileSize() : TestCase("file size") {}
+
+ void run()
+ {
+ FSPath f("fs_stat_TEST_dir/ten_bytes");
+ FSPath d("fs_stat_TEST_dir/dir_a");
+ FSPath e("fs_stat_TEST_dir/no_such_file");
+
+ TEST_CHECK_EQUAL(f.stat().file_size(), 10);
+ TEST_CHECK_THROWS(size_t PALUDIS_ATTRIBUTE((unused)) x = d.stat().file_size(), FSError);
+ TEST_CHECK_THROWS(size_t PALUDIS_ATTRIBUTE((unused)) x = e.stat().file_size(), FSError);
+ }
+ } test_fs_stat_size;
+
+ struct FSPathSymlink : TestCase
+ {
+ FSPathSymlink() : TestCase("symlink") {}
+
+ void run()
+ {
+ FSPath f("fs_stat_TEST_dir/new_sym");
+ TEST_CHECK(f.symlink("the_target"));
+ TEST_CHECK(f.stat().is_symlink());
+ TEST_CHECK_EQUAL(f.readlink(), "the_target");
+ f.unlink();
+ }
+ } test_fs_symlink;
+
+ struct FSPathChangePerms : TestCase
+ {
+ FSPathChangePerms() : TestCase("chmod, chown and permissions") {}
+
+ void run()
+ {
+ FSPath a("fs_stat_TEST_dir/no_perms");
+
+ uid_t my_uid = geteuid();
+ a.chown(my_uid, -1);
+ TEST_CHECK_EQUAL(a.stat().owner(), my_uid);
+
+ mode_t all_perms(S_IRUSR | S_IWUSR | S_IXUSR |
+ S_IRGRP | S_IWGRP | S_IXGRP |
+ S_IROTH | S_IWOTH | S_IXOTH);
+ a.chmod(all_perms);
+
+ FSPath b("fs_stat_TEST_dir/no_perms");
+
+ TEST_CHECK_EQUAL(static_cast<mode_t>(b.stat().permissions() & 0xFFF), all_perms);
+
+ mode_t no_perms(0);
+ b.chmod(no_perms);
+
+ FSPath c("fs_stat_TEST_dir/no_perms");
+ TEST_CHECK_EQUAL(static_cast<mode_t>(c.stat().permissions() & 0xFFF), no_perms);
+
+ FSPath d("fs_stat_TEST_dir/i_dont_exist");
+
+ TEST_CHECK_THROWS(mode_t PALUDIS_ATTRIBUTE((unused)) x = d.stat().permissions(), FSError);
+ TEST_CHECK_THROWS(d.chmod(all_perms), FSError);
+ TEST_CHECK_THROWS(d.chown(static_cast<uid_t>(-1), -1), FSError);
+ TEST_CHECK_THROWS(uid_t PALUDIS_ATTRIBUTE((unused)) x = d.stat().owner(), FSError);
+ TEST_CHECK_THROWS(gid_t PALUDIS_ATTRIBUTE((unused)) x = d.stat().group(), FSError);
+
+ if (0 == my_uid)
+ {
+ struct passwd *pw = getpwent();
+
+ if (! pw)
+ throw InternalError(PALUDIS_HERE, "getpwent returned NULL");
+
+ std::string my_file("fs_stat_TEST_dir/all_perms");
+ FSPath e(my_file);
+
+ uid_t my_owner = e.stat().owner();
+ gid_t my_group = e.stat().group();
+
+ if (pw->pw_uid == my_owner)
+ {
+ pw = getpwent();
+
+ if (! pw)
+ throw InternalError(PALUDIS_HERE, "getpwent returned NULL");
+ }
+
+ uid_t new_owner(pw->pw_uid);
+
+ e.chown(new_owner, -1);
+
+ TEST_CHECK_EQUAL(FSPath(my_file).stat().owner(), new_owner);
+ TEST_CHECK_EQUAL(FSPath(my_file).stat().group(), my_group);
+
+ gid_t new_group(pw->pw_gid);
+
+ endpwent();
+
+ e.chown(static_cast<uid_t>(-1), new_group);
+
+ TEST_CHECK_EQUAL(FSPath(my_file).stat().owner(), new_owner);
+ TEST_CHECK_EQUAL(FSPath(my_file).stat().group(), new_group);
+
+ e.chown(static_cast<uid_t>(-1), -1);
+
+ TEST_CHECK_EQUAL(FSPath(my_file).stat().owner(), new_owner);
+ TEST_CHECK_EQUAL(FSPath(my_file).stat().group(), new_group);
+
+ e.chown(my_owner, my_group);
+
+ TEST_CHECK_EQUAL(FSPath(my_file).stat().owner(), my_owner);
+ TEST_CHECK_EQUAL(FSPath(my_file).stat().group(), my_group);
+ }
+ else
+ {
+ FSPath e("fs_stat_TEST_dir/all_perms");
+
+ TEST_CHECK_THROWS(e.chown(0, 0), FSError);
+ }
+ }
+ } test_fs_stat_change_perms;
+}
+
diff --git a/paludis/util/fs_stat_TEST_cleanup.sh b/paludis/util/fs_stat_TEST_cleanup.sh
new file mode 100755
index 0000000..57ce0ab
--- /dev/null
+++ b/paludis/util/fs_stat_TEST_cleanup.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+if [ -d fs_stat_TEST_dir ] ; then
+ rm -fr fs_stat_TEST_dir
+else
+ true
+fi
+
diff --git a/paludis/util/fs_stat_TEST_setup.sh b/paludis/util/fs_stat_TEST_setup.sh
new file mode 100755
index 0000000..98b29f4
--- /dev/null
+++ b/paludis/util/fs_stat_TEST_setup.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+# vim: set ft=sh sw=4 sts=4 et :
+
+mkdir fs_stat_TEST_dir || exit 2
+cd fs_stat_TEST_dir || exit 3
+mkdir dir_a || exit 4
+ln -s dir_a symlink_to_dir_a || exit 5
+ln -s doesnotexist doesnotexist_symlink || exit 5
+touch dir_a/file_in_a || exit 6
+
+touch all_perms || exit 7
+chmod 777 all_perms || exit 8
+touch no_perms || exit 9
+sleep 1
+chmod 000 no_perms || exit 10
+
+mkdir dir_a/dir_in_a
+
+touch file_a || exit 13
+
+echo -n '0123456789' > ten_bytes || exit 11
+ln -s dir_a/file_in_a symlink_to_file_in_a || exit 12
+sleep 1
diff --git a/paludis/util/hashes.cc b/paludis/util/hashes.cc
index 465e74c..67b55cd 100644
--- a/paludis/util/hashes.cc
+++ b/paludis/util/hashes.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2008 Ciaran McCreesh
+ * Copyright (c) 2008, 2010 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
@@ -18,7 +18,6 @@
*/
#include <paludis/util/hashes.hh>
-#include <paludis/util/fs_entry.hh>
#include <paludis/util/stringify.hh>
#include <string>
#include <functional>
@@ -32,7 +31,7 @@ Hash<std::string>::operator() (const std::string & s) const
}
std::size_t
-Hash<FSEntry>::operator() (const FSEntry & s) const
+Hash<FSPath>::operator() (const FSPath & s) const
{
return std::hash<std::string>()(stringify(s));
}
diff --git a/paludis/util/hashes.hh b/paludis/util/hashes.hh
index 5b1b0bf..c776819 100644
--- a/paludis/util/hashes.hh
+++ b/paludis/util/hashes.hh
@@ -22,7 +22,7 @@
#include <paludis/util/attributes.hh>
#include <paludis/util/wrapped_value-fwd.hh>
-#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/util/fs_path-fwd.hh>
#include <cstddef>
#include <utility>
#include <string>
@@ -69,9 +69,9 @@ namespace paludis
};
template <>
- struct PALUDIS_VISIBLE Hash<FSEntry>
+ struct PALUDIS_VISIBLE Hash<FSPath>
{
- std::size_t operator() (const FSEntry &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+ std::size_t operator() (const FSPath &) const PALUDIS_ATTRIBUTE((warn_unused_result));
};
template <typename T_, typename U_>
diff --git a/paludis/util/is_file_with_extension.cc b/paludis/util/is_file_with_extension.cc
index 12dffaf..0f1d4e1 100644
--- a/paludis/util/is_file_with_extension.cc
+++ b/paludis/util/is_file_with_extension.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2010 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
@@ -19,6 +19,9 @@
#include <paludis/util/is_file_with_extension.hh>
#include <paludis/util/stringify.hh>
+#include <paludis/util/fs_path.hh>
+#include <paludis/util/fs_stat.hh>
+#include <paludis/util/options.hh>
#include <ostream>
using namespace paludis;
@@ -26,13 +29,13 @@ using namespace paludis;
#include <paludis/util/is_file_with_extension-se.cc>
bool
-paludis::is_file_with_extension(const FSEntry & f, const std::string & s, const IsFileWithOptions & o)
+paludis::is_file_with_extension(const FSPath & f, const std::string & s, const IsFileWithOptions & o)
{
return is_file_with_prefix_extension(f, "", s, o);
}
bool
-paludis::is_file_with_prefix_extension(const FSEntry & f, const std::string & prefix,
+paludis::is_file_with_prefix_extension(const FSPath & f, const std::string & prefix,
const std::string & ext, const IsFileWithOptions & o)
{
const std::string filename(f.basename());
@@ -45,6 +48,7 @@ paludis::is_file_with_prefix_extension(const FSEntry & f, const std::string & pr
if (0 != filename.compare(0, prefix.length(), prefix))
return false;
- return f.is_regular_file() || ((! o[ifwo_no_follow_symlinks]) && f.exists() && f.realpath().is_regular_file());
+ FSStat f_stat(f);
+ return f_stat.is_regular_file() || ((! o[ifwo_no_follow_symlinks]) && f_stat.exists() && f.realpath().stat().is_regular_file());
}
diff --git a/paludis/util/is_file_with_extension.hh b/paludis/util/is_file_with_extension.hh
index ca5ded4..518a442 100644
--- a/paludis/util/is_file_with_extension.hh
+++ b/paludis/util/is_file_with_extension.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2006, 2007 Ciaran McCreesh
+ * Copyright (c) 2006, 2007, 2010 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,8 +20,10 @@
#ifndef PALUDIS_GUARD_PALUDIS_IS_FILE_WITH_EXTENSION_HH
#define PALUDIS_GUARD_PALUDIS_IS_FILE_WITH_EXTENSION_HH 1
-#include <paludis/util/fs_entry.hh>
-#include <paludis/util/options.hh>
+#include <paludis/util/fs_path-fwd.hh>
+#include <paludis/util/options-fwd.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/stringify.hh>
#include <functional>
#include <string>
@@ -51,23 +53,23 @@ namespace paludis
typedef Options<IsFileWithOption> IsFileWithOptions;
/**
- * Return whether an FSEntry is a file with a given extension.
+ * Return whether an FSPath is a file with a given extension.
*
* \see is_file_with_prefix_extension()
*
* \ingroup g_fs
*/
- bool is_file_with_extension(const FSEntry &, const std::string &, const IsFileWithOptions &) PALUDIS_VISIBLE;
+ bool is_file_with_extension(const FSPath &, const std::string &, const IsFileWithOptions &) PALUDIS_VISIBLE;
/**
- * Return whether an FSEntry is a file with a given prefix and a given
+ * Return whether an FSPath is a file with a given prefix and a given
* extension prefix.
*
* \see is_file_with_extension()
*
* \ingroup g_fs
*/
- bool is_file_with_prefix_extension(const FSEntry &, const std::string &, const std::string &, const IsFileWithOptions &) PALUDIS_VISIBLE;
+ bool is_file_with_prefix_extension(const FSPath &, const std::string &, const std::string &, const IsFileWithOptions &) PALUDIS_VISIBLE;
}
#endif
diff --git a/paludis/util/is_file_with_extension_TEST.cc b/paludis/util/is_file_with_extension_TEST.cc
index fc71ce2..a5e36af 100644
--- a/paludis/util/is_file_with_extension_TEST.cc
+++ b/paludis/util/is_file_with_extension_TEST.cc
@@ -19,6 +19,9 @@
#include <algorithm>
#include <paludis/util/is_file_with_extension.hh>
+#include <paludis/util/fs_path.hh>
+#include <paludis/util/fs_stat.hh>
+#include <paludis/util/options.hh>
#include <test/test_framework.hh>
#include <test/test_runner.hh>
#include <vector>
@@ -43,10 +46,10 @@ namespace test_cases
void run()
{
- FSEntry c("teh.foo");
- FSEntry d("is_file_with_extension_TEST_file.goat");
+ FSPath c("teh.foo");
+ FSPath d("is_file_with_extension_TEST_file.goat");
- TEST_CHECK(d.exists());
+ TEST_CHECK(d.stat().exists());
TEST_CHECK(! is_file_with_extension(c, "foo", { }));
TEST_CHECK(! is_file_with_extension(d, "foo", { }));
@@ -66,10 +69,10 @@ namespace test_cases
void run()
{
- FSEntry d("teh.foo");
- FSEntry e("is_file_with_extension_TEST_file.goat");
+ FSPath d("teh.foo");
+ FSPath e("is_file_with_extension_TEST_file.goat");
- TEST_CHECK(e.exists());
+ TEST_CHECK(e.stat().exists());
TEST_CHECK(! is_file_with_prefix_extension(d, "teh", "foo", { }));
TEST_CHECK(! is_file_with_prefix_extension(e, "teh", "foo", { }));
diff --git a/paludis/util/process.cc b/paludis/util/process.cc
index c61cb39..a48f1a6 100644
--- a/paludis/util/process.cc
+++ b/paludis/util/process.cc
@@ -22,7 +22,7 @@
#include <paludis/util/thread.hh>
#include <paludis/util/pipe.hh>
#include <paludis/util/pty.hh>
-#include <paludis/util/fs_entry.hh>
+#include <paludis/util/fs_path.hh>
#include <paludis/util/stringify.hh>
#include <paludis/util/safe_ofstream.hh>
#include <paludis/util/log.hh>
@@ -836,7 +836,7 @@ Process::clearenv()
}
Process &
-Process::chdir(const FSEntry & f)
+Process::chdir(const FSPath & f)
{
_imp->chdir = stringify(f.realpath_if_exists());
return *this;
diff --git a/paludis/util/process.hh b/paludis/util/process.hh
index daaf84d..ce3ad27 100644
--- a/paludis/util/process.hh
+++ b/paludis/util/process.hh
@@ -24,7 +24,7 @@
#include <paludis/util/attributes.hh>
#include <paludis/util/pimp.hh>
#include <paludis/util/exception.hh>
-#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/util/fs_path-fwd.hh>
#include <string>
#include <iosfwd>
@@ -95,7 +95,7 @@ namespace paludis
Process & setenv(const std::string &, const std::string &);
Process & clearenv();
- Process & chdir(const FSEntry &);
+ Process & chdir(const FSPath &);
Process & use_ptys();
Process & setuid_setgid(uid_t, gid_t);
Process & echo_command_to(std::ostream &);
diff --git a/paludis/util/process_TEST.cc b/paludis/util/process_TEST.cc
index 89ca85a..b14b49e 100644
--- a/paludis/util/process_TEST.cc
+++ b/paludis/util/process_TEST.cc
@@ -18,7 +18,7 @@
*/
#include <paludis/util/process.hh>
-#include <paludis/util/fs_entry.hh>
+#include <paludis/util/fs_path.hh>
#include <paludis/util/pipe.hh>
#include <paludis/util/safe_ofstream.hh>
#include <test/test_framework.hh>
@@ -207,7 +207,7 @@ namespace test_cases
std::stringstream stdout_stream;
Process pwd_process(ProcessCommand({"pwd"}));
pwd_process.capture_stdout(stdout_stream);
- pwd_process.chdir(FSEntry("/"));
+ pwd_process.chdir(FSPath("/"));
TEST_CHECK_EQUAL(pwd_process.run().wait(), 0);
TEST_CHECK_EQUAL(stdout_stream.str(), "/\n");
diff --git a/paludis/util/realpath.cc b/paludis/util/realpath.cc
index d69150d..101055b 100644
--- a/paludis/util/realpath.cc
+++ b/paludis/util/realpath.cc
@@ -18,29 +18,31 @@
*/
#include <paludis/util/realpath.hh>
-#include <paludis/util/fs_entry.hh>
+#include <paludis/util/fs_path.hh>
+#include <paludis/util/fs_stat.hh>
+#include <paludis/util/fs_error.hh>
#include <paludis/util/stringify.hh>
using namespace paludis;
namespace
{
- FSEntry
+ FSPath
do_realpath_with_current_and_root(
- const FSEntry & file, const FSEntry & current, const FSEntry & root,
- const FSEntry & orig_file, const FSEntry & orig_current, unsigned & symlinks)
+ const FSPath & file, const FSPath & current, const FSPath & root,
+ const FSPath & orig_file, const FSPath & orig_current, unsigned & symlinks)
{
if (symlinks >= 40)
throw FSError("Too many symlinks encountered while canonicalising '" + stringify(orig_file) +
"' relative to '" + stringify(orig_current) + "' with root '" + stringify(root) + "'");
- FSEntry cur(current);
+ FSPath cur(current);
std::string file_str(stringify(file));
if ('/' == file_str[0])
{
file_str.erase(0, 1);
- cur = FSEntry("/");
+ cur = FSPath("/");
}
while (! file_str.empty())
@@ -67,9 +69,9 @@ namespace
continue;
}
- FSEntry full(root / cur / component);
- if (full.is_symbolic_link())
- cur = do_realpath_with_current_and_root(FSEntry(full.readlink()), cur, root, orig_file, orig_current, ++symlinks);
+ FSPath full(root / cur / component);
+ if (full.stat().is_symlink())
+ cur = do_realpath_with_current_and_root(FSPath(full.readlink()), cur, root, orig_file, orig_current, ++symlinks);
else
cur = cur / component;
}
@@ -78,18 +80,18 @@ namespace
}
}
-FSEntry
-paludis::realpath_with_current_and_root(const FSEntry & file, const FSEntry & current, const FSEntry & root)
+FSPath
+paludis::realpath_with_current_and_root(const FSPath & file, const FSPath & current, const FSPath & root)
{
unsigned symlinks(0);
return do_realpath_with_current_and_root(file, current, root, file, current, symlinks);
}
-FSEntry
-paludis::dereference_with_root(const FSEntry & file, const FSEntry & root)
+FSPath
+paludis::dereference_with_root(const FSPath & file, const FSPath & root)
{
- if (file.is_symbolic_link())
- return root / realpath_with_current_and_root(FSEntry(file.readlink()), file.dirname().strip_leading(root), root);
+ if (file.stat().is_symlink())
+ return root / realpath_with_current_and_root(FSPath(file.readlink()), file.dirname().strip_leading(root), root);
else
return file;
}
diff --git a/paludis/util/realpath.hh b/paludis/util/realpath.hh
index 3961c9d..5e9a723 100644
--- a/paludis/util/realpath.hh
+++ b/paludis/util/realpath.hh
@@ -21,14 +21,14 @@
#define PALUDIS_GUARD_PALUDIS_UTIL_REALPATH_HH
#include <paludis/util/attributes.hh>
-#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/util/fs_path-fwd.hh>
namespace paludis
{
- FSEntry realpath_with_current_and_root(
- const FSEntry &, const FSEntry &, const FSEntry &) PALUDIS_ATTRIBUTE((warn_unused_result)) PALUDIS_VISIBLE;
+ FSPath realpath_with_current_and_root(
+ const FSPath &, const FSPath &, const FSPath &) PALUDIS_ATTRIBUTE((warn_unused_result)) PALUDIS_VISIBLE;
- FSEntry dereference_with_root(const FSEntry &, const FSEntry &) PALUDIS_ATTRIBUTE((warn_unused_result)) PALUDIS_VISIBLE;
+ FSPath dereference_with_root(const FSPath &, const FSPath &) PALUDIS_ATTRIBUTE((warn_unused_result)) PALUDIS_VISIBLE;
}
#endif
diff --git a/paludis/util/realpath_TEST.cc b/paludis/util/realpath_TEST.cc
index 46a33d5..6f573ba 100644
--- a/paludis/util/realpath_TEST.cc
+++ b/paludis/util/realpath_TEST.cc
@@ -18,7 +18,8 @@
*/
#include <paludis/util/realpath.hh>
-#include <paludis/util/fs_entry.hh>
+#include <paludis/util/fs_path.hh>
+#include <paludis/util/fs_error.hh>
#include <test/test_runner.hh>
#include <test/test_framework.hh>
@@ -32,35 +33,35 @@ namespace test_cases
{
RealpathWithCurrentAndRootTest() : TestCase("realpath_with_current_and_root") {}
- FSEntry resolve(const FSEntry & symlink, const FSEntry & root)
+ FSPath resolve(const FSPath & symlink, const FSPath & root)
{
- return realpath_with_current_and_root(FSEntry((root / symlink).readlink()), symlink.dirname(), root);
+ return realpath_with_current_and_root(FSPath((root / symlink).readlink()), symlink.dirname(), root);
}
void run()
{
- FSEntry root("realpath_TEST_dir");
+ FSPath root("realpath_TEST_dir");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libfoo.so"), root), "/usr/lib64/libfoo.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libbar.so"), root), "/usr/lib64/libbar.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libbaz.so"), root), "/usr/lib64/libbaz.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libxyzzy.so"), root), "/usr/lib64/libxyzzy.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libplugh.so"), root), "/usr/lib64/libplugh.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libplover.so"), root), "/usr/lib64/libplover.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libblast.so"), root), "/usr/lib64/libblast.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libquux.so"), root), "/usr/lib64/libquux.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libnarf.so"), root), "/usr/lib64/libnarf.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libblech.so"), root), "/usr/lib64/libblech.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libstab.so"), root), "/usr/lib64/libstab.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libsnark.so"), root), "/usr/lib64/libsnark.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libfool.so"), root), "/usr/lib32/libfool.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libbarf.so"), root), "/usr/lib64/barf/libbarf.so.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libblip.so"), root), "/usr/lib64/libblip.so.1.0.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/libpoing.so"), root), "/usr/lib64/libpoing.so.1.0.1");
- TEST_CHECK_STRINGIFY_EQUAL(resolve(FSEntry("/usr/lib64/x/liby.so"), root), "/usr/lib64/x/liby.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libfoo.so"), root), "/usr/lib64/libfoo.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libbar.so"), root), "/usr/lib64/libbar.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libbaz.so"), root), "/usr/lib64/libbaz.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libxyzzy.so"), root), "/usr/lib64/libxyzzy.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libplugh.so"), root), "/usr/lib64/libplugh.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libplover.so"), root), "/usr/lib64/libplover.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libblast.so"), root), "/usr/lib64/libblast.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libquux.so"), root), "/usr/lib64/libquux.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libnarf.so"), root), "/usr/lib64/libnarf.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libblech.so"), root), "/usr/lib64/libblech.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libstab.so"), root), "/usr/lib64/libstab.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libsnark.so"), root), "/usr/lib64/libsnark.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libfool.so"), root), "/usr/lib32/libfool.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libbarf.so"), root), "/usr/lib64/barf/libbarf.so.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libblip.so"), root), "/usr/lib64/libblip.so.1.0.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/libpoing.so"), root), "/usr/lib64/libpoing.so.1.0.1");
+ TEST_CHECK_STRINGIFY_EQUAL(resolve(FSPath("/usr/lib64/x/liby.so"), root), "/usr/lib64/x/liby.so.1");
- TEST_CHECK_THROWS(resolve(FSEntry("/usr/lib64/libouch.so"), root),FSError);
- TEST_CHECK_THROWS(resolve(FSEntry("/usr/lib64/libping.so"), root),FSError);
+ TEST_CHECK_THROWS(resolve(FSPath("/usr/lib64/libouch.so"), root), FSError);
+ TEST_CHECK_THROWS(resolve(FSPath("/usr/lib64/libping.so"), root), FSError);
}
} realpath_with_current_and_root_test;
}
diff --git a/paludis/util/safe_ifstream.cc b/paludis/util/safe_ifstream.cc
index 62704ba..dce4eda 100644
--- a/paludis/util/safe_ifstream.cc
+++ b/paludis/util/safe_ifstream.cc
@@ -94,9 +94,16 @@ SafeIFStreamBase::SafeIFStreamBase(const int f) :
{
}
+SafeIFStream::SafeIFStream(const int f) :
+ SafeIFStreamBase(f),
+ std::istream(&buf),
+ _close(false)
+{
+}
+
namespace
{
- int open_fsentry(const FSEntry & e)
+ int open_path(const FSPath & e)
{
Context context("When opening '" + stringify(e) + "' for read:");
@@ -108,15 +115,8 @@ namespace
}
}
-SafeIFStream::SafeIFStream(const int f) :
- SafeIFStreamBase(f),
- std::istream(&buf),
- _close(false)
-{
-}
-
-SafeIFStream::SafeIFStream(const FSEntry & e) :
- SafeIFStreamBase(open_fsentry(e)),
+SafeIFStream::SafeIFStream(const FSPath & e) :
+ SafeIFStreamBase(open_path(e)),
std::istream(&buf),
_close(true)
{
@@ -133,4 +133,3 @@ SafeIFStreamError::SafeIFStreamError(const std::string & s) throw () :
{
}
-
diff --git a/paludis/util/safe_ifstream.hh b/paludis/util/safe_ifstream.hh
index f905292..70a6347 100644
--- a/paludis/util/safe_ifstream.hh
+++ b/paludis/util/safe_ifstream.hh
@@ -22,7 +22,7 @@
#include <paludis/util/attributes.hh>
#include <paludis/util/exception.hh>
-#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/util/fs_path-fwd.hh>
#include <istream>
/** \file
@@ -111,7 +111,7 @@ namespace paludis
///\{
explicit SafeIFStream(const int fd);
- explicit SafeIFStream(const FSEntry &);
+ explicit SafeIFStream(const FSPath &);
~SafeIFStream();
///\}
diff --git a/paludis/util/safe_ifstream_TEST.cc b/paludis/util/safe_ifstream_TEST.cc
index 8456b51..c22b1fd 100644
--- a/paludis/util/safe_ifstream_TEST.cc
+++ b/paludis/util/safe_ifstream_TEST.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2009 Ciaran McCreesh
+ * Copyright (c) 2009, 2010 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
@@ -18,7 +18,7 @@
*/
#include <paludis/util/safe_ifstream.hh>
-#include <paludis/util/fs_entry.hh>
+#include <paludis/util/fs_path.hh>
#include <test/test_runner.hh>
#include <test/test_framework.hh>
#include <unistd.h>
@@ -35,7 +35,7 @@ namespace test_cases
void run()
{
- SafeIFStream s(FSEntry::cwd() / "safe_ifstream_TEST_dir" / "existing");
+ SafeIFStream s(FSPath::cwd() / "safe_ifstream_TEST_dir" / "existing");
TEST_CHECK(s);
std::string t;
s >> t;
@@ -62,7 +62,7 @@ namespace test_cases
void run()
{
- SafeIFStream s(FSEntry::cwd() / "safe_ifstream_TEST_dir" / "existing");
+ SafeIFStream s(FSPath::cwd() / "safe_ifstream_TEST_dir" / "existing");
TEST_CHECK(s);
std::string t;
s >> t;
@@ -79,7 +79,7 @@ namespace test_cases
void run()
{
- TEST_CHECK_THROWS(SafeIFStream(FSEntry::cwd() / "safe_ifstream_TEST_dir" / "existing_dir"), SafeIFStreamError);
+ TEST_CHECK_THROWS(SafeIFStream(FSPath::cwd() / "safe_ifstream_TEST_dir" / "existing_dir"), SafeIFStreamError);
}
} test_existing_dir;
@@ -94,7 +94,7 @@ namespace test_cases
void run()
{
- TEST_CHECK_THROWS(SafeIFStream(FSEntry::cwd() / "safe_ifstream_TEST_dir" / "existing_perm"), SafeIFStreamError);
+ TEST_CHECK_THROWS(SafeIFStream(FSPath::cwd() / "safe_ifstream_TEST_dir" / "existing_perm"), SafeIFStreamError);
}
} test_existing_perm;
@@ -104,7 +104,7 @@ namespace test_cases
void run()
{
- TEST_CHECK_THROWS(SafeIFStream(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "noent"), SafeIFStreamError);
+ TEST_CHECK_THROWS(SafeIFStream(FSPath::cwd() / "safe_ofstream_TEST_dir" / "noent"), SafeIFStreamError);
}
} test_existing_noent;
}
diff --git a/paludis/util/safe_ofstream.cc b/paludis/util/safe_ofstream.cc
index 6f1c31d..4ebc117 100644
--- a/paludis/util/safe_ofstream.cc
+++ b/paludis/util/safe_ofstream.cc
@@ -56,9 +56,16 @@ SafeOFStreamBase::SafeOFStreamBase(const int f) :
{
}
+SafeOFStream::SafeOFStream(const int f) :
+ SafeOFStreamBase(f),
+ std::ostream(&buf),
+ _close(false)
+{
+}
+
namespace
{
- int check_open_fsentry(const FSEntry & e, int open_flags)
+ int check_open_path(const FSPath & e, int open_flags)
{
Context context("When opening '" + stringify(e) + "' for write:");
@@ -73,15 +80,8 @@ namespace
}
}
-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)),
+SafeOFStream::SafeOFStream(const FSPath & p, const int open_flags) :
+ SafeOFStreamBase(check_open_path(p, open_flags)),
std::ostream(&buf),
_close(true)
{
diff --git a/paludis/util/safe_ofstream.hh b/paludis/util/safe_ofstream.hh
index 543a94b..274ffe9 100644
--- a/paludis/util/safe_ofstream.hh
+++ b/paludis/util/safe_ofstream.hh
@@ -22,7 +22,7 @@
#include <paludis/util/attributes.hh>
#include <paludis/util/exception.hh>
-#include <paludis/util/fs_entry-fwd.hh>
+#include <paludis/util/fs_path-fwd.hh>
#include <ostream>
/** \file
@@ -109,7 +109,7 @@ namespace paludis
///\{
explicit SafeOFStream(const int fd);
- explicit SafeOFStream(const FSEntry &, const int open_flags = -1);
+ explicit SafeOFStream(const FSPath &, const int open_flags = -1);
~SafeOFStream();
///\}
diff --git a/paludis/util/safe_ofstream_TEST.cc b/paludis/util/safe_ofstream_TEST.cc
index 739d0f4..05c1fb7 100644
--- a/paludis/util/safe_ofstream_TEST.cc
+++ b/paludis/util/safe_ofstream_TEST.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2009 Ciaran McCreesh
+ * Copyright (c) 2009, 2010 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
@@ -18,7 +18,7 @@
*/
#include <paludis/util/safe_ofstream.hh>
-#include <paludis/util/fs_entry.hh>
+#include <paludis/util/fs_path.hh>
#include <test/test_runner.hh>
#include <test/test_framework.hh>
#include <unistd.h>
@@ -35,7 +35,7 @@ namespace test_cases
void run()
{
- SafeOFStream s(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "new");
+ SafeOFStream s(FSPath::cwd() / "safe_ofstream_TEST_dir" / "new");
TEST_CHECK(s);
s << "foo";
TEST_CHECK(s);
@@ -53,7 +53,7 @@ namespace test_cases
void run()
{
- SafeOFStream s(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "existing");
+ SafeOFStream s(FSPath::cwd() / "safe_ofstream_TEST_dir" / "existing");
TEST_CHECK(s);
s << "foo";
TEST_CHECK(s);
@@ -71,7 +71,7 @@ namespace test_cases
void run()
{
- SafeOFStream s(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "existing_sym");
+ SafeOFStream s(FSPath::cwd() / "safe_ofstream_TEST_dir" / "existing_sym");
TEST_CHECK(s);
s << "foo";
TEST_CHECK(s);
@@ -89,7 +89,7 @@ namespace test_cases
void run()
{
- TEST_CHECK_THROWS(SafeOFStream(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "existing_dir"), SafeOFStreamError);
+ TEST_CHECK_THROWS(SafeOFStream(FSPath::cwd() / "safe_ofstream_TEST_dir" / "existing_dir"), SafeOFStreamError);
}
bool repeatable() const
@@ -104,7 +104,7 @@ namespace test_cases
void run()
{
- TEST_CHECK_THROWS(SafeOFStream(FSEntry::cwd() / "safe_ofstream_TEST_dir" / "existing_perm"), SafeOFStreamError);
+ TEST_CHECK_THROWS(SafeOFStream(FSPath::cwd() / "safe_ofstream_TEST_dir" / "existing_perm"), SafeOFStreamError);
}
bool skip() const
@@ -127,7 +127,7 @@ namespace test_cases
bool threw(false);
try
{
- SafeOFStream s(FSEntry("/dev/full"));
+ SafeOFStream s(FSPath("/dev/full"));
TEST_CHECK(s);
s << "foo";
TEST_CHECK(! s);
diff --git a/paludis/util/system_TEST.cc b/paludis/util/system_TEST.cc
index 98012ef..95bbc12 100644
--- a/paludis/util/system_TEST.cc
+++ b/paludis/util/system_TEST.cc
@@ -18,7 +18,6 @@
*/
#include <paludis/util/system.hh>
-#include <paludis/util/fs_entry.hh>
#include <paludis/util/log.hh>
#include <paludis/util/thread_pool.hh>
#include <test/test_framework.hh>
diff --git a/paludis/util/wildcard_expander.cc b/paludis/util/wildcard_expander.cc
index bc5741c..9cbf131 100644
--- a/paludis/util/wildcard_expander.cc
+++ b/paludis/util/wildcard_expander.cc
@@ -20,7 +20,6 @@
#include <paludis/util/wildcard_expander.hh>
#include <paludis/util/exception.hh>
-#include <paludis/util/fs_entry.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/util/stringify.hh>
#include <memory>
@@ -37,16 +36,16 @@ namespace paludis
template <>
struct Imp<WildcardExpander>
{
- std::shared_ptr<std::vector<FSEntry> > files;
- std::vector<FSEntry>::const_iterator it;
+ std::shared_ptr<std::vector<FSPath> > files;
+ std::vector<FSPath>::const_iterator it;
Imp() :
- files(std::make_shared<std::vector<FSEntry>>())
+ files(std::make_shared<std::vector<FSPath>>())
{
}
- Imp(const std::shared_ptr<std::vector<FSEntry> > & the_files,
- std::vector<FSEntry>::const_iterator the_it) :
+ Imp(const std::shared_ptr<std::vector<FSPath> > & the_files,
+ std::vector<FSPath>::const_iterator the_it) :
files(the_files),
it(the_it)
{
@@ -107,7 +106,7 @@ namespace
}
}
-WildcardExpander::WildcardExpander(const std::string & pattern, const paludis::FSEntry & root) :
+WildcardExpander::WildcardExpander(const std::string & pattern, const FSPath & root) :
Pimp<WildcardExpander>()
{
// GLOB_NOCHECK seems to be buggy in glibc 2.5: fails
@@ -117,9 +116,9 @@ WildcardExpander::WildcardExpander(const std::string & pattern, const paludis::F
Glob g(stringify(root / pattern), 0);
if (0 < g->gl_pathc)
for (unsigned i = 0; i < g->gl_pathc; ++i)
- _imp->files->push_back(FSEntry(g->gl_pathv[i]).strip_leading(root));
+ _imp->files->push_back(FSPath(g->gl_pathv[i]).strip_leading(root));
else
- _imp->files->push_back(FSEntry("/") / pattern);
+ _imp->files->push_back(FSPath("/") / pattern);
_imp->it = _imp->files->begin();
}
@@ -147,13 +146,13 @@ WildcardExpander::operator= (const WildcardExpander & other)
return *this;
}
-const FSEntry &
+const FSPath &
WildcardExpander::operator* () const
{
return *_imp->it;
}
-const FSEntry *
+const FSPath *
WildcardExpander::operator-> () const
{
return &*_imp->it;
diff --git a/paludis/util/wildcard_expander.hh b/paludis/util/wildcard_expander.hh
index ad91297..e1b5ee0 100644
--- a/paludis/util/wildcard_expander.hh
+++ b/paludis/util/wildcard_expander.hh
@@ -21,7 +21,8 @@
#define PALUDIS_GUARD_PALUDIS_UTIL_WILDCARD_EXPANDER_HH
#include <paludis/util/attributes.hh>
-#include <paludis/util/fs_entry.hh>
+#include <paludis/util/fs_path.hh>
+#include <paludis/util/fs_error.hh>
#include <paludis/util/operators.hh>
#include <paludis/util/pimp.hh>
@@ -37,12 +38,12 @@ namespace paludis
};
class PALUDIS_VISIBLE WildcardExpander :
- public std::iterator<std::forward_iterator_tag, const FSEntry>,
+ public std::iterator<std::forward_iterator_tag, const FSPath>,
public equality_operators::HasEqualityOperators,
private Pimp<WildcardExpander>
{
public:
- WildcardExpander(const std::string &, const FSEntry & = FSEntry("/"));
+ WildcardExpander(const std::string &, const FSPath & = FSPath("/"));
WildcardExpander();
WildcardExpander(const WildcardExpander &);
@@ -50,8 +51,8 @@ namespace paludis
WildcardExpander & operator= (const WildcardExpander &);
- const FSEntry & operator* () const PALUDIS_ATTRIBUTE((warn_unused_result));
- const FSEntry * operator-> () const PALUDIS_ATTRIBUTE((warn_unused_result));
+ const FSPath & operator* () const PALUDIS_ATTRIBUTE((warn_unused_result));
+ const FSPath * operator-> () const PALUDIS_ATTRIBUTE((warn_unused_result));
WildcardExpander & operator++ ();
WildcardExpander operator++ (int);
diff --git a/paludis/util/wildcard_expander_TEST.cc b/paludis/util/wildcard_expander_TEST.cc
index 98327a6..0626f24 100644
--- a/paludis/util/wildcard_expander_TEST.cc
+++ b/paludis/util/wildcard_expander_TEST.cc
@@ -18,7 +18,7 @@
*/
#include <paludis/util/wildcard_expander.hh>
-#include <paludis/util/fs_entry.hh>
+#include <paludis/util/fs_path.hh>
#include <paludis/util/join.hh>
#include <test/test_runner.hh>
@@ -35,7 +35,7 @@ namespace test_cases
std::string expand(const std::string & pattern)
{
- return join(WildcardExpander(pattern, FSEntry::cwd() / "wildcard_expander_TEST_dir"),
+ return join(WildcardExpander(pattern, FSPath::cwd() / "wildcard_expander_TEST_dir"),
WildcardExpander(), " ");
}
@@ -57,7 +57,7 @@ namespace test_cases
void run()
{
- WildcardExpander it("/foo*bar", FSEntry::cwd() / "wildcard_expander_TEST_dir");
+ WildcardExpander it("/foo*bar", FSPath::cwd() / "wildcard_expander_TEST_dir");
TEST_CHECK(it == it);
TEST_CHECK(! (it != it));
TEST_CHECK(it != WildcardExpander());
@@ -92,7 +92,7 @@ namespace test_cases
TEST_CHECK(++it3 != WildcardExpander());
TEST_CHECK(++it3 == WildcardExpander());
- TEST_CHECK_EQUAL(join(WildcardExpander("/foo*bar", FSEntry::cwd() / "wildcard_expander_TEST_dir"),
+ TEST_CHECK_EQUAL(join(WildcardExpander("/foo*bar", FSPath::cwd() / "wildcard_expander_TEST_dir"),
WildcardExpander(), " "),
"/fooAbar /fooBbar /fooCbar /fooDbar /fooEbar");
}