diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /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-x | sys/src/cmd/9nfs/nfs.c | 471 |
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; +} |