static int findCDir(Biobuf *bin) { int64_t ecoff; int32_t off; int entries, zclen; ecoff = Bseek(bin, -ZECHeadSize, 2); if(ecoff < 0) sysfatal("can't seek to header"); if(get4(bin) != ZECHeader) sysfatal("bad magic number on directory"); get2(bin); get2(bin); get2(bin); entries = get2(bin); get4(bin); off = get4(bin); zclen = get2(bin); while(zclen-- > 0) get1(bin); if(Bseek(bin, off, 0) != off) sysfatal("can't seek to contents"); return entries; }
Entry getentry(long b) { long e, n, dtop; static Entry ans; static int anslen = 0; e = (*dict->nextoff)(b+1); ans.doff = b; if(e < 0) { dtop = Bseek(bdict, 0L, 2); if(b < dtop) { e = dtop; } else { err("couldn't seek to entry"); ans.start = 0; ans.end = 0; } } n = e-b; if(n) { if(n > anslen) { ans.start = realloc(ans.start, n); if(!ans.start) { err("out of memory"); exits("nomem"); } anslen = n; } Bseek(bdict, b, 0); n = Bread(bdict, ans.start, n); ans.end = ans.start + n; } return ans; }
char * doread(Ram *r, int64_t off, int32_t cnt) { int i, err; Block bs; ZipHead zh; static Qid oqid; static char buf[Maxbuf]; static uint8_t *cache = nil; if (cnt > Maxbuf) sysfatal("file too big (>%d)", Maxbuf); if (Bseek(bin, r->addr & 0x7FFFFFFFFFFFFFFFLL, 0) < 0) sysfatal("seek failed"); memset(&zh, 0, sizeof(zh)); if (!header(bin, &zh)) sysfatal("cannot get local header"); switch(zh.meth){ case 0: if (Bseek(bin, off, 1) < 0) sysfatal("seek failed"); if (Bread(bin, buf, cnt) != cnt) sysfatal("read failed"); break; case 8: if (r->qid.path != oqid.path){ oqid = r->qid; if (cache) free(cache); cache = emalloc(r->ndata); bs.pos = cache; bs.limit = cache+r->ndata; if ((err = inflate(&bs, blwrite, bin, (int(*)(void*))Bgetc)) != FlateOk) sysfatal("inflate failed - %s", flateerr(err)); if (blockcrc(crctab, crc, cache, r->ndata) != zh.crc) fprint(2, "%s - crc failed", r->name); if ((r->addr & High64) && MUNGE_CR){ for (i = 0; i < r->ndata -1; i++) if (cache[i] == '\r' && cache[i +1] == '\n') cache[i] = ' '; } } memcpy(buf, cache+off, cnt); break; default: sysfatal("%d - unsupported compression method", zh.meth); break; } return buf; }
int64_t Bfilelen(void *vb) { Biobuf *b; int64_t n; b = vb; n = Bseek(b, 0L, 2); Bseek(b, 0L, 0); return n; }
int locate(void) { vlong top, bot, mid; long c; int n; bot = 0; top = Bseek(dfile, 0, 2); for(;;) { mid = (top+bot) / 2; Bseek(dfile, mid, 0); do c = Bgetrune(dfile); while(c>=0 && c!='\n'); mid = Boffset(dfile); if(!getword(dfile, entry, sizeof(entry)/sizeof(entry[0]))) break; rcanon(entry, word); n = compare(key, word); switch(n) { case -2: case -1: case 0: if(top <= mid) break; top = mid; continue; case 1: case 2: bot = mid; continue; } break; } Bseek(dfile, bot, 0); while(getword(dfile, entry, sizeof(entry)/sizeof(entry[0]))) { rcanon(entry, word); n = compare(key, word); switch(n) { case -2: return 0; case -1: if(exact) return 0; case 0: return 1; case 1: case 2: continue; } } return 0; }
void Creadblock(Cdimg *cd, void *buf, ulong block, ulong len) { assert(block != 0); /* nothing useful there */ Bflush(&cd->bwr); if(Bseek(&cd->brd, block*Blocksize, 0) != block*Blocksize) sysfatal("error seeking to block %lud", block); if(Bread(&cd->brd, buf, len) != len) sysfatal("error reading %lud bytes at block %lud: %r %lld", len, block, Bseek(&cd->brd, 0, 2)); }
/* * Return offset into bdict where next webster entry after fromoff starts. * Webster entries start with <p><hw> */ long pgwnextoff(long fromoff) { long a, n; int c; a = Bseek(bdict, fromoff, 0); if(a != fromoff) return -1; n = 0; for(;;) { c = Bgetc(bdict); if(c < 0) break; if(c == '<' && Bgetc(bdict) == 'p' && Bgetc(bdict) == '>') { c = Bgetc(bdict); if(c == '<') { if (Bgetc(bdict) == 'h' && Bgetc(bdict) == 'w' && Bgetc(bdict) == '>') n = 7; } else if (c == '{') n = 4; if(n) break; } } return (Boffset(bdict)-n); }
int oreadblock(Ofile *f, int block, uint32_t off, char *buf, int nbuf) { int n; if(block < 0 || block >= f->nblock) { werrstr("attempt to read %x/%lx\n", block, f->nblock); return -1; } if(off >= Blocksize){ print("offset too far into block\n"); return 0; } if(off+nbuf > Blocksize) nbuf = Blocksize-off; /* blocks start numbering at -1 [sic] */ off += (block+1)*Blocksize; if(Bseek(f->b, off, 0) != off){ print("seek failed\n"); return -1; } n = Bread(f->b, buf, nbuf); if(n < 0) print("Bread failed: %r"); return n; }
int32_t pcollgnextoff(int32_t fromoff) { int c, state = 0, defoff = -1; if(Bseek(bdict, fromoff, 0) < 0) return -1; while((c = Bgetc(bdict)) >= 0){ if(c == '\r') defoff = Boffset(bdict); switch(state){ case 0: if(c == 0x05) state = 1; break; case 1: if(c == 'h') state = 2; else state = 0; break; case 2: if(c == 0x06) return (Boffset(bdict)-3); else state = 0; break; } } return defoff; }
void contentinit(void) { static Biobuf *b = nil; static Qid qid; char *file, *s; Suffix *this; file = "/sys/lib/mimetype"; if(b == nil){ /* first time */ b = Bopen(file, OREAD); if(b == nil) sysfatal("can't read from %s", file); } if(updateQid(Bfildes(b), &qid) == 0) return; Bseek(b, 0, 0); while(suffixes!=nil){ this = suffixes; suffixes = suffixes->next; free(this->suffix); free(this->generic); free(this->specific); free(this->encoding); free(this); } while((s = Brdline(b, '\n')) != nil){ s[Blinelen(b) - 1] = 0; suffixes = parsesuffix(s, suffixes); } }
static int okfile(char *cp, Biobuf *fp) { char *buf; int len; char *bp, *ep; int c; len = strlen(cp); Bseek(fp, 0, 0); /* one iteration per system name in the file */ while(buf = Brdline(fp, '\n')) { ep = &buf[Blinelen(fp)]; for(bp=buf; bp < ep;){ while(isspace(*bp) || *bp==',') bp++; if(strncmp(bp, cp, len) == 0) { c = *(bp+len); if(isspace(c) || c==',') return 1; } while(bp < ep && (!isspace(*bp)) && *bp!=',') bp++; } } /* didn't find it, prohibit forwarding */ return 0; }
static int pswritepage(Document *d, int fd, int page) { Biobuf *b = d->b; PSInfo *ps = d->extra; int t, n, i; long begin, end; char buf[8192]; if(page == -1) begin = ps->psoff; else begin = ps->page[page].offset; end = ps->page[page+1].offset; if(chatty) { fprint(2, "writepage(%d)... from #%ld to #%ld...\n", page, begin, end); } Bseek(b, begin, 0); t = end-begin; n = sizeof(buf); if(n > t) n = t; while(t > 0 && (i=Bread(b, buf, n)) > 0) { if(write(fd, buf, i) != i) return -1; t -= i; if(n > t) n = t; } return end-begin; }
void dcmd(char *arname, int count, char **files) { Armember *bp; int fd, i; if (!count) return; fd = openar(arname, ORDWR, 0); Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); astart = newtempfile(artemp); for (i = 0; bp = getdir(&bar); i++) { if(match(count, files)) { mesg('d', file); skip(&bar, bp->size); if (strcmp(file, symdef) == 0) allobj = 0; } else if (i == 0 && strcmp(file, symdef) == 0) skip(&bar, bp->size); else { scanobj(&bar, astart, bp->size); arcopy(&bar, astart, bp); } } close(fd); install(arname, astart, 0, 0, 0); }
/* * Skip an archive member */ void skip(Biobuf *bp, long len) { if (len & 01) len++; Bseek(bp, len, 1); }
void main(int argc, char *argv[]) { int i; Biobuf *bin; Binit(&bout, 1, OWRITE); argv0 = argv[0]; ARGBEGIN { case 'a': aflag = 1; break; case 'g': gflag = 1; break; case 'h': hflag = 1; break; case 'n': nflag = 1; break; case 's': sflag = 1; break; case 'u': uflag = 1; break; } ARGEND if (argc > 1) multifile++; for(i=0; i<argc; i++){ filename = argv[i]; bin = Bopen(filename, OREAD); if(bin == 0){ error("cannot open %s", filename); continue; } if (isar(bin)) doar(bin); else{ Bseek(bin, 0, 0); dofile(bin); } Bterm(bin); } exits(errs); }
int gsopen(Modem *m) { int n; char bytes[Gshdrsize]; /* * Is this gs output */ n = Bread(m->bp, bytes, Gshdrsize); if(n != Gshdrsize) return seterror(m, Esys); if(bytes[0]!='\0' || strcmp(bytes+1, "PC Research, Inc")!=0){ Bseek(m->bp, 0, 0); return seterror(m, Esys); } m->valid |= Vtype; if(bytes[0x1d]) m->vr = 1; else m->vr = 0; m->wd = 0; m->ln = 2; m->df = 0; return Eok; }
/* * look for the next file in an archive. * adapted from libmach. */ static vlong nextar(Biobuf *bp, vlong off, struct ar_hdr *a) { int r; int32 arsize; char *buf; if (off&01) off++; Bseek(bp, off, 0); buf = Brdline(bp, '\n'); r = Blinelen(bp); if(buf == nil) { if(r == 0) return 0; return -1; } if(r != SAR_HDR) return -1; memmove(a, buf, SAR_HDR); if(strncmp(a->fmag, ARFMAG, sizeof a->fmag)) return -1; arsize = strtol(a->size, 0, 0); if (arsize&1) arsize++; return arsize + r; }
static int macholoadrel(MachoObj *m, MachoSect *sect) { MachoRel *rel, *r; uchar *buf, *p; int i, n; uint32 v; if(sect->rel != nil || sect->nreloc == 0) return 0; rel = mal(sect->nreloc * sizeof r[0]); n = sect->nreloc * 8; buf = mal(n); if(Bseek(m->f, m->base + sect->reloff, 0) < 0 || Bread(m->f, buf, n) != n) return -1; for(i=0; i<sect->nreloc; i++) { r = &rel[i]; p = buf+i*8; r->addr = m->e->e32(p); // TODO(rsc): Wrong interpretation for big-endian bitfields? if(r->addr & 0x80000000) { // scatterbrained relocation r->scattered = 1; v = r->addr >> 24; r->addr &= 0xFFFFFF; r->type = v & 0xF; v >>= 4; r->length = 1<<(v&3); v >>= 2; r->pcrel = v & 1; r->value = m->e->e32(p+4); } else {
/* * find the start of the central directory * returns the number of entries in the directory, * or -1 if there was an error */ static int findCDir(Biobuf *bin, char *file) { int64_t ecoff; int32_t off, size, m; int entries, zclen, dn, ds, de; ecoff = Bseek(bin, -ZECHeadSize, 2); if(ecoff < 0){ fprint(2, "unzip: can't seek to contents of %s\n", file); longjmp(seekjmp, 1); return -1; } if(setjmp(zjmp)) return -1; if((m=get4(bin)) != ZECHeader){ fprint(2, "unzip: bad magic number for table of contents of %s: %#.8lx\n", file, m); longjmp(seekjmp, 1); return -1; } dn = get2(bin); ds = get2(bin); de = get2(bin); entries = get2(bin); size = get4(bin); off = get4(bin); zclen = get2(bin); while(zclen-- > 0) get1(bin); if(verbose > 1){ print("table starts at %ld for %ld bytes\n", off, size); if(ecoff - size != off) print("\ttable should start at %lld-%ld=%lld\n", ecoff, size, ecoff-size); if(dn || ds || de != entries) print("\tcurrent disk=%d start disk=%d table entries on this disk=%d\n", dn, ds, de); } if(Bseek(bin, off, 0) != off){ fprint(2, "unzip: can't seek to start of contents of %s\n", file); longjmp(seekjmp, 1); return -1; } return entries; }
/* * extract files using the info in the central directory structure */ static int unzip(Biobuf *bin, char *file) { ZipHead zh; int64_t off; int ok, eok, entries; entries = findCDir(bin, file); if(entries < 0) return 0; ok = 1; while(entries-- > 0){ if(setjmp(zjmp)){ free(zh.file); return 0; } memset(&zh, 0, sizeof(zh)); if(!cheader(bin, &zh)) return ok; off = Boffset(bin); if(wantFile(zh.file)){ if(Bseek(bin, zh.off, 0) < 0){ fprint(2, "unzip: can't seek to start of %s, skipping\n", zh.file); ok = 0; }else{ eok = unzipEntry(bin, &zh); if(eok <= 0){ fprint(2, "unzip: skipping %s\n", zh.file); ok = 0; } } } free(zh.file); zh.file = nil; if(Bseek(bin, off, 0) < 0){ fprint(2, "unzip: can't seek to start of next entry, terminating extraction\n"); return 0; } } return ok; }
void join(int seekf) { int cmp, less; int n[NIN]; int64_t top, bot; less = seekf == F2; top = 0; bot = Boffset(f[seekf]); readboth(n); while((n[F1]>0 && n[F2]>0) || ((a1||a2) && n[F1]+n[F2]>0)) { cmp = comp(); if((n[F1]>0 && n[F2]>0 && cmp>0) || n[F1]==0) { if(a2) output(0, n[F2]); if (seekf == F2) bot = Boffset(f[seekf]); n[F2] = input(F2); } else if((n[F1]>0 && n[F2]>0 && cmp<0) || n[F2]==0) { if(a1) output(n[F1], 0); if (seekf == F1) bot = Boffset(f[seekf]); n[F1] = input(F1); } else { /* n[F1]>0 && n[F2]>0 && cmp==0 */ while(n[F2]>0 && cmp==0) { output(n[F1], n[F2]); top = Boffset(f[seekf]); n[seekf] = input(seekf); cmp = comp(); } seekbotreadboth(seekf, bot, n); for(;;) { cmp = comp(); if(n[F1]>0 && n[F2]>0 && cmp==0) { output(n[F1], n[F2]); n[seekf] = input(seekf); } else if((n[F1]>0 && n[F2]>0 && (less? cmp<0 :cmp>0)) || n[seekf]==0) seekbotreadboth(seekf, bot, n); else { /* * n[F1]>0 && n[F2]>0 && * (less? cmp>0 :cmp<0) || * n[seekf==F1? F2: F1]==0 */ Bseek(f[seekf], top, 0); bot = top; n[seekf] = input(seekf); break; } } } } }
void qcmd(char *arname, int count, char **files) { int fd, i; Armember *bp; Biobuf *bfile; if(aflag || bflag) { fprint(2, "ar: abi not allowed with q\n"); exits("error"); } fd = openar(arname, ORDWR, 1); if (fd < 0) { if(!cflag) fprint(2, "ar: creating %s\n", arname); fd = arcreate(arname); } Binit(&bar, fd, OREAD); Bseek(&bar,seek(fd,0,1), 1); /* leave note group behind when writing archive; i.e. sidestep interrupts */ rfork(RFNOTEG); Bseek(&bar, 0, 2); bp = newmember(); for(i=0; i<count && files[i]; i++) { file = files[i]; files[i] = 0; bfile = Bopen(file, OREAD); if(!bfile) fprint(2, "ar: %s cannot open\n", file); else { mesg('q', file); armove(bfile, 0, bp); if (!arwrite(fd, bp)) wrerr(); free(bp->member); bp->member = 0; Bterm(bfile); } } free(bp); close(fd); }
static void copy(Biobufhdr *fin, Biobufhdr *fout, Section *s) { if (s->end <= s->start) return; Bseek(fin, s->start, 0); while (Bseek(fin, 0L, 1) < s->end && (buf=Brdline(fin, '\n')) != nil){ /* * We have to be careful here, because % can legitimately appear * in Ascii85 encodings, and must not be elided. * The goal here is to make any DSC comments impotent without * actually changing the behavior of the Postscript. * Since stripping ``comments'' breaks Ascii85, we can instead just * indent comments a space, which turns DSC comments into non-DSC comments * and has no effect on binary encodings, which are whitespace-blind. */ if(buf[0] == '%') Bputc(fout, ' '); Bwrite(fout, buf, Blinelen(fin)); } }
/* * extract the symbol references from an object file */ void scanobj(Biobuf *b, Arfile *ap, int size) { int obj; long offset; Dir *d; static int lastobj = -1; if (!allobj) /* non-object file encountered */ return; offset = Boffset(b); obj = objtype(b, 0); if (obj < 0) { /* not an object file */ allobj = 0; d = dirfstat(Bfildes(b)); if (d != nil && d->length == 0) fprint(2, "ar: zero length file %s\n", file); free(d); Bseek(b, offset, 0); return; } if (lastobj >= 0 && obj != lastobj) { fprint(2, "ar: inconsistent object file %s\n", file); allobj = 0; Bseek(b, offset, 0); return; } lastobj = obj; if (!readar(b, obj, offset+size, 0)) { fprint(2, "ar: invalid symbol reference in file %s\n", file); allobj = 0; Bseek(b, offset, 0); return; } Bseek(b, offset, 0); objtraverse(objsym, ap); }
static int allowed(char *dir) { Reprog *re; int okay; Resub match; if (strcmp(dir, "..") == 0 || strncmp(dir, "../", 3) == 0) return(0); if (aio == nil) return(0); if (aio != nil) Bseek(aio, 0, 0); if (dio != nil) Bseek(dio, 0, 0); /* if no deny list, assume everything is denied */ okay = (dio != nil); /* go through denials till we find a match */ while (okay && (re = getre(dio)) != nil) { memset(&match, 0, sizeof(match)); okay = (regexec(re, dir, &match, 1) != 1); free(re); } /* go through accepts till we have a match */ if (aio == nil) return(okay); while (!okay && (re = getre(aio)) != nil) { memset(&match, 0, sizeof(match)); okay = (regexec(re, dir, &match, 1) == 1); free(re); } return(okay); }
long worldnextoff(long fromoff) { int nh, np, nd; uchar buf[6]; if(Bseek(bdict, fromoff-1, 0) < 0) return -1; if(Bread(bdict, buf, 6) != 6) return -1; nh = GSHORT(buf); np = GSHORT(buf+2); nd = GSHORT(buf+4); return fromoff-1 + 6 + nh + np + nd; }
void thumbpctab(Biobuf *b, Fhdr *fp) { int n, o, ta; uchar c[8]; pcentry *tab; Bseek(b, fp->lnpcoff+fp->lnpcsz, 0); o = (int)Boffset(b); Bseek(b, 0, 2); n = (int)Boffset(b)-o; pctab = (pcentry*)malloc(n); if(pctab == 0) return; ta = fp->txtaddr; tab = pctab; Bseek(b, fp->lnpcoff+fp->lnpcsz, 0); while(Bread(b, c, sizeof(c)) == sizeof(c)){ tab->start = ta + (c[0]<<24)|(c[1]<<16)|(c[2]<<8)|c[3]; tab->stop = ta + (c[4]<<24)|(c[5]<<16)|(c[6]<<8)|c[7]; tab++; } npctab = n/sizeof(c); }
int _read5(Biobuf *bp, Prog *p) { int as, n; Addr a; as = BGETC(bp); /* as */ if(as < 0) return 0; p->kind = aNone; p->sig = 0; if(as == ANAME || as == ASIGNAME){ if(as == ASIGNAME){ Bread(bp, &p->sig, 4); p->sig = leswal(p->sig); } p->kind = aName; p->type = type2char(BGETC(bp)); /* type */ p->sym = BGETC(bp); /* sym */ n = 0; for(;;) { as = BGETC(bp); if(as < 0) return 0; n++; if(as == 0) break; } p->id = malloc(n); if(p->id == 0) return 0; Bseek(bp, -n, 1); if(Bread(bp, p->id, n) != n) return 0; return 1; } if(as == ATEXT) p->kind = aText; else if(as == AGLOBL) p->kind = aData; skip(bp, 6); /* scond(1), reg(1), lineno(4) */ a = addr(bp); addr(bp); if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN) p->kind = aNone; p->sym = a.sym; return 1; }
static int map(PeObj *obj, PeSect *sect) { if(sect->base != nil) return 0; sect->base = mal(sect->sh.SizeOfRawData); if(sect->sh.PointerToRawData == 0) // .bss doesn't have data in object file return 0; werrstr("short read"); if(Bseek(obj->f, obj->base+sect->sh.PointerToRawData, 0) < 0 || Bread(obj->f, sect->base, sect->sh.SizeOfRawData) != sect->sh.SizeOfRawData) return -1; return 0; }
Biobuf * prepare(int i, char *arg) { struct line *p; int j, h; Biobuf *bp; char *cp, buf[MAXLINELEN]; int nbytes; Rune r; bp = Bopen(arg, OREAD); if (!bp) { panic(mflag ? 0: 2, "cannot open %s: %r\n", arg); return 0; } if (binary) return bp; nbytes = Bread(bp, buf, MIN(1024, MAXLINELEN)); if (nbytes > 0) { cp = buf; while (cp < buf+nbytes-UTFmax) { /* * heuristic for a binary file in the * brave new UNICODE world */ cp += chartorune(&r, cp); if (r == 0 || (r > 0x7f && r <= 0xa0)) { binary++; return bp; } } Bseek(bp, 0, 0); } p = MALLOC(struct line, 3); for (j = 0; h = readhash(bp, buf); p[j].value = h) p = REALLOC(p, struct line, (++j+3)); len[i] = j; file[i] = p; input[i] = bp; /*fix*/ if (i == 0) { /*fix*/ file1 = arg; firstchange = 0; } else file2 = arg; return bp; }