110d63b7dSRichard Lowe /*
210d63b7dSRichard Lowe * CDDL HEADER START
310d63b7dSRichard Lowe *
410d63b7dSRichard Lowe * The contents of this file are subject to the terms of the
510d63b7dSRichard Lowe * Common Development and Distribution License (the "License").
610d63b7dSRichard Lowe * You may not use this file except in compliance with the License.
710d63b7dSRichard Lowe *
810d63b7dSRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910d63b7dSRichard Lowe * or http://www.opensolaris.org/os/licensing.
1010d63b7dSRichard Lowe * See the License for the specific language governing permissions
1110d63b7dSRichard Lowe * and limitations under the License.
1210d63b7dSRichard Lowe *
1310d63b7dSRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
1410d63b7dSRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510d63b7dSRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
1610d63b7dSRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
1710d63b7dSRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
1810d63b7dSRichard Lowe *
1910d63b7dSRichard Lowe * CDDL HEADER END
2010d63b7dSRichard Lowe */
2110d63b7dSRichard Lowe /*
2210d63b7dSRichard Lowe * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
2310d63b7dSRichard Lowe * Use is subject to license terms.
2410d63b7dSRichard Lowe */
2510d63b7dSRichard Lowe
2610d63b7dSRichard Lowe /*
2710d63b7dSRichard Lowe * ar.c
2810d63b7dSRichard Lowe *
2910d63b7dSRichard Lowe * Deal with the lib.a(member.o) and lib.a((entry-point)) notations
3010d63b7dSRichard Lowe *
3110d63b7dSRichard Lowe * Look inside archives for notations a(b) and a((b))
3210d63b7dSRichard Lowe * a(b) is file member b in archive a
3310d63b7dSRichard Lowe * a((b)) is entry point b in object archive a
3410d63b7dSRichard Lowe *
3510d63b7dSRichard Lowe * For 6.0, create a make which can understand all archive
3610d63b7dSRichard Lowe * formats. This is kind of tricky, and <ar.h> isnt any help.
3710d63b7dSRichard Lowe */
3810d63b7dSRichard Lowe
3910d63b7dSRichard Lowe /*
4010d63b7dSRichard Lowe * Included files
4110d63b7dSRichard Lowe */
4210d63b7dSRichard Lowe #include <alloca.h> /* alloca() */
4310d63b7dSRichard Lowe #include <ar.h>
4410d63b7dSRichard Lowe #include <errno.h> /* errno */
4510d63b7dSRichard Lowe #include <fcntl.h> /* open() */
4610d63b7dSRichard Lowe #include <libintl.h>
4710d63b7dSRichard Lowe #include <mk/defs.h>
4810d63b7dSRichard Lowe #include <mksh/misc.h> /* retmem_mb() */
4910d63b7dSRichard Lowe
5010d63b7dSRichard Lowe struct ranlib {
5110d63b7dSRichard Lowe union {
5210d63b7dSRichard Lowe off_t ran_strx; /* string table index of */
5310d63b7dSRichard Lowe char *ran_name; /* symbol defined by */
5410d63b7dSRichard Lowe } ran_un;
5510d63b7dSRichard Lowe off_t ran_off; /* library member at this offset */
5610d63b7dSRichard Lowe };
5710d63b7dSRichard Lowe
5810d63b7dSRichard Lowe #include <unistd.h> /* close() */
5910d63b7dSRichard Lowe
6010d63b7dSRichard Lowe
6110d63b7dSRichard Lowe /*
6210d63b7dSRichard Lowe * Defined macros
6310d63b7dSRichard Lowe */
6410d63b7dSRichard Lowe #ifndef S5EMUL
6510d63b7dSRichard Lowe #undef BITSPERBYTE
6610d63b7dSRichard Lowe #define BITSPERBYTE 8
6710d63b7dSRichard Lowe #endif
6810d63b7dSRichard Lowe
6910d63b7dSRichard Lowe /*
7010d63b7dSRichard Lowe * Defines for all the different archive formats. See next comment
7110d63b7dSRichard Lowe * block for justification for not using <ar.h>s versions.
7210d63b7dSRichard Lowe */
7310d63b7dSRichard Lowe #define AR_5_MAGIC "<ar>" /* 5.0 format magic string */
7410d63b7dSRichard Lowe #define AR_5_MAGIC_LENGTH 4 /* 5.0 format string length */
7510d63b7dSRichard Lowe
7610d63b7dSRichard Lowe #define AR_PORT_MAGIC "!<arch>\n" /* Port. (6.0) magic string */
7710d63b7dSRichard Lowe #define AR_PORT_MAGIC_LENGTH 8 /* Port. (6.0) string length */
7810d63b7dSRichard Lowe #define AR_PORT_END_MAGIC "`\n" /* Port. (6.0) end of header */
7910d63b7dSRichard Lowe #define AR_PORT_WORD 4 /* Port. (6.0) 'word' length */
8010d63b7dSRichard Lowe
8110d63b7dSRichard Lowe /*
8210d63b7dSRichard Lowe * typedefs & structs
8310d63b7dSRichard Lowe */
8410d63b7dSRichard Lowe /*
8510d63b7dSRichard Lowe * These are the archive file headers for the formats. Note
8610d63b7dSRichard Lowe * that it really doesnt matter if these structures are defined
8710d63b7dSRichard Lowe * here. They are correct as of the respective archive format
8810d63b7dSRichard Lowe * releases. If the archive format is changed, then since backwards
8910d63b7dSRichard Lowe * compatability is the desired behavior, a new structure is added
9010d63b7dSRichard Lowe * to the list.
9110d63b7dSRichard Lowe */
9210d63b7dSRichard Lowe typedef struct { /* 5.0 ar header format: vax family; 3b family */
9310d63b7dSRichard Lowe char ar_magic[AR_5_MAGIC_LENGTH]; /* AR_5_MAGIC*/
9410d63b7dSRichard Lowe char ar_name[16]; /* Space terminated */
9510d63b7dSRichard Lowe char ar_date[AR_PORT_WORD]; /* sgetl() accessed */
9610d63b7dSRichard Lowe char ar_syms[AR_PORT_WORD]; /* sgetl() accessed */
9710d63b7dSRichard Lowe } Arh_5;
9810d63b7dSRichard Lowe
9910d63b7dSRichard Lowe typedef struct { /* 5.0 ar symbol format: vax family; 3b family */
10010d63b7dSRichard Lowe char sym_name[8]; /* Space terminated */
10110d63b7dSRichard Lowe char sym_ptr[AR_PORT_WORD]; /* sgetl() accessed */
10210d63b7dSRichard Lowe } Ars_5;
10310d63b7dSRichard Lowe
10410d63b7dSRichard Lowe typedef struct { /* 5.0 ar member format: vax family; 3b family */
10510d63b7dSRichard Lowe char arf_name[16]; /* Space terminated */
10610d63b7dSRichard Lowe char arf_date[AR_PORT_WORD]; /* sgetl() accessed */
10710d63b7dSRichard Lowe char arf_uid[AR_PORT_WORD]; /* sgetl() accessed */
10810d63b7dSRichard Lowe char arf_gid[AR_PORT_WORD]; /* sgetl() accessed */
10910d63b7dSRichard Lowe char arf_mode[AR_PORT_WORD]; /* sgetl() accessed */
11010d63b7dSRichard Lowe char arf_size[AR_PORT_WORD]; /* sgetl() accessed */
11110d63b7dSRichard Lowe } Arf_5;
11210d63b7dSRichard Lowe
11310d63b7dSRichard Lowe typedef struct { /* Portable (6.0) ar format: vax family; 3b family */
11410d63b7dSRichard Lowe char ar_name[16]; /* Space terminated */
11510d63b7dSRichard Lowe /* left-adjusted fields; decimal ascii; blank filled */
11610d63b7dSRichard Lowe char ar_date[12];
11710d63b7dSRichard Lowe char ar_uid[6];
11810d63b7dSRichard Lowe char ar_gid[6];
11910d63b7dSRichard Lowe char ar_mode[8]; /* octal ascii */
12010d63b7dSRichard Lowe char ar_size[10];
12110d63b7dSRichard Lowe /* special end-of-header string (AR_PORT_END_MAGIC) */
12210d63b7dSRichard Lowe char ar_fmag[2];
12310d63b7dSRichard Lowe } Ar_port;
12410d63b7dSRichard Lowe
12510d63b7dSRichard Lowe enum ar_type {
12610d63b7dSRichard Lowe AR_5,
12710d63b7dSRichard Lowe AR_PORT
12810d63b7dSRichard Lowe };
12910d63b7dSRichard Lowe
13010d63b7dSRichard Lowe typedef unsigned int ar_port_word; // must be 4-bytes long
13110d63b7dSRichard Lowe
13210d63b7dSRichard Lowe typedef struct {
13310d63b7dSRichard Lowe FILE *fd;
13410d63b7dSRichard Lowe /* to distiguish ar format */
13510d63b7dSRichard Lowe enum ar_type type;
13610d63b7dSRichard Lowe /* where first ar member header is at */
13710d63b7dSRichard Lowe long first_ar_mem;
13810d63b7dSRichard Lowe /* where the symbol lookup starts */
13910d63b7dSRichard Lowe long sym_begin;
14010d63b7dSRichard Lowe /* the number of symbols available */
14110d63b7dSRichard Lowe long num_symbols;
14210d63b7dSRichard Lowe /* length of symbol directory file */
14310d63b7dSRichard Lowe long sym_size;
14410d63b7dSRichard Lowe Arh_5 arh_5;
14510d63b7dSRichard Lowe Ars_5 ars_5;
14610d63b7dSRichard Lowe Arf_5 arf_5;
14710d63b7dSRichard Lowe Ar_port ar_port;
14810d63b7dSRichard Lowe } Ar;
14910d63b7dSRichard Lowe
15010d63b7dSRichard Lowe /*
15110d63b7dSRichard Lowe * Static variables
15210d63b7dSRichard Lowe */
15310d63b7dSRichard Lowe
15410d63b7dSRichard Lowe /*
15510d63b7dSRichard Lowe * File table of contents
15610d63b7dSRichard Lowe */
157*e7afc443SToomas Soome extern timestruc_t& read_archive(Name target);
158*e7afc443SToomas Soome static Boolean open_archive(char *filename, Ar *arp);
159*e7afc443SToomas Soome static void close_archive(Ar *arp);
160*e7afc443SToomas Soome static Boolean read_archive_dir(Ar *arp, Name library, char **long_names_table);
161*e7afc443SToomas Soome static void translate_entry(Ar *arp, Name target, Property member, char **long_names_table);
16210d63b7dSRichard Lowe static long sgetl(char *);
16310d63b7dSRichard Lowe
16410d63b7dSRichard Lowe /*
16510d63b7dSRichard Lowe * read_archive(target)
16610d63b7dSRichard Lowe *
16710d63b7dSRichard Lowe * Read the contents of an ar file.
16810d63b7dSRichard Lowe *
16910d63b7dSRichard Lowe * Return value:
17010d63b7dSRichard Lowe * The time the member was created
17110d63b7dSRichard Lowe *
17210d63b7dSRichard Lowe * Parameters:
17310d63b7dSRichard Lowe * target The member to find time for
17410d63b7dSRichard Lowe *
17510d63b7dSRichard Lowe * Global variables used:
17610d63b7dSRichard Lowe * empty_name The Name ""
17710d63b7dSRichard Lowe */
17810d63b7dSRichard Lowe
17910d63b7dSRichard Lowe int read_member_header (Ar_port *header, FILE *fd, char* filename);
180*e7afc443SToomas Soome int process_long_names_member (Ar *arp, char **long_names_table, char *filename);
18110d63b7dSRichard Lowe
18210d63b7dSRichard Lowe timestruc_t&
read_archive(Name target)183*e7afc443SToomas Soome read_archive(Name target)
18410d63b7dSRichard Lowe {
185*e7afc443SToomas Soome Property member;
18610d63b7dSRichard Lowe wchar_t *slash;
18710d63b7dSRichard Lowe String_rec true_member_name;
18810d63b7dSRichard Lowe wchar_t buffer[STRING_BUFFER_LENGTH];
189*e7afc443SToomas Soome Name true_member = NULL;
19010d63b7dSRichard Lowe Ar ar;
19110d63b7dSRichard Lowe char *long_names_table = NULL; /* Table of long
19210d63b7dSRichard Lowe member names */
19310d63b7dSRichard Lowe
19410d63b7dSRichard Lowe member = get_prop(target->prop, member_prop);
19510d63b7dSRichard Lowe /*
19610d63b7dSRichard Lowe * Check if the member has directory component.
19710d63b7dSRichard Lowe * If so, remove the dir and see if we know the date.
19810d63b7dSRichard Lowe */
19910d63b7dSRichard Lowe if (member->body.member.member != NULL) {
20010d63b7dSRichard Lowe Wstring member_string(member->body.member.member);
20110d63b7dSRichard Lowe wchar_t * wcb = member_string.get_string();
20210d63b7dSRichard Lowe if((slash = (wchar_t *) wcsrchr(wcb, (int) slash_char)) != NULL) {
20310d63b7dSRichard Lowe INIT_STRING_FROM_STACK(true_member_name, buffer);
20410d63b7dSRichard Lowe append_string(member->body.member.library->string_mb,
20510d63b7dSRichard Lowe &true_member_name,
20610d63b7dSRichard Lowe FIND_LENGTH);
20710d63b7dSRichard Lowe append_char((int) parenleft_char, &true_member_name);
20810d63b7dSRichard Lowe append_string(slash + 1, &true_member_name, FIND_LENGTH);
20910d63b7dSRichard Lowe append_char((int) parenright_char, &true_member_name);
21010d63b7dSRichard Lowe true_member = GETNAME(true_member_name.buffer.start,
21110d63b7dSRichard Lowe FIND_LENGTH);
21210d63b7dSRichard Lowe if (true_member->stat.time != file_no_time) {
21310d63b7dSRichard Lowe target->stat.time = true_member->stat.time;
21410d63b7dSRichard Lowe return target->stat.time;
21510d63b7dSRichard Lowe }
21610d63b7dSRichard Lowe }
21710d63b7dSRichard Lowe }
21810d63b7dSRichard Lowe if (open_archive(member->body.member.library->string_mb, &ar) == failed) {
21910d63b7dSRichard Lowe if (errno == ENOENT) {
22010d63b7dSRichard Lowe target->stat.stat_errno = ENOENT;
22110d63b7dSRichard Lowe close_archive(&ar);
22210d63b7dSRichard Lowe if (member->body.member.member == NULL) {
22310d63b7dSRichard Lowe member->body.member.member = empty_name;
22410d63b7dSRichard Lowe }
22510d63b7dSRichard Lowe return target->stat.time = file_doesnt_exist;
22610d63b7dSRichard Lowe } else {
22710d63b7dSRichard Lowe fatal(gettext("Can't access archive `%s': %s"),
22810d63b7dSRichard Lowe member->body.member.library->string_mb,
22910d63b7dSRichard Lowe errmsg(errno));
23010d63b7dSRichard Lowe }
23110d63b7dSRichard Lowe }
23210d63b7dSRichard Lowe if (target->stat.time == file_no_time) {
23310d63b7dSRichard Lowe if (read_archive_dir(&ar, member->body.member.library,
23410d63b7dSRichard Lowe &long_names_table)
23510d63b7dSRichard Lowe == failed){
23610d63b7dSRichard Lowe fatal(gettext("Can't access archive `%s': %s"),
23710d63b7dSRichard Lowe member->body.member.library->string_mb,
23810d63b7dSRichard Lowe errmsg(errno));
23910d63b7dSRichard Lowe }
24010d63b7dSRichard Lowe }
24110d63b7dSRichard Lowe if (member->body.member.entry != NULL) {
24210d63b7dSRichard Lowe translate_entry(&ar, target, member,&long_names_table);
24310d63b7dSRichard Lowe }
24410d63b7dSRichard Lowe close_archive(&ar);
24510d63b7dSRichard Lowe if (long_names_table) {
24610d63b7dSRichard Lowe retmem_mb(long_names_table);
24710d63b7dSRichard Lowe }
24810d63b7dSRichard Lowe if (true_member != NULL) {
24910d63b7dSRichard Lowe target->stat.time = true_member->stat.time;
25010d63b7dSRichard Lowe }
25110d63b7dSRichard Lowe if (target->stat.time == file_no_time) {
25210d63b7dSRichard Lowe target->stat.time = file_doesnt_exist;
25310d63b7dSRichard Lowe }
25410d63b7dSRichard Lowe return target->stat.time;
25510d63b7dSRichard Lowe }
25610d63b7dSRichard Lowe
25710d63b7dSRichard Lowe /*
25810d63b7dSRichard Lowe * open_archive(filename, arp)
25910d63b7dSRichard Lowe *
26010d63b7dSRichard Lowe * Return value:
26110d63b7dSRichard Lowe * Indicates if open failed or not
26210d63b7dSRichard Lowe *
26310d63b7dSRichard Lowe * Parameters:
26410d63b7dSRichard Lowe * filename The name of the archive we need to read
26510d63b7dSRichard Lowe * arp Pointer to ar file description block
26610d63b7dSRichard Lowe *
26710d63b7dSRichard Lowe * Global variables used:
26810d63b7dSRichard Lowe */
26910d63b7dSRichard Lowe static Boolean
open_archive(char * filename,Ar * arp)270*e7afc443SToomas Soome open_archive(char *filename, Ar *arp)
27110d63b7dSRichard Lowe {
27210d63b7dSRichard Lowe int fd;
27310d63b7dSRichard Lowe char mag_5[AR_5_MAGIC_LENGTH];
27410d63b7dSRichard Lowe char mag_port[AR_PORT_MAGIC_LENGTH];
27510d63b7dSRichard Lowe char buffer[4];
27610d63b7dSRichard Lowe
27710d63b7dSRichard Lowe arp->fd = NULL;
27810d63b7dSRichard Lowe fd = open_vroot(filename, O_RDONLY, 0, NULL, VROOT_DEFAULT);
27910d63b7dSRichard Lowe if ((fd < 0) || ((arp->fd = fdopen(fd, "r")) == NULL)) {
28010d63b7dSRichard Lowe return failed;
28110d63b7dSRichard Lowe }
28210d63b7dSRichard Lowe (void) fcntl(fileno(arp->fd), F_SETFD, 1);
28310d63b7dSRichard Lowe
28410d63b7dSRichard Lowe if (fread(mag_port, AR_PORT_MAGIC_LENGTH, 1, arp->fd) != 1) {
28510d63b7dSRichard Lowe return failed;
28610d63b7dSRichard Lowe }
28710d63b7dSRichard Lowe if (IS_EQUALN(mag_port, AR_PORT_MAGIC, AR_PORT_MAGIC_LENGTH)) {
28810d63b7dSRichard Lowe arp->type = AR_PORT;
28910d63b7dSRichard Lowe /*
29010d63b7dSRichard Lowe * Read in first member header to find out if there is
29110d63b7dSRichard Lowe * a symbol definition table.
29210d63b7dSRichard Lowe */
29310d63b7dSRichard Lowe
29410d63b7dSRichard Lowe int ret = read_member_header(&arp->ar_port, arp->fd, filename);
29510d63b7dSRichard Lowe if (ret == failed) {
29610d63b7dSRichard Lowe return failed;
29710d63b7dSRichard Lowe } else if(ret == -1) {
29810d63b7dSRichard Lowe /* There is no member header - empty archive */
29910d63b7dSRichard Lowe arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
30010d63b7dSRichard Lowe arp->first_ar_mem = ftell(arp->fd);
30110d63b7dSRichard Lowe return succeeded;
30210d63b7dSRichard Lowe }
30310d63b7dSRichard Lowe /*
30410d63b7dSRichard Lowe * The following values are the default if there is
30510d63b7dSRichard Lowe * no symbol directory and long member names.
30610d63b7dSRichard Lowe */
30710d63b7dSRichard Lowe arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
30810d63b7dSRichard Lowe arp->first_ar_mem = ftell(arp->fd) - (long) sizeof (Ar_port);
30910d63b7dSRichard Lowe
31010d63b7dSRichard Lowe /*
31110d63b7dSRichard Lowe * Do we have a symbol table? A symbol table is always
31210d63b7dSRichard Lowe * the first member in an archive. In 4.1.x it has the
31310d63b7dSRichard Lowe * name __.SYMDEF, in SVr4, it has the name "/ "
31410d63b7dSRichard Lowe */
31510d63b7dSRichard Lowe /*
31610d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, "/ ");
31710d63b7dSRichard Lowe if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
31810d63b7dSRichard Lowe */
31910d63b7dSRichard Lowe if (IS_EQUALN(arp->ar_port.ar_name,
32010d63b7dSRichard Lowe "/ ",
32110d63b7dSRichard Lowe 16)) {
32210d63b7dSRichard Lowe if (sscanf(arp->ar_port.ar_size,
32310d63b7dSRichard Lowe "%ld",
32410d63b7dSRichard Lowe &arp->sym_size) != 1) {
32510d63b7dSRichard Lowe return failed;
32610d63b7dSRichard Lowe }
32710d63b7dSRichard Lowe arp->sym_size += (arp->sym_size & 1); /* round up */
32810d63b7dSRichard Lowe if (fread(buffer, sizeof buffer, 1, arp->fd) != 1) {
32910d63b7dSRichard Lowe return failed;
33010d63b7dSRichard Lowe }
33110d63b7dSRichard Lowe arp->num_symbols = sgetl(buffer);
33210d63b7dSRichard Lowe arp->sym_begin = ftell(arp->fd);
33310d63b7dSRichard Lowe arp->first_ar_mem = arp->sym_begin +
33410d63b7dSRichard Lowe arp->sym_size - sizeof buffer;
33510d63b7dSRichard Lowe }
33610d63b7dSRichard Lowe return succeeded;
33710d63b7dSRichard Lowe }
33810d63b7dSRichard Lowe fatal(gettext("`%s' is not an archive"), filename);
33910d63b7dSRichard Lowe /* NOTREACHED */
34010d63b7dSRichard Lowe return failed;
34110d63b7dSRichard Lowe }
34210d63b7dSRichard Lowe
34310d63b7dSRichard Lowe
34410d63b7dSRichard Lowe /*
34510d63b7dSRichard Lowe * close_archive(arp)
34610d63b7dSRichard Lowe *
34710d63b7dSRichard Lowe * Parameters:
34810d63b7dSRichard Lowe * arp Pointer to ar file description block
34910d63b7dSRichard Lowe *
35010d63b7dSRichard Lowe * Global variables used:
35110d63b7dSRichard Lowe */
35210d63b7dSRichard Lowe static void
close_archive(Ar * arp)353*e7afc443SToomas Soome close_archive(Ar *arp)
35410d63b7dSRichard Lowe {
35510d63b7dSRichard Lowe if (arp->fd != NULL) {
35610d63b7dSRichard Lowe (void) fclose(arp->fd);
35710d63b7dSRichard Lowe }
35810d63b7dSRichard Lowe }
35910d63b7dSRichard Lowe
36010d63b7dSRichard Lowe /*
36110d63b7dSRichard Lowe * read_archive_dir(arp, library, long_names_table)
36210d63b7dSRichard Lowe *
36310d63b7dSRichard Lowe * Reads the directory of an archive and enters all
36410d63b7dSRichard Lowe * the members into the make symboltable in lib(member) format
36510d63b7dSRichard Lowe * with their dates.
36610d63b7dSRichard Lowe *
36710d63b7dSRichard Lowe * Parameters:
36810d63b7dSRichard Lowe * arp Pointer to ar file description block
36910d63b7dSRichard Lowe * library Name of lib to enter members for.
37010d63b7dSRichard Lowe * Used to form "lib(member)" string.
37110d63b7dSRichard Lowe * long_names_table table that contains list of members
37210d63b7dSRichard Lowe * with names > 15 characters long
37310d63b7dSRichard Lowe *
37410d63b7dSRichard Lowe * Global variables used:
37510d63b7dSRichard Lowe */
37610d63b7dSRichard Lowe static Boolean
read_archive_dir(Ar * arp,Name library,char ** long_names_table)377*e7afc443SToomas Soome read_archive_dir(Ar *arp, Name library, char **long_names_table)
37810d63b7dSRichard Lowe {
37910d63b7dSRichard Lowe wchar_t *name_string;
38010d63b7dSRichard Lowe wchar_t *member_string;
381*e7afc443SToomas Soome long len;
382*e7afc443SToomas Soome wchar_t *p;
383*e7afc443SToomas Soome char *q;
384*e7afc443SToomas Soome Name name;
38510d63b7dSRichard Lowe Property member;
38610d63b7dSRichard Lowe long ptr;
38710d63b7dSRichard Lowe long date;
38810d63b7dSRichard Lowe
38910d63b7dSRichard Lowe int offset;
39010d63b7dSRichard Lowe
39110d63b7dSRichard Lowe /*
39210d63b7dSRichard Lowe * If any of the members has a name > 15 chars,
39310d63b7dSRichard Lowe * it will be found here.
39410d63b7dSRichard Lowe */
39510d63b7dSRichard Lowe if (process_long_names_member(arp, long_names_table, library->string_mb) == failed) {
39610d63b7dSRichard Lowe return failed;
39710d63b7dSRichard Lowe }
39810d63b7dSRichard Lowe name_string = ALLOC_WC((int) (library->hash.length +
39910d63b7dSRichard Lowe (int) ar_member_name_len * 2));
40010d63b7dSRichard Lowe (void) mbstowcs(name_string, library->string_mb, (int) library->hash.length);
40110d63b7dSRichard Lowe member_string = name_string + library->hash.length;
40210d63b7dSRichard Lowe *member_string++ = (int) parenleft_char;
40310d63b7dSRichard Lowe
40410d63b7dSRichard Lowe if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
40510d63b7dSRichard Lowe goto read_error;
40610d63b7dSRichard Lowe }
40710d63b7dSRichard Lowe /* Read the directory using the appropriate format */
40810d63b7dSRichard Lowe switch (arp->type) {
40910d63b7dSRichard Lowe case AR_5:
41010d63b7dSRichard Lowe for (;;) {
41110d63b7dSRichard Lowe if (fread((char *) &arp->arf_5, sizeof arp->arf_5, 1, arp->fd)
41210d63b7dSRichard Lowe != 1) {
41310d63b7dSRichard Lowe if (feof(arp->fd)) {
41410d63b7dSRichard Lowe return succeeded;
41510d63b7dSRichard Lowe }
41610d63b7dSRichard Lowe break;
41710d63b7dSRichard Lowe }
41810d63b7dSRichard Lowe len = sizeof arp->arf_5.arf_name;
41910d63b7dSRichard Lowe for (p = member_string, q = arp->arf_5.arf_name;
42010d63b7dSRichard Lowe (len > 0) && (*q != (int) nul_char) && !isspace(*q);
42110d63b7dSRichard Lowe ) {
42210d63b7dSRichard Lowe MBTOWC(p, q);
42310d63b7dSRichard Lowe p++;
42410d63b7dSRichard Lowe q++;
42510d63b7dSRichard Lowe }
42610d63b7dSRichard Lowe *p++ = (int) parenright_char;
42710d63b7dSRichard Lowe *p = (int) nul_char;
42810d63b7dSRichard Lowe name = GETNAME(name_string, FIND_LENGTH);
42910d63b7dSRichard Lowe /*
43010d63b7dSRichard Lowe * [tolik] Fix for dmake bug 1234018.
43110d63b7dSRichard Lowe * If name->stat.time is already set, then it should not
43210d63b7dSRichard Lowe * be changed. (D)make propogates time stamp for one
43310d63b7dSRichard Lowe * member, and when it calls exists() for another member,
43410d63b7dSRichard Lowe * the first one may be changed.
43510d63b7dSRichard Lowe */
43610d63b7dSRichard Lowe if(name->stat.time == file_no_time) {
43710d63b7dSRichard Lowe name->stat.time.tv_sec = sgetl(arp->arf_5.arf_date);
43810d63b7dSRichard Lowe name->stat.time.tv_nsec = LONG_MAX;
43910d63b7dSRichard Lowe }
44010d63b7dSRichard Lowe name->is_member = library->is_member;
44110d63b7dSRichard Lowe member = maybe_append_prop(name, member_prop);
44210d63b7dSRichard Lowe member->body.member.library = library;
44310d63b7dSRichard Lowe *--p = (int) nul_char;
44410d63b7dSRichard Lowe if (member->body.member.member == NULL) {
44510d63b7dSRichard Lowe member->body.member.member =
44610d63b7dSRichard Lowe GETNAME(member_string, FIND_LENGTH);
44710d63b7dSRichard Lowe }
44810d63b7dSRichard Lowe ptr = sgetl(arp->arf_5.arf_size);
44910d63b7dSRichard Lowe ptr += (ptr & 1);
45010d63b7dSRichard Lowe if (fseek(arp->fd, ptr, 1) != 0) {
45110d63b7dSRichard Lowe goto read_error;
45210d63b7dSRichard Lowe }
45310d63b7dSRichard Lowe }
45410d63b7dSRichard Lowe break;
45510d63b7dSRichard Lowe case AR_PORT:
45610d63b7dSRichard Lowe for (;;) {
45710d63b7dSRichard Lowe if ((fread((char *) &arp->ar_port,
45810d63b7dSRichard Lowe sizeof arp->ar_port,
45910d63b7dSRichard Lowe 1,
46010d63b7dSRichard Lowe arp->fd) != 1) ||
46110d63b7dSRichard Lowe !IS_EQUALN(arp->ar_port.ar_fmag,
46210d63b7dSRichard Lowe AR_PORT_END_MAGIC,
46310d63b7dSRichard Lowe sizeof arp->ar_port.ar_fmag)) {
46410d63b7dSRichard Lowe if (feof(arp->fd)) {
46510d63b7dSRichard Lowe return succeeded;
46610d63b7dSRichard Lowe }
46710d63b7dSRichard Lowe fatal(
46810d63b7dSRichard Lowe gettext("Read error in archive `%s': invalid archive file member header at 0x%x"),
46910d63b7dSRichard Lowe library->string_mb,
47010d63b7dSRichard Lowe ftell(arp->fd)
47110d63b7dSRichard Lowe );
47210d63b7dSRichard Lowe }
47310d63b7dSRichard Lowe /* If it's a long name, retrieve it from long name table */
47410d63b7dSRichard Lowe if (arp->ar_port.ar_name[0] == '/') {
47510d63b7dSRichard Lowe /*
47610d63b7dSRichard Lowe * "len" is used for hashing the string.
47710d63b7dSRichard Lowe * We're using "ar_member_name_len" instead of
47810d63b7dSRichard Lowe * the actual name length since it's the longest
47910d63b7dSRichard Lowe * string the "ar" command can handle at this
48010d63b7dSRichard Lowe * point.
48110d63b7dSRichard Lowe */
48210d63b7dSRichard Lowe len = ar_member_name_len;
48310d63b7dSRichard Lowe sscanf(arp->ar_port.ar_name + 1,
48410d63b7dSRichard Lowe "%ld",
48510d63b7dSRichard Lowe &offset);
48610d63b7dSRichard Lowe q = *long_names_table + offset;
48710d63b7dSRichard Lowe } else {
48810d63b7dSRichard Lowe q = arp->ar_port.ar_name;
48910d63b7dSRichard Lowe len = sizeof arp->ar_port.ar_name;
49010d63b7dSRichard Lowe }
49110d63b7dSRichard Lowe
49210d63b7dSRichard Lowe for (p = member_string;
49310d63b7dSRichard Lowe (len > 0) &&
49410d63b7dSRichard Lowe (*q != (int) nul_char) &&
49510d63b7dSRichard Lowe !isspace(*q) &&
49610d63b7dSRichard Lowe (*q != (int) slash_char);
49710d63b7dSRichard Lowe ) {
49810d63b7dSRichard Lowe MBTOWC(p, q);
49910d63b7dSRichard Lowe p++;
50010d63b7dSRichard Lowe q++;
50110d63b7dSRichard Lowe }
50210d63b7dSRichard Lowe *p++ = (int) parenright_char;
50310d63b7dSRichard Lowe *p = (int) nul_char;
50410d63b7dSRichard Lowe name = GETNAME(name_string, FIND_LENGTH);
50510d63b7dSRichard Lowe name->is_member = library->is_member;
50610d63b7dSRichard Lowe member = maybe_append_prop(name, member_prop);
50710d63b7dSRichard Lowe member->body.member.library = library;
50810d63b7dSRichard Lowe *--p = (int) nul_char;
50910d63b7dSRichard Lowe if (member->body.member.member == NULL) {
51010d63b7dSRichard Lowe member->body.member.member =
51110d63b7dSRichard Lowe GETNAME(member_string, FIND_LENGTH);
51210d63b7dSRichard Lowe }
51310d63b7dSRichard Lowe if (sscanf(arp->ar_port.ar_date, "%ld", &date) != 1) {
51410d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, name_string);
51510d63b7dSRichard Lowe fatal(gettext("Bad date field for member `%s' in archive `%s'"),
51610d63b7dSRichard Lowe mbs_buffer,
51710d63b7dSRichard Lowe library->string_mb);
51810d63b7dSRichard Lowe }
51910d63b7dSRichard Lowe /*
52010d63b7dSRichard Lowe * [tolik] Fix for dmake bug 1234018.
52110d63b7dSRichard Lowe */
52210d63b7dSRichard Lowe if(name->stat.time == file_no_time) {
52310d63b7dSRichard Lowe name->stat.time.tv_sec = date;
52410d63b7dSRichard Lowe name->stat.time.tv_nsec = LONG_MAX;
52510d63b7dSRichard Lowe }
52610d63b7dSRichard Lowe if (sscanf(arp->ar_port.ar_size, "%ld", &ptr) != 1) {
52710d63b7dSRichard Lowe WCSTOMBS(mbs_buffer, name_string);
52810d63b7dSRichard Lowe fatal(gettext("Bad size field for member `%s' in archive `%s'"),
52910d63b7dSRichard Lowe mbs_buffer,
53010d63b7dSRichard Lowe library->string_mb);
53110d63b7dSRichard Lowe }
53210d63b7dSRichard Lowe ptr += (ptr & 1);
53310d63b7dSRichard Lowe if (fseek(arp->fd, ptr, 1) != 0) {
53410d63b7dSRichard Lowe goto read_error;
53510d63b7dSRichard Lowe }
53610d63b7dSRichard Lowe }
53710d63b7dSRichard Lowe break;
53810d63b7dSRichard Lowe }
53910d63b7dSRichard Lowe
54010d63b7dSRichard Lowe /* Only here if fread() [or IS_EQUALN()] failed and not at EOF */
54110d63b7dSRichard Lowe read_error:
54210d63b7dSRichard Lowe fatal(gettext("Read error in archive `%s': %s"),
54310d63b7dSRichard Lowe library->string_mb,
54410d63b7dSRichard Lowe errmsg(errno));
54510d63b7dSRichard Lowe /* NOTREACHED */
54610d63b7dSRichard Lowe }
54710d63b7dSRichard Lowe
54810d63b7dSRichard Lowe
54910d63b7dSRichard Lowe /*
55010d63b7dSRichard Lowe * process_long_names_member(arp)
55110d63b7dSRichard Lowe *
55210d63b7dSRichard Lowe * If the archive contains members with names longer
55310d63b7dSRichard Lowe * than 15 characters, then it has a special member
55410d63b7dSRichard Lowe * with the name "// " that contains a table
55510d63b7dSRichard Lowe * of null-terminated long names. This member
55610d63b7dSRichard Lowe * is always the first member, after the symbol table
55710d63b7dSRichard Lowe * if it exists.
55810d63b7dSRichard Lowe *
55910d63b7dSRichard Lowe * Parameters:
56010d63b7dSRichard Lowe * arp Pointer to ar file description block
56110d63b7dSRichard Lowe *
56210d63b7dSRichard Lowe * Global variables used:
56310d63b7dSRichard Lowe */
56410d63b7dSRichard Lowe int
process_long_names_member(Ar * arp,char ** long_names_table,char * filename)565*e7afc443SToomas Soome process_long_names_member(Ar *arp, char **long_names_table, char *filename)
56610d63b7dSRichard Lowe {
56710d63b7dSRichard Lowe Ar_port *ar_member_header;
56810d63b7dSRichard Lowe int table_size;
56910d63b7dSRichard Lowe
57010d63b7dSRichard Lowe if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
57110d63b7dSRichard Lowe return failed;
57210d63b7dSRichard Lowe }
57310d63b7dSRichard Lowe if ((ar_member_header =
57410d63b7dSRichard Lowe (Ar_port *) alloca((int) sizeof(Ar_port))) == NULL){
57510d63b7dSRichard Lowe perror(gettext("memory allocation failure"));
57610d63b7dSRichard Lowe return failed;
57710d63b7dSRichard Lowe }
57810d63b7dSRichard Lowe int ret = read_member_header(ar_member_header, arp->fd, filename);
57910d63b7dSRichard Lowe if (ret == failed) {
58010d63b7dSRichard Lowe return failed;
58110d63b7dSRichard Lowe } else if(ret == -1) {
58210d63b7dSRichard Lowe /* There is no member header - empty archive */
58310d63b7dSRichard Lowe return succeeded;
58410d63b7dSRichard Lowe }
58510d63b7dSRichard Lowe /* Do we have special member containing long names? */
58610d63b7dSRichard Lowe if (IS_EQUALN(ar_member_header->ar_name,
58710d63b7dSRichard Lowe "// ",
58810d63b7dSRichard Lowe 16)){
58910d63b7dSRichard Lowe if (sscanf(ar_member_header->ar_size,
59010d63b7dSRichard Lowe "%ld",
59110d63b7dSRichard Lowe &table_size) != 1) {
59210d63b7dSRichard Lowe return failed;
59310d63b7dSRichard Lowe }
59410d63b7dSRichard Lowe *long_names_table = (char *) malloc(table_size);
59510d63b7dSRichard Lowe /* Read the list of long member names into the table */
59610d63b7dSRichard Lowe if (fread(*long_names_table, table_size, 1, arp->fd) != 1) {
59710d63b7dSRichard Lowe return failed;
59810d63b7dSRichard Lowe }
59910d63b7dSRichard Lowe arp->first_ar_mem = ftell(arp->fd);
60010d63b7dSRichard Lowe }
60110d63b7dSRichard Lowe return succeeded;
60210d63b7dSRichard Lowe }
60310d63b7dSRichard Lowe
60410d63b7dSRichard Lowe /*
60510d63b7dSRichard Lowe * translate_entry(arp, target, member)
60610d63b7dSRichard Lowe *
60710d63b7dSRichard Lowe * Finds the member for one lib.a((entry))
60810d63b7dSRichard Lowe *
60910d63b7dSRichard Lowe * Parameters:
61010d63b7dSRichard Lowe * arp Pointer to ar file description block
61110d63b7dSRichard Lowe * target Target to find member name for
61210d63b7dSRichard Lowe * member Property to fill in with info
61310d63b7dSRichard Lowe *
61410d63b7dSRichard Lowe * Global variables used:
61510d63b7dSRichard Lowe */
61610d63b7dSRichard Lowe static void
translate_entry(Ar * arp,Name target,Property member,char ** long_names_table)617*e7afc443SToomas Soome translate_entry(Ar *arp, Name target, Property member, char **long_names_table)
61810d63b7dSRichard Lowe {
619*e7afc443SToomas Soome int len;
620*e7afc443SToomas Soome int i;
62110d63b7dSRichard Lowe wchar_t *member_string;
62210d63b7dSRichard Lowe ar_port_word *offs;
62310d63b7dSRichard Lowe int strtablen;
62410d63b7dSRichard Lowe char *syms; /* string table */
62510d63b7dSRichard Lowe char *csym; /* string table */
62610d63b7dSRichard Lowe ar_port_word *offend; /* end of offsets table */
62710d63b7dSRichard Lowe int date;
628*e7afc443SToomas Soome wchar_t *ap;
629*e7afc443SToomas Soome char *hp;
63010d63b7dSRichard Lowe int maxs;
63110d63b7dSRichard Lowe int offset;
63210d63b7dSRichard Lowe char buffer[4];
63310d63b7dSRichard Lowe
63410d63b7dSRichard Lowe if (arp->sym_begin == 0L || arp->num_symbols == 0L) {
63510d63b7dSRichard Lowe fatal(gettext("Cannot find symbol `%s' in archive `%s'"),
63610d63b7dSRichard Lowe member->body.member.entry->string_mb,
63710d63b7dSRichard Lowe member->body.member.library->string_mb);
63810d63b7dSRichard Lowe }
63910d63b7dSRichard Lowe
64010d63b7dSRichard Lowe if (fseek(arp->fd, arp->sym_begin, 0) != 0) {
64110d63b7dSRichard Lowe goto read_error;
64210d63b7dSRichard Lowe }
64310d63b7dSRichard Lowe member_string = ALLOC_WC((int) ((int) ar_member_name_len * 2));
64410d63b7dSRichard Lowe
64510d63b7dSRichard Lowe switch (arp->type) {
64610d63b7dSRichard Lowe case AR_5:
64710d63b7dSRichard Lowe if ((len = member->body.member.entry->hash.length) > 8) {
64810d63b7dSRichard Lowe len = 8;
64910d63b7dSRichard Lowe }
65010d63b7dSRichard Lowe for (i = 0; i < arp->num_symbols; i++) {
65110d63b7dSRichard Lowe if (fread((char *) &arp->ars_5,
65210d63b7dSRichard Lowe sizeof arp->ars_5,
65310d63b7dSRichard Lowe 1,
65410d63b7dSRichard Lowe arp->fd) != 1) {
65510d63b7dSRichard Lowe goto read_error;
65610d63b7dSRichard Lowe }
65710d63b7dSRichard Lowe if (IS_EQUALN(arp->ars_5.sym_name,
65810d63b7dSRichard Lowe member->body.member.entry->string_mb,
65910d63b7dSRichard Lowe len)) {
66010d63b7dSRichard Lowe if ((fseek(arp->fd,
66110d63b7dSRichard Lowe sgetl(arp->ars_5.sym_ptr),
66210d63b7dSRichard Lowe 0) != 0) ||
66310d63b7dSRichard Lowe (fread((char *) &arp->arf_5,
66410d63b7dSRichard Lowe sizeof arp->arf_5,
66510d63b7dSRichard Lowe 1,
66610d63b7dSRichard Lowe arp->fd) != 1)) {
66710d63b7dSRichard Lowe goto read_error;
66810d63b7dSRichard Lowe }
66910d63b7dSRichard Lowe MBSTOWCS(wcs_buffer, arp->arf_5.arf_name);
67010d63b7dSRichard Lowe (void) wcsncpy(member_string,
67110d63b7dSRichard Lowe wcs_buffer,
67210d63b7dSRichard Lowe wcslen(wcs_buffer));
67310d63b7dSRichard Lowe member_string[sizeof(arp->arf_5.arf_name)] =
67410d63b7dSRichard Lowe (int) nul_char;
67510d63b7dSRichard Lowe member->body.member.member =
67610d63b7dSRichard Lowe GETNAME(member_string, FIND_LENGTH);
67710d63b7dSRichard Lowe target->stat.time.tv_sec = sgetl(arp->arf_5.arf_date);
67810d63b7dSRichard Lowe target->stat.time.tv_nsec = LONG_MAX;
67910d63b7dSRichard Lowe return;
68010d63b7dSRichard Lowe }
68110d63b7dSRichard Lowe }
68210d63b7dSRichard Lowe break;
68310d63b7dSRichard Lowe case AR_PORT:
68410d63b7dSRichard Lowe offs = (ar_port_word *) alloca((int) (arp->num_symbols * AR_PORT_WORD));
68510d63b7dSRichard Lowe if (fread((char *) offs,
68610d63b7dSRichard Lowe AR_PORT_WORD,
68710d63b7dSRichard Lowe (int) arp->num_symbols,
68810d63b7dSRichard Lowe arp->fd) != arp->num_symbols) {
68910d63b7dSRichard Lowe goto read_error;
69010d63b7dSRichard Lowe }
69110d63b7dSRichard Lowe
69210d63b7dSRichard Lowe for(i=0;i<arp->num_symbols;i++) {
69310d63b7dSRichard Lowe *((int*)buffer)=offs[i];
69410d63b7dSRichard Lowe offs[i]=(ar_port_word)sgetl(buffer);
69510d63b7dSRichard Lowe }
69610d63b7dSRichard Lowe
69710d63b7dSRichard Lowe strtablen=arp->sym_size-4-(int) (arp->num_symbols * AR_PORT_WORD);
69810d63b7dSRichard Lowe syms = (char *) alloca(strtablen);
69910d63b7dSRichard Lowe if (fread(syms,
70010d63b7dSRichard Lowe sizeof (char),
70110d63b7dSRichard Lowe strtablen,
70210d63b7dSRichard Lowe arp->fd) != strtablen) {
70310d63b7dSRichard Lowe goto read_error;
70410d63b7dSRichard Lowe }
70510d63b7dSRichard Lowe offend = &offs[arp->num_symbols];
70610d63b7dSRichard Lowe while (offs < offend) {
70710d63b7dSRichard Lowe maxs = strlen(member->body.member.entry->string_mb);
70810d63b7dSRichard Lowe if(strlen(syms) > maxs)
70910d63b7dSRichard Lowe maxs = strlen(syms);
71010d63b7dSRichard Lowe if (IS_EQUALN(syms,
71110d63b7dSRichard Lowe member->body.member.entry->string_mb,
71210d63b7dSRichard Lowe maxs)) {
71310d63b7dSRichard Lowe if (fseek(arp->fd,
71410d63b7dSRichard Lowe (long) *offs,
71510d63b7dSRichard Lowe 0) != 0) {
71610d63b7dSRichard Lowe goto read_error;
71710d63b7dSRichard Lowe }
71810d63b7dSRichard Lowe if ((fread((char *) &arp->ar_port,
71910d63b7dSRichard Lowe sizeof arp->ar_port,
72010d63b7dSRichard Lowe 1,
72110d63b7dSRichard Lowe arp->fd) != 1) ||
72210d63b7dSRichard Lowe !IS_EQUALN(arp->ar_port.ar_fmag,
72310d63b7dSRichard Lowe AR_PORT_END_MAGIC,
72410d63b7dSRichard Lowe sizeof arp->ar_port.ar_fmag)) {
72510d63b7dSRichard Lowe goto read_error;
72610d63b7dSRichard Lowe }
72710d63b7dSRichard Lowe if (sscanf(arp->ar_port.ar_date,
72810d63b7dSRichard Lowe "%ld",
72910d63b7dSRichard Lowe &date) != 1) {
73010d63b7dSRichard Lowe fatal(gettext("Bad date field for member `%s' in archive `%s'"),
73110d63b7dSRichard Lowe arp->ar_port.ar_name,
73210d63b7dSRichard Lowe target->string_mb);
73310d63b7dSRichard Lowe }
73410d63b7dSRichard Lowe /* If it's a long name, retrieve it from long name table */
73510d63b7dSRichard Lowe if (arp->ar_port.ar_name[0] == '/') {
73610d63b7dSRichard Lowe sscanf(arp->ar_port.ar_name + 1,
73710d63b7dSRichard Lowe "%ld",
73810d63b7dSRichard Lowe &offset);
73910d63b7dSRichard Lowe len = ar_member_name_len;
74010d63b7dSRichard Lowe hp = *long_names_table + offset;
74110d63b7dSRichard Lowe } else {
74210d63b7dSRichard Lowe len = sizeof arp->ar_port.ar_name;
74310d63b7dSRichard Lowe hp = arp->ar_port.ar_name;
74410d63b7dSRichard Lowe }
74510d63b7dSRichard Lowe ap = member_string;
74610d63b7dSRichard Lowe while (*hp &&
74710d63b7dSRichard Lowe (*hp != (int) slash_char) &&
74810d63b7dSRichard Lowe (ap < &member_string[len])) {
74910d63b7dSRichard Lowe MBTOWC(ap, hp);
75010d63b7dSRichard Lowe ap++;
75110d63b7dSRichard Lowe hp++;
75210d63b7dSRichard Lowe }
75310d63b7dSRichard Lowe *ap = (int) nul_char;
75410d63b7dSRichard Lowe member->body.member.member =
75510d63b7dSRichard Lowe GETNAME(member_string, FIND_LENGTH);
75610d63b7dSRichard Lowe target->stat.time.tv_sec = date;
75710d63b7dSRichard Lowe target->stat.time.tv_nsec = LONG_MAX;
75810d63b7dSRichard Lowe return;
75910d63b7dSRichard Lowe }
76010d63b7dSRichard Lowe offs++;
76110d63b7dSRichard Lowe while(*syms!='\0') syms++;
76210d63b7dSRichard Lowe syms++;
76310d63b7dSRichard Lowe }
76410d63b7dSRichard Lowe }
76510d63b7dSRichard Lowe fatal(gettext("Cannot find symbol `%s' in archive `%s'"),
76610d63b7dSRichard Lowe member->body.member.entry->string_mb,
76710d63b7dSRichard Lowe member->body.member.library->string_mb);
76810d63b7dSRichard Lowe /*NOTREACHED*/
76910d63b7dSRichard Lowe
77010d63b7dSRichard Lowe read_error:
77110d63b7dSRichard Lowe if (ferror(arp->fd)) {
77210d63b7dSRichard Lowe fatal(gettext("Read error in archive `%s': %s"),
77310d63b7dSRichard Lowe member->body.member.library->string_mb,
77410d63b7dSRichard Lowe errmsg(errno));
77510d63b7dSRichard Lowe } else {
77610d63b7dSRichard Lowe fatal(gettext("Read error in archive `%s': Premature EOF"),
77710d63b7dSRichard Lowe member->body.member.library->string_mb);
77810d63b7dSRichard Lowe }
77910d63b7dSRichard Lowe }
78010d63b7dSRichard Lowe
78110d63b7dSRichard Lowe /*
78210d63b7dSRichard Lowe * sgetl(buffer)
78310d63b7dSRichard Lowe *
78410d63b7dSRichard Lowe * The intent here is to provide a means to make the value of
78510d63b7dSRichard Lowe * bytes in an io-buffer correspond to the value of a long
78610d63b7dSRichard Lowe * in the memory while doing the io a long at a time.
78710d63b7dSRichard Lowe * Files written and read in this way are machine-independent.
78810d63b7dSRichard Lowe *
78910d63b7dSRichard Lowe * Return value:
79010d63b7dSRichard Lowe * Long int read from buffer
79110d63b7dSRichard Lowe * Parameters:
79210d63b7dSRichard Lowe * buffer buffer we need to read long int from
79310d63b7dSRichard Lowe *
79410d63b7dSRichard Lowe * Global variables used:
79510d63b7dSRichard Lowe */
79610d63b7dSRichard Lowe static long
sgetl(char * buffer)797*e7afc443SToomas Soome sgetl(char *buffer)
79810d63b7dSRichard Lowe {
799*e7afc443SToomas Soome long w = 0;
800*e7afc443SToomas Soome int i = BITSPERBYTE * AR_PORT_WORD;
80110d63b7dSRichard Lowe
80210d63b7dSRichard Lowe while ((i -= BITSPERBYTE) >= 0) {
80310d63b7dSRichard Lowe w |= (long) ((unsigned char) *buffer++) << i;
80410d63b7dSRichard Lowe }
80510d63b7dSRichard Lowe return w;
80610d63b7dSRichard Lowe }
80710d63b7dSRichard Lowe
80810d63b7dSRichard Lowe
80910d63b7dSRichard Lowe /*
81010d63b7dSRichard Lowe * read_member_header(header, fd, filename)
81110d63b7dSRichard Lowe *
81210d63b7dSRichard Lowe * reads the member header for the 4.1.x and SVr4 archives.
81310d63b7dSRichard Lowe *
81410d63b7dSRichard Lowe * Return value:
81510d63b7dSRichard Lowe * fails if read error or member
81610d63b7dSRichard Lowe * header is not the right format
81710d63b7dSRichard Lowe * Parameters:
81810d63b7dSRichard Lowe * header There's one before each archive member
81910d63b7dSRichard Lowe * fd file descriptor for the archive file.
82010d63b7dSRichard Lowe *
82110d63b7dSRichard Lowe * Global variables used:
82210d63b7dSRichard Lowe */
82310d63b7dSRichard Lowe int
read_member_header(Ar_port * header,FILE * fd,char * filename)82410d63b7dSRichard Lowe read_member_header(Ar_port *header, FILE *fd, char* filename)
82510d63b7dSRichard Lowe {
82610d63b7dSRichard Lowe int num = fread((char *) header, sizeof (Ar_port), 1, fd);
82710d63b7dSRichard Lowe if (num != 1 && feof(fd)) {
82810d63b7dSRichard Lowe /* There is no member header - empty archive */
82910d63b7dSRichard Lowe return -1;
83010d63b7dSRichard Lowe }
83110d63b7dSRichard Lowe if ((num != 1) ||
83210d63b7dSRichard Lowe !IS_EQUALN(
83310d63b7dSRichard Lowe AR_PORT_END_MAGIC,
83410d63b7dSRichard Lowe header->ar_fmag,
83510d63b7dSRichard Lowe sizeof (header->ar_fmag)
83610d63b7dSRichard Lowe )
83710d63b7dSRichard Lowe ) {
83810d63b7dSRichard Lowe fatal(
83910d63b7dSRichard Lowe gettext("Read error in archive `%s': invalid archive file member header at 0x%x"),
84010d63b7dSRichard Lowe filename,
84110d63b7dSRichard Lowe ftell(fd)
84210d63b7dSRichard Lowe );
84310d63b7dSRichard Lowe }
84410d63b7dSRichard Lowe return succeeded;
84510d63b7dSRichard Lowe }
84610d63b7dSRichard Lowe
847