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