Commit | Line | Data |
---|---|---|
d9256bab | 1 | /*- |
80baa34f KB |
2 | * Copyright (c) 1990, 1993 |
3 | * The Regents of the University of California. All rights reserved. | |
d9256bab KB |
4 | * |
5 | * This code is derived from software contributed to Berkeley by | |
6 | * Hugh Smith at The University of Guelph. | |
7 | * | |
8 | * %sccs.include.redist.c% | |
9 | */ | |
10 | ||
11 | #ifndef lint | |
80baa34f | 12 | static char sccsid[] = "@(#)build.c 8.1 (Berkeley) %G%"; |
d9256bab KB |
13 | #endif /* not lint */ |
14 | ||
15 | #include <sys/types.h> | |
16 | #include <sys/errno.h> | |
17 | #include <sys/stat.h> | |
7e464d18 | 18 | |
d9256bab | 19 | #include <a.out.h> |
d9256bab | 20 | #include <ar.h> |
7e464d18 KB |
21 | #include <dirent.h> |
22 | #include <fcntl.h> | |
d9256bab KB |
23 | #include <ranlib.h> |
24 | #include <stdio.h> | |
7e464d18 KB |
25 | #include <unistd.h> |
26 | ||
27 | #include "archive.h" | |
d9256bab KB |
28 | |
29 | extern CHDR chdr; /* converted header */ | |
30 | extern char *archive; /* archive name */ | |
31 | extern char *tname; /* temporary file "name" */ | |
32 | ||
33 | typedef struct _rlib { | |
34 | struct _rlib *next; /* next structure */ | |
35 | off_t pos; /* offset of defining archive file */ | |
36 | char *sym; /* symbol */ | |
37 | int symlen; /* strlen(sym) */ | |
38 | } RLIB; | |
39 | RLIB *rhead, **pnext; | |
40 | ||
41 | FILE *fp; | |
7e464d18 KB |
42 | |
43 | long symcnt; /* symbol count */ | |
44 | long tsymlen; /* total string length */ | |
45 | ||
46 | static void rexec __P((int, int)); | |
47 | static void symobj __P((void)); | |
d9256bab KB |
48 | |
49 | build() | |
50 | { | |
51 | CF cf; | |
52 | int afd, tfd; | |
53 | off_t size; | |
54 | ||
55 | afd = open_archive(O_RDWR); | |
56 | fp = fdopen(afd, "r+"); | |
57 | tfd = tmp(); | |
58 | ||
59 | SETCF(afd, archive, tfd, tname, RPAD|WPAD); | |
60 | ||
61 | /* Read through the archive, creating list of symbols. */ | |
62 | pnext = &rhead; | |
7e464d18 | 63 | symcnt = tsymlen = 0; |
f10e4796 | 64 | while(get_arobj(afd)) { |
d9256bab | 65 | if (!strcmp(chdr.name, RANLIBMAG)) { |
f10e4796 | 66 | skip_arobj(afd); |
d9256bab KB |
67 | continue; |
68 | } | |
69 | rexec(afd, tfd); | |
f10e4796 | 70 | put_arobj(&cf, (struct stat *)NULL); |
d9256bab KB |
71 | } |
72 | *pnext = NULL; | |
73 | ||
74 | /* Create the symbol table. */ | |
75 | symobj(); | |
76 | ||
77 | /* Copy the saved objects into the archive. */ | |
78 | size = lseek(tfd, (off_t)0, SEEK_CUR); | |
79 | (void)lseek(tfd, (off_t)0, SEEK_SET); | |
80 | SETCF(tfd, tname, afd, archive, RPAD|WPAD); | |
f10e4796 | 81 | copy_ar(&cf, size); |
d9256bab KB |
82 | (void)ftruncate(afd, lseek(afd, (off_t)0, SEEK_CUR)); |
83 | (void)close(tfd); | |
84 | ||
85 | /* Set the time. */ | |
86 | settime(afd); | |
87 | close_archive(afd); | |
88 | return(0); | |
89 | } | |
90 | ||
d9256bab KB |
91 | /* |
92 | * rexec | |
93 | * Read the exec structure; ignore any files that don't look | |
94 | * exactly right. | |
95 | */ | |
d6db39e0 | 96 | static void |
d9256bab KB |
97 | rexec(rfd, wfd) |
98 | register int rfd; | |
99 | int wfd; | |
100 | { | |
101 | register RLIB *rp; | |
102 | register long nsyms; | |
103 | register int nr, symlen; | |
104 | register char *strtab, *sym; | |
105 | struct exec ebuf; | |
106 | struct nlist nl; | |
107 | off_t r_off, w_off; | |
108 | long strsize; | |
109 | void *emalloc(); | |
110 | ||
111 | /* Get current offsets for original and tmp files. */ | |
112 | r_off = lseek(rfd, (off_t)0, SEEK_CUR); | |
113 | w_off = lseek(wfd, (off_t)0, SEEK_CUR); | |
114 | ||
115 | /* Read in exec structure. */ | |
eb373ab0 | 116 | nr = read(rfd, &ebuf, sizeof(struct exec)); |
d9256bab KB |
117 | if (nr != sizeof(struct exec)) |
118 | goto badread; | |
119 | ||
120 | /* Check magic number and symbol count. */ | |
121 | if (N_BADMAG(ebuf) || ebuf.a_syms == 0) | |
122 | goto bad1; | |
123 | ||
124 | /* Seek to string table. */ | |
eb373ab0 | 125 | if (lseek(rfd, r_off + N_STROFF(ebuf), SEEK_SET) == (off_t)-1) |
d9256bab KB |
126 | error(archive); |
127 | ||
128 | /* Read in size of the string table. */ | |
eb373ab0 | 129 | nr = read(rfd, &strsize, sizeof(strsize)); |
d9256bab KB |
130 | if (nr != sizeof(strsize)) |
131 | goto badread; | |
132 | ||
133 | /* Read in the string table. */ | |
134 | strsize -= sizeof(strsize); | |
eb373ab0 | 135 | strtab = emalloc(strsize); |
d9256bab KB |
136 | nr = read(rfd, strtab, strsize); |
137 | if (nr != strsize) { | |
138 | badread: if (nr < 0) | |
139 | error(archive); | |
140 | goto bad2; | |
141 | } | |
142 | ||
143 | /* Seek to symbol table. */ | |
3c2c28cc | 144 | if (fseek(fp, (long)r_off + N_SYMOFF(ebuf), SEEK_SET)) |
d9256bab KB |
145 | goto bad2; |
146 | ||
147 | /* For each symbol read the nlist entry and save it as necessary. */ | |
148 | nsyms = ebuf.a_syms / sizeof(struct nlist); | |
149 | while (nsyms--) { | |
eb373ab0 | 150 | if (!fread(&nl, sizeof(struct nlist), 1, fp)) { |
d9256bab KB |
151 | if (feof(fp)) |
152 | badfmt(); | |
153 | error(archive); | |
154 | } | |
155 | ||
156 | /* Ignore if no name or local. */ | |
157 | if (!nl.n_un.n_strx || !(nl.n_type & N_EXT)) | |
158 | continue; | |
159 | ||
160 | /* | |
161 | * If the symbol is an undefined external and the n_value | |
162 | * field is non-zero, keep it. | |
163 | */ | |
164 | if ((nl.n_type & N_TYPE) == N_UNDF && !nl.n_value) | |
165 | continue; | |
166 | ||
167 | /* First four bytes are the table size. */ | |
168 | sym = strtab + nl.n_un.n_strx - sizeof(long); | |
169 | symlen = strlen(sym) + 1; | |
170 | ||
171 | rp = (RLIB *)emalloc(sizeof(RLIB)); | |
172 | rp->sym = (char *)emalloc(symlen); | |
173 | bcopy(sym, rp->sym, symlen); | |
174 | rp->symlen = symlen; | |
175 | rp->pos = w_off; | |
176 | ||
177 | /* Build in forward order for "ar -m" command. */ | |
178 | *pnext = rp; | |
179 | pnext = &rp->next; | |
180 | ||
181 | ++symcnt; | |
182 | tsymlen += symlen; | |
183 | } | |
184 | ||
185 | bad2: free(strtab); | |
eb373ab0 | 186 | bad1: (void)lseek(rfd, r_off, SEEK_SET); |
d9256bab KB |
187 | } |
188 | ||
189 | /* | |
190 | * symobj -- | |
191 | * Write the symbol table into the archive, computing offsets as | |
192 | * writing. | |
193 | */ | |
d6db39e0 | 194 | static void |
d9256bab KB |
195 | symobj() |
196 | { | |
197 | register RLIB *rp; | |
198 | struct ranlib rn; | |
eb373ab0 KB |
199 | off_t ransize; |
200 | long size, stroff; | |
d9256bab | 201 | char hb[sizeof(struct ar_hdr) + 1], pad; |
d9256bab KB |
202 | |
203 | /* Rewind the archive, leaving the magic number. */ | |
3c2c28cc | 204 | if (fseek(fp, (long)SARMAG, SEEK_SET)) |
d9256bab KB |
205 | error(archive); |
206 | ||
207 | /* Size of the ranlib archive file, pad if necessary. */ | |
208 | ransize = sizeof(long) + | |
209 | symcnt * sizeof(struct ranlib) + sizeof(long) + tsymlen; | |
210 | if (ransize & 01) { | |
211 | ++ransize; | |
212 | pad = '\n'; | |
213 | } else | |
214 | pad = '\0'; | |
215 | ||
216 | /* Put out the ranlib archive file header. */ | |
217 | #define DEFMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) | |
218 | (void)sprintf(hb, HDR2, RANLIBMAG, 0L, getuid(), getgid(), | |
d6db39e0 | 219 | DEFMODE & ~umask(0), ransize, ARFMAG); |
d9256bab KB |
220 | if (!fwrite(hb, sizeof(struct ar_hdr), 1, fp)) |
221 | error(tname); | |
222 | ||
223 | /* First long is the size of the ranlib structure section. */ | |
224 | size = symcnt * sizeof(struct ranlib); | |
eb373ab0 | 225 | if (!fwrite(&size, sizeof(size), 1, fp)) |
d9256bab KB |
226 | error(tname); |
227 | ||
228 | /* Offset of the first archive file. */ | |
229 | size = SARMAG + sizeof(struct ar_hdr) + ransize; | |
230 | ||
231 | /* | |
232 | * Write out the ranlib structures. The offset into the string | |
233 | * table is cumulative, the offset into the archive is the value | |
234 | * set in rexec() plus the offset to the first archive file. | |
235 | */ | |
236 | for (rp = rhead, stroff = 0; rp; rp = rp->next) { | |
237 | rn.ran_un.ran_strx = stroff; | |
238 | stroff += rp->symlen; | |
239 | rn.ran_off = size + rp->pos; | |
eb373ab0 | 240 | if (!fwrite(&rn, sizeof(struct ranlib), 1, fp)) |
d9256bab KB |
241 | error(archive); |
242 | } | |
243 | ||
244 | /* Second long is the size of the string table. */ | |
eb373ab0 | 245 | if (!fwrite(&tsymlen, sizeof(tsymlen), 1, fp)) |
d9256bab KB |
246 | error(tname); |
247 | ||
248 | /* Write out the string table. */ | |
249 | for (rp = rhead; rp; rp = rp->next) | |
250 | if (!fwrite(rp->sym, rp->symlen, 1, fp)) | |
251 | error(tname); | |
252 | ||
253 | if (pad && !fwrite(&pad, sizeof(pad), 1, fp)) | |
254 | error(tname); | |
255 | ||
256 | (void)fflush(fp); | |
257 | } |