summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libadhocutil/Jamfile.jam2
-rw-r--r--libadhocutil/fileUtils.cpp59
-rw-r--r--libadhocutil/fileUtils.h42
-rw-r--r--libadhocutil/unittests/Jamfile.jam11
-rw-r--r--libadhocutil/unittests/testFileUtils.cpp40
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, "");
+}
+