start thinking about vac -- doesn't build yet
This commit is contained in:
parent
7a4ee46d25
commit
7763a61a35
22 changed files with 7959 additions and 0 deletions
849
src/cmd/vac/vacfs.c
Normal file
849
src/cmd/vac/vacfs.c
Normal file
|
|
@ -0,0 +1,849 @@
|
|||
#include "stdinc.h"
|
||||
#include <auth.h>
|
||||
#include <fcall.h>
|
||||
#include "vac.h"
|
||||
|
||||
typedef struct Fid Fid;
|
||||
typedef struct DirBuf DirBuf;
|
||||
|
||||
enum
|
||||
{
|
||||
OPERM = 0x3, /* mask of all permission types in open mode */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DirBufSize = 20,
|
||||
};
|
||||
|
||||
struct Fid
|
||||
{
|
||||
short busy;
|
||||
short open;
|
||||
int fid;
|
||||
char *user;
|
||||
Qid qid;
|
||||
VacFile *file;
|
||||
|
||||
DirBuf *db;
|
||||
|
||||
Fid *next;
|
||||
};
|
||||
|
||||
struct DirBuf
|
||||
{
|
||||
VacDirEnum *vde;
|
||||
VacDir buf[DirBufSize];
|
||||
int i, n;
|
||||
int eof;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Pexec = 1,
|
||||
Pwrite = 2,
|
||||
Pread = 4,
|
||||
Pother = 1,
|
||||
Pgroup = 8,
|
||||
Powner = 64,
|
||||
};
|
||||
|
||||
Fid *fids;
|
||||
uchar *data;
|
||||
int mfd[2];
|
||||
char *user;
|
||||
uchar mdata[8192+IOHDRSZ];
|
||||
int messagesize = sizeof mdata;
|
||||
Fcall rhdr;
|
||||
Fcall thdr;
|
||||
VacFS *fs;
|
||||
VtSession *session;
|
||||
int noperm;
|
||||
|
||||
Fid * newfid(int);
|
||||
void error(char*);
|
||||
void io(void);
|
||||
void shutdown(void);
|
||||
void usage(void);
|
||||
int perm(Fid*, int);
|
||||
int permf(VacFile*, char*, int);
|
||||
ulong getl(void *p);
|
||||
void init(char*, char*, long, int);
|
||||
DirBuf *dirBufAlloc(VacFile*);
|
||||
VacDir *dirBufGet(DirBuf*);
|
||||
int dirBufUnget(DirBuf*);
|
||||
void dirBufFree(DirBuf*);
|
||||
int vacdirread(Fid *f, char *p, long off, long cnt);
|
||||
int vdStat(VacDir *vd, uchar *p, int np);
|
||||
|
||||
char *rflush(Fid*), *rversion(Fid*),
|
||||
*rauth(Fid*), *rattach(Fid*), *rwalk(Fid*),
|
||||
*ropen(Fid*), *rcreate(Fid*),
|
||||
*rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
|
||||
*rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
|
||||
|
||||
char *(*fcalls[])(Fid*) = {
|
||||
[Tflush] rflush,
|
||||
[Tversion] rversion,
|
||||
[Tattach] rattach,
|
||||
[Tauth] rauth,
|
||||
[Twalk] rwalk,
|
||||
[Topen] ropen,
|
||||
[Tcreate] rcreate,
|
||||
[Tread] rread,
|
||||
[Twrite] rwrite,
|
||||
[Tclunk] rclunk,
|
||||
[Tremove] rremove,
|
||||
[Tstat] rstat,
|
||||
[Twstat] rwstat,
|
||||
};
|
||||
|
||||
char Eperm[] = "permission denied";
|
||||
char Enotdir[] = "not a directory";
|
||||
char Enotexist[] = "file does not exist";
|
||||
char Einuse[] = "file in use";
|
||||
char Eexist[] = "file exists";
|
||||
char Enotowner[] = "not owner";
|
||||
char Eisopen[] = "file already open for I/O";
|
||||
char Excl[] = "exclusive use file already open";
|
||||
char Ename[] = "illegal name";
|
||||
char Erdonly[] = "read only file system";
|
||||
char Eio[] = "i/o error";
|
||||
char Eempty[] = "directory is not empty";
|
||||
char Emode[] = "illegal mode";
|
||||
|
||||
int dflag;
|
||||
|
||||
void
|
||||
notifyf(void *a, char *s)
|
||||
{
|
||||
USED(a);
|
||||
if(strncmp(s, "interrupt", 9) == 0)
|
||||
noted(NCONT);
|
||||
noted(NDFLT);
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *defmnt;
|
||||
int p[2];
|
||||
char buf[12];
|
||||
int fd;
|
||||
int stdio = 0;
|
||||
char *host = nil;
|
||||
long ncache = 1000;
|
||||
int readOnly = 1;
|
||||
|
||||
defmnt = "/n/vac";
|
||||
ARGBEGIN{
|
||||
case 'd':
|
||||
fmtinstall('F', fcallfmt);
|
||||
dflag = 1;
|
||||
break;
|
||||
case 'c':
|
||||
ncache = atoi(ARGF());
|
||||
break;
|
||||
case 'i':
|
||||
defmnt = 0;
|
||||
stdio = 1;
|
||||
mfd[0] = 0;
|
||||
mfd[1] = 1;
|
||||
break;
|
||||
case 'h':
|
||||
host = ARGF();
|
||||
break;
|
||||
case 's':
|
||||
defmnt = 0;
|
||||
break;
|
||||
case 'p':
|
||||
noperm = 1;
|
||||
break;
|
||||
case 'm':
|
||||
defmnt = ARGF();
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
if(argc != 1)
|
||||
usage();
|
||||
|
||||
vtAttach();
|
||||
|
||||
init(argv[0], host, ncache, readOnly);
|
||||
|
||||
if(pipe(p) < 0)
|
||||
sysfatal("pipe failed: %r");
|
||||
if(!stdio){
|
||||
mfd[0] = p[0];
|
||||
mfd[1] = p[0];
|
||||
if(defmnt == 0){
|
||||
fd = create("#s/vacfs", OWRITE, 0666);
|
||||
if(fd < 0)
|
||||
sysfatal("create of /srv/vacfs failed: %r");
|
||||
sprint(buf, "%d", p[1]);
|
||||
if(write(fd, buf, strlen(buf)) < 0)
|
||||
sysfatal("writing /srv/vacfs: %r");
|
||||
}
|
||||
}
|
||||
|
||||
switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
|
||||
case -1:
|
||||
sysfatal("fork: %r");
|
||||
case 0:
|
||||
vtAttach();
|
||||
close(p[1]);
|
||||
io();
|
||||
shutdown();
|
||||
break;
|
||||
default:
|
||||
close(p[0]); /* don't deadlock if child fails */
|
||||
if(defmnt && mount(p[1], -1, defmnt, MREPL|MCREATE, "") < 0)
|
||||
sysfatal("mount failed: %r");
|
||||
}
|
||||
vtDetach();
|
||||
exits(0);
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: %s [-sd] [-h host] [-c ncache] [-m mountpoint] vacfile\n", argv0);
|
||||
exits("usage");
|
||||
}
|
||||
|
||||
char*
|
||||
rversion(Fid *unused)
|
||||
{
|
||||
Fid *f;
|
||||
|
||||
USED(unused);
|
||||
|
||||
for(f = fids; f; f = f->next)
|
||||
if(f->busy)
|
||||
rclunk(f);
|
||||
|
||||
if(rhdr.msize < 256)
|
||||
return "version: message size too small";
|
||||
messagesize = rhdr.msize;
|
||||
if(messagesize > sizeof mdata)
|
||||
messagesize = sizeof mdata;
|
||||
thdr.msize = messagesize;
|
||||
if(strncmp(rhdr.version, "9P2000", 6) != 0)
|
||||
return "unrecognized 9P version";
|
||||
thdr.version = "9P2000";
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
rflush(Fid *f)
|
||||
{
|
||||
USED(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
rauth(Fid *f)
|
||||
{
|
||||
USED(f);
|
||||
return "vacfs: authentication not required";
|
||||
}
|
||||
|
||||
char*
|
||||
rattach(Fid *f)
|
||||
{
|
||||
/* no authentication for the momment */
|
||||
VacFile *file;
|
||||
|
||||
file = vfsGetRoot(fs);
|
||||
if(file == nil)
|
||||
return vtGetError();
|
||||
f->busy = 1;
|
||||
f->file = file;
|
||||
f->qid = (Qid){vfGetId(f->file), 0, QTDIR};
|
||||
thdr.qid = f->qid;
|
||||
if(rhdr.uname[0])
|
||||
f->user = vtStrDup(rhdr.uname);
|
||||
else
|
||||
f->user = "none";
|
||||
return 0;
|
||||
}
|
||||
|
||||
VacFile*
|
||||
_vfWalk(VacFile *file, char *name)
|
||||
{
|
||||
VacFile *n;
|
||||
|
||||
n = vfWalk(file, name);
|
||||
if(n)
|
||||
return n;
|
||||
if(strcmp(name, "SLASH") == 0)
|
||||
return vfWalk(file, "/");
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
rwalk(Fid *f)
|
||||
{
|
||||
VacFile *file, *nfile;
|
||||
Fid *nf;
|
||||
int nqid, nwname;
|
||||
Qid qid;
|
||||
|
||||
if(f->busy == 0)
|
||||
return Enotexist;
|
||||
nf = nil;
|
||||
if(rhdr.fid != rhdr.newfid){
|
||||
if(f->open)
|
||||
return Eisopen;
|
||||
if(f->busy == 0)
|
||||
return Enotexist;
|
||||
nf = newfid(rhdr.newfid);
|
||||
if(nf->busy)
|
||||
return Eisopen;
|
||||
nf->busy = 1;
|
||||
nf->open = 0;
|
||||
nf->qid = f->qid;
|
||||
nf->file = vfIncRef(f->file);
|
||||
nf->user = vtStrDup(f->user);
|
||||
f = nf;
|
||||
}
|
||||
|
||||
nwname = rhdr.nwname;
|
||||
|
||||
/* easy case */
|
||||
if(nwname == 0) {
|
||||
thdr.nwqid = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
file = f->file;
|
||||
vfIncRef(file);
|
||||
qid = f->qid;
|
||||
|
||||
for(nqid = 0; nqid < nwname; nqid++){
|
||||
if((qid.type & QTDIR) == 0){
|
||||
vtSetError(Enotdir);
|
||||
break;
|
||||
}
|
||||
if(!permf(file, f->user, Pexec)) {
|
||||
vtSetError(Eperm);
|
||||
break;
|
||||
}
|
||||
nfile = _vfWalk(file, rhdr.wname[nqid]);
|
||||
if(nfile == nil)
|
||||
break;
|
||||
vfDecRef(file);
|
||||
file = nfile;
|
||||
qid.type = QTFILE;
|
||||
if(vfIsDir(file))
|
||||
qid.type = QTDIR;
|
||||
qid.vers = vfGetMcount(file);
|
||||
qid.path = vfGetId(file);
|
||||
thdr.wqid[nqid] = qid;
|
||||
}
|
||||
|
||||
thdr.nwqid = nqid;
|
||||
|
||||
if(nqid == nwname){
|
||||
/* success */
|
||||
f->qid = thdr.wqid[nqid-1];
|
||||
vfDecRef(f->file);
|
||||
f->file = file;
|
||||
return 0;
|
||||
}
|
||||
|
||||
vfDecRef(file);
|
||||
if(nf != nil)
|
||||
rclunk(nf);
|
||||
|
||||
/* only error on the first element */
|
||||
if(nqid == 0)
|
||||
return vtGetError();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
ropen(Fid *f)
|
||||
{
|
||||
int mode, trunc;
|
||||
|
||||
if(f->open)
|
||||
return Eisopen;
|
||||
if(!f->busy)
|
||||
return Enotexist;
|
||||
mode = rhdr.mode;
|
||||
thdr.iounit = messagesize - IOHDRSZ;
|
||||
if(f->qid.type & QTDIR){
|
||||
if(mode != OREAD)
|
||||
return Eperm;
|
||||
if(!perm(f, Pread))
|
||||
return Eperm;
|
||||
thdr.qid = f->qid;
|
||||
f->db = nil;
|
||||
f->open = 1;
|
||||
return 0;
|
||||
}
|
||||
if(mode & ORCLOSE)
|
||||
return Erdonly;
|
||||
trunc = mode & OTRUNC;
|
||||
mode &= OPERM;
|
||||
if(mode==OWRITE || mode==ORDWR || trunc)
|
||||
if(!perm(f, Pwrite))
|
||||
return Eperm;
|
||||
if(mode==OREAD || mode==ORDWR)
|
||||
if(!perm(f, Pread))
|
||||
return Eperm;
|
||||
if(mode==OEXEC)
|
||||
if(!perm(f, Pexec))
|
||||
return Eperm;
|
||||
thdr.qid = f->qid;
|
||||
thdr.iounit = messagesize - IOHDRSZ;
|
||||
f->open = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
rcreate(Fid* fid)
|
||||
{
|
||||
VacFile *vf;
|
||||
ulong mode;
|
||||
|
||||
if(fid->open)
|
||||
return Eisopen;
|
||||
if(!fid->busy)
|
||||
return Enotexist;
|
||||
if(vfsIsReadOnly(fs))
|
||||
return Erdonly;
|
||||
vf = fid->file;
|
||||
if(!vfIsDir(vf))
|
||||
return Enotdir;
|
||||
if(!permf(vf, fid->user, Pwrite))
|
||||
return Eperm;
|
||||
|
||||
mode = rhdr.perm & 0777;
|
||||
|
||||
if(rhdr.perm & DMDIR){
|
||||
if((rhdr.mode & OTRUNC) || (rhdr.perm & DMAPPEND))
|
||||
return Emode;
|
||||
switch(rhdr.mode & OPERM){
|
||||
default:
|
||||
return Emode;
|
||||
case OEXEC:
|
||||
case OREAD:
|
||||
break;
|
||||
case OWRITE:
|
||||
case ORDWR:
|
||||
return Eperm;
|
||||
}
|
||||
mode |= ModeDir;
|
||||
}
|
||||
vf = vfCreate(vf, rhdr.name, mode, "none");
|
||||
if(vf == nil)
|
||||
return vtGetError();
|
||||
vfDecRef(fid->file);
|
||||
|
||||
fid->file = vf;
|
||||
fid->qid.type = QTFILE;
|
||||
if(vfIsDir(vf))
|
||||
fid->qid.type = QTDIR;
|
||||
fid->qid.vers = vfGetMcount(vf);
|
||||
fid->qid.path = vfGetId(vf);
|
||||
|
||||
thdr.qid = fid->qid;
|
||||
thdr.iounit = messagesize - IOHDRSZ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
rread(Fid *f)
|
||||
{
|
||||
char *buf;
|
||||
vlong off;
|
||||
int cnt;
|
||||
VacFile *vf;
|
||||
char *err;
|
||||
int n;
|
||||
|
||||
if(!f->busy)
|
||||
return Enotexist;
|
||||
vf = f->file;
|
||||
thdr.count = 0;
|
||||
off = rhdr.offset;
|
||||
buf = thdr.data;
|
||||
cnt = rhdr.count;
|
||||
if(f->qid.type & QTDIR)
|
||||
n = vacdirread(f, buf, off, cnt);
|
||||
else
|
||||
n = vfRead(vf, buf, cnt, off);
|
||||
if(n < 0) {
|
||||
err = vtGetError();
|
||||
if(err == nil)
|
||||
err = "unknown error!";
|
||||
return err;
|
||||
}
|
||||
thdr.count = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
rwrite(Fid *f)
|
||||
{
|
||||
char *buf;
|
||||
vlong off;
|
||||
int cnt;
|
||||
VacFile *vf;
|
||||
|
||||
if(!f->busy)
|
||||
return Enotexist;
|
||||
vf = f->file;
|
||||
thdr.count = 0;
|
||||
off = rhdr.offset;
|
||||
buf = rhdr.data;
|
||||
cnt = rhdr.count;
|
||||
if(f->qid.type & QTDIR)
|
||||
return "file is a directory";
|
||||
thdr.count = vfWrite(vf, buf, cnt, off, "none");
|
||||
if(thdr.count < 0) {
|
||||
fprint(2, "write failed: %s\n", vtGetError());
|
||||
return vtGetError();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
rclunk(Fid *f)
|
||||
{
|
||||
f->busy = 0;
|
||||
f->open = 0;
|
||||
vtMemFree(f->user);
|
||||
f->user = nil;
|
||||
vfDecRef(f->file);
|
||||
f->file = nil;
|
||||
dirBufFree(f->db);
|
||||
f->db = nil;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
rremove(Fid *f)
|
||||
{
|
||||
VacFile *vf, *vfp;
|
||||
char *err = nil;
|
||||
|
||||
if(!f->busy)
|
||||
return Enotexist;
|
||||
vf = f->file;
|
||||
vfp = vfGetParent(vf);
|
||||
|
||||
if(!permf(vfp, f->user, Pwrite)) {
|
||||
err = Eperm;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if(!vfRemove(vf, "none")) {
|
||||
print("vfRemove failed\n");
|
||||
err = vtGetError();
|
||||
}
|
||||
|
||||
Exit:
|
||||
vfDecRef(vfp);
|
||||
rclunk(f);
|
||||
return err;
|
||||
}
|
||||
|
||||
char *
|
||||
rstat(Fid *f)
|
||||
{
|
||||
VacDir dir;
|
||||
static uchar statbuf[1024];
|
||||
|
||||
if(!f->busy)
|
||||
return Enotexist;
|
||||
vfGetDir(f->file, &dir);
|
||||
thdr.stat = statbuf;
|
||||
thdr.nstat = vdStat(&dir, thdr.stat, sizeof statbuf);
|
||||
vdCleanup(&dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
rwstat(Fid *f)
|
||||
{
|
||||
if(!f->busy)
|
||||
return Enotexist;
|
||||
return Erdonly;
|
||||
}
|
||||
|
||||
int
|
||||
vdStat(VacDir *vd, uchar *p, int np)
|
||||
{
|
||||
Dir dir;
|
||||
|
||||
memset(&dir, 0, sizeof(dir));
|
||||
|
||||
/*
|
||||
* Where do path and version come from
|
||||
*/
|
||||
dir.qid.path = vd->qid;
|
||||
dir.qid.vers = vd->mcount;
|
||||
dir.mode = vd->mode & 0777;
|
||||
if(vd->mode & ModeAppend){
|
||||
dir.qid.type |= QTAPPEND;
|
||||
dir.mode |= DMAPPEND;
|
||||
}
|
||||
if(vd->mode & ModeExclusive){
|
||||
dir.qid.type |= QTEXCL;
|
||||
dir.mode |= DMEXCL;
|
||||
}
|
||||
if(vd->mode & ModeDir){
|
||||
dir.qid.type |= QTDIR;
|
||||
dir.mode |= DMDIR;
|
||||
}
|
||||
|
||||
dir.atime = vd->atime;
|
||||
dir.mtime = vd->mtime;
|
||||
dir.length = vd->size;
|
||||
|
||||
dir.name = vd->elem;
|
||||
dir.uid = vd->uid;
|
||||
dir.gid = vd->gid;
|
||||
dir.muid = vd->mid;
|
||||
|
||||
return convD2M(&dir, p, np);
|
||||
}
|
||||
|
||||
DirBuf*
|
||||
dirBufAlloc(VacFile *vf)
|
||||
{
|
||||
DirBuf *db;
|
||||
|
||||
db = vtMemAllocZ(sizeof(DirBuf));
|
||||
db->vde = vfDirEnum(vf);
|
||||
return db;
|
||||
}
|
||||
|
||||
VacDir *
|
||||
dirBufGet(DirBuf *db)
|
||||
{
|
||||
VacDir *vd;
|
||||
int n;
|
||||
|
||||
if(db->eof)
|
||||
return nil;
|
||||
|
||||
if(db->i >= db->n) {
|
||||
n = vdeRead(db->vde, db->buf, DirBufSize);
|
||||
if(n < 0)
|
||||
return nil;
|
||||
db->i = 0;
|
||||
db->n = n;
|
||||
if(n == 0) {
|
||||
db->eof = 1;
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
vd = db->buf + db->i;
|
||||
db->i++;
|
||||
|
||||
return vd;
|
||||
}
|
||||
|
||||
int
|
||||
dirBufUnget(DirBuf *db)
|
||||
{
|
||||
assert(db->i > 0);
|
||||
db->i--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
dirBufFree(DirBuf *db)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(db == nil)
|
||||
return;
|
||||
|
||||
for(i=db->i; i<db->n; i++)
|
||||
vdCleanup(db->buf + i);
|
||||
vdeFree(db->vde);
|
||||
vtMemFree(db);
|
||||
}
|
||||
|
||||
int
|
||||
vacdirread(Fid *f, char *p, long off, long cnt)
|
||||
{
|
||||
int n, nb;
|
||||
VacDir *vd;
|
||||
|
||||
/*
|
||||
* special case of rewinding a directory
|
||||
* otherwise ignore the offset
|
||||
*/
|
||||
if(off == 0 && f->db) {
|
||||
dirBufFree(f->db);
|
||||
f->db = nil;
|
||||
}
|
||||
|
||||
if(f->db == nil)
|
||||
f->db = dirBufAlloc(f->file);
|
||||
|
||||
for(nb = 0; nb < cnt; nb += n) {
|
||||
vd = dirBufGet(f->db);
|
||||
if(vd == nil) {
|
||||
if(!f->db->eof)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
n = vdStat(vd, (uchar*)p, cnt-nb);
|
||||
if(n <= BIT16SZ) {
|
||||
dirBufUnget(f->db);
|
||||
break;
|
||||
}
|
||||
vdCleanup(vd);
|
||||
p += n;
|
||||
}
|
||||
return nb;
|
||||
}
|
||||
|
||||
Fid *
|
||||
newfid(int fid)
|
||||
{
|
||||
Fid *f, *ff;
|
||||
|
||||
ff = 0;
|
||||
for(f = fids; f; f = f->next)
|
||||
if(f->fid == fid)
|
||||
return f;
|
||||
else if(!ff && !f->busy)
|
||||
ff = f;
|
||||
if(ff){
|
||||
ff->fid = fid;
|
||||
return ff;
|
||||
}
|
||||
f = vtMemAllocZ(sizeof *f);
|
||||
f->fid = fid;
|
||||
f->next = fids;
|
||||
fids = f;
|
||||
return f;
|
||||
}
|
||||
|
||||
void
|
||||
io(void)
|
||||
{
|
||||
char *err;
|
||||
int n;
|
||||
|
||||
for(;;){
|
||||
/*
|
||||
* reading from a pipe or a network device
|
||||
* will give an error after a few eof reads
|
||||
* however, we cannot tell the difference
|
||||
* between a zero-length read and an interrupt
|
||||
* on the processes writing to us,
|
||||
* so we wait for the error
|
||||
*/
|
||||
n = read9pmsg(mfd[0], mdata, sizeof mdata);
|
||||
if(n == 0)
|
||||
continue;
|
||||
if(n < 0)
|
||||
break;
|
||||
if(convM2S(mdata, n, &rhdr) != n)
|
||||
sysfatal("convM2S conversion error");
|
||||
|
||||
if(dflag)
|
||||
fprint(2, "vacfs:<-%F\n", &rhdr);
|
||||
|
||||
thdr.data = (char*)mdata + IOHDRSZ;
|
||||
if(!fcalls[rhdr.type])
|
||||
err = "bad fcall type";
|
||||
else
|
||||
err = (*fcalls[rhdr.type])(newfid(rhdr.fid));
|
||||
if(err){
|
||||
thdr.type = Rerror;
|
||||
thdr.ename = err;
|
||||
}else{
|
||||
thdr.type = rhdr.type + 1;
|
||||
thdr.fid = rhdr.fid;
|
||||
}
|
||||
thdr.tag = rhdr.tag;
|
||||
if(dflag)
|
||||
fprint(2, "vacfs:->%F\n", &thdr);
|
||||
n = convS2M(&thdr, mdata, messagesize);
|
||||
if(write(mfd[1], mdata, n) != n)
|
||||
sysfatal("mount write: %r");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
permf(VacFile *vf, char *user, int p)
|
||||
{
|
||||
VacDir dir;
|
||||
ulong perm;
|
||||
|
||||
if(!vfGetDir(vf, &dir))
|
||||
return 0;
|
||||
perm = dir.mode & 0777;
|
||||
if(noperm)
|
||||
goto Good;
|
||||
if((p*Pother) & perm)
|
||||
goto Good;
|
||||
if(strcmp(user, dir.gid)==0 && ((p*Pgroup) & perm))
|
||||
goto Good;
|
||||
if(strcmp(user, dir.uid)==0 && ((p*Powner) & perm))
|
||||
goto Good;
|
||||
vdCleanup(&dir);
|
||||
return 0;
|
||||
Good:
|
||||
vdCleanup(&dir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
perm(Fid *f, int p)
|
||||
{
|
||||
return permf(f->file, f->user, p);
|
||||
}
|
||||
|
||||
void
|
||||
init(char *file, char *host, long ncache, int readOnly)
|
||||
{
|
||||
notify(notifyf);
|
||||
user = getuser();
|
||||
|
||||
fmtinstall('V', vtScoreFmt);
|
||||
fmtinstall('R', vtErrFmt);
|
||||
|
||||
session = vtDial(host, 0);
|
||||
if(session == nil)
|
||||
vtFatal("could not connect to server: %s", vtGetError());
|
||||
|
||||
if(!vtConnect(session, 0))
|
||||
vtFatal("vtConnect: %s", vtGetError());
|
||||
|
||||
fs = vfsOpen(session, file, readOnly, ncache);
|
||||
if(fs == nil)
|
||||
vtFatal("vfsOpen: %s", vtGetError());
|
||||
}
|
||||
|
||||
void
|
||||
shutdown(void)
|
||||
{
|
||||
Fid *f;
|
||||
|
||||
for(f = fids; f; f = f->next) {
|
||||
if(!f->busy)
|
||||
continue;
|
||||
fprint(2, "open fid: %d\n", f->fid);
|
||||
rclunk(f);
|
||||
}
|
||||
|
||||
vfsClose(fs);
|
||||
vtClose(session);
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue