#include <u.h>#include <libc.h>#include <fcall.h>#include <libg.h>#include <frame.h>#include "dat.h"#include "fns.h" #define NFID 5000#define NFILE 1000 typedef struct Rfile Rfile;typedef struct File File;typedef struct Dirtab Dirtab; struct Rfile /* indexed by fid to find file */{ int busy; int open; int eof; File *file;}; struct File{ int busy; ulong path; /* == qid.path */ ulong slot; /* == qid.vers */ Dirtab *dir;}; struct Dirtab{ char *name; ulong qid; ulong perm;}; char *errname[]={ [Ebadaddr] "bad address in control message", [Ebadctl] "bad control message", [Eclosed] "page is closed", [Eio] "i/o error", [Eisdir] "file is a directory", [Enonexist] "file does not exist", [Enopage] "no context to create page", [Enotdir] "not a directory", [Eperm] "permission denied", [Eslot] "slot out of range", [Egreg] "it's all greg's fault",}; Rfile rfile[NFID];File file[NFILE];char rdata[MAXMSG+MAXFDATA+1];char tdata[MAXMSG+MAXFDATA+1];Fcall rhdr;Fcall thdr;int sfd; /* server end of pipe */char user[NAMELEN];Client client[NSLOT];char *tmpstr; void rflush(void);void rattach(Rfile*);void rclone(Rfile*, int);int rwalk(Rfile*);void ropen(Rfile*);void rcreate(Rfile*);void rread(Rfile*);void rwrite(Rfile*);void rclunk(Rfile*, int);void rstat(Rfile*);void rwstat(Rfile*);void rerrstr(Rfile*);void ruserstr(Rfile*); void sendmsg(int);long getclock(void); char *mname[]={ [Tnop] "Tnop", [Rnop] "Rnop", [Tflush] "Tflush", [Rflush] "Rflush", [Terror] "Terror", [Rerror] "Rerror", [Tsession] "Tsession", [Rsession] "Rsession", [Tattach] "Tattach", [Rattach] "Rattach", [Tclone] "Tclone", [Rclone] "Rclone", [Twalk] "Twalk", [Rwalk] "Rwalk", [Topen] "Topen", [Ropen] "Ropen", [Tcreate] "Tcreate", [Rcreate] "Rcreate", [Tclunk] "Tclunk", [Rclunk] "Rclunk", [Tread] "Tread", [Rread] "Rread", [Twrite] "Twrite", [Rwrite] "Rwrite", [Tremove] "Tremove", [Rremove] "Rremove", [Tstat] "Tstat", [Rstat] "Rstat", [Twstat] "Twstat", [Rwstat] "Rwstat", 0, 0, 0}; /* * Layout of qid: * path bits 0-3 type of file (cons, index, etc.) * path bits 4-31 page id * vers slot number */ enum{ Qdir, Qcons, Qindex, Qconsctl, Qmouse, Qnew, Qdir1, Qctl, Qtag, Qbody, Qtagpos, Qtagsel, Qbodypos, Qbodysel, Qbodyapp,}; #define NQID 16#define QPAGESHIFT 4#define QID(qid) ((qid)&(NQID-1))#define QPAGE(qid) (((qid)&~(CHDIR|(NQID-1)))>>QPAGESHIFT) Dirtab dirtab0[] ={ ".", {CHDIR+Qdir}, CHDIR|0500, "cons", {Qcons}, 0200, "index", {Qindex}, 0400, "consctl", {Qconsctl}, 0200, "mouse", {Qmouse}, 0200, "new", {CHDIR+Qnew}, CHDIR|0500, ".", {CHDIR+Qdir1}, CHDIR|0500, 0, 0, 0,}; Dirtab dirtab1[] ={ ".", {CHDIR+Qdir1}, CHDIR|0500, "ctl", {Qctl}, 0600, "tag", {Qtag}, 0400, "body", {Qbody}, 0400, "tagpos", {Qtagpos}, 0400, "tagsel", {Qtagsel}, 0400, "bodypos", {Qbodypos}, 0400, "bodysel", {Qbodysel}, 0400, "bodyapp", {Qbodyapp}, 0200, 0, 0, 0,}; voidio(void){ long n; Rfile *rf; bflush(); n = read(sfd, rdata, sizeof rdata); if(n <= 0) error("mount read"); if(convM2S(rdata, &rhdr, n) == 0) error("format error"); if(rhdr.fid<0 || NFID<=rhdr.fid) error("fid out of range"); /*BUG: check busy */ rf = &rfile[rhdr.fid];/* fprint(2, "msg: %d %s on %d\n", rhdr.type, mname[rhdr.type]? mname[rhdr.type] : "mystery", rhdr.fid); /**/ switch(rhdr.type){ default: error("type"); break; case Tflush: rflush(); break; case Tattach: rattach(rf); break; case Tclone: rclone(rf, 0); break; case Twalk: rwalk(rf); break; case Tclwalk: rclone(rf, 1); break; case Topen: ropen(rf); break; case Tcreate: rcreate(rf); break; case Tread: rread(rf); break; case Twrite: rwrite(rf); break; case Tclunk: rclunk(rf, 0); break; case Tremove: rclunk(rf, Eperm); break; case Tstat: rstat(rf); break; case Twstat: rwstat(rf); break; }} intnewfile(void){ int i; for(i=0; i<NFILE; i++) if(file[i].busy == 0) return i; error("no free files"); return -1;} voidrflush(void) /* program is synchronous so flush is easy */{ sendmsg(0);} voidrattach(Rfile *rf){ int f, s, err; err = 0; if(strcmp(rhdr.aname, "slave") == 0){ f = 0; file[0].slot = 0; }else{ s = atoi(rhdr.aname); if(s<=0 || s>=NSLOT){ print("slot %d out of range\n", s); err = Eslot; goto send; } f = newfile(); file[f].slot = s; } rf->busy = 1; rf->open = 0; rf->eof = 0; file[f].busy = 1; file[f].path = CHDIR; file[f].dir = &dirtab0[0]; rf->file = &file[f]; thdr.qid.path = rf->file->path; thdr.qid.vers = rf->file->slot; strcpy(user, rhdr.uname); client[rf->file->slot].ref++; send: sendmsg(err);} voidrclone(Rfile *rf, int dowalk){ Rfile *nrf; int err=0; nrf = &rfile[rhdr.newfid]; if(rhdr.newfid<0 || NFID<=rhdr.newfid) error("clone nfid out of range"); if(nrf->busy) error("clone to used channel"); nrf->busy = 1; nrf->open = 0; nrf->eof = 0; nrf->file = rf->file; client[nrf->file->slot].ref++; if(dowalk){ rhdr.fid = rhdr.newfid; if(rwalk(nrf)){ client[nrf->file->slot].ref--; nrf->busy = 0; } return; } send: sendmsg(err);} intrwalk(Rfile *rf){ int err, slot; long dqid, qid, pno; char *name; File *fp; Dirtab *tab; Page *p; int i, j, q; err = 0; qid = 0; slot = rf->file->slot; dqid = rf->file->path; pno = QPAGE(dqid)<<QPAGESHIFT; name = rhdr.name; if((dqid&CHDIR) == 0){ err = Enotdir; goto send; } if(QID(dqid) == Qdir1){ tab = dirtab1; goto Tablookup; } /* first, is it a directory-by-number? */ q = atoi(name); if(q > 0){ if(pagelookup(q)){ qid = CHDIR|(q<<QPAGESHIFT)|Qdir1; tab = dirtab0; j = Qdir1; /* distasteful! */ goto Found; } err = Enonexist; goto send; } /* no: table lookup */ tab = dirtab0; Tablookup: for(j=0; tab[j].name; j++){ if(strcmp(name, tab[j].name) == 0){ if(tab[j].qid == CHDIR+Qnew){ /* make new page */ if(curt) p = curt->page; else{ p = page; if(p == 0){ err = Enopage; goto send; } } if(p->parent == 0) while(p->down) p = p->down; q = pageadd(p->parent, 1)->id; qid = CHDIR|(q<<QPAGESHIFT)|Qdir1; tab = dirtab0; j = Qdir1; /* distasteful! */ }else qid = pno|tab[j].qid; Found: for(i=0,fp=file; i<NFILE; i++,fp++) if(fp->busy && fp->path==qid && fp->slot==rf->file->slot){ rf->file = fp; goto send; } i = newfile(); fp = &file[i]; fp->busy = 1; fp->slot = rf->file->slot; fp->path = qid; fp->dir = &tab[j]; rf->file = fp; goto send; } } err = Enonexist; send: thdr.qid.path = qid; thdr.qid.vers = slot; sendmsg(err); return err;} voidropen(Rfile *rf){ int err, mode, trunc; File *fp; long perm; err = 0; fp = rf->file; perm = fp->dir->perm; mode = rhdr.mode; if(fp->path & CHDIR){ if(mode){ err = Eperm; goto send; } }else{ trunc = mode & OTRUNC; mode &= ~OTRUNC; if(mode<0 || mode>OEXEC){ err = Eperm; goto send; } if(((mode==OREAD || mode==ORDWR) && !(perm&0400)) || ((mode==OWRITE || mode==ORDWR) && !(perm&0200)) || ((mode==OEXEC) && !(perm&0100)) || (trunc && !(perm&0200))){ err = Eperm; goto send; } } if(fp->slot > 0) switch(QID(fp->path)){ case Qdir: case Qdir1: case Qcons: case Qindex: break; case Qconsctl: case Qmouse: err = Egreg; goto send; case Qctl: case Qtag: case Qbody: case Qtagpos: case Qtagsel: case Qbodypos: case Qbodysel: case Qbodyapp: break; default: err = Enonexist; goto send; } rf->open = 1; send: thdr.qid.path = fp->path; thdr.qid.vers = fp->slot; sendmsg(err);} voidrcreate(Rfile *rf){ USED(rf); sendmsg(Eperm);} #define NUMLEN 12 voidrread(Rfile *rf){ int j, n, err, cnt; long off, clock, slot, qid, cn; Rune *r; ulong c0, c1, q0; Dir dir; File *fp; Dirtab *tab; Dirtab *dp; Client *c; String *s; Text *t; Page *p; static char buf[NQID*DIRLEN]; n = 0; err = 0; off = rhdr.offset; cnt = rhdr.count;Lines 1–500 of 940. Load more
#include <u.h> #include <libc.h> #include <fcall.h> #include <libg.h> #include <frame.h> #include "dat.h" #include "fns.h" #define NFID 5000 #define NFILE 1000 typedef struct Rfile Rfile; typedef struct File File; typedef struct Dirtab Dirtab; struct Rfile /* indexed by fid to find file */ { int busy; int open; int eof; File *file; }; struct File { int busy; ulong path; /* == qid.path */ ulong slot; /* == qid.vers */ Dirtab *dir; }; struct Dirtab { char *name; ulong qid; ulong perm; }; char *errname[]= { [Ebadaddr] "bad address in control message", [Ebadctl] "bad control message", [Eclosed] "page is closed", [Eio] "i/o error", [Eisdir] "file is a directory", [Enonexist] "file does not exist", [Enopage] "no context to create page", [Enotdir] "not a directory", [Eperm] "permission denied", [Eslot] "slot out of range", [Egreg] "it's all greg's fault", }; Rfile rfile[NFID]; File file[NFILE]; char rdata[MAXMSG+MAXFDATA+1]; char tdata[MAXMSG+MAXFDATA+1]; Fcall rhdr; Fcall thdr; int sfd; /* server end of pipe */ char user[NAMELEN]; Client client[NSLOT]; char *tmpstr; void rflush(void); void rattach(Rfile*); void rclone(Rfile*, int); int rwalk(Rfile*); void ropen(Rfile*); void rcreate(Rfile*); void rread(Rfile*); void rwrite(Rfile*); void rclunk(Rfile*, int); void rstat(Rfile*); void rwstat(Rfile*); void rerrstr(Rfile*); void ruserstr(Rfile*); void sendmsg(int); long getclock(void); char *mname[]={ [Tnop] "Tnop", [Rnop] "Rnop", [Tflush] "Tflush", [Rflush] "Rflush", [Terror] "Terror", [Rerror] "Rerror", [Tsession] "Tsession", [Rsession] "Rsession", [Tattach] "Tattach", [Rattach] "Rattach", [Tclone] "Tclone", [Rclone] "Rclone", [Twalk] "Twalk", [Rwalk] "Rwalk", [Topen] "Topen", [Ropen] "Ropen", [Tcreate] "Tcreate", [Rcreate] "Rcreate", [Tclunk] "Tclunk", [Rclunk] "Rclunk", [Tread] "Tread", [Rread] "Rread", [Twrite] "Twrite", [Rwrite] "Rwrite", [Tremove] "Tremove", [Rremove] "Rremove", [Tstat] "Tstat", [Rstat] "Rstat", [Twstat] "Twstat", [Rwstat] "Rwstat", 0, 0, 0 }; /* * Layout of qid: * path bits 0-3 type of file (cons, index, etc.) * path bits 4-31 page id * vers slot number */ enum{ Qdir, Qcons, Qindex, Qconsctl, Qmouse, Qnew, Qdir1, Qctl, Qtag, Qbody, Qtagpos, Qtagsel, Qbodypos, Qbodysel, Qbodyapp, }; #define NQID 16 #define QPAGESHIFT 4 #define QID(qid) ((qid)&(NQID-1)) #define QPAGE(qid) (((qid)&~(CHDIR|(NQID-1)))>>QPAGESHIFT) Dirtab dirtab0[] = { ".", {CHDIR+Qdir}, CHDIR|0500, "cons", {Qcons}, 0200, "index", {Qindex}, 0400, "consctl", {Qconsctl}, 0200, "mouse", {Qmouse}, 0200, "new", {CHDIR+Qnew}, CHDIR|0500, ".", {CHDIR+Qdir1}, CHDIR|0500, 0, 0, 0, }; Dirtab dirtab1[] = { ".", {CHDIR+Qdir1}, CHDIR|0500, "ctl", {Qctl}, 0600, "tag", {Qtag}, 0400, "body", {Qbody}, 0400, "tagpos", {Qtagpos}, 0400, "tagsel", {Qtagsel}, 0400, "bodypos", {Qbodypos}, 0400, "bodysel", {Qbodysel}, 0400, "bodyapp", {Qbodyapp}, 0200, 0, 0, 0, }; void io(void) { long n; Rfile *rf; bflush(); n = read(sfd, rdata, sizeof rdata); if(n <= 0) error("mount read"); if(convM2S(rdata, &rhdr, n) == 0) error("format error"); if(rhdr.fid<0 || NFID<=rhdr.fid) error("fid out of range"); /*BUG: check busy */ rf = &rfile[rhdr.fid]; /* fprint(2, "msg: %d %s on %d\n", rhdr.type, mname[rhdr.type]? mname[rhdr.type] : "mystery", rhdr.fid); /**/ switch(rhdr.type){ default: error("type"); break; case Tflush: rflush(); break; case Tattach: rattach(rf); break; case Tclone: rclone(rf, 0); break; case Twalk: rwalk(rf); break; case Tclwalk: rclone(rf, 1); break; case Topen: ropen(rf); break; case Tcreate: rcreate(rf); break; case Tread: rread(rf); break; case Twrite: rwrite(rf); break; case Tclunk: rclunk(rf, 0); break; case Tremove: rclunk(rf, Eperm); break; case Tstat: rstat(rf); break; case Twstat: rwstat(rf); break; } } int newfile(void) { int i; for(i=0; i<NFILE; i++) if(file[i].busy == 0) return i; error("no free files"); return -1; } void rflush(void) /* program is synchronous so flush is easy */ { sendmsg(0); } void rattach(Rfile *rf) { int f, s, err; err = 0; if(strcmp(rhdr.aname, "slave") == 0){ f = 0; file[0].slot = 0; }else{ s = atoi(rhdr.aname); if(s<=0 || s>=NSLOT){ print("slot %d out of range\n", s); err = Eslot; goto send; } f = newfile(); file[f].slot = s; } rf->busy = 1; rf->open = 0; rf->eof = 0; file[f].busy = 1; file[f].path = CHDIR; file[f].dir = &dirtab0[0]; rf->file = &file[f]; thdr.qid.path = rf->file->path; thdr.qid.vers = rf->file->slot; strcpy(user, rhdr.uname); client[rf->file->slot].ref++; send: sendmsg(err); } void rclone(Rfile *rf, int dowalk) { Rfile *nrf; int err=0; nrf = &rfile[rhdr.newfid]; if(rhdr.newfid<0 || NFID<=rhdr.newfid) error("clone nfid out of range"); if(nrf->busy) error("clone to used channel"); nrf->busy = 1; nrf->open = 0; nrf->eof = 0; nrf->file = rf->file; client[nrf->file->slot].ref++; if(dowalk){ rhdr.fid = rhdr.newfid; if(rwalk(nrf)){ client[nrf->file->slot].ref--; nrf->busy = 0; } return; } send: sendmsg(err); } int rwalk(Rfile *rf) { int err, slot; long dqid, qid, pno; char *name; File *fp; Dirtab *tab; Page *p; int i, j, q; err = 0; qid = 0; slot = rf->file->slot; dqid = rf->file->path; pno = QPAGE(dqid)<<QPAGESHIFT; name = rhdr.name; if((dqid&CHDIR) == 0){ err = Enotdir; goto send; } if(QID(dqid) == Qdir1){ tab = dirtab1; goto Tablookup; } /* first, is it a directory-by-number? */ q = atoi(name); if(q > 0){ if(pagelookup(q)){ qid = CHDIR|(q<<QPAGESHIFT)|Qdir1; tab = dirtab0; j = Qdir1; /* distasteful! */ goto Found; } err = Enonexist; goto send; } /* no: table lookup */ tab = dirtab0; Tablookup: for(j=0; tab[j].name; j++){ if(strcmp(name, tab[j].name) == 0){ if(tab[j].qid == CHDIR+Qnew){ /* make new page */ if(curt) p = curt->page; else{ p = page; if(p == 0){ err = Enopage; goto send; } } if(p->parent == 0) while(p->down) p = p->down; q = pageadd(p->parent, 1)->id; qid = CHDIR|(q<<QPAGESHIFT)|Qdir1; tab = dirtab0; j = Qdir1; /* distasteful! */ }else qid = pno|tab[j].qid; Found: for(i=0,fp=file; i<NFILE; i++,fp++) if(fp->busy && fp->path==qid && fp->slot==rf->file->slot){ rf->file = fp; goto send; } i = newfile(); fp = &file[i]; fp->busy = 1; fp->slot = rf->file->slot; fp->path = qid; fp->dir = &tab[j]; rf->file = fp; goto send; } } err = Enonexist; send: thdr.qid.path = qid; thdr.qid.vers = slot; sendmsg(err); return err; } void ropen(Rfile *rf) { int err, mode, trunc; File *fp; long perm; err = 0; fp = rf->file; perm = fp->dir->perm; mode = rhdr.mode; if(fp->path & CHDIR){ if(mode){ err = Eperm; goto send; } }else{ trunc = mode & OTRUNC; mode &= ~OTRUNC; if(mode<0 || mode>OEXEC){ err = Eperm; goto send; } if(((mode==OREAD || mode==ORDWR) && !(perm&0400)) || ((mode==OWRITE || mode==ORDWR) && !(perm&0200)) || ((mode==OEXEC) && !(perm&0100)) || (trunc && !(perm&0200))){ err = Eperm; goto send; } } if(fp->slot > 0) switch(QID(fp->path)){ case Qdir: case Qdir1: case Qcons: case Qindex: break; case Qconsctl: case Qmouse: err = Egreg; goto send; case Qctl: case Qtag: case Qbody: case Qtagpos: case Qtagsel: case Qbodypos: case Qbodysel: case Qbodyapp: break; default: err = Enonexist; goto send; } rf->open = 1; send: thdr.qid.path = fp->path; thdr.qid.vers = fp->slot; sendmsg(err); } void rcreate(Rfile *rf) { USED(rf); sendmsg(Eperm); } #define NUMLEN 12 void rread(Rfile *rf) { int j, n, err, cnt; long off, clock, slot, qid, cn; Rune *r; ulong c0, c1, q0; Dir dir; File *fp; Dirtab *tab; Dirtab *dp; Client *c; String *s; Text *t; Page *p; static char buf[NQID*DIRLEN]; n = 0; err = 0; off = rhdr.offset; cnt = rhdr.count;