xref: /titanic_50/usr/src/cmd/make/bin/ar.cc (revision 10d63b7db37a83b39c7f511cf9426c9d03ea0760)
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