summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2010-10-27 18:26:09 +0000
committerrandomdan <randomdan@localhost>2010-10-27 18:26:09 +0000
commite12ba0dffeac81845dbac902ac6e467c59e5b0fc (patch)
treee8dab40584b827d35dadb2594fef20cfe46aebaa
parentStore the fuse config and initialise the Ice proxies as needed (diff)
downloadnetfs-e12ba0dffeac81845dbac902ac6e467c59e5b0fc.tar.bz2
netfs-e12ba0dffeac81845dbac902ac6e467c59e5b0fc.tar.xz
netfs-e12ba0dffeac81845dbac902ac6e467c59e5b0fc.zip
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
-rw-r--r--netfs/Jamfile.jam18
-rw-r--r--netfs/daemon.cpp37
-rw-r--r--netfs/daemon.h13
-rw-r--r--netfs/daemonDirs.cpp20
-rw-r--r--netfs/daemonDirs.h23
-rw-r--r--netfs/daemonFileSystem.cpp11
-rw-r--r--netfs/daemonFileSystem.h49
-rw-r--r--netfs/daemonFiles.cpp35
-rw-r--r--netfs/daemonFiles.h27
-rw-r--r--netfs/daemonMisc.cpp59
-rw-r--r--netfs/daemonMisc.h22
-rw-r--r--netfs/daemonSystem.cpp10
-rw-r--r--netfs/daemonSystem.h15
-rw-r--r--netfs/entCache.cpp95
-rw-r--r--netfs/entCache.h29
-rw-r--r--netfs/fuse.cpp240
-rw-r--r--netfs/fuse.h19
-rw-r--r--netfs/fuseDirs.cpp10
-rw-r--r--netfs/fuseFiles.cpp22
-rw-r--r--netfs/fuseMisc.cpp34
-rw-r--r--netfs/fuseSystem.cpp2
-rw-r--r--netfs/fuseapp.cpp164
-rw-r--r--netfs/fuseapp.h4
-rw-r--r--netfs/netfsComms.ice16
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;