xref: /csrg-svn/usr.bin/ranlib/ranlib.c (revision 19963)
112673Ssam #ifndef lint
2*19963Smckusick static	char sccsid[] = "@(#)ranlib.c 4.9 05/06/85";
312673Ssam #endif
4625Sbill /*
5625Sbill  * ranlib - create table of contents for archive; string table version
6625Sbill  */
7625Sbill #include <sys/types.h>
8899Sbill #include <ar.h>
9625Sbill #include <ranlib.h>
10899Sbill #include <a.out.h>
11625Sbill #include <stdio.h>
12625Sbill 
13625Sbill struct	ar_hdr	archdr;
14625Sbill #define	OARMAG 0177545
15625Sbill long	arsize;
16625Sbill struct	exec	exp;
17625Sbill FILE	*fi, *fo;
18625Sbill long	off, oldoff;
19625Sbill long	atol(), ftell();
2011152Sshantz #define TABSZ	6000
21625Sbill struct	ranlib tab[TABSZ];
22625Sbill int	tnum;
231753Sbill #define	STRTABSZ	75000
24625Sbill char	tstrtab[STRTABSZ];
25625Sbill int	tssiz;
26625Sbill char	*strtab;
27625Sbill int	ssiz;
28625Sbill int	new;
29625Sbill char	tempnm[] = "__.SYMDEF";
30625Sbill char	firstname[17];
31625Sbill 
32625Sbill main(argc, argv)
33625Sbill char **argv;
34625Sbill {
35625Sbill 	char cmdbuf[BUFSIZ];
369343Srt 	/* magbuf must be an int array so it is aligned on an int-ish
379343Srt 	   boundary, so that we may access its first word as an int! */
389343Srt 	int magbuf[(SARMAG+sizeof(int))/sizeof(int)];
3919932Smckusick 	register int just_touch = 0;
40625Sbill 
4119932Smckusick 	/* check for the "-t" flag" */
4219932Smckusick 	if (argc > 1 && strcmp(argv[1], "-t") == 0) {
4319932Smckusick 		just_touch++;
4419932Smckusick 		argc--;
4519932Smckusick 		argv++;
4619932Smckusick 	}
4719932Smckusick 
48625Sbill 	--argc;
49625Sbill 	while(argc--) {
50625Sbill 		fi = fopen(*++argv,"r");
51625Sbill 		if (fi == NULL) {
52625Sbill 			fprintf(stderr, "ranlib: cannot open %s\n", *argv);
53625Sbill 			continue;
54625Sbill 		}
55625Sbill 		off = SARMAG;
569343Srt 		fread((char *)magbuf, 1, SARMAG, fi);
579343Srt 		if (strncmp((char *)magbuf, ARMAG, SARMAG)) {
589343Srt 			if (magbuf[0] == OARMAG)
59625Sbill 				fprintf(stderr, "old format ");
60625Sbill 			else
61625Sbill 				fprintf(stderr, "not an ");
62625Sbill 			fprintf(stderr, "archive: %s\n", *argv);
63625Sbill 			continue;
64625Sbill 		}
65*19963Smckusick 		if (just_touch) {
66*19963Smckusick 			register int	len;
67*19963Smckusick 
68*19963Smckusick 			fseek(fi, (long) SARMAG, 0);
69*19963Smckusick 			if (fread(cmdbuf, sizeof archdr.ar_name, 1, fi) != 1) {
70*19963Smckusick 				fprintf(stderr, "malformed archive: %s\n",
71*19963Smckusick 					*argv);
72*19963Smckusick 				continue;
73*19963Smckusick 			}
74*19963Smckusick 			len = strlen(tempnm);
75*19963Smckusick 			if (bcmp(cmdbuf, tempnm, len) != 0 ||
76*19963Smckusick 			    cmdbuf[len] != ' ') {
77*19963Smckusick 				fprintf(stderr, "no symbol table: %s\n", *argv);
78*19963Smckusick 				continue;
79*19963Smckusick 			}
80*19963Smckusick 			fclose(fi);
81*19963Smckusick 			fixdate(*++argv);
82*19963Smckusick 			continue;
83*19963Smckusick 		}
84625Sbill 		fseek(fi, 0L, 0);
85625Sbill 		new = tnum = 0;
86625Sbill 		if (nextel(fi) == 0) {
87625Sbill 			fclose(fi);
88625Sbill 			continue;
89625Sbill 		}
90625Sbill 		do {
91625Sbill 			long o;
92625Sbill 			register n;
93625Sbill 			struct nlist sym;
94625Sbill 
95625Sbill 			fread((char *)&exp, 1, sizeof(struct exec), fi);
96625Sbill 			if (N_BADMAG(exp))
97625Sbill 				continue;
9817423Sralph 			if (!strncmp(tempnm, archdr.ar_name, sizeof(archdr.ar_name)))
9917423Sralph 				continue;
100625Sbill 			if (exp.a_syms == 0) {
101625Sbill 				fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name);
1023607Ssklower 				continue;
103625Sbill 			}
104625Sbill 			o = N_STROFF(exp) - sizeof (struct exec);
105625Sbill 			if (ftell(fi)+o+sizeof(ssiz) >= off) {
10617423Sralph 				fprintf(stderr, "ranlib: warning: %s(%s): old format .o file\n", *argv, archdr.ar_name);
10717423Sralph 				continue;
108625Sbill 			}
109625Sbill 			fseek(fi, o, 1);
110625Sbill 			fread((char *)&ssiz, 1, sizeof (ssiz), fi);
1119343Srt 			if (ssiz < sizeof ssiz){
1129343Srt 				/* sanity check */
11317423Sralph 				fprintf(stderr, "ranlib: warning: %s(%s): mangled string table\n", *argv, archdr.ar_name);
11417423Sralph 				continue;
1159343Srt 			}
116625Sbill 			strtab = (char *)calloc(1, ssiz);
117625Sbill 			if (strtab == 0) {
118625Sbill 				fprintf(stderr, "ranlib: ran out of memory\n");
119625Sbill 				exit(1);
120625Sbill 			}
121625Sbill 			fread(strtab+sizeof(ssiz), ssiz - sizeof(ssiz), 1, fi);
122625Sbill 			fseek(fi, -(exp.a_syms+ssiz), 1);
123625Sbill 			n = exp.a_syms / sizeof(struct nlist);
124625Sbill 			while (--n >= 0) {
125625Sbill 				fread((char *)&sym, 1, sizeof(sym), fi);
126625Sbill 				if (sym.n_un.n_strx == 0)
127625Sbill 					continue;
128625Sbill 				sym.n_un.n_name = strtab + sym.n_un.n_strx;
129625Sbill 				if ((sym.n_type&N_EXT)==0)
130625Sbill 					continue;
131625Sbill 				switch (sym.n_type&N_TYPE) {
132625Sbill 
133625Sbill 				case N_UNDF:
134625Sbill 					if (sym.n_value!=0)
135625Sbill 						stash(&sym);
136625Sbill 					continue;
137625Sbill 
138625Sbill 				default:
139625Sbill 					stash(&sym);
140625Sbill 					continue;
141625Sbill 				}
142625Sbill 			}
143625Sbill 		} while(nextel(fi));
144625Sbill 		new = fixsize();
145625Sbill 		fclose(fi);
146625Sbill 		fo = fopen(tempnm, "w");
147625Sbill 		if(fo == NULL) {
148625Sbill 			fprintf(stderr, "can't create temporary\n");
149625Sbill 			exit(1);
150625Sbill 		}
151625Sbill 		tnum *= sizeof (struct ranlib);
152625Sbill 		fwrite(&tnum, 1, sizeof (tnum), fo);
153625Sbill 		tnum /= sizeof (struct ranlib);
154625Sbill 		fwrite((char *)tab, tnum, sizeof(struct ranlib), fo);
155625Sbill 		fwrite(&tssiz, 1, sizeof (tssiz), fo);
156625Sbill 		fwrite(tstrtab, tssiz, 1, fo);
157625Sbill 		fclose(fo);
158625Sbill 		if(new)
159899Sbill 			sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm);
160625Sbill 		else
161899Sbill 			sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm);
162625Sbill 		if(system(cmdbuf))
163625Sbill 			fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf);
164625Sbill 		else
165625Sbill 			fixdate(*argv);
166625Sbill 		unlink(tempnm);
167625Sbill 	}
168625Sbill 	exit(0);
169625Sbill }
170625Sbill 
171625Sbill nextel(af)
172625Sbill FILE *af;
173625Sbill {
174625Sbill 	register r;
175625Sbill 	register char *cp;
176625Sbill 
177625Sbill 	oldoff = off;
178625Sbill 	fseek(af, off, 0);
179625Sbill 	r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
180625Sbill 	if (r != sizeof(struct ar_hdr))
181625Sbill 		return(0);
182625Sbill 	for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++)
183625Sbill 		if (*cp == ' ')
184625Sbill 			*cp = '\0';
185625Sbill 	arsize = atol(archdr.ar_size);
186625Sbill 	if (arsize & 1)
187625Sbill 		arsize++;
188625Sbill 	off = ftell(af) + arsize;
189625Sbill 	return(1);
190625Sbill }
191625Sbill 
192625Sbill stash(s)
193625Sbill 	struct nlist *s;
194625Sbill {
195625Sbill 	int i;
196625Sbill 	register char *cp;
197625Sbill 
198625Sbill 	if(tnum >= TABSZ) {
199625Sbill 		fprintf(stderr, "ranlib: symbol table overflow\n");
200625Sbill 		exit(1);
201625Sbill 	}
202625Sbill 	tab[tnum].ran_un.ran_strx = tssiz;
203625Sbill 	tab[tnum].ran_off = oldoff;
204625Sbill 	for (cp = s->n_un.n_name; tstrtab[tssiz++] = *cp++;)
205625Sbill 		if (tssiz > STRTABSZ) {
206625Sbill 			fprintf(stderr, "ranlib: string table overflow\n");
207625Sbill 			exit(1);
208625Sbill 		}
209625Sbill 	tnum++;
210625Sbill }
211625Sbill 
212625Sbill fixsize()
213625Sbill {
214625Sbill 	int i;
215625Sbill 	off_t offdelta;
216625Sbill 
217625Sbill 	if (tssiz&1)
218625Sbill 		tssiz++;
219625Sbill 	offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) +
220625Sbill 	    sizeof (tssiz) + tssiz;
221625Sbill 	off = SARMAG;
222625Sbill 	nextel(fi);
223625Sbill 	if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) {
224625Sbill 		new = 0;
225625Sbill 		offdelta -= sizeof(archdr) + arsize;
226625Sbill 	} else {
227625Sbill 		new = 1;
228625Sbill 		strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name));
229625Sbill 	}
230625Sbill 	for(i=0; i<tnum; i++)
231625Sbill 		tab[i].ran_off += offdelta;
232625Sbill 	return(new);
233625Sbill }
234625Sbill 
235625Sbill /* patch time */
236625Sbill fixdate(s)
237625Sbill 	char *s;
238625Sbill {
239625Sbill 	long time();
240625Sbill 	char buf[24];
241625Sbill 	int fd;
242625Sbill 
243625Sbill 	fd = open(s, 1);
244625Sbill 	if(fd < 0) {
245625Sbill 		fprintf(stderr, "ranlib: can't reopen %s\n", s);
246625Sbill 		return;
247625Sbill 	}
248625Sbill 	sprintf(buf, "%-*ld", sizeof(archdr.ar_date), time((long *)NULL)+5);
249625Sbill 	lseek(fd, (long)SARMAG + ((char *)archdr.ar_date-(char *)&archdr), 0);
250625Sbill 	write(fd, buf, sizeof(archdr.ar_date));
251625Sbill 	close(fd);
252625Sbill }
253