From d9256bab0fc9e43ed9a5b83be858c294ef2ed16b Mon Sep 17 00:00:00 2001 From: Keith Bostic Date: Sat, 19 Jan 1991 02:45:35 -0800 Subject: [PATCH] date and time created 91/01/18 18:45:35 by bostic SCCS-vsn: usr.bin/ranlib/build.c 5.1 --- usr/src/usr.bin/ranlib/build.c | 253 +++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) create mode 100644 usr/src/usr.bin/ranlib/build.c diff --git a/usr/src/usr.bin/ranlib/build.c b/usr/src/usr.bin/ranlib/build.c new file mode 100644 index 0000000000..790aedcecc --- /dev/null +++ b/usr/src/usr.bin/ranlib/build.c @@ -0,0 +1,253 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Hugh Smith at The University of Guelph. + * + * %sccs.include.redist.c% + */ + +#ifndef lint +static char sccsid[] = "@(#)build.c 5.1 (Berkeley) %G%"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern CHDR chdr; /* converted header */ +extern char *archive; /* archive name */ +extern char *tname; /* temporary file "name" */ + +typedef struct _rlib { + struct _rlib *next; /* next structure */ + off_t pos; /* offset of defining archive file */ + char *sym; /* symbol */ + int symlen; /* strlen(sym) */ +} RLIB; +RLIB *rhead, **pnext; + +FILE *fp; + +build() +{ + CF cf; + int afd, tfd; + off_t size; + + afd = open_archive(O_RDWR); + fp = fdopen(afd, "r+"); + tfd = tmp(); + + SETCF(afd, archive, tfd, tname, RPAD|WPAD); + + /* Read through the archive, creating list of symbols. */ + pnext = &rhead; + while(get_header(afd)) { + if (!strcmp(chdr.name, RANLIBMAG)) { + SKIP(afd, chdr.size, archive); + continue; + } + rexec(afd, tfd); + put_header(&cf, (struct stat *)NULL); + copyfile(&cf, chdr.size); + } + *pnext = NULL; + + /* Create the symbol table. */ + symobj(); + + /* Copy the saved objects into the archive. */ + size = lseek(tfd, (off_t)0, SEEK_CUR); + (void)lseek(tfd, (off_t)0, SEEK_SET); + SETCF(tfd, tname, afd, archive, RPAD|WPAD); + copyfile(&cf, size); + (void)ftruncate(afd, lseek(afd, (off_t)0, SEEK_CUR)); + (void)close(tfd); + + /* Set the time. */ + settime(afd); + close_archive(afd); + return(0); +} + +long symcnt; /* symbol count */ +long tsymlen; /* total string length */ + +/* + * rexec + * Read the exec structure; ignore any files that don't look + * exactly right. + */ +static +rexec(rfd, wfd) + register int rfd; + int wfd; +{ + register RLIB *rp; + register long nsyms; + register int nr, symlen; + register char *strtab, *sym; + struct exec ebuf; + struct nlist nl; + off_t r_off, w_off; + long strsize; + void *emalloc(); + + /* Get current offsets for original and tmp files. */ + r_off = lseek(rfd, (off_t)0, SEEK_CUR); + w_off = lseek(wfd, (off_t)0, SEEK_CUR); + + /* Read in exec structure. */ + nr = read(rfd, (char *)&ebuf, sizeof(struct exec)); + if (nr != sizeof(struct exec)) + goto badread; + + /* Check magic number and symbol count. */ + if (N_BADMAG(ebuf) || ebuf.a_syms == 0) + goto bad1; + + /* Seek to string table. */ + if (lseek(rfd, N_STROFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) + error(archive); + + /* Read in size of the string table. */ + nr = read(rfd, (char *)&strsize, sizeof(strsize)); + if (nr != sizeof(strsize)) + goto badread; + + /* Read in the string table. */ + strsize -= sizeof(strsize); + strtab = (char *)emalloc(strsize); + nr = read(rfd, strtab, strsize); + if (nr != strsize) { +badread: if (nr < 0) + error(archive); + goto bad2; + } + + /* Seek to symbol table. */ + if (fseek(fp, N_SYMOFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) + goto bad2; + + /* For each symbol read the nlist entry and save it as necessary. */ + nsyms = ebuf.a_syms / sizeof(struct nlist); + while (nsyms--) { + if (!fread((char *)&nl, sizeof(struct nlist), 1, fp)) { + if (feof(fp)) + badfmt(); + error(archive); + } + + /* Ignore if no name or local. */ + if (!nl.n_un.n_strx || !(nl.n_type & N_EXT)) + continue; + + /* + * If the symbol is an undefined external and the n_value + * field is non-zero, keep it. + */ + if ((nl.n_type & N_TYPE) == N_UNDF && !nl.n_value) + continue; + + /* First four bytes are the table size. */ + sym = strtab + nl.n_un.n_strx - sizeof(long); + symlen = strlen(sym) + 1; + + rp = (RLIB *)emalloc(sizeof(RLIB)); + rp->sym = (char *)emalloc(symlen); + bcopy(sym, rp->sym, symlen); + rp->symlen = symlen; + rp->pos = w_off; + + /* Build in forward order for "ar -m" command. */ + *pnext = rp; + pnext = &rp->next; + + ++symcnt; + tsymlen += symlen; + } + +bad2: free(strtab); +bad1: (void)lseek(rfd, (off_t)r_off, SEEK_SET); +} + +/* + * symobj -- + * Write the symbol table into the archive, computing offsets as + * writing. + */ +static +symobj() +{ + register RLIB *rp; + struct ranlib rn; + char hb[sizeof(struct ar_hdr) + 1], pad; + long ransize, size, stroff; + gid_t getgid(); + uid_t getuid(); + + /* Rewind the archive, leaving the magic number. */ + if (fseek(fp, (off_t)SARMAG, SEEK_SET) == (off_t)-1) + error(archive); + + /* Size of the ranlib archive file, pad if necessary. */ + ransize = sizeof(long) + + symcnt * sizeof(struct ranlib) + sizeof(long) + tsymlen; + if (ransize & 01) { + ++ransize; + pad = '\n'; + } else + pad = '\0'; + + /* Put out the ranlib archive file header. */ +#define DEFMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) + (void)sprintf(hb, HDR2, RANLIBMAG, 0L, getuid(), getgid(), + DEFMODE & ~umask(), ransize, ARFMAG); + if (!fwrite(hb, sizeof(struct ar_hdr), 1, fp)) + error(tname); + + /* First long is the size of the ranlib structure section. */ + size = symcnt * sizeof(struct ranlib); + if (!fwrite((char *)&size, sizeof(size), 1, fp)) + error(tname); + + /* Offset of the first archive file. */ + size = SARMAG + sizeof(struct ar_hdr) + ransize; + + /* + * Write out the ranlib structures. The offset into the string + * table is cumulative, the offset into the archive is the value + * set in rexec() plus the offset to the first archive file. + */ + for (rp = rhead, stroff = 0; rp; rp = rp->next) { + rn.ran_un.ran_strx = stroff; + stroff += rp->symlen; + rn.ran_off = size + rp->pos; + if (!fwrite((char *)&rn, sizeof(struct ranlib), 1, fp)) + error(archive); + } + + /* Second long is the size of the string table. */ + if (!fwrite((char *)&tsymlen, sizeof(tsymlen), 1, fp)) + error(tname); + + /* Write out the string table. */ + for (rp = rhead; rp; rp = rp->next) + if (!fwrite(rp->sym, rp->symlen, 1, fp)) + error(tname); + + if (pad && !fwrite(&pad, sizeof(pad), 1, fp)) + error(tname); + + (void)fflush(fp); +} -- 2.20.1