diff options
Diffstat (limited to 'netfs/fuse/fuseFiles.cpp')
-rw-r--r-- | netfs/fuse/fuseFiles.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/netfs/fuse/fuseFiles.cpp b/netfs/fuse/fuseFiles.cpp new file mode 100644 index 0000000..4a96e51 --- /dev/null +++ b/netfs/fuse/fuseFiles.cpp @@ -0,0 +1,155 @@ +#include "pch.hpp" +#include <string.h> +#include <typeConvert.h> +#include "fuse.h" + +NetFS::FuseApp::OpenFile::OpenFile(FilePrx r, const std::string & p, int f) : + remote(r), + path(p), + flags(f) +{ +} + +void +NetFS::FuseApp::setProxy(OpenFilePtr of, uint64_t & fh) +{ + LOCK; + while (openFiles.find(fh = ++openFileID) != openFiles.end()) ; + openFiles.insert({ fh, of }); +} + +NetFS::FuseApp::OpenFilePtr +NetFS::FuseApp::getFileProxy(uint64_t localID) const +{ + SLOCK; + OpenFiles::const_iterator i = openFiles.find(localID); + if (i != openFiles.end()) { + return i->second; + } + throw NetFS::SystemError(EBADF); +} + +void +NetFS::FuseApp::clearFileProxy(uint64_t localID) +{ + LOCK; + openFiles.erase(localID); +} + +int +NetFS::FuseApp::open(const char * p, struct fuse_file_info * fi) +{ + try { + auto remote = volume->open(reqEnv(), p, fi->flags); + setProxy(new OpenFile(remote, p, fi->flags), fi->fh); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::create(const char * p, mode_t m, struct fuse_file_info * fi) +{ + try { + auto remote = volume->create(reqEnv(), p, fi->flags, m); + setProxy(new OpenFile(remote, p, fi->flags), fi->fh); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::release(const char *, struct fuse_file_info * fi) +{ + try { + auto remote = getFileProxy(fi->fh)->remote; + remote->close(); + clearFileProxy(fi->fh); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi) +{ + try { + auto remote = getFileProxy(fi->fh)->remote; + NetFS::Buffer data = remote->read(o, s); + memcpy(buf, &data.front(), data.size()); + return data.size(); + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::write(const char *, const char * buf, size_t s, off_t o, struct fuse_file_info * fi) +{ + try { + auto remote = getFileProxy(fi->fh)->remote; + remote->write(o, s, NetFS::Buffer(buf, buf + s)); + return s; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::truncate(const char * p, off_t o) +{ + try { + volume->truncate(reqEnv(), p, o); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::ftruncate(const char *, off_t o, fuse_file_info * fi) +{ + try { + auto remote = getFileProxy(fi->fh)->remote; + remote->ftruncate(reqEnv(), o); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +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) }; + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + +int +NetFS::FuseApp::unlink(const char * p) +{ + try { + volume->unlink(reqEnv(), p); + return 0; + } + catch (NetFS::SystemError & e) { + return -e.syserrno; + } +} + |