📄 fsys.c
字号:
}}static voidhold(Plumbmsg *m, Dirtab *d){ Holdq *h, *q; h = emalloc(sizeof(Holdq)); h->msg = m; /* add to end of queue */ if(d->holdq == nil) d->holdq = h; else{ for(q=d->holdq; q->next!=nil; q=q->next) ; q->next = h; }}static voidqueueheld(Dirtab *d){ Holdq *h; while(d->holdq != nil){ h = d->holdq; d->holdq = h->next; queuesend(d, h->msg); /* no need to drain queue because we know no-one is reading yet */ free(h); }}static voiddispose(Fcall *t, uchar *buf, Plumbmsg *m, Ruleset *rs, Exec *e){ int i; char *err; qlock(&queue); err = nil; if(m->dst==nil || m->dst[0]=='\0'){ err = Enoport; if(rs != nil) err = startup(rs, e); plumbfree(m); }else for(i=NQID; i<ndir; i++) if(strcmp(m->dst, dir[i].name) == 0){ if(dir[i].nopen == 0){ err = startup(rs, e); if(e!=nil && e->holdforclient) hold(m, &dir[i]); else plumbfree(m); }else{ queuesend(&dir[i], m); drainqueue(&dir[i]); } break; } freeexec(e); qunlock(&queue); fsysrespond(t, buf, err); free(t);}static Fcall*fsysversion(Fcall *t, uchar *buf, Fid*){ if(t->msize < 256){ fsysrespond(t, buf, "version: message size too small"); return t; } if(t->msize < messagesize) messagesize = t->msize; t->msize = messagesize; if(strncmp(t->version, "9P2000", 6) != 0){ fsysrespond(t, buf, "unrecognized 9P version"); return t; } t->version = "9P2000"; fsysrespond(t, buf, nil); return t;}static Fcall*fsysauth(Fcall *t, uchar *buf, Fid*){ fsysrespond(t, buf, "plumber: authentication not required"); return t;}static Fcall*fsysattach(Fcall *t, uchar *buf, Fid *f){ Fcall out; if(strcmp(t->uname, user) != 0){ fsysrespond(&out, buf, Eperm); return t; } f->busy = 1; f->open = 0; f->qid.type = QTDIR; f->qid.path = Qdir; f->qid.vers = 0; f->dir = dir; memset(&out, 0, sizeof(Fcall)); out.type = t->type; out.tag = t->tag; out.fid = f->fid; out.qid = f->qid; fsysrespond(&out, buf, nil); return t;}static Fcall*fsysflush(Fcall *t, uchar *buf, Fid*){ int i; qlock(&queue); for(i=NQID; i<ndir; i++) flushqueue(&dir[i], t->oldtag); qunlock(&queue); fsysrespond(t, buf, nil); return t;}static Fcall*fsyswalk(Fcall *t, uchar *buf, Fid *f){ Fcall out; Fid *nf; ulong path; Dirtab *d, *dir; Qid q; int i; uchar type; char *err; if(f->open){ fsysrespond(t, buf, "clone of an open fid"); return t; } nf = nil; if(t->fid != t->newfid){ nf = newfid(t->newfid); if(nf->busy){ fsysrespond(t, buf, "clone to a busy fid"); return t; } nf->busy = 1; nf->open = 0; nf->dir = f->dir; nf->qid = f->qid; f = nf; /* walk f */ } out.nwqid = 0; err = nil; dir = f->dir; q = f->qid; if(t->nwname > 0){ for(i=0; i<t->nwname; i++){ if((q.type & QTDIR) == 0){ err = Enotdir; break; } if(strcmp(t->wname[i], "..") == 0){ type = QTDIR; path = Qdir; Accept: q.type = type; q.vers = 0; q.path = path; out.wqid[out.nwqid++] = q; continue; } d = dir; d++; /* skip '.' */ for(; d->name; d++) if(strcmp(t->wname[i], d->name) == 0){ type = d->type; path = d->qid; dir = d; goto Accept; } err = Enoexist; break; } } out.type = t->type; out.tag = t->tag; if(err!=nil || out.nwqid<t->nwname){ if(nf) nf->busy = 0; }else if(out.nwqid == t->nwname){ f->qid = q; f->dir = dir; } fsysrespond(&out, buf, err); return t;}static Fcall*fsysopen(Fcall *t, uchar *buf, Fid *f){ int m, clearrules, mode; clearrules = 0; if(t->mode & OTRUNC){ if(f->qid.path != Qrules) goto Deny; clearrules = 1; } /* can't truncate anything, so just disregard */ mode = t->mode & ~(OTRUNC|OCEXEC); /* can't execute or remove anything */ if(mode==OEXEC || (mode&ORCLOSE)) goto Deny; switch(mode){ default: goto Deny; case OREAD: m = 0400; break; case OWRITE: m = 0200; break; case ORDWR: m = 0600; break; } if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m) goto Deny; if(f->qid.path==Qrules && (mode==OWRITE || mode==ORDWR)){ lock(&rulesref); if(rulesref.ref++ != 0){ rulesref.ref--; unlock(&rulesref); fsysrespond(t, buf, Einuse); return t; } unlock(&rulesref); } if(clearrules){ writerules(nil, 0); rules[0] = nil; } t->qid = f->qid; t->iounit = 0; qlock(&queue); f->mode = mode; f->open = 1; f->dir->nopen++; f->nextopen = f->dir->fopen; f->dir->fopen = f; queueheld(f->dir); qunlock(&queue); fsysrespond(t, buf, nil); return t; Deny: fsysrespond(t, buf, Eperm); return t;}static Fcall*fsyscreate(Fcall *t, uchar *buf, Fid*){ fsysrespond(t, buf, Eperm); return t;}static Fcall*fsysreadrules(Fcall *t, uchar *buf){ char *p; int n; p = printrules(); n = strlen(p); t->data = p; if(t->offset >= n) t->count = 0; else{ t->data = p+t->offset; if(t->offset+t->count > n) t->count = n-t->offset; } fsysrespond(t, buf, nil); free(p); return t;}static Fcall*fsysread(Fcall *t, uchar *buf, Fid *f){ uchar *b; int i, n, o, e; uint len; Dirtab *d; uint clock; if(f->qid.path != Qdir){ if(f->qid.path == Qrules) return fsysreadrules(t, buf); /* read from port */ if(f->qid.path < NQID){ fsysrespond(t, buf, "internal error: unknown read port"); return t; } qlock(&queue); queueread(f->dir, t, buf, f); drainqueue(f->dir); qunlock(&queue); return nil; } o = t->offset; e = t->offset+t->count; clock = getclock(); b = malloc(messagesize-IOHDRSZ); if(b == nil){ fsysrespond(t, buf, Enomem); return t; } n = 0; d = dir; d++; /* first entry is '.' */ for(i=0; d->name!=nil && i<e; i+=len){ len = dostat(d, b+n, messagesize-IOHDRSZ-n, clock); if(len <= BIT16SZ) break; if(i >= o) n += len; d++; } t->data = (char*)b; t->count = n; fsysrespond(t, buf, nil); free(b); return t;}static Fcall*fsyswrite(Fcall *t, uchar *buf, Fid *f){ Plumbmsg *m; int i, n; long count; char *data; Exec *e; switch((int)f->qid.path){ case Qdir: fsysrespond(t, buf, Eisdir); return t; case Qrules: clock = getclock(); fsysrespond(t, buf, writerules(t->data, t->count)); return t; case Qsend: if(f->offset == 0){ data = t->data; count = t->count; }else{ /* partial message already assembled */ f->writebuf = erealloc(f->writebuf, f->offset + t->count); memmove(f->writebuf+f->offset, t->data, t->count); data = f->writebuf; count = f->offset+t->count; } m = plumbunpackpartial(data, count, &n); if(m == nil){ if(n == 0){ f->offset = 0; free(f->writebuf); f->writebuf = nil; fsysrespond(t, buf, Ebadmsg); return t; } /* can read more... */ if(f->offset == 0){ f->writebuf = emalloc(t->count); memmove(f->writebuf, t->data, t->count); } /* else buffer has already been grown */ f->offset += t->count; fsysrespond(t, buf, nil); return t; } /* release partial buffer */ f->offset = 0; free(f->writebuf); f->writebuf = nil; for(i=0; rules[i]; i++) if((e=matchruleset(m, rules[i])) != nil){ dispose(t, buf, m, rules[i], e); return nil; } if(m->dst != nil){ dispose(t, buf, m, nil, nil); return nil; } fsysrespond(t, buf, "no matching plumb rule"); return t; } fsysrespond(t, buf, "internal error: write to unknown file"); return t;}static Fcall*fsysstat(Fcall *t, uchar *buf, Fid *f){ t->stat = emalloc(messagesize-IOHDRSZ); t->nstat = dostat(f->dir, t->stat, messagesize-IOHDRSZ, clock); fsysrespond(t, buf, nil); free(t->stat); t->stat = nil; return t;}static Fcall*fsyswstat(Fcall *t, uchar *buf, Fid*){ fsysrespond(t, buf, Eperm); return t;}static Fcall*fsysremove(Fcall *t, uchar *buf, Fid*){ fsysrespond(t, buf, Eperm); return t;}static Fcall*fsysclunk(Fcall *t, uchar *buf, Fid *f){ Fid *prev, *p; Dirtab *d; qlock(&queue); if(f->open){ d = f->dir; d->nopen--; if(d->qid==Qrules && (f->mode==OWRITE || f->mode==ORDWR)){ /* * just to be sure last rule is parsed; error messages will be lost, though, * unless last write ended with a blank line */ writerules(nil, 0); lock(&rulesref); rulesref.ref--; unlock(&rulesref); } prev = nil; for(p=d->fopen; p; p=p->nextopen){ if(p == f){ if(prev) prev->nextopen = f->nextopen; else d->fopen = f->nextopen; removesenders(d, f); break; } prev = p; } } f->busy = 0; f->open = 0; f->offset = 0; if(f->writebuf != nil){ free(f->writebuf); f->writebuf = nil; } qunlock(&queue); fsysrespond(t, buf, nil); return t;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -