146012Sbostic /*- 246012Sbostic * Copyright (c) 1990 The Regents of the University of California. 346012Sbostic * All rights reserved. 446012Sbostic * 546012Sbostic * This code is derived from software contributed to Berkeley by 646012Sbostic * Hugh Smith at The University of Guelph. 746012Sbostic * 846012Sbostic * %sccs.include.redist.c% 946012Sbostic */ 1046012Sbostic 1146012Sbostic #ifndef lint 12*47241Sbostic static char sccsid[] = "@(#)build.c 5.3 (Berkeley) 03/12/91"; 1346012Sbostic #endif /* not lint */ 1446012Sbostic 1546012Sbostic #include <sys/types.h> 1646012Sbostic #include <sys/errno.h> 1746012Sbostic #include <sys/stat.h> 1846012Sbostic #include <fcntl.h> 1946012Sbostic #include <a.out.h> 2046012Sbostic #include <dirent.h> 2146012Sbostic #include <unistd.h> 2246012Sbostic #include <ar.h> 2346012Sbostic #include <ranlib.h> 2446012Sbostic #include <stdio.h> 2546012Sbostic #include <archive.h> 2646012Sbostic 2746012Sbostic extern CHDR chdr; /* converted header */ 2846012Sbostic extern char *archive; /* archive name */ 2946012Sbostic extern char *tname; /* temporary file "name" */ 3046012Sbostic 3146012Sbostic typedef struct _rlib { 3246012Sbostic struct _rlib *next; /* next structure */ 3346012Sbostic off_t pos; /* offset of defining archive file */ 3446012Sbostic char *sym; /* symbol */ 3546012Sbostic int symlen; /* strlen(sym) */ 3646012Sbostic } RLIB; 3746012Sbostic RLIB *rhead, **pnext; 3846012Sbostic 3946012Sbostic FILE *fp; 4046698Sbostic static void rexec(), symobj(); 4146012Sbostic 4246012Sbostic build() 4346012Sbostic { 4446012Sbostic CF cf; 4546012Sbostic int afd, tfd; 4646012Sbostic off_t size; 4746012Sbostic 4846012Sbostic afd = open_archive(O_RDWR); 4946012Sbostic fp = fdopen(afd, "r+"); 5046012Sbostic tfd = tmp(); 5146012Sbostic 5246012Sbostic SETCF(afd, archive, tfd, tname, RPAD|WPAD); 5346012Sbostic 5446012Sbostic /* Read through the archive, creating list of symbols. */ 5546012Sbostic pnext = &rhead; 56*47241Sbostic while(get_arobj(afd)) { 5746012Sbostic if (!strcmp(chdr.name, RANLIBMAG)) { 58*47241Sbostic skip_arobj(afd); 5946012Sbostic continue; 6046012Sbostic } 6146012Sbostic rexec(afd, tfd); 62*47241Sbostic put_arobj(&cf, (struct stat *)NULL); 6346012Sbostic } 6446012Sbostic *pnext = NULL; 6546012Sbostic 6646012Sbostic /* Create the symbol table. */ 6746012Sbostic symobj(); 6846012Sbostic 6946012Sbostic /* Copy the saved objects into the archive. */ 7046012Sbostic size = lseek(tfd, (off_t)0, SEEK_CUR); 7146012Sbostic (void)lseek(tfd, (off_t)0, SEEK_SET); 7246012Sbostic SETCF(tfd, tname, afd, archive, RPAD|WPAD); 73*47241Sbostic copy_ar(&cf, size); 7446012Sbostic (void)ftruncate(afd, lseek(afd, (off_t)0, SEEK_CUR)); 7546012Sbostic (void)close(tfd); 7646012Sbostic 7746012Sbostic /* Set the time. */ 7846012Sbostic settime(afd); 7946012Sbostic close_archive(afd); 8046012Sbostic return(0); 8146012Sbostic } 8246012Sbostic 8346012Sbostic long symcnt; /* symbol count */ 8446012Sbostic long tsymlen; /* total string length */ 8546012Sbostic 8646012Sbostic /* 8746012Sbostic * rexec 8846012Sbostic * Read the exec structure; ignore any files that don't look 8946012Sbostic * exactly right. 9046012Sbostic */ 9146698Sbostic static void 9246012Sbostic rexec(rfd, wfd) 9346012Sbostic register int rfd; 9446012Sbostic int wfd; 9546012Sbostic { 9646012Sbostic register RLIB *rp; 9746012Sbostic register long nsyms; 9846012Sbostic register int nr, symlen; 9946012Sbostic register char *strtab, *sym; 10046012Sbostic struct exec ebuf; 10146012Sbostic struct nlist nl; 10246012Sbostic off_t r_off, w_off; 10346012Sbostic long strsize; 10446012Sbostic void *emalloc(); 10546012Sbostic 10646012Sbostic /* Get current offsets for original and tmp files. */ 10746012Sbostic r_off = lseek(rfd, (off_t)0, SEEK_CUR); 10846012Sbostic w_off = lseek(wfd, (off_t)0, SEEK_CUR); 10946012Sbostic 11046012Sbostic /* Read in exec structure. */ 11146012Sbostic nr = read(rfd, (char *)&ebuf, sizeof(struct exec)); 11246012Sbostic if (nr != sizeof(struct exec)) 11346012Sbostic goto badread; 11446012Sbostic 11546012Sbostic /* Check magic number and symbol count. */ 11646012Sbostic if (N_BADMAG(ebuf) || ebuf.a_syms == 0) 11746012Sbostic goto bad1; 11846012Sbostic 11946012Sbostic /* Seek to string table. */ 12046012Sbostic if (lseek(rfd, N_STROFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) 12146012Sbostic error(archive); 12246012Sbostic 12346012Sbostic /* Read in size of the string table. */ 12446012Sbostic nr = read(rfd, (char *)&strsize, sizeof(strsize)); 12546012Sbostic if (nr != sizeof(strsize)) 12646012Sbostic goto badread; 12746012Sbostic 12846012Sbostic /* Read in the string table. */ 12946012Sbostic strsize -= sizeof(strsize); 13046012Sbostic strtab = (char *)emalloc(strsize); 13146012Sbostic nr = read(rfd, strtab, strsize); 13246012Sbostic if (nr != strsize) { 13346012Sbostic badread: if (nr < 0) 13446012Sbostic error(archive); 13546012Sbostic goto bad2; 13646012Sbostic } 13746012Sbostic 13846012Sbostic /* Seek to symbol table. */ 13946012Sbostic if (fseek(fp, N_SYMOFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) 14046012Sbostic goto bad2; 14146012Sbostic 14246012Sbostic /* For each symbol read the nlist entry and save it as necessary. */ 14346012Sbostic nsyms = ebuf.a_syms / sizeof(struct nlist); 14446012Sbostic while (nsyms--) { 14546012Sbostic if (!fread((char *)&nl, sizeof(struct nlist), 1, fp)) { 14646012Sbostic if (feof(fp)) 14746012Sbostic badfmt(); 14846012Sbostic error(archive); 14946012Sbostic } 15046012Sbostic 15146012Sbostic /* Ignore if no name or local. */ 15246012Sbostic if (!nl.n_un.n_strx || !(nl.n_type & N_EXT)) 15346012Sbostic continue; 15446012Sbostic 15546012Sbostic /* 15646012Sbostic * If the symbol is an undefined external and the n_value 15746012Sbostic * field is non-zero, keep it. 15846012Sbostic */ 15946012Sbostic if ((nl.n_type & N_TYPE) == N_UNDF && !nl.n_value) 16046012Sbostic continue; 16146012Sbostic 16246012Sbostic /* First four bytes are the table size. */ 16346012Sbostic sym = strtab + nl.n_un.n_strx - sizeof(long); 16446012Sbostic symlen = strlen(sym) + 1; 16546012Sbostic 16646012Sbostic rp = (RLIB *)emalloc(sizeof(RLIB)); 16746012Sbostic rp->sym = (char *)emalloc(symlen); 16846012Sbostic bcopy(sym, rp->sym, symlen); 16946012Sbostic rp->symlen = symlen; 17046012Sbostic rp->pos = w_off; 17146012Sbostic 17246012Sbostic /* Build in forward order for "ar -m" command. */ 17346012Sbostic *pnext = rp; 17446012Sbostic pnext = &rp->next; 17546012Sbostic 17646012Sbostic ++symcnt; 17746012Sbostic tsymlen += symlen; 17846012Sbostic } 17946012Sbostic 18046012Sbostic bad2: free(strtab); 18146012Sbostic bad1: (void)lseek(rfd, (off_t)r_off, SEEK_SET); 18246012Sbostic } 18346012Sbostic 18446012Sbostic /* 18546012Sbostic * symobj -- 18646012Sbostic * Write the symbol table into the archive, computing offsets as 18746012Sbostic * writing. 18846012Sbostic */ 18946698Sbostic static void 19046012Sbostic symobj() 19146012Sbostic { 19246012Sbostic register RLIB *rp; 19346012Sbostic struct ranlib rn; 19446012Sbostic char hb[sizeof(struct ar_hdr) + 1], pad; 19546012Sbostic long ransize, size, stroff; 19646012Sbostic gid_t getgid(); 19746012Sbostic uid_t getuid(); 19846012Sbostic 19946012Sbostic /* Rewind the archive, leaving the magic number. */ 20046012Sbostic if (fseek(fp, (off_t)SARMAG, SEEK_SET) == (off_t)-1) 20146012Sbostic error(archive); 20246012Sbostic 20346012Sbostic /* Size of the ranlib archive file, pad if necessary. */ 20446012Sbostic ransize = sizeof(long) + 20546012Sbostic symcnt * sizeof(struct ranlib) + sizeof(long) + tsymlen; 20646012Sbostic if (ransize & 01) { 20746012Sbostic ++ransize; 20846012Sbostic pad = '\n'; 20946012Sbostic } else 21046012Sbostic pad = '\0'; 21146012Sbostic 21246012Sbostic /* Put out the ranlib archive file header. */ 21346012Sbostic #define DEFMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 21446012Sbostic (void)sprintf(hb, HDR2, RANLIBMAG, 0L, getuid(), getgid(), 21546698Sbostic DEFMODE & ~umask(0), ransize, ARFMAG); 21646012Sbostic if (!fwrite(hb, sizeof(struct ar_hdr), 1, fp)) 21746012Sbostic error(tname); 21846012Sbostic 21946012Sbostic /* First long is the size of the ranlib structure section. */ 22046012Sbostic size = symcnt * sizeof(struct ranlib); 22146012Sbostic if (!fwrite((char *)&size, sizeof(size), 1, fp)) 22246012Sbostic error(tname); 22346012Sbostic 22446012Sbostic /* Offset of the first archive file. */ 22546012Sbostic size = SARMAG + sizeof(struct ar_hdr) + ransize; 22646012Sbostic 22746012Sbostic /* 22846012Sbostic * Write out the ranlib structures. The offset into the string 22946012Sbostic * table is cumulative, the offset into the archive is the value 23046012Sbostic * set in rexec() plus the offset to the first archive file. 23146012Sbostic */ 23246012Sbostic for (rp = rhead, stroff = 0; rp; rp = rp->next) { 23346012Sbostic rn.ran_un.ran_strx = stroff; 23446012Sbostic stroff += rp->symlen; 23546012Sbostic rn.ran_off = size + rp->pos; 23646012Sbostic if (!fwrite((char *)&rn, sizeof(struct ranlib), 1, fp)) 23746012Sbostic error(archive); 23846012Sbostic } 23946012Sbostic 24046012Sbostic /* Second long is the size of the string table. */ 24146012Sbostic if (!fwrite((char *)&tsymlen, sizeof(tsymlen), 1, fp)) 24246012Sbostic error(tname); 24346012Sbostic 24446012Sbostic /* Write out the string table. */ 24546012Sbostic for (rp = rhead; rp; rp = rp->next) 24646012Sbostic if (!fwrite(rp->sym, rp->symlen, 1, fp)) 24746012Sbostic error(tname); 24846012Sbostic 24946012Sbostic if (pad && !fwrite(&pad, sizeof(pad), 1, fp)) 25046012Sbostic error(tname); 25146012Sbostic 25246012Sbostic (void)fflush(fp); 25346012Sbostic } 254