diff options
| -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*);  | 
