1*10d63b7dSRichard Lowe /*
2*10d63b7dSRichard Lowe * CDDL HEADER START
3*10d63b7dSRichard Lowe *
4*10d63b7dSRichard Lowe * The contents of this file are subject to the terms of the
5*10d63b7dSRichard Lowe * Common Development and Distribution License (the "License").
6*10d63b7dSRichard Lowe * You may not use this file except in compliance with the License.
7*10d63b7dSRichard Lowe *
8*10d63b7dSRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10d63b7dSRichard Lowe * or http://www.opensolaris.org/os/licensing.
10*10d63b7dSRichard Lowe * See the License for the specific language governing permissions
11*10d63b7dSRichard Lowe * and limitations under the License.
12*10d63b7dSRichard Lowe *
13*10d63b7dSRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
14*10d63b7dSRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10d63b7dSRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
16*10d63b7dSRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
17*10d63b7dSRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
18*10d63b7dSRichard Lowe *
19*10d63b7dSRichard Lowe * CDDL HEADER END
20*10d63b7dSRichard Lowe */
21*10d63b7dSRichard Lowe /*
22*10d63b7dSRichard Lowe * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23*10d63b7dSRichard Lowe * Use is subject to license terms.
24*10d63b7dSRichard Lowe */
25*10d63b7dSRichard Lowe
26*10d63b7dSRichard Lowe /*
27*10d63b7dSRichard Lowe * ar.c
28*10d63b7dSRichard Lowe *
29*10d63b7dSRichard Lowe * Deal with the lib.a(member.o) and lib.a((entry-point)) notations
30*10d63b7dSRichard Lowe *
31*10d63b7dSRichard Lowe * Look inside archives for notations a(b) and a((b))
32*10d63b7dSRichard Lowe * a(b) is file member b in archive a
33*10d63b7dSRichard Lowe * a((b)) is entry point b in object archive a
34*10d63b7dSRichard Lowe *
35*10d63b7dSRichard Lowe * For 6.0, create a make which can understand all archive
36*10d63b7dSRichard Lowe * formats. This is kind of tricky, and <ar.h> isnt any help.
37*10d63b7dSRichard Lowe */
38*10d63b7dSRichard Lowe
39*10d63b7dSRichard Lowe /*
40*10d63b7dSRichard Lowe * Included files
41*10d63b7dSRichard Lowe */
42*10d63b7dSRichard Lowe #include <alloca.h> /* alloca() */
43*10d63b7dSRichard Lowe #include <ar.h>
44*10d63b7dSRichard Lowe #include <errno.h> /* errno */
45*10d63b7dSRichard Lowe #include <fcntl.h> /* open() */
46*10d63b7dSRichard Lowe #include <libintl.h>
47*10d63b7dSRichard Lowe #include <mk/defs.h>
48*10d63b7dSRichard Lowe #include <mksh/misc.h> /* retmem_mb() */
49*10d63b7dSRichard Lowe
50*10d63b7dSRichard Lowe struct ranlib {
51*10d63b7dSRichard Lowe union {
52*10d63b7dSRichard Lowe off_t ran_strx; /* string table index of */
53*10d63b7dSRichard Lowe char *ran_name; /* symbol defined by */
54*10d63b7dSRichard Lowe } ran_un;
55*10d63b7dSRichard Lowe off_t ran_off; /* library member at this offset */
56*10d63b7dSRichard Lowe };
57*10d63b7dSRichard Lowe
58*10d63b7dSRichard Lowe #include <unistd.h> /* close() */
59*10d63b7dSRichard Lowe
60*10d63b7dSRichard Lowe
61*10d63b7dSRichard Lowe /*
62*10d63b7dSRichard Lowe * Defined macros
63*10d63b7dSRichard Lowe */
64*10d63b7dSRichard Lowe #ifndef S5EMUL
65*10d63b7dSRichard Lowe #undef BITSPERBYTE
66*10d63b7dSRichard Lowe #define BITSPERBYTE 8
67*10d63b7dSRichard Lowe #endif
68*10d63b7dSRichard Lowe
69*10d63b7dSRichard Lowe /*
70*10d63b7dSRichard Lowe * Defines for all the different archive formats. See next comment
71*10d63b7dSRichard Lowe * block for justification for not using <ar.h>s versions.
72*10d63b7dSRichard Lowe */
73*10d63b7dSRichard Lowe #define AR_5_MAGIC "<ar>" /* 5.0 format magic string */
74*10d63b7dSRichard Lowe #define AR_5_MAGIC_LENGTH 4 /* 5.0 format string length */
75*10d63b7dSRichard Lowe
76*10d63b7dSRichard Lowe #define AR_PORT_MAGIC "!<arch>\n" /* Port. (6.0) magic string */
77*10d63b7dSRichard Lowe #define AR_PORT_MAGIC_LENGTH 8 /* Port. (6.0) string length */
78*10d63b7dSRichard Lowe #define AR_PORT_END_MAGIC "`\n" /* Port. (6.0) end of header */
79*10d63b7dSRichard Lowe #define AR_PORT_WORD 4 /* Port. (6.0) 'word' length */
80*10d63b7dSRichard Lowe
81*10d63b7dSRichard Lowe /*
82*10d63b7dSRichard Lowe * typedefs & structs
83*10d63b7dSRichard Lowe */
84*10d63b7dSRichard Lowe /*
85*10d63b7dSRichard Lowe * These are the archive file headers for the formats. Note
86*10d63b7dSRichard Lowe * that it really doesnt matter if these structures are defined
87*10d63b7dSRichard Lowe * here. They are correct as of the respective archive format
88*10d63b7dSRichard Lowe * releases. If the archive format is changed, then since backwards
89*10d63b7dSRichard Lowe * compatability is the desired behavior, a new structure is added
90*10d63b7dSRichard Lowe * to the list.
91*10d63b7dSRichard Lowe */
92*10d63b7dSRichard Lowe typedef struct { /* 5.0 ar header format: vax family; 3b family */
93*10d63b7dSRichard Lowe char ar_magic[AR_5_MAGIC_LENGTH]; /* AR_5_MAGIC*/
94*10d63b7dSRichard Lowe char ar_name[16]; /* Space terminated */
95*10d63b7dSRichard Lowe char ar_date[AR_PORT_WORD]; /* sgetl() accessed */
96*10d63b7dSRichard Lowe char ar_syms[AR_PORT_WORD]; /* sgetl() accessed */
97*10d63b7dSRichard Lowe } Arh_5;
98*10d63b7dSRichard Lowe
99*10d63b7dSRichard Lowe typedef struct { /* 5.0 ar symbol format: vax family; 3b family */
100*10d63b7dSRichard Lowe char sym_name[8]; /* Space terminated */
101*10d63b7dSRichard Lowe char sym_ptr[AR_PORT_WORD]; /* sgetl() accessed */
102*10d63b7dSRichard Lowe } Ars_5;
103*10d63b7dSRichard Lowe
104*10d63b7dSRichard Lowe typedef struct { /* 5.0 ar member format: vax family; 3b family */
105*10d63b7dSRichard Lowe char arf_name[16]; /* Space terminated */
106*10d63b7dSRichard Lowe char arf_date[AR_PORT_WORD]; /* sgetl() accessed */
107*10d63b7dSRichard Lowe char arf_uid[AR_PORT_WORD]; /* sgetl() accessed */
108*10d63b7dSRichard Lowe char arf_gid[AR_PORT_WORD]; /* sgetl() accessed */
109*10d63b7dSRichard Lowe char arf_mode[AR_PORT_WORD]; /* sgetl() accessed */
110*10d63b7dSRichard Lowe char arf_size[AR_PORT_WORD]; /* sgetl() accessed */
111*10d63b7dSRichard Lowe } Arf_5;
112*10d63b7dSRichard Lowe
113*10d63b7dSRichard Lowe typedef struct { /* Portable (6.0) ar format: vax family; 3b family */
114*10d63b7dSRichard Lowe char ar_name[16]; /* Space terminated */
115*10d63b7dSRichard Lowe /* left-adjusted fields; decimal ascii; blank filled */
116*10d63b7dSRichard Lowe char ar_date[12];
117*10d63b7dSRichard Lowe char ar_uid[6];
118*10d63b7dSRichard Lowe char ar_gid[6];
119*10d63b7dSRichard Lowe char ar_mode[8]; /* octal ascii */
120*10d63b7dSRichard Lowe char ar_size[10];
121*10d63b7dSRichard Lowe /* special end-of-header string (AR_PORT_END_MAGIC) */
122*10d63b7dSRichard Lowe char ar_fmag[2];
123*10d63b7dSRichard Lowe } Ar_port;
124*10d63b7dSRichard Lowe
125*10d63b7dSRichard Lowe enum ar_type {
126*10d63b7dSRichard Lowe AR_5,
127*10d63b7dSRichard Lowe AR_PORT
128*10d63b7dSRichard Lowe };
129*10d63b7dSRichard Lowe
130*10d63b7dSRichard Lowe typedef unsigned int ar_port_word; // must be 4-bytes long
131*10d63b7dSRichard Lowe
132*10d63b7dSRichard Lowe typedef struct {
133*10d63b7dSRichard Lowe FILE *fd;
134*10d63b7dSRichard Lowe /* to distiguish ar format */
135*10d63b7dSRichard Lowe enum ar_type type;
136*10d63b7dSRichard Lowe /* where first ar member header is at */
137*10d63b7dSRichard Lowe long first_ar_mem;
138*10d63b7dSRichard Lowe /* where the symbol lookup starts */
139*10d63b7dSRichard Lowe long sym_begin;
140*10d63b7dSRichard Lowe /* the number of symbols available */
141*10d63b7dSRichard Lowe long num_symbols;
142*10d63b7dSRichard Lowe /* length of symbol directory file */
143*10d63b7dSRichard Lowe long sym_size;
144*10d63b7dSRichard Lowe Arh_5 arh_5;
145*10d63b7dSRichard Lowe Ars_5 ars_5;
146*10d63b7dSRichard Lowe Arf_5 arf_5;
147*10d63b7dSRichard Lowe Ar_port ar_port;
148*10d63b7dSRichard Lowe } Ar;
149*10d63b7dSRichard Lowe
150*10d63b7dSRichard Lowe /*
151*10d63b7dSRichard Lowe * Static variables
152*10d63b7dSRichard Lowe */
153*10d63b7dSRichard Lowe
154*10d63b7dSRichard Lowe /*
155*10d63b7dSRichard Lowe * File table of contents
156*10d63b7dSRichard Lowe */
157*10d63b7dSRichard Lowe extern timestruc_t& read_archive(register Name target);
158*10d63b7dSRichard Lowe static Boolean open_archive(char *filename, register Ar *arp);
159*10d63b7dSRichard Lowe static void close_archive(register Ar *arp);
160*10d63b7dSRichard Lowe static Boolean read_archive_dir(register Ar *arp, Name library, char **long_names_table);
161*10d63b7dSRichard Lowe static void translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table);
162*10d63b7dSRichard Lowe static long sgetl(char *);
163*10d63b7dSRichard Lowe
164*10d63b7dSRichard Lowe /*
165*10d63b7dSRichard Lowe * read_archive(target)
166*10d63b7dSRichard Lowe *
167*10d63b7dSRichard Lowe * Read the contents of an ar file.
168*10d63b7dSRichard Lowe *
169*10d63b7dSRichard Lowe * Return value:
170*10d63b7dSRichard Lowe * The time the member was created
171*10d63b7dSRichard Lowe *
172*10d63b7dSRichard Lowe * Parameters:
173*10d63b7dSRichard Lowe * target The member to find time for
174*10d63b7dSRichard Lowe *
175*10d63b7dSRichard Lowe * Global variables used:
176*10d63b7dSRichard Lowe * empty_name The Name ""
177*10d63b7dSRichard Lowe */
178*10d63b7dSRichard Lowe
179*10d63b7dSRichard Lowe int read_member_header (Ar_port *header, FILE *fd, char* filename);
180*10d63b7dSRichard Lowe int process_long_names_member (register Ar *arp, char **long_names_table, char *filename);
181*10d63b7dSRichard Lowe
182*10d63b7dSRichard Lowe timestruc_t&
read_archive(register Name target)183*10d63b7dSRichard Lowe read_archive(register Name target)
184*10d63b7dSRichard Lowe {
185*10d63b7dSRichard Lowe register Property member;
186*10d63b7dSRichard Lowe wchar_t *slash;
187*10d63b7dSRichard Lowe String_rec true_member_name;
188*10d63b7dSRichard Lowe wchar_t buffer[STRING_BUFFER_LENGTH];
189*10d63b7dSRichard Lowe register Name true_member = NULL;
190*10d63b7dSRichard Lowe Ar ar;
191*10d63b7dSRichard Lowe char *long_names_table = NULL; /* Table of long
192*10d63b7dSRichard Lowe member names */
193*10d63b7dSRichard Lowe
194*10d63b7dSRichard Lowe member = get_prop(target->prop, member_prop);
195*10d63b7dSRichard Lowe /*
196*10d63b7dSRichard Lowe * Check if the member has directory component.
197*10d63b7dSRichard Lowe * If so, remove the dir and see if we know the date.
198*10d63b7dSRichard Lowe */
199*10d63b7dSRichard Lowe if (member->body.member.member != NULL) {
200*10d63b7dSRichard Lowe Wstring member_string(member->body.member.member);
201*10d63b7dSRichard Lowe wchar_t * wcb = member_string.get_string();
202*10d63b7dSRichard Lowe if((slash = (wchar_t *) wcsrchr(wcb, (int) slash_char)) != NULL) {
203*10d63b7dSRichard Lowe INIT_STRING_FROM_STACK(true_member_name, buffer);
204*10d63b7dSRichard Lowe append_string(member->body.member.library->string_mb,
205*10d63b7dSRichard Lowe &true_member_name,
206*10d63b7dSRichard Lowe FIND_LENGTH);
207*10d63b7dSRichard Lowe append_char((int) parenleft_char, &true_member_name);
208*10d63b7dSRichard Lowe append_string(slash + 1, &true_member_name, FIND_LENGTH);
209*10d63b7dSRichard Lowe append_char((int) parenright_char, &true_member_name);
210*10d63b7dSRichard Lowe true_member = GETNAME(true_member_name.buffer.start,
211*10d63b7dSRichard Lowe FIND_LENGTH);
212*10d63b7dSRichard Lowe if (true_member->stat.time != file_no_time) {
213*10d63b7dSRichard Lowe target->stat.time = true_member->stat.time;
214*10d63b7dSRichard Lowe return target->stat.time;
215*10d63b7dSRichard Lowe }
216*10d63b7dSRichard Lowe }
217*10d63b7dSRichard Lowe }
218*10d63b7dSRichard Lowe if (open_archive(member->body.member.library->string_mb, &ar) == failed) {
219*10d63b7dSRichard Lowe if (errno == ENOENT) {
220*10d63b7dSRichard Lowe target->stat.stat_errno = ENOENT;
221*10d63b7dSRichard Lowe close_archive(&ar);
222*10d63b7dSRichard Lowe if (member->body.member.member == NULL) {
223*10d63b7dSRichard Lowe member->body.member.member = empty_name;
224*10d63b7dSRichard Lowe }
225*10d63b7dSRichard Lowe return target->stat.time = file_doesnt_exist;
226*10d63b7dSRichard Lowe } else {
227*10d63b7dSRichard Lowe fatal(gettext("Can't access archive `%s': %s"),
228*10d63b7dSRichard Lowe member->body.member.library->string_mb,
229*10d63b7dSRichard Lowe errmsg(errno));
230*10d63b7dSRichard Lowe }
231*10d63b7dSRichard Lowe }
232*10d63b7dSRichard Lowe if (target->stat.time == file_no_time) {
233*10d63b7dSRichard Lowe if (read_archive_dir(&ar, member->body.member.library,
234*10d63b7dSRichard Lowe &long_names_table)
235*10d63b7dSRichard Lowe == failed){
236*10d63b7dSRichard Lowe fatal(gettext("Can't access archive `%s': %s"),
237*10d63b7dSRichard Lowe member->body.member.library->string_mb,
238*10d63b7dSRichard Lowe errmsg(errno));
239*10d63b7dSRichard Lowe }
240*10d63b7dSRichard Lowe }
241*10d63b7dSRichard Lowe if (member->body.member.entry != NULL) {
242*10d63b7dSRichard Lowe translate_entry(&ar, target, member,&long_names_table);
243*10d63b7dSRichard Lowe }
244*10d63b7dSRichard Lowe close_archive(&ar);
245*10d63b7dSRichard Lowe if (long_names_table) {
246*10d63b7dSRichard Lowe retmem_mb(long_names_table);
247*10d63b7dSRichard Lowe }
248*10d63b7dSRichard Lowe if (true_member != NULL) {
249*10d63b7dSRichard Lowe target->stat.time = true_member->stat.time;
250*10d63b7dSRichard Lowe }
251*10d63b7dSRichard Lowe if (target->stat.time == file_no_time) {
252*10d63b7dSRichard Lowe target->stat.time = file_doesnt_exist;
253*10d63b7dSRichard Lowe }
254*10d63b7dSRichard Lowe return target->stat.time;
255*10d63b7dSRichard Lowe }
256*10d63b7dSRichard Lowe
257*10d63b7dSRichard Lowe /*
258*10d63b7dSRichard Lowe * open_archive(filename, arp)
259*10d63b7dSRichard Lowe *
260*10d63b7dSRichard Lowe * Return value:
261*10d63b7dSRichard Lowe * Indicates if open failed or not
262*10d63b7dSRichard Lowe *
263*10d63b7dSRichard Lowe * Parameters:
264*10d63b7dSRichard Lowe * filename The name of the archive we need to read
265*10d63b7dSRichard Lowe * arp Pointer to ar file description block
266*10d63b7dSRichard Lowe *
267*10d63b7dSRichard Lowe * Global variables used:
268*10d63b7dSRichard Lowe */
269*10d63b7dSRichard Lowe static Boolean
open_archive(char * filename,register Ar * arp)270*10d63b7dSRichard Lowe open_archive(char *filename, register Ar *arp)
271*10d63b7dSRichard Lowe {
272*10d63b7dSRichard Lowe int fd;
273*10d63b7dSRichard Lowe char mag_5[AR_5_MAGIC_LENGTH];
274*10d63b7dSRichard Lowe char mag_port[AR_PORT_MAGIC_LENGTH];
275*10d63b7dSRichard Lowe char buffer[4];
276*10d63b7dSRichard Lowe
277*10d63b7dSRichard Lowe arp->fd = NULL;
278*10d63b7dSRichard Lowe fd = open_vroot(filename, O_RDONLY, 0, NULL, VROOT_DEFAULT);
279*10d63b7dSRichard Lowe if ((fd < 0) || ((arp->fd = fdopen(fd, "r")) == NULL)) {
280*10d63b7dSRichard Lowe return failed;
281*10d63b7dSRichard Lowe }
282*10d63b7dSRichard Lowe (void) fcntl(fileno(arp->fd), F_SETFD, 1);
283*10d63b7dSRichard Lowe
284*10d63b7dSRichard Lowe if (fread(mag_port, AR_PORT_MAGIC_LENGTH, 1, arp->fd) != 1) {
285*10d63b7dSRichard Lowe return failed;
286*10d63b7dSRichard Lowe }
287*10d63b7dSRichard Lowe if (IS_EQUALN(mag_port, AR_PORT_MAGIC, AR_PORT_MAGIC_LENGTH)) {
288*10d63b7dSRichard Lowe arp->type = AR_PORT;
289*10d63b7dSRichard Lowe /*
290*10d63b7dSRichard Lowe * Read in first member header to find out if there is
291*10d63b7dSRichard Lowe * a symbol definition table.
292*10d63b7dSRichard Lowe */
293*10d63b7dSRichard Lowe
294*10d63b7dSRichard Lowe int ret = read_member_header(&arp->ar_port, arp->fd, filename);
295*10d63b7dSRichard Lowe if (ret == failed) {
296*10d63b7dSRichard Lowe return failed;
297*10d63b7dSRichard Lowe } else if(ret == -1) {
298*10d63b7dSRichard Lowe /* There is no member header - empty archive */
299*10d63b7dSRichard Lowe arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
300*10d63b7dSRichard Lowe arp->first_ar_mem = ftell(arp->fd);
301*10d63b7dSRichard Lowe return succeeded;
302*10d63b7dSRichard Lowe }
303*10d63b7dSRichard Lowe /*
304*10d63b7dSRichard Lowe * The following values are the default if there is
305*10d63b7dSRichard Lowe * no symbol directory and long member names.
306*10d63b7dSRichard Lowe */
307*10d63b7dSRichard Lowe arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
308*10d63b7dSRichard Lowe arp->first_ar_mem = ftell(arp->fd) - (long) sizeof (Ar_port);
309*10d63b7dSRichard Lowe
310*10d63b7dSRichard Lowe /*
311*10d63b7dSRichard Lowe * Do we have a symbol table? A symbol table is always
312*10d63b7dSRichard Lowe * the first member in an archive. In 4.1.x it has the
313*10d63b7dSRichard Lowe * name __.SYMDEF, in SVr4, it has the name "/ "
314*10d63b7dSRichard Lowe */
315*10d63b7dSRichard Lowe /*
316*10d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, "/ ");
317*10d63b7dSRichard Lowe if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
318*10d63b7dSRichard Lowe */
319*10d63b7dSRichard Lowe if (IS_EQUALN(arp->ar_port.ar_name,
320*10d63b7dSRichard Lowe "/ ",
321*10d63b7dSRichard Lowe 16)) {
322*10d63b7dSRichard Lowe if (sscanf(arp->ar_port.ar_size,
323*10d63b7dSRichard Lowe "%ld",
324*10d63b7dSRichard Lowe &arp->sym_size) != 1) {
325*10d63b7dSRichard Lowe return failed;
326*10d63b7dSRichard Lowe }
327*10d63b7dSRichard Lowe arp->sym_size += (arp->sym_size & 1); /* round up */
328*10d63b7dSRichard Lowe if (fread(buffer, sizeof buffer, 1, arp->fd) != 1) {
329*10d63b7dSRichard Lowe return failed;
330*10d63b7dSRichard Lowe }
331*10d63b7dSRichard Lowe arp->num_symbols = sgetl(buffer);
332*10d63b7dSRichard Lowe arp->sym_begin = ftell(arp->fd);
333*10d63b7dSRichard Lowe arp->first_ar_mem = arp->sym_begin +
334*10d63b7dSRichard Lowe arp->sym_size - sizeof buffer;
335*10d63b7dSRichard Lowe }
336*10d63b7dSRichard Lowe return succeeded;
337*10d63b7dSRichard Lowe }
338*10d63b7dSRichard Lowe fatal(gettext("`%s' is not an archive"), filename);
339*10d63b7dSRichard Lowe /* NOTREACHED */
340*10d63b7dSRichard Lowe return failed;
341*10d63b7dSRichard Lowe }
342*10d63b7dSRichard Lowe
343*10d63b7dSRichard Lowe
344*10d63b7dSRichard Lowe /*
345*10d63b7dSRichard Lowe * close_archive(arp)
346*10d63b7dSRichard Lowe *
347*10d63b7dSRichard Lowe * Parameters:
348*10d63b7dSRichard Lowe * arp Pointer to ar file description block
349*10d63b7dSRichard Lowe *
350*10d63b7dSRichard Lowe * Global variables used:
351*10d63b7dSRichard Lowe */
352*10d63b7dSRichard Lowe static void
close_archive(register Ar * arp)353*10d63b7dSRichard Lowe close_archive(register Ar *arp)
354*10d63b7dSRichard Lowe {
355*10d63b7dSRichard Lowe if (arp->fd != NULL) {
356*10d63b7dSRichard Lowe (void) fclose(arp->fd);
357*10d63b7dSRichard Lowe }
358*10d63b7dSRichard Lowe }
359*10d63b7dSRichard Lowe
360*10d63b7dSRichard Lowe /*
361*10d63b7dSRichard Lowe * read_archive_dir(arp, library, long_names_table)
362*10d63b7dSRichard Lowe *
363*10d63b7dSRichard Lowe * Reads the directory of an archive and enters all
364*10d63b7dSRichard Lowe * the members into the make symboltable in lib(member) format
365*10d63b7dSRichard Lowe * with their dates.
366*10d63b7dSRichard Lowe *
367*10d63b7dSRichard Lowe * Parameters:
368*10d63b7dSRichard Lowe * arp Pointer to ar file description block
369*10d63b7dSRichard Lowe * library Name of lib to enter members for.
370*10d63b7dSRichard Lowe * Used to form "lib(member)" string.
371*10d63b7dSRichard Lowe * long_names_table table that contains list of members
372*10d63b7dSRichard Lowe * with names > 15 characters long
373*10d63b7dSRichard Lowe *
374*10d63b7dSRichard Lowe * Global variables used:
375*10d63b7dSRichard Lowe */
376*10d63b7dSRichard Lowe static Boolean
read_archive_dir(register Ar * arp,Name library,char ** long_names_table)377*10d63b7dSRichard Lowe read_archive_dir(register Ar *arp, Name library, char **long_names_table)
378*10d63b7dSRichard Lowe {
379*10d63b7dSRichard Lowe wchar_t *name_string;
380*10d63b7dSRichard Lowe wchar_t *member_string;
381*10d63b7dSRichard Lowe register long len;
382*10d63b7dSRichard Lowe register wchar_t *p;
383*10d63b7dSRichard Lowe register char *q;
384*10d63b7dSRichard Lowe register Name name;
385*10d63b7dSRichard Lowe Property member;
386*10d63b7dSRichard Lowe long ptr;
387*10d63b7dSRichard Lowe long date;
388*10d63b7dSRichard Lowe
389*10d63b7dSRichard Lowe int offset;
390*10d63b7dSRichard Lowe
391*10d63b7dSRichard Lowe /*
392*10d63b7dSRichard Lowe * If any of the members has a name > 15 chars,
393*10d63b7dSRichard Lowe * it will be found here.
394*10d63b7dSRichard Lowe */
395*10d63b7dSRichard Lowe if (process_long_names_member(arp, long_names_table, library->string_mb) == failed) {
396*10d63b7dSRichard Lowe return failed;
397*10d63b7dSRichard Lowe }
398*10d63b7dSRichard Lowe name_string = ALLOC_WC((int) (library->hash.length +
399*10d63b7dSRichard Lowe (int) ar_member_name_len * 2));
400*10d63b7dSRichard Lowe (void) mbstowcs(name_string, library->string_mb, (int) library->hash.length);
401*10d63b7dSRichard Lowe member_string = name_string + library->hash.length;
402*10d63b7dSRichard Lowe *member_string++ = (int) parenleft_char;
403*10d63b7dSRichard Lowe
404*10d63b7dSRichard Lowe if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
405*10d63b7dSRichard Lowe goto read_error;
406*10d63b7dSRichard Lowe }
407*10d63b7dSRichard Lowe /* Read the directory using the appropriate format */
408*10d63b7dSRichard Lowe switch (arp->type) {
409*10d63b7dSRichard Lowe case AR_5:
410*10d63b7dSRichard Lowe for (;;) {
411*10d63b7dSRichard Lowe if (fread((char *) &arp->arf_5, sizeof arp->arf_5, 1, arp->fd)
412*10d63b7dSRichard Lowe != 1) {
413*10d63b7dSRichard Lowe if (feof(arp->fd)) {
414*10d63b7dSRichard Lowe return succeeded;
415*10d63b7dSRichard Lowe }
416*10d63b7dSRichard Lowe break;
417*10d63b7dSRichard Lowe }
418*10d63b7dSRichard Lowe len = sizeof arp->arf_5.arf_name;
419*10d63b7dSRichard Lowe for (p = member_string, q = arp->arf_5.arf_name;
420*10d63b7dSRichard Lowe (len > 0) && (*q != (int) nul_char) && !isspace(*q);
421*10d63b7dSRichard Lowe ) {
422*10d63b7dSRichard Lowe MBTOWC(p, q);
423*10d63b7dSRichard Lowe p++;
424*10d63b7dSRichard Lowe q++;
425*10d63b7dSRichard Lowe }
426*10d63b7dSRichard Lowe *p++ = (int) parenright_char;
427*10d63b7dSRichard Lowe *p = (int) nul_char;
428*10d63b7dSRichard Lowe name = GETNAME(name_string, FIND_LENGTH);
429*10d63b7dSRichard Lowe /*
430*10d63b7dSRichard Lowe * [tolik] Fix for dmake bug 1234018.
431*10d63b7dSRichard Lowe * If name->stat.time is already set, then it should not
432*10d63b7dSRichard Lowe * be changed. (D)make propogates time stamp for one
433*10d63b7dSRichard Lowe * member, and when it calls exists() for another member,
434*10d63b7dSRichard Lowe * the first one may be changed.
435*10d63b7dSRichard Lowe */
436*10d63b7dSRichard Lowe if(name->stat.time == file_no_time) {
437*10d63b7dSRichard Lowe name->stat.time.tv_sec = sgetl(arp->arf_5.arf_date);
438*10d63b7dSRichard Lowe name->stat.time.tv_nsec = LONG_MAX;
439*10d63b7dSRichard Lowe }
440*10d63b7dSRichard Lowe name->is_member = library->is_member;
441*10d63b7dSRichard Lowe member = maybe_append_prop(name, member_prop);
442*10d63b7dSRichard Lowe member->body.member.library = library;
443*10d63b7dSRichard Lowe *--p = (int) nul_char;
444*10d63b7dSRichard Lowe if (member->body.member.member == NULL) {
445*10d63b7dSRichard Lowe member->body.member.member =
446*10d63b7dSRichard Lowe GETNAME(member_string, FIND_LENGTH);
447*10d63b7dSRichard Lowe }
448*10d63b7dSRichard Lowe ptr = sgetl(arp->arf_5.arf_size);
449*10d63b7dSRichard Lowe ptr += (ptr & 1);
450*10d63b7dSRichard Lowe if (fseek(arp->fd, ptr, 1) != 0) {
451*10d63b7dSRichard Lowe goto read_error;
452*10d63b7dSRichard Lowe }
453*10d63b7dSRichard Lowe }
454*10d63b7dSRichard Lowe break;
455*10d63b7dSRichard Lowe case AR_PORT:
456*10d63b7dSRichard Lowe for (;;) {
457*10d63b7dSRichard Lowe if ((fread((char *) &arp->ar_port,
458*10d63b7dSRichard Lowe sizeof arp->ar_port,
459*10d63b7dSRichard Lowe 1,
460*10d63b7dSRichard Lowe arp->fd) != 1) ||
461*10d63b7dSRichard Lowe !IS_EQUALN(arp->ar_port.ar_fmag,
462*10d63b7dSRichard Lowe AR_PORT_END_MAGIC,
463*10d63b7dSRichard Lowe sizeof arp->ar_port.ar_fmag)) {
464*10d63b7dSRichard Lowe if (feof(arp->fd)) {
465*10d63b7dSRichard Lowe return succeeded;
466*10d63b7dSRichard Lowe }
467*10d63b7dSRichard Lowe fatal(
468*10d63b7dSRichard Lowe gettext("Read error in archive `%s': invalid archive file member header at 0x%x"),
469*10d63b7dSRichard Lowe library->string_mb,
470*10d63b7dSRichard Lowe ftell(arp->fd)
471*10d63b7dSRichard Lowe );
472*10d63b7dSRichard Lowe }
473*10d63b7dSRichard Lowe /* If it's a long name, retrieve it from long name table */
474*10d63b7dSRichard Lowe if (arp->ar_port.ar_name[0] == '/') {
475*10d63b7dSRichard Lowe /*
476*10d63b7dSRichard Lowe * "len" is used for hashing the string.
477*10d63b7dSRichard Lowe * We're using "ar_member_name_len" instead of
478*10d63b7dSRichard Lowe * the actual name length since it's the longest
479*10d63b7dSRichard Lowe * string the "ar" command can handle at this
480*10d63b7dSRichard Lowe * point.
481*10d63b7dSRichard Lowe */
482*10d63b7dSRichard Lowe len = ar_member_name_len;
483*10d63b7dSRichard Lowe sscanf(arp->ar_port.ar_name + 1,
484*10d63b7dSRichard Lowe "%ld",
485*10d63b7dSRichard Lowe &offset);
486*10d63b7dSRichard Lowe q = *long_names_table + offset;
487*10d63b7dSRichard Lowe } else {
488*10d63b7dSRichard Lowe q = arp->ar_port.ar_name;
489*10d63b7dSRichard Lowe len = sizeof arp->ar_port.ar_name;
490*10d63b7dSRichard Lowe }
491*10d63b7dSRichard Lowe
492*10d63b7dSRichard Lowe for (p = member_string;
493*10d63b7dSRichard Lowe (len > 0) &&
494*10d63b7dSRichard Lowe (*q != (int) nul_char) &&
495*10d63b7dSRichard Lowe !isspace(*q) &&
496*10d63b7dSRichard Lowe (*q != (int) slash_char);
497*10d63b7dSRichard Lowe ) {
498*10d63b7dSRichard Lowe MBTOWC(p, q);
499*10d63b7dSRichard Lowe p++;
500*10d63b7dSRichard Lowe q++;
501*10d63b7dSRichard Lowe }
502*10d63b7dSRichard Lowe *p++ = (int) parenright_char;
503*10d63b7dSRichard Lowe *p = (int) nul_char;
504*10d63b7dSRichard Lowe name = GETNAME(name_string, FIND_LENGTH);
505*10d63b7dSRichard Lowe name->is_member = library->is_member;
506*10d63b7dSRichard Lowe member = maybe_append_prop(name, member_prop);
507*10d63b7dSRichard Lowe member->body.member.library = library;
508*10d63b7dSRichard Lowe *--p = (int) nul_char;
509*10d63b7dSRichard Lowe if (member->body.member.member == NULL) {
510*10d63b7dSRichard Lowe member->body.member.member =
511*10d63b7dSRichard Lowe GETNAME(member_string, FIND_LENGTH);
512*10d63b7dSRichard Lowe }
513*10d63b7dSRichard Lowe if (sscanf(arp->ar_port.ar_date, "%ld", &date) != 1) {
514*10d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, name_string);
515*10d63b7dSRichard Lowe fatal(gettext("Bad date field for member `%s' in archive `%s'"),
516*10d63b7dSRichard Lowe mbs_buffer,
517*10d63b7dSRichard Lowe library->string_mb);
518*10d63b7dSRichard Lowe }
519*10d63b7dSRichard Lowe /*
520*10d63b7dSRichard Lowe * [tolik] Fix for dmake bug 1234018.
521*10d63b7dSRichard Lowe */
522*10d63b7dSRichard Lowe if(name->stat.time == file_no_time) {
523*10d63b7dSRichard Lowe name->stat.time.tv_sec = date;
524*10d63b7dSRichard Lowe name->stat.time.tv_nsec = LONG_MAX;
525*10d63b7dSRichard Lowe }
526*10d63b7dSRichard Lowe if (sscanf(arp->ar_port.ar_size, "%ld", &ptr) != 1) {
527*10d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, name_string);
528*10d63b7dSRichard Lowe fatal(gettext("Bad size field for member `%s' in archive `%s'"),
529*10d63b7dSRichard Lowe mbs_buffer,
530*10d63b7dSRichard Lowe library->string_mb);
531*10d63b7dSRichard Lowe }
532*10d63b7dSRichard Lowe ptr += (ptr & 1);
533*10d63b7dSRichard Lowe if (fseek(arp->fd, ptr, 1) != 0) {
534*10d63b7dSRichard Lowe goto read_error;
535*10d63b7dSRichard Lowe }
536*10d63b7dSRichard Lowe }
537*10d63b7dSRichard Lowe break;
538*10d63b7dSRichard Lowe }
539*10d63b7dSRichard Lowe
540*10d63b7dSRichard Lowe /* Only here if fread() [or IS_EQUALN()] failed and not at EOF */
541*10d63b7dSRichard Lowe read_error:
542*10d63b7dSRichard Lowe fatal(gettext("Read error in archive `%s': %s"),
543*10d63b7dSRichard Lowe library->string_mb,
544*10d63b7dSRichard Lowe errmsg(errno));
545*10d63b7dSRichard Lowe /* NOTREACHED */
546*10d63b7dSRichard Lowe }
547*10d63b7dSRichard Lowe
548*10d63b7dSRichard Lowe
549*10d63b7dSRichard Lowe /*
550*10d63b7dSRichard Lowe * process_long_names_member(arp)
551*10d63b7dSRichard Lowe *
552*10d63b7dSRichard Lowe * If the archive contains members with names longer
553*10d63b7dSRichard Lowe * than 15 characters, then it has a special member
554*10d63b7dSRichard Lowe * with the name "// " that contains a table
555*10d63b7dSRichard Lowe * of null-terminated long names. This member
556*10d63b7dSRichard Lowe * is always the first member, after the symbol table
557*10d63b7dSRichard Lowe * if it exists.
558*10d63b7dSRichard Lowe *
559*10d63b7dSRichard Lowe * Parameters:
560*10d63b7dSRichard Lowe * arp Pointer to ar file description block
561*10d63b7dSRichard Lowe *
562*10d63b7dSRichard Lowe * Global variables used:
563*10d63b7dSRichard Lowe */
564*10d63b7dSRichard Lowe int
process_long_names_member(register Ar * arp,char ** long_names_table,char * filename)565*10d63b7dSRichard Lowe process_long_names_member(register Ar *arp, char **long_names_table, char *filename)
566*10d63b7dSRichard Lowe {
567*10d63b7dSRichard Lowe Ar_port *ar_member_header;
568*10d63b7dSRichard Lowe int table_size;
569*10d63b7dSRichard Lowe
570*10d63b7dSRichard Lowe if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
571*10d63b7dSRichard Lowe return failed;
572*10d63b7dSRichard Lowe }
573*10d63b7dSRichard Lowe if ((ar_member_header =
574*10d63b7dSRichard Lowe (Ar_port *) alloca((int) sizeof(Ar_port))) == NULL){
575*10d63b7dSRichard Lowe perror(gettext("memory allocation failure"));
576*10d63b7dSRichard Lowe return failed;
577*10d63b7dSRichard Lowe }
578*10d63b7dSRichard Lowe int ret = read_member_header(ar_member_header, arp->fd, filename);
579*10d63b7dSRichard Lowe if (ret == failed) {
580*10d63b7dSRichard Lowe return failed;
581*10d63b7dSRichard Lowe } else if(ret == -1) {
582*10d63b7dSRichard Lowe /* There is no member header - empty archive */
583*10d63b7dSRichard Lowe return succeeded;
584*10d63b7dSRichard Lowe }
585*10d63b7dSRichard Lowe /* Do we have special member containing long names? */
586*10d63b7dSRichard Lowe if (IS_EQUALN(ar_member_header->ar_name,
587*10d63b7dSRichard Lowe "// ",
588*10d63b7dSRichard Lowe 16)){
589*10d63b7dSRichard Lowe if (sscanf(ar_member_header->ar_size,
590*10d63b7dSRichard Lowe "%ld",
591*10d63b7dSRichard Lowe &table_size) != 1) {
592*10d63b7dSRichard Lowe return failed;
593*10d63b7dSRichard Lowe }
594*10d63b7dSRichard Lowe *long_names_table = (char *) malloc(table_size);
595*10d63b7dSRichard Lowe /* Read the list of long member names into the table */
596*10d63b7dSRichard Lowe if (fread(*long_names_table, table_size, 1, arp->fd) != 1) {
597*10d63b7dSRichard Lowe return failed;
598*10d63b7dSRichard Lowe }
599*10d63b7dSRichard Lowe arp->first_ar_mem = ftell(arp->fd);
600*10d63b7dSRichard Lowe }
601*10d63b7dSRichard Lowe return succeeded;
602*10d63b7dSRichard Lowe }
603*10d63b7dSRichard Lowe
604*10d63b7dSRichard Lowe /*
605*10d63b7dSRichard Lowe * translate_entry(arp, target, member)
606*10d63b7dSRichard Lowe *
607*10d63b7dSRichard Lowe * Finds the member for one lib.a((entry))
608*10d63b7dSRichard Lowe *
609*10d63b7dSRichard Lowe * Parameters:
610*10d63b7dSRichard Lowe * arp Pointer to ar file description block
611*10d63b7dSRichard Lowe * target Target to find member name for
612*10d63b7dSRichard Lowe * member Property to fill in with info
613*10d63b7dSRichard Lowe *
614*10d63b7dSRichard Lowe * Global variables used:
615*10d63b7dSRichard Lowe */
616*10d63b7dSRichard Lowe static void
translate_entry(register Ar * arp,Name target,register Property member,char ** long_names_table)617*10d63b7dSRichard Lowe translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table)
618*10d63b7dSRichard Lowe {
619*10d63b7dSRichard Lowe register int len;
620*10d63b7dSRichard Lowe register int i;
621*10d63b7dSRichard Lowe wchar_t *member_string;
622*10d63b7dSRichard Lowe ar_port_word *offs;
623*10d63b7dSRichard Lowe int strtablen;
624*10d63b7dSRichard Lowe char *syms; /* string table */
625*10d63b7dSRichard Lowe char *csym; /* string table */
626*10d63b7dSRichard Lowe ar_port_word *offend; /* end of offsets table */
627*10d63b7dSRichard Lowe int date;
628*10d63b7dSRichard Lowe register wchar_t *ap;
629*10d63b7dSRichard Lowe register char *hp;
630*10d63b7dSRichard Lowe int maxs;
631*10d63b7dSRichard Lowe int offset;
632*10d63b7dSRichard Lowe char buffer[4];
633*10d63b7dSRichard Lowe
634*10d63b7dSRichard Lowe if (arp->sym_begin == 0L || arp->num_symbols == 0L) {
635*10d63b7dSRichard Lowe fatal(gettext("Cannot find symbol `%s' in archive `%s'"),
636*10d63b7dSRichard Lowe member->body.member.entry->string_mb,
637*10d63b7dSRichard Lowe member->body.member.library->string_mb);
638*10d63b7dSRichard Lowe }
639*10d63b7dSRichard Lowe
640*10d63b7dSRichard Lowe if (fseek(arp->fd, arp->sym_begin, 0) != 0) {
641*10d63b7dSRichard Lowe goto read_error;
642*10d63b7dSRichard Lowe }
643*10d63b7dSRichard Lowe member_string = ALLOC_WC((int) ((int) ar_member_name_len * 2));
644*10d63b7dSRichard Lowe
645*10d63b7dSRichard Lowe switch (arp->type) {
646*10d63b7dSRichard Lowe case AR_5:
647*10d63b7dSRichard Lowe if ((len = member->body.member.entry->hash.length) > 8) {
648*10d63b7dSRichard Lowe len = 8;
649*10d63b7dSRichard Lowe }
650*10d63b7dSRichard Lowe for (i = 0; i < arp->num_symbols; i++) {
651*10d63b7dSRichard Lowe if (fread((char *) &arp->ars_5,
652*10d63b7dSRichard Lowe sizeof arp->ars_5,
653*10d63b7dSRichard Lowe 1,
654*10d63b7dSRichard Lowe arp->fd) != 1) {
655*10d63b7dSRichard Lowe goto read_error;
656*10d63b7dSRichard Lowe }
657*10d63b7dSRichard Lowe if (IS_EQUALN(arp->ars_5.sym_name,
658*10d63b7dSRichard Lowe member->body.member.entry->string_mb,
659*10d63b7dSRichard Lowe len)) {
660*10d63b7dSRichard Lowe if ((fseek(arp->fd,
661*10d63b7dSRichard Lowe sgetl(arp->ars_5.sym_ptr),
662*10d63b7dSRichard Lowe 0) != 0) ||
663*10d63b7dSRichard Lowe (fread((char *) &arp->arf_5,
664*10d63b7dSRichard Lowe sizeof arp->arf_5,
665*10d63b7dSRichard Lowe 1,
666*10d63b7dSRichard Lowe arp->fd) != 1)) {
667*10d63b7dSRichard Lowe goto read_error;
668*10d63b7dSRichard Lowe }
669*10d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, arp->arf_5.arf_name);
670*10d63b7dSRichard Lowe (void) wcsncpy(member_string,
671*10d63b7dSRichard Lowe wcs_buffer,
672*10d63b7dSRichard Lowe wcslen(wcs_buffer));
673*10d63b7dSRichard Lowe member_string[sizeof(arp->arf_5.arf_name)] =
674*10d63b7dSRichard Lowe (int) nul_char;
675*10d63b7dSRichard Lowe member->body.member.member =
676*10d63b7dSRichard Lowe GETNAME(member_string, FIND_LENGTH);
677*10d63b7dSRichard Lowe target->stat.time.tv_sec = sgetl(arp->arf_5.arf_date);
678*10d63b7dSRichard Lowe target->stat.time.tv_nsec = LONG_MAX;
679*10d63b7dSRichard Lowe return;
680*10d63b7dSRichard Lowe }
681*10d63b7dSRichard Lowe }
682*10d63b7dSRichard Lowe break;
683*10d63b7dSRichard Lowe case AR_PORT:
684*10d63b7dSRichard Lowe offs = (ar_port_word *) alloca((int) (arp->num_symbols * AR_PORT_WORD));
685*10d63b7dSRichard Lowe if (fread((char *) offs,
686*10d63b7dSRichard Lowe AR_PORT_WORD,
687*10d63b7dSRichard Lowe (int) arp->num_symbols,
688*10d63b7dSRichard Lowe arp->fd) != arp->num_symbols) {
689*10d63b7dSRichard Lowe goto read_error;
690*10d63b7dSRichard Lowe }
691*10d63b7dSRichard Lowe
692*10d63b7dSRichard Lowe for(i=0;i<arp->num_symbols;i++) {
693*10d63b7dSRichard Lowe *((int*)buffer)=offs[i];
694*10d63b7dSRichard Lowe offs[i]=(ar_port_word)sgetl(buffer);
695*10d63b7dSRichard Lowe }
696*10d63b7dSRichard Lowe
697*10d63b7dSRichard Lowe strtablen=arp->sym_size-4-(int) (arp->num_symbols * AR_PORT_WORD);
698*10d63b7dSRichard Lowe syms = (char *) alloca(strtablen);
699*10d63b7dSRichard Lowe if (fread(syms,
700*10d63b7dSRichard Lowe sizeof (char),
701*10d63b7dSRichard Lowe strtablen,
702*10d63b7dSRichard Lowe arp->fd) != strtablen) {
703*10d63b7dSRichard Lowe goto read_error;
704*10d63b7dSRichard Lowe }
705*10d63b7dSRichard Lowe offend = &offs[arp->num_symbols];
706*10d63b7dSRichard Lowe while (offs < offend) {
707*10d63b7dSRichard Lowe maxs = strlen(member->body.member.entry->string_mb);
708*10d63b7dSRichard Lowe if(strlen(syms) > maxs)
709*10d63b7dSRichard Lowe maxs = strlen(syms);
710*10d63b7dSRichard Lowe if (IS_EQUALN(syms,
711*10d63b7dSRichard Lowe member->body.member.entry->string_mb,
712*10d63b7dSRichard Lowe maxs)) {
713*10d63b7dSRichard Lowe if (fseek(arp->fd,
714*10d63b7dSRichard Lowe (long) *offs,
715*10d63b7dSRichard Lowe 0) != 0) {
716*10d63b7dSRichard Lowe goto read_error;
717*10d63b7dSRichard Lowe }
718*10d63b7dSRichard Lowe if ((fread((char *) &arp->ar_port,
719*10d63b7dSRichard Lowe sizeof arp->ar_port,
720*10d63b7dSRichard Lowe 1,
721*10d63b7dSRichard Lowe arp->fd) != 1) ||
722*10d63b7dSRichard Lowe !IS_EQUALN(arp->ar_port.ar_fmag,
723*10d63b7dSRichard Lowe AR_PORT_END_MAGIC,
724*10d63b7dSRichard Lowe sizeof arp->ar_port.ar_fmag)) {
725*10d63b7dSRichard Lowe goto read_error;
726*10d63b7dSRichard Lowe }
727*10d63b7dSRichard Lowe if (sscanf(arp->ar_port.ar_date,
728*10d63b7dSRichard Lowe "%ld",
729*10d63b7dSRichard Lowe &date) != 1) {
730*10d63b7dSRichard Lowe fatal(gettext("Bad date field for member `%s' in archive `%s'"),
731*10d63b7dSRichard Lowe arp->ar_port.ar_name,
732*10d63b7dSRichard Lowe target->string_mb);
733*10d63b7dSRichard Lowe }
734*10d63b7dSRichard Lowe /* If it's a long name, retrieve it from long name table */
735*10d63b7dSRichard Lowe if (arp->ar_port.ar_name[0] == '/') {
736*10d63b7dSRichard Lowe sscanf(arp->ar_port.ar_name + 1,
737*10d63b7dSRichard Lowe "%ld",
738*10d63b7dSRichard Lowe &offset);
739*10d63b7dSRichard Lowe len = ar_member_name_len;
740*10d63b7dSRichard Lowe hp = *long_names_table + offset;
741*10d63b7dSRichard Lowe } else {
742*10d63b7dSRichard Lowe len = sizeof arp->ar_port.ar_name;
743*10d63b7dSRichard Lowe hp = arp->ar_port.ar_name;
744*10d63b7dSRichard Lowe }
745*10d63b7dSRichard Lowe ap = member_string;
746*10d63b7dSRichard Lowe while (*hp &&
747*10d63b7dSRichard Lowe (*hp != (int) slash_char) &&
748*10d63b7dSRichard Lowe (ap < &member_string[len])) {
749*10d63b7dSRichard Lowe MBTOWC(ap, hp);
750*10d63b7dSRichard Lowe ap++;
751*10d63b7dSRichard Lowe hp++;
752*10d63b7dSRichard Lowe }
753*10d63b7dSRichard Lowe *ap = (int) nul_char;
754*10d63b7dSRichard Lowe member->body.member.member =
755*10d63b7dSRichard Lowe GETNAME(member_string, FIND_LENGTH);
756*10d63b7dSRichard Lowe target->stat.time.tv_sec = date;
757*10d63b7dSRichard Lowe target->stat.time.tv_nsec = LONG_MAX;
758*10d63b7dSRichard Lowe return;
759*10d63b7dSRichard Lowe }
760*10d63b7dSRichard Lowe offs++;
761*10d63b7dSRichard Lowe while(*syms!='\0') syms++;
762*10d63b7dSRichard Lowe syms++;
763*10d63b7dSRichard Lowe }
764*10d63b7dSRichard Lowe }
765*10d63b7dSRichard Lowe fatal(gettext("Cannot find symbol `%s' in archive `%s'"),
766*10d63b7dSRichard Lowe member->body.member.entry->string_mb,
767*10d63b7dSRichard Lowe member->body.member.library->string_mb);
768*10d63b7dSRichard Lowe /*NOTREACHED*/
769*10d63b7dSRichard Lowe
770*10d63b7dSRichard Lowe read_error:
771*10d63b7dSRichard Lowe if (ferror(arp->fd)) {
772*10d63b7dSRichard Lowe fatal(gettext("Read error in archive `%s': %s"),
773*10d63b7dSRichard Lowe member->body.member.library->string_mb,
774*10d63b7dSRichard Lowe errmsg(errno));
775*10d63b7dSRichard Lowe } else {
776*10d63b7dSRichard Lowe fatal(gettext("Read error in archive `%s': Premature EOF"),
777*10d63b7dSRichard Lowe member->body.member.library->string_mb);
778*10d63b7dSRichard Lowe }
779*10d63b7dSRichard Lowe }
780*10d63b7dSRichard Lowe
781*10d63b7dSRichard Lowe /*
782*10d63b7dSRichard Lowe * sgetl(buffer)
783*10d63b7dSRichard Lowe *
784*10d63b7dSRichard Lowe * The intent here is to provide a means to make the value of
785*10d63b7dSRichard Lowe * bytes in an io-buffer correspond to the value of a long
786*10d63b7dSRichard Lowe * in the memory while doing the io a long at a time.
787*10d63b7dSRichard Lowe * Files written and read in this way are machine-independent.
788*10d63b7dSRichard Lowe *
789*10d63b7dSRichard Lowe * Return value:
790*10d63b7dSRichard Lowe * Long int read from buffer
791*10d63b7dSRichard Lowe * Parameters:
792*10d63b7dSRichard Lowe * buffer buffer we need to read long int from
793*10d63b7dSRichard Lowe *
794*10d63b7dSRichard Lowe * Global variables used:
795*10d63b7dSRichard Lowe */
796*10d63b7dSRichard Lowe static long
sgetl(register char * buffer)797*10d63b7dSRichard Lowe sgetl(register char *buffer)
798*10d63b7dSRichard Lowe {
799*10d63b7dSRichard Lowe register long w = 0;
800*10d63b7dSRichard Lowe register int i = BITSPERBYTE * AR_PORT_WORD;
801*10d63b7dSRichard Lowe
802*10d63b7dSRichard Lowe while ((i -= BITSPERBYTE) >= 0) {
803*10d63b7dSRichard Lowe w |= (long) ((unsigned char) *buffer++) << i;
804*10d63b7dSRichard Lowe }
805*10d63b7dSRichard Lowe return w;
806*10d63b7dSRichard Lowe }
807*10d63b7dSRichard Lowe
808*10d63b7dSRichard Lowe
809*10d63b7dSRichard Lowe /*
810*10d63b7dSRichard Lowe * read_member_header(header, fd, filename)
811*10d63b7dSRichard Lowe *
812*10d63b7dSRichard Lowe * reads the member header for the 4.1.x and SVr4 archives.
813*10d63b7dSRichard Lowe *
814*10d63b7dSRichard Lowe * Return value:
815*10d63b7dSRichard Lowe * fails if read error or member
816*10d63b7dSRichard Lowe * header is not the right format
817*10d63b7dSRichard Lowe * Parameters:
818*10d63b7dSRichard Lowe * header There's one before each archive member
819*10d63b7dSRichard Lowe * fd file descriptor for the archive file.
820*10d63b7dSRichard Lowe *
821*10d63b7dSRichard Lowe * Global variables used:
822*10d63b7dSRichard Lowe */
823*10d63b7dSRichard Lowe int
read_member_header(Ar_port * header,FILE * fd,char * filename)824*10d63b7dSRichard Lowe read_member_header(Ar_port *header, FILE *fd, char* filename)
825*10d63b7dSRichard Lowe {
826*10d63b7dSRichard Lowe int num = fread((char *) header, sizeof (Ar_port), 1, fd);
827*10d63b7dSRichard Lowe if (num != 1 && feof(fd)) {
828*10d63b7dSRichard Lowe /* There is no member header - empty archive */
829*10d63b7dSRichard Lowe return -1;
830*10d63b7dSRichard Lowe }
831*10d63b7dSRichard Lowe if ((num != 1) ||
832*10d63b7dSRichard Lowe !IS_EQUALN(
833*10d63b7dSRichard Lowe AR_PORT_END_MAGIC,
834*10d63b7dSRichard Lowe header->ar_fmag,
835*10d63b7dSRichard Lowe sizeof (header->ar_fmag)
836*10d63b7dSRichard Lowe )
837*10d63b7dSRichard Lowe ) {
838*10d63b7dSRichard Lowe fatal(
839*10d63b7dSRichard Lowe gettext("Read error in archive `%s': invalid archive file member header at 0x%x"),
840*10d63b7dSRichard Lowe filename,
841*10d63b7dSRichard Lowe ftell(fd)
842*10d63b7dSRichard Lowe );
843*10d63b7dSRichard Lowe }
844*10d63b7dSRichard Lowe return succeeded;
845*10d63b7dSRichard Lowe }
846*10d63b7dSRichard Lowe
847