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, ""); +} +  | 
