summaryrefslogtreecommitdiffstats
path: root/src/cmd/vbackup/nfs3srv.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-07-13 03:49:41 +0000
committerrsc <devnull@localhost>2005-07-13 03:49:41 +0000
commit004aa293f360ea0f63ec50f5042f8c0fb2831e4f (patch)
treed44b801b47c82861d68d4045acf0bf7129ce6009 /src/cmd/vbackup/nfs3srv.c
parent0c98da8bf8ea51d0288222f6c6ba3c125cf20f46 (diff)
downloadplan9port-004aa293f360ea0f63ec50f5042f8c0fb2831e4f.tar.gz
plan9port-004aa293f360ea0f63ec50f5042f8c0fb2831e4f.zip
Dump-like file system backup for Unix, built on Venti.
Diffstat (limited to 'src/cmd/vbackup/nfs3srv.c')
-rw-r--r--src/cmd/vbackup/nfs3srv.c428
1 files changed, 428 insertions, 0 deletions
diff --git a/src/cmd/vbackup/nfs3srv.c b/src/cmd/vbackup/nfs3srv.c
new file mode 100644
index 00000000..b2cdd9cf
--- /dev/null
+++ b/src/cmd/vbackup/nfs3srv.c
@@ -0,0 +1,428 @@
+/*
+ * Simple read-only NFS v3 server.
+ * Runs every request in its own thread.
+ * Expects client to provide the fsxxx routines in nfs3srv.h.
+ */
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <sunrpc.h>
+#include <nfs3.h>
+#include "nfs3srv.h"
+
+static SunStatus
+authunixunpack(SunRpc *rpc, SunAuthUnix *au)
+{
+ uchar *p, *ep;
+ SunAuthInfo *ai;
+
+ ai = &rpc->cred;
+ if(ai->flavor != SunAuthSys)
+ return SunAuthTooWeak;
+ p = ai->data;
+ ep = p+ai->ndata;
+ if(sunauthunixunpack(p, ep, &p, au) < 0)
+ return SunGarbageArgs;
+ if(au->uid == 0)
+ au->uid = -1;
+ if(au->gid == 0)
+ au->gid = -1;
+
+ return SunSuccess;
+}
+
+static int
+rnull(SunMsg *m)
+{
+ NfsMount3RNull rx;
+
+ memset(&rx, 0, sizeof rx);
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+rmnt(SunMsg *m)
+{
+ Nfs3Handle nh;
+ NfsMount3RMnt rx;
+ SunAuthUnix au;
+ int ok;
+
+ if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
+ return sunmsgreplyerror(m, ok);
+
+ /* ignore file system path and return the dump tree */
+
+ memset(&rx, 0, sizeof rx);
+ rx.nauth = 0;
+ rx.status = 0;
+ memset(&nh, 0, sizeof nh);
+ fsgetroot(&nh);
+ rx.handle = nh.h;
+ rx.len = nh.len;
+
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+rumnt(SunMsg *m)
+{
+ NfsMount3RUmnt rx;
+
+ /* ignore */
+
+ memset(&rx, 0, sizeof rx);
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+rumntall(SunMsg *m)
+{
+ NfsMount3RUmntall rx;
+
+ /* ignore */
+
+ memset(&rx, 0, sizeof rx);
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+rexport(SunMsg *m)
+{
+ NfsMount3RExport rx;
+
+ /* ignore */
+
+ memset(&rx, 0, sizeof rx);
+ rx.count = 0;
+ return sunmsgreply(m, &rx.call);
+}
+
+static void
+rmount3(void *v)
+{
+ SunMsg *m;
+
+ m = v;
+ switch(m->call->type){
+ default:
+ sunmsgreplyerror(m, SunProcUnavail);
+ case NfsMount3CallTNull:
+ rnull(m);
+ break;
+ case NfsMount3CallTMnt:
+ rmnt(m);
+ break;
+ case NfsMount3CallTDump:
+ rmnt(m);
+ break;
+ case NfsMount3CallTUmnt:
+ rumnt(m);
+ break;
+ case NfsMount3CallTUmntall:
+ rumntall(m);
+ break;
+ case NfsMount3CallTExport:
+ rexport(m);
+ break;
+ }
+}
+
+void
+mount3proc(void *v)
+{
+ Channel *c;
+ SunMsg *m;
+
+ threadsetname("mount1");
+ c = v;
+ while((m=recvp(c)) != nil)
+ threadcreate(rmount3, m, SunStackSize);
+}
+
+static int
+senderror(SunMsg *m, SunCall *rc, Nfs3Status status)
+{
+ /* knows that status is first field in all replies */
+ ((Nfs3RGetattr*)rc)->status = status;
+ return sunmsgreply(m, rc);
+}
+
+static int
+rnull0(SunMsg *m)
+{
+ Nfs3RNull rx;
+
+ memset(&rx, 0, sizeof rx);
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+rgetattr(SunMsg *m)
+{
+ Nfs3TGetattr *tx = (Nfs3TGetattr*)m->call;
+ Nfs3RGetattr rx;
+ SunAuthUnix au;
+ int ok;
+
+ if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
+ return sunmsgreplyerror(m, ok);
+
+ memset(&rx, 0, sizeof rx);
+ rx.status = fsgetattr(&au, &tx->handle, &rx.attr);
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+rlookup(SunMsg *m)
+{
+ Nfs3TLookup *tx = (Nfs3TLookup*)m->call;
+ Nfs3RLookup rx;
+ SunAuthUnix au;
+ int ok;
+
+ if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
+ return sunmsgreplyerror(m, ok);
+
+ memset(&rx, 0, sizeof rx);
+ rx.status = fsgetattr(&au, &tx->handle, &rx.dirAttr);
+ if(rx.status != Nfs3Ok)
+ return sunmsgreply(m, &rx.call);
+ rx.haveDirAttr = 1;
+ rx.status = fslookup(&au, &tx->handle, tx->name, &rx.handle);
+ if(rx.status != Nfs3Ok)
+ return sunmsgreply(m, &rx.call);
+ rx.status = fsgetattr(&au, &rx.handle, &rx.attr);
+ if(rx.status != Nfs3Ok)
+ return sunmsgreply(m, &rx.call);
+ rx.haveAttr = 1;
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+raccess(SunMsg *m)
+{
+ Nfs3TAccess *tx = (Nfs3TAccess*)m->call;
+ Nfs3RAccess rx;
+ SunAuthUnix au;
+ int ok;
+
+ if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
+ return sunmsgreplyerror(m, ok);
+
+ memset(&rx, 0, sizeof rx);
+ rx.haveAttr = 1;
+ rx.status = fsaccess(&au, &tx->handle, tx->access, &rx.access, &rx.attr);
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+rreadlink(SunMsg *m)
+{
+ Nfs3RReadlink rx;
+ Nfs3TReadlink *tx = (Nfs3TReadlink*)m->call;
+ SunAuthUnix au;
+ int ok;
+
+ if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
+ return sunmsgreplyerror(m, ok);
+
+ memset(&rx, 0, sizeof rx);
+ rx.haveAttr = 0;
+ rx.data = nil;
+ rx.status = fsreadlink(&au, &tx->handle, &rx.data);
+ sunmsgreply(m, &rx.call);
+ free(rx.data);
+ return 0;
+}
+
+static int
+rread(SunMsg *m)
+{
+ Nfs3TRead *tx = (Nfs3TRead*)m->call;
+ Nfs3RRead rx;
+ SunAuthUnix au;
+ int ok;
+
+ if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
+ return sunmsgreplyerror(m, ok);
+
+ memset(&rx, 0, sizeof rx);
+ rx.haveAttr = 0;
+ rx.data = nil;
+ rx.status = fsreadfile(&au, &tx->handle, tx->count, tx->offset, &rx.data, &rx.count, &rx.eof);
+ if(rx.status == Nfs3Ok)
+ rx.ndata = rx.count;
+
+ sunmsgreply(m, &rx.call);
+ free(rx.data);
+ return 0;
+}
+
+static int
+rreaddir(SunMsg *m)
+{
+ Nfs3TReadDir *tx = (Nfs3TReadDir*)m->call;
+ Nfs3RReadDir rx;
+ SunAuthUnix au;
+ int ok;
+
+ if((ok = authunixunpack(&m->rpc, &au)) != SunSuccess)
+ return sunmsgreplyerror(m, ok);
+
+ memset(&rx, 0, sizeof rx);
+ rx.status = fsreaddir(&au, &tx->handle, tx->count, tx->cookie, &rx.data, &rx.count, &rx.eof);
+ sunmsgreply(m, &rx.call);
+ free(rx.data);
+ return 0;
+}
+
+static int
+rreaddirplus(SunMsg *m)
+{
+ Nfs3RReadDirPlus rx;
+
+ memset(&rx, 0, sizeof rx);
+ rx.status = Nfs3ErrNotSupp;
+ sunmsgreply(m, &rx.call);
+ return 0;
+}
+
+static int
+rfsstat(SunMsg *m)
+{
+ Nfs3RFsStat rx;
+
+ /* just make something up */
+ memset(&rx, 0, sizeof rx);
+ rx.status = Nfs3Ok;
+ rx.haveAttr = 0;
+ rx.totalBytes = 1000000000;
+ rx.freeBytes = 0;
+ rx.availBytes = 0;
+ rx.totalFiles = 100000;
+ rx.freeFiles = 0;
+ rx.availFiles = 0;
+ rx.invarSec = 0;
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+rfsinfo(SunMsg *m)
+{
+ Nfs3RFsInfo rx;
+
+ /* just make something up */
+ memset(&rx, 0, sizeof rx);
+ rx.status = Nfs3Ok;
+ rx.haveAttr = 0;
+ rx.readMax = MaxDataSize;
+ rx.readPref = MaxDataSize;
+ rx.readMult = MaxDataSize;
+ rx.writeMax = MaxDataSize;
+ rx.writePref = MaxDataSize;
+ rx.writeMult = MaxDataSize;
+ rx.readDirPref = MaxDataSize;
+ rx.maxFileSize = 1LL<<60;
+ rx.timePrec.sec = 1;
+ rx.timePrec.nsec = 0;
+ rx.flags = Nfs3FsHomogeneous|Nfs3FsCanSetTime;
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+rpathconf(SunMsg *m)
+{
+ Nfs3RPathconf rx;
+
+ memset(&rx, 0, sizeof rx);
+ rx.status = Nfs3Ok;
+ rx.haveAttr = 0;
+ rx.maxLink = 1;
+ rx.maxName = 1024;
+ rx.noTrunc = 1;
+ rx.chownRestricted = 0;
+ rx.caseInsensitive = 0;
+ rx.casePreserving = 1;
+ return sunmsgreply(m, &rx.call);
+}
+
+static int
+rrofs(SunMsg *m)
+{
+ uchar buf[512]; /* clumsy hack*/
+
+ memset(buf, 0, sizeof buf);
+ return senderror(m, (SunCall*)buf, Nfs3ErrRoFs);
+}
+
+
+static void
+rnfs3(void *v)
+{
+ SunMsg *m;
+
+ m = v;
+ switch(m->call->type){
+ default:
+ abort();
+ case Nfs3CallTNull:
+ rnull0(m);
+ break;
+ case Nfs3CallTGetattr:
+ rgetattr(m);
+ break;
+ case Nfs3CallTLookup:
+ rlookup(m);
+ break;
+ case Nfs3CallTAccess:
+ raccess(m);
+ break;
+ case Nfs3CallTReadlink:
+ rreadlink(m);
+ break;
+ case Nfs3CallTRead:
+ rread(m);
+ break;
+ case Nfs3CallTReadDir:
+ rreaddir(m);
+ break;
+ case Nfs3CallTReadDirPlus:
+ rreaddirplus(m);
+ break;
+ case Nfs3CallTFsStat:
+ rfsstat(m);
+ break;
+ case Nfs3CallTFsInfo:
+ rfsinfo(m);
+ break;
+ case Nfs3CallTPathconf:
+ rpathconf(m);
+ break;
+ case Nfs3CallTSetattr:
+ case Nfs3CallTWrite:
+ case Nfs3CallTCreate:
+ case Nfs3CallTMkdir:
+ case Nfs3CallTSymlink:
+ case Nfs3CallTMknod:
+ case Nfs3CallTRemove:
+ case Nfs3CallTRmdir:
+ case Nfs3CallTLink:
+ case Nfs3CallTCommit:
+ rrofs(m);
+ break;
+ }
+}
+
+void
+nfs3proc(void *v)
+{
+ Channel *c;
+ SunMsg *m;
+
+ c = v;
+ threadsetname("nfs3");
+ while((m = recvp(c)) != nil)
+ threadcreate(rnfs3, m, SunStackSize);
+}
+