📄 9p1.c
字号:
f->lastra = 0; if(in->mode & MRCLOSE) fmod |= FREMOV; f->open = fmod; f->addr = addr1; f->slot = slot1; if(t) t->file = f; mkqid9p1(&ou->qid, &qid); goto out;badaccess: ou->err = Eaccess; goto out;phase: ou->err = Ephase;out: if(p) putbuf(p); if(f) qunlock(f); ou->fid = in->fid;}voidf_read(Chan *cp, Oldfcall *in, Oldfcall *ou){ Iobuf *p, *p1; File *f; Dentry *d, *d1; Tlock *t; long addr, offset, tim; int nread, count, n, o, slot; if(CHAT(cp)) { print("c_read %d\n", cp->chan); print(" fid = %d\n", in->fid); print(" offset = %ld\n", in->offset); print(" count = %ld\n", in->count); } p = 0; count = in->count; offset = in->offset; nread = 0; f = filep(cp, in->fid, 0); if(!f) { ou->err = Efid; goto out; } if(!(f->open & FREAD)) { ou->err = Eopen; goto out; } if(count < 0 || count > MAXDAT) { ou->err = Ecount; goto out; } if(offset < 0) { ou->err = Eoffset; goto out; } p = getbuf(f->fs->dev, f->addr, Bread); d = getdir(p, f->slot); if(!d || !(d->mode & DALLOC)) { ou->err = Ealloc; goto out; } if(ou->err = mkqidcmp(&f->qid, d)) goto out; if(t = f->tlock) { tim = time(0); if(t->time < tim || t->file != f) { ou->err = Ebroken; goto out; } /* renew the lock */ t->time = tim + TLOCK; } accessdir(p, d, FREAD); if(d->mode & DDIR) { addr = 0; goto dread; } if(offset+count > d->size) count = d->size - offset; while(count > 0) { addr = offset / BUFSIZE; if(addr == f->lastra+1) dbufread(p, d, addr+1); f->lastra = addr; o = offset % BUFSIZE; n = BUFSIZE - o; if(n > count) n = count; p1 = dnodebuf(p, d, addr, 0); if(p1) { if(checktag(p1, Tfile, QPNONE)) { ou->err = Ephase; putbuf(p1); goto out; } memmove(ou->data+nread, p1->iobuf+o, n); putbuf(p1); } else memset(ou->data+nread, 0, n); count -= n; nread += n; offset += n; } goto out;dread: p1 = dnodebuf(p, d, addr, 0); if(!p1) goto out; if(checktag(p1, Tdir, QPNONE)) { ou->err = Ephase; putbuf(p1); goto out; } n = DIRREC; for(slot=0; slot<DIRPERBUF; slot++) { d1 = getdir(p1, slot); if(!(d1->mode & DALLOC)) continue; if(offset >= n) { offset -= n; continue; } if(count < n) { putbuf(p1); goto out; } if(convD2M9p1(d1, ou->data+nread) != n) print("dirread convD2M\n"); nread += n; count -= n; } putbuf(p1); addr++; goto dread;out: count = in->count - nread; if(count > 0) memset(ou->data+nread, 0, count); if(p) putbuf(p); if(f) qunlock(f); ou->fid = in->fid; ou->count = nread; if(CHAT(cp)) print(" nread = %d\n", nread);}voidf_write(Chan *cp, Oldfcall *in, Oldfcall *ou){ Iobuf *p, *p1; Dentry *d; File *f; Tlock *t; long offset, addr, tim; int count, nwrite, o, n; if(CHAT(cp)) { print("c_write %d\n", cp->chan); print(" fid = %d\n", in->fid); print(" offset = %ld\n", in->offset); print(" count = %ld\n", in->count); } offset = in->offset; count = in->count; nwrite = 0; p = 0; f = filep(cp, in->fid, 0); if(!f) { ou->err = Efid; goto out; } if(!(f->open & FWRITE)) { ou->err = Eopen; goto out; } if(isro(f->fs->dev) || (cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) { ou->err = Eronly; goto out; } if(count < 0 || count > MAXDAT) { ou->err = Ecount; goto out; } if(offset < 0) { ou->err = Eoffset; goto out; } p = getbuf(f->fs->dev, f->addr, Bread|Bmod); d = getdir(p, f->slot); if(!d || !(d->mode & DALLOC)) { ou->err = Ealloc; goto out; } if(ou->err = mkqidcmp(&f->qid, d)) goto out; if(t = f->tlock) { tim = time(0); if(t->time < tim || t->file != f) { ou->err = Ebroken; goto out; } /* renew the lock */ t->time = tim + TLOCK; } accessdir(p, d, FWRITE); if(d->mode & DAPND) offset = d->size; if(offset+count > d->size) d->size = offset+count; while(count > 0) { addr = offset / BUFSIZE; o = offset % BUFSIZE; n = BUFSIZE - o; if(n > count) n = count; p1 = dnodebuf(p, d, addr, Tfile); if(p1 == 0) { ou->err = Efull; goto out; } if(checktag(p1, Tfile, d->qid.path)) { putbuf(p1); ou->err = Ephase; goto out; } memmove(p1->iobuf+o, in->data+nwrite, n); p1->flags |= Bmod; putbuf(p1); count -= n; nwrite += n; offset += n; } if(CHAT(cp)) print(" nwrite = %d\n", nwrite);out: if(p) putbuf(p); if(f) qunlock(f); ou->fid = in->fid; ou->count = nwrite;}intdoremove(File *f, int iscon){ Iobuf *p, *p1; Dentry *d, *d1; long addr; int slot, err; p = 0; p1 = 0; if(isro(f->fs->dev) || (f->cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) { err = Eronly; goto out; } /* * check on parent directory of file to be deleted */ if(f->wpath == 0 || f->wpath->addr == f->addr) { err = Ephase; goto out; } p1 = getbuf(f->fs->dev, f->wpath->addr, Bread); d1 = getdir(p1, f->wpath->slot); if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) { err = Ephase; goto out; } if(!iscon && iaccess(f, d1, DWRITE)) { err = Eaccess; goto out; } accessdir(p1, d1, FWRITE); putbuf(p1); p1 = 0; /* * check on file to be deleted */ p = getbuf(f->fs->dev, f->addr, Bread); d = getdir(p, f->slot); if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { err = Ealloc; goto out; } if(err = mkqidcmp(&f->qid, d)) goto out; /* * if deleting a directory, make sure it is empty */ if((d->mode & DDIR)) for(addr=0;; addr++) { p1 = dnodebuf(p, d, addr, 0); if(!p1) break; if(checktag(p1, Tdir, d->qid.path)) { err = Ephase; goto out; } for(slot=0; slot<DIRPERBUF; slot++) { d1 = getdir(p1, slot); if(!(d1->mode & DALLOC)) continue; err = Eempty; goto out; } putbuf(p1); } /* * do it */ dtrunc(p, d); memset(d, 0, sizeof(Dentry)); settag(p, Tdir, QPNONE);out: if(p1) putbuf(p1); if(p) putbuf(p); return err;}voidf_remove(Chan *cp, Oldfcall *in, Oldfcall *ou){ File *f; if(CHAT(cp)) { print("c_remove %d\n", cp->chan); print(" fid = %d\n", in->fid); } f = filep(cp, in->fid, 0); if(!f) { ou->err = Efid; goto out; } ou->err = doremove(f, cp==cons.chan);out: ou->fid = in->fid; if(f) qunlock(f);}voidf_stat(Chan *cp, Oldfcall *in, Oldfcall *ou){ Iobuf *p; Dentry *d; File *f; if(CHAT(cp)) { print("c_stat %d\n", cp->chan); print(" fid = %d\n", in->fid); } p = 0; memset(ou->stat, 0, sizeof(ou->stat)); 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(ou->err = mkqidcmp(&f->qid, d)) goto out; if(d->qid.path == QPROOT) /* stat of root gives time */ d->atime = time(0); if(convD2M9p1(d, ou->stat) != DIRREC) print("stat convD2M\n");out: if(p) putbuf(p); if(f) qunlock(f); ou->fid = in->fid;}voidf_wstat(Chan *cp, Oldfcall *in, Oldfcall *ou){ Iobuf *p, *p1; Dentry *d, *d1, xd; File *f; int slot; long addr; if(CHAT(cp)) { print("c_wstat %d\n", cp->chan); print(" fid = %d\n", in->fid); } p = 0; p1 = 0; d1 = 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; } /* * first get parent */ if(f->wpath) { p1 = getbuf(f->fs->dev, f->wpath->addr, Bread); d1 = getdir(p1, f->wpath->slot); if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) { ou->err = Ephase; 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; convM2D9p1(in->stat, &xd); if(CHAT(cp)) { print(" d.name = %s\n", xd.name); print(" d.uid = %d\n", xd.uid); print(" d.gid = %d\n", xd.gid); print(" d.mode = %.4x\n", xd.mode); } /* * if chown, * must be god */ while(xd.uid != d->uid) { if(wstatallow) /* set to allow chown during boot */ break; ou->err = Enotu; goto out; } /* * if chgroup, * must be either * a) owner and in new group * b) leader of both groups */ while(xd.gid != d->gid) { if(wstatallow || writeallow) /* set to allow chgrp during boot */ break; if(d->uid == f->uid && ingroup(f->uid, xd.gid)) break; if(leadgroup(f->uid, xd.gid)) if(leadgroup(f->uid, d->gid)) break; ou->err = Enotg; goto out; } /* * if rename, * must have write permission in parent */ if(xd.name[0] == 0) strncpy(xd.name, d->name, sizeof(xd.name)); while(strncmp(d->name, xd.name, sizeof(d->name)) != 0) { if(checkname(xd.name)) { ou->err = Ename; goto out; } if(strcmp(xd.name, ".") == 0 || strcmp(xd.name, "..") == 0) { ou->err = Ename; goto out; } /* * drop entry to prevent lock, then * check that destination name is unique, */ putbuf(p); for(addr=0;; addr++) { p = dnodebuf(p1, d1, addr, 0); if(!p) break; if(checktag(p, Tdir, d1->qid.path)) { putbuf(p); continue; } for(slot=0; slot<DIRPERBUF; slot++) { d = getdir(p, slot); if(!(d->mode & DALLOC)) continue; if(!strncmp(xd.name, d->name, sizeof(xd.name))) { ou->err = Eexist; goto out; } } putbuf(p); } /* * reacquire entry */ p = getbuf(f->fs->dev, f->addr, Bread); d = getdir(p, f->slot); if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { ou->err = Ephase; goto out; } if(wstatallow || writeallow) /* set to allow rename during boot */ break; if(!d1 || iaccess(f, d1, DWRITE)) { ou->err = Eaccess; goto out; } break; } /* * if mode/time, either * a) owner * b) leader of either group */ while(d->mtime != xd.mtime || ((d->mode^xd.mode) & (DAPND|DLOCK|0777))) { if(wstatallow) /* set to allow chmod during boot */ break; if(d->uid == f->uid) break; if(leadgroup(f->uid, xd.gid)) break; if(leadgroup(f->uid, d->gid)) break; ou->err = Enotu; goto out; } d->mtime = xd.mtime; d->uid = xd.uid; d->gid = xd.gid; d->mode = (xd.mode & (DAPND|DLOCK|0777)) | (d->mode & (DALLOC|DDIR)); strncpy(d->name, xd.name, sizeof(d->name)); if(wstatallow) { p->flags |= Bmod; if(xd.atime) d->atime = xd.atime; if(xd.mtime) d->mtime = xd.mtime; } else accessdir(p, d, FWSTAT);out: if(p) putbuf(p); if(p1) putbuf(p1); if(f) qunlock(f); ou->fid = in->fid;}void(*call9p1[MAXSYSCALL])(Chan*, Oldfcall*, Oldfcall*) ={ [Tnop9p1] f_nop, [Tosession9p1] f_session, [Tsession9p1] f_session, [Tflush9p1] f_flush, [Toattach9p1] f_attach, [Tattach9p1] f_attach, [Tclone9p1] f_clone, [Twalk9p1] f_walk, [Topen9p1] f_open, [Tcreate9p1] f_create, [Tread9p1] f_read, [Twrite9p1] f_write, [Tclunk9p1] f_clunk, [Tremove9p1] f_remove, [Tstat9p1] f_stat, [Twstat9p1] f_wstat, [Tclwalk9p1] f_clwalk,};static voidsend(Chan *c, uchar *buf, int n){ int fd, m; fd = c->chan; m = write(fd, buf, n); if(m == n) return; panic("write failed");}voiderror9p1(Chan *c, uchar *buf){ buf[0] = Rnop9p1; buf[1] = ~0; buf[2] = ~0; send(c, buf, 3);}voidserve9p1(Chan *chan, uchar *ib, int nib){ int n, t; uchar inbuf[MAXMSG+MAXDAT], outbuf[MAXMSG+MAXDAT]; Oldfcall fi, fo; for(;;){ if(nib){ memmove(inbuf, ib, nib); n = nib; nib = 0; }else n = read(chan->chan, inbuf, sizeof inbuf); if(chat) print("read msg %d\n", n); if(n == 0 && (chan == cons.srvchan || chan == cons.chan)) continue; if(n <= 0) return; if(convM2S9p1(inbuf, &fi, n) != n){ error9p1(chan, outbuf); continue; } t = fi.type; if(t < 0 || t >= MAXSYSCALL || (t&1) || !call9p1[t]) { print("9p1: bad message type\n"); error9p1(chan, outbuf); continue; } if(CHAT(chan)) print("9p1: fi %O\n", &fi); /* * set up reply message */ fo.err = 0; if(t == Tread9p1) fo.data = (char*)outbuf + 8; /* * call the file system */ cons.work.count++; cons.rate.count += n; /* * call the file system */ rlock(&mainlock); rlock(&chan->reflock); (*call9p1[t])(chan, &fi, &fo); runlock(&chan->reflock); runlock(&mainlock); fo.type = t+1; fo.tag = fi.tag; if(chat) print("9p1: fo %O\n", &fo); if(fo.err) { strcpy(fo.ename, errstring[fo.err]); if(CHAT(cp)) print(" error: %s\n", fo.ename); fo.type = Terror9p1+1; } n = convS2M9p1(&fo, outbuf); if(n == 0) { print("9p1: bad S2M conversion\n"); error9p1(chan, outbuf); continue; } cons.rate.count += n; send(chan, outbuf, n); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -