diff options
-rw-r--r-- | libadhocutil/Jamfile.jam | 2 | ||||
-rw-r--r-- | libadhocutil/fileUtils.cpp | 59 | ||||
-rw-r--r-- | libadhocutil/fileUtils.h | 42 | ||||
-rw-r--r-- | libadhocutil/unittests/Jamfile.jam | 11 | ||||
-rw-r--r-- | libadhocutil/unittests/testFileUtils.cpp | 40 |
5 files changed, 154 insertions, 0 deletions
diff --git a/libadhocutil/Jamfile.jam b/libadhocutil/Jamfile.jam index b957347..e0504d2 100644 --- a/libadhocutil/Jamfile.jam +++ b/libadhocutil/Jamfile.jam @@ -2,6 +2,7 @@ import package ; import lex ; lib boost_system ; +lib boost_filesystem ; lib boost_thread ; lib Ice : ; lib IceUtil ; @@ -17,6 +18,7 @@ lib adhocutil : <include>. <library>iceall <library>boost_system + <library>boost_filesystem <library>boost_thread <library>curl <library>dl diff --git a/libadhocutil/fileUtils.cpp b/libadhocutil/fileUtils.cpp new file mode 100644 index 0000000..0cd3382 --- /dev/null +++ b/libadhocutil/fileUtils.cpp @@ -0,0 +1,59 @@ +#include "fileUtils.h" +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> + +namespace AdHoc { + namespace FileUtils { + boost::filesystem::path operator/(const boost::filesystem::path & p, unsigned int n) + { + auto pp = p.begin(); + while (n--) ++pp; + return *pp; + } + + FileHandle::FileHandle(const boost::filesystem::path & path) : + fh(open(path.c_str(), O_RDONLY)) + { + if (fh < 0) { + throw std::runtime_error("Failed to open " + path.string()); + } + } + + FileHandle::~FileHandle() + { + close(fh); + } + + FileHandleStat::FileHandleStat(const boost::filesystem::path & path) : + FileHandle(path) + { + if (fstat(fh, &st)) { + // LCOV_EXCL_START can't think of a way to test open succeeding and fstat failing + throw std::runtime_error("Failed to stat " + path.string()); + // LCOV_EXCL_STOP + } + } + + const struct stat & + FileHandleStat::getStat() const + { + return st; + } + + MemMap::MemMap(const boost::filesystem::path & path) : + FileHandleStat(path), + data(mmap(0, st.st_size, PROT_READ, MAP_SHARED, fh, 0)) + { + if (data == (void*)-1) { + throw std::runtime_error("Failed to mmap " + path.string()); + } + } + + MemMap::~MemMap() + { + munmap(data, st.st_size); + } + } +} + diff --git a/libadhocutil/fileUtils.h b/libadhocutil/fileUtils.h new file mode 100644 index 0000000..a11accb --- /dev/null +++ b/libadhocutil/fileUtils.h @@ -0,0 +1,42 @@ +#ifndef ADHOCUTIL_FILEUTILS_H +#define ADHOCUTIL_FILEUTILS_H + +#include <boost/filesystem/path.hpp> +#include <sys/stat.h> +#include "visibility.h" + +namespace AdHoc { + namespace FileUtils { + DLL_PUBLIC boost::filesystem::path operator/(const boost::filesystem::path & p, unsigned int n); + + class DLL_PUBLIC FileHandle { + public: + FileHandle(const boost::filesystem::path & path); + virtual ~FileHandle(); + + const int fh; + }; + + class DLL_PUBLIC FileHandleStat : public FileHandle { + public: + FileHandleStat(const boost::filesystem::path & path); + + const struct stat & getStat() const; + + protected: + struct stat st; + }; + + class DLL_PUBLIC MemMap : public FileHandleStat { + public: + MemMap(const boost::filesystem::path & path); + ~MemMap(); + + void * const data; + }; + } +} + +#endif + + diff --git a/libadhocutil/unittests/Jamfile.jam b/libadhocutil/unittests/Jamfile.jam index 3991ad5..36250dc 100644 --- a/libadhocutil/unittests/Jamfile.jam +++ b/libadhocutil/unittests/Jamfile.jam @@ -238,3 +238,14 @@ run testFprintbf ; +run + testFileUtils.cpp + : : : + <define>BOOST_TEST_DYN_LINK + <library>..//adhocutil + <library>boost_utf + <define>ROOT=\"$(me)\" + <library>boost_system + <library>boost_filesystem + ; + diff --git a/libadhocutil/unittests/testFileUtils.cpp b/libadhocutil/unittests/testFileUtils.cpp new file mode 100644 index 0000000..88521d3 --- /dev/null +++ b/libadhocutil/unittests/testFileUtils.cpp @@ -0,0 +1,40 @@ +#define BOOST_TEST_MODULE FileUtils +#include <boost/test/unit_test.hpp> + +#include <fileUtils.h> +#include <definedDirs.h> + +BOOST_AUTO_TEST_CASE( memmap ) +{ + AdHoc::FileUtils::MemMap f(rootDir / "testFileUtils.cpp"); + BOOST_REQUIRE(f.fh); + BOOST_REQUIRE_EQUAL(f.getStat().st_mode, 0100644); + BOOST_REQUIRE_EQUAL(0, memcmp(f.data, "#define BOOST_TEST_MODULE FileUtils", 35)); +} + +BOOST_AUTO_TEST_CASE( openfail ) +{ + BOOST_REQUIRE_THROW({ + AdHoc::FileUtils::MemMap f("/tmp/nothere"); + }, std::runtime_error); +} + +BOOST_AUTO_TEST_CASE( mapfail ) +{ + BOOST_REQUIRE_THROW({ + AdHoc::FileUtils::MemMap f("/dev/null"); + }, std::runtime_error); +} + +BOOST_AUTO_TEST_CASE( pathPart ) +{ + using namespace AdHoc::FileUtils; + boost::filesystem::path p("/this/is/some/path"); + BOOST_REQUIRE_EQUAL(p / 0, "/"); + BOOST_REQUIRE_EQUAL(p / 1, "this"); + BOOST_REQUIRE_EQUAL(p / 2, "is"); + BOOST_REQUIRE_EQUAL(p / 3, "some"); + BOOST_REQUIRE_EQUAL(p / 4, "path"); + BOOST_REQUIRE_EQUAL(p / 5, ""); +} + |