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*46698Sbostic static char sccsid[] = "@(#)build.c 5.2 (Berkeley) 02/26/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; 40*46698Sbostic 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; 5646012Sbostic while(get_header(afd)) { 5746012Sbostic if (!strcmp(chdr.name, RANLIBMAG)) { 5846012Sbostic SKIP(afd, chdr.size, archive); 5946012Sbostic continue; 6046012Sbostic } 6146012Sbostic rexec(afd, tfd); 6246012Sbostic put_header(&cf, (struct stat *)NULL); 6346012Sbostic copyfile(&cf, chdr.size); 6446012Sbostic } 6546012Sbostic *pnext = NULL; 6646012Sbostic 6746012Sbostic /* Create the symbol table. */ 6846012Sbostic symobj(); 6946012Sbostic 7046012Sbostic /* Copy the saved objects into the archive. */ 7146012Sbostic size = lseek(tfd, (off_t)0, SEEK_CUR); 7246012Sbostic (void)lseek(tfd, (off_t)0, SEEK_SET); 7346012Sbostic SETCF(tfd, tname, afd, archive, RPAD|WPAD); 7446012Sbostic copyfile(&cf, size); 7546012Sbostic (void)ftruncate(afd, lseek(afd, (off_t)0, SEEK_CUR)); 7646012Sbostic (void)close(tfd); 7746012Sbostic 7846012Sbostic /* Set the time. */ 7946012Sbostic settime(afd); 8046012Sbostic close_archive(afd); 8146012Sbostic return(0); 8246012Sbostic } 8346012Sbostic 8446012Sbostic long symcnt; /* symbol count */ 8546012Sbostic long tsymlen; /* total string length */ 8646012Sbostic 8746012Sbostic /* 8846012Sbostic * rexec 8946012Sbostic * Read the exec structure; ignore any files that don't look 9046012Sbostic * exactly right. 9146012Sbostic */ 92*46698Sbostic static void 9346012Sbostic rexec(rfd, wfd) 9446012Sbostic register int rfd; 9546012Sbostic int wfd; 9646012Sbostic { 9746012Sbostic register RLIB *rp; 9846012Sbostic register long nsyms; 9946012Sbostic register int nr, symlen; 10046012Sbostic register char *strtab, *sym; 10146012Sbostic struct exec ebuf; 10246012Sbostic struct nlist nl; 10346012Sbostic off_t r_off, w_off; 10446012Sbostic long strsize; 10546012Sbostic void *emalloc(); 10646012Sbostic 10746012Sbostic /* Get current offsets for original and tmp files. */ 10846012Sbostic r_off = lseek(rfd, (off_t)0, SEEK_CUR); 10946012Sbostic w_off = lseek(wfd, (off_t)0, SEEK_CUR); 11046012Sbostic 11146012Sbostic /* Read in exec structure. */ 11246012Sbostic nr = read(rfd, (char *)&ebuf, sizeof(struct exec)); 11346012Sbostic if (nr != sizeof(struct exec)) 11446012Sbostic goto badread; 11546012Sbostic 11646012Sbostic /* Check magic number and symbol count. */ 11746012Sbostic if (N_BADMAG(ebuf) || ebuf.a_syms == 0) 11846012Sbostic goto bad1; 11946012Sbostic 12046012Sbostic /* Seek to string table. */ 12146012Sbostic if (lseek(rfd, N_STROFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) 12246012Sbostic error(archive); 12346012Sbostic 12446012Sbostic /* Read in size of the string table. */ 12546012Sbostic nr = read(rfd, (char *)&strsize, sizeof(strsize)); 12646012Sbostic if (nr != sizeof(strsize)) 12746012Sbostic goto badread; 12846012Sbostic 12946012Sbostic /* Read in the string table. */ 13046012Sbostic strsize -= sizeof(strsize); 13146012Sbostic strtab = (char *)emalloc(strsize); 13246012Sbostic nr = read(rfd, strtab, strsize); 13346012Sbostic if (nr != strsize) { 13446012Sbostic badread: if (nr < 0) 13546012Sbostic error(archive); 13646012Sbostic goto bad2; 13746012Sbostic } 13846012Sbostic 13946012Sbostic /* Seek to symbol table. */ 14046012Sbostic if (fseek(fp, N_SYMOFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) 14146012Sbostic goto bad2; 14246012Sbostic 14346012Sbostic /* For each symbol read the nlist entry and save it as necessary. */ 14446012Sbostic nsyms = ebuf.a_syms / sizeof(struct nlist); 14546012Sbostic while (nsyms--) { 14646012Sbostic if (!fread((char *)&nl, sizeof(struct nlist), 1, fp)) { 14746012Sbostic if (feof(fp)) 14846012Sbostic badfmt(); 14946012Sbostic error(archive); 15046012Sbostic } 15146012Sbostic 15246012Sbostic /* Ignore if no name or local. */ 15346012Sbostic if (!nl.n_un.n_strx || !(nl.n_type & N_EXT)) 15446012Sbostic continue; 15546012Sbostic 15646012Sbostic /* 15746012Sbostic * If the symbol is an undefined external and the n_value 15846012Sbostic * field is non-zero, keep it. 15946012Sbostic */ 16046012Sbostic if ((nl.n_type & N_TYPE) == N_UNDF && !nl.n_value) 16146012Sbostic continue; 16246012Sbostic 16346012Sbostic /* First four bytes are the table size. */ 16446012Sbostic sym = strtab + nl.n_un.n_strx - sizeof(long); 16546012Sbostic symlen = strlen(sym) + 1; 16646012Sbostic 16746012Sbostic rp = (RLIB *)emalloc(sizeof(RLIB)); 16846012Sbostic rp->sym = (char *)emalloc(symlen); 16946012Sbostic bcopy(sym, rp->sym, symlen); 17046012Sbostic rp->symlen = symlen; 17146012Sbostic rp->pos = w_off; 17246012Sbostic 17346012Sbostic /* Build in forward order for "ar -m" command. */ 17446012Sbostic *pnext = rp; 17546012Sbostic pnext = &rp->next; 17646012Sbostic 17746012Sbostic ++symcnt; 17846012Sbostic tsymlen += symlen; 17946012Sbostic } 18046012Sbostic 18146012Sbostic bad2: free(strtab); 18246012Sbostic bad1: (void)lseek(rfd, (off_t)r_off, SEEK_SET); 18346012Sbostic } 18446012Sbostic 18546012Sbostic /* 18646012Sbostic * symobj -- 18746012Sbostic * Write the symbol table into the archive, computing offsets as 18846012Sbostic * writing. 18946012Sbostic */ 190*46698Sbostic static void 19146012Sbostic symobj() 19246012Sbostic { 19346012Sbostic register RLIB *rp; 19446012Sbostic struct ranlib rn; 19546012Sbostic char hb[sizeof(struct ar_hdr) + 1], pad; 19646012Sbostic long ransize, size, stroff; 19746012Sbostic gid_t getgid(); 19846012Sbostic uid_t getuid(); 19946012Sbostic 20046012Sbostic /* Rewind the archive, leaving the magic number. */ 20146012Sbostic if (fseek(fp, (off_t)SARMAG, SEEK_SET) == (off_t)-1) 20246012Sbostic error(archive); 20346012Sbostic 20446012Sbostic /* Size of the ranlib archive file, pad if necessary. */ 20546012Sbostic ransize = sizeof(long) + 20646012Sbostic symcnt * sizeof(struct ranlib) + sizeof(long) + tsymlen; 20746012Sbostic if (ransize & 01) { 20846012Sbostic ++ransize; 20946012Sbostic pad = '\n'; 21046012Sbostic } else 21146012Sbostic pad = '\0'; 21246012Sbostic 21346012Sbostic /* Put out the ranlib archive file header. */ 21446012Sbostic #define DEFMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 21546012Sbostic (void)sprintf(hb, HDR2, RANLIBMAG, 0L, getuid(), getgid(), 216*46698Sbostic DEFMODE & ~umask(0), ransize, ARFMAG); 21746012Sbostic if (!fwrite(hb, sizeof(struct ar_hdr), 1, fp)) 21846012Sbostic error(tname); 21946012Sbostic 22046012Sbostic /* First long is the size of the ranlib structure section. */ 22146012Sbostic size = symcnt * sizeof(struct ranlib); 22246012Sbostic if (!fwrite((char *)&size, sizeof(size), 1, fp)) 22346012Sbostic error(tname); 22446012Sbostic 22546012Sbostic /* Offset of the first archive file. */ 22646012Sbostic size = SARMAG + sizeof(struct ar_hdr) + ransize; 22746012Sbostic 22846012Sbostic /* 22946012Sbostic * Write out the ranlib structures. The offset into the string 23046012Sbostic * table is cumulative, the offset into the archive is the value 23146012Sbostic * set in rexec() plus the offset to the first archive file. 23246012Sbostic */ 23346012Sbostic for (rp = rhead, stroff = 0; rp; rp = rp->next) { 23446012Sbostic rn.ran_un.ran_strx = stroff; 23546012Sbostic stroff += rp->symlen; 23646012Sbostic rn.ran_off = size + rp->pos; 23746012Sbostic if (!fwrite((char *)&rn, sizeof(struct ranlib), 1, fp)) 23846012Sbostic error(archive); 23946012Sbostic } 24046012Sbostic 24146012Sbostic /* Second long is the size of the string table. */ 24246012Sbostic if (!fwrite((char *)&tsymlen, sizeof(tsymlen), 1, fp)) 24346012Sbostic error(tname); 24446012Sbostic 24546012Sbostic /* Write out the string table. */ 24646012Sbostic for (rp = rhead; rp; rp = rp->next) 24746012Sbostic if (!fwrite(rp->sym, rp->symlen, 1, fp)) 24846012Sbostic error(tname); 24946012Sbostic 25046012Sbostic if (pad && !fwrite(&pad, sizeof(pad), 1, fp)) 25146012Sbostic error(tname); 25246012Sbostic 25346012Sbostic (void)fflush(fp); 25446012Sbostic } 255