summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--netfs/daemon/daemon.cpp6
-rw-r--r--netfs/daemon/daemon.h7
-rw-r--r--netfs/daemon/daemonFile.cpp9
-rw-r--r--netfs/daemon/daemonFile.h6
-rw-r--r--netfs/daemon/daemonService.cpp2
-rw-r--r--netfs/daemon/daemonService.h3
-rw-r--r--netfs/daemon/daemonVolume.cpp47
-rw-r--r--netfs/daemon/daemonVolume.h6
-rw-r--r--netfs/daemon/ioHelpers.cpp19
-rw-r--r--netfs/fuse/fuse.cpp3
-rw-r--r--netfs/fuse/fuse.h3
-rw-r--r--netfs/fuse/fuseDirs.cpp3
-rw-r--r--netfs/fuse/fuseFiles.cpp3
-rw-r--r--netfs/fuse/fuseMisc.cpp3
-rw-r--r--netfs/lib/entCache.cpp130
-rw-r--r--netfs/lib/entCache.h66
-rw-r--r--netfs/lib/pch.hpp8
17 files changed, 200 insertions, 124 deletions
diff --git a/netfs/daemon/daemon.cpp b/netfs/daemon/daemon.cpp
index 199ecaa..13ccab7 100644
--- a/netfs/daemon/daemon.cpp
+++ b/netfs/daemon/daemon.cpp
@@ -56,9 +56,9 @@ extern "C" {
}
}
-TempPrivs::TempPrivs(const NetFS::ReqEnv & re, const UserEntCache * uec, const GroupEntCache * gec, const boost::filesystem::path & r) :
- myu(uec->getID(re.user)),
- myg(gec->getID(re.grp)),
+TempPrivs::TempPrivs(const NetFS::ReqEnv & re, const boost::filesystem::path & r) :
+ myu(UserEntCache::instance.getID(re.user)),
+ myg(GroupEntCache::instance.getID(re.grp)),
root(r)
{
}
diff --git a/netfs/daemon/daemon.h b/netfs/daemon/daemon.h
index 82af76e..d9417cd 100644
--- a/netfs/daemon/daemon.h
+++ b/netfs/daemon/daemon.h
@@ -3,13 +3,8 @@
#include <Ice/Ice.h>
#include <IceBox/IceBox.h>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/tuple/tuple.hpp>
-#include <boost/nondet_random.hpp>
#include <configuration.h>
#include <types.h>
-#include <entCache.h>
class NetFSDaemon : public IceBox::Service {
public:
@@ -28,7 +23,7 @@ class NetFSDaemon : public IceBox::Service {
class TempPrivs {
public:
- TempPrivs(const NetFS::ReqEnv & re, const UserEntCache * uec, const GroupEntCache * gec, const boost::filesystem::path &);
+ TempPrivs(const NetFS::ReqEnv & re, const boost::filesystem::path &);
void AssertRead(const boost::filesystem::path &) const;
void AssertWrite(const boost::filesystem::path &) const;
diff --git a/netfs/daemon/daemonFile.cpp b/netfs/daemon/daemonFile.cpp
index dd8b706..91a302d 100644
--- a/netfs/daemon/daemonFile.cpp
+++ b/netfs/daemon/daemonFile.cpp
@@ -5,11 +5,10 @@
#include <typeConvert.h>
#include <sys/stat.h>
#include "daemonFile.h"
+#include <entCache.h>
-FileServer::FileServer(int f, UserEntCache * u, GroupEntCache * g) :
- fd(f),
- uentries(u),
- gentries(g)
+FileServer::FileServer(int f) :
+ fd(f)
{
}
@@ -36,7 +35,7 @@ FileServer::fgetattr(const NetFS::ReqEnv & re, const Ice::Current &)
throw NetFS::SystemError(errno);
}
NetFS::Attr a;
- a << StatSource { s, boost::bind(&UserEntCache::getName, uentries, _1), boost::bind(&GroupEntCache::getName, gentries, _1) };
+ a << StatSource { s, boost::bind(&UserEntCache::getName, &UserEntCache::instance, _1), boost::bind(&GroupEntCache::getName, &GroupEntCache::instance, _1) };
return a;
}
diff --git a/netfs/daemon/daemonFile.h b/netfs/daemon/daemonFile.h
index 6493bf8..8449386 100644
--- a/netfs/daemon/daemonFile.h
+++ b/netfs/daemon/daemonFile.h
@@ -2,11 +2,10 @@
#define DAEMONFILE_H
#include <file.h>
-#include "entCache.h"
class FileServer : public NetFS::File {
public:
- FileServer(int fd, UserEntCache * u, GroupEntCache * g);
+ FileServer(int fd);
virtual ~FileServer();
virtual void close(const Ice::Current&) override;
@@ -18,9 +17,6 @@ class FileServer : public NetFS::File {
private:
const int fd;
-
- UserEntCache * uentries;
- GroupEntCache * gentries;
};
#endif
diff --git a/netfs/daemon/daemonService.cpp b/netfs/daemon/daemonService.cpp
index 80305fd..0a01085 100644
--- a/netfs/daemon/daemonService.cpp
+++ b/netfs/daemon/daemonService.cpp
@@ -15,6 +15,6 @@ ServiceServer::connect(const std::string & share, const std::string &, const Ice
if (e == config->Exports.end()) {
throw NetFS::ConfigError();
}
- return NetFS::VolumePrx::checkedCast(ice.adapter->addWithUUID(new VolumeServer(e->second->RootPath, &uentries, &gentries)));
+ return NetFS::VolumePrx::checkedCast(ice.adapter->addWithUUID(new VolumeServer(e->second->RootPath)));
}
diff --git a/netfs/daemon/daemonService.h b/netfs/daemon/daemonService.h
index 4785dfa..783ad96 100644
--- a/netfs/daemon/daemonService.h
+++ b/netfs/daemon/daemonService.h
@@ -12,9 +12,6 @@ class ServiceServer : public NetFS::Service {
private:
NetFS::Daemon::ConfigurationPtr config;
-
- UserEntCache uentries;
- GroupEntCache gentries;
};
#endif
diff --git a/netfs/daemon/daemonVolume.cpp b/netfs/daemon/daemonVolume.cpp
index 0779043..c87b1b0 100644
--- a/netfs/daemon/daemonVolume.cpp
+++ b/netfs/daemon/daemonVolume.cpp
@@ -12,13 +12,12 @@
#include "lockHelpers.h"
#include "ioHelpers.h"
#include <boost/filesystem/operations.hpp>
+#include <entCache.h>
extern std::map<Ice::Int, int> files;
-VolumeServer::VolumeServer(const boost::filesystem::path & r, UserEntCache * u, GroupEntCache * g) :
- root(r),
- uentries(u),
- gentries(g)
+VolumeServer::VolumeServer(const boost::filesystem::path & r) :
+ root(r)
{
}
@@ -35,7 +34,7 @@ VolumeServer::disconnect(const Ice::Current & ice)
Ice::Int
VolumeServer::access(const NetFS::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current &)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
struct stat s;
boost::filesystem::path p(resolvePath(path));
if (::stat(p.string().c_str(), &s) != 0) {
@@ -61,7 +60,7 @@ VolumeServer::access(const NetFS::ReqEnv & re, const std::string & path, Ice::In
NetFS::Attr
VolumeServer::getattr(const NetFS::ReqEnv & re, const std::string & path, const Ice::Current &)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
struct stat s;
boost::filesystem::path p(resolvePath(path));
tp.AssertRead(p.parent_path());
@@ -69,14 +68,14 @@ VolumeServer::getattr(const NetFS::ReqEnv & re, const std::string & path, const
throw NetFS::SystemError(errno);
}
NetFS::Attr a;
- a << StatSource { s, boost::bind(&UserEntCache::getName, uentries, _1), boost::bind(&GroupEntCache::getName, gentries, _1) };
+ a << StatSource { s, boost::bind(&UserEntCache::getName, &UserEntCache::instance, _1), boost::bind(&GroupEntCache::getName, &GroupEntCache::instance, _1) };
return a;
}
void
VolumeServer::symlink(const NetFS::ReqEnv & re, const std::string & path1, const std::string & path2, const Ice::Current &)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p(resolvePath(path2));
tp.AssertWrite(p.parent_path());
@@ -92,7 +91,7 @@ VolumeServer::symlink(const NetFS::ReqEnv & re, const std::string & path1, const
void
VolumeServer::link(const NetFS::ReqEnv & re, const std::string & path1, const std::string & path2, const Ice::Current &)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p1(resolvePath(path1));
boost::filesystem::path p2(resolvePath(path2));
@@ -108,7 +107,7 @@ VolumeServer::link(const NetFS::ReqEnv & re, const std::string & path1, const st
void
VolumeServer::rename(const NetFS::ReqEnv & re, const std::string & from, const std::string & to, const Ice::Current &)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path f(resolvePath(from));
boost::filesystem::path t(resolvePath(to));
@@ -128,7 +127,7 @@ VolumeServer::rename(const NetFS::ReqEnv & re, const std::string & from, const s
std::string
VolumeServer::readlink(const NetFS::ReqEnv & re, const std::string & path, const Ice::Current &)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
char buf[PATH_MAX];
boost::filesystem::path p(resolvePath(path));
@@ -143,7 +142,7 @@ VolumeServer::readlink(const NetFS::ReqEnv & re, const std::string & path, const
void
VolumeServer::chmod(const NetFS::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current &)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p(resolvePath(path));
tp.AssertWrite(p);
@@ -155,7 +154,7 @@ VolumeServer::chmod(const NetFS::ReqEnv & re, const std::string & path, Ice::Int
void
VolumeServer::chown(const NetFS::ReqEnv & re, const std::string & path, Ice::Int uid, Ice::Int gid, const Ice::Current &)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p(resolvePath(path));
tp.AssertWrite(p);
@@ -168,7 +167,7 @@ void
VolumeServer::utimens(const NetFS::ReqEnv & re, const std::string & path,
Ice::Long s0, Ice::Long ns0, Ice::Long s1, Ice::Long ns1, const Ice::Current&)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
struct timespec times[2];
times[0].tv_sec = s0;
@@ -185,7 +184,7 @@ VolumeServer::utimens(const NetFS::ReqEnv & re, const std::string & path,
NetFS::VFS
VolumeServer::statfs(const NetFS::ReqEnv & re, const std::string & path, const Ice::Current&)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
struct statvfs s;
boost::filesystem::path p(resolvePath(path));
@@ -201,7 +200,7 @@ VolumeServer::statfs(const NetFS::ReqEnv & re, const std::string & path, const I
void
VolumeServer::truncate(const NetFS::ReqEnv & re, const std::string & path, Ice::Long size, const Ice::Current&)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p(resolvePath(path));
tp.AssertWrite(p);
@@ -213,7 +212,7 @@ VolumeServer::truncate(const NetFS::ReqEnv & re, const std::string & path, Ice::
void
VolumeServer::unlink(const NetFS::ReqEnv & re, const std::string & path, const Ice::Current&)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p(resolvePath(path));
tp.AssertWrite(p);
@@ -232,7 +231,7 @@ VolumeServer::openReadOnly(const NetFS::ReqEnv & re, const std::string & path, I
NetFS::FilePrx
VolumeServer::open(const NetFS::ReqEnv & re, const std::string & path, Ice::Int flags, const Ice::Current & ice)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p(resolvePath(path));
tp.AssertRead(p);
@@ -240,13 +239,13 @@ VolumeServer::open(const NetFS::ReqEnv & re, const std::string & path, Ice::Int
if (fd == -1) {
throw NetFS::SystemError(errno);
}
- return NetFS::FilePrx::checkedCast(ice.adapter->addWithUUID(new FileServer(fd, uentries, gentries)));
+ return NetFS::FilePrx::checkedCast(ice.adapter->addWithUUID(new FileServer(fd)));
}
NetFS::FilePrx
VolumeServer::create(const NetFS::ReqEnv & re, const std::string & path, Ice::Int flags, Ice::Int mode, const Ice::Current & ice)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p(resolvePath(path));
tp.AssertWrite(p.parent_path());
@@ -259,13 +258,13 @@ VolumeServer::create(const NetFS::ReqEnv & re, const std::string & path, Ice::In
::unlink(p.string().c_str());
throw NetFS::SystemError(errno);
}
- return NetFS::FilePrx::checkedCast(ice.adapter->addWithUUID(new FileServer(fd, uentries, gentries)));
+ return NetFS::FilePrx::checkedCast(ice.adapter->addWithUUID(new FileServer(fd)));
}
NetFS::DirectoryPrx
VolumeServer::opendir(const NetFS::ReqEnv & re, const std::string & path, const Ice::Current & ice)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p(resolvePath(path));
tp.AssertRead(p);
@@ -279,7 +278,7 @@ VolumeServer::opendir(const NetFS::ReqEnv & re, const std::string & path, const
void
VolumeServer::mkdir(const NetFS::ReqEnv & re, const std::string & path, Ice::Int mode, const Ice::Current&)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p(resolvePath(path));
tp.AssertWrite(p.parent_path());
@@ -295,7 +294,7 @@ VolumeServer::mkdir(const NetFS::ReqEnv & re, const std::string & path, Ice::Int
void
VolumeServer::rmdir(const NetFS::ReqEnv & re, const std::string & path, const Ice::Current&)
{
- TempPrivs tp(re, uentries, gentries, root);
+ TempPrivs tp(re, root);
errno = 0;
boost::filesystem::path p(resolvePath(path));
tp.AssertWrite(p);
diff --git a/netfs/daemon/daemonVolume.h b/netfs/daemon/daemonVolume.h
index c52e81a..e3ca40c 100644
--- a/netfs/daemon/daemonVolume.h
+++ b/netfs/daemon/daemonVolume.h
@@ -2,12 +2,11 @@
#define DAEMONVOLUME_H
#include <volume.h>
-#include "entCache.h"
#include <boost/thread/shared_mutex.hpp>
class VolumeServer : public NetFS::Volume {
public:
- VolumeServer(const boost::filesystem::path & root, UserEntCache * u, GroupEntCache * g);
+ VolumeServer(const boost::filesystem::path & root);
virtual ~VolumeServer();
virtual NetFS::DirectoryPrx opendir(const NetFS::ReqEnv &, const std::string & path, const Ice::Current&) override;
@@ -43,9 +42,6 @@ class VolumeServer : public NetFS::Volume {
private:
const boost::filesystem::path root;
mutable boost::shared_mutex lock;
-
- UserEntCache * uentries;
- GroupEntCache * gentries;
};
#endif
diff --git a/netfs/daemon/ioHelpers.cpp b/netfs/daemon/ioHelpers.cpp
index d06424b..05f809c 100644
--- a/netfs/daemon/ioHelpers.cpp
+++ b/netfs/daemon/ioHelpers.cpp
@@ -1,29 +1,36 @@
#include "ioHelpers.h"
+#include <entCache.h>
-bool ReadableBy(const struct stat & s, uid_t u, gid_t g)
+#define us UserEntCache::instance
+#define gs GroupEntCache::instance
+
+bool
+ReadableBy(const struct stat & s, uid_t u, gid_t g)
{
if (u == 0) return true;
if (s.st_mode & S_IROTH) return true;
- if (s.st_mode & S_IRGRP && s.st_gid == g) return true;
if (s.st_mode & S_IRUSR && s.st_uid == u) return true;
+ if (s.st_mode & S_IRGRP && (s.st_gid == g || us.getEntry(u)->group == s.st_gid || gs.getEntry(s.st_gid)->hasMember(u))) return true;
return false;
}
-bool WritableBy(const struct stat & s, uid_t u, gid_t g)
+bool
+WritableBy(const struct stat & s, uid_t u, gid_t g)
{
if (u == 0) return true;
if (s.st_mode & S_IWOTH) return true;
- if (s.st_mode & S_IWGRP && s.st_gid == g) return true;
if (s.st_mode & S_IWUSR && s.st_uid == u) return true;
+ if (s.st_mode & S_IWGRP && (s.st_gid == g || us.getEntry(u)->group == s.st_gid || gs.getEntry(s.st_gid)->hasMember(u))) return true;
return false;
}
-bool ExecutableBy(const struct stat & s, uid_t u, gid_t g)
+bool
+ExecutableBy(const struct stat & s, uid_t u, gid_t g)
{
if (u == 0 && (s.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR))) return true;
if (s.st_mode & S_IXOTH) return true;
- if (s.st_mode & S_IXGRP && s.st_gid == g) return true;
if (s.st_mode & S_IXUSR && s.st_uid == u) return true;
+ if (s.st_mode & S_IXGRP && (s.st_gid == g || us.getEntry(u)->group == s.st_gid || gs.getEntry(s.st_gid)->hasMember(u))) return true;
return false;
}
diff --git a/netfs/fuse/fuse.cpp b/netfs/fuse/fuse.cpp
index 3d14d1c..559c57c 100644
--- a/netfs/fuse/fuse.cpp
+++ b/netfs/fuse/fuse.cpp
@@ -4,6 +4,7 @@
#include "fuse.h"
#include "lockHelpers.h"
#include "cache.impl.h"
+#include <entCache.h>
template class Cache<struct stat, std::string, IceUtil::Shared, IceUtil::Handle<Cacheable<struct stat, std::string, IceUtil::Shared>>>;
template class OptimisticCallCacheable<struct stat, std::string, IceUtil::Shared>;
@@ -148,7 +149,7 @@ NetFS::FuseApp::reqEnv()
connectToService();
connectToVolume();
struct fuse_context * c = fuse_get_context();
- return { uentries.getName(c->uid), gentries.getName(c->gid) };
+ return { UserEntCache::instance.getName(c->uid), GroupEntCache::instance.getName(c->gid) };
}
int
diff --git a/netfs/fuse/fuse.h b/netfs/fuse/fuse.h
index d95dec4..859c3e6 100644
--- a/netfs/fuse/fuse.h
+++ b/netfs/fuse/fuse.h
@@ -6,7 +6,6 @@
#include <service.h>
#include "fuseapp.h"
#include "fuseConfig.h"
-#include "entCache.h"
#include "cache.h"
namespace NetFS {
@@ -102,8 +101,6 @@ namespace NetFS {
std::string exportName;
std::string configPath;
- UserEntCache uentries;
- GroupEntCache gentries;
OpenDirs openDirs;
int openDirID;
OpenFiles openFiles;
diff --git a/netfs/fuse/fuseDirs.cpp b/netfs/fuse/fuseDirs.cpp
index 35aad94..4c1b2aa 100644
--- a/netfs/fuse/fuseDirs.cpp
+++ b/netfs/fuse/fuseDirs.cpp
@@ -3,6 +3,7 @@
#include "misc.h"
#include "lockHelpers.h"
#include <typeConvert.h>
+#include <entCache.h>
NetFS::FuseApp::OpenDir::OpenDir(DirectoryPrx r, const std::string & p) :
remote(r),
@@ -78,7 +79,7 @@ NetFS::FuseApp::readdir(const char * p, void * buf, fuse_fill_dir_t filler, off_
statCache.Add(new OptimisticCallCacheable<struct stat, std::string, IceUtil::Shared>(
[asga,this]() {
struct stat s;
- s << AttrSource { volume->end_getattr(asga), boost::bind(&UserEntCache::getID, &uentries, _1), boost::bind(&GroupEntCache::getID, &gentries, _1) };
+ s << AttrSource { volume->end_getattr(asga), boost::bind(&UserEntCache::getID, &UserEntCache::instance, _1), boost::bind(&GroupEntCache::getID, &GroupEntCache::instance, _1) };
return s;
}, epath, time_t(NULL) + 2));
}
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp
index 112c383..9ce260c 100644
--- a/netfs/fuse/fuseFiles.cpp
+++ b/netfs/fuse/fuseFiles.cpp
@@ -3,6 +3,7 @@
#include <typeConvert.h>
#include "fuse.h"
#include "lockHelpers.h"
+#include <entCache.h>
NetFS::FuseApp::OpenFile::OpenFile(FilePrx r, const std::string & p, int f) :
remote(r),
@@ -134,7 +135,7 @@ NetFS::FuseApp::fgetattr(const char *, struct stat * s, fuse_file_info * fi)
{
try {
auto remote = getFileProxy(fi->fh)->remote;
- *s << AttrSource { remote->fgetattr(reqEnv()), boost::bind(&UserEntCache::getID, &uentries, _1), boost::bind(&GroupEntCache::getID, &gentries, _1) };
+ *s << AttrSource { remote->fgetattr(reqEnv()), boost::bind(&UserEntCache::getID, &UserEntCache::instance, _1), boost::bind(&GroupEntCache::getID, &GroupEntCache::instance, _1) };
return 0;
}
catch (NetFS::SystemError & e) {
diff --git a/netfs/fuse/fuseMisc.cpp b/netfs/fuse/fuseMisc.cpp
index 1eecdd4..d5064f3 100644
--- a/netfs/fuse/fuseMisc.cpp
+++ b/netfs/fuse/fuseMisc.cpp
@@ -2,6 +2,7 @@
#include "fuse.h"
#include <string.h>
#include <typeConvert.h>
+#include <entCache.h>
int
NetFS::FuseApp::access(const char * p, int a)
@@ -18,7 +19,7 @@ NetFS::FuseApp::getattr(const char * p, struct stat * s)
*s = *cacehedStat;
}
else {
- *s << AttrSource { volume->getattr(reqEnv(), p), boost::bind(&UserEntCache::getID, &uentries, _1), boost::bind(&GroupEntCache::getID, &gentries, _1) };
+ *s << AttrSource { volume->getattr(reqEnv(), p), boost::bind(&UserEntCache::getID, &UserEntCache::instance, _1), boost::bind(&GroupEntCache::getID, &GroupEntCache::instance, _1) };
}
return 0;
}
diff --git a/netfs/lib/entCache.cpp b/netfs/lib/entCache.cpp
index 02735b4..a4cf27d 100644
--- a/netfs/lib/entCache.cpp
+++ b/netfs/lib/entCache.cpp
@@ -2,77 +2,129 @@
#include "entCache.h"
#include <exceptions.h>
#include "lockHelpers.h"
+#include <pwd.h>
+#include <grp.h>
-template<class id_t, class name_t>
-EntCache<id_t, name_t>::EntCache()
+template<class entry_t>
+EntCache<entry_t>::EntCache() :
+ fillTime(0)
{
}
-template<class id_t, class name_t>
-EntCache<id_t, name_t>::~EntCache()
+template<class entry_t>
+EntCache<entry_t>::~EntCache()
{
}
-template<class id_t, class name_t>
-const id_t &
-EntCache<id_t, name_t>::getID(const name_t & u) const
+template<class entry_t>
+const typename EntCache<entry_t>::id_t &
+EntCache<entry_t>::getID(const EntCache<entry_t>::name_t & u) const
{
- SharedScopeLock(lock) {
- typename IDs::right_map::const_iterator cu = idcache.right.find(u);
- if (cu != idcache.right.end()) {
- return cu->second;
- }
+ return getEntry(u)->id;
+}
+
+template<class entry_t>
+const typename EntCache<entry_t>::name_t &
+EntCache<entry_t>::getName(const EntCache<entry_t>::id_t & u) const
+{
+ return getEntry(u)->name;
+}
+
+template<class entry_t>
+template<class key_t>
+typename EntCache<entry_t>::entry_ptr
+EntCache<entry_t>::getEntry(const key_t & key) const
+{
+ typename EntCache<entry_t>::entry_ptr ent;
+ if (fillTime + 60 > time(NULL)) {
+ ent = getEntryNoFill<key_t>(key);
}
- fillCache();
- SharedLock(lock);
- typename IDs::right_map::const_iterator cu = idcache.right.find(u);
- if (cu != idcache.right.end()) {
- return cu->second;
+ if (!ent) {
+ fillCache();
+ ent = getEntryNoFill<key_t>(key);
+ }
+ if (!ent) {
+ throw NetFS::SystemError(EPERM);
}
- throw NetFS::SystemError(EPERM);
+ return ent;
}
-template<class id_t, class name_t>
-const name_t &
-EntCache<id_t, name_t>::getName(const id_t & u) const
+template<class entry_t>
+template<class key_t>
+typename EntCache<entry_t>::entry_ptr
+EntCache<entry_t>::getEntryNoFill(const key_t & key) const
{
- SharedScopeLock(lock) {
- typename IDs::left_map::const_iterator cu = idcache.left.find(u);
- if (cu != idcache.left.end()) {
- return cu->second;
- }
- }
- fillCache();
SharedLock(lock);
- typename IDs::left_map::const_iterator cu = idcache.left.find(u);
- if (cu != idcache.left.end()) {
- return cu->second;
+ auto & collection = idcache.template get<key_t>();
+ auto i = collection.find(key);
+ if (i != collection.end()) {
+ return *i;
}
- throw NetFS::SystemError(EPERM);
+ return NULL;
}
-template class EntCache<uid_t, std::string>;
+User::User(uid_t u, const std::string & n, gid_t g) :
+ id(u),
+ name(n),
+ group(g)
+{
+}
+
+const int BUFLEN = 8196;
+
+template<>
void
-UserEntCache::fillCache() const
+EntCache<User>::fillCache() const
{
Lock(lock);
setpwent();
idcache.clear();
- while (struct passwd * pwp = getpwent()) {
- idcache.insert(boost::bimap<uid_t, std::string>::value_type(pwp->pw_uid, pwp->pw_name));
+ char buf[BUFLEN];
+ struct passwd pwbuf, * pwp;
+ while (getpwent_r(&pwbuf, buf, BUFLEN, &pwp) == 0) {
+ idcache.insert(new User(pwp->pw_uid, pwp->pw_name, pwp->pw_gid));
}
endpwent();
+ time(&fillTime);
+}
+
+Group::Group(gid_t g, const std::string & n) :
+ id(g),
+ name(n)
+{
}
+template<>
void
-GroupEntCache::fillCache() const
+EntCache<Group>::fillCache() const
{
Lock(lock);
setgrent();
+ char buf[BUFLEN];
idcache.clear();
- while (struct group * grpp = getgrent()) {
- idcache.insert(boost::bimap<gid_t, std::string>::value_type(grpp->gr_gid, grpp->gr_name));
+ struct group grpbuf, * grp;
+ while (getgrent_r(&grpbuf, buf, BUFLEN, &grp) == 0) {
+ auto g = new Group(grp->gr_gid, grp->gr_name);
+ for (auto member = grp->gr_mem; *member; member++) {
+ try {
+ g->members.insert(EntCache<User>::instance.getID(*member));
+ }
+ catch (const NetFS::SystemError &) {
+ }
+ }
+ idcache.insert(g);
}
endgrent();
+ time(&fillTime);
}
+bool
+Group::hasMember(uid_t u) const
+{
+ return (members.find(u) != members.end());
+}
+
+template<class T> const EntCache<T> EntCache<T>::instance;
+template class EntCache<User>;
+template class EntCache<Group>;
+
diff --git a/netfs/lib/entCache.h b/netfs/lib/entCache.h
index c16cd0b..ea941e8 100644
--- a/netfs/lib/entCache.h
+++ b/netfs/lib/entCache.h
@@ -1,37 +1,71 @@
#ifndef ENTCACHE_H
#define ENTCACHE_H
-#include <pwd.h>
-#include <grp.h>
#include <string>
-#include <boost/bimap.hpp>
+#include <set>
+#include <IceUtil/Shared.h>
+#include <IceUtil/Handle.h>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
#include <boost/thread/shared_mutex.hpp>
-template<class id_t, class name_t>
+class User : public IceUtil::Shared {
+ public:
+ User(uid_t, const std::string &, gid_t);
+ uid_t id;
+ std::string name;
+ gid_t group;
+};
+
+class Group : public IceUtil::Shared {
+ public:
+ Group(gid_t, const std::string &);
+
+ bool hasMember(uid_t) const;
+
+ gid_t id;
+ std::string name;
+ std::set<uid_t> members;
+};
+
+template<class entry_t>
class EntCache {
public:
- EntCache();
+ typedef decltype(entry_t::id) id_t;
+ typedef decltype(entry_t::name) name_t;
+ typedef IceUtil::Handle<entry_t> entry_ptr;
+
virtual ~EntCache();
const id_t & getID(const name_t & ) const;
const name_t & getName(const id_t &) const;
+ template<class key_t>
+ entry_ptr getEntry(const key_t &) const;
+
+ static const EntCache<entry_t> instance;
protected:
- virtual void fillCache() const = 0;
- typedef boost::bimap<id_t, name_t> IDs;
- mutable IDs idcache;
- mutable boost::shared_mutex lock;
-};
+ EntCache();
-class UserEntCache : public EntCache<uid_t, std::string> {
- private:
void fillCache() const;
-};
+ template<class key_t>
+ entry_ptr getEntryNoFill(const key_t &) const;
-class GroupEntCache : public EntCache<gid_t, std::string> {
- private:
- void fillCache() const;
+ typedef boost::multi_index::multi_index_container<IceUtil::Handle<entry_t>,
+ boost::multi_index::indexed_by<
+ boost::multi_index::ordered_unique<
+ boost::multi_index::tag<id_t>, BOOST_MULTI_INDEX_MEMBER(entry_t, const id_t, id)>,
+ boost::multi_index::ordered_unique<
+ boost::multi_index::tag<std::string>, BOOST_MULTI_INDEX_MEMBER(entry_t, const std::string, name)>
+ > > IDs;
+ mutable IDs idcache;
+ mutable boost::shared_mutex lock;
+ mutable time_t fillTime;
};
+typedef EntCache<User> UserEntCache;
+typedef EntCache<Group> GroupEntCache;
+
#endif
diff --git a/netfs/lib/pch.hpp b/netfs/lib/pch.hpp
index bfa768e..91b6a5b 100644
--- a/netfs/lib/pch.hpp
+++ b/netfs/lib/pch.hpp
@@ -3,16 +3,16 @@
#define NETFS_PCH
#include <boost/foreach.hpp>
-#include <boost/thread/locks.hpp>
-#include <boost/thread/mutex.hpp>
#include <boost/thread/shared_mutex.hpp>
-#include <boost/tuple/tuple.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/ordered_index.hpp>
#include <exception>
#include <Ice/Ice.h>
#include <map>
#include <set>
#include <string>
-#include <typeinfo>
+#include <lockHelpers.h>
#endif
#endif