ref: c3ba64f6935322f09b6de5c2285544fd471c605d
dir: /sys/src/cmd/9nfs/nfs.c/
#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 %zd...", 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; }