diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-08-06 15:25:11 +0100 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-08-06 15:25:11 +0100 | 
| commit | e0ccafb4870529756988246d82aa7809b5eede61 (patch) | |
| tree | a2d78160c17ec4f6151ba1b3c8654f0fcac516a5 | |
| parent | Add missing docs for GlobalStatic (diff) | |
| download | libadhocutil-e0ccafb4870529756988246d82aa7809b5eede61.tar.bz2 libadhocutil-e0ccafb4870529756988246d82aa7809b5eede61.tar.xz libadhocutil-e0ccafb4870529756988246d82aa7809b5eede61.zip  | |
Extend FileUtils with move constructors, complete set of constructors for FileHandleStat and MemMap and allow for refreshing the stat structurelibadhocutil-0.4.3
| -rw-r--r-- | libadhocutil/fileUtils.cpp | 89 | ||||
| -rw-r--r-- | libadhocutil/fileUtils.h | 65 | ||||
| -rw-r--r-- | libadhocutil/unittests/testFileUtils.cpp | 52 | 
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");  | 
