diff options
| author | rsc <devnull@localhost> | 2005-07-13 03:49:41 +0000 |
|---|---|---|
| committer | rsc <devnull@localhost> | 2005-07-13 03:49:41 +0000 |
| commit | 004aa293f360ea0f63ec50f5042f8c0fb2831e4f (patch) | |
| tree | d44b801b47c82861d68d4045acf0bf7129ce6009 /src/cmd/vbackup/nfs3srv.c | |
| parent | 0c98da8bf8ea51d0288222f6c6ba3c125cf20f46 (diff) | |
| download | plan9port-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.c | 428 |
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); +} + |
