summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2015-06-13 15:17:54 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2015-06-13 15:17:54 +0100
commit5ef75bd1080dafa1c269a2cd1f4e16ae9a7da813 (patch)
tree9a826feaae98a55e013d0e96972ec0df4f6f6372
parentMove to C++0y (diff)
parentMove sandbox setup/teardown into a global fixture. (diff)
downloadnetfs-5ef75bd1080dafa1c269a2cd1f4e16ae9a7da813.tar.bz2
netfs-5ef75bd1080dafa1c269a2cd1f4e16ae9a7da813.tar.xz
netfs-5ef75bd1080dafa1c269a2cd1f4e16ae9a7da813.zip
Merge branch 'netfs-test-refactor'
-rw-r--r--libfusepp/Jamfile.jam5
-rw-r--r--libfusepp/fuseAppBase.cpp (renamed from libfusepp/fuseapp.cpp)8
-rw-r--r--libfusepp/fuseAppBase.h (renamed from libfusepp/fuseapp.h)10
-rw-r--r--netfs/Jamfile.jam4
-rw-r--r--netfs/daemon/Jamfile.jam16
-rw-r--r--netfs/daemon/daemon.cpp42
-rw-r--r--netfs/daemon/daemon.h16
-rw-r--r--netfs/daemon/daemonConfig.ice (renamed from netfs/daemon/configuration.ice)0
-rw-r--r--netfs/daemon/daemonDirectory.cpp2
-rw-r--r--netfs/daemon/daemonFile.cpp4
-rw-r--r--netfs/daemon/daemonService.cpp2
-rw-r--r--netfs/daemon/daemonService.h1
-rw-r--r--netfs/daemon/daemonVolume.cpp4
-rw-r--r--netfs/daemon/pch.hpp2
-rw-r--r--netfs/fuse/Jamfile.jam41
-rw-r--r--netfs/fuse/fuseApp.cpp (renamed from netfs/fuse/fuse.cpp)25
-rw-r--r--netfs/fuse/fuseApp.h (renamed from netfs/fuse/fuse.h)9
-rw-r--r--netfs/fuse/fuseConfig.ice (renamed from netfs/fuse/configuration.ice)0
-rw-r--r--netfs/fuse/fuseDirs.cpp6
-rw-r--r--netfs/fuse/fuseFiles.cpp6
-rw-r--r--netfs/fuse/fuseMisc.cpp6
-rw-r--r--netfs/fuse/fuseSystem.cpp4
-rw-r--r--netfs/fuse/netfs.cpp29
-rw-r--r--netfs/fuse/pch.hpp5
-rw-r--r--netfs/ice/typeConvert.cpp8
-rw-r--r--netfs/ice/typeConvert.h8
-rw-r--r--netfs/lib/entCache.cpp18
-rw-r--r--netfs/lib/entCache.h4
-rw-r--r--netfs/lib/pch.hpp3
-rw-r--r--netfs/unittests/Jamfile.jam26
-rw-r--r--netfs/unittests/testCore.cpp221
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));
+}
+