📄 9p1.c
字号:
#include "all.h"#include "9p1.h"/* * buggery to give false qid for * the top 2 levels of the dump fs */voidmkqid(Qid* qid, Dentry *d, int buggery){ int c; if(buggery && d->qid.path == QPROOT && (d->qid.path & QPDIR)){ c = d->name[0]; if(c >= '0' && c <= '9'){ qid->path = 3; qid->vers = d->qid.version; qid->type = QTDIR; c = (c-'0')*10 + (d->name[1]-'0'); if(c >= 1 && c <= 12) qid->path = 4; return; } } mkqid9p2(qid, &d->qid, d->mode);}intmkqidcmp(Qid* qid, Dentry *d){ Qid tmp; mkqid(&tmp, d, 1); if(qid->path==tmp.path && (qid->type&QTDIR)==(tmp.type&QTDIR)) return 0; return Eqid;}voidf_nop(Chan *cp, Oldfcall *in, Oldfcall *ou){ USED(in); USED(ou); if(CHAT(cp)) print("c_nop %d\n", cp->chan);}voidf_flush(Chan *cp, Oldfcall *in, Oldfcall *ou){ USED(in); USED(ou); if(CHAT(cp)) print("c_flush %d\n", cp->chan); runlock(&cp->reflock); wlock(&cp->reflock); wunlock(&cp->reflock); rlock(&cp->reflock);}voidf_session(Chan *cp, Oldfcall *in, Oldfcall *ou){ if(CHAT(cp)) print("c_session %d\n", cp->chan); memmove(cp->rchal, in->chal, sizeof(cp->rchal)); if(wstatallow || cp == cons.srvchan){ memset(ou->chal, 0, sizeof(ou->chal)); memset(ou->authid, 0, sizeof(ou->authid)); }else{ mkchallenge(cp); memmove(ou->chal, cp->chal, sizeof(ou->chal)); memmove(ou->authid, nvr.authid, sizeof(ou->authid)); } sprint(ou->authdom, "%s.%s", service, nvr.authdom); fileinit(cp);}voidf_attach(Chan *cp, Oldfcall *in, Oldfcall *ou){ Iobuf *p; Dentry *d; File *f; int u; Filsys *fs; long raddr; if(CHAT(cp)) { print("c_attach %d\n", cp->chan); print(" fid = %d\n", in->fid); print(" uid = %s\n", in->uname); print(" arg = %s\n", in->aname); } ou->qid = QID9P1(0,0); ou->fid = in->fid; if(!in->aname[0]) /* default */ strncpy(in->aname, filesys[0].name, sizeof(in->aname)); p = 0; f = filep(cp, in->fid, 1); if(!f) { ou->err = Efid; goto out; } u = -1; if(cp != cons.chan){ if(authorize(cp, in, ou) == 0 || strcmp(in->uname, "adm") == 0){ ou->err = Eauth; goto out; } u = strtouid(in->uname); if(u < 0){ ou->err = Ebadu; goto out; } } fs = fsstr(in->aname); if(fs == 0) { ou->err = Ebadspc; goto out; } raddr = getraddr(fs->dev); p = getbuf(fs->dev, raddr, Bread); d = getdir(p, 0); if(!d || checktag(p, Tdir, QPROOT) || !(d->mode & DALLOC)) { ou->err = Ealloc; goto out; } f->uid = u; if(iaccess(f, d, DREAD)) { ou->err = Eaccess; goto out; } accessdir(p, d, FREAD); mkqid(&f->qid, d, 1); f->fs = fs; f->addr = raddr; f->slot = 0; f->open = 0; freewp(f->wpath); f->wpath = 0; mkqid9p1(&ou->qid, &f->qid);out: if(p) putbuf(p); if(f) { qunlock(f); if(ou->err) freefp(f); }}voidf_clone(Chan *cp, Oldfcall *in, Oldfcall *ou){ File *f1, *f2; int fid, fid1; if(CHAT(cp)) { print("c_clone %d\n", cp->chan); print(" old fid = %d\n", in->fid); print(" new fid = %d\n", in->newfid); } fid = in->fid; fid1 = in->newfid; f1 = 0; f2 = 0; if(fid < fid1) { f1 = filep(cp, fid, 0); f2 = filep(cp, fid1, 1); } else if(fid1 < fid) { f2 = filep(cp, fid1, 1); f1 = filep(cp, fid, 0); } if(!f1 || !f2) { ou->err = Efid; goto out; } f2->fs = f1->fs; f2->addr = f1->addr; f2->open = f1->open & ~FREMOV; f2->uid = f1->uid; f2->slot = f1->slot; f2->qid = f1->qid; freewp(f2->wpath); f2->wpath = getwp(f1->wpath);out: ou->fid = fid; if(f1) qunlock(f1); if(f2) qunlock(f2);}voidf_walk(Chan *cp, Oldfcall *in, Oldfcall *ou){ Iobuf *p, *p1; Dentry *d, *d1; File *f; Wpath *w, *ow; int slot; long addr; if(CHAT(cp)) { print("c_walk %d\n", cp->chan); print(" fid = %d\n", in->fid); print(" name = %s\n", in->name); } ou->fid = in->fid; ou->qid = QID9P1(0,0); p = 0; f = filep(cp, in->fid, 0); if(!f) { ou->err = Efid; goto out; } p = getbuf(f->fs->dev, f->addr, Bread); d = getdir(p, f->slot); if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { ou->err = Ealloc; goto out; } if(!(d->mode & DDIR)) { ou->err = Edir1; goto out; } if(ou->err = mkqidcmp(&f->qid, d)) goto out; if(cp != cons.chan && iaccess(f, d, DEXEC)) { ou->err = Eaccess; goto out; } accessdir(p, d, FREAD); if(strcmp(in->name, ".") == 0) goto setdot; if(strcmp(in->name, "..") == 0) { if(f->wpath == 0) goto setdot; putbuf(p); p = 0; addr = f->wpath->addr; slot = f->wpath->slot; p1 = getbuf(f->fs->dev, addr, Bread); d1 = getdir(p1, slot); if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) { if(p1) putbuf(p1); ou->err = Ephase; goto out; } ow = f->wpath; f->wpath = ow->up; putwp(ow); goto found; } for(addr=0;; addr++) { p1 = dnodebuf(p, d, addr, 0); if(!p1 || checktag(p1, Tdir, d->qid.path) ) { if(p1) putbuf(p1); ou->err = Eentry; goto out; } for(slot=0; slot<DIRPERBUF; slot++) { d1 = getdir(p1, slot); if(!(d1->mode & DALLOC)) continue; if(strncmp(in->name, d1->name, sizeof(in->name))) continue; /* * update walk path */ w = newwp(); if(!w) { ou->err = Ewalk; putbuf(p1); goto out; } w->addr = f->addr; w->slot = f->slot; w->up = f->wpath; f->wpath = w; slot += DIRPERBUF*addr; goto found; } putbuf(p1); }found: f->addr = p1->addr; mkqid(&f->qid, d1, 1); putbuf(p1); f->slot = slot;setdot: mkqid9p1(&ou->qid, &f->qid); f->open = 0;out: if(p) putbuf(p); if(f) qunlock(f);}voidf_clunk(Chan *cp, Oldfcall *in, Oldfcall *ou){ File *f; Tlock *t; long tim; if(CHAT(cp)) { print("c_clunk %d\n", cp->chan); print(" fid = %d\n", in->fid); } f = filep(cp, in->fid, 0); if(!f) { print("%p\n", f); ou->err = Efid; goto out; } if(t = f->tlock) { tim = time(0); if(t->time < tim || t->file != f) ou->err = Ebroken; t->time = 0; /* free the lock */ f->tlock = 0; } if(f->open & FREMOV) ou->err = doremove(f, 0); f->open = 0; freewp(f->wpath); freefp(f);out: if(f) qunlock(f); ou->fid = in->fid;}voidf_clwalk(Chan *cp, Oldfcall *in, Oldfcall *ou){ int er, fid; if(CHAT(cp)) print("c_clwalk macro\n"); f_clone(cp, in, ou); /* sets tag, fid */ if(ou->err) return; fid = in->fid; in->fid = in->newfid; f_walk(cp, in, ou); /* sets tag, fid, qid */ er = ou->err; if(er == Eentry) { /* * if error is "no entry" * return non error and fid */ ou->err = 0; f_clunk(cp, in, ou); /* sets tag, fid */ ou->err = 0; ou->fid = fid; if(CHAT(cp)) print(" error: %s\n", errstring[er]); return; } if(er) { /* * if any other error * return an error */ ou->err = 0; f_clunk(cp, in, ou); /* sets tag, fid */ ou->err = er; return; } /* * non error * return newfid */}voidf_open(Chan *cp, Oldfcall *in, Oldfcall *ou){ Iobuf *p; Dentry *d; File *f; Tlock *t; Qid qid; int ro, fmod; if(CHAT(cp)) { print("c_open %d\n", cp->chan); print(" fid = %d\n", in->fid); print(" mode = %o\n", in->mode); } p = 0; f = filep(cp, in->fid, 0); if(!f) { ou->err = Efid; goto out; } /* * if remove on close, check access here */ ro = isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup)); if(in->mode & MRCLOSE) { if(ro) { ou->err = Eronly; goto out; } /* * check on parent directory of file to be deleted */ if(f->wpath == 0 || f->wpath->addr == f->addr) { ou->err = Ephase; goto out; } p = getbuf(f->fs->dev, f->wpath->addr, Bread); d = getdir(p, f->wpath->slot); if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { ou->err = Ephase; goto out; } if(iaccess(f, d, DWRITE)) { ou->err = Eaccess; goto out; } putbuf(p); } p = getbuf(f->fs->dev, f->addr, Bread); d = getdir(p, f->slot); if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { ou->err = Ealloc; goto out; } if(ou->err = mkqidcmp(&f->qid, d)) goto out; mkqid(&qid, d, 1); switch(in->mode & 7) { case MREAD: if(iaccess(f, d, DREAD) && !writeallow) goto badaccess; fmod = FREAD; break; case MWRITE: if((d->mode & DDIR) || (iaccess(f, d, DWRITE) && !writeallow)) goto badaccess; if(ro) { ou->err = Eronly; goto out; } fmod = FWRITE; break; case MBOTH: if((d->mode & DDIR) || (iaccess(f, d, DREAD) && !writeallow) || (iaccess(f, d, DWRITE) && !writeallow)) goto badaccess; if(ro) { ou->err = Eronly; goto out; } fmod = FREAD+FWRITE; break; case MEXEC: if((d->mode & DDIR) || iaccess(f, d, DEXEC)) goto badaccess; fmod = FREAD; break; default: ou->err = Emode; goto out; } if(in->mode & MTRUNC) { if((d->mode & DDIR) || (iaccess(f, d, DWRITE) && !writeallow)) goto badaccess; if(ro) { ou->err = Eronly; goto out; } } t = 0; if(d->mode & DLOCK) { t = tlocked(p, d); if(t == 0) { ou->err = Elocked; goto out; } t->file = f; } if(in->mode & MRCLOSE) fmod |= FREMOV; f->open = fmod; if(in->mode & MTRUNC) if(!(d->mode & DAPND)) dtrunc(p, d); f->tlock = t; f->lastra = 0; mkqid9p1(&ou->qid, &qid); goto out;badaccess: ou->err = Eaccess; f->open = 0;out: if(p) putbuf(p); if(f) qunlock(f); ou->fid = in->fid;}voidf_create(Chan *cp, Oldfcall *in, Oldfcall *ou){ Iobuf *p, *p1; Dentry *d, *d1; File *f; int slot, slot1, fmod; long addr, addr1, path; Qid qid; Tlock *t; Wpath *w; if(CHAT(cp)) { print("c_create %d\n", cp->chan); print(" fid = %d\n", in->fid); print(" name = %s\n", in->name); print(" perm = %lx+%lo\n", (in->perm>>28)&0xf, in->perm&0777); print(" mode = %d\n", in->mode); } p = 0; f = filep(cp, in->fid, 0); if(!f) { ou->err = Efid; goto out; } if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) { ou->err = Eronly; goto out; } p = getbuf(f->fs->dev, f->addr, Bread); d = getdir(p, f->slot); if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { ou->err = Ealloc; goto out; } if(ou->err = mkqidcmp(&f->qid, d)) goto out; if(!(d->mode & DDIR)) { ou->err = Edir2; goto out; } if(cp != cons.chan && iaccess(f, d, DWRITE) && !writeallow) { ou->err = Eaccess; goto out; } accessdir(p, d, FREAD); if(!strncmp(in->name, ".", sizeof(in->name)) || !strncmp(in->name, "..", sizeof(in->name))) { ou->err = Edot; goto out; } if(checkname(in->name)) { ou->err = Ename; goto out; } addr1 = 0; slot1 = 0; /* set */ for(addr=0;; addr++) { p1 = dnodebuf(p, d, addr, 0); if(!p1) { if(addr1) break; p1 = dnodebuf(p, d, addr, Tdir); } if(p1 == 0) { ou->err = Efull; goto out; } if(checktag(p1, Tdir, d->qid.path)) { putbuf(p1); goto phase; } for(slot=0; slot<DIRPERBUF; slot++) { d1 = getdir(p1, slot); if(!(d1->mode & DALLOC)) { if(!addr1) { addr1 = p1->addr; slot1 = slot + addr*DIRPERBUF; } continue; } if(!strncmp(in->name, d1->name, sizeof(in->name))) { putbuf(p1); ou->err = Eexist; goto out; } } putbuf(p1); } switch(in->mode & 7) { case MEXEC: case MREAD: /* seems only useful to make directories */ fmod = FREAD; break; case MWRITE: fmod = FWRITE; break; case MBOTH: fmod = FREAD+FWRITE; break; default: ou->err = Emode; goto out; } if(in->perm & PDIR) if((in->mode & MTRUNC) || (in->perm & PAPND) || (fmod & FWRITE)) goto badaccess; /* * do it */ path = qidpathgen(&f->fs->dev); p1 = getbuf(f->fs->dev, addr1, Bread|Bimm|Bmod); d1 = getdir(p1, slot1); if(!d1 || checktag(p1, Tdir, d->qid.path)) { if(p1) putbuf(p1); goto phase; } if(d1->mode & DALLOC) { putbuf(p1); goto phase; } strncpy(d1->name, in->name, sizeof(in->name)); /* * bogus argument passing -- see console.c */ if(cp == cons.chan) { d1->uid = cons.uid; d1->gid = cons.gid; } else { d1->uid = f->uid; d1->gid = d->gid; in->perm &= d->mode | ~0666; if(in->perm & PDIR) in->perm &= d->mode | ~0777; } d1->qid.path = path; d1->qid.version = 0; d1->mode = DALLOC | (in->perm & 0777); if(in->perm & PDIR) { d1->mode |= DDIR; d1->qid.path |= QPDIR; } if(in->perm & PAPND) d1->mode |= DAPND; t = 0; if(in->perm & PLOCK) { d1->mode |= DLOCK; t = tlocked(p1, d1); } accessdir(p1, d1, FWRITE); mkqid(&qid, d1, 0); putbuf(p1); accessdir(p, d, FWRITE); /* * do a walk to new directory entry */ w = newwp(); if(!w) { ou->err = Ewalk; goto out; } w->addr = f->addr; w->slot = f->slot; w->up = f->wpath; f->wpath = w; f->qid = qid; f->tlock = t;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -