diff options
| author | Dan Goodliffe <dan@randomdan.homeip.net> | 2015-06-13 15:17:54 +0100 | 
|---|---|---|
| committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2015-06-13 15:17:54 +0100 | 
| commit | 5ef75bd1080dafa1c269a2cd1f4e16ae9a7da813 (patch) | |
| tree | 9a826feaae98a55e013d0e96972ec0df4f6f6372 | |
| parent | Move to C++0y (diff) | |
| parent | Move sandbox setup/teardown into a global fixture. (diff) | |
| download | netfs-5ef75bd1080dafa1c269a2cd1f4e16ae9a7da813.tar.bz2 netfs-5ef75bd1080dafa1c269a2cd1f4e16ae9a7da813.tar.xz netfs-5ef75bd1080dafa1c269a2cd1f4e16ae9a7da813.zip | |
Merge branch 'netfs-test-refactor'
31 files changed, 433 insertions, 102 deletions
| diff --git a/libfusepp/Jamfile.jam b/libfusepp/Jamfile.jam deleted file mode 100644 index 1ba4a26..0000000 --- a/libfusepp/Jamfile.jam +++ /dev/null @@ -1,5 +0,0 @@ -project  -	: usage-requirements -		<include>. -	; - diff --git a/libfusepp/fuseapp.cpp b/libfusepp/fuseAppBase.cpp index 1a6494a..a1ea491 100644 --- a/libfusepp/fuseapp.cpp +++ b/libfusepp/fuseAppBase.cpp @@ -1,4 +1,4 @@ -#include "fuseapp.h" +#include "fuseAppBase.h"  #include <errno.h>  #include <assert.h>  #include <stdio.h> @@ -184,7 +184,7 @@ int FuseAppBase::fallocate(const char *, int, off_t, off_t, struct fuse_file_inf  }  int FuseAppBase::onError(const std::exception & e) throw()  { -	fprintf(stderr, "Unknown exception calling (what: %s)\n", e.what()); +	fprintf(stderr, "Unknown exception (what: %s)\n", e.what());  	return -ENOSYS;  } @@ -198,12 +198,12 @@ void FuseAppBase::fuseDestroy(void *)  }  struct fuse_args -FuseAppBase::runint(int & argc, char** & argv, FuseAppBase * fa) +FuseAppBase::runint(int & argc, char** & argv)  {  	struct fuse_opt fuse_opts[] = {  		{ NULL, 0, 0 }  	}; -	fuseApp = fa; +	fuseApp = this;  	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);  	if (fuse_opt_parse(&args, fuseApp, fuse_opts,  			fuseCall<void *, const char *, int, struct fuse_args *>::helper<&FuseAppBase::opt_parse>) == -1) { diff --git a/libfusepp/fuseapp.h b/libfusepp/fuseAppBase.h index a320d36..d76fbff 100644 --- a/libfusepp/fuseapp.h +++ b/libfusepp/fuseAppBase.h @@ -56,11 +56,14 @@ class FuseAppBase {  		virtual int fallocate(const char *, int, off_t, off_t, struct fuse_file_info *);  		virtual int onError(const std::exception & err) throw(); +		virtual int fuse_opt_parse(struct fuse_args *args, void *data, const struct fuse_opt opts[], fuse_opt_proc_t proc) = 0; +		virtual int main(int &, char **, const struct fuse_operations *) = 0; +  #define GetHelper(func) getHelper<&FuseAppBase::func>(typeid(&FuseAppBase::func) != typeid(&FuseApp::func))  		template <typename FuseApp>  		static int run(int & argc, char** & argv, FuseApp * fa)  		{ -			auto args = runint(argc, argv, fa); +			auto args = fa->runint(argc, argv);  			struct fuse_operations operations = {  				fuseCall<const char *, struct stat *>::GetHelper(getattr),  				fuseCall<const char *, char *, size_t>::GetHelper(readlink), @@ -119,10 +122,11 @@ class FuseAppBase {  #endif  #endif  			}; -			return fuse_main(args.argc, args.argv, &operations, fa); +			return fa->main(args.argc, args.argv, &operations);  		} +		struct fuse_args runint(int &, char ** &); +  	private: -		static struct fuse_args runint(int &, char ** &, FuseAppBase *);  		static void * fuseInit(struct fuse_conn_info *conn);  		static void fuseDestroy(void *); diff --git a/netfs/Jamfile.jam b/netfs/Jamfile.jam index d006225..6df8110 100644 --- a/netfs/Jamfile.jam +++ b/netfs/Jamfile.jam @@ -13,10 +13,12 @@ lib Ice : : <name>Ice ;  lib IceUtil : : <name>IceUtil ;  lib IceBox : : <name>IceBox ;  lib pthread : : <name>pthread ; -lib fuse : : <name>fuse ; +lib slicer : : : : <include>/usr/include/slicer ; +lib slicer-xml : : : : <include>/usr/include/slicer ;  build-project daemon ;  build-project fuse ; +build-project unittests ;  explicit install ;  package.install install : : fuse//netfs : daemon//netfsd ; diff --git a/netfs/daemon/Jamfile.jam b/netfs/daemon/Jamfile.jam index fd8c463..53ac99d 100644 --- a/netfs/daemon/Jamfile.jam +++ b/netfs/daemon/Jamfile.jam @@ -1,5 +1,3 @@ -lib slicer : : : : <include>/usr/include/slicer ; -lib slicer-xml : : : : <include>/usr/include/slicer ;  cpp-pch pch : pch.hpp :  	<define>_FILE_OFFSET_BITS=64 @@ -13,21 +11,21 @@ cpp-pch pch : pch.hpp :  	;  lib netfsdConfiguration : -	configuration.ice +	daemonConfig.ice  	:  	<library>..//Ice  	<library>..//IceUtil  	<library>..//pthread  	<library>..//boost_filesystem  	<library>..//boost_system -	<library>slicer +	<library>..//slicer  	<slicer>yes  	: :  	<include>.  	<library>..//IceUtil  	<library>..//Ice  	<library>..//boost_system -	<library>slicer +	<library>..//slicer  	;  lib netfsd : @@ -49,7 +47,13 @@ lib netfsd :  	<library>..//IceUtil  	<library>..//IceBox  	<library>..//libxmlpp -	<library>slicer-xml +	<library>..//slicer-xml +	: : +	<include>. +	<implicit-dependency>../ice//netfsComms +	<library>netfsdConfiguration +	<implicit-dependency>netfsdConfiguration +	<library>..//IceBox  	; diff --git a/netfs/daemon/daemon.cpp b/netfs/daemon/daemon.cpp index d36e63f..3ad6294 100644 --- a/netfs/daemon/daemon.cpp +++ b/netfs/daemon/daemon.cpp @@ -1,4 +1,4 @@ -#include "pch.hpp" +#include <pch.hpp>  #include <Ice/Ice.h>  #include "daemon.h"  #include "daemonService.h" @@ -8,19 +8,33 @@  #include "ioHelpers.h"  #include <sys/stat.h> +NetFSDaemon::NetFSDaemon(const Ice::CommunicatorPtr & i) : +	ic(i) +{ +} + +NetFSDaemon::~NetFSDaemon() +{ +	adapter->deactivate(); +} +  std::string  NetFSDaemon::hostname()  { -	char buf[128]; -	gethostname(buf, sizeof(buf)); -	return buf; +	auto props = ic->getProperties(); +	auto hostNameOverride = props->getProperty("NetFSD.HostNameOverride"); +	if (hostNameOverride.empty()) { +		char buf[128]; +		gethostname(buf, sizeof(buf)); +		return buf; +	} +	return hostNameOverride;  }  // name = NetFSDaemonAdapter  void -NetFSDaemon::start(const std::string & name, const Ice::CommunicatorPtr & ic, const Ice::StringSeq&) +NetFSDaemon::start(const std::string & name, const Ice::CommunicatorPtr &, const Ice::StringSeq&)  { -	this->ic = ic;  	Ice::PropertiesPtr props = ic->getProperties();  	LoadConfiguration(props->getProperty("NetFSD.ConfigPath")); @@ -29,11 +43,17 @@ NetFSDaemon::start(const std::string & name, const Ice::CommunicatorPtr & ic, co  	adapter->activate();  } +NetFS::Daemon::ConfigurationPtr +NetFSDaemon::ReadConfiguration(const boost::filesystem::path & path) const +{ +	return Slicer::Deserialize<Slicer::XmlFileDeserializer, NetFS::Daemon::Configuration>(path); +} +  void  NetFSDaemon::LoadConfiguration(const boost::filesystem::path & path)  {  	dc = new NetFS::Daemon::RuntimeConfiguration(); -	dc->CurrentConfiguration = Slicer::Deserialize<Slicer::XmlFileDeserializer, NetFS::Daemon::Configuration>(path); +	dc->CurrentConfiguration = ReadConfiguration(path);  	auto selfItr = dc->CurrentConfiguration->Hosts.find(hostname());  	if (selfItr == dc->CurrentConfiguration->Hosts.end()) {  		throw std::runtime_error("This host is not defined in the configuration."); @@ -49,15 +69,15 @@ NetFSDaemon::stop()  extern "C" {  	IceBox::Service * -	createNetFSDaemon(Ice::CommunicatorPtr) +	createNetFSDaemon(Ice::CommunicatorPtr ic)  	{ -		return new NetFSDaemon(); +		return new NetFSDaemon(ic);  	}  }  TempPrivs::TempPrivs(const NetFS::ReqEnv & re, const boost::filesystem::path & r) : -	myu(UserEntCache::instance.getID(re.user)), -	myg(GroupEntCache::instance.getID(re.grp)), +	myu(UserEntCache::instance.getEntry(re.user)->id), +	myg(GroupEntCache::instance.getEntry(re.grp)->id),  	root(r)  {  } diff --git a/netfs/daemon/daemon.h b/netfs/daemon/daemon.h index 471a296..7ed5cb4 100644 --- a/netfs/daemon/daemon.h +++ b/netfs/daemon/daemon.h @@ -3,23 +3,29 @@  #include <Ice/Ice.h>  #include <IceBox/IceBox.h> -#include <configuration.h> +#include <daemonConfig.h>  #include <types.h>  #include <boost/filesystem/path.hpp>  class NetFSDaemon : public IceBox::Service {  	public: -		virtual void start(const std::string&, const Ice::CommunicatorPtr&, const Ice::StringSeq&); -		virtual void stop(); +		NetFSDaemon(const Ice::CommunicatorPtr &); +		virtual ~NetFSDaemon(); + +		virtual void start(const std::string&, const Ice::CommunicatorPtr&, const Ice::StringSeq&) override; +		virtual void stop() override; + +	protected: +		virtual NetFS::Daemon::ConfigurationPtr ReadConfiguration(const boost::filesystem::path & path) const;  	private:  		void LoadConfiguration(const boost::filesystem::path & path); -		Ice::CommunicatorPtr ic; +		const Ice::CommunicatorPtr ic;  		Ice::ObjectAdapterPtr adapter;  		NetFS::Daemon::RuntimeConfigurationPtr dc; -		static std::string hostname(); +		std::string hostname();  };  class TempPrivs { diff --git a/netfs/daemon/configuration.ice b/netfs/daemon/daemonConfig.ice index bb77344..bb77344 100644 --- a/netfs/daemon/configuration.ice +++ b/netfs/daemon/daemonConfig.ice diff --git a/netfs/daemon/daemonDirectory.cpp b/netfs/daemon/daemonDirectory.cpp index b43806f..b61b8be 100644 --- a/netfs/daemon/daemonDirectory.cpp +++ b/netfs/daemon/daemonDirectory.cpp @@ -1,4 +1,4 @@ -#include "pch.hpp" +#include <pch.hpp>  #include <Ice/ObjectAdapter.h>  #include <dirent.h>  #include <errno.h> diff --git a/netfs/daemon/daemonFile.cpp b/netfs/daemon/daemonFile.cpp index 79077a1..3acd1ca 100644 --- a/netfs/daemon/daemonFile.cpp +++ b/netfs/daemon/daemonFile.cpp @@ -1,4 +1,4 @@ -#include "pch.hpp" +#include <pch.hpp>  #include <Ice/ObjectAdapter.h>  #include <errno.h>  #include <map> @@ -36,7 +36,7 @@ FileServer::fgetattr(const NetFS::ReqEnv & re, const Ice::Current &)  		throw NetFS::SystemError(errno);  	}  	NetFS::Attr a; -	a << StatSource { s, boost::bind(&UserEntCache::getName, &UserEntCache::instance, _1), boost::bind(&GroupEntCache::getName, &GroupEntCache::instance, _1) }; +	a << StatSource { s, boost::bind(&UserEntCache::getName, &UserEntCache::instance, _1, _2), boost::bind(&GroupEntCache::getName, &GroupEntCache::instance, _1, _2) };  	return a;  } diff --git a/netfs/daemon/daemonService.cpp b/netfs/daemon/daemonService.cpp index 4b9e804..fe587f1 100644 --- a/netfs/daemon/daemonService.cpp +++ b/netfs/daemon/daemonService.cpp @@ -1,4 +1,4 @@ -#include "pch.hpp" +#include <pch.hpp>  #include "daemon.h"  #include "daemonService.h"  #include "daemonVolume.h" diff --git a/netfs/daemon/daemonService.h b/netfs/daemon/daemonService.h index 783ad96..345df2c 100644 --- a/netfs/daemon/daemonService.h +++ b/netfs/daemon/daemonService.h @@ -3,6 +3,7 @@  #include <service.h>  #include <entCache.h> +#include <daemonConfig.h>  class ServiceServer : public NetFS::Service {  	public: diff --git a/netfs/daemon/daemonVolume.cpp b/netfs/daemon/daemonVolume.cpp index 0caead6..0556d9a 100644 --- a/netfs/daemon/daemonVolume.cpp +++ b/netfs/daemon/daemonVolume.cpp @@ -1,4 +1,4 @@ -#include "pch.hpp" +#include <pch.hpp>  #include <Ice/ObjectAdapter.h>  #include <errno.h>  #include <map> @@ -70,7 +70,7 @@ VolumeServer::getattr(const NetFS::ReqEnv & re, const std::string & path, const  		throw NetFS::SystemError(errno);  	}  	NetFS::Attr a; -	a << StatSource { s, boost::bind(&UserEntCache::getName, &UserEntCache::instance, _1), boost::bind(&GroupEntCache::getName, &GroupEntCache::instance, _1) }; +	a << StatSource { s, boost::bind(&UserEntCache::getName, &UserEntCache::instance, _1, _2), boost::bind(&GroupEntCache::getName, &GroupEntCache::instance, _1, _2) };  	return a;  } diff --git a/netfs/daemon/pch.hpp b/netfs/daemon/pch.hpp index 3229655..adc5ff2 100644 --- a/netfs/daemon/pch.hpp +++ b/netfs/daemon/pch.hpp @@ -6,8 +6,8 @@  #include <boost/filesystem/path.hpp>  #include "daemon.h"  #include <IceBox/IceBox.h> +#include <Ice/Ice.h>  #endif  #endif - diff --git a/netfs/fuse/Jamfile.jam b/netfs/fuse/Jamfile.jam index 8223aa7..c5d3a7a 100644 --- a/netfs/fuse/Jamfile.jam +++ b/netfs/fuse/Jamfile.jam @@ -1,5 +1,4 @@ -lib slicer : : : : <include>/usr/include/slicer ; -lib slicer-xml : : : : <include>/usr/include/slicer ; +lib fuse : : <name>fuse ;  cpp-pch pch : pch.hpp :  	<define>_FILE_OFFSET_BITS=64 @@ -8,46 +7,60 @@ cpp-pch pch : pch.hpp :  	<implicit-dependency>../ice//netfsComms  	<library>../ice//netfsComms  	<library>..//boost_thread -	<library>..//fuse +	<library>fuse  	<library>..//Ice  	; -obj configuration : -	configuration.ice +lib netfsClientConfiguration : +	fuseConfig.ice  	:  	<slicer>yes  	<library>..//Ice  	<library>..//IceUtil  	<library>..//pthread -	<library>slicer +	<library>..//slicer  	: :  	<library>..//IceUtil  	<library>..//Ice  	<library>..//boost_system -	<library>slicer +	<library>..//slicer  	; -exe netfs : +lib netfsClient :  	pch -	configuration -	[ glob *.cpp ] +	netfsClientConfiguration +	[ glob *.cpp : netfs.cpp ]  	[ glob ../../libfusepp/fuse*.cpp ]  	:  	<define>_FILE_OFFSET_BITS=64  	<include>../../libmisc  	<include>../../libfusepp  	<implicit-dependency>../ice//netfsComms -	<implicit-dependency>configuration +	<library>netfsClientConfiguration +	<implicit-dependency>netfsClientConfiguration  	<library>../ice//netfsComms  	<library>../lib//netfsCommon  	<library>..//boost_thread  	<library>..//boost_system -	<library>..//fuse  	<library>..//Ice  	<library>..//IceUtil  	<library>..//pthread -	<library>slicer +	<library>..//slicer  	<library>..//libxmlpp -	<library>slicer-xml +	<library>..//slicer-xml +	: : +	<include>. +	<include>../../libfusepp +	<library>../ice//netfsComms +	<implicit-dependency>../ice//netfsComms +	<library>netfsClientConfiguration +	<implicit-dependency>netfsClientConfiguration +	<define>_FILE_OFFSET_BITS=64 +	; + +exe netfs : +	netfs.cpp : +	<library>netfsClient +	<library>fuse  	; diff --git a/netfs/fuse/fuse.cpp b/netfs/fuse/fuseApp.cpp index 7f90710..fdcce57 100644 --- a/netfs/fuse/fuse.cpp +++ b/netfs/fuse/fuseApp.cpp @@ -1,6 +1,6 @@ -#include "pch.hpp" +#include <pch.hpp>  #include <string.h> -#include "fuse.h" +#include "fuseApp.h"  #include "lockHelpers.h"  #include "cache.impl.h"  #include <entCache.h> @@ -34,11 +34,17 @@ NetFS::FuseApp::~FuseApp()  	}  } +NetFS::Client::ConfigurationPtr +NetFS::FuseApp::ReadConfiguration(const std::string & path) const +{ +	return Slicer::Deserialize<Slicer::XmlFileDeserializer, NetFS::Client::Configuration>(path); +} +  void *  NetFS::FuseApp::init(struct fuse_conn_info *)  {  	ic = Ice::initialize(_argc, _argv); -	fc = Slicer::Deserialize<Slicer::XmlFileDeserializer, NetFS::Client::Configuration>(configPath); +	fc = ReadConfiguration(configPath);  	return NULL;  } @@ -98,7 +104,7 @@ NetFS::FuseApp::connectToVolume()  		}  		volume = service->connect(e->second->ExportName, "bar");  		if (!volume) { -			throw "Invalid filesystem proxy"; +			throw std::runtime_error("Invalid filesystem proxy");  		}  	}  } @@ -165,12 +171,9 @@ NetFS::FuseApp::reqEnv()  	connectToService();  	connectToVolume();  	struct fuse_context * c = fuse_get_context(); -	return { UserEntCache::instance.getName(c->uid), GroupEntCache::instance.getName(c->gid) }; -} - -int -main(int argc, char* argv[]) -{ -	return FuseAppBase::run(argc, argv, new NetFS::FuseApp(argc, argv)); +	NetFS::ReqEnv re; +	UserEntCache::instance.getName(c->uid, &re.user); +	GroupEntCache::instance.getName(c->gid, &re.grp); +	return re;  } diff --git a/netfs/fuse/fuse.h b/netfs/fuse/fuseApp.h index 3821285..e514b55 100644 --- a/netfs/fuse/fuse.h +++ b/netfs/fuse/fuseApp.h @@ -4,8 +4,8 @@  #include <boost/thread/shared_mutex.hpp>  #include <Ice/Ice.h>  #include <service.h> -#include "fuseapp.h" -#include "configuration.h" +#include "fuseAppBase.h" +#include "fuseConfig.h"  #include "cache.h"  namespace NetFS { @@ -78,6 +78,11 @@ namespace NetFS {  			// stuff  			int onError(const std::exception & err) throw(); +			virtual struct fuse_context * fuse_get_context() = 0; + +		protected: +			virtual NetFS::Client::ConfigurationPtr ReadConfiguration(const std::string &) const; +  		private:  			void setProxy(OpenFilePtr, uint64_t & fh);  			OpenFilePtr getFileProxy(uint64_t localID) const; diff --git a/netfs/fuse/configuration.ice b/netfs/fuse/fuseConfig.ice index db37770..db37770 100644 --- a/netfs/fuse/configuration.ice +++ b/netfs/fuse/fuseConfig.ice diff --git a/netfs/fuse/fuseDirs.cpp b/netfs/fuse/fuseDirs.cpp index 75cb5a5..1da9484 100644 --- a/netfs/fuse/fuseDirs.cpp +++ b/netfs/fuse/fuseDirs.cpp @@ -1,5 +1,5 @@ -#include "pch.hpp" -#include "fuse.h" +#include <pch.hpp> +#include "fuseApp.h"  #include "misc.h"  #include "lockHelpers.h"  #include <typeConvert.h> @@ -79,7 +79,7 @@ NetFS::FuseApp::readdir(const char * p, void * buf, fuse_fill_dir_t filler, off_  			statCache.Add(new OptimisticCallCacheable<struct stat, std::string, IceUtil::Shared>(  						[asga,this]() {  							struct stat s; -							s << AttrSource { volume->end_getattr(asga), boost::bind(&UserEntCache::getID, &UserEntCache::instance, _1), boost::bind(&GroupEntCache::getID, &GroupEntCache::instance, _1) }; +							s << AttrSource { volume->end_getattr(asga), boost::bind(&UserEntCache::getID, &UserEntCache::instance, _1, _2), boost::bind(&GroupEntCache::getID, &GroupEntCache::instance, _1, _2) };  							return s;  						}, epath, time_t(NULL) + 2));  		} diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp index 9ce260c..c6d4283 100644 --- a/netfs/fuse/fuseFiles.cpp +++ b/netfs/fuse/fuseFiles.cpp @@ -1,7 +1,7 @@ -#include "pch.hpp" +#include <pch.hpp>  #include <string.h>  #include <typeConvert.h> -#include "fuse.h" +#include "fuseApp.h"  #include "lockHelpers.h"  #include <entCache.h> @@ -135,7 +135,7 @@ NetFS::FuseApp::fgetattr(const char *, struct stat * s, fuse_file_info * fi)  {  	try {  		auto remote = getFileProxy(fi->fh)->remote; -		*s << AttrSource { remote->fgetattr(reqEnv()), boost::bind(&UserEntCache::getID, &UserEntCache::instance, _1), boost::bind(&GroupEntCache::getID, &GroupEntCache::instance, _1) }; +		*s << AttrSource { remote->fgetattr(reqEnv()), boost::bind(&UserEntCache::getID, &UserEntCache::instance, _1, _2), boost::bind(&GroupEntCache::getID, &GroupEntCache::instance, _1, _2) };  		return 0;  	}  	catch (NetFS::SystemError & e) { diff --git a/netfs/fuse/fuseMisc.cpp b/netfs/fuse/fuseMisc.cpp index 0e366be..1f999bd 100644 --- a/netfs/fuse/fuseMisc.cpp +++ b/netfs/fuse/fuseMisc.cpp @@ -1,5 +1,5 @@ -#include "pch.hpp" -#include "fuse.h" +#include <pch.hpp> +#include "fuseApp.h"  #include <string.h>  #include <typeConvert.h>  #include <entCache.h> @@ -19,7 +19,7 @@ NetFS::FuseApp::getattr(const char * p, struct stat * s)  			*s = *cacehedStat;  		}  		else { -			*s << AttrSource { volume->getattr(reqEnv(), p), boost::bind(&UserEntCache::getID, &UserEntCache::instance, _1), boost::bind(&GroupEntCache::getID, &GroupEntCache::instance, _1) }; +			*s << AttrSource { volume->getattr(reqEnv(), p), boost::bind(&UserEntCache::getID, &UserEntCache::instance, _1, _2), boost::bind(&GroupEntCache::getID, &GroupEntCache::instance, _1, _2) };  		}  		return 0;  	} diff --git a/netfs/fuse/fuseSystem.cpp b/netfs/fuse/fuseSystem.cpp index 0b29d86..e2a9ab7 100644 --- a/netfs/fuse/fuseSystem.cpp +++ b/netfs/fuse/fuseSystem.cpp @@ -1,6 +1,6 @@ -#include "pch.hpp" +#include <pch.hpp>  #include <typeConvert.h> -#include "fuse.h" +#include "fuseApp.h"  int  NetFS::FuseApp::statfs(const char * p, struct statvfs * vfs) diff --git a/netfs/fuse/netfs.cpp b/netfs/fuse/netfs.cpp new file mode 100644 index 0000000..f700a74 --- /dev/null +++ b/netfs/fuse/netfs.cpp @@ -0,0 +1,29 @@ +#include "fuseApp.h" + +class FuseImpl : public NetFS::FuseApp { +	public: +		FuseImpl(int & argc, char ** argv) : NetFS::FuseApp(argc, argv) { } + +		struct fuse_context * fuse_get_context() override +		{ +			return ::fuse_get_context(); +		} +		 +		int fuse_opt_parse(struct fuse_args * args, void * data, const struct fuse_opt opts[], fuse_opt_proc_t proc) override +		{ +			return ::fuse_opt_parse(args, data, opts, proc); +		} + +		int main(int & argc, char ** argv, const struct fuse_operations * ops) override +		{ +			return ::fuse_main(argc, argv, ops, this); +		} + +}; + +int +main(int argc, char* argv[]) +{ +	return FuseAppBase::run(argc, argv, new FuseImpl(argc, argv)); +} + diff --git a/netfs/fuse/pch.hpp b/netfs/fuse/pch.hpp index 7cb79ed..2342973 100644 --- a/netfs/fuse/pch.hpp +++ b/netfs/fuse/pch.hpp @@ -3,11 +3,10 @@  #define NETFS_FUSE_PCH  #include "../lib/pch.hpp" -#include "../../libfusepp/fuseapp.h" +#include "../../libfusepp/fuseAppBase.h"  #include <fuse.h> +#include <Ice/Ice.h>  #endif  #endif - - diff --git a/netfs/ice/typeConvert.cpp b/netfs/ice/typeConvert.cpp index 538b894..cc3ee93 100644 --- a/netfs/ice/typeConvert.cpp +++ b/netfs/ice/typeConvert.cpp @@ -7,8 +7,8 @@ operator<<(struct stat & s, const AttrSource & a)  	s.st_ino = a.attr.inode;  	s.st_mode = a.attr.mode;  	s.st_nlink = a.attr.links; -	s.st_uid = a.user(a.attr.uid); -	s.st_gid = a.group(a.attr.gid); +	a.user(a.attr.uid, &s.st_uid); +	a.group(a.attr.gid, &s.st_gid);  	s.st_rdev = a.attr.rdev;  	s.st_size = a.attr.size;  	s.st_blksize = a.attr.blockSize; @@ -41,8 +41,8 @@ operator<<(NetFS::Attr & a, const struct StatSource & s)  	a.inode = s.stat.st_ino;  	a.mode = s.stat.st_mode;  	a.links = s.stat.st_nlink; -	a.uid = s.user(s.stat.st_uid); -	a.gid = s.group(s.stat.st_gid); +	s.user(s.stat.st_uid, &a.uid); +	s.group(s.stat.st_gid, &a.gid);  	a.rdev = s.stat.st_rdev;  	a.size = s.stat.st_size;  	a.blockSize = s.stat.st_blksize; diff --git a/netfs/ice/typeConvert.h b/netfs/ice/typeConvert.h index dd56a3f..13e2b44 100644 --- a/netfs/ice/typeConvert.h +++ b/netfs/ice/typeConvert.h @@ -3,11 +3,11 @@  #include <sys/statvfs.h>  #include <boost/function.hpp> -typedef boost::function<uid_t(const std::string &)> UserIdLookup; -typedef boost::function<gid_t(const std::string &)> GroupIdLookup; +typedef boost::function<void(const std::string &, uid_t *)> UserIdLookup; +typedef boost::function<void(const std::string &, gid_t *)> GroupIdLookup; -typedef boost::function<std::string(uid_t)> UserNameLookup; -typedef boost::function<std::string(gid_t)> GroupNameLookup; +typedef boost::function<void(uid_t, std::string *)> UserNameLookup; +typedef boost::function<void(gid_t, std::string *)> GroupNameLookup;  struct AttrSource {  	const NetFS::Attr & attr; diff --git a/netfs/lib/entCache.cpp b/netfs/lib/entCache.cpp index a4cf27d..286c017 100644 --- a/netfs/lib/entCache.cpp +++ b/netfs/lib/entCache.cpp @@ -1,4 +1,4 @@ -#include "pch.hpp" +#include <pch.hpp>  #include "entCache.h"  #include <exceptions.h>  #include "lockHelpers.h" @@ -17,17 +17,19 @@ EntCache<entry_t>::~EntCache()  }  template<class entry_t> -const typename EntCache<entry_t>::id_t & -EntCache<entry_t>::getID(const EntCache<entry_t>::name_t & u) const +void +EntCache<entry_t>::getID(const EntCache<entry_t>::name_t & u, EntCache<entry_t>::id_t * target) const  { -	return getEntry(u)->id; +	auto e = getEntry(u); +	*target = e->id;  }  template<class entry_t> -const typename EntCache<entry_t>::name_t & -EntCache<entry_t>::getName(const EntCache<entry_t>::id_t & u) const +void +EntCache<entry_t>::getName(const EntCache<entry_t>::id_t & u, EntCache<entry_t>::name_t * target) const  { -	return getEntry(u)->name; +	auto e = getEntry(u); +	*target = e->name;  }  template<class entry_t> @@ -107,7 +109,7 @@ EntCache<Group>::fillCache() const  		auto g = new Group(grp->gr_gid, grp->gr_name);  		for (auto member = grp->gr_mem; *member; member++) {  			try { -				g->members.insert(EntCache<User>::instance.getID(*member)); +				g->members.insert(EntCache<User>::instance.getEntry((const name_t &)*member)->id);  			}  			catch (const NetFS::SystemError &) {  			} diff --git a/netfs/lib/entCache.h b/netfs/lib/entCache.h index ea941e8..443474f 100644 --- a/netfs/lib/entCache.h +++ b/netfs/lib/entCache.h @@ -38,8 +38,8 @@ class EntCache {  		virtual ~EntCache(); -		const id_t & getID(const name_t & ) const; -		const name_t & getName(const id_t &) const; +		void getID(const name_t &, id_t *) const; +		void getName(const id_t &, name_t *) const;  		template<class key_t>  		entry_ptr getEntry(const key_t &) const; diff --git a/netfs/lib/pch.hpp b/netfs/lib/pch.hpp index ffd9890..fc37faa 100644 --- a/netfs/lib/pch.hpp +++ b/netfs/lib/pch.hpp @@ -7,7 +7,8 @@  #include <boost/multi_index/member.hpp>  #include <boost/multi_index/ordered_index.hpp>  #include <exception> -#include <Ice/Ice.h> +#include <IceUtil/Shared.h> +#include <IceUtil/Handle.h>  #include <map>  #include <set>  #include <string> diff --git a/netfs/unittests/Jamfile.jam b/netfs/unittests/Jamfile.jam new file mode 100644 index 0000000..af02411 --- /dev/null +++ b/netfs/unittests/Jamfile.jam @@ -0,0 +1,26 @@ +import testing ; + +lib boost_utf : : <name>boost_unit_test_framework ; +lib boost_system ; +lib boost_filesystem ; +lib IceUtil ; +lib Ice ; + +path-constant me : . ; + +run +	testCore.cpp +	: : +	: +	<define>BOOST_TEST_DYN_LINK +	<library>IceUtil +	<library>Ice +	<library>boost_system +	<library>boost_filesystem +	<library>boost_utf +	<library>../daemon//netfsd +	<library>../fuse//netfsClient +	<library>../ice//netfsComms +	<define>ROOT=\"$(me)\" +	: testCore ; + diff --git a/netfs/unittests/testCore.cpp b/netfs/unittests/testCore.cpp new file mode 100644 index 0000000..1fc1817 --- /dev/null +++ b/netfs/unittests/testCore.cpp @@ -0,0 +1,221 @@ +#define BOOST_TEST_MODULE TestNetFSCore +#include <boost/test/unit_test.hpp> +#include <boost/filesystem/operations.hpp> +#include <Ice/ObjectAdapter.h> +#include <Ice/Service.h> +#include <daemon.h> +#include <fuseApp.h> +#include <boost/filesystem/path.hpp> + +#ifndef ROOT +#error "ROOT needs to be defined at compilation time" +#endif + +#define XSTR(s) STR(s) +#define STR(s) #s +const boost::filesystem::path RootDir(XSTR(ROOT)); +const boost::filesystem::path TestExportRoot(RootDir / "testExport"); + +std::string testEndpoint("tcp -h localhost -p 12012"); + +class MockDaemon : public NetFSDaemon { +	public: +		MockDaemon(const Ice::CommunicatorPtr & ic) : NetFSDaemon(ic) { } + +	protected: +		virtual NetFS::Daemon::ConfigurationPtr ReadConfiguration(const boost::filesystem::path &) const override +		{ +			return new NetFS::Daemon::Configuration( +				{ +					{ "testvol", new NetFS::Daemon::Export(TestExportRoot.string()) } +				}, +				{ +					{ "unittest", new NetFS::Daemon::Host(testEndpoint) } +				}); +		} +}; + +class MockDaemonHost { +	public: +		MockDaemonHost() : +			params({}), +			ic(Ice::initialize(params)), +			daemon(new MockDaemon(ic)) +		{ +			ic->getProperties()->setProperty("NetFSD.HostNameOverride", "unittest"); +			daemon->start("NetFSDaemonAdapter", ic, {}); + +		} + +		~MockDaemonHost() +		{ +			delete daemon; +			ic->destroy(); +		} + +		Ice::StringSeq params; +		Ice::CommunicatorPtr ic; +		NetFSDaemon * daemon; +}; +typedef boost::shared_ptr<MockDaemonHost> MockDaemonHostPtr; + +char * argv[] = { +	strdup((RootDir / ":testvol").string().c_str()), +	strdup((RootDir / "test").string().c_str()) +}; + +class FuseMock : public NetFS::FuseApp { +	public: +		FuseMock(int & argc, char ** argv) : +			NetFS::FuseApp(argc, argv) +		{ +			::memset(&context, 0, sizeof(fuse_context)); +			context.pid = getpid(); +			context.uid = getuid(); +			context.gid = getgid(); +		} + +		struct fuse_context * fuse_get_context() override +		{ +			return &context; +		} + +		int fuse_opt_parse(struct fuse_args * args, void * data, const struct fuse_opt [], fuse_opt_proc_t proc) override +		{ +			for (int n = 0; n < args->argc; n += 1) { +				proc(data, args->argv[n], n, args); +			} +			return 0; +		} + +		int main(int &, char **, const struct fuse_operations * o) override +		{ +			o->init(NULL); +			ops = *o; +			return 0; +		} + +		fuse_operations ops; + +	protected: +		virtual NetFS::Client::ConfigurationPtr ReadConfiguration(const std::string &) const override +		{ +			return new NetFS::Client::Configuration( +				{ +					{ "testvol", new NetFS::Client::Resource("testvol", "Service", { testEndpoint }) } +				}); +		} + +	private: +		fuse_context context; +}; + +class FuseMockHost { +	public: +		FuseMockHost() : +			argc(2), +			app(new FuseMock(argc, argv)), +			fuse(&app->ops) +		{ +			char ** a = argv; +			FuseAppBase::run(argc, a, app); +		} + +		int argc; +		FuseMock * app; +		fuse_operations * fuse; +}; + +class Core { +	public: +		Core() : +			ic(daemonHost.ic), +			daemon(daemonHost.daemon), +			fuse(fuseHost.fuse) +		{ +		} + +	protected: +		MockDaemonHost daemonHost; +		FuseMockHost fuseHost; + +		Ice::CommunicatorPtr ic; +		NetFSDaemon * const daemon; +		fuse_operations * fuse;; +}; + +class GlobalSandBox { +	public: +		GlobalSandBox() +		{ +			boost::filesystem::remove_all(TestExportRoot); +			boost::filesystem::create_directories(TestExportRoot); +		} +		~GlobalSandBox() +		{ +			boost::filesystem::remove_all(TestExportRoot); +		} +}; + +BOOST_GLOBAL_FIXTURE(GlobalSandBox); + +BOOST_FIXTURE_TEST_SUITE( NetfsCore, Core ) + +BOOST_AUTO_TEST_CASE ( daemonInitialised ) +{ +	auto service = NetFS::ServicePrx::checkedCast(ic->stringToProxy("Service")); +	BOOST_REQUIRE(service); +	service->ice_ping(); +} + +BOOST_AUTO_TEST_CASE ( clientInitialised ) +{ +	struct statvfs s; +	BOOST_REQUIRE_EQUAL(0, fuse->statfs("/",  &s)); +} + +BOOST_AUTO_TEST_SUITE_END(); + + +BOOST_AUTO_TEST_CASE ( createAndDaemonRestart ) +{ +	MockDaemonHostPtr daemon(new MockDaemonHost()); +	FuseMockHost fuse; + +	struct statvfs s; +	BOOST_REQUIRE_EQUAL(0, fuse.fuse->statfs("/",  &s)); + +	const char * fileName = "/createMe"; +	BOOST_CHECKPOINT("Create a new file"); +	struct fuse_file_info fh; +	memset(&fh, 0, sizeof(fh)); +	fh.flags = O_WRONLY | O_CREAT | O_APPEND; +	BOOST_REQUIRE_EQUAL(0, fuse.fuse->create(fileName, 0100644, &fh)); +	BOOST_REQUIRE(fh.fh); + +	BOOST_CHECKPOINT("Fetch file attributes"); +	struct stat st; +	BOOST_REQUIRE_EQUAL(0, fuse.fuse->fgetattr(fileName, &st, &fh)); +	BOOST_REQUIRE_EQUAL(st.st_size, 0); +	BOOST_REQUIRE_EQUAL(st.st_uid, getuid()); +	BOOST_REQUIRE_EQUAL(st.st_gid, getgid()); + +	BOOST_CHECKPOINT("Write some data"); +	char someData[890]; +	BOOST_REQUIRE_EQUAL(sizeof(someData), fuse.fuse->write(fileName, someData, sizeof(someData), 0, &fh)); + +	BOOST_REQUIRE_EQUAL(0, fuse.fuse->fgetattr(fileName, &st, &fh)); +	BOOST_REQUIRE_EQUAL(st.st_size, sizeof(someData)); + +	BOOST_CHECKPOINT("Delete old daemon object"); +	daemon.reset(); +	BOOST_CHECKPOINT("Create new daemon object"); +	daemon = MockDaemonHostPtr(new MockDaemonHost()); + +	BOOST_CHECKPOINT("Fetch file attributes again"); +	BOOST_REQUIRE_EQUAL(0, fuse.fuse->fgetattr(fileName, &st, &fh)); + +	BOOST_CHECKPOINT("Close file"); +	BOOST_REQUIRE_EQUAL(0, fuse.fuse->release(fileName, &fh)); +} + | 
