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