xref: /csrg-svn/usr.bin/ranlib/ranlib.c (revision 22410)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 char copyright[] =
9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10  All rights reserved.\n";
11 #endif not lint
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)ranlib.c	5.1 (Berkeley) 06/06/85";
15 #endif not lint
16 
17 /*
18  * ranlib - create table of contents for archive; string table version
19  */
20 #include <sys/types.h>
21 #include <ar.h>
22 #include <ranlib.h>
23 #include <a.out.h>
24 #include <stdio.h>
25 
26 struct	ar_hdr	archdr;
27 #define	OARMAG 0177545
28 long	arsize;
29 struct	exec	exp;
30 FILE	*fi, *fo;
31 long	off, oldoff;
32 long	atol(), ftell();
33 #define TABSZ	6000
34 struct	ranlib tab[TABSZ];
35 int	tnum;
36 #define	STRTABSZ	75000
37 char	tstrtab[STRTABSZ];
38 int	tssiz;
39 char	*strtab;
40 int	ssiz;
41 int	new;
42 char	tempnm[] = "__.SYMDEF";
43 char	firstname[17];
44 
45 main(argc, argv)
46 char **argv;
47 {
48 	char cmdbuf[BUFSIZ];
49 	/* magbuf must be an int array so it is aligned on an int-ish
50 	   boundary, so that we may access its first word as an int! */
51 	int magbuf[(SARMAG+sizeof(int))/sizeof(int)];
52 	register int just_touch = 0;
53 
54 	/* check for the "-t" flag" */
55 	if (argc > 1 && strcmp(argv[1], "-t") == 0) {
56 		just_touch++;
57 		argc--;
58 		argv++;
59 	}
60 
61 	--argc;
62 	while(argc--) {
63 		fi = fopen(*++argv,"r");
64 		if (fi == NULL) {
65 			fprintf(stderr, "ranlib: cannot open %s\n", *argv);
66 			continue;
67 		}
68 		off = SARMAG;
69 		fread((char *)magbuf, 1, SARMAG, fi);
70 		if (strncmp((char *)magbuf, ARMAG, SARMAG)) {
71 			if (magbuf[0] == OARMAG)
72 				fprintf(stderr, "old format ");
73 			else
74 				fprintf(stderr, "not an ");
75 			fprintf(stderr, "archive: %s\n", *argv);
76 			continue;
77 		}
78 		if (just_touch) {
79 			register int	len;
80 
81 			fseek(fi, (long) SARMAG, 0);
82 			if (fread(cmdbuf, sizeof archdr.ar_name, 1, fi) != 1) {
83 				fprintf(stderr, "malformed archive: %s\n",
84 					*argv);
85 				continue;
86 			}
87 			len = strlen(tempnm);
88 			if (bcmp(cmdbuf, tempnm, len) != 0 ||
89 			    cmdbuf[len] != ' ') {
90 				fprintf(stderr, "no symbol table: %s\n", *argv);
91 				continue;
92 			}
93 			fclose(fi);
94 			fixdate(*++argv);
95 			continue;
96 		}
97 		fseek(fi, 0L, 0);
98 		new = tnum = 0;
99 		if (nextel(fi) == 0) {
100 			fclose(fi);
101 			continue;
102 		}
103 		do {
104 			long o;
105 			register n;
106 			struct nlist sym;
107 
108 			fread((char *)&exp, 1, sizeof(struct exec), fi);
109 			if (N_BADMAG(exp))
110 				continue;
111 			if (!strncmp(tempnm, archdr.ar_name, sizeof(archdr.ar_name)))
112 				continue;
113 			if (exp.a_syms == 0) {
114 				fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name);
115 				continue;
116 			}
117 			o = N_STROFF(exp) - sizeof (struct exec);
118 			if (ftell(fi)+o+sizeof(ssiz) >= off) {
119 				fprintf(stderr, "ranlib: warning: %s(%s): old format .o file\n", *argv, archdr.ar_name);
120 				continue;
121 			}
122 			fseek(fi, o, 1);
123 			fread((char *)&ssiz, 1, sizeof (ssiz), fi);
124 			if (ssiz < sizeof ssiz){
125 				/* sanity check */
126 				fprintf(stderr, "ranlib: warning: %s(%s): mangled string table\n", *argv, archdr.ar_name);
127 				continue;
128 			}
129 			strtab = (char *)calloc(1, ssiz);
130 			if (strtab == 0) {
131 				fprintf(stderr, "ranlib: ran out of memory\n");
132 				exit(1);
133 			}
134 			fread(strtab+sizeof(ssiz), ssiz - sizeof(ssiz), 1, fi);
135 			fseek(fi, -(exp.a_syms+ssiz), 1);
136 			n = exp.a_syms / sizeof(struct nlist);
137 			while (--n >= 0) {
138 				fread((char *)&sym, 1, sizeof(sym), fi);
139 				if (sym.n_un.n_strx == 0)
140 					continue;
141 				sym.n_un.n_name = strtab + sym.n_un.n_strx;
142 				if ((sym.n_type&N_EXT)==0)
143 					continue;
144 				switch (sym.n_type&N_TYPE) {
145 
146 				case N_UNDF:
147 					if (sym.n_value!=0)
148 						stash(&sym);
149 					continue;
150 
151 				default:
152 					stash(&sym);
153 					continue;
154 				}
155 			}
156 		} while(nextel(fi));
157 		new = fixsize();
158 		fclose(fi);
159 		fo = fopen(tempnm, "w");
160 		if(fo == NULL) {
161 			fprintf(stderr, "can't create temporary\n");
162 			exit(1);
163 		}
164 		tnum *= sizeof (struct ranlib);
165 		fwrite(&tnum, 1, sizeof (tnum), fo);
166 		tnum /= sizeof (struct ranlib);
167 		fwrite((char *)tab, tnum, sizeof(struct ranlib), fo);
168 		fwrite(&tssiz, 1, sizeof (tssiz), fo);
169 		fwrite(tstrtab, tssiz, 1, fo);
170 		fclose(fo);
171 		if(new)
172 			sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm);
173 		else
174 			sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm);
175 		if(system(cmdbuf))
176 			fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf);
177 		else
178 			fixdate(*argv);
179 		unlink(tempnm);
180 	}
181 	exit(0);
182 }
183 
184 nextel(af)
185 FILE *af;
186 {
187 	register r;
188 	register char *cp;
189 
190 	oldoff = off;
191 	fseek(af, off, 0);
192 	r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
193 	if (r != sizeof(struct ar_hdr))
194 		return(0);
195 	for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++)
196 		if (*cp == ' ')
197 			*cp = '\0';
198 	arsize = atol(archdr.ar_size);
199 	if (arsize & 1)
200 		arsize++;
201 	off = ftell(af) + arsize;
202 	return(1);
203 }
204 
205 stash(s)
206 	struct nlist *s;
207 {
208 	int i;
209 	register char *cp;
210 
211 	if(tnum >= TABSZ) {
212 		fprintf(stderr, "ranlib: symbol table overflow\n");
213 		exit(1);
214 	}
215 	tab[tnum].ran_un.ran_strx = tssiz;
216 	tab[tnum].ran_off = oldoff;
217 	for (cp = s->n_un.n_name; tstrtab[tssiz++] = *cp++;)
218 		if (tssiz > STRTABSZ) {
219 			fprintf(stderr, "ranlib: string table overflow\n");
220 			exit(1);
221 		}
222 	tnum++;
223 }
224 
225 fixsize()
226 {
227 	int i;
228 	off_t offdelta;
229 
230 	if (tssiz&1)
231 		tssiz++;
232 	offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) +
233 	    sizeof (tssiz) + tssiz;
234 	off = SARMAG;
235 	nextel(fi);
236 	if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) {
237 		new = 0;
238 		offdelta -= sizeof(archdr) + arsize;
239 	} else {
240 		new = 1;
241 		strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name));
242 	}
243 	for(i=0; i<tnum; i++)
244 		tab[i].ran_off += offdelta;
245 	return(new);
246 }
247 
248 /* patch time */
249 fixdate(s)
250 	char *s;
251 {
252 	long time();
253 	char buf[24];
254 	int fd;
255 
256 	fd = open(s, 1);
257 	if(fd < 0) {
258 		fprintf(stderr, "ranlib: can't reopen %s\n", s);
259 		return;
260 	}
261 	sprintf(buf, "%-*ld", sizeof(archdr.ar_date), time((long *)NULL)+5);
262 	lseek(fd, (long)SARMAG + ((char *)archdr.ar_date-(char *)&archdr), 0);
263 	write(fd, buf, sizeof(archdr.ar_date));
264 	close(fd);
265 }
266