summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;