📄 sub.c
字号:
#include "all.h"#include "io.h"#ifdef OLD#define swaboff swab4#else#define swaboff swab8#endifFilsys*fsstr(char *p){ Filsys *fs; for(fs=filsys; fs->name; fs++) if(strcmp(fs->name, p) == 0) return fs; return 0;}Filsys*dev2fs(Device *dev){ Filsys *fs; for(fs=filsys; fs->name; fs++) if(fs->dev == dev) return fs; return 0;}/* * allocate 'count' contiguous channels * of type 'type' and return pointer to base */Chan*chaninit(int type, int count, int data){ uchar *p; Chan *cp, *icp; int i; p = ialloc(count * (sizeof(Chan)+data), 0); icp = (Chan*)p; for(i=0; i<count; i++) { cp = (Chan*)p; cp->next = chans; chans = cp; cp->type = type; cp->chan = cons.chano; cons.chano++; strncpy(cp->whoname, "<none>", sizeof(cp->whoname)); dofilter(&cp->work, C0a, C0b, 1); dofilter(&cp->rate, C0a, C0b, 1000); wlock(&cp->reflock); wunlock(&cp->reflock); rlock(&cp->reflock); runlock(&cp->reflock); p += sizeof(Chan); if(data){ cp->pdata = p; p += data; } } return icp;}voidfileinit(Chan *cp){ File *f, *prev; Tlock *t; int h;loop: lock(&flock); for (h=0; h<nelem(flist); h++) for (prev=0, f=flist[h]; f; prev=f, f=f->next) { if(f->cp != cp) continue; if(prev) { prev->next = f->next; f->next = flist[h]; flist[h] = f; } flist[h] = f->next; unlock(&flock); qlock(f); if(t = f->tlock) { if(t->file == f) t->time = 0; /* free the lock */ f->tlock = 0; } if(f->open & FREMOV) doremove(f, 0); freewp(f->wpath); f->open = 0; authfree(f->auth); f->auth = 0; f->cp = 0; qunlock(f); goto loop; } unlock(&flock);}#define NOFID (ulong)~0/* * returns a locked file structure */File*filep(Chan *cp, ulong fid, int flag){ File *f; int h; if(fid == NOFID) return 0; h = (long)cp + fid; if(h < 0) h = ~h; h %= nelem(flist);loop: lock(&flock); for(f=flist[h]; f; f=f->next) if(f->fid == fid && f->cp == cp){ /* * Already in use is an error * when called from attach or clone (walk * in 9P2000). The console uses FID[12] and * never clunks them so catch that case. */ if(flag == 0 || cp == cons.chan) goto out; unlock(&flock); return 0; } if(flag) { f = newfp(); if(f) { f->fid = fid; f->cp = cp; f->wpath = 0; f->tlock = 0; f->doffset = 0; f->dslot = 0; f->auth = 0; f->next = flist[h]; flist[h] = f; goto out; } } unlock(&flock); return 0;out: unlock(&flock); qlock(f); if(f->fid == fid && f->cp == cp) return f; qunlock(f); goto loop;}/* * always called with flock locked */File*newfp(void){ static int first; File *f; int start, i; i = first; start = i; do { f = &files[i]; i++; if(i >= conf.nfile) i = 0; if(f->cp) continue; first = i; return f; } while(i != start); print("out of files\n"); return 0;}voidfreefp(File *fp){ Chan *cp; File *f, *prev; int h; if(!fp || !(cp = fp->cp)) return; h = (long)cp + fp->fid; if(h < 0) h = ~h; h %= nelem(flist); lock(&flock); for(prev=0,f=flist[h]; f; prev=f,f=f->next) if(f == fp) { if(prev) prev->next = f->next; else flist[h] = f->next; break; } fp->cp = 0; unlock(&flock);}intiaccess(File *f, Dentry *d, int m){ /* uid none gets only other permissions */ if(f->uid != 0) { /* * owner */ if(f->uid == d->uid) if((m<<6) & d->mode) return 0; /* * group membership */ if(ingroup(f->uid, d->gid)) if((m<<3) & d->mode) return 0; } /* * other */ if(m & d->mode) { if((d->mode & DDIR) && (m == DEXEC)) return 0; if(!ingroup(f->uid, 9999)) return 0; } /* * various forms of superuser */ if(wstatallow) return 0; if(duallow != 0 && duallow == f->uid) if((d->mode & DDIR) && (m == DREAD || m == DEXEC)) return 0; return 1;}Tlock*tlocked(Iobuf *p, Dentry *d){ Tlock *t, *t1; Off qpath; Timet tim; Device *dev; tim = toytime(); qpath = d->qid.path; dev = p->dev;again: t1 = 0; for(t=tlocks+NTLOCK-1; t>=tlocks; t--) { if(t->qpath == qpath) if(t->time >= tim) if(t->dev == dev) return nil; /* its locked */ if(t1 != nil && t->time == 0) t1 = t; /* remember free lock */ } if(t1 == 0) { // reclaim old locks lock(&tlocklock); for(t=tlocks+NTLOCK-1; t>=tlocks; t--) if(t->time < tim) { t->time = 0; t1 = t; } unlock(&tlocklock); } if(t1) { lock(&tlocklock); if(t1->time != 0) { unlock(&tlocklock); goto again; } t1->dev = dev; t1->qpath = qpath; t1->time = tim + TLOCK; unlock(&tlocklock); } /* botch * out of tlock nodes simulates * a locked file */ return t1;}Wpath*newwp(void){ static int si = 0; int i; Wpath *w, *sw, *ew; i = si + 1; if(i < 0 || i >= conf.nwpath) i = 0; si = i; sw = &wpaths[i]; ew = &wpaths[conf.nwpath]; for(w=sw;;) { w++; if(w >= ew) w = &wpaths[0]; if(w == sw) { print("out of wpaths\n"); return 0; } if(w->refs) continue; lock(&wpathlock); if(w->refs) { unlock(&wpathlock); continue; } w->refs = 1; w->up = 0; unlock(&wpathlock); return w; }}voidfreewp(Wpath *w){ lock(&wpathlock); for(; w; w=w->up) w->refs--; unlock(&wpathlock);}Offqidpathgen(Device *dev){ Iobuf *p; Superb *sb; Off path; p = getbuf(dev, superaddr(dev), Bread|Bmod); if(!p || checktag(p, Tsuper, QPSUPER)) panic("newqid: super block"); sb = (Superb*)p->iobuf; sb->qidgen++; path = sb->qidgen; putbuf(p); return path;}/* truncating to length > 0 */static voidtruncfree(Truncstate *ts, Device *dev, int d, Iobuf *p, int i){ int pastlast; Off a; pastlast = ts->pastlast; a = ((Off *)p->iobuf)[i]; if (d > 0 || pastlast) buffree(dev, a, d, ts); if (pastlast) { ((Off *)p->iobuf)[i] = 0; p->flags |= Bmod|Bimm; } else if (d == 0 && ts->relblk == ts->lastblk) ts->pastlast = 1; if (d == 0) ts->relblk++;}/* * free the block at `addr' on dev. * if it's an indirect block (d [depth] > 0), * first recursively free all the blocks it names. * * ts->relblk is the block number within the file of this * block (or the first data block eventually pointed to via * this indirect block). */voidbuffree(Device *dev, Off addr, int d, Truncstate *ts){ Iobuf *p; Off a; int i, pastlast; if(!addr) return; pastlast = (ts == nil? 1: ts->pastlast); /* * if this is an indirect block, recurse and free any * suitable blocks within it (possibly via further indirect blocks). */ if(d > 0) { d--; p = getbuf(dev, addr, Bread); if(p) { if (ts == nil) /* common case: create */ for(i=INDPERBUF-1; i>=0; i--) { a = ((Off *)p->iobuf)[i]; buffree(dev, a, d, nil); } else /* wstat truncation */ for (i = 0; i < INDPERBUF; i++) truncfree(ts, dev, d, p, i); putbuf(p); } } if (!pastlast) return; /* * having zeroed the pointer to this block, add it to the free list. * stop outstanding i/o */ p = getbuf(dev, addr, Bprobe); if(p) { p->flags &= ~(Bmod|Bimm); putbuf(p); } /* * dont put written worm * blocks into free list */ if(dev->type == Devcw) { i = cwfree(dev, addr); if(i) return; } p = getbuf(dev, superaddr(dev), Bread|Bmod); if(!p || checktag(p, Tsuper, QPSUPER)) panic("buffree: super block"); addfree(dev, addr, (Superb*)p->iobuf); putbuf(p);}Offbufalloc(Device *dev, int tag, long qid, int uid){ Iobuf *bp, *p; Superb *sb; Off a, n; p = getbuf(dev, superaddr(dev), Bread|Bmod); if(!p || checktag(p, Tsuper, QPSUPER)) { print("bufalloc: super block\n"); if(p) putbuf(p); return 0; } sb = (Superb*)p->iobuf;loop: n = --sb->fbuf.nfree; sb->tfree--; if(n < 0 || n >= FEPERBUF) { print("bufalloc: %Z: bad freelist\n", dev); n = 0; sb->fbuf.free[0] = 0; } a = sb->fbuf.free[n]; if(n <= 0) { if(a == 0) { sb->tfree = 0; sb->fbuf.nfree = 1; if(dev->type == Devcw) { n = uid; if(n < 0 || n >= nelem(growacct)) n = 0; growacct[n]++; if(cwgrow(dev, sb, uid)) goto loop; } putbuf(p); print("fs %Z full uid=%d\n", dev, uid); return 0; } bp = getbuf(dev, a, Bread); if(!bp || checktag(bp, Tfree, QPNONE)) { if(bp) putbuf(bp); putbuf(p); return 0; } sb->fbuf = *(Fbuf*)bp->iobuf; putbuf(bp); } bp = getbuf(dev, a, Bmod); memset(bp->iobuf, 0, RBUFSIZE); settag(bp, tag, qid); if(tag == Tind1 || tag == Tind2 || tag == Tdir) bp->flags |= Bimm; putbuf(bp); putbuf(p); return a;}/* * what are legal characters in a name? * only disallow control characters. * a) utf avoids control characters. * b) '/' may not be the separator */intcheckname(char *n){ int i, c; for(i=0; i<NAMELEN; i++) { c = *n & 0xff; if(c == 0) { if(i == 0) return 1; memset(n, 0, NAMELEN-i); return 0; } if(c <= 040) return 1; n++; } return 1; /* too long */}voidaddfree(Device *dev, Off addr, Superb *sb){ int n; Iobuf *p; n = sb->fbuf.nfree; if(n < 0 || n > FEPERBUF) panic("addfree: bad freelist"); if(n >= FEPERBUF) { p = getbuf(dev, addr, Bmod|Bimm); if(p == 0) panic("addfree: getbuf"); *(Fbuf*)p->iobuf = sb->fbuf; settag(p, Tfree, QPNONE); putbuf(p); n = 0; } sb->fbuf.free[n++] = addr; sb->fbuf.nfree = n; sb->tfree++; if(addr >= sb->fsize) sb->fsize = addr+1;}static intYfmt(Fmt* fmt){ Chan *cp; char s[20]; cp = va_arg(fmt->args, Chan*); sprint(s, "C%d.%.3d", cp->type, cp->chan); return fmtstrcpy(fmt, s);}static intZfmt(Fmt* fmt){ Device *d; int c, c1; char s[100]; d = va_arg(fmt->args, Device*); if(d == 0) { sprint(s, "Z***"); goto out; } switch(d->type) { default: sprint(s, "D%d", d->type); break; case Devwren: c = 'w'; goto d1; case Devide: c = 'h'; goto d1; case Devmarvsata: c = 'm'; goto d1; case Devworm: c = 'r'; goto d1; case Devlworm: c = 'l'; goto d1; d1: if(d->wren.ctrl == 0 && d->wren.lun == 0) sprint(s, "%c%d", c, d->wren.targ); else sprint(s, "%c%d.%d.%d", c, d->wren.ctrl, d->wren.targ, d->wren.lun); break; case Devmcat: c = '('; c1 = ')'; goto d2; case Devmlev: c = '['; c1 = ']'; goto d2; case Devmirr: c = '{'; c1 = '}'; d2: if(d->cat.first == d->cat.last) sprint(s, "%c%Z%c", c, d->cat.first, c1); else if(d->cat.first->link == d->cat.last) sprint(s, "%c%Z%Z%c", c, d->cat.first, d->cat.last, c1); else sprint(s, "%c%Z-%Z%c", c, d->cat.first, d->cat.last, c1); break; case Devro: sprint(s, "o%Z%Z", d->ro.parent->cw.c, d->ro.parent->cw.w); break; case Devcw: sprint(s, "c%Z%Z", d->cw.c, d->cw.w); break; case Devjuke: sprint(s, "j%Z%Z", d->j.j, d->j.m); break; case Devfworm: sprint(s, "f%Z", d->fw.fw); break; case Devpart: sprint(s, "p(%Z)%ld.%ld", d->part.d, d->part.base, d->part.size); break; case Devswab: sprint(s, "x%Z", d->swab.d); break; case Devnone: sprint(s, "n"); break; }out: return fmtstrcpy(fmt, s);}static intWfmt(Fmt* fmt){ Filter* a; char s[30]; a = va_arg(fmt->args, Filter*); snprint(s, sizeof s, "%lud", fdf(a->filter, a->c3*a->c1)); return fmtstrcpy(fmt, s);}static intGfmt(Fmt* fmt){ int t; char *s; t = va_arg(fmt->args, int); s = "<badtag>"; if(t >= 0 && t < MAXTAG) s = tagnames[t]; return fmtstrcpy(fmt, s);}static intEfmt(Fmt* fmt){ char s[64]; uchar *p; p = va_arg(fmt->args, uchar*); sprint(s, "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux", p[0], p[1], p[2], p[3], p[4], p[5]); return fmtstrcpy(fmt, s);}static intIfmt(Fmt* fmt){ char s[64]; uchar *p; p = va_arg(fmt->args, uchar*); sprint(s, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); return fmtstrcpy(fmt, s);}voidformatinit(void){ quotefmtinstall(); fmtinstall('Y', Yfmt); /* print channels */ fmtinstall('Z', Zfmt); /* print devices */ fmtinstall('W', Wfmt); /* print filters */ fmtinstall('G', Gfmt); /* print tags */ fmtinstall('T', Tfmt); /* print times */ fmtinstall('E', Efmt); /* print ether addresses */ fmtinstall('I', Ifmt); /* print ip addresses */}voidrootream(Device *dev, Off addr){ Iobuf *p; Dentry *d; p = getbuf(dev, addr, Bmod|Bimm); memset(p->iobuf, 0, RBUFSIZE); settag(p, Tdir, QPROOT); d = getdir(p, 0); strcpy(d->name, "/"); d->uid = -1; d->gid = -1; d->mode = DALLOC | DDIR | ((DREAD|DEXEC) << 6) | ((DREAD|DEXEC) << 3) | ((DREAD|DEXEC) << 0); d->qid = QID9P1(QPROOT|QPDIR,0); d->atime = time(); d->mtime = d->atime; d->muid = 0; putbuf(p);}voidsuperream(Device *dev, Off addr){ Iobuf *p; Superb *s; Off i; p = getbuf(dev, addr, Bmod|Bimm); memset(p->iobuf, 0, RBUFSIZE); settag(p, Tsuper, QPSUPER); s = (Superb*)p->iobuf; s->fstart = 2; s->fsize = devsize(dev); s->fbuf.nfree = 1; s->qidgen = 10;#ifdef AUTOSWAB s->magic = 0x123456789abcdef0;#endif for(i=s->fsize-1; i>=addr+2; i--) addfree(dev, i, s); putbuf(p);}struct{ Lock; Msgbuf *smsgbuf; Msgbuf *lmsgbuf;} msgalloc;/* * pre-allocate some message buffers at boot time. * if this supply is exhausted, more will be allocated as needed. */voidmbinit(void){ Msgbuf *mb; Rabuf *rb; int i; lock(&msgalloc); unlock(&msgalloc); msgalloc.lmsgbuf = 0; msgalloc.smsgbuf = 0; for(i=0; i<conf.nlgmsg; i++) { mb = ialloc(sizeof(Msgbuf), 0); if(1) mb->xdata = ialloc(LARGEBUF+256, 256); else mb->xdata = ialloc(LARGEBUF+OFFMSG, LINESIZE); mb->flags = LARGE; mb->free = 0; mbfree(mb); cons.nlarge++; } for(i=0; i<conf.nsmmsg; i++) { mb = ialloc(sizeof(Msgbuf), 0); if(1) mb->xdata = ialloc(SMALLBUF+256, 256); else mb->xdata = ialloc(SMALLBUF+OFFMSG, LINESIZE); mb->flags = 0; mb->free = 0; mbfree(mb); cons.nsmall++; } memset(mballocs, 0, sizeof(mballocs));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -