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