xref: /titanic_41/usr/src/cmd/make/bin/ar.cc (revision 3625efb1376c3d31a0e742ed72b778e5b3add543)
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