xref: /csrg-svn/usr.bin/ranlib/ranlib.c (revision 22410)
1*22410Sdist /*
2*22410Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22410Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22410Sdist  * specifies the terms and conditions for redistribution.
5*22410Sdist  */
6*22410Sdist 
712673Ssam #ifndef lint
8*22410Sdist char copyright[] =
9*22410Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10*22410Sdist  All rights reserved.\n";
11*22410Sdist #endif not lint
12*22410Sdist 
13*22410Sdist #ifndef lint
14*22410Sdist static char sccsid[] = "@(#)ranlib.c	5.1 (Berkeley) 06/06/85";
15*22410Sdist #endif not lint
16*22410Sdist 
17625Sbill /*
18625Sbill  * ranlib - create table of contents for archive; string table version
19625Sbill  */
20625Sbill #include <sys/types.h>
21899Sbill #include <ar.h>
22625Sbill #include <ranlib.h>
23899Sbill #include <a.out.h>
24625Sbill #include <stdio.h>
25625Sbill 
26625Sbill struct	ar_hdr	archdr;
27625Sbill #define	OARMAG 0177545
28625Sbill long	arsize;
29625Sbill struct	exec	exp;
30625Sbill FILE	*fi, *fo;
31625Sbill long	off, oldoff;
32625Sbill long	atol(), ftell();
3311152Sshantz #define TABSZ	6000
34625Sbill struct	ranlib tab[TABSZ];
35625Sbill int	tnum;
361753Sbill #define	STRTABSZ	75000
37625Sbill char	tstrtab[STRTABSZ];
38625Sbill int	tssiz;
39625Sbill char	*strtab;
40625Sbill int	ssiz;
41625Sbill int	new;
42625Sbill char	tempnm[] = "__.SYMDEF";
43625Sbill char	firstname[17];
44625Sbill 
45625Sbill main(argc, argv)
46625Sbill char **argv;
47625Sbill {
48625Sbill 	char cmdbuf[BUFSIZ];
499343Srt 	/* magbuf must be an int array so it is aligned on an int-ish
509343Srt 	   boundary, so that we may access its first word as an int! */
519343Srt 	int magbuf[(SARMAG+sizeof(int))/sizeof(int)];
5219932Smckusick 	register int just_touch = 0;
53625Sbill 
5419932Smckusick 	/* check for the "-t" flag" */
5519932Smckusick 	if (argc > 1 && strcmp(argv[1], "-t") == 0) {
5619932Smckusick 		just_touch++;
5719932Smckusick 		argc--;
5819932Smckusick 		argv++;
5919932Smckusick 	}
6019932Smckusick 
61625Sbill 	--argc;
62625Sbill 	while(argc--) {
63625Sbill 		fi = fopen(*++argv,"r");
64625Sbill 		if (fi == NULL) {
65625Sbill 			fprintf(stderr, "ranlib: cannot open %s\n", *argv);
66625Sbill 			continue;
67625Sbill 		}
68625Sbill 		off = SARMAG;
699343Srt 		fread((char *)magbuf, 1, SARMAG, fi);
709343Srt 		if (strncmp((char *)magbuf, ARMAG, SARMAG)) {
719343Srt 			if (magbuf[0] == OARMAG)
72625Sbill 				fprintf(stderr, "old format ");
73625Sbill 			else
74625Sbill 				fprintf(stderr, "not an ");
75625Sbill 			fprintf(stderr, "archive: %s\n", *argv);
76625Sbill 			continue;
77625Sbill 		}
7819963Smckusick 		if (just_touch) {
7919963Smckusick 			register int	len;
8019963Smckusick 
8119963Smckusick 			fseek(fi, (long) SARMAG, 0);
8219963Smckusick 			if (fread(cmdbuf, sizeof archdr.ar_name, 1, fi) != 1) {
8319963Smckusick 				fprintf(stderr, "malformed archive: %s\n",
8419963Smckusick 					*argv);
8519963Smckusick 				continue;
8619963Smckusick 			}
8719963Smckusick 			len = strlen(tempnm);
8819963Smckusick 			if (bcmp(cmdbuf, tempnm, len) != 0 ||
8919963Smckusick 			    cmdbuf[len] != ' ') {
9019963Smckusick 				fprintf(stderr, "no symbol table: %s\n", *argv);
9119963Smckusick 				continue;
9219963Smckusick 			}
9319963Smckusick 			fclose(fi);
9419963Smckusick 			fixdate(*++argv);
9519963Smckusick 			continue;
9619963Smckusick 		}
97625Sbill 		fseek(fi, 0L, 0);
98625Sbill 		new = tnum = 0;
99625Sbill 		if (nextel(fi) == 0) {
100625Sbill 			fclose(fi);
101625Sbill 			continue;
102625Sbill 		}
103625Sbill 		do {
104625Sbill 			long o;
105625Sbill 			register n;
106625Sbill 			struct nlist sym;
107625Sbill 
108625Sbill 			fread((char *)&exp, 1, sizeof(struct exec), fi);
109625Sbill 			if (N_BADMAG(exp))
110625Sbill 				continue;
11117423Sralph 			if (!strncmp(tempnm, archdr.ar_name, sizeof(archdr.ar_name)))
11217423Sralph 				continue;
113625Sbill 			if (exp.a_syms == 0) {
114625Sbill 				fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name);
1153607Ssklower 				continue;
116625Sbill 			}
117625Sbill 			o = N_STROFF(exp) - sizeof (struct exec);
118625Sbill 			if (ftell(fi)+o+sizeof(ssiz) >= off) {
11917423Sralph 				fprintf(stderr, "ranlib: warning: %s(%s): old format .o file\n", *argv, archdr.ar_name);
12017423Sralph 				continue;
121625Sbill 			}
122625Sbill 			fseek(fi, o, 1);
123625Sbill 			fread((char *)&ssiz, 1, sizeof (ssiz), fi);
1249343Srt 			if (ssiz < sizeof ssiz){
1259343Srt 				/* sanity check */
12617423Sralph 				fprintf(stderr, "ranlib: warning: %s(%s): mangled string table\n", *argv, archdr.ar_name);
12717423Sralph 				continue;
1289343Srt 			}
129625Sbill 			strtab = (char *)calloc(1, ssiz);
130625Sbill 			if (strtab == 0) {
131625Sbill 				fprintf(stderr, "ranlib: ran out of memory\n");
132625Sbill 				exit(1);
133625Sbill 			}
134625Sbill 			fread(strtab+sizeof(ssiz), ssiz - sizeof(ssiz), 1, fi);
135625Sbill 			fseek(fi, -(exp.a_syms+ssiz), 1);
136625Sbill 			n = exp.a_syms / sizeof(struct nlist);
137625Sbill 			while (--n >= 0) {
138625Sbill 				fread((char *)&sym, 1, sizeof(sym), fi);
139625Sbill 				if (sym.n_un.n_strx == 0)
140625Sbill 					continue;
141625Sbill 				sym.n_un.n_name = strtab + sym.n_un.n_strx;
142625Sbill 				if ((sym.n_type&N_EXT)==0)
143625Sbill 					continue;
144625Sbill 				switch (sym.n_type&N_TYPE) {
145625Sbill 
146625Sbill 				case N_UNDF:
147625Sbill 					if (sym.n_value!=0)
148625Sbill 						stash(&sym);
149625Sbill 					continue;
150625Sbill 
151625Sbill 				default:
152625Sbill 					stash(&sym);
153625Sbill 					continue;
154625Sbill 				}
155625Sbill 			}
156625Sbill 		} while(nextel(fi));
157625Sbill 		new = fixsize();
158625Sbill 		fclose(fi);
159625Sbill 		fo = fopen(tempnm, "w");
160625Sbill 		if(fo == NULL) {
161625Sbill 			fprintf(stderr, "can't create temporary\n");
162625Sbill 			exit(1);
163625Sbill 		}
164625Sbill 		tnum *= sizeof (struct ranlib);
165625Sbill 		fwrite(&tnum, 1, sizeof (tnum), fo);
166625Sbill 		tnum /= sizeof (struct ranlib);
167625Sbill 		fwrite((char *)tab, tnum, sizeof(struct ranlib), fo);
168625Sbill 		fwrite(&tssiz, 1, sizeof (tssiz), fo);
169625Sbill 		fwrite(tstrtab, tssiz, 1, fo);
170625Sbill 		fclose(fo);
171625Sbill 		if(new)
172899Sbill 			sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm);
173625Sbill 		else
174899Sbill 			sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm);
175625Sbill 		if(system(cmdbuf))
176625Sbill 			fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf);
177625Sbill 		else
178625Sbill 			fixdate(*argv);
179625Sbill 		unlink(tempnm);
180625Sbill 	}
181625Sbill 	exit(0);
182625Sbill }
183625Sbill 
184625Sbill nextel(af)
185625Sbill FILE *af;
186625Sbill {
187625Sbill 	register r;
188625Sbill 	register char *cp;
189625Sbill 
190625Sbill 	oldoff = off;
191625Sbill 	fseek(af, off, 0);
192625Sbill 	r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
193625Sbill 	if (r != sizeof(struct ar_hdr))
194625Sbill 		return(0);
195625Sbill 	for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++)
196625Sbill 		if (*cp == ' ')
197625Sbill 			*cp = '\0';
198625Sbill 	arsize = atol(archdr.ar_size);
199625Sbill 	if (arsize & 1)
200625Sbill 		arsize++;
201625Sbill 	off = ftell(af) + arsize;
202625Sbill 	return(1);
203625Sbill }
204625Sbill 
205625Sbill stash(s)
206625Sbill 	struct nlist *s;
207625Sbill {
208625Sbill 	int i;
209625Sbill 	register char *cp;
210625Sbill 
211625Sbill 	if(tnum >= TABSZ) {
212625Sbill 		fprintf(stderr, "ranlib: symbol table overflow\n");
213625Sbill 		exit(1);
214625Sbill 	}
215625Sbill 	tab[tnum].ran_un.ran_strx = tssiz;
216625Sbill 	tab[tnum].ran_off = oldoff;
217625Sbill 	for (cp = s->n_un.n_name; tstrtab[tssiz++] = *cp++;)
218625Sbill 		if (tssiz > STRTABSZ) {
219625Sbill 			fprintf(stderr, "ranlib: string table overflow\n");
220625Sbill 			exit(1);
221625Sbill 		}
222625Sbill 	tnum++;
223625Sbill }
224625Sbill 
225625Sbill fixsize()
226625Sbill {
227625Sbill 	int i;
228625Sbill 	off_t offdelta;
229625Sbill 
230625Sbill 	if (tssiz&1)
231625Sbill 		tssiz++;
232625Sbill 	offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) +
233625Sbill 	    sizeof (tssiz) + tssiz;
234625Sbill 	off = SARMAG;
235625Sbill 	nextel(fi);
236625Sbill 	if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) {
237625Sbill 		new = 0;
238625Sbill 		offdelta -= sizeof(archdr) + arsize;
239625Sbill 	} else {
240625Sbill 		new = 1;
241625Sbill 		strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name));
242625Sbill 	}
243625Sbill 	for(i=0; i<tnum; i++)
244625Sbill 		tab[i].ran_off += offdelta;
245625Sbill 	return(new);
246625Sbill }
247625Sbill 
248625Sbill /* patch time */
249625Sbill fixdate(s)
250625Sbill 	char *s;
251625Sbill {
252625Sbill 	long time();
253625Sbill 	char buf[24];
254625Sbill 	int fd;
255625Sbill 
256625Sbill 	fd = open(s, 1);
257625Sbill 	if(fd < 0) {
258625Sbill 		fprintf(stderr, "ranlib: can't reopen %s\n", s);
259625Sbill 		return;
260625Sbill 	}
261625Sbill 	sprintf(buf, "%-*ld", sizeof(archdr.ar_date), time((long *)NULL)+5);
262625Sbill 	lseek(fd, (long)SARMAG + ((char *)archdr.ar_date-(char *)&archdr), 0);
263625Sbill 	write(fd, buf, sizeof(archdr.ar_date));
264625Sbill 	close(fd);
265625Sbill }
266