summaryrefslogtreecommitdiff
path: root/sys/src/cmd/9nfs/nfs.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/9nfs/nfs.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/9nfs/nfs.c')
-rwxr-xr-xsys/src/cmd/9nfs/nfs.c471
1 files changed, 471 insertions, 0 deletions
diff --git a/sys/src/cmd/9nfs/nfs.c b/sys/src/cmd/9nfs/nfs.c
new file mode 100755
index 000000000..c01536742
--- /dev/null
+++ b/sys/src/cmd/9nfs/nfs.c
@@ -0,0 +1,471 @@
+#include "all.h"
+
+extern uchar buf[];
+
+Xfid *
+rpc2xfid(Rpccall *cmd, Dir *dp)
+{
+ char *argptr = cmd->args;
+ Xfile *xp;
+ Xfid *xf;
+ Session *s;
+ char *service;
+ Authunix au;
+ Qid qid;
+ char client[256], *user;
+ Unixidmap *m;
+ int i;
+ uvlong x1, x2;
+
+ chat("rpc2xfid %.8lux %.8lux %p %p\n", *((ulong*)argptr), *((ulong*)argptr+1), buf, argptr);
+ if(argptr[0] == 0 && argptr[1] == 0){ /* root */
+ chat("root...");
+ xp = xfroot(&argptr[2], 0);
+ s = xp ? xp->s : 0;
+ }else{
+ ulong ul;
+ chat("noroot %.8lux...", *((ulong*)argptr));
+ if((ul=GLONG()) != starttime){
+ chat("bad tag %lux %lux...", ul, starttime);
+ return 0;
+ }
+ s = (Session *)GLONG();
+ x1 = GLONG();
+ x2 = GLONG();
+ qid.path = x1 | (x2<<32);
+ qid.vers = 0;
+ qid.type = GBYTE();
+ xp = xfile(&qid, s, 0);
+ }
+ if(xp == 0){
+ chat("no xfile...");
+ return 0;
+ }
+ if(auth2unix(&cmd->cred, &au) != 0){
+ chat("auth flavor=%ld, count=%ld\n",
+ cmd->cred.flavor, cmd->cred.count);
+ for(i=0; i<cmd->cred.count; i++)
+ chat(" %.2ux", ((uchar *)cmd->cred.data)[i]);
+ chat("...");
+ return 0;
+ }else{
+/* chat("auth: %d %.*s u=%d g=%d",
+ * au.stamp, utfnlen(au.mach.s, au.mach.n), au.mach.s, au.uid, au.gid);
+ * for(i=0; i<au.gidlen; i++)
+ * chat(", %d", au.gids[i]);
+ * chat("...");
+ */
+ char *p = memchr(au.mach.s, '.', au.mach.n);
+ chat("%ld@%.*s...", au.uid, utfnlen(au.mach.s, (p ? p-au.mach.s : au.mach.n)), au.mach.s);
+ }
+ if(au.mach.n >= sizeof client){
+ chat("client name too long...");
+ return 0;
+ }
+ memcpy(client, au.mach.s, au.mach.n);
+ client[au.mach.n] = 0;
+ service = xp->parent->s->service;
+ cmd->up = m = pair2idmap(service, cmd->host);
+ if(m == 0){
+ chat("no map for pair (%s,%s)...", service, client);
+ /*chat("getdom %d.%d.%d.%d", cmd->host&0xFF, (cmd->host>>8)&0xFF,
+ (cmd->host>>16)&0xFF, (cmd->host>>24)&0xFF);/**/
+ /*if(getdom(cmd->host, client, sizeof(client))<0)
+ return 0;/**/
+ return 0;
+ }
+ /*chat("map=(%s,%s)...", m->server, m->client);/**/
+ cmd->user = user = id2name(&m->u.ids, au.uid);
+ if(user == 0){
+ chat("no user for id %ld...", au.uid);
+ return 0;
+ }
+ chat("user=%s...", user);/**/
+ xf = 0;
+ if(s == xp->parent->s){
+ if(!s->noauth)
+ xf = setuser(xp, user);
+ if(xf == 0)
+ xf = setuser(xp, "none");
+ if(xf == 0)
+ chat("can't set user none...");
+ }else
+ xf = xp->users;
+ if(xf)
+ chat("uid=%s...", xf->uid);
+ if(xf && dp && xfstat(xf, dp) < 0){
+ chat("can't stat %s...", xp->name);
+ return 0;
+ }
+ return xf;
+}
+
+Xfid *
+setuser(Xfile *xp, char *user)
+{
+ Xfid *xf, *xpf;
+ Session *s;
+
+ xf = xfid(user, xp, 1);
+ if(xf->urfid)
+ return xf;
+ if(xp->parent==xp || !(xpf = setuser(xp->parent, user))) /* assign = */
+ return xfid(user, xp, -1);
+ s = xp->s;
+ xf->urfid = newfid(s);
+ xf->urfid->owner = &xf->urfid;
+ setfid(s, xpf->urfid);
+ s->f.newfid = xf->urfid - s->fids;
+ s->f.nwname = 1;
+ s->f.wname[0] = xp->name;
+ if(xmesg(s, Twalk) || s->f.nwqid != 1)
+ return xfid(user, xp, -1);
+ return xf;
+}
+
+int
+xfstat(Xfid *xf, Dir *dp)
+{
+ Xfile *xp;
+ Session *s;
+ char buf[128];
+
+ xp = xf->xp;
+ s = xp->s;
+ if(s != xp->parent->s){
+ seprint(buf, buf+sizeof buf, "#%s", xf->uid);
+ dp->name = strstore(buf);
+ dp->uid = xf->uid;
+ dp->gid = xf->uid;
+ dp->muid = xf->uid;
+ dp->qid.path = (uvlong)xf->uid;
+ dp->qid.type = QTFILE;
+ dp->qid.vers = 0;
+ dp->mode = 0666;
+ dp->atime = time(0);
+ dp->mtime = dp->atime;
+ dp->length = NETCHLEN;
+ dp->type = 0;
+ dp->type = 0;
+ return 0;
+ }
+ setfid(s, xf->urfid);
+ if(xmesg(s, Tstat) == 0){
+ convM2D(s->f.stat, s->f.nstat, dp, (char*)s->statbuf);
+ if(xp->qid.path == dp->qid.path){
+ xp->name = strstore(dp->name);
+ return 0;
+ }
+ /* not reached ? */
+ chat("xp->qid.path=0x%.16llux, dp->qid.path=0x%.16llux name=%s...",
+ xp->qid.path, dp->qid.path, dp->name);
+ }
+ if(xp != xp->parent)
+ xpclear(xp);
+ else
+ clog("can't stat root: %s",
+ s->f.type == Rerror ? s->f.ename : "??");
+ return -1;
+}
+
+int
+xfwstat(Xfid *xf, Dir *dp)
+{
+ Xfile *xp;
+ Session *s;
+
+ xp = xf->xp;
+ s = xp->s;
+
+ /*
+ * xf->urfid can be zero because some DOS NFS clients
+ * try to do wstat on the #user authentication files on close.
+ */
+ if(s == 0 || xf->urfid == 0)
+ return -1;
+ setfid(s, xf->urfid);
+ s->f.stat = s->statbuf;
+ convD2M(dp, s->f.stat, Maxstatdata);
+ if(xmesg(s, Twstat))
+ return -1;
+ xp->name = strstore(dp->name);
+ return 0;
+}
+
+int
+xfopen(Xfid *xf, int flag)
+{
+ static int modes[] = {
+ [Oread] OREAD, [Owrite] OWRITE, [Oread|Owrite] ORDWR,
+ };
+ Xfile *xp;
+ Session *s;
+ Fid *opfid;
+ int omode;
+
+ if(xf->opfid && (xf->mode & flag & Open) == flag)
+ return 0;
+ omode = modes[(xf->mode|flag) & Open];
+ if(flag & Trunc)
+ omode |= OTRUNC;
+ xp = xf->xp;
+ chat("open(\"%s\", %d)...", xp->name, omode);
+ s = xp->s;
+ opfid = newfid(s);
+ setfid(s, xf->urfid);
+ s->f.newfid = opfid - s->fids;
+ s->f.nwname = 0;
+ if(xmesg(s, Twalk)){
+ putfid(s, opfid);
+ return -1;
+ }
+ setfid(s, opfid);
+ s->f.mode = omode;
+ if(xmesg(s, Topen)){
+ clunkfid(s, opfid);
+ return -1;
+ }
+ if(xf->opfid)
+ clunkfid(s, xf->opfid);
+ xf->mode |= flag & Open;
+ xf->opfid = opfid;
+ opfid->owner = &xf->opfid;
+ xf->offset = 0;
+ return 0;
+}
+
+void
+xfclose(Xfid *xf)
+{
+ Xfile *xp;
+
+ if(xf->mode & Open){
+ xp = xf->xp;
+ chat("close(\"%s\")...", xp->name);
+ if(xf->opfid)
+ clunkfid(xp->s, xf->opfid);
+ xf->mode &= ~Open;
+ xf->opfid = 0;
+ }
+}
+
+void
+xfclear(Xfid *xf)
+{
+ Xfile *xp = xf->xp;
+
+ if(xf->opfid){
+ clunkfid(xp->s, xf->opfid);
+ xf->opfid = 0;
+ }
+ if(xf->urfid){
+ clunkfid(xp->s, xf->urfid);
+ xf->urfid = 0;
+ }
+ xfid(xf->uid, xp, -1);
+}
+
+Xfid *
+xfwalkcr(int type, Xfid *xf, String *elem, long perm)
+{
+ Session *s;
+ Xfile *xp, *newxp;
+ Xfid *newxf;
+ Fid *nfid;
+
+ chat("xf%s(\"%s\")...", type==Tcreate ? "create" : "walk", elem->s);
+ xp = xf->xp;
+ s = xp->s;
+ nfid = newfid(s);
+ setfid(s, xf->urfid);
+ s->f.newfid = nfid - s->fids;
+ if(type == Tcreate){
+ s->f.nwname = 0;
+ if(xmesg(s, Twalk)){
+ putfid(s, nfid);
+ return 0;
+ }
+ s->f.fid = nfid - s->fids;
+ }
+ if(type == Tcreate){
+ s->f.name = elem->s;
+ s->f.perm = perm;
+ s->f.mode = (perm&DMDIR) ? OREAD : ORDWR;
+ if(xmesg(s, type)){
+ clunkfid(s, nfid);
+ return 0;
+ }
+ }else{ /* Twalk */
+ s->f.nwname = 1;
+ s->f.wname[0] = elem->s;
+ if(xmesg(s, type) || s->f.nwqid!=1){
+ putfid(s, nfid);
+ return 0;
+ }
+ s->f.qid = s->f.wqid[0]; /* only one element */
+ }
+ chat("fid=%d,qid=0x%llux,%ld,%.2ux...", s->f.fid, s->f.qid.path, s->f.qid.vers, s->f.qid.type);
+ newxp = xfile(&s->f.qid, s, 1);
+ if(newxp->parent == 0){
+ chat("new xfile...");
+ newxp->parent = xp;
+ newxp->sib = xp->child;
+ xp->child = newxp;
+ }
+ newxf = xfid(xf->uid, newxp, 1);
+ if(type == Tcreate){
+ newxf->mode = (perm&DMDIR) ? Oread : (Oread|Owrite);
+ newxf->opfid = nfid;
+ nfid->owner = &newxf->opfid;
+ nfid = newfid(s);
+ setfid(s, xf->urfid);
+ s->f.newfid = nfid - s->fids;
+ s->f.nwname = 1;
+ s->f.wname[0] = elem->s;
+ if(xmesg(s, Twalk) || s->f.nwqid!=1){
+ putfid(s, nfid);
+ xpclear(newxp);
+ return 0;
+ }
+ newxf->urfid = nfid;
+ nfid->owner = &newxf->urfid;
+ }else if(newxf->urfid){
+ chat("old xfid %ld...", newxf->urfid-s->fids);
+ clunkfid(s, nfid);
+ }else{
+ newxf->urfid = nfid;
+ nfid->owner = &newxf->urfid;
+ }
+ newxp->name = strstore(elem->s);
+ return newxf;
+}
+
+void
+xpclear(Xfile *xp)
+{
+ Session *s;
+ Xfid *xf;
+ Xfile *xnp;
+
+ s = xp->s;
+ while(xf = xp->users) /* assign = */
+ xfclear(xf);
+ while(xnp = xp->child){ /* assign = */
+ xp->child = xnp->sib;
+ xnp->parent = 0;
+ xpclear(xnp);
+ xfile(&xnp->qid, s, -1);
+ }
+ if(xnp = xp->parent){ /* assign = */
+ if(xnp->child == xp)
+ xnp->child = xp->sib;
+ else{
+ xnp = xnp->child;
+ while(xnp->sib != xp)
+ xnp = xnp->sib;
+ xnp->sib = xp->sib;
+ }
+ xfile(&xp->qid, s, -1);
+ }
+}
+
+int
+xp2fhandle(Xfile *xp, Fhandle fh)
+{
+ uchar *dataptr = fh;
+ ulong x;
+ int n;
+
+ memset(fh, 0, FHSIZE);
+ if(xp == xp->parent){ /* root */
+ dataptr[0] = 0;
+ dataptr[1] = 0;
+ n = strlen(xp->s->service);
+ if(n > FHSIZE-3)
+ n = FHSIZE-3;
+ memmove(&dataptr[2], xp->s->service, n);
+ dataptr[2+n] = 0;
+ }else{
+ PLONG(starttime);
+ PLONG((u32int)(uintptr)xp->s);
+ x = xp->qid.path;
+ PLONG(x);
+ x = xp->qid.path>>32;
+ PLONG(x);
+ PBYTE(xp->qid.type);
+ USED(dataptr);
+ }
+ return FHSIZE;
+}
+
+int
+dir2fattr(Unixidmap *up, Dir *dp, void *mp)
+{
+ uchar *dataptr = mp;
+ long length;
+ int r;
+
+ r = dp->mode & 0777;
+ if (dp->mode & DMDIR)
+ length = 1024;
+ else
+ length = dp->length;
+ if((dp->mode & DMDIR) && dp->type == '/' && dp->dev == 0)
+ r |= 0555;
+ if(dp->mode & DMDIR){
+ PLONG(NFDIR); /* type */
+ r |= S_IFDIR;
+ PLONG(r); /* mode */
+ PLONG(3); /* nlink */
+ }else{
+ PLONG(NFREG); /* type */
+ r |= S_IFREG;
+ PLONG(r); /* mode */
+ PLONG(1); /* nlink */
+ }
+ r = name2id(&up->u.ids, dp->uid);
+ if(r < 0){
+ r = name2id(&up->u.ids, "daemon");
+ if(r < 0)
+ r = 1;
+ }
+ PLONG(r); /* uid */
+ r = name2id(&up->g.ids, dp->gid);
+ if(r < 0){
+ r = name2id(&up->g.ids, "user");
+ if(r < 0)
+ r = 1;
+ }
+ PLONG(r); /* gid */
+ PLONG(length); /* size */
+ PLONG(2048); /* blocksize */
+ PLONG(0); /* rdev */
+ r = (length+2047)/2048;
+ PLONG(r); /* blocks */
+ r = (dp->type<<16) | dp->dev;
+ PLONG(r); /* fsid */
+ PLONG(dp->qid.path); /* fileid */
+ PLONG(dp->atime); /* atime */
+ PLONG(0);
+ PLONG(dp->mtime); /* mtime */
+ PLONG(0);
+ PLONG(dp->mtime); /* ctime */
+ PLONG(0);
+ return dataptr - (uchar *)mp;
+}
+
+int
+convM2sattr(void *mp, Sattr *sp)
+{
+ uchar *argptr = mp;
+
+ sp->mode = GLONG();
+ sp->uid = GLONG();
+ sp->gid = GLONG();
+ sp->size = GLONG();
+ sp->atime = GLONG();
+ sp->ausec = GLONG();
+ sp->mtime = GLONG();
+ sp->musec = GLONG();
+ return argptr - (uchar *)mp;
+}