📄 consolefs.c
字号:
}}int dbmtime;/* * a request processor (one per Fs) */voidfsrun(void *v){ int n, t; Request *r; Fid *f; Dir *d; void **a = v; Fs* fs; int *pfd; fs = a[0]; pfd = a[1]; fs->fd = pfd[0]; for(;;){ d = dirstat(consoledb); if(d != nil && d->mtime != dbmtime){ dbmtime = d->mtime; readdb(fs); } free(d); r = allocreq(fs, messagesize); n = read9pmsg(fs->fd, r->buf, messagesize); if(n <= 0) fatal("unmounted"); if(convM2S(r->buf, n, &r->f) == 0){ fprint(2, "can't convert %ux %ux %ux\n", r->buf[0], r->buf[1], r->buf[2]); free(r); continue; } f = fsgetfid(fs, r->f.fid); r->fid = f; if(debug) fprint(2, "%F path %llux\n", &r->f, f->qid.path); t = r->f.type; r->f.type++; (*fcall[t])(fs, r, f); }}Fid*fsgetfid(Fs *fs, int fid){ Fid *f, *nf; lock(fs); for(f = fs->hash[fid%Nhash]; f; f = f->next){ if(f->fid == fid){ f->ref++; unlock(fs); return f; } } nf = emalloc(sizeof(Fid)); nf->next = fs->hash[fid%Nhash]; fs->hash[fid%Nhash] = nf; nf->fid = fid; nf->ref = 1; nf->wp = nf->buf; nf->rp = nf->wp; unlock(fs); return nf;}voidfsputfid(Fs *fs, Fid *f){ Fid **l, *nf; lock(fs); if(--f->ref > 0){ unlock(fs); return; } for(l = &fs->hash[f->fid%Nhash]; nf = *l; l = &nf->next) if(nf == f){ *l = f->next; break; } unlock(fs); free(f->user); free(f);}voidfsauth(Fs *fs, Request *r, Fid*){ fsreply(fs, r, "consolefs: authentication not required");}voidfsversion(Fs *fs, Request *r, Fid*){ if(r->f.msize < 256){ fsreply(fs, r, "message size too small"); return; } messagesize = r->f.msize; if(messagesize > 8192+IOHDRSZ) messagesize = 8192+IOHDRSZ; r->f.msize = messagesize; if(strncmp(r->f.version, "9P2000", 6) != 0){ fsreply(fs, r, "unrecognized 9P version"); return; } r->f.version = "9P2000"; fsreply(fs, r, nil);}voidfsflush(Fs *fs, Request *r, Fid *f){ Request *or; or = remtag(&f->r, r->f.oldtag); if(or != nil){ fsputfid(fs, or->fid); free(or); } fsreply(fs, r, nil);}voidfsattach(Fs *fs, Request *r, Fid *f){ f->qid.type = QTDIR; f->qid.path = QID(0, Ttopdir); f->qid.vers = 0; if(r->f.uname[0]) f->user = strdup(r->f.uname); else f->user = strdup("none"); /* hold down the fid till the clunk */ f->attached = 1; lock(fs); f->ref++; unlock(fs); r->f.qid = f->qid; fsreply(fs, r, nil);}voidfswalk(Fs *fs, Request *r, Fid *f){ char *name; Dir d; int i, n, nqid, nwname; Qid qid, wqid[MAXWELEM]; Fid *nf; char *err; if(f->attached == 0){ fsreply(fs, r, Enofid); return; } nf = nil; if(r->f.fid != r->f.newfid){ nf = fsgetfid(fs, r->f.newfid); nf->attached = f->attached; nf->open = f->open; nf->qid = f->qid; nf->user = strdup(f->user); nf->c = f->c; nf->wp = nf->buf; nf->rp = nf->wp; f = nf; } qid = f->qid; err = nil; nwname = r->f.nwname; nqid = 0; if(nwname > 0){ for(; err == nil && nqid < nwname; nqid++){ if(nqid >= MAXWELEM){ err = "too many name elements"; break; } name = r->f.wname[nqid]; if(strcmp(name, "..") == 0) qid = parentqid(qid); else if(strcmp(name, ".") != 0){ for(i = 0; ; i++){ n = fsdirgen(fs, qid, i, &d, nil, 0); if(n < 0){ err = Eexist; break; } if(n > 0 && strcmp(name, d.name) == 0){ qid = d.qid; break; } } } wqid[nqid] = qid; } if(nf != nil && nqid < nwname) fsputfid(fs, nf); if(nqid == nwname) f->qid = qid; } memmove(r->f.wqid, wqid, nqid*sizeof(Qid)); r->f.nwqid = nqid; fsreply(fs, r, err);}intingroup(char *user, char *group){ Ndbtuple *t, *nt; Ndbs s; t = ndbsearch(db, &s, "group", group); if(t == nil) return 0; for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "uid") == 0) if(strcmp(nt->val, user) == 0) break; } ndbfree(t); return nt != nil;}intuserok(char *u, char *cname){ Ndbtuple *t, *nt; Ndbs s; t = ndbsearch(db, &s, "console", cname); if(t == nil) return 0; for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "uid") == 0) if(strcmp(nt->val, u) == 0) break; if(strcmp(nt->attr, "gid") == 0) if(ingroup(u, nt->val)) break; } ndbfree(t); return nt != nil;}int m2p[] ={ [OREAD] 4, [OWRITE] 2, [ORDWR] 6};/* * broadcast a message to all listeners */voidbcastmsg(Fs *fs, Console *c, char *msg, int n){ Fid *fl; for(fl = c->flist; fl; fl = fl->cnext){ fromconsole(fl, msg, n); fskick(fs, fl); }}voidfsopen(Fs *fs, Request *r, Fid *f){ int mode; Console *c; if(f->attached == 0){ fsreply(fs, r, Enofid); return; } if(f->open){ fsreply(fs, r, Eisopen); return; } mode = r->f.mode & 3; if((QTDIR & f->qid.type) && mode != OREAD){ fsreply(fs, r, Eperm); return; } switch(TYPE(f->qid)){ case Qdata: c = fs->cons[CONS(f->qid)]; if(!userok(f->user, c->name)){ fsreply(fs, r, Eperm); return; } f->rp = f->buf; f->wp = f->buf; f->c = c; lock(c); sprint(f->mbuf, "[%s] ", f->user); f->bufn = strlen(f->mbuf); f->used = 0; f->cnext = c->flist; c->flist = f; bcastmembers(fs, c, "+", f); if(c->pid == 0) fsreopen(fs, c); unlock(c); break; case Qctl: c = fs->cons[CONS(f->qid)]; if(!userok(f->user, c->name)){ fsreply(fs, r, Eperm); return; } f->c = c; break; case Qstat: c = fs->cons[CONS(f->qid)]; if(!userok(f->user, c->name)){ fsreply(fs, r, Eperm); return; } f->c = c; break; } f->open = 1; r->f.iounit = messagesize-IOHDRSZ; r->f.qid = f->qid; fsreply(fs, r, nil);}voidfscreate(Fs *fs, Request *r, Fid*){ fsreply(fs, r, Eperm);}voidfsread(Fs *fs, Request *r, Fid *f){ uchar *p, *e; int i, m, off; vlong offset; Dir d; char sbuf[ERRMAX]; if(f->attached == 0){ fsreply(fs, r, Enofid); return; } if((int)r->f.count < 0){ fsreply(fs, r, Ebadcount); return; } if(QTDIR & f->qid.type){ p = r->buf + IOHDRSZ; e = p + r->f.count; offset = r->f.offset; off = 0; for(i=0; p<e; i++, off+=m){ m = fsdirgen(fs, f->qid, i, &d, p, e-p); if(m < 0) break; if(m > BIT16SZ && off >= offset) p += m; } r->f.data = (char*)r->buf + IOHDRSZ; r->f.count = (char*)p - r->f.data; } else { switch(TYPE(f->qid)){ case Qdata: addreq(&f->r, r); fskick(fs, f); return; case Qctl: r->f.data = (char*)r->buf+IOHDRSZ; r->f.count = 0; break; case Qstat: if(r->f.count > sizeof(sbuf)) r->f.count = sizeof(sbuf); i = pread(f->c->sfd, sbuf, r->f.count, r->f.offset); if(i < 0){ errstr(sbuf, sizeof sbuf); fsreply(fs, r, sbuf); return; } r->f.data = sbuf; r->f.count = i; break; default: fsreply(fs, r, Eexist); return; } } fsreply(fs, r, nil);}voidfswrite(Fs *fs, Request *r, Fid *f){ int i, eol = 0; if(f->attached == 0){ fsreply(fs, r, Enofid); return; } if((int)r->f.count < 0){ fsreply(fs, r, Ebadcount); return; } if(QTDIR & f->qid.type){ fsreply(fs, r, Eperm); return; } switch(TYPE(f->qid)){ default: fsreply(fs, r, Eperm); return; case Qctl: write(f->c->cfd, r->f.data, r->f.count); break; case Qdata: for(i = 0; i < r->f.count; i++){ if(r->f.data[i] == '\n'){ if(f->c->chat && f->used) eol = 1; if(f->c->cronly) r->f.data[i] = '\r'; } else f->used = 1; } if(f->c->chat){ fskick(fs, f); if(!f->used) break; if(f->bufn + r->f.count > Bufsize){ r->f.count -= (f->bufn + r->f.count) % Bufsize; eol = 1; } strncat(f->mbuf, r->f.data, r->f.count); f->bufn += r->f.count; if(eol){ bcastmsg(fs, f->c, f->mbuf, f->bufn); sprint(f->mbuf, "[%s] ", f->user); f->bufn = strlen(f->mbuf); f->used = 0; } } else write(f->c->fd, r->f.data, r->f.count); break; } fsreply(fs, r, nil);}voidfsclunk(Fs *fs, Request *r, Fid *f){ Fid **l, *fl; Request *nr; if(f->open && TYPE(f->qid) == Qdata){ while((nr = remreq(&f->r)) != nil){ fsputfid(fs, f); free(nr); } lock(f->c); for(l = &f->c->flist; *l; l = &fl->cnext){ fl = *l; if(fl == f){ *l = fl->cnext; break; } } bcastmembers(fs, f->c, "-", f); if(f->c->ondemand && f->c->flist == nil) fsreopen(fs, f->c); unlock(f->c); } fsreply(fs, r, nil); fsputfid(fs, f);}voidfsremove(Fs *fs, Request *r, Fid*){ fsreply(fs, r, Eperm);}voidfsstat(Fs *fs, Request *r, Fid *f){ int i, n; Qid q; Dir d; q = parentqid(f->qid); for(i = 0; ; i++){ r->f.stat = r->buf+IOHDRSZ; n = fsdirgen(fs, q, i, &d, r->f.stat, messagesize-IOHDRSZ); if(n < 0){ fsreply(fs, r, Eexist); return; } r->f.nstat = n; if(r->f.nstat > BIT16SZ && d.qid.path == f->qid.path) break; } fsreply(fs, r, nil);}voidfswstat(Fs *fs, Request *r, Fid*){ fsreply(fs, r, Eperm);}voidfsreply(Fs *fs, Request *r, char *err){ int n; uchar buf[8192+IOHDRSZ]; if(err){ r->f.type = Rerror; r->f.ename = err; } n = convS2M(&r->f, buf, messagesize); if(debug) fprint(2, "%F path %llux n=%d\n", &r->f, r->fid->qid.path, n); fsputfid(fs, r->fid); if(write(fs->fd, buf, n) != n) fatal("unmounted"); free(r);}/* * called whenever input or a read request has been received */voidfskick(Fs *fs, Fid *f){ Request *r; char *p, *rp, *wp, *ep; int i; lock(f); while(f->rp != f->wp){ r = remreq(&f->r); if(r == nil) break; p = (char*)r->buf; rp = f->rp; wp = f->wp; ep = &f->buf[Bufsize]; for(i = 0; i < r->f.count && rp != wp; i++){ *p++ = *rp++; if(rp >= ep) rp = f->buf; } f->rp = rp; r->f.data = (char*)r->buf; r->f.count = p - (char*)r->buf; fsreply(fs, r, nil); } unlock(f);}voidusage(void){ fprint(2, "usage: consolefs [-d] [-m mount-point] [-c console-db]\n"); threadexitsall("usage");}voidthreadmain(int argc, char **argv){ fmtinstall('F', fcallfmt); ARGBEGIN{ case 'd': debug++; break; case 'c': consoledb = ARGF(); if(consoledb == nil) usage(); break; case 'm': mntpt = ARGF(); if(mntpt == nil) usage(); break; }ARGEND; db = ndbopen(consoledb); if(db == nil) fatal("can't open %s: %r", consoledb); fsmount(mntpt);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -