From e12ba0dffeac81845dbac902ac6e467c59e5b0fc Mon Sep 17 00:00:00 2001 From: randomdan Date: Wed, 27 Oct 2010 18:26:09 +0000 Subject: Merge all FS operations into one interface Add missing utimens support Change effective user when performing (most) operations Refactor FUSE client to get remaining base code into base file Transmit user and group names, not numbers Load a cache of users and groups Custom error handling in derived FUSE class Reconnect and retry on AuthError Define 64bit offset on client and server to support huge files Fix a few instances where the export path wasn't prefixed to the request path --- netfs/Jamfile.jam | 18 +++- netfs/daemon.cpp | 37 +++++-- netfs/daemon.h | 13 +++ netfs/daemonDirs.cpp | 20 ++-- netfs/daemonDirs.h | 23 ----- netfs/daemonFileSystem.cpp | 11 +++ netfs/daemonFileSystem.h | 49 +++++++++ netfs/daemonFiles.cpp | 35 +++---- netfs/daemonFiles.h | 27 ----- netfs/daemonMisc.cpp | 59 +++++++---- netfs/daemonMisc.h | 22 ----- netfs/daemonSystem.cpp | 10 +- netfs/daemonSystem.h | 15 --- netfs/entCache.cpp | 95 ++++++++++++++++++ netfs/entCache.h | 29 ++++++ netfs/fuse.cpp | 240 ++++++++------------------------------------- netfs/fuse.h | 19 ++-- netfs/fuseDirs.cpp | 10 +- netfs/fuseFiles.cpp | 22 ++--- netfs/fuseMisc.cpp | 34 +++++-- netfs/fuseSystem.cpp | 2 +- netfs/fuseapp.cpp | 164 +++++++++++++++++++++++++++++++ netfs/fuseapp.h | 4 + netfs/netfsComms.ice | 16 ++- 24 files changed, 575 insertions(+), 399 deletions(-) delete mode 100644 netfs/daemonDirs.h create mode 100644 netfs/daemonFileSystem.cpp create mode 100644 netfs/daemonFileSystem.h delete mode 100644 netfs/daemonFiles.h delete mode 100644 netfs/daemonMisc.h delete mode 100644 netfs/daemonSystem.h create mode 100644 netfs/entCache.cpp create mode 100644 netfs/entCache.h 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 : : : : "`pkg-config --cflags libxml++-2.6`" "`pkg-config --libs libxml++-2.6`" ; -alias fuse : : : : - "-D_FILE_OFFSET_BITS=64" - "-lfuse" ; lib boost_regex : : boost_regex ; lib boost_filesystem : : boost_filesystem ; lib boost_random : : boost_random ; lib Ice : : Ice ; +lib fuse : : fuse ; import type ; import generators ; @@ -79,12 +77,20 @@ lib netfsComms : netfsComms.ice : ; +lib netfsCommon : + entCache.cpp : + _FILE_OFFSET_BITS=64 + netfsComms + ; + exe netfs : [ glob fuse*.cpp ] : - ../libmisc//misc + _FILE_OFFSET_BITS=64 netfsComms + ../libmisc//misc netfsComms + netfsCommon fuse Ice ; @@ -92,9 +98,11 @@ exe netfs : lib netfsd : [ glob daemon*.cpp ] : - ../libmisc//misc + _FILE_OFFSET_BITS=64 netfsComms + ../libmisc//misc netfsComms + netfsCommon boost_random boost_filesystem 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 #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 #include #include "daemonConfig.h" +#include "netfsComms.h" +#include "entCache.h" #include class DaemonGlobalState : public IntrusivePtrBase { @@ -63,5 +65,16 @@ class SessionPtr { boost::lock_guard 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 #include #include -#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 - -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 + +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 #include #include -#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 #include #include -#include "daemonMisc.h" +#include "daemonFileSystem.h" extern std::map 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 #include #include -#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 + +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::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::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 +#include +#include +#include + +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 UIDs; + typedef boost::bimap 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 -#include -#include -#include #include -#include -#include -#include -#include #include "fuse.h" -static FuseAppBase * fuseApp; - -std::map NetFS::ReqEnv::uidcache; -std::map NetFS::ReqEnv::gidcache; - -template -static int fuseCall(A a) -{ - try { - return (fuseApp->*f)(a); - } - catch (...) { - return -ENOSYS; - } -} -template -static int fuseCall(A a, B b) +NetFS::ReqEnv::ReqEnv(const NetFS * netfs) { - try { - return (fuseApp->*f)(a, b); - } - catch (...) { - return -ENOSYS; - } -} -template -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 -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 -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 -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(&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::const_iterator u = uidcache.find(c->uid); - std::map::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 -int runFuseApp(int argc, char* argv[]) -{ - struct fuse_opt fuse_opts[] = { - { NULL, 0, 0 } - }; - - fuseApp = new FuseApp(argc, argv); - struct fuse_operations operations = { - fuseCall, - fuseCall, - NULL, // getdir deprecated - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - NULL, // utime deprecated - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseInit, - fuseDestroy, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - fuseCall, - NULL, - NULL, - NULL, - NULL - }; - struct fuse_args args = FUSE_ARGS_INIT(argc, argv); - if (fuse_opt_parse(&args, fuseApp, fuse_opts, - fuseCall) == -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(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 uidcache; - static std::map 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 +#include #include +#include +#include +#include + +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 +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); + } + catch (...) { + fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); + return -ENOSYS; + } +} +template +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); + } + catch (...) { + fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); + return -ENOSYS; + } +} +template +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); + } + catch (...) { + fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); + return -ENOSYS; + } +} +template +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); + } + catch (...) { + fprintf(stderr, "Unknown exception calling %s\n", typeid(f).name()); + return -ENOSYS; + } +} +template +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); + } + 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, + fuseCall, + NULL, // getdir deprecated + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + NULL, // utime deprecated + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseInit, + fuseDestroy, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + fuseCall, + NULL, + NULL, + NULL, + NULL + }; + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + if (fuse_opt_parse(&args, fuseApp, fuse_opts, + fuseCall) == -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 +#include 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 Buffer; sequence 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; -- cgit v1.2.3