summaryrefslogtreecommitdiff
path: root/netfs/fuse/fuseFiles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netfs/fuse/fuseFiles.cpp')
-rw-r--r--netfs/fuse/fuseFiles.cpp155
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;
+ }
+}
+