plan9fox/sys/src/cmd/9nfs/nfs.c

472 lines
9.3 KiB
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;
}