diff options
author | randomdan <randomdan@localhost> | 2009-10-23 19:17:14 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2009-10-23 19:17:14 +0000 |
commit | 212a4763b7f5236e05b38f6ab5190678e1926c0a (patch) | |
tree | ecd19468f47e1993a6e669b826a00c2f09d43337 | |
parent | All messages coded, change to ensure msg IDs are unique at compile time (diff) | |
download | netfs-212a4763b7f5236e05b38f6ab5190678e1926c0a.tar.bz2 netfs-212a4763b7f5236e05b38f6ab5190678e1926c0a.tar.xz netfs-212a4763b7f5236e05b38f6ab5190678e1926c0a.zip |
All basic funcs implemented, not tested
-rw-r--r-- | netfs/comms.cpp | 10 | ||||
-rw-r--r-- | netfs/comms.h | 19 | ||||
-rw-r--r-- | netfs/daemon.cpp | 183 | ||||
-rw-r--r-- | netfs/daemon.h | 49 | ||||
-rw-r--r-- | netfs/daemonDirs.cpp | 82 | ||||
-rw-r--r-- | netfs/daemonFS.cpp | 20 | ||||
-rw-r--r-- | netfs/daemonFiles.cpp | 118 | ||||
-rw-r--r-- | netfs/daemonMisc.cpp | 108 | ||||
-rw-r--r-- | netfs/fuse.cpp | 190 | ||||
-rw-r--r-- | netfs/fuse.h | 60 | ||||
-rw-r--r-- | netfs/fuseDirs.cpp | 48 | ||||
-rw-r--r-- | netfs/fuseFS.cpp | 13 | ||||
-rw-r--r-- | netfs/fuseFiles.cpp | 75 | ||||
-rw-r--r-- | netfs/fuseMisc.cpp | 87 | ||||
-rw-r--r-- | netfs/makefile.in | 8 | ||||
-rw-r--r-- | netfs/msgtypes.cpp | 30 | ||||
-rw-r--r-- | netfs/msgtypes.h | 10 |
17 files changed, 793 insertions, 317 deletions
diff --git a/netfs/comms.cpp b/netfs/comms.cpp index 86a7313..5993ac7 100644 --- a/netfs/comms.cpp +++ b/netfs/comms.cpp @@ -49,11 +49,11 @@ packetSender(FILE * host) Packet::Packet(FILE * host) { if (fread(&index, sizeof(index), 1, host) != 1) { - // error + throw ReadMessageFailed(); } DataPayload::TypeID t = 0; if (fread(&t, sizeof(t), 1, host) != 1) { - // error + throw ReadMessageFailed(); } data = MsgFacs()[t](); data->Read(host); @@ -62,15 +62,15 @@ void Packet::write(FILE * host) const { if (fwrite(&index, sizeof(index), 1, host) != 1) { - // error + throw WriteMessageFailed(); } DataPayload::TypeID t = data->dataTypeID(); if (fwrite(&t, sizeof(t), 1, host) != 1) { - // error + throw WriteMessageFailed(); } data->Send(host); if (fflush(host) != 0) { - // + throw WriteMessageFailed(); } } diff --git a/netfs/comms.h b/netfs/comms.h index 54681b5..cd25a9e 100644 --- a/netfs/comms.h +++ b/netfs/comms.h @@ -3,9 +3,13 @@ #include <stdio.h> #include <stdint.h> -#include <fuse/fuse.h> #include "smartpointer.h" +#include "fuseapp.h" +class WriteMessageFailed : std::exception { +}; +class ReadMessageFailed : std::exception { +}; class DataPayload : public IsRefCounted { public: typedef uint16_t TypeID; @@ -24,6 +28,9 @@ class TypedPayload : public DataPayload { void Send(FILE * h) const { data.Send(h); } void Read(FILE * h) { data.Read(h); } }; +typedef SmartPointer<DataPayload> DataPayloadPtr; +typedef SmartPointer<const DataPayload> DataPayloadCPtr; + template <class Type> class TypedPayloadReq : public TypedPayload<Type> { public: @@ -35,11 +42,15 @@ class TypedPayloadReq : public TypedPayload<Type> { TypedPayload<Type>::data.uid = fc->uid; TypedPayload<Type>::data.gid = fc->gid; } - ReplyPtr exchange(NetFS *); + ReplyPtr exchange(NetFS * net); + /* + { + DataPayloadPtr p = net->exchange(this); + return p.as<TypedPayload<typename Type::Reply> >(); + } + */ }; -typedef SmartPointer<DataPayload> DataPayloadPtr; -typedef SmartPointer<const DataPayload> DataPayloadCPtr; class Packet : public IsRefCounted { public: diff --git a/netfs/daemon.cpp b/netfs/daemon.cpp index 1cbb5bc..b029316 100644 --- a/netfs/daemon.cpp +++ b/netfs/daemon.cpp @@ -1,7 +1,6 @@ #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> -#include <dirent.h> #include <errno.h> #include <string.h> #include <set> @@ -9,163 +8,19 @@ #include "comms.h" #include "msgtypes.h" #include "misc.h" +#include "daemon.h" -class DaemonGlobalState : public IsRefCounted { -}; -typedef SmartPointer<DaemonGlobalState> DaemonGlobalStatePtr; -class Sender { - public: - Sender(int i, FILE * f) - { - idx = i; - host = f; - } - void Send(DataPayloadPtr p) - { - PacketPtr r = new Packet(idx, p); - r->write(host); - } - private: - int idx; - FILE * host; -}; -#define handler(type) void handle(SmartPointer<TypedPayload<type> > req, Sender & s) -handler(AccessRequest) -{ - TypedPayload<AccessRequest::Reply> * r = new TypedPayload<AccessRequest::Reply>(); - r->data.value = access(req->data.path.c_str(), req->data.access); - s.Send(r); -} -handler(GetAttrRequest) -{ - TypedPayload<GetAttrRequest::Reply> * r = new TypedPayload<GetAttrRequest::Reply>(); - r->data.res = stat(req->data.path.c_str(), &r->data.val); - s.Send(r); -} -int dirNo = 0; -std::map<int, DIR*> dirs; -handler(OpenDirRequest) -{ - TypedPayload<OpenDirRequest::Reply> * r = new TypedPayload<OpenDirRequest::Reply>(); - errno = 0; - DIR * od = opendir(req->data.path.c_str()); - if (od) { - dirs[++dirNo] = od; - r->data.handle = dirNo; - } - r->data.error = errno; - s.Send(r); -} -handler(CloseDirRequest) -{ - TypedPayload<CloseDirRequest::Reply> * r = new TypedPayload<CloseDirRequest::Reply>(); - if (dirs.find(req->data.handle) != dirs.end()) { - errno = 0; - if (closedir(dirs[req->data.handle]) != 0) { - r->data.error = errno; - } - else { - dirs.erase(req->data.handle); - } - } - else { - r->data.error = EBADF; - } - s.Send(r); -} -typedef TypedPayload<ReadDirContent>::Ptr DirContPLPtr; -typedef TypedPayload<ReadDirContent> DirContPL; -typedef std::set<DirContPLPtr> DirContPLs; -handler(ReadDirRequest) -{ - TypedPayload<ReadDirRequest::Reply> * r = new TypedPayload<ReadDirRequest::Reply>(); - if (dirs.find(req->data.handle) != dirs.end()) { - errno = 0; - dirent * d; - DirContPLs ds; - while ((d = readdir(dirs[req->data.handle])) && errno == 0) { - DirContPLPtr dc = new DirContPL(); - dc->data.path = d->d_name; - ds.insert(dc); - } - r->data.error = errno; - r->data.count = ds.size(); - s.Send(r); - foreach(DirContPLs::const_iterator, ds, dir) { - s.Send(*dir); - } - } - else { - r->data.error = EBADF; - s.Send(r); - } -} -int fileNo = 0; -std::map<int, int> files; -handler(OpenRequest) +Sender::Sender(int i, FILE * f) { - TypedPayload<OpenRequest::Reply> * r = new TypedPayload<OpenRequest::Reply>(); - errno = 0; - int fd = open(req->data.path.c_str(), 0); - if (fd != -1) { - files[++fileNo] = fd; - r->data.handle = fileNo; - } - r->data.error = errno; - s.Send(r); + idx = i; + host = f; } -handler(CloseRequest) +void Sender::Send(DataPayloadPtr p) { - TypedPayload<CloseRequest::Reply> * r = new TypedPayload<CloseRequest::Reply>(); - if (files.find(req->data.handle) != files.end()) { - errno = 0; - if (close(files[req->data.handle]) != 0) { - r->data.error = errno; - } - else { - files.erase(req->data.handle); - } - } - else { - r->data.error = EBADF; - } - s.Send(r); -} -handler(ReadRequest) -{ - TypedPayload<ReadRequest::Reply> * r = new TypedPayload<ReadRequest::Reply>(); - if (files.find(req->data.handle) != files.end()) { - char * tmpdata = new char[req->data.size](); - errno = 0; - if (pread(files[req->data.handle], tmpdata, req->data.size, req->data.offset) != -1) { - r->data.data = tmpdata; - r->data.size = req->data.size; - } - else { - r->data.size = 0; - r->data.data = NULL; - } - r->data.error = errno; - } - else { - r->data.error = EBADF; - } - s.Send(r); -} -handler(WriteRequest) -{ - TypedPayload<WriteRequest::Reply> * r = new TypedPayload<WriteRequest::Reply>(); - if (files.find(req->data.handle) != files.end()) { - errno = 0; - if (pwrite(files[req->data.handle], req->data.data, req->data.size, req->data.offset) != -1) { - } - r->data.error = errno; - } - else { - r->data.error = EBADF; - } - s.Send(r); + PacketPtr r = new Packet(idx, p); + r->write(host); } + #define TRYCLASS(cls) \ if (type == cls::TypeID) { handle(p->data.as<TypedPayload<cls> >(), s); } @@ -176,15 +31,33 @@ runDaemonOn(FILE * f, DaemonConfigPtr, DaemonGlobalStatePtr) PacketPtr p = new Packet(f); Sender s(p->index, f); uint16_t type (p->data->dataTypeID()); - TRYCLASS(AccessRequest); - TRYCLASS(GetAttrRequest); + // Dirs TRYCLASS(OpenDirRequest); TRYCLASS(CloseDirRequest); TRYCLASS(ReadDirRequest); + TRYCLASS(RmDirRequest); + TRYCLASS(MkDirRequest); + // Misc + TRYCLASS(AccessRequest); + TRYCLASS(GetAttrRequest); + TRYCLASS(FgetAttrRequest); + TRYCLASS(UnlinkRequest); + TRYCLASS(SymlinkRequest); + TRYCLASS(LinkRequest); + TRYCLASS(RenameRequest); + TRYCLASS(ReadlinkRequest); + TRYCLASS(ChmodRequest); + TRYCLASS(ChownRequest); + // Files TRYCLASS(OpenRequest); TRYCLASS(CloseRequest); TRYCLASS(ReadRequest); TRYCLASS(WriteRequest); + TRYCLASS(TruncateRequest); + TRYCLASS(FtruncateRequest); + TRYCLASS(CreateRequest); + // FS + TRYCLASS(StatfsRequest); } fclose(f); } diff --git a/netfs/daemon.h b/netfs/daemon.h new file mode 100644 index 0000000..2517529 --- /dev/null +++ b/netfs/daemon.h @@ -0,0 +1,49 @@ +#ifndef DAEMON_H +#define DAEMON_H + +#include "comms.h" +#include "msgtypes.h" + +class DaemonGlobalState : public IsRefCounted { +}; +typedef SmartPointer<DaemonGlobalState> DaemonGlobalStatePtr; +class Sender { + public: + Sender(int i, FILE * f); + void Send(DataPayloadPtr p); + private: + int idx; + FILE * host; +}; + +#define handler(type) void handle(SmartPointer<TypedPayload<type> > req, Sender & s) +// Dirs +handler(OpenDirRequest); +handler(CloseDirRequest); +handler(ReadDirRequest); +handler(RmDirRequest); +handler(MkDirRequest); +// Misc +handler(AccessRequest); +handler(GetAttrRequest); +handler(FgetAttrRequest); +handler(UnlinkRequest); +handler(SymlinkRequest); +handler(LinkRequest); +handler(RenameRequest); +handler(ReadlinkRequest); +handler(ChmodRequest); +handler(ChownRequest); +// Files +handler(OpenRequest); +handler(CloseRequest); +handler(ReadRequest); +handler(WriteRequest); +handler(TruncateRequest); +handler(FtruncateRequest); +handler(CreateRequest); +// FS +handler(StatfsRequest); + +#endif + diff --git a/netfs/daemonDirs.cpp b/netfs/daemonDirs.cpp new file mode 100644 index 0000000..89b2426 --- /dev/null +++ b/netfs/daemonDirs.cpp @@ -0,0 +1,82 @@ +#include <dirent.h> +#include <errno.h> +#include <set> +#include "comms.h" +#include "msgtypes.h" +#include "daemon.h" +#include "misc.h" + +int dirNo = 0; +std::map<int, DIR*> dirs; +handler(OpenDirRequest) +{ + TypedPayload<OpenDirRequest::Reply> * r = new TypedPayload<OpenDirRequest::Reply>(); + errno = 0; + DIR * od = opendir(req->data.path.c_str()); + if (od) { + dirs[++dirNo] = od; + r->data.handle = dirNo; + } + r->data.error = errno; + s.Send(r); +} +handler(CloseDirRequest) +{ + TypedPayload<CloseDirRequest::Reply> * r = new TypedPayload<CloseDirRequest::Reply>(); + if (dirs.find(req->data.handle) != dirs.end()) { + errno = 0; + if (closedir(dirs[req->data.handle]) != 0) { + r->data.error = errno; + } + else { + dirs.erase(req->data.handle); + } + } + else { + r->data.error = EBADF; + } + s.Send(r); +} +typedef TypedPayload<ReadDirContent>::Ptr DirContPLPtr; +typedef TypedPayload<ReadDirContent> DirContPL; +typedef std::set<DirContPLPtr> DirContPLs; +handler(ReadDirRequest) +{ + TypedPayload<ReadDirRequest::Reply> * r = new TypedPayload<ReadDirRequest::Reply>(); + if (dirs.find(req->data.handle) != dirs.end()) { + errno = 0; + dirent * d; + DirContPLs ds; + while ((d = readdir(dirs[req->data.handle])) && errno == 0) { + DirContPLPtr dc = new DirContPL(); + dc->data.path = d->d_name; + ds.insert(dc); + } + r->data.error = errno; + r->data.count = ds.size(); + s.Send(r); + foreach(DirContPLs::const_iterator, ds, dir) { + s.Send(*dir); + } + } + else { + r->data.error = EBADF; + s.Send(r); + } +} +handler(MkDirRequest) +{ + TypedPayload<MkDirRequest::Reply> * r = new TypedPayload<MkDirRequest::Reply>(); + errno = 0; + mkdir(req->data.path.c_str(), req->data.mode); + r->data.value = errno; + s.Send(r); +} +handler(RmDirRequest) +{ + TypedPayload<MkDirRequest::Reply> * r = new TypedPayload<MkDirRequest::Reply>(); + errno = 0; + rmdir(req->data.path.c_str()); + r->data.value = errno; + s.Send(r); +} diff --git a/netfs/daemonFS.cpp b/netfs/daemonFS.cpp new file mode 100644 index 0000000..f8220ea --- /dev/null +++ b/netfs/daemonFS.cpp @@ -0,0 +1,20 @@ +#include <errno.h> +#include <sys/vfs.h> +#include "comms.h" +#include "msgtypes.h" +#include "daemon.h" +#include "misc.h" + +handler(StatfsRequest) +{ + TypedPayload<StatfsRequest::Reply> * r = new TypedPayload<StatfsRequest::Reply>(); + errno = 0; + if (statvfs(req->data.path.c_str(), &r->data.statfs) != 0) { + r->data.error = errno; + } + else { + r->data.error = 0; + } + s.Send(r); +} + diff --git a/netfs/daemonFiles.cpp b/netfs/daemonFiles.cpp new file mode 100644 index 0000000..fe518ae --- /dev/null +++ b/netfs/daemonFiles.cpp @@ -0,0 +1,118 @@ +#include <errno.h> +#include <set> +#include "comms.h" +#include "msgtypes.h" +#include "daemon.h" +#include "misc.h" + +handler(TruncateRequest) +{ + TypedPayload<TruncateRequest::Reply> * r = new TypedPayload<TruncateRequest::Reply>(); + errno = 0; + if (truncate(req->data.path.c_str(), req->data.size) != 0) { + r->data.value = errno; + } + else { + r->data.value = 0; + } + s.Send(r); +} +handler(FtruncateRequest) +{ + TypedPayload<FtruncateRequest::Reply> * r = new TypedPayload<FtruncateRequest::Reply>(); + errno = 0; + if (ftruncate(req->data.handle, req->data.size) != 0) { + r->data.value = errno; + } + else { + r->data.value = 0; + } + s.Send(r); +} +handler(UnlinkRequest) +{ + TypedPayload<UnlinkRequest::Reply> * r = new TypedPayload<UnlinkRequest::Reply>(); + errno = 0; + unlink(req->data.path.c_str()); + r->data.value = errno; + s.Send(r); +} +int fileNo = 0; +std::map<int, int> files; +handler(OpenRequest) +{ + TypedPayload<OpenRequest::Reply> * r = new TypedPayload<OpenRequest::Reply>(); + errno = 0; + int fd = open(req->data.path.c_str(), 0); + if (fd != -1) { + files[++fileNo] = fd; + r->data.handle = fileNo; + } + r->data.error = errno; + s.Send(r); +} +handler(CreateRequest) +{ + TypedPayload<OpenRequest::Reply> * r = new TypedPayload<OpenRequest::Reply>(); + errno = 0; + int fd = open(req->data.path.c_str(), O_CREAT, req->data.mode); + if (fd != -1) { + files[++fileNo] = fd; + r->data.handle = fileNo; + } + r->data.error = errno; + s.Send(r); +} +handler(CloseRequest) +{ + TypedPayload<CloseRequest::Reply> * r = new TypedPayload<CloseRequest::Reply>(); + if (files.find(req->data.handle) != files.end()) { + errno = 0; + if (close(files[req->data.handle]) != 0) { + r->data.error = errno; + } + else { + files.erase(req->data.handle); + } + } + else { + r->data.error = EBADF; + } + s.Send(r); +} +handler(ReadRequest) +{ + TypedPayload<ReadRequest::Reply> * r = new TypedPayload<ReadRequest::Reply>(); + if (files.find(req->data.handle) != files.end()) { + char * tmpdata = new char[req->data.size](); + errno = 0; + if (pread(files[req->data.handle], tmpdata, req->data.size, req->data.offset) != -1) { + r->data.data = tmpdata; + r->data.size = req->data.size; + } + else { + r->data.size = 0; + r->data.data = NULL; + } + r->data.error = errno; + } + else { + r->data.error = EBADF; + } + s.Send(r); +} +handler(WriteRequest) +{ + TypedPayload<WriteRequest::Reply> * r = new TypedPayload<WriteRequest::Reply>(); + if (files.find(req->data.handle) != files.end()) { + errno = 0; + if (pwrite(files[req->data.handle], req->data.data, req->data.size, req->data.offset) != -1) { + } + r->data.error = errno; + } + else { + r->data.error = EBADF; + } + s.Send(r); +} + diff --git a/netfs/daemonMisc.cpp b/netfs/daemonMisc.cpp new file mode 100644 index 0000000..e3cebc3 --- /dev/null +++ b/netfs/daemonMisc.cpp @@ -0,0 +1,108 @@ +#include <errno.h> +#include <set> +#include <unistd.h> +#include <limits.h> +#include "comms.h" +#include "msgtypes.h" +#include "daemon.h" +#include "misc.h" + +handler(AccessRequest) +{ + TypedPayload<AccessRequest::Reply> * r = new TypedPayload<AccessRequest::Reply>(); + r->data.value = access(req->data.path.c_str(), req->data.access); + s.Send(r); +} +handler(GetAttrRequest) +{ + TypedPayload<GetAttrRequest::Reply> * r = new TypedPayload<GetAttrRequest::Reply>(); + errno = 0; + r->data.res = stat(req->data.path.c_str(), &r->data.val); + r->data.res = errno; + s.Send(r); +} +handler(FgetAttrRequest) +{ + TypedPayload<FgetAttrRequest::Reply> * r = new TypedPayload<FgetAttrRequest::Reply>(); + errno = 0; + r->data.res = fstat(req->data.handle, &r->data.val); + r->data.res = errno; + s.Send(r); +} +handler(SymlinkRequest) +{ + TypedPayload<SymlinkRequest::Reply> * r = new TypedPayload<SymlinkRequest::Reply>(); + errno = 0; + if (symlink(req->data.path1.c_str(), req->data.path2.c_str()) != 0) { + r->data.value = errno; + } + else { + r->data.value = 0; + } + s.Send(r); +} +handler(LinkRequest) +{ + TypedPayload<LinkRequest::Reply> * r = new TypedPayload<LinkRequest::Reply>(); + errno = 0; + if (link(req->data.path1.c_str(), req->data.path2.c_str()) != 0) { + r->data.value = errno; + } + else { + r->data.value = 0; + } + s.Send(r); +} +handler(RenameRequest) +{ + TypedPayload<RenameRequest::Reply> * r = new TypedPayload<RenameRequest::Reply>(); + errno = 0; + if (rename(req->data.path1.c_str(), req->data.path2.c_str()) != 0) { + r->data.value = errno; + } + else { + r->data.value = 0; + } + s.Send(r); +} +handler(ReadlinkRequest) +{ + TypedPayload<ReadlinkRequest::Reply> * r = new TypedPayload<ReadlinkRequest::Reply>(); + errno = 0; + char buf[PATH_MAX]; + ssize_t rc = readlink(req->data.path.c_str(), buf, PATH_MAX); + if (rc == -1) { + r->data.error = errno; + } + else { + buf[rc] = '\0'; + r->data.path = buf; + r->data.error = 0; + } + s.Send(r); +} +handler(ChmodRequest) +{ + TypedPayload<ChmodRequest::Reply> * r = new TypedPayload<ChmodRequest::Reply>(); + errno = 0; + if (chmod(req->data.path.c_str(), req->data.mode) != 0) { + r->data.value = errno; + } + else { + r->data.value = 0; + } + s.Send(r); +} +handler(ChownRequest) +{ + TypedPayload<ChownRequest::Reply> * r = new TypedPayload<ChownRequest::Reply>(); + errno = 0; + if (chown(req->data.path.c_str(), req->data.user, req->data.group) != 0) { + r->data.value = errno; + } + else { + r->data.value = 0; + } + s.Send(r); +} + diff --git a/netfs/fuse.cpp b/netfs/fuse.cpp index 610605d..c540af1 100644 --- a/netfs/fuse.cpp +++ b/netfs/fuse.cpp @@ -1,12 +1,10 @@ #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> -#include "fuseapp.h" #include <errno.h> #include <string.h> #include <stdlib.h> -#include "comms.h" -#include "msgtypes.h" +#include "fuse.h" static FuseAppBase * fuseApp; @@ -70,153 +68,55 @@ static void fuseDestroy(void * x) delete (App*)x; } -class NetFS : public FuseAppBase +NetFS::NetFS() : + f(NULL) { - int access(const char * p, int a) - { - TypedPayloadReq<AccessRequest>::Ptr msg = new TypedPayloadReq<AccessRequest>(fuse_get_context()); - msg->data.access = a; - msg->data.path = p; - return -msg->exchange(this)->data.value; - } - int getattr(const char * p, struct stat * s) - { - TypedPayloadReq<GetAttrRequest>::Ptr msg = new TypedPayloadReq<GetAttrRequest>(fuse_get_context()); - msg->data.path = p; - TypedPayload<GetAttrReply>::Ptr rep = msg->exchange(this); - *s = rep->data.val; - return -rep->data.res; - } - int opendir(const char * p, struct fuse_file_info * fi) - { - TypedPayloadReq<OpenDirRequest>::Ptr msg = new TypedPayloadReq<OpenDirRequest>(fuse_get_context()); - msg->data.path = p; - TypedPayload<OpenDirReply>::Ptr rep = msg->exchange(this); - fi->fh = rep->data.handle; - return -rep->data.error; - } - int releasedir(const char *, struct fuse_file_info * fi) - { - TypedPayloadReq<CloseDirRequest>::Ptr msg = new TypedPayloadReq<CloseDirRequest>(fuse_get_context()); - msg->data.handle = fi->fh; - TypedPayload<CloseDirReply>::Ptr rep = msg->exchange(this); - return -rep->data.error; - } - int readdir(const char *, void * buf, fuse_fill_dir_t filler, off_t, struct fuse_file_info * fi) - { - TypedPayloadReq<ReadDirRequest>::Ptr msg = new TypedPayloadReq<ReadDirRequest>(fuse_get_context()); - msg->data.handle = fi->fh; - TypedPayload<ReadDirReply>::Ptr rep = msg->exchange(this); - size_t cnt = rep->data.count; - while (cnt--) { - TypedPayload<ReadDirContent>::Ptr dir = recvType<ReadDirContent>(); - filler(buf, dir->data.path.c_str(), &dir->data.val, 0); + struct addrinfo hints; + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + struct addrinfo *result, *rp; + int s = getaddrinfo("localhost", "4000", &hints, &result); + if (s) { + // Error + } + for (rp = result; rp != NULL; rp = rp->ai_next) { + int sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sfd == -1) + // Error + continue; + if (connect(sfd, rp->ai_addr, rp->ai_addrlen)) { + // Error + continue; } - return -rep->data.error; - } - int open(const char * p, struct fuse_file_info * fi) - { - TypedPayloadReq<OpenRequest>::Ptr msg = new TypedPayloadReq<OpenRequest>(fuse_get_context()); - msg->data.path = p; - TypedPayload<OpenReply>::Ptr rep = msg->exchange(this); - fi->fh = rep->data.handle; - return -rep->data.error; - } - int release(const char *, struct fuse_file_info * fi) - { - TypedPayloadReq<CloseRequest>::Ptr msg = new TypedPayloadReq<CloseRequest>(fuse_get_context()); - msg->data.handle = fi->fh; - TypedPayload<CloseReply>::Ptr rep = msg->exchange(this); - return -rep->data.error; + f = fdopen(sfd, "a+"); + break; } - int read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi) - { - TypedPayloadReq<ReadRequest>::Ptr msg = new TypedPayloadReq<ReadRequest>(fuse_get_context()); - msg->data.handle = fi->fh; - msg->data.offset = o; - msg->data.size = s; - TypedPayload<ReadReply>::Ptr rep = msg->exchange(this); - if (rep->data.size) { - memcpy(buf, rep->data.data, std::min(s, rep->data.size)); - return rep->data.size; - } - else { - return -rep->data.error; - } - } - int write(const char *, const char * buf, size_t s, off_t o, struct fuse_file_info * fi) - { - TypedPayloadReq<WriteRequest>::Ptr msg = new TypedPayloadReq<WriteRequest>(fuse_get_context()); - msg->data.handle = fi->fh; - msg->data.offset = o; - msg->data.size = s; - msg->data.data = new char[s](); - memcpy(msg->data.data, buf, s); - TypedPayload<WriteReply>::Ptr rep = msg->exchange(this); - return -rep->data.error; +} +NetFS::~NetFS() +{ + if (f) { + fclose(f); } - public: - NetFS() : - f(NULL) - { - struct addrinfo hints; - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - struct addrinfo *result, *rp; - int s = getaddrinfo("localhost", "4000", &hints, &result); - if (s) { - // Error - } - for (rp = result; rp != NULL; rp = rp->ai_next) { - int sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (sfd == -1) - // Error - continue; - if (connect(sfd, rp->ai_addr, rp->ai_addrlen)) { - // Error - continue; - } - f = fdopen(sfd, "a+"); - break; - } - } - ~NetFS() - { - if (f) { - fclose(f); - } - } - DataPayloadPtr exchange(DataPayloadPtr dp) - { - send(dp); - return recv(); - } - void send(DataPayloadPtr dp) - { - PacketPtr sendme = new Packet(0, dp); - sendme->write(f); - } - DataPayloadPtr recv() - { - PacketPtr recvd = new Packet(f); - return recvd->data; - } - template <typename Type> - SmartPointer<TypedPayload<Type> > recvType() - { - DataPayloadPtr p = this->recv(); - return p.as<TypedPayload<Type> >(); - } - private: - FILE * f; -}; -template <typename Type> -SmartPointer<TypedPayload<typename Type::Reply> > TypedPayloadReq<Type>::exchange(NetFS * net) +} +DataPayloadPtr +NetFS::exchange(DataPayloadPtr dp) +{ + send(dp); + return recv(); +} +void +NetFS::send(DataPayloadPtr dp) +{ + PacketPtr sendme = new Packet(0, dp); + sendme->write(f); +} +DataPayloadPtr +NetFS::recv() { - DataPayloadPtr p = net->exchange(this); - return p.as<TypedPayload<typename Type::Reply> >(); + PacketPtr recvd = new Packet(f); + return recvd->data; } template <class FuseApp> diff --git a/netfs/fuse.h b/netfs/fuse.h new file mode 100644 index 0000000..dc0a124 --- /dev/null +++ b/netfs/fuse.h @@ -0,0 +1,60 @@ +#ifndef FUSE_H +#define FUSE_H + +#include "fuseapp.h" +#include "comms.h" + +class NetFS : public FuseAppBase +{ + // misc + int access(const char * p, int a); + int getattr(const char * p, struct stat * s); + int fgetattr(const char *, struct stat *, struct fuse_file_info *); + int chmod(const char *, mode_t); + int chown(const char *, uid_t, gid_t); + int link(const char *, const char *); + int readlink(const char *, char *, size_t); + int rename(const char *, const char *); + int symlink(const char *, const char *); + int unlink(const char *); + // dirs + int opendir(const char * p, struct fuse_file_info * fi); + int releasedir(const char *, struct fuse_file_info * fi); + int readdir(const char *, void * buf, fuse_fill_dir_t filler, off_t, struct fuse_file_info * fi); + int mkdir(const char *, mode_t); + int rmdir(const char *); + // files + int open(const char * p, struct fuse_file_info * fi); + int create(const char *, mode_t, struct fuse_file_info *); + int release(const char *, struct fuse_file_info * fi); + int read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi); + int write(const char *, const char * buf, size_t s, off_t o, struct fuse_file_info * fi); + int truncate(const char *, off_t); + int ftruncate(const char *, off_t, struct fuse_file_info *); + // fs + int statfs(const char *, struct statvfs *); + // stuff + public: + NetFS(); + ~NetFS(); + DataPayloadPtr exchange(DataPayloadPtr dp); + void send(DataPayloadPtr dp); + DataPayloadPtr recv(); + template <typename Type> + SmartPointer<TypedPayload<Type> > recvType() + { + DataPayloadPtr p = this->recv(); + return p.as<TypedPayload<Type> >(); + } + private: + FILE * f; +}; + +// this needs to go here to avoid circular includes regarding the net->exchange call +template<class X> +SmartPointer<TypedPayload<typename X::Reply> > TypedPayloadReq<X>::exchange(NetFS * net) +{ + DataPayloadPtr p = net->exchange(this); + return p.as<TypedPayload<typename X::Reply> >(); +} +#endif diff --git a/netfs/fuseDirs.cpp b/netfs/fuseDirs.cpp new file mode 100644 index 0000000..17e4a3e --- /dev/null +++ b/netfs/fuseDirs.cpp @@ -0,0 +1,48 @@ +#include "fuse.h" +#include "msgtypes.h" + +int +NetFS::opendir(const char * p, struct fuse_file_info * fi) +{ + TypedPayloadReq<OpenDirRequest>::Ptr msg = new TypedPayloadReq<OpenDirRequest>(fuse_get_context()); + msg->data.path = p; + TypedPayload<OpenDirReply>::Ptr rep = msg->exchange(this); + fi->fh = rep->data.handle; + return -rep->data.error; +} +int +NetFS::releasedir(const char *, struct fuse_file_info * fi) +{ + TypedPayloadReq<CloseDirRequest>::Ptr msg = new TypedPayloadReq<CloseDirRequest>(fuse_get_context()); + msg->data.handle = fi->fh; + TypedPayload<CloseDirReply>::Ptr rep = msg->exchange(this); + return -rep->data.error; +} +int +NetFS::readdir(const char *, void * buf, fuse_fill_dir_t filler, off_t, struct fuse_file_info * fi) +{ + TypedPayloadReq<ReadDirRequest>::Ptr msg = new TypedPayloadReq<ReadDirRequest>(fuse_get_context()); + msg->data.handle = fi->fh; + TypedPayload<ReadDirReply>::Ptr rep = msg->exchange(this); + size_t cnt = rep->data.count; + while (cnt--) { + TypedPayload<ReadDirContent>::Ptr dir = recvType<ReadDirContent>(); + filler(buf, dir->data.path.c_str(), &dir->data.val, 0); + } + return -rep->data.error; +} +int +NetFS::mkdir(const char * d, mode_t m) +{ + TypedPayloadReq<MkDirRequest>::Ptr msg = new TypedPayloadReq<MkDirRequest>(fuse_get_context()); + msg->data.path = d; + msg->data.mode = m; + return -msg->exchange(this)->data.value; +} +int +NetFS::rmdir(const char * d) +{ + TypedPayloadReq<RmDirRequest>::Ptr msg = new TypedPayloadReq<RmDirRequest>(fuse_get_context()); + msg->data.path = d; + return -msg->exchange(this)->data.value; +} diff --git a/netfs/fuseFS.cpp b/netfs/fuseFS.cpp new file mode 100644 index 0000000..ab27044 --- /dev/null +++ b/netfs/fuseFS.cpp @@ -0,0 +1,13 @@ +#include "fuse.h" +#include "msgtypes.h" + +int +NetFS::statfs(const char * p, struct statvfs * vfs) +{ + TypedPayloadReq<StatfsRequest>::Ptr msg = new TypedPayloadReq<StatfsRequest>(fuse_get_context()); + msg->data.path = p; + TypedPayload<StatfsReply>::Ptr rep = msg->exchange(this); + *vfs = rep->data.statfs; + return -rep->data.error; +} + diff --git a/netfs/fuseFiles.cpp b/netfs/fuseFiles.cpp new file mode 100644 index 0000000..42b3012 --- /dev/null +++ b/netfs/fuseFiles.cpp @@ -0,0 +1,75 @@ +#include <string.h> +#include "fuse.h" +#include "msgtypes.h" + +int +NetFS::open(const char * p, struct fuse_file_info * fi) +{ + TypedPayloadReq<OpenRequest>::Ptr msg = new TypedPayloadReq<OpenRequest>(fuse_get_context()); + msg->data.path = p; + TypedPayload<OpenReply>::Ptr rep = msg->exchange(this); + fi->fh = rep->data.handle; + return -rep->data.error; +} +int +NetFS::create(const char * p, mode_t m, struct fuse_file_info * fi) +{ + TypedPayloadReq<CreateRequest>::Ptr msg = new TypedPayloadReq<CreateRequest>(fuse_get_context()); + msg->data.path = p; + msg->data.mode = m; + TypedPayload<OpenReply>::Ptr rep = msg->exchange(this); + fi->fh = rep->data.handle; + return -rep->data.error; +} +int +NetFS::release(const char *, struct fuse_file_info * fi) +{ + TypedPayloadReq<CloseRequest>::Ptr msg = new TypedPayloadReq<CloseRequest>(fuse_get_context()); + msg->data.handle = fi->fh; + TypedPayload<CloseReply>::Ptr rep = msg->exchange(this); + return -rep->data.error; +} +int +NetFS::read(const char *, char * buf, size_t s, off_t o, struct fuse_file_info * fi) +{ + TypedPayloadReq<ReadRequest>::Ptr msg = new TypedPayloadReq<ReadRequest>(fuse_get_context()); + msg->data.handle = fi->fh; + msg->data.offset = o; + msg->data.size = s; + TypedPayload<ReadReply>::Ptr rep = msg->exchange(this); + if (rep->data.size) { + memcpy(buf, rep->data.data, std::min(s, rep->data.size)); + return rep->data.size; + } + else { + return -rep->data.error; + } +} +int +NetFS::write(const char *, const char * buf, size_t s, off_t o, struct fuse_file_info * fi) +{ + TypedPayloadReq<WriteRequest>::Ptr msg = new TypedPayloadReq<WriteRequest>(fuse_get_context()); + msg->data.handle = fi->fh; + msg->data.offset = o; + msg->data.size = s; + msg->data.data = new char[s](); + memcpy(msg->data.data, buf, s); + TypedPayload<WriteReply>::Ptr rep = msg->exchange(this); + return -rep->data.error; +} +int +NetFS::truncate(const char * p, off_t o) +{ + TypedPayloadReq<TruncateRequest>::Ptr msg = new TypedPayloadReq<TruncateRequest>(fuse_get_context()); + msg->data.path = p; + msg->data.size = o; + return -msg->exchange(this)->data.value; +} +int +NetFS::ftruncate(const char *, off_t o, fuse_file_info * fi) +{ + TypedPayloadReq<FtruncateRequest>::Ptr msg = new TypedPayloadReq<FtruncateRequest>(fuse_get_context()); + msg->data.handle = fi->fh; + msg->data.size = o; + return -msg->exchange(this)->data.value; +} diff --git a/netfs/fuseMisc.cpp b/netfs/fuseMisc.cpp new file mode 100644 index 0000000..2746916 --- /dev/null +++ b/netfs/fuseMisc.cpp @@ -0,0 +1,87 @@ +#include "fuse.h" +#include "msgtypes.h" +#include <string.h> + +int +NetFS::access(const char * p, int a) +{ + TypedPayloadReq<AccessRequest>::Ptr msg = new TypedPayloadReq<AccessRequest>(fuse_get_context()); + msg->data.access = a; + msg->data.path = p; + return -msg->exchange(this)->data.value; +} +int +NetFS::getattr(const char * p, struct stat * s) +{ + TypedPayloadReq<GetAttrRequest>::Ptr msg = new TypedPayloadReq<GetAttrRequest>(fuse_get_context()); + msg->data.path = p; + TypedPayload<GetAttrReply>::Ptr rep = msg->exchange(this); + *s = rep->data.val; + return -rep->data.res; +} +int +NetFS::fgetattr(const char *, struct stat * s, fuse_file_info * fi) +{ + TypedPayloadReq<FgetAttrRequest>::Ptr msg = new TypedPayloadReq<FgetAttrRequest>(fuse_get_context()); + msg->data.handle = fi->fh; + TypedPayload<GetAttrReply>::Ptr rep = msg->exchange(this); + *s = rep->data.val; + return -rep->data.res; +} +int +NetFS::chmod(const char * p, mode_t m) +{ + TypedPayloadReq<ChmodRequest>::Ptr msg = new TypedPayloadReq<ChmodRequest>(fuse_get_context()); + msg->data.path = p; + msg->data.mode = m; + return msg->exchange(this)->data.value; +} +int +NetFS::chown(const char * p, uid_t u, gid_t g) +{ + TypedPayloadReq<ChownRequest>::Ptr msg = new TypedPayloadReq<ChownRequest>(fuse_get_context()); + msg->data.path = p; + msg->data.user = u; + msg->data.group = g; + return msg->exchange(this)->data.value; +} +int +NetFS::link(const char * p1, const char * p2) +{ + TypedPayloadReq<LinkRequest>::Ptr msg = new TypedPayloadReq<LinkRequest>(fuse_get_context()); + msg->data.path1 = p1; + msg->data.path2 = p2; + return msg->exchange(this)->data.value; +} +int +NetFS::symlink(const char * p1, const char * p2) +{ + TypedPayloadReq<SymlinkRequest>::Ptr msg = new TypedPayloadReq<SymlinkRequest>(fuse_get_context()); + msg->data.path1 = p1; + msg->data.path2 = p2; + return msg->exchange(this)->data.value; +} +int +NetFS::readlink(const char * p, char * p2, size_t s) +{ + TypedPayloadReq<ReadlinkRequest>::Ptr msg = new TypedPayloadReq<ReadlinkRequest>(fuse_get_context()); + msg->data.path = p; + TypedPayload<ReadlinkReply>::Ptr rep = msg->exchange(this); + strncpy(p2, rep->data.path.c_str(), std::min(rep->data.path.length(), s)); + return -rep->data.error; +} +int +NetFS::rename(const char * p1, const char * p2) +{ + TypedPayloadReq<RenameRequest>::Ptr msg = new TypedPayloadReq<RenameRequest>(fuse_get_context()); + msg->data.path1 = p1; + msg->data.path2 = p2; + return msg->exchange(this)->data.value; +} +int +NetFS::unlink(const char * p) +{ + TypedPayloadReq<UnlinkRequest>::Ptr msg = new TypedPayloadReq<UnlinkRequest>(fuse_get_context()); + msg->data.path = p; + return msg->exchange(this)->data.value; +} diff --git a/netfs/makefile.in b/netfs/makefile.in index f7901ba..4086315 100644 --- a/netfs/makefile.in +++ b/netfs/makefile.in @@ -30,11 +30,19 @@ NETFSOBJS= \ comms.o \ fuse.o \ fuseapp.o \ + fuseFiles.o \ + fuseDirs.o \ + fuseMisc.o \ + fuseFS.o \ msgtypes.o \ NETFSDOBJS= \ comms.o \ daemon.o \ + daemonDirs.o \ + daemonFiles.o \ + daemonMisc.o \ + daemonFS.o \ daemonConfig.o \ msgtypes.o \ diff --git a/netfs/msgtypes.cpp b/netfs/msgtypes.cpp index b2d449e..9ac6b04 100644 --- a/netfs/msgtypes.cpp +++ b/netfs/msgtypes.cpp @@ -14,7 +14,8 @@ template<> void operator<<(FILE & f, const std::string & t) { std::string::size_type len = t.length(); f << len; - if (fwrite(t.data(), len, 1, &f) < len) { + if (fwrite(t.data(), len, 1, &f) != 1) { + throw WriteMessageFailed(); } } template<> void operator>>(FILE & f, std::string & t) @@ -24,17 +25,23 @@ template<> void operator>>(FILE & f, std::string & t) t.clear(); t.reserve(len); while (len --) { - t.push_back(fgetc(&f)); + int c = fgetc(&f); + if (c == EOF) { + throw ReadMessageFailed(); + } + t.push_back(c); } } template<class Type> void operator<<(FILE & f, const Type & t) { - if (fwrite(&t, sizeof(t), 1, &f) < sizeof(t)) { + if (fwrite(&t, sizeof(t), 1, &f) != 1) { + throw WriteMessageFailed(); } } template<class Type> void operator>>(FILE & f, Type & t) { - if (fread(&t, sizeof(t), 1, &f) < sizeof(t)) { + if (fread(&t, sizeof(t), 1, &f) != 1) { + throw ReadMessageFailed(); } } @@ -90,6 +97,9 @@ Xfer2(29, TruncateRequest, RequestBase, path, size) Xfer2(30, FtruncateRequest, RequestBase, handle, size) Xfer1(31, StatfsRequest, RequestBase, path) Xfer2(32, StatfsReply, ContentBase, statfs, error) +Xfer1(33, FgetAttrRequest, RequestBase, handle) +Xfer2(34, CreateRequest, RequestBase, path, mode) +Xfer1(35, RmDirRequest, RequestBase, path) MSGTYPE(2, ReadReply) ReadReply::~ReadReply() @@ -105,7 +115,8 @@ ReadReply::Send(FILE*f) const *f << error; *f << size; if (size) { - if (fwrite(data, size, 1, f) < size) { + if (fwrite(data, size, 1, f) != 1) { + throw WriteMessageFailed(); } } } @@ -117,7 +128,8 @@ ReadReply::Read(FILE*f) *f >> size; if (size) { data = new char[size](); - if (fread(data, size, 1, f) < size) { + if (fread(data, size, 1, f) != 1) { + throw ReadMessageFailed(); } } else { @@ -139,7 +151,8 @@ WriteRequest::Send(FILE*f) const *f << handle; *f << size; *f << offset; - if (fwrite(data, size, 1, f) < size) { + if (fwrite(data, size, 1, f) != 1) { + throw WriteMessageFailed(); } } void @@ -151,7 +164,8 @@ WriteRequest::Read(FILE*f) *f >> offset; if (size) { data = new char[size](); - if (fread(data, size, 1, f) < size) { + if (fread(data, size, 1, f) != 1) { + throw ReadMessageFailed(); } } else { diff --git a/netfs/msgtypes.h b/netfs/msgtypes.h index 78986d3..71909cc 100644 --- a/netfs/msgtypes.h +++ b/netfs/msgtypes.h @@ -224,6 +224,15 @@ class WriteRequest : public RequestBase { class MkDirRequest : public RequestBase { public: std::string path; + mode_t mode; + typedef SimpleInt Reply; + const static uint16_t TypeID; + virtual void Send(FILE*) const; + virtual void Read(FILE*); +}; +class RmDirRequest : public RequestBase { + public: + std::string path; typedef SimpleInt Reply; const static uint16_t TypeID; virtual void Send(FILE*) const; @@ -267,6 +276,7 @@ class RenameRequest : public RequestBase { class ReadlinkReply : public ContentBase { public: std::string path; + int error; const static uint16_t TypeID; virtual void Send(FILE*) const; virtual void Read(FILE*); |