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