diff options
-rw-r--r-- | netfs/daemon/daemonVolume.cpp | 4 | ||||
-rw-r--r-- | netfs/fuse/Jamfile.jam | 4 | ||||
-rw-r--r-- | netfs/fuse/fuseApp.cpp | 16 | ||||
-rw-r--r-- | netfs/fuse/fuseApp.h | 2 | ||||
-rw-r--r-- | netfs/fuse/fuseConfig.ice | 3 | ||||
-rw-r--r-- | netfs/ice/Jamfile.jam | 6 | ||||
-rw-r--r-- | netfs/ice/entryResolver.h | 20 | ||||
-rw-r--r-- | netfs/ice/mapper.ice | 31 | ||||
-rw-r--r-- | netfs/ice/typeConverter.cpp | 16 | ||||
-rw-r--r-- | netfs/ice/typeConverter.h | 11 | ||||
-rw-r--r-- | netfs/lib/defaultMapper.cpp | 26 | ||||
-rw-r--r-- | netfs/lib/defaultMapper.h | 21 | ||||
-rw-r--r-- | netfs/lib/entCache.h | 31 | ||||
-rw-r--r-- | netfs/lib/entCache.impl.h | 70 | ||||
-rw-r--r-- | netfs/lib/entryResolver.h | 14 | ||||
-rw-r--r-- | netfs/unittests/Jamfile.jam | 2 | ||||
-rw-r--r-- | netfs/unittests/testLib.cpp | 62 |
17 files changed, 157 insertions, 182 deletions
diff --git a/netfs/daemon/daemonVolume.cpp b/netfs/daemon/daemonVolume.cpp index 3ae43da..7ae3a1f 100644 --- a/netfs/daemon/daemonVolume.cpp +++ b/netfs/daemon/daemonVolume.cpp @@ -7,6 +7,7 @@ #include <boost/algorithm/string/predicate.hpp> #include <cerrno> #include <climits> +#include <defaultMapper.h> #include <entCache.h> #include <fcntl.h> #include <map> @@ -16,7 +17,8 @@ extern std::map<Ice::Int, int> files; VolumeServer::VolumeServer(const std::filesystem::path & r, const EntCache<User> & u, const EntCache<Group> & g) : - root(std::filesystem::canonical(r)), userLookup(u), groupLookup(g), converter(u, g) + root(std::filesystem::canonical(r)), userLookup(u), groupLookup(g), + converter(std::make_shared<NetFS::Mapping::DefaultMapper>()) { } diff --git a/netfs/fuse/Jamfile.jam b/netfs/fuse/Jamfile.jam index 14338d5..8516d8b 100644 --- a/netfs/fuse/Jamfile.jam +++ b/netfs/fuse/Jamfile.jam @@ -6,6 +6,8 @@ obj fuseConfig : fuseConfig.ice : <toolset>tidy:<checker>none <library>../ice//netfs-api <implicit-dependency>../ice//netfs-api + <library>..//slicer + <include>. ; lib netfs-client-configuration : fuseConfig @@ -19,9 +21,11 @@ lib netfs-client-configuration : <library>..//Ice <library>..//slicer <library>..//adhocutil + <include>. : : <library>..//Ice <library>..//slicer + <include>. ; lib netfs-client : diff --git a/netfs/fuse/fuseApp.cpp b/netfs/fuse/fuseApp.cpp index 78a3a03..f0576b3 100644 --- a/netfs/fuse/fuseApp.cpp +++ b/netfs/fuse/fuseApp.cpp @@ -7,6 +7,7 @@ #include <boost/lexical_cast.hpp> #include <compileTimeFormatter.h> #include <cstring> +#include <defaultMapper.h> #include <entCache.h> #include <safeMapFind.h> #include <slicer/slicer.h> @@ -17,10 +18,7 @@ namespace AdHoc { template class CallCacheable<struct stat, std::string>; } -NetFS::FuseApp::FuseApp(Ice::StringSeq && a) : - iceArgs(std::move(a)), sessionOpened(false), openHandleId(0), converter(userLookup, groupLookup) -{ -} +NetFS::FuseApp::FuseApp(Ice::StringSeq && a) : iceArgs(std::move(a)), sessionOpened(false), openHandleId(0) { } NetFS::FuseApp::~FuseApp() { @@ -80,7 +78,11 @@ NetFS::FuseApp::init(struct fuse_conn_info *, struct fuse_config *) fcr = configureFromFile(arg.substr(0, colon), arg.substr(colon + 1)); } } + if (!fcr->mapper) { + fcr->mapper = std::make_shared<Mapping::DefaultMapper>(); + } BOOST_ASSERT(fcr); + converter.mapper = fcr->mapper; return this; } @@ -275,8 +277,6 @@ NetFS::ReqEnv NetFS::FuseApp::reqEnv() { struct fuse_context * c = fuse_get_context(); - NetFS::ReqEnv re; - userLookup.getName(c->uid, &re.user); - groupLookup.getName(c->gid, &re.grp); - return re; + const auto t = converter.mapper->mapFileSystem(c->uid, c->gid); + return {t.username, t.groupname}; } diff --git a/netfs/fuse/fuseApp.h b/netfs/fuse/fuseApp.h index d373e94..b905b23 100644 --- a/netfs/fuse/fuseApp.h +++ b/netfs/fuse/fuseApp.h @@ -111,8 +111,6 @@ namespace NetFS { OpenFiles openFiles; int openHandleId; - EntCache<User> userLookup; - EntCache<Group> groupLookup; EntryTypeConverter converter; using StatCache = AdHoc::Cache<struct stat, std::string>; diff --git a/netfs/fuse/fuseConfig.ice b/netfs/fuse/fuseConfig.ice index 52116ea..2d2bf9f 100644 --- a/netfs/fuse/fuseConfig.ice +++ b/netfs/fuse/fuseConfig.ice @@ -1,4 +1,5 @@ #include <exceptions.ice> +#include <mapper.ice> module NetFS { module Client { @@ -20,6 +21,8 @@ module NetFS { ["slicer:name:async"] bool Async = false; + + Mapping::Mapper mapper; }; ["slicer:key:name","slicer:value:resource","slicer:item:resource"] diff --git a/netfs/ice/Jamfile.jam b/netfs/ice/Jamfile.jam index cfb4f14..a695712 100644 --- a/netfs/ice/Jamfile.jam +++ b/netfs/ice/Jamfile.jam @@ -6,14 +6,18 @@ obj file : file.ice : <toolset>tidy:<checker>none ; obj service : service.ice : <toolset>tidy:<checker>none ; obj types : types.ice : <toolset>tidy:<checker>none ; obj volume : volume.ice : <toolset>tidy:<checker>none ; -alias gen : directory exceptions file service types volume ; +obj mapper : mapper.ice : <toolset>tidy:<checker>none ; +alias gen : directory exceptions file service types volume mapper ; lib netfs-api : gen + mapper.ice [ glob *.cpp ] : <library>..//Ice <library>..//pthread <library>..//adhocutil + <library>..//slicer <implicit-dependency>gen + <slicer>pure : : <include>. <library>..//Ice diff --git a/netfs/ice/entryResolver.h b/netfs/ice/entryResolver.h deleted file mode 100644 index 973af4c..0000000 --- a/netfs/ice/entryResolver.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef NETFS_ENTRYRESOLVER_H -#define NETFS_ENTRYRESOLVER_H - -#include <cstdint> -#include <unistd.h> - -enum class ResolvedAs : uint8_t { - Real, - Fallback, -}; - -template<typename id_t, typename name_t> class EntryResolver { -public: - virtual ~EntryResolver() = default; - - virtual ResolvedAs getID(const name_t &, id_t *) const = 0; - virtual ResolvedAs getName(const id_t &, name_t *) const = 0; -}; - -#endif diff --git a/netfs/ice/mapper.ice b/netfs/ice/mapper.ice new file mode 100644 index 0000000..d2f31e8 --- /dev/null +++ b/netfs/ice/mapper.ice @@ -0,0 +1,31 @@ +#ifndef _MAPPER +#define _MAPPER + +#include "exceptions.ice" + +module NetFS { + module Mapping { + ["slicer:ignore"] + local struct Transport { + string username; + string groupname; + int mask; + }; + + ["slicer:ignore"] + local struct FileSystem { + int uid; + int gid; + int mask; + }; + + local class Mapper { + Transport mapFileSystem(int uid, int gid) throws SystemError; + FileSystem mapTransport(string un, string gn) throws SystemError; + }; + }; + +} + +#endif + diff --git a/netfs/ice/typeConverter.cpp b/netfs/ice/typeConverter.cpp index e365c5d..6b33828 100644 --- a/netfs/ice/typeConverter.cpp +++ b/netfs/ice/typeConverter.cpp @@ -1,7 +1,7 @@ #include "typeConverter.h" #include <boost/numeric/conversion/cast.hpp> -EntryTypeConverter::EntryTypeConverter(const UserLookup & u, const GroupLookup & g) : userLookup(u), groupLookup(g) { } +EntryTypeConverter::EntryTypeConverter(NetFS::Mapping::MapperPtr m) : mapper(m) { } // Wrapper function to assure no unexpected corruption occurs // during narrowing assignments. @@ -16,14 +16,15 @@ safeAssign(T & t, const S & s) struct stat EntryTypeConverter::convert(const NetFS::Attr & a) const { + auto map = mapper->mapTransport(a.uid, a.gid); struct stat s { }; s.st_dev = a.dev; s.st_ino = a.inode; - s.st_mode = a.mode; + s.st_mode = a.mode & ~map.mask; s.st_nlink = a.links; - userLookup.getID(a.uid, &s.st_uid); - groupLookup.getID(a.gid, &s.st_gid); + s.st_uid = map.uid; + s.st_gid = map.gid; s.st_rdev = a.rdev; s.st_size = a.size; s.st_blksize = a.blockSize; @@ -62,13 +63,14 @@ TypeConverter::convert(const NetFS::VFS & v) const NetFS::Attr EntryTypeConverter::convert(const struct stat & s) const { + auto map = mapper->mapFileSystem(s.st_uid, s.st_gid); NetFS::Attr a {}; a.dev = s.st_dev; a.inode = s.st_ino; - a.mode = s.st_mode; + a.mode = s.st_mode & ~map.mask; a.links = s.st_nlink; - userLookup.getName(s.st_uid, &a.uid); - groupLookup.getName(s.st_gid, &a.gid); + a.uid = std::move(map.username); + a.gid = std::move(map.groupname); a.rdev = s.st_rdev; a.size = s.st_size; a.blockSize = s.st_blksize; diff --git a/netfs/ice/typeConverter.h b/netfs/ice/typeConverter.h index 3cd2941..0baff2b 100644 --- a/netfs/ice/typeConverter.h +++ b/netfs/ice/typeConverter.h @@ -1,7 +1,7 @@ #ifndef NETFS_TYPECONVERT_H #define NETFS_TYPECONVERT_H -#include "entryResolver.h" +#include <mapper.h> #include <sys/stat.h> #include <sys/statvfs.h> #include <types.h> @@ -16,17 +16,14 @@ public: class DLL_PUBLIC EntryTypeConverter : public TypeConverter { public: - using UserLookup = EntryResolver<uid_t, std::string>; - using GroupLookup = EntryResolver<gid_t, std::string>; - EntryTypeConverter(const UserLookup &, const GroupLookup &); + EntryTypeConverter() = default; + EntryTypeConverter(NetFS::Mapping::MapperPtr); // Attributes struct stat convert(const NetFS::Attr &) const; NetFS::Attr convert(const struct stat &) const; -protected: - const UserLookup & userLookup; - const GroupLookup & groupLookup; + NetFS::Mapping::MapperPtr mapper; }; #endif diff --git a/netfs/lib/defaultMapper.cpp b/netfs/lib/defaultMapper.cpp new file mode 100644 index 0000000..1d75e12 --- /dev/null +++ b/netfs/lib/defaultMapper.cpp @@ -0,0 +1,26 @@ +#include "defaultMapper.h" +#include <exceptions.h> + +namespace NetFS::Mapping { + FileSystem + DefaultMapper::mapTransport(const std::string & un, const std::string & gn) + { + auto u = users.getEntry(un); + auto g = groups.getEntry(gn); + if (!u || !g) { + throw NetFS::SystemError(EPERM); + } + return {static_cast<int>(u->id), static_cast<int>(g->id), 0}; + } + + Transport + DefaultMapper::mapFileSystem(int uid, int gid) + { + auto u = users.getEntry(uid); + auto g = groups.getEntry(gid); + if (!u || !g) { + throw NetFS::SystemError(EPERM); + } + return {u->name, g->name, 0}; + } +} diff --git a/netfs/lib/defaultMapper.h b/netfs/lib/defaultMapper.h new file mode 100644 index 0000000..719c7bf --- /dev/null +++ b/netfs/lib/defaultMapper.h @@ -0,0 +1,21 @@ +#ifndef NETFS_MAPPING_DEFAULTIMPL_H +#define NETFS_MAPPING_DEFAULTIMPL_H + +#include "entCache.h" +#include <mapper.h> + +namespace NetFS { + namespace Mapping { + class DefaultMapper : public Mapper { + public: + Transport mapFileSystem(int uid, int gid) override; + FileSystem mapTransport(const std::string & un, const std::string & gn) override; + + protected: + UserEntCache users; + GroupEntCache groups; + }; + } +} + +#endif diff --git a/netfs/lib/entCache.h b/netfs/lib/entCache.h index e8c6461..02224f5 100644 --- a/netfs/lib/entCache.h +++ b/netfs/lib/entCache.h @@ -1,11 +1,12 @@ #ifndef ENTCACHE_H #define ENTCACHE_H +#include "entryResolver.h" #include <c++11Helpers.h> -#include <entryResolver.h> #include <set> #include <shared_mutex> #include <string> +#include <unistd.h> class User { public: @@ -26,11 +27,10 @@ public: std::set<uid_t> members; }; -template<class entry_t> class EntCache : public EntryResolver<decltype(entry_t::id), decltype(entry_t::name)> { +template<class entry_t> class EntCache : public EntryResolver<entry_t> { public: EntCache(); - EntCache(entry_t fb); - ~EntCache() override; + ~EntCache() noexcept override; SPECIAL_MEMBERS_DEFAULT_MOVE_NO_COPY(EntCache); @@ -38,27 +38,24 @@ public: using name_t = decltype(entry_t::name); using entry_ptr = std::shared_ptr<entry_t>; - struct Resolution : public entry_ptr { - Resolution(entry_ptr, ResolvedAs = ResolvedAs::Real); - ResolvedAs resolution; + [[nodiscard]] entry_ptr inline getEntry(const id_t & i) const noexcept override + { + return getEntryInternal<id_t>(i); + } + [[nodiscard]] entry_ptr inline getEntry(const name_t & n) const noexcept override + { + return getEntryInternal<name_t>(n); }; - ResolvedAs getID(const name_t &, id_t *) const override; - ResolvedAs getName(const id_t &, name_t *) const override; - template<class key_t> Resolution getEntry(const key_t &) const; - - void setFallback(entry_t fb); - void clearFallback(); - protected: - void fillCache() const; - template<class key_t> entry_ptr getEntryNoFill(const key_t &) const; + void fillCache() const noexcept; + template<class key_t>[[nodiscard]] entry_ptr getEntryInternal(const key_t &) const noexcept; + template<class key_t>[[nodiscard]] entry_ptr getEntryNoFill(const key_t &) const noexcept; class Ids; std::unique_ptr<Ids> idcache; mutable std::shared_mutex lock; mutable time_t fillTime {0}; - entry_ptr fallback; }; using UserEntCache = EntCache<User>; diff --git a/netfs/lib/entCache.impl.h b/netfs/lib/entCache.impl.h index 0021f00..6243d7d 100644 --- a/netfs/lib/entCache.impl.h +++ b/netfs/lib/entCache.impl.h @@ -5,7 +5,6 @@ #include <boost/multi_index/member.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index_container.hpp> -#include <exceptions.h> #include <grp.h> #include <lockHelpers.h> #include <pwd.h> @@ -21,41 +20,12 @@ class EntCache<entry_t>::Ids : }; template<class entry_t> EntCache<entry_t>::EntCache() : idcache(std::make_unique<Ids>()) { } - -template<class entry_t> EntCache<entry_t>::EntCache(entry_t fb) : idcache(std::make_unique<Ids>()) -{ - setFallback(std::move(fb)); -} - -template<class entry_t> EntCache<entry_t>::~EntCache() = default; - -template<class entry_t> -ResolvedAs -EntCache<entry_t>::getID(const EntCache<entry_t>::name_t & u, EntCache<entry_t>::id_t * target) const -{ - auto e = getEntry(u); - *target = e->id; - return e.resolution; -} - -template<class entry_t> -ResolvedAs -EntCache<entry_t>::getName(const EntCache<entry_t>::id_t & u, EntCache<entry_t>::name_t * target) const -{ - auto e = getEntry(u); - *target = e->name; - return e.resolution; -} - -template<class entry_t> -EntCache<entry_t>::Resolution::Resolution(entry_ptr e, ResolvedAs res) : entry_ptr(std::move(e)), resolution(res) -{ -} +template<class entry_t> EntCache<entry_t>::~EntCache() noexcept = default; template<class entry_t> template<class key_t> -typename EntCache<entry_t>::Resolution -EntCache<entry_t>::getEntry(const key_t & key) const +typename EntCache<entry_t>::entry_ptr +EntCache<entry_t>::getEntryInternal(const key_t & key) const noexcept { if (fillTime + 60 > time(nullptr)) { if (auto ent = getEntryNoFill<key_t>(key)) { @@ -63,19 +33,13 @@ EntCache<entry_t>::getEntry(const key_t & key) const } } fillCache(); - if (auto ent = getEntryNoFill<key_t>(key)) { - return ent; - } - if (fallback) { - return {fallback, ResolvedAs::Fallback}; - } - throw NetFS::SystemError(EPERM); + return getEntryNoFill<key_t>(key); } template<class entry_t> template<class key_t> typename EntCache<entry_t>::entry_ptr -EntCache<entry_t>::getEntryNoFill(const key_t & key) const +EntCache<entry_t>::getEntryNoFill(const key_t & key) const noexcept { SharedLock(lock); auto & collection = idcache->template get<key_t>(); @@ -86,27 +50,13 @@ EntCache<entry_t>::getEntryNoFill(const key_t & key) const return nullptr; } -template<typename entry_t> -void -EntCache<entry_t>::setFallback(entry_t fb) -{ - fallback = std::make_shared<entry_t>(std::move(fb)); -} - -template<typename entry_t> -void -EntCache<entry_t>::clearFallback() -{ - fallback.reset(); -} - User::User(uid_t u, std::string n, gid_t g) : id(u), name(std::move(n)), group(g) { } const int BUFLEN = 8196; template<> void -EntCache<User>::fillCache() const +EntCache<User>::fillCache() const noexcept { Lock(lock); setpwent(); @@ -125,7 +75,7 @@ Group::Group(gid_t g, std::string n) : id(g), name(std::move(n)) { } template<> void -EntCache<Group>::fillCache() const +EntCache<Group>::fillCache() const noexcept { Lock(lock); setgrent(); @@ -137,10 +87,8 @@ EntCache<Group>::fillCache() const while (getgrent_r(&grpbuf, buf.data(), buf.size(), &grp) == 0) { auto g = std::make_shared<Group>(grp->gr_gid, grp->gr_name); for (auto member = grp->gr_mem; *member; member++) { - try { - g->members.insert(instance.getEntry((const name_t &)*member)->id); - } - catch (const NetFS::SystemError &) { + if (auto ent = instance.getEntry((const gid_t &)*member)) { + g->members.insert(ent->id); } } idcache->insert(std::move(g)); diff --git a/netfs/lib/entryResolver.h b/netfs/lib/entryResolver.h new file mode 100644 index 0000000..84eb6ed --- /dev/null +++ b/netfs/lib/entryResolver.h @@ -0,0 +1,14 @@ +#ifndef NETFS_ENTRYRESOLVER_H +#define NETFS_ENTRYRESOLVER_H + +#include <memory> + +template<typename entry_t> class EntryResolver { +public: + virtual ~EntryResolver() noexcept = default; + + virtual std::shared_ptr<entry_t> getEntry(const decltype(entry_t::id) &) const noexcept = 0; + virtual std::shared_ptr<entry_t> getEntry(const decltype(entry_t::name) &) const noexcept = 0; +}; + +#endif diff --git a/netfs/unittests/Jamfile.jam b/netfs/unittests/Jamfile.jam index f1f3dba..18abadd 100644 --- a/netfs/unittests/Jamfile.jam +++ b/netfs/unittests/Jamfile.jam @@ -74,7 +74,6 @@ run testLib.cpp <library>testMocks ; -# explicit testFuse ; run testFuse.cpp : -- : defaultDaemon.xml @@ -82,5 +81,6 @@ run testFuse.cpp <define>BOOST_TEST_DYN_LINK <library>boost_utf <library>testMocks + <dependency>testCore ; diff --git a/netfs/unittests/testLib.cpp b/netfs/unittests/testLib.cpp index b44ab37..14ea71f 100644 --- a/netfs/unittests/testLib.cpp +++ b/netfs/unittests/testLib.cpp @@ -4,15 +4,6 @@ #include <entCache.impl.h> #include <lockHelpers.h> -namespace std { - ostream & - operator<<(ostream & strm, const ResolvedAs & r) - { - strm << r; - return strm; - } -} - struct TestEntry { TestEntry(int i, std::string n) : id(i), name(std::move(n)) { } @@ -23,7 +14,7 @@ using TestEntCache = EntCache<TestEntry>; template<> void -EntCache<TestEntry>::fillCache() const +EntCache<TestEntry>::fillCache() const noexcept { Lock(lock); idcache->insert(std::make_shared<TestEntry>(1, "user1")); @@ -40,65 +31,22 @@ BOOST_FIXTURE_TEST_SUITE(tec, TestEntCache); BOOST_DATA_TEST_CASE(notfoundid, BadIds, id) { - std::string outname; - BOOST_CHECK_THROW(getName(id, &outname), NetFS::SystemError); -} - -BOOST_DATA_TEST_CASE(notfoundname, BadNames, name) -{ - int outid; - BOOST_CHECK_THROW(getID(name, &outid), NetFS::SystemError); -} - -BOOST_DATA_TEST_CASE(foundid, GoodNames ^ GoodIds, name, id) -{ - std::string outname; - BOOST_CHECK_EQUAL(getName(id, &outname), ResolvedAs::Real); - BOOST_CHECK_EQUAL(name, outname); -} - -BOOST_DATA_TEST_CASE(foundname, GoodNames ^ GoodIds, name, id) -{ - int outid; - BOOST_CHECK_EQUAL(getID(name, &outid), ResolvedAs::Real); - BOOST_CHECK_EQUAL(id, outid); -} - -BOOST_AUTO_TEST_SUITE_END(); - -class TestEntCacheWithFallback : public TestEntCache { -public: - TestEntCacheWithFallback() : TestEntCache({4, "fallback"}) { } -}; - -BOOST_FIXTURE_TEST_SUITE(tecfb, TestEntCacheWithFallback); - -BOOST_DATA_TEST_CASE(notfoundid, BadIds, id) -{ - std::string outname; - BOOST_CHECK_EQUAL(getName(id, &outname), ResolvedAs::Fallback); - BOOST_CHECK_EQUAL(outname, fallback->name); + BOOST_CHECK(!getEntry(id)); } BOOST_DATA_TEST_CASE(notfoundname, BadNames, name) { - int outid; - BOOST_CHECK_EQUAL(getID(name, &outid), ResolvedAs::Fallback); - BOOST_CHECK_EQUAL(outid, fallback->id); + BOOST_CHECK(!getEntry(name)); } BOOST_DATA_TEST_CASE(foundid, GoodNames ^ GoodIds, name, id) { - std::string outname; - BOOST_CHECK_EQUAL(getName(id, &outname), ResolvedAs::Real); - BOOST_CHECK_EQUAL(name, outname); + BOOST_CHECK_EQUAL(getEntry(id)->name, name); } BOOST_DATA_TEST_CASE(foundname, GoodNames ^ GoodIds, name, id) { - int outid; - BOOST_CHECK_EQUAL(getID(name, &outid), ResolvedAs::Real); - BOOST_CHECK_EQUAL(id, outid); + BOOST_CHECK_EQUAL(getEntry(name)->id, id); } BOOST_AUTO_TEST_SUITE_END(); |