/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "stdinc.h"#include <fcall.h>#include "vac.h" #define convM2Su(a, b, c, d) convM2S(a, b, c)#define convS2Mu(a, b, c, d) convS2M(a, b, c)#define convM2Du(a, b, c, d) convM2D(a, b, c)#define convD2Mu(a, b, c, d) convD2M(a, b, c) typedef struct Fid Fid; enum{ Stacksize = 320 * 1024, /* was 32K */ OPERM = 0x3 /* mask of all permission types in open mode */}; struct Fid{ short busy; short open; int fid; char *user; Qid qid; VacFile *file; VacDirEnum *vde; Fid *next;}; enum{ Pexec = 1, Pwrite = 2, Pread = 4, Pother = 1, Pgroup = 8, Powner = 64}; Fid *fids;uchar *data;int mfd[2];int srvfd = -1;char *user;uchar mdata[8192+IOHDRSZ];int messagesize = sizeof mdata;Fcall rhdr;Fcall thdr;VacFs *fs;VtConn *conn;int noperm;int dotu;char *defmnt; Fid * newfid(int);void error(char*);void io(void);void vacshutdown(void);void usage(void);int perm(Fid*, int);int permf(VacFile*, char*, int);ulong getl(void *p);void init(char*, char*, long, int);int vacdirread(Fid *f, char *p, long off, long cnt);int vacstat(VacFile *parent, VacDir *vd, uchar *p, int np);void srv(void* a); 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[Tmax])(Fid*); voidinitfcalls(void){ fcalls[Tflush]= rflush; fcalls[Tversion]= rversion; fcalls[Tattach]= rattach; fcalls[Tauth]= rauth; fcalls[Twalk]= rwalk; fcalls[Topen]= ropen; fcalls[Tcreate]= rcreate; fcalls[Tread]= rread; fcalls[Twrite]= rwrite; fcalls[Tclunk]= rclunk; fcalls[Tremove]= rremove; fcalls[Tstat]= rstat; fcalls[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; voidnotifyf(void *a, char *s){ USED(a); if(strncmp(s, "interrupt", 9) == 0) noted(NCONT); noted(NDFLT);} voidthreadmain(int argc, char *argv[]){ char *defsrv, *srvname; int p[2], fd; int stdio; char *host = nil; long ncache; stdio = 0; ncache = 256; fmtinstall('H', encodefmt); fmtinstall('V', vtscorefmt); fmtinstall('F', vtfcallfmt); defmnt = nil; defsrv = nil; ARGBEGIN{ case 'd': fmtinstall('F', fcallfmt); dflag = 1; break; case 'c': ncache = atoi(EARGF(usage())); break; case 'i': defmnt = nil; stdio = 1; mfd[0] = 0; mfd[1] = 1; break; case 'h': host = EARGF(usage()); break; case 'S': defsrv = EARGF(usage()); break; case 's': defsrv = "vacfs"; break; case 'm': defmnt = EARGF(usage()); break; case 'p': noperm = 1; break; case 'V': chattyventi = 1; break; default: usage(); }ARGEND if(argc != 1) usage(); if(defsrv == nil && defmnt == nil && !stdio) defmnt = "/n/vac"; if(stdio && defmnt) sysfatal("cannot use -m with -i"); initfcalls(); notify(notifyf); user = getuser(); conn = vtdial(host); if(conn == nil) sysfatal("could not connect to server: %r"); if(vtconnect(conn) < 0) sysfatal("vtconnect: %r"); fs = vacfsopen(conn, argv[0], VtOREAD, ncache); if(fs == nil) sysfatal("vacfsopen: %r"); if(!stdio){ if(pipe(p) < 0) sysfatal("pipe failed: %r"); mfd[0] = p[0]; mfd[1] = p[0]; srvfd = p[1]; if(defsrv){ srvname = smprint("/srv/%s", defsrv); fd = create(srvname, OWRITE|ORCLOSE, 0666); if(fd < 0) sysfatal("create %s: %r", srvname); if(fprint(fd, "%d", srvfd) < 0) sysfatal("write %s: %r", srvname); free(srvname); } } procrfork(srv, 0, Stacksize, RFFDG|RFNAMEG|RFNOTEG); if(!stdio){ close(p[0]); if(defmnt){ if(mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0) sysfatal("mount %s: %r", defmnt); } } threadexits(0);} voidsrv(void *a){ USED(a); io(); vacshutdown();} voidusage(void){ fprint(2, "usage: %s [-sd] [-h host] [-c ncache] [-m mountpoint] vacfile\n", argv0); threadexitsall("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 vtstrdup("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 vtstrdup("unrecognized 9P version"); thdr.version = "9P2000"; if(strncmp(rhdr.version, "9P2000.u", 8) == 0){ dotu = 1; thdr.version = "9P2000.u"; } return nil;} char*rflush(Fid *f){ USED(f); return 0;} char*rauth(Fid *f){ USED(f); return vtstrdup("vacfs: authentication not required");} char*rattach(Fid *f){ /* no authentication for the momment */ VacFile *file; char err[80]; file = vacfsgetroot(fs); if(file == nil) { rerrstr(err, sizeof err); return vtstrdup(err); } f->busy = 1; f->file = file; f->qid.path = vacfilegetid(f->file); f->qid.vers = 0; f->qid.type = QTDIR; thdr.qid = f->qid; if(rhdr.uname[0]) f->user = vtstrdup(rhdr.uname); else f->user = "none"; return 0;} char*rwalk(Fid *f){ VacFile *file, *nfile; Fid *nf; int nqid, nwname; Qid qid; char *err = nil; if(f->busy == 0) return Enotexist; nf = nil; if(rhdr.fid != rhdr.newfid){ if(f->open) return vtstrdup(Eisopen); if(f->busy == 0) return vtstrdup(Enotexist); nf = newfid(rhdr.newfid); if(nf->busy) return vtstrdup(Eisopen); nf->busy = 1; nf->open = 0; nf->qid = f->qid; nf->file = vacfileincref(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; vacfileincref(file); qid = f->qid; for(nqid = 0; nqid < nwname; nqid++){ if((qid.type & QTDIR) == 0){ err = Enotdir; break; } if(!permf(file, f->user, Pexec)) { err = Eperm; break; } nfile = vacfilewalk(file, rhdr.wname[nqid]); if(nfile == nil) break; vacfiledecref(file); file = nfile; qid.type = QTFILE; if(vacfileisdir(file)) qid.type = QTDIR; qid.vers = vacfilegetmcount(file); qid.path = vacfilegetid(file); thdr.wqid[nqid] = qid; } thdr.nwqid = nqid; if(nqid == nwname){ /* success */ f->qid = thdr.wqid[nqid-1]; vacfiledecref(f->file); f->file = file; return 0; } vacfiledecref(file); if(nf != nil) rclunk(nf); /* only error on the first element */ if(nqid == 0) return vtstrdup(err); return 0;} char *ropen(Fid *f){ int mode, trunc; if(f->open) return vtstrdup(Eisopen); if(!f->busy) return vtstrdup(Enotexist); mode = rhdr.mode; thdr.iounit = messagesize - IOHDRSZ; if(f->qid.type & QTDIR){ if(mode != OREAD) return vtstrdup(Eperm); if(!perm(f, Pread)) return vtstrdup(Eperm); thdr.qid = f->qid; f->vde = nil; f->open = 1; return 0; } if(mode & ORCLOSE) return vtstrdup(Erdonly); trunc = mode & OTRUNC; mode &= OPERM; if(mode==OWRITE || mode==ORDWR || trunc) if(!perm(f, Pwrite)) return vtstrdup(Eperm); if(mode==OREAD || mode==ORDWR) if(!perm(f, Pread)) return vtstrdup(Eperm); if(mode==OEXEC) if(!perm(f, Pexec)) return vtstrdup(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 vtstrdup(Eisopen); if(!fid->busy) return vtstrdup(Enotexist); if(fs->mode & ModeSnapshot) return vtstrdup(Erdonly); vf = fid->file; if(!vacfileisdir(vf)) return vtstrdup(Enotdir); if(!permf(vf, fid->user, Pwrite)) return vtstrdup(Eperm); mode = rhdr.perm & 0777; if(rhdr.perm & DMDIR){ if((rhdr.mode & OTRUNC) || (rhdr.perm & DMAPPEND)) return vtstrdup(Emode); switch(rhdr.mode & OPERM){ default: return vtstrdup(Emode); case OEXEC: case OREAD: break; case OWRITE: case ORDWR: return vtstrdup(Eperm); } mode |= ModeDir; } vf = vacfilecreate(vf, rhdr.name, mode); if(vf == nil) { char err[80]; rerrstr(err, sizeof err); return vtstrdup(err); } vacfiledecref(fid->file); fid->file = vf; fid->qid.type = QTFILE; if(vacfileisdir(vf)) fid->qid.type = QTDIR; fid->qid.vers = vacfilegetmcount(vf); fid->qid.path = vacfilegetid(vf); thdr.qid = fid->qid; thdr.iounit = messagesize - IOHDRSZ; return 0;} char*rread(Fid *f)Lines 1–500 of 797. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "stdinc.h" #include <fcall.h> #include "vac.h" #define convM2Su(a, b, c, d) convM2S(a, b, c) #define convS2Mu(a, b, c, d) convS2M(a, b, c) #define convM2Du(a, b, c, d) convM2D(a, b, c) #define convD2Mu(a, b, c, d) convD2M(a, b, c) typedef struct Fid Fid; enum { Stacksize = 320 * 1024, /* was 32K */ OPERM = 0x3 /* mask of all permission types in open mode */ }; struct Fid { short busy; short open; int fid; char *user; Qid qid; VacFile *file; VacDirEnum *vde; Fid *next; }; enum { Pexec = 1, Pwrite = 2, Pread = 4, Pother = 1, Pgroup = 8, Powner = 64 }; Fid *fids; uchar *data; int mfd[2]; int srvfd = -1; char *user; uchar mdata[8192+IOHDRSZ]; int messagesize = sizeof mdata; Fcall rhdr; Fcall thdr; VacFs *fs; VtConn *conn; int noperm; int dotu; char *defmnt; Fid * newfid(int); void error(char*); void io(void); void vacshutdown(void); void usage(void); int perm(Fid*, int); int permf(VacFile*, char*, int); ulong getl(void *p); void init(char*, char*, long, int); int vacdirread(Fid *f, char *p, long off, long cnt); int vacstat(VacFile *parent, VacDir *vd, uchar *p, int np); void srv(void* a); 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[Tmax])(Fid*); void initfcalls(void) { fcalls[Tflush]= rflush; fcalls[Tversion]= rversion; fcalls[Tattach]= rattach; fcalls[Tauth]= rauth; fcalls[Twalk]= rwalk; fcalls[Topen]= ropen; fcalls[Tcreate]= rcreate; fcalls[Tread]= rread; fcalls[Twrite]= rwrite; fcalls[Tclunk]= rclunk; fcalls[Tremove]= rremove; fcalls[Tstat]= rstat; fcalls[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 threadmain(int argc, char *argv[]) { char *defsrv, *srvname; int p[2], fd; int stdio; char *host = nil; long ncache; stdio = 0; ncache = 256; fmtinstall('H', encodefmt); fmtinstall('V', vtscorefmt); fmtinstall('F', vtfcallfmt); defmnt = nil; defsrv = nil; ARGBEGIN{ case 'd': fmtinstall('F', fcallfmt); dflag = 1; break; case 'c': ncache = atoi(EARGF(usage())); break; case 'i': defmnt = nil; stdio = 1; mfd[0] = 0; mfd[1] = 1; break; case 'h': host = EARGF(usage()); break; case 'S': defsrv = EARGF(usage()); break; case 's': defsrv = "vacfs"; break; case 'm': defmnt = EARGF(usage()); break; case 'p': noperm = 1; break; case 'V': chattyventi = 1; break; default: usage(); }ARGEND if(argc != 1) usage(); if(defsrv == nil && defmnt == nil && !stdio) defmnt = "/n/vac"; if(stdio && defmnt) sysfatal("cannot use -m with -i"); initfcalls(); notify(notifyf); user = getuser(); conn = vtdial(host); if(conn == nil) sysfatal("could not connect to server: %r"); if(vtconnect(conn) < 0) sysfatal("vtconnect: %r"); fs = vacfsopen(conn, argv[0], VtOREAD, ncache); if(fs == nil) sysfatal("vacfsopen: %r"); if(!stdio){ if(pipe(p) < 0) sysfatal("pipe failed: %r"); mfd[0] = p[0]; mfd[1] = p[0]; srvfd = p[1]; if(defsrv){ srvname = smprint("/srv/%s", defsrv); fd = create(srvname, OWRITE|ORCLOSE, 0666); if(fd < 0) sysfatal("create %s: %r", srvname); if(fprint(fd, "%d", srvfd) < 0) sysfatal("write %s: %r", srvname); free(srvname); } } procrfork(srv, 0, Stacksize, RFFDG|RFNAMEG|RFNOTEG); if(!stdio){ close(p[0]); if(defmnt){ if(mount(srvfd, -1, defmnt, MREPL|MCREATE, "") < 0) sysfatal("mount %s: %r", defmnt); } } threadexits(0); } void srv(void *a) { USED(a); io(); vacshutdown(); } void usage(void) { fprint(2, "usage: %s [-sd] [-h host] [-c ncache] [-m mountpoint] vacfile\n", argv0); threadexitsall("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 vtstrdup("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 vtstrdup("unrecognized 9P version"); thdr.version = "9P2000"; if(strncmp(rhdr.version, "9P2000.u", 8) == 0){ dotu = 1; thdr.version = "9P2000.u"; } return nil; } char* rflush(Fid *f) { USED(f); return 0; } char* rauth(Fid *f) { USED(f); return vtstrdup("vacfs: authentication not required"); } char* rattach(Fid *f) { /* no authentication for the momment */ VacFile *file; char err[80]; file = vacfsgetroot(fs); if(file == nil) { rerrstr(err, sizeof err); return vtstrdup(err); } f->busy = 1; f->file = file; f->qid.path = vacfilegetid(f->file); f->qid.vers = 0; f->qid.type = QTDIR; thdr.qid = f->qid; if(rhdr.uname[0]) f->user = vtstrdup(rhdr.uname); else f->user = "none"; return 0; } char* rwalk(Fid *f) { VacFile *file, *nfile; Fid *nf; int nqid, nwname; Qid qid; char *err = nil; if(f->busy == 0) return Enotexist; nf = nil; if(rhdr.fid != rhdr.newfid){ if(f->open) return vtstrdup(Eisopen); if(f->busy == 0) return vtstrdup(Enotexist); nf = newfid(rhdr.newfid); if(nf->busy) return vtstrdup(Eisopen); nf->busy = 1; nf->open = 0; nf->qid = f->qid; nf->file = vacfileincref(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; vacfileincref(file); qid = f->qid; for(nqid = 0; nqid < nwname; nqid++){ if((qid.type & QTDIR) == 0){ err = Enotdir; break; } if(!permf(file, f->user, Pexec)) { err = Eperm; break; } nfile = vacfilewalk(file, rhdr.wname[nqid]); if(nfile == nil) break; vacfiledecref(file); file = nfile; qid.type = QTFILE; if(vacfileisdir(file)) qid.type = QTDIR; qid.vers = vacfilegetmcount(file); qid.path = vacfilegetid(file); thdr.wqid[nqid] = qid; } thdr.nwqid = nqid; if(nqid == nwname){ /* success */ f->qid = thdr.wqid[nqid-1]; vacfiledecref(f->file); f->file = file; return 0; } vacfiledecref(file); if(nf != nil) rclunk(nf); /* only error on the first element */ if(nqid == 0) return vtstrdup(err); return 0; } char * ropen(Fid *f) { int mode, trunc; if(f->open) return vtstrdup(Eisopen); if(!f->busy) return vtstrdup(Enotexist); mode = rhdr.mode; thdr.iounit = messagesize - IOHDRSZ; if(f->qid.type & QTDIR){ if(mode != OREAD) return vtstrdup(Eperm); if(!perm(f, Pread)) return vtstrdup(Eperm); thdr.qid = f->qid; f->vde = nil; f->open = 1; return 0; } if(mode & ORCLOSE) return vtstrdup(Erdonly); trunc = mode & OTRUNC; mode &= OPERM; if(mode==OWRITE || mode==ORDWR || trunc) if(!perm(f, Pwrite)) return vtstrdup(Eperm); if(mode==OREAD || mode==ORDWR) if(!perm(f, Pread)) return vtstrdup(Eperm); if(mode==OEXEC) if(!perm(f, Pexec)) return vtstrdup(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 vtstrdup(Eisopen); if(!fid->busy) return vtstrdup(Enotexist); if(fs->mode & ModeSnapshot) return vtstrdup(Erdonly); vf = fid->file; if(!vacfileisdir(vf)) return vtstrdup(Enotdir); if(!permf(vf, fid->user, Pwrite)) return vtstrdup(Eperm); mode = rhdr.perm & 0777; if(rhdr.perm & DMDIR){ if((rhdr.mode & OTRUNC) || (rhdr.perm & DMAPPEND)) return vtstrdup(Emode); switch(rhdr.mode & OPERM){ default: return vtstrdup(Emode); case OEXEC: case OREAD: break; case OWRITE: case ORDWR: return vtstrdup(Eperm); } mode |= ModeDir; } vf = vacfilecreate(vf, rhdr.name, mode); if(vf == nil) { char err[80]; rerrstr(err, sizeof err); return vtstrdup(err); } vacfiledecref(fid->file); fid->file = vf; fid->qid.type = QTFILE; if(vacfileisdir(vf)) fid->qid.type = QTDIR; fid->qid.vers = vacfilegetmcount(vf); fid->qid.path = vacfilegetid(vf); thdr.qid = fid->qid; thdr.iounit = messagesize - IOHDRSZ; return 0; } char* rread(Fid *f)