2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Hugh Smith at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)build.c 8.1 (Berkeley) 6/6/93
37 * $FreeBSD: src/usr.bin/ranlib/build.c,v 1.7 1999/08/28 01:05:01 peter Exp $
38 * $DragonFly: src/usr.bin/ranlib/build.c,v 1.4 2004/07/24 13:45:44 eirikn Exp $
41 #include <sys/types.h>
56 extern int tmp( void );
57 extern void error( char * );
58 extern void badfmt( void );
59 extern void settime( int );
61 extern CHDR chdr
; /* converted header */
62 extern char *archive
; /* archive name */
63 extern char *tname
; /* temporary file "name" */
65 typedef struct _rlib
{
66 struct _rlib
*next
; /* next structure */
67 off_t pos
; /* offset of defining archive file */
68 char *sym
; /* symbol */
69 int symlen
; /* strlen(sym) */
75 long symcnt
; /* symbol count */
76 long tsymlen
; /* total string length */
78 static void rexec(int, int);
79 static void symobj(void);
88 afd
= open_archive(O_RDWR
);
89 fp
= fdopen(afd
, "r+");
92 SETCF(afd
, archive
, tfd
, tname
, RPAD
|WPAD
);
94 /* Read through the archive, creating list of symbols. */
97 while(get_arobj(afd
)) {
98 if (!strcmp(chdr
.name
, RANLIBMAG
)) {
103 put_arobj(&cf
, (struct stat
*)NULL
);
107 /* Create the symbol table. */
110 /* Copy the saved objects into the archive. */
111 size
= lseek(tfd
, (off_t
)0, SEEK_CUR
);
112 (void)lseek(tfd
, (off_t
)0, SEEK_SET
);
113 SETCF(tfd
, tname
, afd
, archive
, WPAD
);
115 (void)ftruncate(afd
, lseek(afd
, (off_t
)0, SEEK_CUR
));
126 * Read the exec structure; ignore any files that don't look
130 rexec(int rfd
, int wfd
)
134 register int nr
, symlen
;
135 register char *strtab
= 0, *sym
;
142 /* Get current offsets for original and tmp files. */
143 r_off
= lseek(rfd
, (off_t
)0, SEEK_CUR
);
144 w_off
= lseek(wfd
, (off_t
)0, SEEK_CUR
);
146 /* Read in exec structure. */
147 nr
= read(rfd
, &ebuf
, sizeof(struct exec
));
148 if (nr
!= sizeof(struct exec
))
151 /* Check magic number and symbol count. */
152 if (N_BADMAG(ebuf
) || ebuf
.a_syms
== 0)
155 /* Seek to string table. */
156 if (lseek(rfd
, r_off
+ N_STROFF(ebuf
), SEEK_SET
) == (off_t
)-1)
159 /* Read in size of the string table. */
160 nr
= read(rfd
, &strsize
, sizeof(strsize
));
161 if (nr
!= sizeof(strsize
))
164 /* Read in the string table. */
165 strsize
-= sizeof(strsize
);
166 strtab
= emalloc(strsize
);
167 nr
= read(rfd
, strtab
, strsize
);
174 /* Seek to symbol table. */
175 if (fseek(fp
, (long)r_off
+ N_SYMOFF(ebuf
), SEEK_SET
))
178 /* For each symbol read the nlist entry and save it as necessary. */
179 nsyms
= ebuf
.a_syms
/ sizeof(struct nlist
);
181 if (!fread(&nl
, sizeof(struct nlist
), 1, fp
)) {
187 /* Ignore if no name or local. */
188 if (!nl
.n_un
.n_strx
|| !(nl
.n_type
& N_EXT
))
192 * If the symbol is an undefined external and the n_value
193 * field is non-zero, keep it.
195 if ((nl
.n_type
& N_TYPE
) == N_UNDF
&& !nl
.n_value
)
198 /* First four bytes are the table size. */
199 sym
= strtab
+ nl
.n_un
.n_strx
- sizeof(long);
200 symlen
= strlen(sym
) + 1;
202 rp
= (RLIB
*)emalloc(sizeof(RLIB
));
203 rp
->sym
= (char *)emalloc(symlen
);
204 bcopy(sym
, rp
->sym
, symlen
);
208 /* Build in forward order for "ar -m" command. */
217 bad1
: (void)lseek(rfd
, r_off
, SEEK_SET
);
222 * Write the symbol table into the archive, computing offsets as
228 register RLIB
*rp
, *rpnext
;
232 char hb
[sizeof(struct ar_hdr
) + 1], pad
;
234 /* Rewind the archive, leaving the magic number. */
235 if (fseek(fp
, (long)SARMAG
, SEEK_SET
))
238 /* Size of the ranlib archive file, pad if necessary. */
239 ransize
= sizeof(long) +
240 symcnt
* sizeof(struct ranlib
) + sizeof(long) + tsymlen
;
247 /* Put out the ranlib archive file header. */
248 #define DEFMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
249 (void)sprintf(hb
, HDR2
, RANLIBMAG
, 0L, getuid(), getgid(),
250 DEFMODE
& ~umask(0), ransize
, ARFMAG
);
251 if (!fwrite(hb
, sizeof(struct ar_hdr
), 1, fp
))
254 /* First long is the size of the ranlib structure section. */
255 size
= symcnt
* sizeof(struct ranlib
);
256 if (!fwrite(&size
, sizeof(size
), 1, fp
))
259 /* Offset of the first archive file. */
260 size
= SARMAG
+ sizeof(struct ar_hdr
) + ransize
;
263 * Write out the ranlib structures. The offset into the string
264 * table is cumulative, the offset into the archive is the value
265 * set in rexec() plus the offset to the first archive file.
267 for (rp
= rhead
, stroff
= 0; rp
; rp
= rp
->next
) {
268 rn
.ran_un
.ran_strx
= stroff
;
269 stroff
+= rp
->symlen
;
270 rn
.ran_off
= size
+ rp
->pos
;
271 if (!fwrite(&rn
, sizeof(struct ranlib
), 1, fp
))
275 /* Second long is the size of the string table. */
276 if (!fwrite(&tsymlen
, sizeof(tsymlen
), 1, fp
))
279 /* Write out the string table. */
280 for (rp
= rhead
; rp
; rp
= rpnext
) {
281 if (!fwrite(rp
->sym
, rp
->symlen
, 1, fp
))
289 if (pad
&& !fwrite(&pad
, sizeof(pad
), 1, fp
))