X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/537f7e1718a8ccb48e14a45f927db51688d305c4..2222b6d952c6894c770971322ecee37801103a7c:/usr/src/old/ld/ld.c diff --git a/usr/src/old/ld/ld.c b/usr/src/old/ld/ld.c index d48d009162..ab714d04a4 100644 --- a/usr/src/old/ld/ld.c +++ b/usr/src/old/ld/ld.c @@ -1,17 +1,32 @@ -static char sccsid[] = "@(#)ld.c 3.2 %G%"; /* - * VAX VM/UNIX ld - string table version + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. */ -#include +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif not lint + +#ifndef lint +static char sccsid[] = "@(#)ld.c 5.10 (Berkeley) %G%"; +#endif not lint + +/* + * ld - string table version for VAX + */ + +#include #include #include #include #include #include #include -#include -#include +#include +#include /* * Basic strategy: @@ -170,16 +185,23 @@ char *tabstr; /* string table for table of contents */ * (historically) read from such a file at 2 different places at the * same time. These structures are remnants from those days, * and now serve only to catch ``Premature EOF''. + * In order to make I/O more efficient, we provide routines which + * use the optimal block size returned by stat(). */ +#define BLKSIZE 1024 typedef struct { short *fakeptr; int bno; int nibuf; int nuser; - char buff[BSIZE]; + char *buff; + int bufsize; } PAGE; PAGE page[2]; +int p_blksize; +int p_blkshift; +int p_blkmask; struct { short *fakeptr; @@ -217,6 +239,7 @@ int Sflag; /* discard all except locals and globals*/ int rflag; /* preserve relocation bits, don't define common */ int arflag; /* original copy of rflag */ int sflag; /* discard all symbols */ +int Mflag; /* print rudimentary load map */ int nflag; /* pure procedure */ int dflag; /* define common even with rflag */ int zflag; /* demand paged */ @@ -224,6 +247,8 @@ long hsize; /* size of hole at beginning of data to be squashed */ int Aflag; /* doing incremental load */ int Nflag; /* want impure a.out */ int funding; /* reading fundamental file for incremental load */ +int yflag; /* number of symbols to be traced */ +char **ytab; /* the symbols */ /* * These are the cumulative sizes, set in pass 1, which @@ -273,9 +298,10 @@ int delarg = 4; */ struct biobuf { short b_nleft; /* Number free spaces left in b_buf */ -/* Initialize to be less than BUFSIZ initially, to boundary align in file */ +/* Initialize to be less than b_bufsize initially, to boundary align in file */ char *b_ptr; /* Next place to stuff characters */ - char b_buf[BUFSIZ]; /* The buffer itself */ + char *b_buf; /* Pointer to the buffer */ + int b_bufsize; /* Size of the buffer */ off_t b_off; /* Current file offset */ struct biobuf *b_link; /* Link in chain for bflush() */ } *biobufs; @@ -295,17 +321,29 @@ off_t offset = sizeof (off_t); int ofilfnd; /* -o given; otherwise move l.out to a.out */ char *ofilename = "l.out"; +int ofilemode; /* respect umask even for unsucessful ld's */ int infil; /* current input file descriptor */ char *filname; /* and its name */ +#define NDIRS 25 +#define NDEFDIRS 3 /* number of default directories in dirs[] */ +char *dirs[NDIRS]; /* directories for library search */ +int ndir; /* number of directories */ + /* * Base of the string table of the current module (pass1 and pass2). */ char *curstr; +/* + * System software page size, as returned by getpagesize. + */ +int pagesize; + char get(); int delexit(); char *savestr(); +char *malloc(); main(argc, argv) char **argv; @@ -321,8 +359,27 @@ char **argv; } if (argc == 1) exit(4); - p = argv+1; + pagesize = getpagesize(); + /* + * Pull out search directories. + */ + for (c = 1; c < argc; c++) { + ap = argv[c]; + if (ap[0] == '-' && ap[1] == 'L') { + if (ap[2] == 0) + error(1, "-L: pathname missing"); + if (ndir >= NDIRS - NDEFDIRS) + error(1, "-L: too many directories"); + dirs[ndir++] = &ap[2]; + } + } + /* add default search directories */ + dirs[ndir++] = "/lib"; + dirs[ndir++] = "/usr/lib"; + dirs[ndir++] = "/usr/local/lib"; + + p = argv+1; /* * Scan files once to find where symbols are defined. */ @@ -346,7 +403,7 @@ char **argv; case 'u': case 'e': if (++c >= argc) - error(1, "-u or -c: arg missing"); + error(1, " -u or -e: arg missing"); enter(slookup(*p++)); if (ap[i]=='e') entrypt = lastsym; @@ -393,6 +450,9 @@ char **argv; load1arg(&ap[i]); ap[i]=save; goto next; + case 'M': + Mflag++; + continue; case 'x': xflag++; continue; @@ -427,10 +487,22 @@ char **argv; case 't': trace++; continue; + case 'y': + if (ap[i+1] == 0) + error(1, "-y: symbol name missing"); + if (yflag == 0) { + ytab = (char **)calloc(argc, sizeof (char **)); + if (ytab == 0) + error(1, "ran out of memory (-y)"); + } + ytab[yflag++] = &ap[i+1]; + goto next; case 'z': zflag++; Nflag = nflag = 0; continue; + case 'L': + goto next; default: filname = savestr("-x"); /* kludge */ filname[1] = ap[i]; /* kludge */ @@ -472,11 +544,29 @@ htoi(p) delexit() { + struct stat stbuf; + long size; + char c = 0; bflush(); unlink("l.out"); + /* + * We have to insure that the last block of the data segment + * is allocated a full pagesize block. If the underlying + * file system allocates frags that are smaller than pagesize, + * a full zero filled pagesize block needs to be allocated so + * that when it is demand paged, the paged in block will be + * appropriately filled with zeros. + */ + fstat(biofd, &stbuf); + size = round(stbuf.st_size, pagesize); + if (!rflag && size > stbuf.st_size) { + lseek(biofd, size - 1, 0); + if (write(biofd, &c, 1) != 1) + delarg |= 4; + } if (delarg==0 && Aflag==0) - chmod(ofilename, 0777 &~ umask(0)); + (void) chmod(ofilename, ofilemode); exit (delarg); } @@ -525,6 +615,9 @@ endload(argc, argv) funding = 0; c++; continue; + case 'y': + case 'L': + goto next; case 'l': ap[--i]='-'; load2arg(&ap[i]); @@ -544,8 +637,12 @@ load1arg(cp) { register struct ranlib *tp; off_t nloc; + int kind; - switch (getfile(cp)) { + kind = getfile(cp); + if (Mflag) + printf("%s\n", filname); + switch (kind) { /* * Plain file. @@ -559,7 +656,8 @@ load1arg(cp) * (Slowly) process each member. */ case 1: - error(-1, "warning: archive has no table of contents"); + error(-1, +"warning: archive has no table of contents; add one using ranlib(1)"); nloc = SARMAG; while (step(nloc)) nloc += sizeof(archdr) + @@ -601,8 +699,8 @@ load1arg(cp) } while (ldrand()) continue; - cfree((char *)tab); - cfree(tabstr); + free((char *)tab); + free(tabstr); nextlibp(-1); break; @@ -611,7 +709,8 @@ load1arg(cp) * as a normal library (but skip the __.SYMDEF file). */ case 3: - error(-1, "warning: table of contents is out of date"); + error(-1, +"warning: table of contents for archive is out of date; rerun ranlib(1)"); nloc = SARMAG; do nloc += sizeof(archdr) + @@ -660,6 +759,8 @@ nextlibp(val) error(1, "ran out of memory (nextlibp)"); } clibseg->li_first[clibseg->li_used++] = val; + if (val != -1 && Mflag) + printf("\t%s\n", archdr.ar_name); } /* @@ -678,7 +779,7 @@ ldrand() tplast = &tab[tnum-1]; for (tp = tab; tp <= tplast; tp++) { - if ((hp = slookup(tp->ran_un.ran_name)) == 0) + if ((hp = slookup(tp->ran_un.ran_name)) == 0 || *hp == 0) continue; sp = *hp; if (sp->n_type != N_EXT+N_UNDF) @@ -706,8 +807,12 @@ load1(libflg, loc) readhdr(loc); if (filhdr.a_syms == 0) { - if (filhdr.a_text+filhdr.a_data == 0) + if (filhdr.a_text+filhdr.a_data == 0) { + /* load2() adds a symbol for the file name */ + if (!libflg) + ssize += sizeof (cursym); return (0); + } error(1, "no namelist"); } if (libflg) @@ -828,7 +933,7 @@ middle() if (!Aflag) addsym = symseg[0].sy_first; database = round(tsize+textbase, - (nflag||zflag? PAGSIZ : sizeof (long))); + (nflag||zflag? pagesize : sizeof (long))); database += hsize; if (dflag || rflag==0) { ldrsym(p_etext, tsize, N_EXT+N_TEXT); @@ -871,7 +976,8 @@ middle() switch (sp->n_type & (N_TYPE+N_EXT)) { case N_EXT+N_UNDF: - errlev |= 01; + if (arflag == 0) + errlev |= 01; if ((arflag==0 || dflag) && sp->n_value==0) { if (sp==p_end || sp==p_etext || sp==p_edata) continue; @@ -941,16 +1047,26 @@ struct biobuf toutb; setupout() { int bss; - - biofd = creat(ofilename, 0666); - if (biofd < 0) - error(1, "cannot create output"); - tout = &toutb; - bopen(tout, 0); + struct stat stbuf; + extern char *sys_errlist[]; + extern int errno; + + ofilemode = 0777 & ~umask(0); + biofd = creat(ofilename, 0666 & ofilemode); + if (biofd < 0) { + filname = ofilename; /* kludge */ + archdr.ar_name[0] = 0; /* kludge */ + error(1, sys_errlist[errno]); /* kludge */ + } + fstat(biofd, &stbuf); /* suppose file exists, wrong*/ + if (stbuf.st_mode & 0111) { /* mode, ld fails? */ + chmod(ofilename, stbuf.st_mode & 0666); + ofilemode = stbuf.st_mode; + } filhdr.a_magic = nflag ? NMAGIC : (zflag ? ZMAGIC : OMAGIC); filhdr.a_text = nflag ? tsize : - round(tsize, zflag ? PAGSIZ : sizeof (long)); - filhdr.a_data = zflag ? round(dsize, PAGSIZ) : dsize; + round(tsize, zflag ? pagesize : sizeof (long)); + filhdr.a_data = zflag ? round(dsize, pagesize) : dsize; bss = bsize - (filhdr.a_data - dsize); if (bss < 0) bss = 0; @@ -967,33 +1083,32 @@ setupout() filhdr.a_entry = 0; filhdr.a_trsize = (rflag ? trsize:0); filhdr.a_drsize = (rflag ? drsize:0); + tout = &toutb; + bopen(tout, 0, stbuf.st_blksize); bwrite((char *)&filhdr, sizeof (filhdr), tout); - if (zflag) { - bflush1(tout); - biobufs = 0; - bopen(tout, PAGSIZ); - } + if (zflag) + bseek(tout, pagesize); wroff = N_TXTOFF(filhdr) + filhdr.a_text; - outb(&dout, filhdr.a_data); + outb(&dout, filhdr.a_data, stbuf.st_blksize); if (rflag) { - outb(&trout, filhdr.a_trsize); - outb(&drout, filhdr.a_drsize); + outb(&trout, filhdr.a_trsize, stbuf.st_blksize); + outb(&drout, filhdr.a_drsize, stbuf.st_blksize); } if (sflag==0 || xflag==0) { - outb(&sout, filhdr.a_syms); + outb(&sout, filhdr.a_syms, stbuf.st_blksize); wroff += sizeof (offset); - outb(&strout, 0); + outb(&strout, 0, stbuf.st_blksize); } } -outb(bp, inc) +outb(bp, inc, bufsize) register struct biobuf **bp; { *bp = (struct biobuf *)malloc(sizeof (struct biobuf)); if (*bp == 0) error(1, "ran out of memory (outb)"); - bopen(*bp, wroff); + bopen(*bp, wroff, bufsize); wroff += inc; } @@ -1098,6 +1213,14 @@ long loc; } /* end inline expansion of symreloc() */ type = cursym.n_type; + if (yflag && cursym.n_un.n_name) + for (i = 0; i < yflag; i++) + /* fast check for 2d character! */ + if (ytab[i][1] == cursym.n_un.n_name[1] && + !strcmp(ytab[i], cursym.n_un.n_name)) { + tracesym(); + break; + } if ((type&N_EXT) == 0) { if (!sflag&&!xflag&& (!Xflag||cursym.n_un.n_name[0]!='L'||type&N_STAB)) @@ -1148,11 +1271,117 @@ long loc; filhdr.a_data++; } torigin += filhdr.a_text; - dorigin += filhdr.a_data; - borigin += filhdr.a_bss; + dorigin += round(filhdr.a_data, sizeof (long)); + borigin += round(filhdr.a_bss, sizeof (long)); free(curstr); } +struct tynames { + int ty_value; + char *ty_name; +} tynames[] = { + N_UNDF, "undefined", + N_ABS, "absolute", + N_TEXT, "text", + N_DATA, "data", + N_BSS, "bss", + N_COMM, "common", + 0, 0, +}; + +tracesym() +{ + register struct tynames *tp; + + if (cursym.n_type & N_STAB) + return; + printf("%s", filname); + if (archdr.ar_name[0]) + printf("(%s)", archdr.ar_name); + printf(": "); + if ((cursym.n_type&N_TYPE) == N_UNDF && cursym.n_value) { + printf("definition of common %s size %d\n", + cursym.n_un.n_name, cursym.n_value); + return; + } + for (tp = tynames; tp->ty_name; tp++) + if (tp->ty_value == (cursym.n_type&N_TYPE)) + break; + printf((cursym.n_type&N_TYPE) ? "definition of" : "reference to"); + if (cursym.n_type&N_EXT) + printf(" external"); + if (tp->ty_name) + printf(" %s", tp->ty_name); + printf(" %s\n", cursym.n_un.n_name); +} + +#if !defined(tahoe) +/* for machines which allow arbitrarily aligned word and longword accesses */ +#define getw(cp) (*(short *)(cp)) +#define getl(cp) (*(long *)(cp)) +#define putw(cp, w) (*(short *)(cp) = (w)) +#define putl(cp, l) (*(long *)(cp) = (l)) +#else +short +getw(cp) + char *cp; +{ + union { + short w; + char c[2]; + } w; + + w.c[0] = *cp++; + w.c[1] = *cp++; + return (w.w); +} + +getl(cp) + char *cp; +{ + union { + long l; + char c[4]; + } l; + + l.c[0] = *cp++; + l.c[1] = *cp++; + l.c[2] = *cp++; + l.c[3] = *cp++; + return (l.l); +} + +putw(cp, v) + char *cp; + short v; +{ + union { + short w; + char c[2]; + } w; + + w.w = v; + *cp++ = w.c[0]; + *cp++ = w.c[1]; +} + +putl(cp, v) + char *cp; + long v; +{ + union { + long l; + char c[4]; + } l; + + l.l = v; + *cp++ = l.c[0]; + *cp++ = l.c[1]; + *cp++ = l.c[2]; + *cp++ = l.c[3]; +} +#endif + /* * This routine relocates the single text or data segment argument. * Offsets from external symbols are resolved by adding the value @@ -1167,7 +1396,7 @@ long loc; * each relocation datum address by our base position in the new segment. */ load2td(creloc, position, b1, b2) - long creloc, offset; + long creloc, position; struct biobuf *b1, *b2; { register struct nlist *sp; @@ -1200,11 +1429,11 @@ load2td(creloc, position, b1, b2) break; case 1: /* word */ - tw = *(short *)cp; + tw = getw(cp); break; case 2: /* long */ - tw = *(long *)cp; + tw = getl(cp); break; default: @@ -1282,10 +1511,10 @@ load2td(creloc, position, b1, b2) case 1: /* word */ if (tw < -32768 || tw > 32767) error(0, "word displacement overflow"); - *(short *)cp = tw; + putw(cp, tw); break; case 2: /* long */ - *(long *)cp = tw; + putl(cp, tw); break; } /* @@ -1301,8 +1530,8 @@ load2td(creloc, position, b1, b2) bwrite(codep, codesz, b1); if (rflag) bwrite(relp, relsz, b2); - cfree((char *)relp); - cfree(codep); + free((char *)relp); + free(codep); } finishout() @@ -1318,7 +1547,8 @@ finishout() } if (!ofilfnd) { unlink("a.out"); - link("l.out", "a.out"); + if (link("l.out", "a.out") < 0) + error(1, "cannot move l.out to a.out"); ofilename = "a.out"; } delarg = errlev; @@ -1332,7 +1562,7 @@ char *s; if (sflag || xflag) return; cursym.n_un.n_name = s; - cursym.n_type = N_TEXT; + cursym.n_type = N_EXT | N_FN; cursym.n_value = torigin; symwrite(&cursym, sout); } @@ -1376,16 +1606,16 @@ top: sp->ptr = p; goto top; } - if (n > BUFSIZ) { - take = n - n % BSIZE; - lseek(infil, (sp->bno+1)*BSIZE, 0); + if (n > p_blksize) { + take = n - n % p_blksize; + lseek(infil, (sp->bno+1)< sp->size || read(infil, loc, take) != take) error(1, "premature EOF"); loc += take; n -= take; sp->size -= take; sp->pos += take; - dseek(sp, (sp->bno+1+take/BSIZE)*BSIZE, -1); + dseek(sp, (sp->bno+1+(take>>p_blkshift))<>BSHIFT; - o = loc&BMASK; + b = loc>>p_blkshift; + o = loc&p_blkmask; if (o&01) error(1, "loader error; odd offset"); --sp->pno->nuser; @@ -1430,12 +1660,12 @@ long loc, s; if (page[0].bno < page[1].bno) p = &page[0]; p->bno = b; - lseek(infil, loc & ~(long)BMASK, 0); - if ((n = read(infil, p->buff, sizeof(p->buff))) < 0) + lseek(infil, loc & ~(long)p_blkmask, 0); + if ((n = read(infil, p->buff, p_blksize)) < 0) n = 0; p->nibuf = n; - } else - error(1, "botch: no pages"); + } else + error(1, "botch: no pages"); ++p->nuser; sp->bno = b; sp->pno = p; @@ -1453,7 +1683,7 @@ STREAM *asp; sp = asp; if ((sp->nibuf -= sizeof(char)) < 0) { - dseek(sp, ((long)(sp->bno+1)<bno+1)<nibuf -= sizeof(char); } if ((sp->size -= sizeof(char)) <= 0) { @@ -1470,37 +1700,42 @@ STREAM *asp; getfile(acp) char *acp; { - register char *cp; register int c; char arcmag[SARMAG+1]; struct stat stb; - cp = acp; - infil = -1; archdr.ar_name[0] = '\0'; - filname = cp; - if (cp[0]=='-' && cp[1]=='l') { - char *locfilname = "/usr/local/new/libxxxxxxxxxxxxxxx"; - if(cp[2] == '\0') - cp = "-la"; - filname = "/usr/new/libxxxxxxxxxxxxxxx"; - for(c=0; cp[c+2]; c++) { - filname[c+12] = cp[c+2]; - locfilname[c+18] = cp[c+2]; - } - filname[c+12] = locfilname[c+18] = '.'; - filname[c+13] = locfilname[c+19] = 'a'; - filname[c+14] = locfilname[c+20] = '\0'; - if ((infil = open(filname+4, 0)) >= 0) { - filname += 4; - } else if ((infil = open(filname, 0)) < 0) { - filname = locfilname; - } - } - if (infil == -1 && (infil = open(filname, 0)) < 0) + filname = acp; + if (filname[0] == '-' && filname[1] == 'l') + infil = libopen(filname + 2, O_RDONLY); + else + infil = open(filname, O_RDONLY); + if (infil < 0) error(1, "cannot open"); + fstat(infil, &stb); page[0].bno = page[1].bno = -1; page[0].nuser = page[1].nuser = 0; + c = stb.st_blksize; + if (c == 0 || (c & (c - 1)) != 0) { + /* use default size if not a power of two */ + c = BLKSIZE; + } + if (p_blksize != c) { + p_blksize = c; + p_blkmask = c - 1; + for (p_blkshift = 0; c > 1 ; p_blkshift++) + c >>= 1; + if (page[0].buff != NULL) + free(page[0].buff); + page[0].buff = (char *)malloc(p_blksize); + if (page[0].buff == NULL) + error(1, "ran out of memory (getfile)"); + if (page[1].buff != NULL) + free(page[1].buff); + page[1].buff = (char *)malloc(p_blksize); + if (page[1].buff == NULL) + error(1, "ran out of memory (getfile)"); + } text.pno = reloc.pno = (PAGE *) &fpage; fpage.nuser = 2; dseek(&text, 0L, SARMAG); @@ -1511,15 +1746,48 @@ char *acp; if (strcmp(arcmag, ARMAG)) return (0); dseek(&text, SARMAG, sizeof archdr); - if(text.size <= 0) + if (text.size <= 0) return (1); getarhdr(); - if (strncmp(archdr.ar_name, "__.SYMDEF", sizeof(archdr.ar_name)) != 0) + if (strncmp(archdr.ar_name, RANLIBMAG, sizeof(archdr.ar_name)) != 0) return (1); - fstat(infil, &stb); return (stb.st_mtime > atol(archdr.ar_date) ? 3 : 2); } +/* + * Search for a library with given name + * using the directory search array. + */ +libopen(name, oflags) + char *name; + int oflags; +{ + register char *p, *cp; + register int i; + static char buf[MAXPATHLEN+1]; + int fd = -1; + + if (*name == '\0') /* backwards compat */ + name = "a"; + for (i = 0; i < ndir && fd == -1; i++) { + p = buf; + for (cp = dirs[i]; *cp; *p++ = *cp++) + ; + *p++ = '/'; + for (cp = "lib"; *cp; *p++ = *cp++) + ; + for (cp = name; *cp; *p++ = *cp++) + ; + cp = ".a"; + while (*p++ = *cp++) + ; + fd = open(buf, oflags); + } + if (fd != -1) + filname = buf; + return (fd); +} + struct nlist ** lookup() { @@ -1677,6 +1945,7 @@ symreloc() error(n, s) char *s; { + if (errlev==0) printf("ld:"); if (filname) { @@ -1707,7 +1976,7 @@ off_t loc; if (filhdr.a_text&01 || filhdr.a_data&01) error(1, "text/data size odd"); if (filhdr.a_magic == NMAGIC || filhdr.a_magic == ZMAGIC) { - cdrel = -round(filhdr.a_text, PAGSIZ); + cdrel = -round(filhdr.a_text, pagesize); cbrel = cdrel - filhdr.a_data; } else if (filhdr.a_magic == OMAGIC) { cdrel = -filhdr.a_text; @@ -1742,7 +2011,7 @@ savestr(cp) saveleft = NSAVETAB; if (len > saveleft) saveleft = len; - savetab = (char *)malloc(saveleft); + savetab = malloc(saveleft); if (savetab == 0) error(1, "ran out of memory (savestr)"); } @@ -1753,12 +2022,15 @@ savestr(cp) return (cp); } -bopen(bp, off) - struct biobuf *bp; +bopen(bp, off, bufsize) + register struct biobuf *bp; { - bp->b_ptr = bp->b_buf; - bp->b_nleft = BUFSIZ - off % BUFSIZ; + bp->b_ptr = bp->b_buf = malloc(bufsize); + if (bp->b_ptr == (char *)0) + error(1, "ran out of memory (bopen)"); + bp->b_bufsize = bufsize; + bp->b_nleft = bufsize - (off % bufsize); bp->b_off = off; bp->b_link = biobufs; biobufs = bp; @@ -1783,16 +2055,16 @@ top: put = cnt; bp->b_nleft -= put; to = bp->b_ptr; - asm("movc3 r8,(r11),(r7)"); + bcopy(p, to, put); bp->b_ptr += put; p += put; cnt -= put; goto top; } - if (cnt >= BUFSIZ) { + if (cnt >= bp->b_bufsize) { if (bp->b_ptr != bp->b_buf) bflush1(bp); - put = cnt - cnt % BUFSIZ; + put = cnt - cnt % bp->b_bufsize; if (boffset != bp->b_off) lseek(biofd, bp->b_off, 0); if (write(biofd, p, put) != put) { @@ -1835,7 +2107,7 @@ bflush1(bp) bp->b_off += cnt; boffset = bp->b_off; bp->b_ptr = bp->b_buf; - bp->b_nleft = BUFSIZ; + bp->b_nleft = bp->b_bufsize; } bflushc(bp, c) @@ -1845,3 +2117,13 @@ bflushc(bp, c) bflush1(bp); bputc(c, bp); } + +bseek(bp, off) + register struct biobuf *bp; + register off_t off; +{ + bflush1(bp); + + bp->b_nleft = bp->b_bufsize - (off % bp->b_bufsize); + bp->b_off = off; +}