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