
before, cwfs would print everything to /dev/cons. this change will redirect the output of commands to the /srv/cwfs.cmd pipe so one can use: con -C /srv/cwfs.cmd and not have the fish for the output in /dev/kmesg. use standard error (/dev/cons) for unsolicited messages as there is not always a reader on the command file.
523 lines
7.7 KiB
C
523 lines
7.7 KiB
C
#include "all.h"
|
|
|
|
/* BUG transition */
|
|
// int client9p = 2;
|
|
// int kernel9p = 2;
|
|
|
|
#include "9p1.h"
|
|
|
|
#define CHAR(x) *p++ = f->x
|
|
#define SHORT(x) { ulong vvv = f->x; *p++ = vvv; *p++ = vvv>>8; }
|
|
#define LONGINT(q) {*p++ = (q); *p++ = (q)>>8; *p++ = (q)>>16; *p++ = (q)>>24;}
|
|
#define LONG(x) { ulong vvv = f->x; LONGINT(vvv); }
|
|
#define VLONG(x) { \
|
|
uvlong q = f->x; \
|
|
*p++ = (q)>> 0; *p++ = (q)>> 8; *p++ = (q)>>16; *p++ = (q)>>24; \
|
|
*p++ = (q)>>32; *p++ = (q)>>40; *p++ = (q)>>48; *p++ = (q)>>56; \
|
|
}
|
|
|
|
#define BYTES(x,n) memmove(p, f->x, n); p += n
|
|
#define STRING(x,n) strncpy((char*)p, f->x, n); p += n
|
|
|
|
int
|
|
convS2M9p1(Fcall *f, uchar *ap)
|
|
{
|
|
uchar *p;
|
|
int t;
|
|
|
|
p = ap;
|
|
CHAR(type);
|
|
t = f->type;
|
|
SHORT(tag);
|
|
switch(t) {
|
|
default:
|
|
fprint(2, "convS2M9p1: bad type: %d\n", t);
|
|
return 0;
|
|
|
|
case Tnop:
|
|
case Tosession:
|
|
break;
|
|
|
|
case Tsession:
|
|
BYTES(chal, sizeof(f->chal));
|
|
break;
|
|
|
|
case Tflush:
|
|
SHORT(oldtag);
|
|
break;
|
|
|
|
case Tattach:
|
|
SHORT(fid);
|
|
STRING(uname, sizeof(f->uname));
|
|
STRING(aname, sizeof(f->aname));
|
|
BYTES(ticket, sizeof(f->ticket));
|
|
BYTES(auth, sizeof(f->auth));
|
|
break;
|
|
|
|
case Toattach:
|
|
SHORT(fid);
|
|
STRING(uname, sizeof(f->uname));
|
|
STRING(aname, sizeof(f->aname));
|
|
BYTES(ticket, NAMELEN);
|
|
break;
|
|
|
|
case Tclone:
|
|
SHORT(fid);
|
|
SHORT(newfid);
|
|
break;
|
|
|
|
case Twalk:
|
|
SHORT(fid);
|
|
STRING(name, sizeof(f->name));
|
|
break;
|
|
|
|
case Tclwalk:
|
|
SHORT(fid);
|
|
SHORT(newfid);
|
|
STRING(name, sizeof(f->name));
|
|
break;
|
|
|
|
case Topen:
|
|
SHORT(fid);
|
|
CHAR(mode);
|
|
break;
|
|
|
|
case Tcreate:
|
|
SHORT(fid);
|
|
STRING(name, sizeof(f->name));
|
|
LONG(perm);
|
|
CHAR(mode);
|
|
break;
|
|
|
|
case Tread:
|
|
SHORT(fid);
|
|
VLONG(offset);
|
|
SHORT(count);
|
|
break;
|
|
|
|
case Twrite:
|
|
SHORT(fid);
|
|
VLONG(offset);
|
|
SHORT(count);
|
|
p++;
|
|
if((uchar*)p == (uchar*)f->data) {
|
|
p += f->count;
|
|
break;
|
|
}
|
|
BYTES(data, f->count);
|
|
break;
|
|
|
|
case Tclunk:
|
|
case Tremove:
|
|
case Tstat:
|
|
SHORT(fid);
|
|
break;
|
|
|
|
case Twstat:
|
|
SHORT(fid);
|
|
BYTES(stat, sizeof(f->stat));
|
|
break;
|
|
/*
|
|
*/
|
|
case Rnop:
|
|
case Rosession:
|
|
case Rflush:
|
|
break;
|
|
|
|
case Rsession:
|
|
BYTES(chal, sizeof(f->chal));
|
|
BYTES(authid, sizeof(f->authid));
|
|
BYTES(authdom, sizeof(f->authdom));
|
|
break;
|
|
|
|
case Rerror:
|
|
STRING(ename, sizeof(f->ename));
|
|
break;
|
|
|
|
case Rclone:
|
|
case Rclunk:
|
|
case Rremove:
|
|
case Rwstat:
|
|
SHORT(fid);
|
|
break;
|
|
|
|
case Rwalk:
|
|
case Ropen:
|
|
case Rcreate:
|
|
case Rclwalk:
|
|
SHORT(fid);
|
|
LONG(qid.path);
|
|
LONG(qid.version);
|
|
break;
|
|
|
|
case Rattach:
|
|
SHORT(fid);
|
|
LONG(qid.path);
|
|
LONG(qid.version);
|
|
BYTES(rauth, sizeof(f->rauth));
|
|
break;
|
|
|
|
case Roattach:
|
|
SHORT(fid);
|
|
LONG(qid.path);
|
|
LONG(qid.version);
|
|
break;
|
|
|
|
case Rread:
|
|
SHORT(fid);
|
|
SHORT(count);
|
|
p++;
|
|
if((uchar*)p == (uchar*)f->data) {
|
|
p += f->count;
|
|
break;
|
|
}
|
|
BYTES(data, f->count);
|
|
break;
|
|
|
|
case Rwrite:
|
|
SHORT(fid);
|
|
SHORT(count);
|
|
break;
|
|
|
|
case Rstat:
|
|
SHORT(fid);
|
|
BYTES(stat, sizeof(f->stat));
|
|
break;
|
|
}
|
|
return p - (uchar*)ap;
|
|
}
|
|
|
|
/*
|
|
* buggery to give false qid for
|
|
* the top 2 levels of the dump fs
|
|
*/
|
|
static ulong
|
|
fakeqid9p1(Dentry *f)
|
|
{
|
|
ulong q;
|
|
int c;
|
|
|
|
q = f->qid.path;
|
|
if(q == (QPROOT|QPDIR)) {
|
|
c = f->name[0];
|
|
if(isascii(c) && isdigit(c)) {
|
|
q = 3|QPDIR;
|
|
c = (c-'0')*10 + (f->name[1]-'0');
|
|
if(c >= 1 && c <= 12)
|
|
q = 4|QPDIR;
|
|
}
|
|
}
|
|
return q;
|
|
}
|
|
|
|
int
|
|
convD2M9p1(Dentry *f, char *ap)
|
|
{
|
|
uchar *p;
|
|
ulong q;
|
|
|
|
p = (uchar*)ap;
|
|
STRING(name, sizeof(f->name));
|
|
|
|
memset(p, 0, 2*NAMELEN);
|
|
uidtostr((char*)p, f->uid, 1);
|
|
p += NAMELEN;
|
|
|
|
uidtostr((char*)p, f->gid, 1);
|
|
p += NAMELEN;
|
|
|
|
q = fakeqid9p1(f);
|
|
LONGINT(q);
|
|
LONG(qid.version);
|
|
|
|
q = f->mode & 0x0fff;
|
|
if(f->mode & DDIR)
|
|
q |= PDIR;
|
|
if(f->mode & DAPND)
|
|
q |= PAPND;
|
|
if(f->mode & DLOCK)
|
|
q |= PLOCK;
|
|
LONGINT(q);
|
|
|
|
LONG(atime);
|
|
LONG(mtime);
|
|
VLONG(size);
|
|
LONGINT(0);
|
|
return p - (uchar*)ap;
|
|
}
|
|
|
|
int
|
|
convA2M9p1(Authenticator *f, char *ap, char *key)
|
|
{
|
|
int n;
|
|
uchar *p;
|
|
|
|
p = (uchar*)ap;
|
|
CHAR(num);
|
|
BYTES(chal, CHALLEN);
|
|
LONG(id);
|
|
n = p - (uchar*)ap;
|
|
if(key)
|
|
encrypt(key, ap, n);
|
|
return n;
|
|
}
|
|
|
|
#undef CHAR
|
|
#undef SHORT
|
|
#undef LONG
|
|
#undef LONGINT
|
|
#undef VLONG
|
|
#undef BYTES
|
|
#undef STRING
|
|
|
|
#define CHAR(x) f->x = *p++
|
|
#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2
|
|
#define LONG(x) f->x = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); p += 4
|
|
#define VLONG(x) { \
|
|
f->x = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)) | \
|
|
(uvlong)(p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24)) << 32; \
|
|
p += 8; \
|
|
}
|
|
|
|
#define BYTES(x,n) memmove(f->x, p, n); p += n
|
|
#define STRING(x,n) memmove(f->x, p, n); p += n
|
|
|
|
int
|
|
convM2S9p1(uchar *ap, Fcall *f, int n)
|
|
{
|
|
uchar *p;
|
|
int t;
|
|
|
|
p = ap;
|
|
CHAR(type);
|
|
t = f->type;
|
|
SHORT(tag);
|
|
switch(t) {
|
|
default:
|
|
/*
|
|
* only whine if it couldn't be a 9P2000 Tversion.
|
|
*/
|
|
if(t != 19 || ap[4] != 100)
|
|
fprint(2, "convM2S9p1: bad type: %d\n", f->type);
|
|
return 0;
|
|
|
|
case Tnop:
|
|
case Tosession:
|
|
break;
|
|
|
|
case Tsession:
|
|
BYTES(chal, sizeof(f->chal));
|
|
break;
|
|
|
|
case Tflush:
|
|
SHORT(oldtag);
|
|
break;
|
|
|
|
case Tattach:
|
|
SHORT(fid);
|
|
BYTES(uname, sizeof(f->uname));
|
|
BYTES(aname, sizeof(f->aname));
|
|
BYTES(ticket, sizeof(f->ticket));
|
|
BYTES(auth, sizeof(f->auth));
|
|
break;
|
|
|
|
case Toattach:
|
|
SHORT(fid);
|
|
BYTES(uname, sizeof(f->uname));
|
|
BYTES(aname, sizeof(f->aname));
|
|
BYTES(ticket, NAMELEN);
|
|
break;
|
|
|
|
case Tclone:
|
|
SHORT(fid);
|
|
SHORT(newfid);
|
|
break;
|
|
|
|
case Twalk:
|
|
SHORT(fid);
|
|
BYTES(name, sizeof(f->name));
|
|
break;
|
|
|
|
case Tclwalk:
|
|
SHORT(fid);
|
|
SHORT(newfid);
|
|
BYTES(name, sizeof(f->name));
|
|
break;
|
|
|
|
case Tremove:
|
|
SHORT(fid);
|
|
break;
|
|
|
|
case Topen:
|
|
SHORT(fid);
|
|
CHAR(mode);
|
|
break;
|
|
|
|
case Tcreate:
|
|
SHORT(fid);
|
|
BYTES(name, sizeof(f->name));
|
|
LONG(perm);
|
|
CHAR(mode);
|
|
break;
|
|
|
|
case Tread:
|
|
SHORT(fid);
|
|
VLONG(offset);
|
|
SHORT(count);
|
|
break;
|
|
|
|
case Twrite:
|
|
SHORT(fid);
|
|
VLONG(offset);
|
|
SHORT(count);
|
|
p++;
|
|
f->data = (char*)p; p += f->count;
|
|
break;
|
|
|
|
case Tclunk:
|
|
case Tstat:
|
|
SHORT(fid);
|
|
break;
|
|
|
|
case Twstat:
|
|
SHORT(fid);
|
|
BYTES(stat, sizeof(f->stat));
|
|
break;
|
|
|
|
/*
|
|
*/
|
|
case Rnop:
|
|
case Rosession:
|
|
break;
|
|
|
|
case Rsession:
|
|
BYTES(chal, sizeof(f->chal));
|
|
BYTES(authid, sizeof(f->authid));
|
|
BYTES(authdom, sizeof(f->authdom));
|
|
break;
|
|
|
|
case Rerror:
|
|
BYTES(ename, sizeof(f->ename));
|
|
break;
|
|
|
|
case Rflush:
|
|
break;
|
|
|
|
case Rclone:
|
|
case Rclunk:
|
|
case Rremove:
|
|
case Rwstat:
|
|
SHORT(fid);
|
|
break;
|
|
|
|
case Rwalk:
|
|
case Rclwalk:
|
|
case Ropen:
|
|
case Rcreate:
|
|
SHORT(fid);
|
|
LONG(qid.path);
|
|
LONG(qid.version);
|
|
break;
|
|
|
|
case Rattach:
|
|
SHORT(fid);
|
|
LONG(qid.path);
|
|
LONG(qid.version);
|
|
BYTES(rauth, sizeof(f->rauth));
|
|
break;
|
|
|
|
case Roattach:
|
|
SHORT(fid);
|
|
LONG(qid.path);
|
|
LONG(qid.version);
|
|
break;
|
|
|
|
case Rread:
|
|
SHORT(fid);
|
|
SHORT(count);
|
|
p++;
|
|
f->data = (char*)p; p += f->count;
|
|
break;
|
|
|
|
case Rwrite:
|
|
SHORT(fid);
|
|
SHORT(count);
|
|
break;
|
|
|
|
case Rstat:
|
|
SHORT(fid);
|
|
BYTES(stat, sizeof(f->stat));
|
|
break;
|
|
}
|
|
if((uchar*)ap+n == p)
|
|
return n;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
convM2D9p1(char *ap, Dentry *f)
|
|
{
|
|
uchar *p;
|
|
char str[NAMELEN];
|
|
|
|
p = (uchar*)ap;
|
|
BYTES(name, sizeof(f->name));
|
|
|
|
memmove(str, p, NAMELEN);
|
|
p += NAMELEN;
|
|
f->uid = strtouid(str);
|
|
|
|
memmove(str, p, NAMELEN);
|
|
p += NAMELEN;
|
|
f->gid = strtouid(str);
|
|
|
|
LONG(qid.path);
|
|
LONG(qid.version);
|
|
|
|
LONG(atime);
|
|
f->mode = (f->atime & 0x0fff) | DALLOC;
|
|
if(f->atime & PDIR)
|
|
f->mode |= DDIR;
|
|
if(f->atime & PAPND)
|
|
f->mode |= DAPND;
|
|
if(f->atime & PLOCK)
|
|
f->mode |= DLOCK;
|
|
|
|
LONG(atime);
|
|
LONG(mtime);
|
|
VLONG(size);
|
|
p += 4;
|
|
return p - (uchar*)ap;
|
|
}
|
|
|
|
void
|
|
convM2A9p1(char *ap, Authenticator *f, char *key)
|
|
{
|
|
uchar *p;
|
|
|
|
if(key)
|
|
decrypt(key, ap, AUTHENTLEN);
|
|
p = (uchar*)ap;
|
|
CHAR(num);
|
|
BYTES(chal, CHALLEN);
|
|
LONG(id);
|
|
USED(p);
|
|
}
|
|
|
|
void
|
|
convM2T9p1(char *ap, Ticket *f, char *key)
|
|
{
|
|
uchar *p;
|
|
|
|
if(key)
|
|
decrypt(key, ap, TICKETLEN);
|
|
p = (uchar*)ap;
|
|
CHAR(num);
|
|
BYTES(chal, CHALLEN);
|
|
STRING(cuid, NAMELEN);
|
|
f->cuid[NAMELEN-1] = 0;
|
|
STRING(suid, NAMELEN);
|
|
f->suid[NAMELEN-1] = 0;
|
|
BYTES(key, DESKEYLEN);
|
|
USED(p);
|
|
}
|