diff options
| author | randomdan <randomdan@localhost> | 2014-06-05 08:59:26 +0000 | 
|---|---|---|
| committer | randomdan <randomdan@localhost> | 2014-06-05 08:59:26 +0000 | 
| commit | 489824e6f44614f864fccc8f7b4fe9d672990cc3 (patch) | |
| tree | bf1606dcaf162b56f824e34fe810db6539360866 | |
| parent | Split out ICE support from project jam file, add support for slicer (diff) | |
| download | netfs-489824e6f44614f864fccc8f7b4fe9d672990cc3.tar.bz2 netfs-489824e6f44614f864fccc8f7b4fe9d672990cc3.tar.xz netfs-489824e6f44614f864fccc8f7b4fe9d672990cc3.zip | |
Static entry caches
Improved checking of user/group memberships
| -rw-r--r-- | netfs/daemon/daemon.cpp | 6 | ||||
| -rw-r--r-- | netfs/daemon/daemon.h | 7 | ||||
| -rw-r--r-- | netfs/daemon/daemonFile.cpp | 9 | ||||
| -rw-r--r-- | netfs/daemon/daemonFile.h | 6 | ||||
| -rw-r--r-- | netfs/daemon/daemonService.cpp | 2 | ||||
| -rw-r--r-- | netfs/daemon/daemonService.h | 3 | ||||
| -rw-r--r-- | netfs/daemon/daemonVolume.cpp | 47 | ||||
| -rw-r--r-- | netfs/daemon/daemonVolume.h | 6 | ||||
| -rw-r--r-- | netfs/daemon/ioHelpers.cpp | 19 | ||||
| -rw-r--r-- | netfs/fuse/fuse.cpp | 3 | ||||
| -rw-r--r-- | netfs/fuse/fuse.h | 3 | ||||
| -rw-r--r-- | netfs/fuse/fuseDirs.cpp | 3 | ||||
| -rw-r--r-- | netfs/fuse/fuseFiles.cpp | 3 | ||||
| -rw-r--r-- | netfs/fuse/fuseMisc.cpp | 3 | ||||
| -rw-r--r-- | netfs/lib/entCache.cpp | 130 | ||||
| -rw-r--r-- | netfs/lib/entCache.h | 66 | ||||
| -rw-r--r-- | 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 <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 | 
