1: /*- 2: * Copyright (c) 1990 The Regents of the University of California. 3: * All rights reserved. 4: * 5: * This code is derived from software contributed to Berkeley by 6: * Hugh Smith at The University of Guelph. 7: * 8: * Redistribution and use in source and binary forms, with or without 9: * modification, are permitted provided that the following conditions 10: * are met: 11: * 1. Redistributions of source code must retain the above copyright 12: * notice, this list of conditions and the following disclaimer. 13: * 2. Redistributions in binary form must reproduce the above copyright 14: * notice, this list of conditions and the following disclaimer in the 15: * documentation and/or other materials provided with the distribution. 16: * 3. All advertising materials mentioning features or use of this software 17: * must display the following acknowledgement: 18: * This product includes software developed by the University of 19: * California, Berkeley and its contributors. 20: * 4. Neither the name of the University nor the names of its contributors 21: * may be used to endorse or promote products derived from this software 22: * without specific prior written permission. 23: * 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34: * SUCH DAMAGE. 35: */ 36: 37: #if !defined(lint) && defined(DOSCCS) 38: static char sccsid[] = "@(#)build.c 5.3.1 (Berkeley) 5/17/93"; 39: #endif 40: 41: #include <sys/types.h> 42: #include <sys/errno.h> 43: #include <sys/stat.h> 44: #include <fcntl.h> 45: #include <a.out.h> 46: #include <sys/dir.h> 47: #include <sys/file.h> 48: #include <ar.h> 49: #include <ranlib.h> 50: #include <stdio.h> 51: #include <archive.h> 52: 53: extern off_t lseek(); 54: extern CHDR chdr; /* converted header */ 55: extern char *archive; /* archive name */ 56: extern char *tname; /* temporary file "name" */ 57: 58: typedef struct _rlib { 59: struct _rlib *next; /* next structure */ 60: off_t pos; /* offset of defining archive file */ 61: char *sym; /* symbol */ 62: int symlen; /* strlen(sym) */ 63: } RLIB; 64: RLIB *rhead, **pnext; 65: 66: FILE *fp; 67: static void rexec(), symobj(); 68: void error(), badfmt(); 69: long symcnt; /* symbol count */ 70: long tsymlen; /* total string length */ 71: 72: build() 73: { 74: CF cf; 75: int afd, tfd; 76: off_t size; 77: 78: afd = open_archive(O_RDWR); 79: fp = fdopen(afd, "r+"); 80: tfd = tmp(); 81: 82: SETCF(afd, archive, tfd, tname, RPAD|WPAD); 83: 84: /* Read through the archive, creating list of symbols. */ 85: pnext = &rhead; 86: symcnt = tsymlen = 0; 87: while(get_arobj(afd)) { 88: if (!strcmp(chdr.name, RANLIBMAG)) { 89: skip_arobj(afd); 90: continue; 91: } 92: rexec(afd, tfd); 93: put_arobj(&cf, (struct stat *)NULL); 94: } 95: *pnext = NULL; 96: 97: /* Create the symbol table. */ 98: symobj(); 99: 100: /* Copy the saved objects into the archive. */ 101: size = lseek(tfd, (off_t)0, L_INCR); 102: (void)lseek(tfd, (off_t)0, L_SET); 103: SETCF(tfd, tname, afd, archive, RPAD|WPAD); 104: copy_ar(&cf, size); 105: (void)ftruncate(afd, lseek(afd, (off_t)0, L_INCR)); 106: (void)close(tfd); 107: 108: /* Set the time. */ 109: settime(afd); 110: close_archive(afd); 111: return(0); 112: } 113: 114: /* 115: * rexec 116: * Read the exec structure; ignore any files that don't look 117: * exactly right. 118: */ 119: static void 120: rexec(rfd, wfd) 121: int rfd; 122: int wfd; 123: { 124: register RLIB *rp; 125: RLIB **savnext; 126: long nsyms; 127: register int nr, symlen; 128: char sym[512]; /* XXX - more than enough (we hope) */ 129: struct exec ebuf; 130: struct nlist nl; 131: off_t r_off, w_off, sympos; 132: void *emalloc(); 133: 134: /* Get current offsets for original and tmp files. */ 135: r_off = lseek(rfd, (off_t)0, L_INCR); 136: w_off = lseek(wfd, (off_t)0, L_INCR); 137: 138: /* Read in exec structure. */ 139: nr = read(rfd, (char *)&ebuf, sizeof(struct exec)); 140: if (nr != sizeof(struct exec)) 141: goto bad1; 142: 143: /* Check magic number and symbol count. */ 144: if (N_BADMAG(ebuf) || ebuf.a_syms == 0) 145: goto bad1; 146: 147: /* First four bytes are the table size. */ 148: sympos = N_STROFF(ebuf) + r_off; 149: 150: /* Seek to symbol table. */ 151: if (fseek(fp, (off_t)N_SYMOFF(ebuf) + r_off, L_SET) == (off_t)-1) 152: goto bad1; 153: 154: /* Save starting point in symbol chain */ 155: savnext = pnext; 156: 157: /* For each symbol read the nlist entry and save it as necessary. */ 158: nsyms = ebuf.a_syms / sizeof(struct nlist); 159: while (nsyms--) { 160: if (!fread((char *)&nl, sizeof(struct nlist), 1, fp)) { 161: if (feof(fp)) 162: badfmt(); 163: error(archive); 164: } 165: 166: /* Ignore if no name or local. */ 167: if (!nl.n_un.n_strx || !(nl.n_type & N_EXT)) 168: continue; 169: 170: /* 171: * If the symbol is an undefined external and the n_value 172: * field is non-zero, keep it. 173: */ 174: if ((nl.n_type & N_TYPE) == N_UNDF && !nl.n_value) 175: continue; 176: 177: rp = (RLIB *)emalloc(sizeof(RLIB)); 178: rp->pos = sympos + nl.n_un.n_strx; 179: rp->next = NULL; 180: 181: /* Build in forward order for "ar -m" command. */ 182: *pnext = rp; 183: pnext = &rp->next; 184: ++symcnt; 185: } 186: for (rp = *savnext; rp; rp = rp->next) { 187: fseek(fp, rp->pos, L_SET); 188: symlen = sgets(sym, sizeof (sym), fp); 189: rp->sym = (char *)emalloc(symlen); 190: bcopy(sym, rp->sym, symlen); 191: rp->symlen = symlen; 192: rp->pos = w_off; 193: tsymlen += symlen; 194: } 195: bad1: (void)lseek(rfd, (off_t)r_off, L_SET); 196: } 197: 198: /* 199: * symobj -- 200: * Write the symbol table into the archive, computing offsets as 201: * writing. 202: */ 203: static void 204: symobj() 205: { 206: register RLIB *rp, *next; 207: struct ranlib rn; 208: char hb[sizeof(struct ar_hdr) + 1], pad; 209: long ransize, size, stroff; 210: gid_t getgid(); 211: uid_t getuid(); 212: 213: /* Rewind the archive, leaving the magic number. */ 214: if (fseek(fp, (off_t)SARMAG, L_SET) == (off_t)-1) 215: error(archive); 216: 217: /* Size of the ranlib archive file, pad if necessary. */ 218: ransize = sizeof(long) + 219: symcnt * sizeof(struct ranlib) + sizeof(long) + tsymlen; 220: if (ransize & 01) { 221: ++ransize; 222: pad = '\n'; 223: } else 224: pad = '\0'; 225: 226: /* Put out the ranlib archive file header. */ 227: (void)sprintf(hb, HDR2, RANLIBMAG, 0L, getuid(), getgid(), 228: 0666 & ~umask(0), ransize, ARFMAG); 229: if (!fwrite(hb, sizeof(struct ar_hdr), 1, fp)) 230: error(tname); 231: 232: /* First long is the size of the ranlib structure section. */ 233: size = symcnt * sizeof(struct ranlib); 234: if (!fwrite((char *)&size, sizeof(size), 1, fp)) 235: error(tname); 236: 237: /* Offset of the first archive file. */ 238: size = SARMAG + sizeof(struct ar_hdr) + ransize; 239: 240: /* 241: * Write out the ranlib structures. The offset into the string 242: * table is cumulative, the offset into the archive is the value 243: * set in rexec() plus the offset to the first archive file. 244: */ 245: for (rp = rhead, stroff = 0; rp; rp = rp->next) { 246: rn.ran_un.ran_strx = stroff; 247: stroff += rp->symlen; 248: rn.ran_off = size + rp->pos; 249: if (!fwrite((char *)&rn, sizeof(struct ranlib), 1, fp)) 250: error(archive); 251: } 252: 253: /* Second long is the size of the string table. */ 254: if (!fwrite((char *)&tsymlen, sizeof(tsymlen), 1, fp)) 255: error(tname); 256: 257: /* Write out the string table. */ 258: for (rp = rhead; rp; ) { 259: if (!fwrite(rp->sym, rp->symlen, 1, fp)) 260: error(tname); 261: (void)free(rp->sym); 262: next = rp->next; 263: free(rp); 264: rp = next; 265: } 266: 267: if (pad && !fwrite(&pad, sizeof(pad), 1, fp)) 268: error(tname); 269: 270: (void)fflush(fp); 271: } 272: 273: sgets(buf, n, fp) 274: char *buf; 275: int n; 276: register FILE *fp; 277: { 278: register int i, c; 279: 280: n--; /* room for null */ 281: for (i = 0; i < n; i++) 282: { 283: c = getc(fp); 284: if (c == EOF || c == 0) 285: break; 286: *buf++ = c; 287: } 288: *buf = '\0'; 289: return(i + 1); 290: }