Commit | Line | Data |
---|---|---|
d0aeaf5a DF |
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 | ||
34aa0635 | 7 | #ifndef lint |
d0aeaf5a DF |
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 | |
d93c729e | 14 | static char sccsid[] = "@(#)ranlib.c 5.4 (Berkeley) %G%"; |
d0aeaf5a DF |
15 | #endif not lint |
16 | ||
1372f8b5 BJ |
17 | /* |
18 | * ranlib - create table of contents for archive; string table version | |
19 | */ | |
20 | #include <sys/types.h> | |
2785c759 | 21 | #include <ar.h> |
1372f8b5 | 22 | #include <ranlib.h> |
2785c759 | 23 | #include <a.out.h> |
1372f8b5 BJ |
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(); | |
e62e46e3 | 33 | #define TABSZ 3000 |
1372f8b5 | 34 | int tnum; |
e62e46e3 | 35 | #define STRTABSZ 30000 |
1372f8b5 BJ |
36 | int tssiz; |
37 | char *strtab; | |
38 | int ssiz; | |
39 | int new; | |
d93c729e | 40 | char tempnm[] = RANLIBMAG; |
1372f8b5 | 41 | char firstname[17]; |
e62e46e3 KM |
42 | void stash(); |
43 | char *malloc(), *calloc(); | |
44 | ||
45 | /* | |
46 | * table segment definitions | |
47 | */ | |
48 | char *segalloc(); | |
49 | void segclean(); | |
50 | struct tabsegment { | |
51 | struct tabsegment *pnext; | |
52 | unsigned nelem; | |
53 | struct ranlib tab[TABSZ]; | |
54 | } tabbase, *ptabseg; | |
55 | struct strsegment { | |
56 | struct strsegment *pnext; | |
57 | unsigned nelem; | |
58 | char stab[STRTABSZ]; | |
59 | } strbase, *pstrseg; | |
1372f8b5 BJ |
60 | |
61 | main(argc, argv) | |
62 | char **argv; | |
63 | { | |
64 | char cmdbuf[BUFSIZ]; | |
2a7750c9 | 65 | /* magbuf must be an int array so it is aligned on an int-ish |
66 | boundary, so that we may access its first word as an int! */ | |
67 | int magbuf[(SARMAG+sizeof(int))/sizeof(int)]; | |
30c310a4 | 68 | register int just_touch = 0; |
e62e46e3 KM |
69 | register struct tabsegment *ptab; |
70 | register struct strsegment *pstr; | |
30c310a4 KM |
71 | |
72 | /* check for the "-t" flag" */ | |
73 | if (argc > 1 && strcmp(argv[1], "-t") == 0) { | |
74 | just_touch++; | |
75 | argc--; | |
76 | argv++; | |
77 | } | |
1372f8b5 BJ |
78 | |
79 | --argc; | |
80 | while(argc--) { | |
81 | fi = fopen(*++argv,"r"); | |
82 | if (fi == NULL) { | |
83 | fprintf(stderr, "ranlib: cannot open %s\n", *argv); | |
84 | continue; | |
85 | } | |
86 | off = SARMAG; | |
2a7750c9 | 87 | fread((char *)magbuf, 1, SARMAG, fi); |
88 | if (strncmp((char *)magbuf, ARMAG, SARMAG)) { | |
89 | if (magbuf[0] == OARMAG) | |
1372f8b5 BJ |
90 | fprintf(stderr, "old format "); |
91 | else | |
92 | fprintf(stderr, "not an "); | |
93 | fprintf(stderr, "archive: %s\n", *argv); | |
94 | continue; | |
95 | } | |
62ed4d47 KM |
96 | if (just_touch) { |
97 | register int len; | |
98 | ||
99 | fseek(fi, (long) SARMAG, 0); | |
100 | if (fread(cmdbuf, sizeof archdr.ar_name, 1, fi) != 1) { | |
101 | fprintf(stderr, "malformed archive: %s\n", | |
102 | *argv); | |
103 | continue; | |
104 | } | |
105 | len = strlen(tempnm); | |
106 | if (bcmp(cmdbuf, tempnm, len) != 0 || | |
107 | cmdbuf[len] != ' ') { | |
108 | fprintf(stderr, "no symbol table: %s\n", *argv); | |
109 | continue; | |
110 | } | |
111 | fclose(fi); | |
c75e8e88 | 112 | fixdate(*argv); |
62ed4d47 KM |
113 | continue; |
114 | } | |
1372f8b5 | 115 | fseek(fi, 0L, 0); |
e62e46e3 KM |
116 | new = tssiz = tnum = 0; |
117 | segclean(); | |
1372f8b5 BJ |
118 | if (nextel(fi) == 0) { |
119 | fclose(fi); | |
120 | continue; | |
121 | } | |
122 | do { | |
123 | long o; | |
124 | register n; | |
125 | struct nlist sym; | |
126 | ||
127 | fread((char *)&exp, 1, sizeof(struct exec), fi); | |
128 | if (N_BADMAG(exp)) | |
129 | continue; | |
dcacd57d RC |
130 | if (!strncmp(tempnm, archdr.ar_name, sizeof(archdr.ar_name))) |
131 | continue; | |
1372f8b5 BJ |
132 | if (exp.a_syms == 0) { |
133 | fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name); | |
fd894872 | 134 | continue; |
1372f8b5 BJ |
135 | } |
136 | o = N_STROFF(exp) - sizeof (struct exec); | |
137 | if (ftell(fi)+o+sizeof(ssiz) >= off) { | |
dcacd57d RC |
138 | fprintf(stderr, "ranlib: warning: %s(%s): old format .o file\n", *argv, archdr.ar_name); |
139 | continue; | |
1372f8b5 BJ |
140 | } |
141 | fseek(fi, o, 1); | |
142 | fread((char *)&ssiz, 1, sizeof (ssiz), fi); | |
2a7750c9 | 143 | if (ssiz < sizeof ssiz){ |
144 | /* sanity check */ | |
dcacd57d RC |
145 | fprintf(stderr, "ranlib: warning: %s(%s): mangled string table\n", *argv, archdr.ar_name); |
146 | continue; | |
2a7750c9 | 147 | } |
1372f8b5 BJ |
148 | strtab = (char *)calloc(1, ssiz); |
149 | if (strtab == 0) { | |
150 | fprintf(stderr, "ranlib: ran out of memory\n"); | |
151 | exit(1); | |
152 | } | |
153 | fread(strtab+sizeof(ssiz), ssiz - sizeof(ssiz), 1, fi); | |
154 | fseek(fi, -(exp.a_syms+ssiz), 1); | |
155 | n = exp.a_syms / sizeof(struct nlist); | |
156 | while (--n >= 0) { | |
157 | fread((char *)&sym, 1, sizeof(sym), fi); | |
158 | if (sym.n_un.n_strx == 0) | |
159 | continue; | |
160 | sym.n_un.n_name = strtab + sym.n_un.n_strx; | |
161 | if ((sym.n_type&N_EXT)==0) | |
162 | continue; | |
163 | switch (sym.n_type&N_TYPE) { | |
164 | ||
165 | case N_UNDF: | |
166 | if (sym.n_value!=0) | |
167 | stash(&sym); | |
168 | continue; | |
169 | ||
170 | default: | |
171 | stash(&sym); | |
172 | continue; | |
173 | } | |
174 | } | |
e62e46e3 | 175 | free(strtab); |
1372f8b5 BJ |
176 | } while(nextel(fi)); |
177 | new = fixsize(); | |
178 | fclose(fi); | |
179 | fo = fopen(tempnm, "w"); | |
180 | if(fo == NULL) { | |
181 | fprintf(stderr, "can't create temporary\n"); | |
182 | exit(1); | |
183 | } | |
184 | tnum *= sizeof (struct ranlib); | |
185 | fwrite(&tnum, 1, sizeof (tnum), fo); | |
186 | tnum /= sizeof (struct ranlib); | |
e62e46e3 KM |
187 | ptab = &tabbase; |
188 | do { | |
189 | fwrite((char *)ptab->tab, ptab->nelem, | |
190 | sizeof(struct ranlib), fo); | |
191 | } while (ptab = ptab->pnext); | |
1372f8b5 | 192 | fwrite(&tssiz, 1, sizeof (tssiz), fo); |
e62e46e3 KM |
193 | pstr = &strbase; |
194 | do { | |
195 | fwrite(pstr->stab, pstr->nelem, 1, fo); | |
196 | tssiz -= pstr->nelem; | |
197 | } while (pstr = pstr->pnext); | |
198 | /* pad with nulls */ | |
199 | while (tssiz--) putc('\0', fo); | |
1372f8b5 BJ |
200 | fclose(fo); |
201 | if(new) | |
2785c759 | 202 | sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm); |
1372f8b5 | 203 | else |
2785c759 | 204 | sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm); |
1372f8b5 BJ |
205 | if(system(cmdbuf)) |
206 | fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf); | |
207 | else | |
208 | fixdate(*argv); | |
209 | unlink(tempnm); | |
210 | } | |
211 | exit(0); | |
212 | } | |
213 | ||
214 | nextel(af) | |
215 | FILE *af; | |
216 | { | |
217 | register r; | |
218 | register char *cp; | |
219 | ||
220 | oldoff = off; | |
221 | fseek(af, off, 0); | |
222 | r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af); | |
223 | if (r != sizeof(struct ar_hdr)) | |
224 | return(0); | |
225 | for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++) | |
226 | if (*cp == ' ') | |
227 | *cp = '\0'; | |
228 | arsize = atol(archdr.ar_size); | |
229 | if (arsize & 1) | |
230 | arsize++; | |
231 | off = ftell(af) + arsize; | |
232 | return(1); | |
233 | } | |
234 | ||
e62e46e3 | 235 | void |
1372f8b5 BJ |
236 | stash(s) |
237 | struct nlist *s; | |
238 | { | |
1372f8b5 | 239 | register char *cp; |
e62e46e3 KM |
240 | register char *strtab; |
241 | register strsiz; | |
242 | register struct ranlib *tab; | |
243 | register tabsiz; | |
1372f8b5 | 244 | |
e62e46e3 KM |
245 | if (ptabseg->nelem >= TABSZ) { |
246 | /* allocate a new symbol table segment */ | |
247 | ptabseg = ptabseg->pnext = | |
248 | (struct tabsegment *) segalloc(sizeof(struct tabsegment)); | |
249 | ptabseg->pnext = NULL; | |
250 | ptabseg->nelem = 0; | |
1372f8b5 | 251 | } |
e62e46e3 KM |
252 | tabsiz = ptabseg->nelem; |
253 | tab = ptabseg->tab; | |
254 | ||
255 | if (pstrseg->nelem >= STRTABSZ) { | |
256 | /* allocate a new string table segment */ | |
257 | pstrseg = pstrseg->pnext = | |
258 | (struct strsegment *) segalloc(sizeof(struct strsegment)); | |
259 | pstrseg->pnext = NULL; | |
260 | pstrseg->nelem = 0; | |
261 | } | |
262 | strsiz = pstrseg->nelem; | |
263 | strtab = pstrseg->stab; | |
264 | ||
265 | tab[tabsiz].ran_un.ran_strx = tssiz; | |
266 | tab[tabsiz].ran_off = oldoff; | |
267 | redo: | |
268 | for (cp = s->n_un.n_name; strtab[strsiz++] = *cp++;) | |
269 | if (strsiz >= STRTABSZ) { | |
270 | /* allocate a new string table segment */ | |
271 | pstrseg = pstrseg->pnext = | |
272 | (struct strsegment *) segalloc(sizeof(struct strsegment)); | |
273 | pstrseg->pnext = NULL; | |
274 | strsiz = pstrseg->nelem = 0; | |
275 | strtab = pstrseg->stab; | |
276 | goto redo; | |
1372f8b5 | 277 | } |
e62e46e3 KM |
278 | |
279 | tssiz += strsiz - pstrseg->nelem; /* length of the string */ | |
280 | pstrseg->nelem = strsiz; | |
1372f8b5 | 281 | tnum++; |
e62e46e3 KM |
282 | ptabseg->nelem++; |
283 | } | |
284 | ||
285 | /* allocate a zero filled segment of size bytes */ | |
286 | char * | |
287 | segalloc(size) | |
288 | unsigned size; | |
289 | { | |
290 | char *pseg = NULL; | |
291 | ||
292 | pseg = malloc(size); | |
293 | if (pseg == NULL) { | |
294 | fprintf(stderr, "ranlib: ran out of memeory\n"); | |
295 | exit(1); | |
296 | } | |
297 | return(pseg); | |
298 | } | |
299 | ||
300 | /* free segments */ | |
301 | void | |
302 | segclean() | |
303 | { | |
304 | register struct tabsegment *ptab; | |
305 | register struct strsegment *pstr; | |
306 | ||
307 | /* | |
308 | * symbol table | |
309 | * | |
310 | * The first entry is static. | |
311 | */ | |
312 | ptabseg = &tabbase; | |
313 | ptab = ptabseg->pnext; | |
314 | while (ptabseg = ptab) { | |
315 | ptab = ptabseg->pnext; | |
316 | free((char *)ptabseg); | |
317 | } | |
318 | ptabseg = &tabbase; | |
319 | ptabseg->pnext = NULL; | |
320 | ptabseg->nelem = 0; | |
321 | ||
322 | /* | |
323 | * string table | |
324 | * | |
325 | * The first entry is static. | |
326 | */ | |
327 | pstrseg = &strbase; | |
328 | pstr = pstrseg->pnext; | |
329 | while (pstrseg = pstr) { | |
330 | pstr = pstrseg->pnext; | |
331 | free((char *)pstrseg); | |
332 | } | |
333 | pstrseg = &strbase; | |
334 | pstrseg->pnext = NULL; | |
335 | pstrseg->nelem = 0; | |
1372f8b5 BJ |
336 | } |
337 | ||
338 | fixsize() | |
339 | { | |
340 | int i; | |
341 | off_t offdelta; | |
e62e46e3 | 342 | register struct tabsegment *ptab; |
1372f8b5 BJ |
343 | |
344 | if (tssiz&1) | |
345 | tssiz++; | |
346 | offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) + | |
347 | sizeof (tssiz) + tssiz; | |
348 | off = SARMAG; | |
349 | nextel(fi); | |
350 | if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) { | |
351 | new = 0; | |
352 | offdelta -= sizeof(archdr) + arsize; | |
353 | } else { | |
354 | new = 1; | |
355 | strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name)); | |
356 | } | |
e62e46e3 KM |
357 | ptab = &tabbase; |
358 | do { | |
359 | for (i = 0; i < ptab->nelem; i++) | |
360 | ptab->tab[i].ran_off += offdelta; | |
361 | } while (ptab = ptab->pnext); | |
1372f8b5 BJ |
362 | return(new); |
363 | } | |
364 | ||
365 | /* patch time */ | |
366 | fixdate(s) | |
367 | char *s; | |
368 | { | |
369 | long time(); | |
370 | char buf[24]; | |
371 | int fd; | |
372 | ||
373 | fd = open(s, 1); | |
374 | if(fd < 0) { | |
375 | fprintf(stderr, "ranlib: can't reopen %s\n", s); | |
376 | return; | |
377 | } | |
378 | sprintf(buf, "%-*ld", sizeof(archdr.ar_date), time((long *)NULL)+5); | |
379 | lseek(fd, (long)SARMAG + ((char *)archdr.ar_date-(char *)&archdr), 0); | |
380 | write(fd, buf, sizeof(archdr.ar_date)); | |
381 | close(fd); | |
382 | } |