1*46012Sbostic /*- 2*46012Sbostic * Copyright (c) 1990 The Regents of the University of California. 3*46012Sbostic * All rights reserved. 4*46012Sbostic * 5*46012Sbostic * This code is derived from software contributed to Berkeley by 6*46012Sbostic * Hugh Smith at The University of Guelph. 7*46012Sbostic * 8*46012Sbostic * %sccs.include.redist.c% 9*46012Sbostic */ 10*46012Sbostic 11*46012Sbostic #ifndef lint 12*46012Sbostic static char sccsid[] = "@(#)build.c 5.1 (Berkeley) 01/18/91"; 13*46012Sbostic #endif /* not lint */ 14*46012Sbostic 15*46012Sbostic #include <sys/types.h> 16*46012Sbostic #include <sys/errno.h> 17*46012Sbostic #include <sys/stat.h> 18*46012Sbostic #include <fcntl.h> 19*46012Sbostic #include <a.out.h> 20*46012Sbostic #include <dirent.h> 21*46012Sbostic #include <unistd.h> 22*46012Sbostic #include <ar.h> 23*46012Sbostic #include <ranlib.h> 24*46012Sbostic #include <stdio.h> 25*46012Sbostic #include <archive.h> 26*46012Sbostic 27*46012Sbostic extern CHDR chdr; /* converted header */ 28*46012Sbostic extern char *archive; /* archive name */ 29*46012Sbostic extern char *tname; /* temporary file "name" */ 30*46012Sbostic 31*46012Sbostic typedef struct _rlib { 32*46012Sbostic struct _rlib *next; /* next structure */ 33*46012Sbostic off_t pos; /* offset of defining archive file */ 34*46012Sbostic char *sym; /* symbol */ 35*46012Sbostic int symlen; /* strlen(sym) */ 36*46012Sbostic } RLIB; 37*46012Sbostic RLIB *rhead, **pnext; 38*46012Sbostic 39*46012Sbostic FILE *fp; 40*46012Sbostic 41*46012Sbostic build() 42*46012Sbostic { 43*46012Sbostic CF cf; 44*46012Sbostic int afd, tfd; 45*46012Sbostic off_t size; 46*46012Sbostic 47*46012Sbostic afd = open_archive(O_RDWR); 48*46012Sbostic fp = fdopen(afd, "r+"); 49*46012Sbostic tfd = tmp(); 50*46012Sbostic 51*46012Sbostic SETCF(afd, archive, tfd, tname, RPAD|WPAD); 52*46012Sbostic 53*46012Sbostic /* Read through the archive, creating list of symbols. */ 54*46012Sbostic pnext = &rhead; 55*46012Sbostic while(get_header(afd)) { 56*46012Sbostic if (!strcmp(chdr.name, RANLIBMAG)) { 57*46012Sbostic SKIP(afd, chdr.size, archive); 58*46012Sbostic continue; 59*46012Sbostic } 60*46012Sbostic rexec(afd, tfd); 61*46012Sbostic put_header(&cf, (struct stat *)NULL); 62*46012Sbostic copyfile(&cf, chdr.size); 63*46012Sbostic } 64*46012Sbostic *pnext = NULL; 65*46012Sbostic 66*46012Sbostic /* Create the symbol table. */ 67*46012Sbostic symobj(); 68*46012Sbostic 69*46012Sbostic /* Copy the saved objects into the archive. */ 70*46012Sbostic size = lseek(tfd, (off_t)0, SEEK_CUR); 71*46012Sbostic (void)lseek(tfd, (off_t)0, SEEK_SET); 72*46012Sbostic SETCF(tfd, tname, afd, archive, RPAD|WPAD); 73*46012Sbostic copyfile(&cf, size); 74*46012Sbostic (void)ftruncate(afd, lseek(afd, (off_t)0, SEEK_CUR)); 75*46012Sbostic (void)close(tfd); 76*46012Sbostic 77*46012Sbostic /* Set the time. */ 78*46012Sbostic settime(afd); 79*46012Sbostic close_archive(afd); 80*46012Sbostic return(0); 81*46012Sbostic } 82*46012Sbostic 83*46012Sbostic long symcnt; /* symbol count */ 84*46012Sbostic long tsymlen; /* total string length */ 85*46012Sbostic 86*46012Sbostic /* 87*46012Sbostic * rexec 88*46012Sbostic * Read the exec structure; ignore any files that don't look 89*46012Sbostic * exactly right. 90*46012Sbostic */ 91*46012Sbostic static 92*46012Sbostic rexec(rfd, wfd) 93*46012Sbostic register int rfd; 94*46012Sbostic int wfd; 95*46012Sbostic { 96*46012Sbostic register RLIB *rp; 97*46012Sbostic register long nsyms; 98*46012Sbostic register int nr, symlen; 99*46012Sbostic register char *strtab, *sym; 100*46012Sbostic struct exec ebuf; 101*46012Sbostic struct nlist nl; 102*46012Sbostic off_t r_off, w_off; 103*46012Sbostic long strsize; 104*46012Sbostic void *emalloc(); 105*46012Sbostic 106*46012Sbostic /* Get current offsets for original and tmp files. */ 107*46012Sbostic r_off = lseek(rfd, (off_t)0, SEEK_CUR); 108*46012Sbostic w_off = lseek(wfd, (off_t)0, SEEK_CUR); 109*46012Sbostic 110*46012Sbostic /* Read in exec structure. */ 111*46012Sbostic nr = read(rfd, (char *)&ebuf, sizeof(struct exec)); 112*46012Sbostic if (nr != sizeof(struct exec)) 113*46012Sbostic goto badread; 114*46012Sbostic 115*46012Sbostic /* Check magic number and symbol count. */ 116*46012Sbostic if (N_BADMAG(ebuf) || ebuf.a_syms == 0) 117*46012Sbostic goto bad1; 118*46012Sbostic 119*46012Sbostic /* Seek to string table. */ 120*46012Sbostic if (lseek(rfd, N_STROFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) 121*46012Sbostic error(archive); 122*46012Sbostic 123*46012Sbostic /* Read in size of the string table. */ 124*46012Sbostic nr = read(rfd, (char *)&strsize, sizeof(strsize)); 125*46012Sbostic if (nr != sizeof(strsize)) 126*46012Sbostic goto badread; 127*46012Sbostic 128*46012Sbostic /* Read in the string table. */ 129*46012Sbostic strsize -= sizeof(strsize); 130*46012Sbostic strtab = (char *)emalloc(strsize); 131*46012Sbostic nr = read(rfd, strtab, strsize); 132*46012Sbostic if (nr != strsize) { 133*46012Sbostic badread: if (nr < 0) 134*46012Sbostic error(archive); 135*46012Sbostic goto bad2; 136*46012Sbostic } 137*46012Sbostic 138*46012Sbostic /* Seek to symbol table. */ 139*46012Sbostic if (fseek(fp, N_SYMOFF(ebuf) + r_off, SEEK_SET) == (off_t)-1) 140*46012Sbostic goto bad2; 141*46012Sbostic 142*46012Sbostic /* For each symbol read the nlist entry and save it as necessary. */ 143*46012Sbostic nsyms = ebuf.a_syms / sizeof(struct nlist); 144*46012Sbostic while (nsyms--) { 145*46012Sbostic if (!fread((char *)&nl, sizeof(struct nlist), 1, fp)) { 146*46012Sbostic if (feof(fp)) 147*46012Sbostic badfmt(); 148*46012Sbostic error(archive); 149*46012Sbostic } 150*46012Sbostic 151*46012Sbostic /* Ignore if no name or local. */ 152*46012Sbostic if (!nl.n_un.n_strx || !(nl.n_type & N_EXT)) 153*46012Sbostic continue; 154*46012Sbostic 155*46012Sbostic /* 156*46012Sbostic * If the symbol is an undefined external and the n_value 157*46012Sbostic * field is non-zero, keep it. 158*46012Sbostic */ 159*46012Sbostic if ((nl.n_type & N_TYPE) == N_UNDF && !nl.n_value) 160*46012Sbostic continue; 161*46012Sbostic 162*46012Sbostic /* First four bytes are the table size. */ 163*46012Sbostic sym = strtab + nl.n_un.n_strx - sizeof(long); 164*46012Sbostic symlen = strlen(sym) + 1; 165*46012Sbostic 166*46012Sbostic rp = (RLIB *)emalloc(sizeof(RLIB)); 167*46012Sbostic rp->sym = (char *)emalloc(symlen); 168*46012Sbostic bcopy(sym, rp->sym, symlen); 169*46012Sbostic rp->symlen = symlen; 170*46012Sbostic rp->pos = w_off; 171*46012Sbostic 172*46012Sbostic /* Build in forward order for "ar -m" command. */ 173*46012Sbostic *pnext = rp; 174*46012Sbostic pnext = &rp->next; 175*46012Sbostic 176*46012Sbostic ++symcnt; 177*46012Sbostic tsymlen += symlen; 178*46012Sbostic } 179*46012Sbostic 180*46012Sbostic bad2: free(strtab); 181*46012Sbostic bad1: (void)lseek(rfd, (off_t)r_off, SEEK_SET); 182*46012Sbostic } 183*46012Sbostic 184*46012Sbostic /* 185*46012Sbostic * symobj -- 186*46012Sbostic * Write the symbol table into the archive, computing offsets as 187*46012Sbostic * writing. 188*46012Sbostic */ 189*46012Sbostic static 190*46012Sbostic symobj() 191*46012Sbostic { 192*46012Sbostic register RLIB *rp; 193*46012Sbostic struct ranlib rn; 194*46012Sbostic char hb[sizeof(struct ar_hdr) + 1], pad; 195*46012Sbostic long ransize, size, stroff; 196*46012Sbostic gid_t getgid(); 197*46012Sbostic uid_t getuid(); 198*46012Sbostic 199*46012Sbostic /* Rewind the archive, leaving the magic number. */ 200*46012Sbostic if (fseek(fp, (off_t)SARMAG, SEEK_SET) == (off_t)-1) 201*46012Sbostic error(archive); 202*46012Sbostic 203*46012Sbostic /* Size of the ranlib archive file, pad if necessary. */ 204*46012Sbostic ransize = sizeof(long) + 205*46012Sbostic symcnt * sizeof(struct ranlib) + sizeof(long) + tsymlen; 206*46012Sbostic if (ransize & 01) { 207*46012Sbostic ++ransize; 208*46012Sbostic pad = '\n'; 209*46012Sbostic } else 210*46012Sbostic pad = '\0'; 211*46012Sbostic 212*46012Sbostic /* Put out the ranlib archive file header. */ 213*46012Sbostic #define DEFMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) 214*46012Sbostic (void)sprintf(hb, HDR2, RANLIBMAG, 0L, getuid(), getgid(), 215*46012Sbostic DEFMODE & ~umask(), ransize, ARFMAG); 216*46012Sbostic if (!fwrite(hb, sizeof(struct ar_hdr), 1, fp)) 217*46012Sbostic error(tname); 218*46012Sbostic 219*46012Sbostic /* First long is the size of the ranlib structure section. */ 220*46012Sbostic size = symcnt * sizeof(struct ranlib); 221*46012Sbostic if (!fwrite((char *)&size, sizeof(size), 1, fp)) 222*46012Sbostic error(tname); 223*46012Sbostic 224*46012Sbostic /* Offset of the first archive file. */ 225*46012Sbostic size = SARMAG + sizeof(struct ar_hdr) + ransize; 226*46012Sbostic 227*46012Sbostic /* 228*46012Sbostic * Write out the ranlib structures. The offset into the string 229*46012Sbostic * table is cumulative, the offset into the archive is the value 230*46012Sbostic * set in rexec() plus the offset to the first archive file. 231*46012Sbostic */ 232*46012Sbostic for (rp = rhead, stroff = 0; rp; rp = rp->next) { 233*46012Sbostic rn.ran_un.ran_strx = stroff; 234*46012Sbostic stroff += rp->symlen; 235*46012Sbostic rn.ran_off = size + rp->pos; 236*46012Sbostic if (!fwrite((char *)&rn, sizeof(struct ranlib), 1, fp)) 237*46012Sbostic error(archive); 238*46012Sbostic } 239*46012Sbostic 240*46012Sbostic /* Second long is the size of the string table. */ 241*46012Sbostic if (!fwrite((char *)&tsymlen, sizeof(tsymlen), 1, fp)) 242*46012Sbostic error(tname); 243*46012Sbostic 244*46012Sbostic /* Write out the string table. */ 245*46012Sbostic for (rp = rhead; rp; rp = rp->next) 246*46012Sbostic if (!fwrite(rp->sym, rp->symlen, 1, fp)) 247*46012Sbostic error(tname); 248*46012Sbostic 249*46012Sbostic if (pad && !fwrite(&pad, sizeof(pad), 1, fp)) 250*46012Sbostic error(tname); 251*46012Sbostic 252*46012Sbostic (void)fflush(fp); 253*46012Sbostic } 254