xref: /csrg-svn/usr.bin/ranlib/build.c (revision 62197)
146012Sbostic /*-
2*62197Sbostic  * Copyright (c) 1990, 1993
3*62197Sbostic  *	The Regents of the University of California.  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*62197Sbostic static char sccsid[] = "@(#)build.c	8.1 (Berkeley) 06/06/93";
1346012Sbostic #endif /* not lint */
1446012Sbostic 
1546012Sbostic #include <sys/types.h>
1646012Sbostic #include <sys/errno.h>
1746012Sbostic #include <sys/stat.h>
1860139Sbostic 
1946012Sbostic #include <a.out.h>
2060139Sbostic #include <ar.h>
2146012Sbostic #include <dirent.h>
2260139Sbostic #include <fcntl.h>
2346012Sbostic #include <ranlib.h>
2446012Sbostic #include <stdio.h>
2560139Sbostic #include <unistd.h>
2646012Sbostic 
2760139Sbostic #include "archive.h"
2860139Sbostic 
2946012Sbostic extern CHDR chdr;			/* converted header */
3046012Sbostic extern char *archive;			/* archive name */
3146012Sbostic extern char *tname;			/* temporary file "name" */
3246012Sbostic 
3346012Sbostic typedef struct _rlib {
3446012Sbostic 	struct _rlib *next;		/* next structure */
3546012Sbostic 	off_t pos;			/* offset of defining archive file */
3646012Sbostic 	char *sym;			/* symbol */
3746012Sbostic 	int symlen;			/* strlen(sym) */
3846012Sbostic } RLIB;
3946012Sbostic RLIB *rhead, **pnext;
4046012Sbostic 
4146012Sbostic FILE *fp;
4246012Sbostic 
4360139Sbostic long symcnt;				/* symbol count */
4460139Sbostic long tsymlen;				/* total string length */
4560139Sbostic 
4660139Sbostic static void rexec __P((int, int));
4760139Sbostic static void symobj __P((void));
4860139Sbostic 
build()4946012Sbostic build()
5046012Sbostic {
5146012Sbostic 	CF cf;
5246012Sbostic 	int afd, tfd;
5346012Sbostic 	off_t size;
5446012Sbostic 
5546012Sbostic 	afd = open_archive(O_RDWR);
5646012Sbostic 	fp = fdopen(afd, "r+");
5746012Sbostic 	tfd = tmp();
5846012Sbostic 
5946012Sbostic 	SETCF(afd, archive, tfd, tname, RPAD|WPAD);
6046012Sbostic 
6146012Sbostic 	/* Read through the archive, creating list of symbols. */
6246012Sbostic 	pnext = &rhead;
6360139Sbostic 	symcnt = tsymlen = 0;
6447241Sbostic 	while(get_arobj(afd)) {
6546012Sbostic 		if (!strcmp(chdr.name, RANLIBMAG)) {
6647241Sbostic 			skip_arobj(afd);
6746012Sbostic 			continue;
6846012Sbostic 		}
6946012Sbostic 		rexec(afd, tfd);
7047241Sbostic 		put_arobj(&cf, (struct stat *)NULL);
7146012Sbostic 	}
7246012Sbostic 	*pnext = NULL;
7346012Sbostic 
7446012Sbostic 	/* Create the symbol table. */
7546012Sbostic 	symobj();
7646012Sbostic 
7746012Sbostic 	/* Copy the saved objects into the archive. */
7846012Sbostic 	size = lseek(tfd, (off_t)0, SEEK_CUR);
7946012Sbostic 	(void)lseek(tfd, (off_t)0, SEEK_SET);
8046012Sbostic 	SETCF(tfd, tname, afd, archive, RPAD|WPAD);
8147241Sbostic 	copy_ar(&cf, size);
8246012Sbostic 	(void)ftruncate(afd, lseek(afd, (off_t)0, SEEK_CUR));
8346012Sbostic 	(void)close(tfd);
8446012Sbostic 
8546012Sbostic 	/* Set the time. */
8646012Sbostic 	settime(afd);
8746012Sbostic 	close_archive(afd);
8846012Sbostic 	return(0);
8946012Sbostic }
9046012Sbostic 
9146012Sbostic /*
9246012Sbostic  * rexec
9346012Sbostic  *	Read the exec structure; ignore any files that don't look
9446012Sbostic  *	exactly right.
9546012Sbostic  */
9646698Sbostic static void
rexec(rfd,wfd)9746012Sbostic rexec(rfd, wfd)
9846012Sbostic 	register int rfd;
9946012Sbostic 	int wfd;
10046012Sbostic {
10146012Sbostic 	register RLIB *rp;
10246012Sbostic 	register long nsyms;
10346012Sbostic 	register int nr, symlen;
10446012Sbostic 	register char *strtab, *sym;
10546012Sbostic 	struct exec ebuf;
10646012Sbostic 	struct nlist nl;
10746012Sbostic 	off_t r_off, w_off;
10846012Sbostic 	long strsize;
10946012Sbostic 	void *emalloc();
11046012Sbostic 
11146012Sbostic 	/* Get current offsets for original and tmp files. */
11246012Sbostic 	r_off = lseek(rfd, (off_t)0, SEEK_CUR);
11346012Sbostic 	w_off = lseek(wfd, (off_t)0, SEEK_CUR);
11446012Sbostic 
11546012Sbostic 	/* Read in exec structure. */
11654078Sbostic 	nr = read(rfd, &ebuf, sizeof(struct exec));
11746012Sbostic 	if (nr != sizeof(struct exec))
11846012Sbostic 		goto badread;
11946012Sbostic 
12046012Sbostic 	/* Check magic number and symbol count. */
12146012Sbostic 	if (N_BADMAG(ebuf) || ebuf.a_syms == 0)
12246012Sbostic 		goto bad1;
12346012Sbostic 
12446012Sbostic 	/* Seek to string table. */
12554078Sbostic 	if (lseek(rfd, r_off + N_STROFF(ebuf), SEEK_SET) == (off_t)-1)
12646012Sbostic 		error(archive);
12746012Sbostic 
12846012Sbostic 	/* Read in size of the string table. */
12954078Sbostic 	nr = read(rfd, &strsize, sizeof(strsize));
13046012Sbostic 	if (nr != sizeof(strsize))
13146012Sbostic 		goto badread;
13246012Sbostic 
13346012Sbostic 	/* Read in the string table. */
13446012Sbostic 	strsize -= sizeof(strsize);
13554078Sbostic 	strtab = emalloc(strsize);
13646012Sbostic 	nr = read(rfd, strtab, strsize);
13746012Sbostic 	if (nr != strsize) {
13846012Sbostic badread:	if (nr < 0)
13946012Sbostic 			error(archive);
14046012Sbostic 		goto bad2;
14146012Sbostic 	}
14246012Sbostic 
14346012Sbostic 	/* Seek to symbol table. */
14459716Storek 	if (fseek(fp, (long)r_off + N_SYMOFF(ebuf), SEEK_SET))
14546012Sbostic 		goto bad2;
14646012Sbostic 
14746012Sbostic 	/* For each symbol read the nlist entry and save it as necessary. */
14846012Sbostic 	nsyms = ebuf.a_syms / sizeof(struct nlist);
14946012Sbostic 	while (nsyms--) {
15054078Sbostic 		if (!fread(&nl, sizeof(struct nlist), 1, fp)) {
15146012Sbostic 			if (feof(fp))
15246012Sbostic 				badfmt();
15346012Sbostic 			error(archive);
15446012Sbostic 		}
15546012Sbostic 
15646012Sbostic 		/* Ignore if no name or local. */
15746012Sbostic 		if (!nl.n_un.n_strx || !(nl.n_type & N_EXT))
15846012Sbostic 			continue;
15946012Sbostic 
16046012Sbostic 		/*
16146012Sbostic 		 * If the symbol is an undefined external and the n_value
16246012Sbostic 		 * field is non-zero, keep it.
16346012Sbostic 		 */
16446012Sbostic 		if ((nl.n_type & N_TYPE) == N_UNDF && !nl.n_value)
16546012Sbostic 			continue;
16646012Sbostic 
16746012Sbostic 		/* First four bytes are the table size. */
16846012Sbostic 		sym = strtab + nl.n_un.n_strx - sizeof(long);
16946012Sbostic 		symlen = strlen(sym) + 1;
17046012Sbostic 
17146012Sbostic 		rp = (RLIB *)emalloc(sizeof(RLIB));
17246012Sbostic 		rp->sym = (char *)emalloc(symlen);
17346012Sbostic 		bcopy(sym, rp->sym, symlen);
17446012Sbostic 		rp->symlen = symlen;
17546012Sbostic 		rp->pos = w_off;
17646012Sbostic 
17746012Sbostic 		/* Build in forward order for "ar -m" command. */
17846012Sbostic 		*pnext = rp;
17946012Sbostic 		pnext = &rp->next;
18046012Sbostic 
18146012Sbostic 		++symcnt;
18246012Sbostic 		tsymlen += symlen;
18346012Sbostic 	}
18446012Sbostic 
18546012Sbostic bad2:	free(strtab);
18654078Sbostic bad1:	(void)lseek(rfd, r_off, SEEK_SET);
18746012Sbostic }
18846012Sbostic 
18946012Sbostic /*
19046012Sbostic  * symobj --
19146012Sbostic  *	Write the symbol table into the archive, computing offsets as
19246012Sbostic  *	writing.
19346012Sbostic  */
19446698Sbostic static void
symobj()19546012Sbostic symobj()
19646012Sbostic {
19746012Sbostic 	register RLIB *rp;
19846012Sbostic 	struct ranlib rn;
19954078Sbostic 	off_t ransize;
20054078Sbostic 	long size, stroff;
20146012Sbostic 	char hb[sizeof(struct ar_hdr) + 1], pad;
20246012Sbostic 
20346012Sbostic 	/* Rewind the archive, leaving the magic number. */
20459716Storek 	if (fseek(fp, (long)SARMAG, SEEK_SET))
20546012Sbostic 		error(archive);
20646012Sbostic 
20746012Sbostic 	/* Size of the ranlib archive file, pad if necessary. */
20846012Sbostic 	ransize = sizeof(long) +
20946012Sbostic 	    symcnt * sizeof(struct ranlib) + sizeof(long) + tsymlen;
21046012Sbostic 	if (ransize & 01) {
21146012Sbostic 		++ransize;
21246012Sbostic 		pad = '\n';
21346012Sbostic 	} else
21446012Sbostic 		pad = '\0';
21546012Sbostic 
21646012Sbostic 	/* Put out the ranlib archive file header. */
21746012Sbostic #define	DEFMODE	(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
21846012Sbostic 	(void)sprintf(hb, HDR2, RANLIBMAG, 0L, getuid(), getgid(),
21946698Sbostic 	    DEFMODE & ~umask(0), ransize, ARFMAG);
22046012Sbostic 	if (!fwrite(hb, sizeof(struct ar_hdr), 1, fp))
22146012Sbostic 		error(tname);
22246012Sbostic 
22346012Sbostic 	/* First long is the size of the ranlib structure section. */
22446012Sbostic 	size = symcnt * sizeof(struct ranlib);
22554078Sbostic 	if (!fwrite(&size, sizeof(size), 1, fp))
22646012Sbostic 		error(tname);
22746012Sbostic 
22846012Sbostic 	/* Offset of the first archive file. */
22946012Sbostic 	size = SARMAG + sizeof(struct ar_hdr) + ransize;
23046012Sbostic 
23146012Sbostic 	/*
23246012Sbostic 	 * Write out the ranlib structures.  The offset into the string
23346012Sbostic 	 * table is cumulative, the offset into the archive is the value
23446012Sbostic 	 * set in rexec() plus the offset to the first archive file.
23546012Sbostic 	 */
23646012Sbostic 	for (rp = rhead, stroff = 0; rp; rp = rp->next) {
23746012Sbostic 		rn.ran_un.ran_strx = stroff;
23846012Sbostic 		stroff += rp->symlen;
23946012Sbostic 		rn.ran_off = size + rp->pos;
24054078Sbostic 		if (!fwrite(&rn, sizeof(struct ranlib), 1, fp))
24146012Sbostic 			error(archive);
24246012Sbostic 	}
24346012Sbostic 
24446012Sbostic 	/* Second long is the size of the string table. */
24554078Sbostic 	if (!fwrite(&tsymlen, sizeof(tsymlen), 1, fp))
24646012Sbostic 		error(tname);
24746012Sbostic 
24846012Sbostic 	/* Write out the string table. */
24946012Sbostic 	for (rp = rhead; rp; rp = rp->next)
25046012Sbostic 		if (!fwrite(rp->sym, rp->symlen, 1, fp))
25146012Sbostic 			error(tname);
25246012Sbostic 
25346012Sbostic 	if (pad && !fwrite(&pad, sizeof(pad), 1, fp))
25446012Sbostic 		error(tname);
25546012Sbostic 
25646012Sbostic 	(void)fflush(fp);
25746012Sbostic }
258