From 489824e6f44614f864fccc8f7b4fe9d672990cc3 Mon Sep 17 00:00:00 2001 From: randomdan Date: Thu, 5 Jun 2014 08:59:26 +0000 Subject: Static entry caches Improved checking of user/group memberships --- netfs/daemon/daemon.cpp | 6 +- netfs/daemon/daemon.h | 7 +-- netfs/daemon/daemonFile.cpp | 9 ++- netfs/daemon/daemonFile.h | 6 +- netfs/daemon/daemonService.cpp | 2 +- netfs/daemon/daemonService.h | 3 - netfs/daemon/daemonVolume.cpp | 47 ++++++++------- netfs/daemon/daemonVolume.h | 6 +- netfs/daemon/ioHelpers.cpp | 19 ++++-- netfs/fuse/fuse.cpp | 3 +- netfs/fuse/fuse.h | 3 - netfs/fuse/fuseDirs.cpp | 3 +- netfs/fuse/fuseFiles.cpp | 3 +- netfs/fuse/fuseMisc.cpp | 3 +- netfs/lib/entCache.cpp | 130 ++++++++++++++++++++++++++++------------- netfs/lib/entCache.h | 66 ++++++++++++++++----- netfs/lib/pch.hpp | 8 +-- 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 #include -#include -#include -#include -#include #include #include -#include 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 #include #include "daemonFile.h" +#include -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 -#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 +#include extern std::map 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 -#include "entCache.h" #include 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 -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 template class Cache>>; template class OptimisticCallCacheable; @@ -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 #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 +#include 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( [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 #include "fuse.h" #include "lockHelpers.h" +#include 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 #include +#include 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 #include "lockHelpers.h" +#include +#include -template -EntCache::EntCache() +template +EntCache::EntCache() : + fillTime(0) { } -template -EntCache::~EntCache() +template +EntCache::~EntCache() { } -template -const id_t & -EntCache::getID(const name_t & u) const +template +const typename EntCache::id_t & +EntCache::getID(const EntCache::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 +const typename EntCache::name_t & +EntCache::getName(const EntCache::id_t & u) const +{ + return getEntry(u)->name; +} + +template +template +typename EntCache::entry_ptr +EntCache::getEntry(const key_t & key) const +{ + typename EntCache::entry_ptr ent; + if (fillTime + 60 > time(NULL)) { + ent = getEntryNoFill(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); + } + if (!ent) { + throw NetFS::SystemError(EPERM); } - throw NetFS::SystemError(EPERM); + return ent; } -template -const name_t & -EntCache::getName(const id_t & u) const +template +template +typename EntCache::entry_ptr +EntCache::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(); + auto i = collection.find(key); + if (i != collection.end()) { + return *i; } - throw NetFS::SystemError(EPERM); + return NULL; } -template class EntCache; +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::fillCache() const { Lock(lock); setpwent(); idcache.clear(); - while (struct passwd * pwp = getpwent()) { - idcache.insert(boost::bimap::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::fillCache() const { Lock(lock); setgrent(); + char buf[BUFLEN]; idcache.clear(); - while (struct group * grpp = getgrent()) { - idcache.insert(boost::bimap::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::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 const EntCache EntCache::instance; +template class EntCache; +template class EntCache; + 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 -#include #include -#include +#include +#include +#include +#include +#include +#include #include -template +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 members; +}; + +template class EntCache { public: - EntCache(); + typedef decltype(entry_t::id) id_t; + typedef decltype(entry_t::name) name_t; + typedef IceUtil::Handle entry_ptr; + virtual ~EntCache(); const id_t & getID(const name_t & ) const; const name_t & getName(const id_t &) const; + template + entry_ptr getEntry(const key_t &) const; + + static const EntCache instance; protected: - virtual void fillCache() const = 0; - typedef boost::bimap IDs; - mutable IDs idcache; - mutable boost::shared_mutex lock; -}; + EntCache(); -class UserEntCache : public EntCache { - private: void fillCache() const; -}; + template + entry_ptr getEntryNoFill(const key_t &) const; -class GroupEntCache : public EntCache { - private: - void fillCache() const; + typedef boost::multi_index::multi_index_container, + boost::multi_index::indexed_by< + boost::multi_index::ordered_unique< + boost::multi_index::tag, BOOST_MULTI_INDEX_MEMBER(entry_t, const id_t, id)>, + boost::multi_index::ordered_unique< + boost::multi_index::tag, 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 UserEntCache; +typedef EntCache 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 -#include -#include #include -#include +#include +#include +#include #include #include #include #include #include -#include +#include #endif #endif -- cgit v1.2.3