diff options
-rw-r--r-- | netfs/Jamfile.jam | 18 | ||||
-rw-r--r-- | netfs/daemon.cpp | 37 | ||||
-rw-r--r-- | netfs/daemon.h | 13 | ||||
-rw-r--r-- | netfs/daemonDirs.cpp | 20 | ||||
-rw-r--r-- | netfs/daemonDirs.h | 23 | ||||
-rw-r--r-- | netfs/daemonFileSystem.cpp | 11 | ||||
-rw-r--r-- | netfs/daemonFileSystem.h | 49 | ||||
-rw-r--r-- | netfs/daemonFiles.cpp | 35 | ||||
-rw-r--r-- | netfs/daemonFiles.h | 27 | ||||
-rw-r--r-- | netfs/daemonMisc.cpp | 59 | ||||
-rw-r--r-- | netfs/daemonMisc.h | 22 | ||||
-rw-r--r-- | netfs/daemonSystem.cpp | 10 | ||||
-rw-r--r-- | netfs/daemonSystem.h | 15 | ||||
-rw-r--r-- | netfs/entCache.cpp | 95 | ||||
-rw-r--r-- | netfs/entCache.h | 29 | ||||
-rw-r--r-- | netfs/fuse.cpp | 240 | ||||
-rw-r--r-- | netfs/fuse.h | 19 | ||||
-rw-r--r-- | netfs/fuseDirs.cpp | 10 | ||||
-rw-r--r-- | netfs/fuseFiles.cpp | 22 | ||||
-rw-r--r-- | netfs/fuseMisc.cpp | 34 | ||||
-rw-r--r-- | netfs/fuseSystem.cpp | 2 | ||||
-rw-r--r-- | netfs/fuseapp.cpp | 164 | ||||
-rw-r--r-- | netfs/fuseapp.h | 4 | ||||
-rw-r--r-- | netfs/netfsComms.ice | 16 |
24 files changed, 575 insertions, 399 deletions
diff --git a/netfs/Jamfile.jam b/netfs/Jamfile.jam index 6be0b63..a43d287 100644 --- a/netfs/Jamfile.jam +++ b/netfs/Jamfile.jam @@ -6,14 +6,12 @@ import generators : register-standard ; alias libxmlpp : : : : <cflags>"`pkg-config --cflags libxml++-2.6`" <linkflags>"`pkg-config --libs libxml++-2.6`" ; -alias fuse : : : : - <cflags>"-D_FILE_OFFSET_BITS=64" - <linkflags>"-lfuse" ; lib boost_regex : : <name>boost_regex ; lib boost_filesystem : : <name>boost_filesystem ; lib boost_random : : <name>boost_random ; lib Ice : : <name>Ice ; +lib fuse : : <name>fuse ; import type ; import generators ; @@ -79,12 +77,20 @@ lib netfsComms : netfsComms.ice : ; +lib netfsCommon : + entCache.cpp : + <define>_FILE_OFFSET_BITS=64 + <implicit-dependency>netfsComms + ; + exe netfs : [ glob fuse*.cpp ] : - <library>../libmisc//misc + <define>_FILE_OFFSET_BITS=64 <implicit-dependency>netfsComms + <library>../libmisc//misc <library>netfsComms + <library>netfsCommon <library>fuse <library>Ice ; @@ -92,9 +98,11 @@ exe netfs : lib netfsd : [ glob daemon*.cpp ] : - <library>../libmisc//misc + <define>_FILE_OFFSET_BITS=64 <implicit-dependency>netfsComms + <library>../libmisc//misc <library>netfsComms + <library>netfsCommon <library>boost_random <library>boost_filesystem <library>Ice diff --git a/netfs/daemon.cpp b/netfs/daemon.cpp index 30ff806..7ac795f 100644 --- a/netfs/daemon.cpp +++ b/netfs/daemon.cpp @@ -2,10 +2,7 @@ #include <boost/foreach.hpp> #include "daemon.h" #include "daemonConfig.h" -#include "daemonDirs.h" -#include "daemonFiles.h" -#include "daemonMisc.h" -#include "daemonSystem.h" +#include "daemonFileSystem.h" #include "daemonService.h" // name = NetFSDaemonAdapter @@ -17,10 +14,7 @@ NetFSDaemon::start(const std::string & name, const Ice::CommunicatorPtr & ic, co dgs = new DaemonGlobalState(dc); adapter = ic->createObjectAdapterWithEndpoints(name, dc->self->iceEndpoint); - adapter->add(new FileServer(dgs), ic->stringToIdentity("Files")); - adapter->add(new DirsServer(dgs), ic->stringToIdentity("Dirs")); - adapter->add(new MiscServer(dgs), ic->stringToIdentity("Misc")); - adapter->add(new SystemServer(dgs), ic->stringToIdentity("System")); + adapter->add(new FileSystemServer(dgs), ic->stringToIdentity("FileSystem")); adapter->add(new ServiceServer(dgs), ic->stringToIdentity("Service")); adapter->activate(); } @@ -109,3 +103,30 @@ SessionPtr::operator->() return ptr.get(); } +TempPrivs::TempPrivs(uid_t u, gid_t g) : + myu(u), oldu(geteuid()), + myg(g), oldg(getegid()) +{ + if (setegid(myg)) + throw NetFSComms::SystemError(errno); + if (seteuid(myu)) + throw NetFSComms::SystemError(errno); +} + +TempPrivs::TempPrivs(const NetFSComms::ReqEnv & re, const EntCache * ec) : + myu(ec->getUID(re.user)), oldu(geteuid()), + myg(ec->getGID(re.grp)), oldg(getegid()) +{ + if (setegid(myg)) + throw NetFSComms::SystemError(errno); + if (seteuid(myu)) + throw NetFSComms::SystemError(errno); +} + +TempPrivs::~TempPrivs() +{ + if (seteuid(oldu)) + throw NetFSComms::SystemError(errno); + if (setegid(oldg)) + throw NetFSComms::SystemError(errno); +} diff --git a/netfs/daemon.h b/netfs/daemon.h index 892a1f7..6acd314 100644 --- a/netfs/daemon.h +++ b/netfs/daemon.h @@ -8,6 +8,8 @@ #include <boost/tuple/tuple.hpp> #include <boost/nondet_random.hpp> #include "daemonConfig.h" +#include "netfsComms.h" +#include "entCache.h" #include <dirent.h> class DaemonGlobalState : public IntrusivePtrBase { @@ -63,5 +65,16 @@ class SessionPtr { boost::lock_guard<boost::mutex> lg; }; +class TempPrivs { + public: + TempPrivs(uid_t u, gid_t g); + TempPrivs(const NetFSComms::ReqEnv & re, const EntCache * ec); + virtual ~TempPrivs(); + + private: + const uid_t myu, oldu; + const gid_t myg, oldg; +}; + #endif diff --git a/netfs/daemonDirs.cpp b/netfs/daemonDirs.cpp index 7533f61..ac0247f 100644 --- a/netfs/daemonDirs.cpp +++ b/netfs/daemonDirs.cpp @@ -3,17 +3,13 @@ #include <map> #include <sys/stat.h> #include <sys/types.h> -#include "daemonDirs.h" - -DirsServer::DirsServer(DaemonGlobalStatePtr dgs) : - DaemonModule(dgs) -{ -} +#include "daemonFileSystem.h" Ice::Int -DirsServer::opendir(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) +FileSystemServer::opendir(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; DIR * od = ::opendir((sess->exportCfg->root / path).string().c_str()); if (!od) { @@ -25,7 +21,7 @@ DirsServer::opendir(const NetFSComms::ReqEnv & re, const std::string & path, con } void -DirsServer::closedir(Ice::Long tok, Ice::Int id, const Ice::Current&) +FileSystemServer::closedir(Ice::Long tok, Ice::Int id, const Ice::Current&) { SessionPtr sess(dgs->getSession(tok)); if (sess->dirs.find(id) == sess->dirs.end()) { @@ -40,7 +36,7 @@ DirsServer::closedir(Ice::Long tok, Ice::Int id, const Ice::Current&) } NetFSComms::NameList -DirsServer::readdir(Ice::Long tok, Ice::Int id, const Ice::Current&) +FileSystemServer::readdir(Ice::Long tok, Ice::Int id, const Ice::Current&) { SessionPtr sess(dgs->getSession(tok)); if (sess->dirs.find(id) == sess->dirs.end()) { @@ -59,9 +55,10 @@ DirsServer::readdir(Ice::Long tok, Ice::Int id, const Ice::Current&) } void -DirsServer::mkdir(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current&) +FileSystemServer::mkdir(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current&) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; if (::mkdir((sess->exportCfg->root / path).string().c_str(), mode) != 0) { throw NetFSComms::SystemError(errno); @@ -70,9 +67,10 @@ DirsServer::mkdir(const NetFSComms::ReqEnv & re, const std::string & path, Ice:: } void -DirsServer::rmdir(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) +FileSystemServer::rmdir(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; if (::rmdir((sess->exportCfg->root / path).string().c_str()) != 0) { throw NetFSComms::SystemError(errno); diff --git a/netfs/daemonDirs.h b/netfs/daemonDirs.h deleted file mode 100644 index 29e343a..0000000 --- a/netfs/daemonDirs.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef DAEMONDIRS_H -#define DAEMONDIRS_H - -#include "netfsComms.h" -#include "daemonModule.h" -#include <dirent.h> - -class DirsServer : public DaemonModule, public NetFSComms::Dirs { - public: - DirsServer(DaemonGlobalStatePtr dgs); - - virtual Ice::Int opendir(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); - virtual void closedir(Ice::Long tok, Ice::Int id, const Ice::Current&); - virtual NetFSComms::NameList readdir(Ice::Long tok, Ice::Int id, const Ice::Current&); - - virtual void mkdir(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int id, const Ice::Current&); - virtual void rmdir(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); - - private: -}; - -#endif - diff --git a/netfs/daemonFileSystem.cpp b/netfs/daemonFileSystem.cpp new file mode 100644 index 0000000..2853268 --- /dev/null +++ b/netfs/daemonFileSystem.cpp @@ -0,0 +1,11 @@ +#include "daemonFileSystem.h" + +FileSystemServer::FileSystemServer(DaemonGlobalStatePtr dgs) : + DaemonModule(dgs) +{ +} + +FileSystemServer::~FileSystemServer() +{ +} + diff --git a/netfs/daemonFileSystem.h b/netfs/daemonFileSystem.h new file mode 100644 index 0000000..999ad6c --- /dev/null +++ b/netfs/daemonFileSystem.h @@ -0,0 +1,49 @@ +#ifndef DAEMONFILESYSTEM_H +#define DAEMONFILESYSTEM_H + +#include "netfsComms.h" +#include "daemonModule.h" +#include "entCache.h" +#include <dirent.h> + +class FileSystemServer : public DaemonModule, public NetFSComms::FileSystem { + public: + FileSystemServer(DaemonGlobalStatePtr dgs); + virtual ~FileSystemServer(); + + virtual Ice::Int opendir(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); + virtual void closedir(Ice::Long tok, Ice::Int id, const Ice::Current&); + virtual NetFSComms::NameList readdir(Ice::Long tok, Ice::Int id, const Ice::Current&); + + virtual void mkdir(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int id, const Ice::Current&); + virtual void rmdir(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); + + virtual void truncate(const NetFSComms::ReqEnv &, const std::string & path, Ice::Long size, const Ice::Current&); + virtual void ftruncate(const NetFSComms::ReqEnv &, Ice::Int id, Ice::Long size, const Ice::Current&); + virtual NetFSComms::Attr fgetattr(const NetFSComms::ReqEnv &, Ice::Int id, const Ice::Current&); + + virtual void unlink(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); + + virtual Ice::Int open(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int flags, const Ice::Current&); + virtual Ice::Int create(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int flags, Ice::Int mode, const Ice::Current&); + virtual void close(Ice::Long tok, Ice::Int id, const Ice::Current&); + virtual NetFSComms::Buffer read(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, const Ice::Current&); + virtual void write(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, const NetFSComms::Buffer & data, const Ice::Current&); + + virtual NetFSComms::VFS statfs(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); + + virtual Ice::Int access(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int mode, const Ice::Current&); + virtual NetFSComms::Attr getattr(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); + virtual void symlink(const NetFSComms::ReqEnv &, const std::string & path1, const std::string & path2, const Ice::Current&); + virtual void link(const NetFSComms::ReqEnv &, const std::string & path1, const std::string & path2, const Ice::Current&); + virtual void rename(const NetFSComms::ReqEnv &, const std::string & path1, const std::string & path2, const Ice::Current&); + virtual std::string readlink(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); + virtual void chmod(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int mode, const Ice::Current&); + virtual void chown(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int uid, Ice::Int gid, const Ice::Current&); + virtual void utimens(const NetFSComms::ReqEnv &, const std::string & path, Ice::Long, Ice::Long, Ice::Long, Ice::Long, const Ice::Current&); + private: + EntCache entries; +}; + +#endif + diff --git a/netfs/daemonFiles.cpp b/netfs/daemonFiles.cpp index c6e8a00..2d4021f 100644 --- a/netfs/daemonFiles.cpp +++ b/netfs/daemonFiles.cpp @@ -2,17 +2,13 @@ #include <map> #include <fcntl.h> #include <sys/stat.h> -#include "daemonFiles.h" - -FileServer::FileServer(DaemonGlobalStatePtr dgs) : - DaemonModule(dgs) -{ -} +#include "daemonFileSystem.h" void -FileServer::truncate(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Long size, const Ice::Current&) +FileSystemServer::truncate(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Long size, const Ice::Current&) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; if (::truncate((sess->exportCfg->root / path).string().c_str(), size) != 0) { throw NetFSComms::SystemError(errno); @@ -21,9 +17,10 @@ FileServer::truncate(const NetFSComms::ReqEnv & re, const std::string & path, Ic } void -FileServer::ftruncate(const NetFSComms::ReqEnv & re, Ice::Int id, Ice::Long size, const Ice::Current&) +FileSystemServer::ftruncate(const NetFSComms::ReqEnv & re, Ice::Int id, Ice::Long size, const Ice::Current&) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); if (sess->files.find(id) == sess->files.end()) { throw NetFSComms::SystemError(EBADF); } @@ -35,9 +32,10 @@ FileServer::ftruncate(const NetFSComms::ReqEnv & re, Ice::Int id, Ice::Long size } NetFSComms::Attr -FileServer::fgetattr(const NetFSComms::ReqEnv & re, Ice::Int id, const Ice::Current &) +FileSystemServer::fgetattr(const NetFSComms::ReqEnv & re, Ice::Int id, const Ice::Current &) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); if (sess->files.find(id) == sess->files.end()) { throw NetFSComms::SystemError(EBADF); } @@ -50,8 +48,8 @@ FileServer::fgetattr(const NetFSComms::ReqEnv & re, Ice::Int id, const Ice::Curr a.inode = s.st_ino; a.mode = s.st_mode; a.links = s.st_nlink; - a.uid = s.st_uid; - a.gid = s.st_gid; + a.uid = entries.getUName(s.st_uid); + a.gid = entries.getGName(s.st_gid); a.rdev = s.st_rdev; a.size = s.st_size; a.blockSize = s.st_blksize; @@ -63,9 +61,10 @@ FileServer::fgetattr(const NetFSComms::ReqEnv & re, Ice::Int id, const Ice::Curr } void -FileServer::unlink(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) +FileSystemServer::unlink(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; if (::unlink((sess->exportCfg->root / path).string().c_str()) != 0) { throw NetFSComms::SystemError(errno); @@ -74,9 +73,10 @@ FileServer::unlink(const NetFSComms::ReqEnv & re, const std::string & path, cons } Ice::Int -FileServer::open(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int flags, const Ice::Current&) +FileSystemServer::open(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int flags, const Ice::Current&) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; int fd = ::open((sess->exportCfg->root / path).string().c_str(), flags); if (fd == -1) { @@ -88,9 +88,10 @@ FileServer::open(const NetFSComms::ReqEnv & re, const std::string & path, Ice::I } Ice::Int -FileServer::create(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int flags, Ice::Int mode, const Ice::Current&) +FileSystemServer::create(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int flags, Ice::Int mode, const Ice::Current&) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; int fd = ::open((sess->exportCfg->root / path).string().c_str(), O_CREAT | flags, mode); if (fd == -1) { @@ -102,7 +103,7 @@ FileServer::create(const NetFSComms::ReqEnv & re, const std::string & path, Ice: } void -FileServer::close(Ice::Long tok, Ice::Int id, const Ice::Current&) +FileSystemServer::close(Ice::Long tok, Ice::Int id, const Ice::Current&) { SessionPtr sess(dgs->getSession(tok)); if (sess->files.find(id) == sess->files.end()) { @@ -117,7 +118,7 @@ FileServer::close(Ice::Long tok, Ice::Int id, const Ice::Current&) } NetFSComms::Buffer -FileServer::read(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, const Ice::Current&) +FileSystemServer::read(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, const Ice::Current&) { SessionPtr sess(dgs->getSession(tok)); if (sess->files.find(id) == sess->files.end()) { @@ -137,7 +138,7 @@ FileServer::read(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, c } void -FileServer::write(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, const NetFSComms::Buffer & data, const Ice::Current&) +FileSystemServer::write(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, const NetFSComms::Buffer & data, const Ice::Current&) { SessionPtr sess(dgs->getSession(tok)); if (sess->files.find(id) == sess->files.end()) { diff --git a/netfs/daemonFiles.h b/netfs/daemonFiles.h deleted file mode 100644 index 3c5db92..0000000 --- a/netfs/daemonFiles.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef DAEMONFILES_H -#define DAEMONFILES_H - -#include "netfsComms.h" -#include "daemonModule.h" - -class FileServer : public DaemonModule, public NetFSComms::Files { - public: - FileServer(DaemonGlobalStatePtr dgs); - - virtual void truncate(const NetFSComms::ReqEnv &, const std::string & path, Ice::Long size, const Ice::Current&); - virtual void ftruncate(const NetFSComms::ReqEnv &, Ice::Int id, Ice::Long size, const Ice::Current&); - virtual NetFSComms::Attr fgetattr(const NetFSComms::ReqEnv &, Ice::Int id, const Ice::Current&); - - virtual void unlink(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); - - virtual Ice::Int open(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int flags, const Ice::Current&); - virtual Ice::Int create(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int flags, Ice::Int mode, const Ice::Current&); - virtual void close(Ice::Long tok, Ice::Int id, const Ice::Current&); - virtual NetFSComms::Buffer read(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, const Ice::Current&); - virtual void write(Ice::Long tok, Ice::Int id, Ice::Long offset, Ice::Long size, const NetFSComms::Buffer & data, const Ice::Current&); - - private: -}; - -#endif - diff --git a/netfs/daemonMisc.cpp b/netfs/daemonMisc.cpp index dfcf8bf..06ba166 100644 --- a/netfs/daemonMisc.cpp +++ b/netfs/daemonMisc.cpp @@ -3,26 +3,23 @@ #include <unistd.h> #include <sys/stat.h> #include <limits.h> -#include "daemonMisc.h" +#include "daemonFileSystem.h" extern std::map<Ice::Int, int> files; -MiscServer::MiscServer(DaemonGlobalStatePtr dgs) : - DaemonModule(dgs) -{ -} - Ice::Int -MiscServer::access(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current &) +FileSystemServer::access(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current &) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); return ::access((sess->exportCfg->root / path).string().c_str(), mode); } NetFSComms::Attr -MiscServer::getattr(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current &) +FileSystemServer::getattr(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current &) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); struct stat s; if (::stat((sess->exportCfg->root / path).string().c_str(), &s) != 0) { throw NetFSComms::SystemError(errno); @@ -32,8 +29,8 @@ MiscServer::getattr(const NetFSComms::ReqEnv & re, const std::string & path, con a.inode = s.st_ino; a.mode = s.st_mode; a.links = s.st_nlink; - a.uid = s.st_uid; - a.gid = s.st_gid; + a.uid = entries.getUName(s.st_uid); + a.gid = entries.getGName(s.st_gid); a.rdev = s.st_rdev; a.size = s.st_size; a.blockSize = s.st_blksize; @@ -45,42 +42,46 @@ MiscServer::getattr(const NetFSComms::ReqEnv & re, const std::string & path, con } void -MiscServer::symlink(const NetFSComms::ReqEnv & re, const std::string & path1, const std::string & path2, const Ice::Current &) +FileSystemServer::symlink(const NetFSComms::ReqEnv & re, const std::string & path1, const std::string & path2, const Ice::Current &) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; - if (::symlink(path1.c_str(), path2.c_str()) != 0) { + if (::symlink((sess->exportCfg->root / path1).string().c_str(), (sess->exportCfg->root / path2).string().c_str()) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; } void -MiscServer::link(const NetFSComms::ReqEnv & re, const std::string & path1, const std::string & path2, const Ice::Current &) +FileSystemServer::link(const NetFSComms::ReqEnv & re, const std::string & path1, const std::string & path2, const Ice::Current &) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; - if (::link(path1.c_str(), path2.c_str()) != 0) { + if (::link((sess->exportCfg->root / path1).string().c_str(), (sess->exportCfg->root / path2).string().c_str()) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; } void -MiscServer::rename(const NetFSComms::ReqEnv & re, const std::string & from, const std::string & to, const Ice::Current &) +FileSystemServer::rename(const NetFSComms::ReqEnv & re, const std::string & from, const std::string & to, const Ice::Current &) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; - if (::rename(from.c_str(), to.c_str()) != 0) { + if (::rename((sess->exportCfg->root / from).string().c_str(), (sess->exportCfg->root / to).string().c_str()) != 0) { throw NetFSComms::SystemError(errno); } // s.replicatedRequest = true; } std::string -MiscServer::readlink(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current &) +FileSystemServer::readlink(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current &) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; char buf[PATH_MAX]; ssize_t rc = ::readlink((sess->exportCfg->root / path).string().c_str(), buf, PATH_MAX); @@ -91,9 +92,10 @@ MiscServer::readlink(const NetFSComms::ReqEnv & re, const std::string & path, co } void -MiscServer::chmod(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current &) +FileSystemServer::chmod(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current &) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; if (::chmod((sess->exportCfg->root / path).string().c_str(), mode) != 0) { throw NetFSComms::SystemError(errno); @@ -102,9 +104,10 @@ MiscServer::chmod(const NetFSComms::ReqEnv & re, const std::string & path, Ice:: } void -MiscServer::chown(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int uid, Ice::Int gid, const Ice::Current &) +FileSystemServer::chown(const NetFSComms::ReqEnv & re, const std::string & path, Ice::Int uid, Ice::Int gid, const Ice::Current &) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; if (::chown((sess->exportCfg->root / path).string().c_str(), uid, gid) != 0) { throw NetFSComms::SystemError(errno); @@ -112,3 +115,21 @@ MiscServer::chown(const NetFSComms::ReqEnv & re, const std::string & path, Ice:: // s.replicatedRequest = true; } +void +FileSystemServer::utimens(const NetFSComms::ReqEnv & re, const std::string & path, + Ice::Long s0, Ice::Long ns0, Ice::Long s1, Ice::Long ns1, const Ice::Current&) +{ + SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); + errno = 0; + struct timespec times[2]; + times[0].tv_sec = s0; + times[0].tv_nsec = ns0; + times[1].tv_sec = s1; + times[1].tv_nsec = ns1; + if (::utimensat(0, (sess->exportCfg->root / path).string().c_str(), times, 0) != 0) { + throw NetFSComms::SystemError(errno); + } + // s.replicatedRequest = true; +} + diff --git a/netfs/daemonMisc.h b/netfs/daemonMisc.h deleted file mode 100644 index 1d9336a..0000000 --- a/netfs/daemonMisc.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef DAEMONMISC_H -#define DAEMONMISC_H - -#include "netfsComms.h" -#include "daemonModule.h" - -class MiscServer : public DaemonModule, public NetFSComms::Misc { - public: - MiscServer(DaemonGlobalStatePtr dgs); - - virtual Ice::Int access(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int mode, const Ice::Current&); - virtual NetFSComms::Attr getattr(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); - virtual void symlink(const NetFSComms::ReqEnv &, const std::string & path1, const std::string & path2, const Ice::Current&); - virtual void link(const NetFSComms::ReqEnv &, const std::string & path1, const std::string & path2, const Ice::Current&); - virtual void rename(const NetFSComms::ReqEnv &, const std::string & path1, const std::string & path2, const Ice::Current&); - virtual std::string readlink(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); - virtual void chmod(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int mode, const Ice::Current&); - virtual void chown(const NetFSComms::ReqEnv &, const std::string & path, Ice::Int uid, Ice::Int gid, const Ice::Current&); -}; - -#endif - diff --git a/netfs/daemonSystem.cpp b/netfs/daemonSystem.cpp index cb3b6d1..8e9a13c 100644 --- a/netfs/daemonSystem.cpp +++ b/netfs/daemonSystem.cpp @@ -1,17 +1,13 @@ #include <errno.h> #include <sys/statvfs.h> #include <sys/vfs.h> -#include "daemonSystem.h" - -SystemServer::SystemServer(DaemonGlobalStatePtr dgs) : - DaemonModule(dgs) -{ -} +#include "daemonFileSystem.h" NetFSComms::VFS -SystemServer::statfs(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) +FileSystemServer::statfs(const NetFSComms::ReqEnv & re, const std::string & path, const Ice::Current&) { SessionPtr sess(dgs->getSession(re.tok)); + TempPrivs tp(re, &entries); errno = 0; struct statvfs s; if (::statvfs((sess->exportCfg->root / path).string().c_str(), &s) != 0) { diff --git a/netfs/daemonSystem.h b/netfs/daemonSystem.h deleted file mode 100644 index e42484a..0000000 --- a/netfs/daemonSystem.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DAEMONSYSTEM_H -#define DAEMONSYSTEM_H - -#include "netfsComms.h" -#include "daemonModule.h" - -class SystemServer : public DaemonModule, public NetFSComms::System { - public: - SystemServer(DaemonGlobalStatePtr dgs); - - virtual NetFSComms::VFS statfs(const NetFSComms::ReqEnv &, const std::string & path, const Ice::Current&); -}; - -#endif - diff --git a/netfs/entCache.cpp b/netfs/entCache.cpp new file mode 100644 index 0000000..52e8b67 --- /dev/null +++ b/netfs/entCache.cpp @@ -0,0 +1,95 @@ +#include "entCache.h" +#include <netfsComms.h> + +EntCache::EntCache() +{ +} + +EntCache::~EntCache() +{ +} + +uid_t +EntCache::getUID(const std::string & u) const +{ + UIDs::right_map::const_iterator cu = uidcache.right.find(u); + if (cu != uidcache.right.end()) { + return cu->second; + } + makeuidCache(); + cu = uidcache.right.find(u); + if (cu != uidcache.right.end()) { + return cu->second; + } + throw NetFSComms::SystemError(EPERM); +} + +gid_t +EntCache::getGID(const std::string & g) const +{ + GIDs::right_map::const_iterator cg = gidcache.right.find(g); + if (cg != gidcache.right.end()) { + return cg->second; + } + makegidCache(); + cg = gidcache.right.find(g); + if (cg != gidcache.right.end()) { + return cg->second; + } + throw NetFSComms::SystemError(EPERM); +} + +const std::string & +EntCache::getUName(uid_t u) const +{ + UIDs::left_map::const_iterator cu = uidcache.left.find(u); + if (cu != uidcache.left.end()) { + return cu->second; + } + makeuidCache(); + cu = uidcache.left.find(u); + if (cu != uidcache.left.end()) { + return cu->second; + } + throw NetFSComms::SystemError(EPERM); +} + +const std::string & +EntCache::getGName(gid_t g) const +{ + GIDs::left_map::const_iterator cg = gidcache.left.find(g); + if (cg != gidcache.left.end()) { + return cg->second; + } + makegidCache(); + cg = gidcache.left.find(g); + if (cg != gidcache.left.end()) { + return cg->second; + } + throw NetFSComms::SystemError(EPERM); +} + +void +EntCache::makeuidCache() const +{ + setpwent(); + uidcache.clear(); + while (struct passwd * pwp = getpwent()) { + uidcache.insert(boost::bimap<uid_t, std::string>::value_type(pwp->pw_uid, pwp->pw_name)); + } + endpwent(); +} + +void +EntCache::makegidCache() const +{ + setgrent(); + gidcache.clear(); + while (struct group * grpp = getgrent()) { + gidcache.insert(boost::bimap<gid_t, std::string>::value_type(grpp->gr_gid, grpp->gr_name)); + } + endgrent(); +} + + + diff --git a/netfs/entCache.h b/netfs/entCache.h new file mode 100644 index 0000000..fc8ab08 --- /dev/null +++ b/netfs/entCache.h @@ -0,0 +1,29 @@ +#ifndef ENTCACHE_H +#define ENTCACHE_H + +#include <pwd.h> +#include <grp.h> +#include <string> +#include <boost/bimap.hpp> + +class EntCache { + public: + EntCache(); + virtual ~EntCache(); + + uid_t getUID(const std::string & ) const; + gid_t getGID(const std::string & ) const; + const std::string & getUName(uid_t) const; + const std::string & getGName(gid_t) const; + + private: + void makeuidCache() const; + void makegidCache() const; + typedef boost::bimap<uid_t, std::string> UIDs; + typedef boost::bimap<gid_t, std::string> GIDs; + mutable UIDs uidcache; + mutable GIDs gidcache; +}; + +#endif + diff --git a/netfs/fuse.cpp b/netfs/fuse.cpp index ac35af4..14ce0ba 100644 --- a/netfs/fuse.cpp +++ b/netfs/fuse.cpp @@ -1,77 +1,37 @@ -#include <sys/types.h> -#include <sys/socket.h> -#include <netdb.h> -#include <errno.h> #include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <pwd.h> -#include <grp.h> #include "fuse.h" -static FuseAppBase * fuseApp; - -std::map<uid_t, std::string> NetFS::ReqEnv::uidcache; -std::map<gid_t, std::string> NetFS::ReqEnv::gidcache; - -template <class A, int (FuseAppBase::*f)(A)> -static int fuseCall(A a) -{ - try { - return (fuseApp->*f)(a); - } - catch (...) { - return -ENOSYS; - } -} -template <class A, class B, int (FuseAppBase::*f)(A, B)> -static int fuseCall(A a, B b) +NetFS::ReqEnv::ReqEnv(const NetFS * netfs) { - try { - return (fuseApp->*f)(a, b); - } - catch (...) { - return -ENOSYS; - } -} -template <class A, class B, class C, int (FuseAppBase::*f)(A, B, C)> -static int fuseCall(A a, B b, C c) -{ - try { - return (fuseApp->*f)(a, b, c); - } - catch (...) { - return -ENOSYS; - } + struct fuse_context * c = fuse_get_context(); + tok = netfs->authtok; + user = netfs->entries.getUName(c->uid); + grp = netfs->entries.getGName(c->gid); } -template <class A, class B, class C, class D, int (FuseAppBase::*f)(A, B, C, D)> -static int fuseCall(A a, B b, C c, D d) + +NetFS::NetFS(int & argc, char ** argv) : + _argc(argc), + _argv(argv), + authtok(0) { - try { - return (fuseApp->*f)(a, b, c, d); - } - catch (...) { - return -ENOSYS; - } } -template <class A, class B, class C, class D, class E, int (FuseAppBase::*f)(A, B, C, D, E)> -static int fuseCall(A a, B b, C c, D d, E e) + +NetFS::~NetFS() { - try { - return (fuseApp->*f)(a, b, c, d, e); + if (authtok) { + service->disconnect(authtok); } - catch (...) { - return -ENOSYS; + if (ic) { + ic->destroy(); } } -static void * fuseInit (struct fuse_conn_info *conn) -{ - return fuseApp->init(conn); -} -template <class App> -static void fuseDestroy(void * x) + +void * +NetFS::init(struct fuse_conn_info *) { - delete (App*)x; + ic = Ice::initialize(_argc, _argv); + fc = FuseConfig::Load(configPath); + return NULL; } int @@ -96,10 +56,21 @@ NetFS::opt_parse(void *, const char * arg, int key, struct fuse_args *) return 1; } +int +NetFS::onError(const std::exception & e) const throw() +{ + if (dynamic_cast<const NetFSComms::AuthError *>(&e)) { + // I've become unauthenticated... reauthenticate + authtok = service->connect(exportName, "bar"); + return 0; + } + return FuseAppBase::onError(e); +} + NetFS::ReqEnv NetFS::reqEnv() { - if (!service || !files || !dirs || !misc || !system) { + if (!service || !filesystem) { FuseConfig::ExportPtr e = fc->exports[exportName]; const std::string & ep = *e->endpoints.begin(); @@ -107,150 +78,21 @@ NetFS::reqEnv() if (!service) { throw "Invalid service proxy"; } - authtok = service->connect(exportName, "bar"); - files = NetFSComms::FilesPrx::checkedCast(ic->stringToProxy("Files:" + ep)); - if (!files) { - throw "Invalid files proxy"; + filesystem = NetFSComms::FileSystemPrx::checkedCast(ic->stringToProxy("FileSystem:" + ep)); + if (!filesystem) { + throw "Invalid filesystem proxy"; } - - dirs = NetFSComms::DirsPrx::checkedCast(ic->stringToProxy("Dirs:" + ep)); - if (!dirs) { - throw "Invalid directories proxy"; - } - - misc = NetFSComms::MiscPrx::checkedCast(ic->stringToProxy("Misc:" + ep)); - if (!misc) { - throw "Invalid misc proxy"; - } - - system = NetFSComms::SystemPrx::checkedCast(ic->stringToProxy("System:" + ep)); - if (!files) { - throw "Invalid system proxy"; - } - } - return ReqEnv(authtok); -} - -void -NetFS::ReqEnv::makeugidCache() -{ - setpwent(); - while (struct passwd * pwp = getpwent()) { - uidcache[pwp->pw_uid] = pwp->pw_name; - } - endpwent(); - setgrent(); - while (struct group * grpp = getgrent()) { - gidcache[grpp->gr_gid] = grpp->gr_name; - } - endgrent(); -} - -NetFS::ReqEnv::ReqEnv(Ice::Long at) -{ - struct fuse_context * c = fuse_get_context(); - std::map<uid_t, std::string>::const_iterator u = uidcache.find(c->uid); - std::map<gid_t, std::string>::const_iterator g = gidcache.find(c->gid); - if (u == uidcache.end() || g == gidcache.end()) { - makeugidCache(); - if ((u = uidcache.find(c->uid)) == uidcache.end() || (g = gidcache.find(c->gid)) == gidcache.end()) { - throw NetFSComms::SystemError(EPERM); - } - } - tok = at; - user = u->second; - grp = g->second; -} - -NetFS::NetFS(int & argc, char ** argv) : - _argc(argc), - _argv(argv), - authtok(0) -{ -} - -void * -NetFS::init(struct fuse_conn_info *) -{ - ic = Ice::initialize(_argc, _argv); - fc = FuseConfig::Load(configPath); - return NULL; -} - -NetFS::~NetFS() -{ - if (authtok) { - service->disconnect(authtok); - } - if (ic) { - ic->destroy(); } -} - -template <class FuseApp> -int runFuseApp(int argc, char* argv[]) -{ - struct fuse_opt fuse_opts[] = { - { NULL, 0, 0 } - }; - - fuseApp = new FuseApp(argc, argv); - struct fuse_operations operations = { - fuseCall<const char *, struct stat *, &FuseAppBase::getattr>, - fuseCall<const char *, char *, size_t, &FuseAppBase::readlink>, - NULL, // getdir deprecated - fuseCall<const char *, mode_t, dev_t, &FuseAppBase::mknod>, - fuseCall<const char *, mode_t, &FuseAppBase::mkdir>, - fuseCall<const char *, &FuseAppBase::unlink>, - fuseCall<const char *, &FuseAppBase::rmdir>, - fuseCall<const char *, const char *, &FuseAppBase::symlink>, - fuseCall<const char *, const char *, &FuseAppBase::rename>, - fuseCall<const char *, const char *, &FuseAppBase::link>, - fuseCall<const char *, mode_t, &FuseAppBase::chmod>, - fuseCall<const char *, uid_t, gid_t, &FuseAppBase::chown>, - fuseCall<const char *, off_t, &FuseAppBase::truncate>, - NULL, // utime deprecated - fuseCall<const char *, struct fuse_file_info *, &FuseAppBase::open>, - fuseCall<const char *, char *, size_t, off_t, struct fuse_file_info *, &FuseAppBase::read>, - fuseCall<const char *, const char *, size_t, off_t, struct fuse_file_info *, &FuseAppBase::write>, - fuseCall<const char *, struct statvfs *, &FuseAppBase::statfs>, - fuseCall<const char *, struct fuse_file_info *, &FuseAppBase::flush>, - fuseCall<const char *, struct fuse_file_info *, &FuseAppBase::release>, - fuseCall<const char *, int, struct fuse_file_info *, &FuseAppBase::fsync>, - fuseCall<const char *, const char *, const char *, size_t, int, &FuseAppBase::setxattr>, - fuseCall<const char *, const char *, char *, size_t, &FuseAppBase::getxattr>, - fuseCall<const char *, char *, size_t, &FuseAppBase::listxattr>, - fuseCall<const char *, const char *, &FuseAppBase::removexattr>, - fuseCall<const char *, struct fuse_file_info *, &FuseAppBase::opendir>, - fuseCall<const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, &FuseAppBase::readdir>, - fuseCall<const char *, struct fuse_file_info *, &FuseAppBase::releasedir>, - fuseCall<const char *, int, struct fuse_file_info *, &FuseAppBase::fsyncdir>, - fuseInit, - fuseDestroy<FuseApp>, - fuseCall<const char *, int, &FuseAppBase::access>, - fuseCall<const char *, mode_t, struct fuse_file_info *, &FuseAppBase::create>, - fuseCall<const char *, off_t, struct fuse_file_info *, &FuseAppBase::ftruncate>, - fuseCall<const char *, struct stat *, struct fuse_file_info *, &FuseAppBase::fgetattr>, - fuseCall<const char *, struct fuse_file_info *, int, struct flock *, &FuseAppBase::lock>, - fuseCall<const char *, const struct timespec [2], &FuseAppBase::utimens>, - fuseCall<const char *, size_t, uint64_t *, &FuseAppBase::bmap>, - NULL, - NULL, - NULL, - NULL - }; - 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 *, &FuseAppBase::opt_parse>) == -1) { - exit(1); + if (authtok == 0) { + authtok = service->connect(exportName, "bar"); } - return fuse_main(args.argc, args.argv, &operations, NULL); + return ReqEnv(this); } int main(int argc, char* argv[]) { - return runFuseApp<NetFS>(argc, argv); + return FuseAppBase::run(argc, argv, new NetFS(argc, argv)); } diff --git a/netfs/fuse.h b/netfs/fuse.h index a4e6335..b890838 100644 --- a/netfs/fuse.h +++ b/netfs/fuse.h @@ -5,18 +5,16 @@ #include "netfsComms.h" #include "fuseapp.h" #include "fuseConfig.h" +#include "entCache.h" class NetFS : public FuseAppBase { public: class ReqEnv : public NetFSComms::ReqEnv { public: - ReqEnv(Ice::Long at); - private: - static std::map<uid_t, std::string> uidcache; - static std::map<gid_t, std::string> gidcache; - static void makeugidCache(); + ReqEnv(const NetFS *); }; + NetFS(int & argc, char ** argv); ~NetFS(); private: @@ -33,6 +31,7 @@ class NetFS : public FuseAppBase int rename(const char *, const char *); int symlink(const char *, const char *); int unlink(const char *); + int utimens(const char *, const struct timespec tv[2]); // dirs int opendir(const char * p, struct fuse_file_info * fi); int releasedir(const char *, struct fuse_file_info * fi); @@ -50,6 +49,7 @@ class NetFS : public FuseAppBase // fs int statfs(const char *, struct statvfs *); // stuff + int onError(const std::exception & err) const throw(); ReqEnv reqEnv(); @@ -58,17 +58,16 @@ class NetFS : public FuseAppBase Ice::CommunicatorPtr ic; FuseConfigPtr fc; - NetFSComms::FilesPrx files; - NetFSComms::DirsPrx dirs; - NetFSComms::MiscPrx misc; - NetFSComms::SystemPrx system; + NetFSComms::FileSystemPrx filesystem; NetFSComms::ServicePrx service; - Ice::Long authtok; + mutable Ice::Long authtok; std::string mountPoint; std::string exportName; std::string configPath; + + EntCache entries; }; #endif diff --git a/netfs/fuseDirs.cpp b/netfs/fuseDirs.cpp index a93d7a3..36440a9 100644 --- a/netfs/fuseDirs.cpp +++ b/netfs/fuseDirs.cpp @@ -5,7 +5,7 @@ int NetFS::opendir(const char * p, struct fuse_file_info * fi) { try { - fi->fh = dirs->opendir(reqEnv(), p); + fi->fh = filesystem->opendir(reqEnv(), p); return 0; } catch (NetFSComms::SystemError & e) { @@ -17,7 +17,7 @@ int NetFS::releasedir(const char *, struct fuse_file_info * fi) { try { - dirs->closedir(authtok, fi->fh); + filesystem->closedir(authtok, fi->fh); return 0; } catch (NetFSComms::SystemError & e) { @@ -29,7 +29,7 @@ int NetFS::readdir(const char *, void * buf, fuse_fill_dir_t filler, off_t, struct fuse_file_info * fi) { try { - NetFSComms::NameList ds = dirs->readdir(authtok, fi->fh); + NetFSComms::NameList ds = filesystem->readdir(authtok, fi->fh); for (NetFSComms::NameList::const_iterator e = ds.begin(); e != ds.end(); e++) { filler(buf, e->c_str(), NULL, 0); } @@ -44,7 +44,7 @@ int NetFS::mkdir(const char * p, mode_t m) { try { - dirs->mkdir(reqEnv(), p, m); + filesystem->mkdir(reqEnv(), p, m); return 0; } catch (NetFSComms::SystemError & e) { @@ -55,7 +55,7 @@ int NetFS::rmdir(const char * p) { try { - dirs->rmdir(reqEnv(), p); + filesystem->rmdir(reqEnv(), p); return 0; } catch (NetFSComms::SystemError & e) { diff --git a/netfs/fuseFiles.cpp b/netfs/fuseFiles.cpp index c92f86c..24e1934 100644 --- a/netfs/fuseFiles.cpp +++ b/netfs/fuseFiles.cpp @@ -5,7 +5,7 @@ int NetFS::open(const char * p, struct fuse_file_info * fi) { try { - fi->fh = files->open(reqEnv(), p, fi->flags); + fi->fh = filesystem->open(reqEnv(), p, fi->flags); return 0; } catch (NetFSComms::SystemError & e) { @@ -17,7 +17,7 @@ int NetFS::create(const char * p, mode_t m, struct fuse_file_info * fi) { try { - fi->fh = files->create(reqEnv(), p, 0, m); + fi->fh = filesystem->create(reqEnv(), p, fi->flags, m); return 0; } catch (NetFSComms::SystemError & e) { @@ -29,7 +29,7 @@ int NetFS::release(const char *, struct fuse_file_info * fi) { try { - files->close(authtok, fi->fh); + filesystem->close(authtok, fi->fh); return 0; } catch (NetFSComms::SystemError & e) { @@ -41,7 +41,7 @@ int NetFS::read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi) { try { - NetFSComms::Buffer data = files->read(authtok, fi->fh, o, s); + NetFSComms::Buffer data = filesystem->read(authtok, fi->fh, o, s); for (NetFSComms::Buffer::const_iterator i = data.begin(); i != data.end(); i++, buf++) { *buf = *i; } @@ -57,7 +57,7 @@ NetFS::write(const char *, const char * buf, size_t s, off_t o, struct fuse_file { try { NetFSComms::Buffer data(buf, buf + s); - files->write(authtok, fi->fh, o, s, data); + filesystem->write(authtok, fi->fh, o, s, data); return s; } catch (NetFSComms::SystemError & e) { @@ -69,7 +69,7 @@ int NetFS::truncate(const char * p, off_t o) { try { - files->truncate(reqEnv(), p, o); + filesystem->truncate(reqEnv(), p, o); return 0; } catch (NetFSComms::SystemError & e) { @@ -81,7 +81,7 @@ int NetFS::ftruncate(const char *, off_t o, fuse_file_info * fi) { try { - files->ftruncate(reqEnv(), fi->fh, o); + filesystem->ftruncate(reqEnv(), fi->fh, o); return 0; } catch (NetFSComms::SystemError & e) { @@ -93,13 +93,13 @@ int NetFS::fgetattr(const char *, struct stat * s, fuse_file_info * fi) { try { - NetFSComms::Attr a = files->fgetattr(reqEnv(), fi->fh); + NetFSComms::Attr a = filesystem->fgetattr(reqEnv(), fi->fh); s->st_dev = a.dev; s->st_ino = a.inode; s->st_mode = a.mode; s->st_nlink = a.links; - s->st_uid = a.uid; - s->st_gid = a.gid; + s->st_uid = entries.getUID(a.uid); + s->st_gid = entries.getGID(a.gid); s->st_rdev = a.rdev; s->st_size = a.size; s->st_blksize = a.blockSize; @@ -118,7 +118,7 @@ int NetFS::unlink(const char * p) { try { - files->unlink(reqEnv(), p); + filesystem->unlink(reqEnv(), p); return 0; } catch (NetFSComms::SystemError & e) { diff --git a/netfs/fuseMisc.cpp b/netfs/fuseMisc.cpp index cf7e551..4a855b9 100644 --- a/netfs/fuseMisc.cpp +++ b/netfs/fuseMisc.cpp @@ -4,19 +4,20 @@ int NetFS::access(const char * p, int a) { - return -misc->access(reqEnv(), p, a); + return -filesystem->access(reqEnv(), p, a); } + int NetFS::getattr(const char * p, struct stat * s) { try { - NetFSComms::Attr a = misc->getattr(reqEnv(), p); + NetFSComms::Attr a = filesystem->getattr(reqEnv(), p); s->st_dev = a.dev; s->st_ino = a.inode; s->st_mode = a.mode; s->st_nlink = a.links; - s->st_uid = a.uid; - s->st_gid = a.gid; + s->st_uid = entries.getUID(a.uid); + s->st_gid = entries.getGID(a.gid); s->st_rdev = a.rdev; s->st_size = a.size; s->st_blksize = a.blockSize; @@ -35,7 +36,7 @@ int NetFS::chmod(const char * p, mode_t m) { try { - misc->chmod(reqEnv(), p, m); + filesystem->chmod(reqEnv(), p, m); return 0; } catch (NetFSComms::SystemError & e) { @@ -47,7 +48,7 @@ int NetFS::chown(const char * p, uid_t u, gid_t g) { try { - misc->chown(reqEnv(), p, u, g); + filesystem->chown(reqEnv(), p, u, g); return 0; } catch (NetFSComms::SystemError & e) { @@ -59,7 +60,7 @@ int NetFS::link(const char * p1, const char * p2) { try { - misc->link(reqEnv(), p1, p2); + filesystem->link(reqEnv(), p1, p2); return 0; } catch (NetFSComms::SystemError & e) { @@ -71,7 +72,7 @@ int NetFS::symlink(const char * p1, const char * p2) { try { - misc->symlink(reqEnv(), p1, p2); + filesystem->symlink(reqEnv(), p1, p2); return 0; } catch (NetFSComms::SystemError & e) { @@ -83,7 +84,7 @@ int NetFS::readlink(const char * p, char * p2, size_t s) { try { - std::string l = misc->readlink(reqEnv(), p); + std::string l = filesystem->readlink(reqEnv(), p); l.copy(p2, s); p2[s] = '\0'; return 0; @@ -97,7 +98,20 @@ int NetFS::rename(const char * p1, const char * p2) { try { - misc->rename(reqEnv(), p1, p2); + filesystem->rename(reqEnv(), p1, p2); + return 0; + } + catch (NetFSComms::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::utimens(const char * path, const struct timespec times[2]) +{ + try { + filesystem->utimens(reqEnv(), path, + times[0].tv_sec, times[0].tv_nsec, times[1].tv_sec, times[1].tv_nsec); return 0; } catch (NetFSComms::SystemError & e) { diff --git a/netfs/fuseSystem.cpp b/netfs/fuseSystem.cpp index c05ac22..392203a 100644 --- a/netfs/fuseSystem.cpp +++ b/netfs/fuseSystem.cpp @@ -4,7 +4,7 @@ int NetFS::statfs(const char * p, struct statvfs * vfs) { try { - NetFSComms::VFS v = system->statfs(reqEnv(), p); + NetFSComms::VFS v = filesystem->statfs(reqEnv(), p); vfs->f_bsize = v.blockSize; vfs->f_frsize = v.fragmentSize; vfs->f_blocks = v.blocks; diff --git a/netfs/fuseapp.cpp b/netfs/fuseapp.cpp index 2d24d3e..e293156 100644 --- a/netfs/fuseapp.cpp +++ b/netfs/fuseapp.cpp @@ -1,6 +1,12 @@ #include "fuseapp.h" #include <errno.h> +#include <assert.h> #include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <typeinfo> + +static FuseAppBase * fuseApp; FuseAppBase::FuseAppBase() { @@ -152,4 +158,162 @@ int FuseAppBase::bmap(const char *, size_t, uint64_t *) { return -ENOSYS; } +int FuseAppBase::onError(const std::exception & e) const throw() +{ + fprintf(stderr, "Unknown exception calling (what: %s)\n", e.what()); + return -ENOSYS; +} + +template <class A, int (FuseAppBase::*f)(A)> +static int fuseCall(A a) +{ + try { + return (fuseApp->*f)(a); + } + catch (const std::exception & ex) { + if (int rtn = fuseApp->onError(ex)) { + return rtn; + } + return fuseCall<A, f>(a); + } + catch (...) { + fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); + return -ENOSYS; + } +} +template <class A, class B, int (FuseAppBase::*f)(A, B)> +static int fuseCall(A a, B b) +{ + try { + return (fuseApp->*f)(a, b); + } + catch (const std::exception & ex) { + if (int rtn = fuseApp->onError(ex)) { + return rtn; + } + return fuseCall<A, B, f>(a, b); + } + catch (...) { + fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); + return -ENOSYS; + } +} +template <class A, class B, class C, int (FuseAppBase::*f)(A, B, C)> +static int fuseCall(A a, B b, C c) +{ + try { + return (fuseApp->*f)(a, b, c); + } + catch (const std::exception & ex) { + if (int rtn = fuseApp->onError(ex)) { + return rtn; + } + return fuseCall<A, B, C, f>(a, b, c); + } + catch (...) { + fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); + return -ENOSYS; + } +} +template <class A, class B, class C, class D, int (FuseAppBase::*f)(A, B, C, D)> +static int fuseCall(A a, B b, C c, D d) +{ + try { + return (fuseApp->*f)(a, b, c, d); + } + catch (const std::exception & ex) { + if (int rtn = fuseApp->onError(ex)) { + return rtn; + } + return fuseCall<A, B, C, D, f>(a, b, c, d); + } + catch (...) { + fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); + return -ENOSYS; + } +} +template <class A, class B, class C, class D, class E, int (FuseAppBase::*f)(A, B, C, D, E)> +static int fuseCall(A a, B b, C c, D d, E e) +{ + try { + return (fuseApp->*f)(a, b, c, d, e); + } + catch (const std::exception & ex) { + if (int rtn = fuseApp->onError(ex)) { + return rtn; + } + return fuseCall<A, B, C, D, E, f>(a, b, c, d, e); + } + catch (...) { + fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); + return -ENOSYS; + } +} +static void * fuseInit (struct fuse_conn_info *conn) +{ + return fuseApp->init(conn); +} +static void fuseDestroy(void *) +{ + delete fuseApp; +} + +int +FuseAppBase::run(int & argc, char** & argv, FuseAppBase * fa) +{ + struct fuse_opt fuse_opts[] = { + { NULL, 0, 0 } + }; + fuseApp = fa; + struct fuse_operations operations = { + fuseCall<const char *, struct stat *, &FuseAppBase::getattr>, + fuseCall<const char *, char *, size_t, &FuseAppBase::readlink>, + NULL, // getdir deprecated + fuseCall<const char *, mode_t, dev_t, &FuseAppBase::mknod>, + fuseCall<const char *, mode_t, &FuseAppBase::mkdir>, + fuseCall<const char *, &FuseAppBase::unlink>, + fuseCall<const char *, &FuseAppBase::rmdir>, + fuseCall<const char *, const char *, &FuseAppBase::symlink>, + fuseCall<const char *, const char *, &FuseAppBase::rename>, + fuseCall<const char *, const char *, &FuseAppBase::link>, + fuseCall<const char *, mode_t, &FuseAppBase::chmod>, + fuseCall<const char *, uid_t, gid_t, &FuseAppBase::chown>, + fuseCall<const char *, off_t, &FuseAppBase::truncate>, + NULL, // utime deprecated + fuseCall<const char *, struct fuse_file_info *, &FuseAppBase::open>, + fuseCall<const char *, char *, size_t, off_t, struct fuse_file_info *, &FuseAppBase::read>, + fuseCall<const char *, const char *, size_t, off_t, struct fuse_file_info *, &FuseAppBase::write>, + fuseCall<const char *, struct statvfs *, &FuseAppBase::statfs>, + fuseCall<const char *, struct fuse_file_info *, &FuseAppBase::flush>, + fuseCall<const char *, struct fuse_file_info *, &FuseAppBase::release>, + fuseCall<const char *, int, struct fuse_file_info *, &FuseAppBase::fsync>, + fuseCall<const char *, const char *, const char *, size_t, int, &FuseAppBase::setxattr>, + fuseCall<const char *, const char *, char *, size_t, &FuseAppBase::getxattr>, + fuseCall<const char *, char *, size_t, &FuseAppBase::listxattr>, + fuseCall<const char *, const char *, &FuseAppBase::removexattr>, + fuseCall<const char *, struct fuse_file_info *, &FuseAppBase::opendir>, + fuseCall<const char *, void *, fuse_fill_dir_t, off_t, struct fuse_file_info *, &FuseAppBase::readdir>, + fuseCall<const char *, struct fuse_file_info *, &FuseAppBase::releasedir>, + fuseCall<const char *, int, struct fuse_file_info *, &FuseAppBase::fsyncdir>, + fuseInit, + fuseDestroy, + fuseCall<const char *, int, &FuseAppBase::access>, + fuseCall<const char *, mode_t, struct fuse_file_info *, &FuseAppBase::create>, + fuseCall<const char *, off_t, struct fuse_file_info *, &FuseAppBase::ftruncate>, + fuseCall<const char *, struct stat *, struct fuse_file_info *, &FuseAppBase::fgetattr>, + fuseCall<const char *, struct fuse_file_info *, int, struct flock *, &FuseAppBase::lock>, + fuseCall<const char *, const struct timespec [2], &FuseAppBase::utimens>, + fuseCall<const char *, size_t, uint64_t *, &FuseAppBase::bmap>, + NULL, + NULL, + NULL, + NULL + }; + 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 *, &FuseAppBase::opt_parse>) == -1) { + exit(1); + } + return fuse_main(args.argc, args.argv, &operations, fa); +} diff --git a/netfs/fuseapp.h b/netfs/fuseapp.h index 965ef0d..b75d6f8 100644 --- a/netfs/fuseapp.h +++ b/netfs/fuseapp.h @@ -3,6 +3,7 @@ #define FUSE_USE_VERSION 26 #include <fuse.h> +#include <exception> class FuseAppBase { public: @@ -44,6 +45,9 @@ class FuseAppBase { virtual int lock(const char *, struct fuse_file_info *, int cmd, struct flock *); virtual int utimens(const char *, const struct timespec tv[2]); virtual int bmap(const char *, size_t blocksize, uint64_t *idx); + virtual int onError(const std::exception & err) const throw(); + + static int run(int &, char ** &, FuseAppBase *); }; #endif diff --git a/netfs/netfsComms.ice b/netfs/netfsComms.ice index c4e5c4f..44f983a 100644 --- a/netfs/netfsComms.ice +++ b/netfs/netfsComms.ice @@ -26,8 +26,8 @@ module NetFSComms { long inode; int mode; int links; - int uid; - int gid; + string uid; + string gid; int rdev; long size; long blockSize; @@ -44,7 +44,7 @@ module NetFSComms { sequence<byte> Buffer; sequence<string> NameList; // Interfaces - interface Files { + interface FileSystem { idempotent void truncate(ReqEnv env, string path, long size) throws AuthError, SystemError; idempotent void ftruncate(ReqEnv env, int id, long size) throws AuthError, SystemError; idempotent Attr fgetattr(ReqEnv env, int id) throws AuthError, SystemError; @@ -57,19 +57,16 @@ module NetFSComms { idempotent Buffer read(long tok, int id, long offset, long size) throws AuthError, SystemError; idempotent void write(long tok, int id, long offset, long size, Buffer data) throws AuthError, SystemError; - }; - interface Dirs { + int opendir(ReqEnv env, string path) throws AuthError, SystemError; void closedir(long tok, int id) throws AuthError, SystemError; idempotent NameList readdir(long tok, int id) throws AuthError, SystemError; void mkdir(ReqEnv env, string path, int mode) throws AuthError, SystemError; void rmdir(ReqEnv env, string path) throws AuthError, SystemError; - }; - interface System { + idempotent VFS statfs(ReqEnv env, string path) throws AuthError, SystemError; - }; - interface Misc { + idempotent int access(ReqEnv env, string path, int mode) throws AuthError, SystemError; idempotent Attr getattr(ReqEnv env, string path) throws AuthError, SystemError; void symlink(ReqEnv env, string path1, string path2) throws AuthError, SystemError; @@ -78,6 +75,7 @@ module NetFSComms { idempotent string readlink(ReqEnv env, string path) throws AuthError, SystemError; idempotent void chmod(ReqEnv env, string path, int mode) throws AuthError, SystemError; idempotent void chown(ReqEnv env, string path, int uid, int gid) throws AuthError, SystemError; + idempotent void utimens(ReqEnv env, string path, long atime, long atimens, long mtime, long mtimens) throws AuthError, SystemError; }; interface Service { long connect(string volume, string auth) throws AuthError, ConfigError; |