/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* ar.c
*
* Deal with the lib.a(member.o) and lib.a((entry-point)) notations
*
* Look inside archives for notations a(b) and a((b))
* a(b) is file member b in archive a
* a((b)) is entry point b in object archive a
*
* For 6.0, create a make which can understand all archive
* formats. This is kind of tricky, and <ar.h> isnt any help.
*/
/*
* Included files
*/
#include <alloca.h> /* alloca() */
#include <ar.h>
#include <errno.h> /* errno */
#include <fcntl.h> /* open() */
#include <libintl.h>
struct ranlib {
union {
} ran_un;
};
#include <unistd.h> /* close() */
/*
* Defined macros
*/
#ifndef S5EMUL
#endif
/*
* Defines for all the different archive formats. See next comment
* block for justification for not using <ar.h>s versions.
*/
/*
* typedefs & structs
*/
/*
* These are the archive file headers for the formats. Note
* that it really doesnt matter if these structures are defined
* here. They are correct as of the respective archive format
* releases. If the archive format is changed, then since backwards
* compatability is the desired behavior, a new structure is added
* to the list.
*/
typedef struct { /* 5.0 ar header format: vax family; 3b family */
} Arh_5;
typedef struct { /* 5.0 ar symbol format: vax family; 3b family */
} Ars_5;
typedef struct { /* 5.0 ar member format: vax family; 3b family */
} Arf_5;
typedef struct { /* Portable (6.0) ar format: vax family; 3b family */
/* left-adjusted fields; decimal ascii; blank filled */
/* special end-of-header string (AR_PORT_END_MAGIC) */
} Ar_port;
enum ar_type {
AR_5,
};
typedef struct {
/* to distiguish ar format */
/* where first ar member header is at */
long first_ar_mem;
/* where the symbol lookup starts */
long sym_begin;
/* the number of symbols available */
long num_symbols;
/* length of symbol directory file */
long sym_size;
} Ar;
/*
* Static variables
*/
/*
* File table of contents
*/
static void translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table);
static long sgetl(char *);
/*
* read_archive(target)
*
* Read the contents of an ar file.
*
* Return value:
* The time the member was created
*
* Parameters:
* target The member to find time for
*
* Global variables used:
* empty_name The Name ""
*/
{
wchar_t *slash;
member names */
/*
* Check if the member has directory component.
* If so, remove the dir and see if we know the date.
*/
}
}
}
close_archive(&ar);
}
} else {
}
}
== failed){
}
}
}
close_archive(&ar);
if (long_names_table) {
}
if (true_member != NULL) {
}
}
}
/*
* open_archive(filename, arp)
*
* Return value:
* Indicates if open failed or not
*
* Parameters:
* filename The name of the archive we need to read
* arp Pointer to ar file description block
*
* Global variables used:
*/
static Boolean
{
int fd;
return failed;
}
return failed;
}
/*
* Read in first member header to find out if there is
* a symbol definition table.
*/
return failed;
} else if(ret == -1) {
/* There is no member header - empty archive */
return succeeded;
}
/*
* The following values are the default if there is
* no symbol directory and long member names.
*/
/*
* Do we have a symbol table? A symbol table is always
* the first member in an archive. In 4.1.x it has the
* name __.SYMDEF, in SVr4, it has the name "/ "
*/
/*
MBSTOWCS(wcs_buffer, "/ ");
if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
*/
"/ ",
16)) {
"%ld",
return failed;
}
return failed;
}
}
return succeeded;
}
/* NOTREACHED */
return failed;
}
/*
* close_archive(arp)
*
* Parameters:
* arp Pointer to ar file description block
*
* Global variables used:
*/
static void
{
}
}
/*
* read_archive_dir(arp, library, long_names_table)
*
* Reads the directory of an archive and enters all
* the members into the make symboltable in lib(member) format
* with their dates.
*
* Parameters:
* arp Pointer to ar file description block
* library Name of lib to enter members for.
* Used to form "lib(member)" string.
* long_names_table table that contains list of members
* with names > 15 characters long
*
* Global variables used:
*/
static Boolean
{
wchar_t *name_string;
wchar_t *member_string;
register long len;
register wchar_t *p;
register char *q;
long ptr;
long date;
int offset;
/*
* If any of the members has a name > 15 chars,
* it will be found here.
*/
return failed;
}
(int) ar_member_name_len * 2));
*member_string++ = (int) parenleft_char;
goto read_error;
}
/* Read the directory using the appropriate format */
case AR_5:
for (;;) {
!= 1) {
return succeeded;
}
break;
}
) {
MBTOWC(p, q);
p++;
q++;
}
*p++ = (int) parenright_char;
*p = (int) nul_char;
/*
* [tolik] Fix for dmake bug 1234018.
* If name->stat.time is already set, then it should not
* be changed. (D)make propogates time stamp for one
* member, and when it calls exists() for another member,
* the first one may be changed.
*/
}
*--p = (int) nul_char;
}
goto read_error;
}
}
break;
case AR_PORT:
for (;;) {
1,
return succeeded;
}
gettext("Read error in archive `%s': invalid archive file member header at 0x%x"),
);
}
/* If it's a long name, retrieve it from long name table */
/*
* "len" is used for hashing the string.
* We're using "ar_member_name_len" instead of
* the actual name length since it's the longest
* string the "ar" command can handle at this
* point.
*/
"%ld",
&offset);
q = *long_names_table + offset;
} else {
}
for (p = member_string;
(len > 0) &&
(*q != (int) nul_char) &&
!isspace(*q) &&
(*q != (int) slash_char);
) {
MBTOWC(p, q);
p++;
q++;
}
*p++ = (int) parenright_char;
*p = (int) nul_char;
*--p = (int) nul_char;
}
}
/*
* [tolik] Fix for dmake bug 1234018.
*/
}
}
goto read_error;
}
}
break;
}
/* Only here if fread() [or IS_EQUALN()] failed and not at EOF */
/* NOTREACHED */
}
/*
* process_long_names_member(arp)
*
* If the archive contains members with names longer
* than 15 characters, then it has a special member
* with the name "// " that contains a table
* of null-terminated long names. This member
* is always the first member, after the symbol table
* if it exists.
*
* Parameters:
* arp Pointer to ar file description block
*
* Global variables used:
*/
int
{
int table_size;
return failed;
}
if ((ar_member_header =
return failed;
}
return failed;
} else if(ret == -1) {
/* There is no member header - empty archive */
return succeeded;
}
/* Do we have special member containing long names? */
"// ",
16)){
"%ld",
&table_size) != 1) {
return failed;
}
/* Read the list of long member names into the table */
return failed;
}
}
return succeeded;
}
/*
* translate_entry(arp, target, member)
*
* Finds the member for one lib.a((entry))
*
* Parameters:
* arp Pointer to ar file description block
* target Target to find member name for
* member Property to fill in with info
*
* Global variables used:
*/
static void
{
register int len;
register int i;
wchar_t *member_string;
int strtablen;
int date;
register wchar_t *ap;
register char *hp;
int maxs;
int offset;
}
goto read_error;
}
case AR_5:
len = 8;
}
for (i = 0; i < arp->num_symbols; i++) {
1,
goto read_error;
}
len)) {
0) != 0) ||
1,
goto read_error;
}
(void) wcsncpy(member_string,
wcslen(wcs_buffer));
(int) nul_char;
return;
}
}
break;
case AR_PORT:
(int) arp->num_symbols,
goto read_error;
}
for(i=0;i<arp->num_symbols;i++) {
}
sizeof (char),
goto read_error;
}
maxs)) {
(long) *offs,
0) != 0) {
goto read_error;
}
1,
goto read_error;
}
"%ld",
&date) != 1) {
}
/* If it's a long name, retrieve it from long name table */
"%ld",
&offset);
} else {
}
ap = member_string;
while (*hp &&
(*hp != (int) slash_char) &&
ap++;
hp++;
}
return;
}
offs++;
syms++;
}
}
/*NOTREACHED*/
} else {
}
}
/*
* sgetl(buffer)
*
* The intent here is to provide a means to make the value of
* bytes in an io-buffer correspond to the value of a long
* in the memory while doing the io a long at a time.
* Files written and read in this way are machine-independent.
*
* Return value:
* Long int read from buffer
* Parameters:
* buffer buffer we need to read long int from
*
* Global variables used:
*/
static long
{
register long w = 0;
register int i = BITSPERBYTE * AR_PORT_WORD;
while ((i -= BITSPERBYTE) >= 0) {
w |= (long) ((unsigned char) *buffer++) << i;
}
return w;
}
/*
* read_member_header(header, fd, filename)
*
* reads the member header for the 4.1.x and SVr4 archives.
*
* Return value:
* fails if read error or member
* header is not the right format
* Parameters:
* header There's one before each archive member
* fd file descriptor for the archive file.
*
* Global variables used:
*/
int
{
/* There is no member header - empty archive */
return -1;
}
if ((num != 1) ||
)
) {
gettext("Read error in archive `%s': invalid archive file member header at 0x%x"),
);
}
return succeeded;
}