summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libadhocutil/fileUtils.cpp89
-rw-r--r--libadhocutil/fileUtils.h65
-rw-r--r--libadhocutil/unittests/testFileUtils.cpp52
3 files changed, 191 insertions, 15 deletions
diff --git a/libadhocutil/fileUtils.cpp b/libadhocutil/fileUtils.cpp
index 23fce0e..5273836 100644
--- a/libadhocutil/fileUtils.cpp
+++ b/libadhocutil/fileUtils.cpp
@@ -1,10 +1,13 @@
#include "fileUtils.h"
+#include "compileTimeFormatter.h"
#include <unistd.h>
#include <sys.h>
#include <sys/mman.h>
namespace AdHoc {
namespace FileUtils {
+ AdHocFormatter(FD, "FD %?");
+
boost::filesystem::path operator/(const boost::filesystem::path & p, unsigned int n)
{
auto pp = p.begin();
@@ -43,8 +46,43 @@ namespace AdHoc {
return fh;
}
- FileHandleStat::FileHandleStat(const boost::filesystem::path & path) :
- FileHandle(path)
+ FileHandleStat::FileHandleStat(int fd) :
+ FileHandle(fd)
+ {
+ refreshStat();
+ }
+
+ FileHandleStat::FileHandleStat(const boost::filesystem::path & path, int flags) :
+ FileHandle(path, flags)
+ {
+ refreshStat(path);
+ }
+
+ FileHandleStat::FileHandleStat(const boost::filesystem::path & path, int flags, int mode) :
+ FileHandle(path, flags, mode)
+ {
+ refreshStat(path);
+ }
+
+ const struct stat &
+ FileHandleStat::getStat() const
+ {
+ return st;
+ }
+
+ const struct stat &
+ FileHandleStat::refreshStat()
+ {
+ if (fstat(fh, &st)) {
+ // LCOV_EXCL_START can't think of a way to test open succeeding and fstat failing
+ throw SystemExceptionOn("fstat(2) failed", strerror(errno), errno, FD::get(fh));
+ // LCOV_EXCL_STOP
+ }
+ return st;
+ }
+
+ void
+ FileHandleStat::refreshStat(const boost::filesystem::path & path)
{
if (fstat(fh, &st)) {
// LCOV_EXCL_START can't think of a way to test open succeeding and fstat failing
@@ -53,25 +91,54 @@ namespace AdHoc {
}
}
- const struct stat &
- FileHandleStat::getStat() const
+ MemMap::MemMap(int d, int flags) :
+ FileHandleStat(d),
+ data(setupMap(flags))
{
- return st;
}
- MemMap::MemMap(const boost::filesystem::path & path) :
- FileHandleStat(path),
- data(mmap(0, st.st_size, PROT_READ, MAP_SHARED, fh, 0))
+ MemMap::MemMap(const boost::filesystem::path & path, int flags) :
+ FileHandleStat(path, flags),
+ data(setupMap(path, flags))
+ {
+ }
+
+ MemMap::MemMap(const boost::filesystem::path & path, int flags, int mode) :
+ FileHandleStat(path, flags, mode),
+ data(setupMap(path, flags))
{
- if (data == (void*)-1) {
- throw SystemExceptionOn("mmap(2) failed", strerror(errno), errno, path.string());
- }
}
MemMap::~MemMap()
{
munmap(data, st.st_size);
}
+
+ void *
+ MemMap::setupMapInt(int flags) const
+ {
+ return mmap(0, st.st_size, flags & (O_WRONLY | O_RDWR) ? PROT_WRITE : PROT_READ, MAP_SHARED, fh, 0);
+ }
+
+ void *
+ MemMap::setupMap(int flags) const
+ {
+ auto data = setupMapInt(flags);
+ if (data == (void*)-1) {
+ throw SystemExceptionOn("mmap(2) failed", strerror(errno), errno, FD::get(fh));
+ }
+ return data;
+ }
+
+ void *
+ MemMap::setupMap(const boost::filesystem::path & path, int flags) const
+ {
+ auto data = setupMapInt(flags);
+ if (data == (void*)-1) {
+ throw SystemExceptionOn("mmap(2) failed", strerror(errno), errno, path.string());
+ }
+ return data;
+ }
}
}
diff --git a/libadhocutil/fileUtils.h b/libadhocutil/fileUtils.h
index 4df8c97..708652f 100644
--- a/libadhocutil/fileUtils.h
+++ b/libadhocutil/fileUtils.h
@@ -22,6 +22,11 @@ namespace AdHoc {
class DLL_PUBLIC FileHandle {
public:
/**
+ * Move constructor.
+ */
+ FileHandle(FileHandle &&) = default;
+
+ /**
* Construct from an existing file descriptor.
* @param fd An open file descriptor.
*/
@@ -63,10 +68,30 @@ namespace AdHoc {
class DLL_PUBLIC FileHandleStat : public FileHandle {
public:
/**
+ * Move constructor.
+ */
+ FileHandleStat(FileHandleStat &&) = default;
+
+ /**
+ * Construct from an existing file descriptor.
+ * @param fd An open file descriptor.
+ */
+ FileHandleStat(int fd);
+
+ /**
* Open a new file handle (with the default flags).
* @param path Path of file to open.
+ * @param flags File handle flags
*/
- FileHandleStat(const boost::filesystem::path & path);
+ FileHandleStat(const boost::filesystem::path & path, int flags = O_RDONLY);
+
+ /**
+ * Open a new file handle.
+ * @param path Path of file to open.
+ * @param flags File handle flags
+ * @param mode File handle mode
+ */
+ FileHandleStat(const boost::filesystem::path & path, int flags, int mode);
/**
* Get the stat structure.
@@ -74,9 +99,18 @@ namespace AdHoc {
*/
const struct stat & getStat() const;
+ /**
+ * Refresh and return the stat structure.
+ * @return The stat structure.
+ */
+ const struct stat & refreshStat();
+
protected:
/// The stat structure.
struct stat st;
+
+ private:
+ DLL_PRIVATE void refreshStat(const boost::filesystem::path & path);
};
/**
@@ -85,14 +119,41 @@ namespace AdHoc {
class DLL_PUBLIC MemMap : public FileHandleStat {
public:
/**
+ * Move constructor.
+ */
+ MemMap(MemMap &&) = default;
+
+ /**
+ * Construct from an existing file descriptor.
+ * @param fd An open file descriptor.
+ * @param flags File handle flags
+ */
+ MemMap(int fd, int flags = O_RDONLY);
+
+ /**
* Open a new file handle (with the default flags).
* @param path Path of file to open.
+ * @param flags File handle flags
+ */
+ MemMap(const boost::filesystem::path & path, int flags = O_RDONLY);
+
+ /**
+ * Open a new file handle.
+ * @param path Path of file to open.
+ * @param flags File handle flags
+ * @param mode File handle mode
*/
- MemMap(const boost::filesystem::path & path);
+ MemMap(const boost::filesystem::path & path, int flags, int mode);
+
~MemMap();
/// The file data.
void * const data;
+
+ private:
+ DLL_PUBLIC void * setupMapInt(int flags) const;
+ DLL_PUBLIC void * setupMap(int flags) const;
+ DLL_PUBLIC void * setupMap(const boost::filesystem::path & path, int flags) const;
};
}
}
diff --git a/libadhocutil/unittests/testFileUtils.cpp b/libadhocutil/unittests/testFileUtils.cpp
index 0e1cb79..648281c 100644
--- a/libadhocutil/unittests/testFileUtils.cpp
+++ b/libadhocutil/unittests/testFileUtils.cpp
@@ -5,14 +5,62 @@
#include <definedDirs.h>
#include <sys.h>
-BOOST_AUTO_TEST_CASE( raw )
+template <typename T>
+void testRaw()
{
int f = open("/proc/self/exe", O_RDONLY);
BOOST_REQUIRE(f != -1);
- AdHoc::FileUtils::FileHandle fh(f);
+ T fh(f);
BOOST_REQUIRE_EQUAL(f, fh);
}
+BOOST_AUTO_TEST_CASE( raw )
+{
+ testRaw<AdHoc::FileUtils::FileHandle>();
+ testRaw<AdHoc::FileUtils::FileHandleStat>();
+ testRaw<AdHoc::FileUtils::MemMap>();
+}
+
+template <typename T, typename ... P>
+T openfh(P ... p)
+{
+ T fh(rootDir / "testFileUtils.cpp", p...);
+ return fh;
+}
+
+template <typename T, typename ... P>
+T moveTest(P ... p)
+{
+ T fh = openfh<T>(p...);
+ char out;
+ BOOST_REQUIRE_EQUAL(1, read(fh, &out, 1));
+ return fh;
+}
+
+BOOST_AUTO_TEST_CASE( moveFileHandle )
+{
+ moveTest<AdHoc::FileUtils::FileHandle>();
+ moveTest<AdHoc::FileUtils::FileHandle>(O_RDONLY);
+ moveTest<AdHoc::FileUtils::FileHandle>(O_RDONLY, O_NONBLOCK);
+}
+
+BOOST_AUTO_TEST_CASE( moveFileHandleStat )
+{
+ auto f = moveTest<AdHoc::FileUtils::FileHandleStat>();
+ BOOST_REQUIRE_EQUAL(0100644, f.getStat().st_mode);
+ moveTest<AdHoc::FileUtils::FileHandleStat>(O_RDONLY);
+ moveTest<AdHoc::FileUtils::FileHandleStat>(O_RDONLY, O_NONBLOCK);
+}
+
+BOOST_AUTO_TEST_CASE( moveMemMap )
+{
+ auto f = moveTest<AdHoc::FileUtils::MemMap>();
+ BOOST_REQUIRE_EQUAL(0100644, f.getStat().st_mode);
+ BOOST_REQUIRE_EQUAL(0, memcmp(f.data, "#define BOOST_TEST_MODULE FileUtils", 35));
+ moveTest<AdHoc::FileUtils::MemMap>(O_RDONLY);
+ moveTest<AdHoc::FileUtils::MemMap>(O_RDONLY, O_NONBLOCK);
+}
+
BOOST_AUTO_TEST_CASE( memmap )
{
AdHoc::FileUtils::MemMap f(rootDir / "testFileUtils.cpp");