Add support for thin archives.

* bfd/archive.c (_bfd_find_nested_archive): New function.
    (get_extended_arelt_filename): Add origin parameter.
    (_bfd_generic_read_ar_hdr_mag): Deal with extended name
    combined with a file offset.
    (append_relative_path): New function.
    (_bfd_get_elt_at_filepos): Deal with external members and
    nested archives.
    (bfd_generic_openr_next_archived_file): Thin archives.
    (bfd_generic_archive_p): Recognize new magic string.
    (adjust_relative_path): New function.
    (_bfd_construct_extended_name_table): Construct extended
    names for thin archive members.
    (_bfd_write_archive_contents): Emit new magic string, skip
    copying files for thin archives.
    * bfd/bfd-in.h (bfd_is_thin_archive): New macro.
    * bfd/bfd.c (struct bfd): New fields for thin archives.
    * bfd/libbfd-in.h (struct areltdata): New field for thin archives.
    * bfd/opncls.c (bfd_close): Delete BFDs for nested archives.
    * binutils/ar.c (make_thin_archive): New global flag.
    (map_over_members): Deal with full pathnames in thin archives.
    (usage, main): Add 'T' option for building thin archives.
    (replace_members): Pass thin archive flag to ar_emul_append.
    * binutils/arsup.c (ar_open): Initialize new flag.
    * binutils/binemul.c (ar_emul_append): Add new parameter for
    flattening nested archives.
    (do_ar_emul_default_append): New function.
    (ar_emul_default_append): Factored out recursive code.
    * binutils/binemul.h (ar_emul_default_append): Add new parameter.
    (struct bin_emulation_xfer_struct): New parameter for ar_append.
    * binutils/dlltool.c (gen_lib_file): Initialize thin archive flag.
    * binutils/emul_aix.c (ar_emul_aix_internal): Add new flatten
    parameter, currently unimplemented.
    All callers changed.
    * binutils/objcopy.c (copy_archive): Preserve thin archive flag.
    * binutils/doc/binutils.texi: Update ar documentation.
    * binutils/testsuite/binutils-all/ar.exp: Add thin archive tests.
    * include/aout/ar.h (ARMAGT): New magic string for thin archives.
This commit is contained in:
Nick Clifton 2008-03-28 06:49:44 +00:00
parent 5c81783097
commit a8da640382
22 changed files with 667 additions and 105 deletions

View File

@ -1,3 +1,25 @@
2008-03-27 Cary Coutant <ccoutant@google.com>
Add support for thin archives.
* archive.c (_bfd_find_nested_archive): New function.
(get_extended_arelt_filename): Add origin parameter.
(_bfd_generic_read_ar_hdr_mag): Deal with extended name
combined with a file offset.
(append_relative_path): New function.
(_bfd_get_elt_at_filepos): Deal with external members and
nested archives.
(bfd_generic_openr_next_archived_file): Thin archives.
(bfd_generic_archive_p): Recognize new magic string.
(adjust_relative_path): New function.
(_bfd_construct_extended_name_table): Construct extended
names for thin archive members.
(_bfd_write_archive_contents): Emit new magic string, skip
copying files for thin archives.
* bfd-in.h (bfd_is_thin_archive): New macro.
* bfd.c (struct bfd): New fields for thin archives.
* libbfd-in.h (struct areltdata): New field for thin archives.
* opncls.c (bfd_close): Delete BFDs for nested archives.
2008-03-25 Bernd Schmidt <bernd.schmidt@analog.com>
* elf32-bfin.c (bfin_final_link_relocate): New function, wrapper around

View File

@ -1,6 +1,6 @@
/* BFD back-end for archive files (libraries).
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault.
@ -137,6 +137,7 @@ SUBSECTION
#include "aout/ranlib.h"
#include "safe-ctype.h"
#include "hashtab.h"
#include "filenames.h"
#ifndef errno
extern int errno;
@ -157,7 +158,7 @@ struct ar_cache {
#define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
#define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
#define arch_hdr(bfd) ((struct ar_hdr *) arch_eltdata(bfd)->arch_header)
#define arch_hdr(bfd) ((struct ar_hdr *) arch_eltdata (bfd)->arch_header)
void
_bfd_ar_spacepad (char *p, size_t n, const char *fmt, long val)
@ -326,24 +327,61 @@ _bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt)
return TRUE;
}
static bfd *
_bfd_find_nested_archive (bfd *arch_bfd, const char *filename)
{
bfd *abfd;
for (abfd = arch_bfd->nested_archives;
abfd != NULL;
abfd = abfd->archive_next)
{
if (strcmp (filename, abfd->filename) == 0)
return abfd;
}
abfd = bfd_openr (filename, NULL);
if (abfd)
{
abfd->archive_next = arch_bfd->nested_archives;
arch_bfd->nested_archives = abfd;
}
return abfd;
}
/* The name begins with space. Hence the rest of the name is an index into
the string table. */
static char *
get_extended_arelt_filename (bfd *arch, const char *name)
get_extended_arelt_filename (bfd *arch, const char *name, file_ptr *originp)
{
unsigned long index = 0;
const char *endp;
/* Should extract string so that I can guarantee not to overflow into
the next region, but I'm too lazy. */
errno = 0;
/* Skip first char, which is '/' in SVR4 or ' ' in some other variants. */
index = strtol (name + 1, NULL, 10);
index = strtol (name + 1, (char **) &endp, 10);
if (errno != 0 || index >= bfd_ardata (arch)->extended_names_size)
{
bfd_set_error (bfd_error_malformed_archive);
return NULL;
}
/* In a thin archive, a member of an archive-within-an-archive
will have the offset in the inner archive encoded here. */
if (bfd_is_thin_archive (arch) && endp != NULL && *endp == ':')
{
file_ptr origin = strtol (endp + 1, NULL, 10);
if (errno != 0 || index >= bfd_ardata (arch)->extended_names_size)
{
bfd_set_error (bfd_error_malformed_archive);
return NULL;
}
*originp = origin;
}
else
*originp = 0;
return bfd_ardata (arch)->extended_names + index;
}
@ -376,6 +414,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
bfd_size_type namelen = 0;
bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
char *allocptr = 0;
file_ptr origin = 0;
if (bfd_bread (hdrp, sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr))
{
@ -407,7 +446,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
&& memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL))
&& bfd_ardata (abfd)->extended_names != NULL)
{
filename = get_extended_arelt_filename (abfd, hdr.ar_name);
filename = get_extended_arelt_filename (abfd, hdr.ar_name, &origin);
if (filename == NULL)
return NULL;
}
@ -476,6 +515,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
ared->arch_header = allocptr + sizeof (struct areltdata);
memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr));
ared->parsed_size = parsed_size;
ared->origin = origin;
if (filename != NULL)
ared->filename = filename;
@ -491,6 +531,30 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
return ared;
}
/* Append the relative pathname for a member of the thin archive
to the pathname of the directory containing the archive. */
static char *
append_relative_path (bfd *arch, char *elt_name)
{
const char *arch_name = arch->filename;
const char *base_name = lbasename (arch_name);
size_t prefix_len;
char *filename;
if (base_name == arch_name)
return elt_name;
prefix_len = base_name - arch_name;
filename = bfd_alloc (arch, prefix_len + strlen (elt_name) + 1);
if (filename == NULL)
return NULL;
strncpy (filename, arch_name, prefix_len);
strcpy (filename + prefix_len, elt_name);
return filename;
}
/* This is an internal function; it's mainly used when indexing
through the archive symbol table, but also used to get the next
element, since it handles the bookkeeping so nicely for us. */
@ -500,6 +564,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
{
struct areltdata *new_areldata;
bfd *n_nfd;
char *filename;
if (archive->my_archive)
{
@ -517,21 +582,74 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
if ((new_areldata = _bfd_read_ar_hdr (archive)) == NULL)
return NULL;
n_nfd = _bfd_create_empty_archive_element_shell (archive);
filename = new_areldata->filename;
if (bfd_is_thin_archive (archive))
{
/* This is a proxy entry for an external file. */
if (! IS_ABSOLUTE_PATH (filename))
{
filename = append_relative_path (archive, filename);
if (filename == NULL)
return NULL;
}
if (new_areldata->origin > 0)
{
/* This proxy entry refers to an element of a nested archive.
Locate the member of that archive and return a bfd for it. */
bfd *ext_arch = _bfd_find_nested_archive (archive, filename);
if (ext_arch == NULL
|| ! bfd_check_format (ext_arch, bfd_archive))
{
bfd_release (archive, new_areldata);
return NULL;
}
n_nfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin);
if (n_nfd == NULL)
{
bfd_release (archive, new_areldata);
return NULL;
}
n_nfd->proxy_origin = bfd_tell (archive);
return n_nfd;
}
/* It's not an element of a nested archive;
open the external file as a bfd. */
n_nfd = bfd_openr (filename, NULL);
}
else
{
n_nfd = _bfd_create_empty_archive_element_shell (archive);
}
if (n_nfd == NULL)
{
bfd_release (archive, new_areldata);
return NULL;
}
n_nfd->origin = bfd_tell (archive);
n_nfd->proxy_origin = bfd_tell (archive);
if (bfd_is_thin_archive (archive))
{
n_nfd->origin = 0;
}
else
{
n_nfd->origin = n_nfd->proxy_origin;
n_nfd->filename = filename;
}
n_nfd->arelt_data = new_areldata;
n_nfd->filename = new_areldata->filename;
if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
return n_nfd;
/* Huh? */
/* FIXME: n_nfd isn't allocated in the archive's memory pool.
If we reach this point, I think bfd_release will abort. */
bfd_release (archive, n_nfd);
bfd_release (archive, new_areldata);
return NULL;
@ -568,8 +686,8 @@ DESCRIPTION
bfd *
bfd_openr_next_archived_file (bfd *archive, bfd *last_file)
{
if ((bfd_get_format (archive) != bfd_archive) ||
(archive->direction == write_direction))
if ((bfd_get_format (archive) != bfd_archive)
|| (archive->direction == write_direction))
{
bfd_set_error (bfd_error_invalid_operation);
return NULL;
@ -589,7 +707,9 @@ bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
else
{
unsigned int size = arelt_size (last_file);
filestart = last_file->origin + size;
filestart = last_file->proxy_origin;
if (! bfd_is_thin_archive (archive))
filestart += size;
if (archive->my_archive)
filestart -= archive->origin;
/* Pad to an even boundary...
@ -615,8 +735,11 @@ bfd_generic_archive_p (bfd *abfd)
return NULL;
}
if (strncmp (armag, ARMAG, SARMAG) != 0 &&
strncmp (armag, ARMAGB, SARMAG) != 0)
bfd_is_thin_archive (abfd) = (strncmp (armag, ARMAGT, SARMAG) == 0);
if (strncmp (armag, ARMAG, SARMAG) != 0
&& strncmp (armag, ARMAGB, SARMAG) != 0
&& ! bfd_is_thin_archive (abfd))
return 0;
tdata_hold = bfd_ardata (abfd);
@ -1110,7 +1233,7 @@ _bfd_slurp_extended_name_table (bfd *abfd)
char *limit = temp + namedata->parsed_size;
for (; temp < limit; ++temp)
{
if (*temp == '\012')
if (*temp == ARFMAG[0])
temp[temp > ext_names && temp[-1] == '/' ? -1 : 0] = '\0';
if (*temp == '\\')
*temp = '/';
@ -1190,6 +1313,66 @@ normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
}
#endif
/* Adjust a relative path name based on the reference path. */
static const char *
adjust_relative_path (const char * path, const char * ref_path)
{
static char *pathbuf = NULL;
static int pathbuf_len = 0;
const char *pathp = path;
const char *refp = ref_path;
int element_count = 0;
int len;
char *newp;
/* Remove common leading path elements. */
for (;;)
{
const char *e1 = pathp;
const char *e2 = refp;
while (*e1 && ! IS_DIR_SEPARATOR (*e1))
++e1;
while (*e2 && ! IS_DIR_SEPARATOR (*e2))
++e2;
if (*e1 == '\0' || *e2 == '\0' || e1 - pathp != e2 - refp
|| strncmp (pathp, refp, e1 - pathp) != 0)
break;
pathp = e1 + 1;
refp = e2 + 1;
}
/* For each leading path element in the reference path,
insert "../" into the path. */
for (; *refp; ++refp)
if (IS_DIR_SEPARATOR (*refp))
++element_count;
len = 3 * element_count + strlen (path) + 1;
if (len > pathbuf_len)
{
if (pathbuf != NULL)
free (pathbuf);
pathbuf_len = 0;
pathbuf = bfd_malloc (len);
if (pathbuf == NULL)
return path;
pathbuf_len = len;
}
newp = pathbuf;
while (element_count-- > 0)
{
/* FIXME: Support Windows style path separators as well. */
strcpy (newp, "../");
newp += 3;
}
strcpy (newp, pathp);
return pathbuf;
}
/* Build a BFD style extended name table. */
bfd_boolean
@ -1232,8 +1415,11 @@ _bfd_construct_extended_name_table (bfd *abfd,
bfd_size_type total_namelen = 0;
bfd *current;
char *strptr;
const char *last_filename;
long last_stroff;
*tablen = 0;
last_filename = NULL;
/* Figure out how long the table should be. */
for (current = abfd->archive_head;
@ -1243,6 +1429,42 @@ _bfd_construct_extended_name_table (bfd *abfd,
const char *normal;
unsigned int thislen;
if (bfd_is_thin_archive (abfd))
{
const char *filename = current->filename;
/* If the element being added is a member of another archive
(i.e., we are flattening), use the containing archive's name. */
if (current->my_archive
&& ! bfd_is_thin_archive (current->my_archive))
filename = current->my_archive->filename;
/* If the path is the same as the previous path seen,
reuse it. This can happen when flattening a thin
archive that contains other archives. */
if (last_filename && strcmp (last_filename, filename) == 0)
continue;
last_filename = filename;
/* If the path is relative, adjust it relative to
the containing archive. */
if (! IS_ABSOLUTE_PATH (filename)
&& ! IS_ABSOLUTE_PATH (abfd->filename))
normal = adjust_relative_path (filename, abfd->filename);
else
normal = filename;
/* In a thin archive, always store the full pathname
in the extended name table. */
total_namelen += strlen (normal) + 1;
if (trailing_slash)
/* Leave room for trailing slash. */
++total_namelen;
continue;
}
normal = normalize (current, current->filename);
if (normal == NULL)
return FALSE;
@ -1290,38 +1512,85 @@ _bfd_construct_extended_name_table (bfd *abfd,
*tablen = total_namelen;
strptr = *tabloc;
last_filename = NULL;
last_stroff = 0;
for (current = abfd->archive_head;
current != NULL;
current = current->archive_next)
{
const char *normal;
unsigned int thislen;
long stroff;
const char *filename = current->filename;
normal = normalize (current, current->filename);
if (normal == NULL)
return FALSE;
if (bfd_is_thin_archive (abfd))
{
/* If the element being added is a member of another archive
(i.e., we are flattening), use the containing archive's name. */
if (current->my_archive
&& ! bfd_is_thin_archive (current->my_archive))
filename = current->my_archive->filename;
/* If the path is the same as the previous path seen,
reuse it. This can happen when flattening a thin
archive that contains other archives.
If the path is relative, adjust it relative to
the containing archive. */
if (last_filename && strcmp (last_filename, filename) == 0)
normal = last_filename;
else if (! IS_ABSOLUTE_PATH (filename)
&& ! IS_ABSOLUTE_PATH (abfd->filename))
normal = adjust_relative_path (filename, abfd->filename);
else
normal = filename;
}
else
{
normal = normalize (current, filename);
if (normal == NULL)
return FALSE;
}
thislen = strlen (normal);
if (thislen > maxname)
if (thislen > maxname || bfd_is_thin_archive (abfd))
{
/* Works for now; may need to be re-engineered if we
encounter an oddball archive format and want to
generalise this hack. */
struct ar_hdr *hdr = arch_hdr (current);
strcpy (strptr, normal);
if (! trailing_slash)
strptr[thislen] = '\012';
else
{
strptr[thislen] = '/';
strptr[thislen + 1] = '\012';
if (normal == last_filename)
stroff = last_stroff;
else
{
strcpy (strptr, normal);
if (! trailing_slash)
strptr[thislen] = ARFMAG[0];
else
{
strptr[thislen] = '/';
strptr[thislen + 1] = ARFMAG[0];
}
stroff = strptr - *tabloc;
last_stroff = stroff;
}
hdr->ar_name[0] = ar_padchar (current);
_bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld",
strptr - *tabloc);
strptr += thislen + 1;
if (trailing_slash)
++strptr;
if (bfd_is_thin_archive (abfd) && current->origin > 0)
{
int len = snprintf (hdr->ar_name + 1, maxname - 1, "%-ld:",
stroff);
_bfd_ar_spacepad (hdr->ar_name + 1 + len, maxname - 1 - len,
"%-ld",
current->origin - sizeof (struct ar_hdr));
}
else
_bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld", stroff);
if (normal != last_filename)
{
strptr += thislen + 1;
if (trailing_slash)
++strptr;
last_filename = filename;
}
}
}
@ -1593,6 +1862,7 @@ bfd_gnu_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
{
/* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
char *bslash = strrchr (pathname, '\\');
if (filename == NULL || (bslash != NULL && bslash > filename))
filename = bslash;
if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':')
@ -1610,7 +1880,8 @@ bfd_gnu_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
if (length <= maxlen)
memcpy (hdr->ar_name, filename, length);
else
{ /* pathname: meet procrustes */
{
/* pathname: meet procrustes. */
memcpy (hdr->ar_name, filename, maxlen);
if ((filename[length - 2] == '.') && (filename[length - 1] == 'o'))
{
@ -1638,6 +1909,7 @@ _bfd_write_archive_contents (bfd *arch)
bfd_boolean hasobjects = FALSE;
bfd_size_type wrote;
int tries;
char *armag;
/* Verify the viability of all entries; if any of them live in the
filesystem (as opposed to living in an archive open for input)
@ -1681,7 +1953,10 @@ _bfd_write_archive_contents (bfd *arch)
if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0)
return FALSE;
wrote = bfd_bwrite (ARMAG, SARMAG, arch);
armag = ARMAG;
if (bfd_is_thin_archive (arch))
armag = ARMAGT;
wrote = bfd_bwrite (armag, SARMAG, arch);
if (wrote != SARMAG)
return FALSE;
@ -1707,7 +1982,7 @@ _bfd_write_archive_contents (bfd *arch)
return FALSE;
if ((elength % 2) == 1)
{
if (bfd_bwrite ("\012", 1, arch) != 1)
if (bfd_bwrite (ARFMAG, 1, arch) != 1)
return FALSE;
}
}
@ -1724,11 +1999,15 @@ _bfd_write_archive_contents (bfd *arch)
if (bfd_bwrite (hdr, sizeof (*hdr), arch)
!= sizeof (*hdr))
return FALSE;
if (bfd_is_thin_archive (arch))
continue;
if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0)
goto input_err;
while (remaining)
{
unsigned int amt = DEFAULT_BUFFERSIZE;
if (amt > remaining)
amt = remaining;
errno = 0;
@ -1742,9 +2021,10 @@ _bfd_write_archive_contents (bfd *arch)
return FALSE;
remaining -= amt;
}
if ((arelt_size (current) % 2) == 1)
{
if (bfd_bwrite ("\012", 1, arch) != 1)
if (bfd_bwrite (ARFMAG, 1, arch) != 1)
return FALSE;
}
}
@ -1809,8 +2089,8 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
goto error_return;
/* Drop all the files called __.SYMDEF, we're going to make our own. */
while (arch->archive_head &&
strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
while (arch->archive_head
&& strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
arch->archive_head = arch->archive_head->archive_next;
/* Map over each element. */
@ -1851,10 +2131,10 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
flagword flags = (syms[src_count])->flags;
asection *sec = syms[src_count]->section;
if ((flags & BSF_GLOBAL ||
flags & BSF_WEAK ||
flags & BSF_INDIRECT ||
bfd_is_com_section (sec))
if ((flags & BSF_GLOBAL
|| flags & BSF_WEAK
|| flags & BSF_INDIRECT
|| bfd_is_com_section (sec))
&& ! bfd_is_und_section (sec))
{
bfd_size_type namelen;
@ -2139,10 +2419,14 @@ coff_write_armap (bfd *arch,
return FALSE;
count++;
}
/* Add size of this archive entry. */
archive_member_file_ptr += arelt_size (current) + sizeof (struct ar_hdr);
/* Remember aboout the even alignment. */
archive_member_file_ptr += archive_member_file_ptr % 2;
archive_member_file_ptr += sizeof (struct ar_hdr);
if (! bfd_is_thin_archive (arch))
{
/* Add size of this archive entry. */
archive_member_file_ptr += arelt_size (current);
/* Remember about the even alignment. */
archive_member_file_ptr += archive_member_file_ptr % 2;
}
current = current->archive_next;
}

View File

@ -499,6 +499,7 @@ extern void warn_deprecated (const char *, const char *, int, const char *);
#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
#define bfd_my_archive(abfd) ((abfd)->my_archive)
#define bfd_has_map(abfd) ((abfd)->has_armap)
#define bfd_is_thin_archive(abfd) ((abfd)->is_thin_archive)
#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
#define bfd_usrdata(abfd) ((abfd)->usrdata)

View File

@ -506,6 +506,7 @@ extern void warn_deprecated (const char *, const char *, int, const char *);
#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
#define bfd_my_archive(abfd) ((abfd)->my_archive)
#define bfd_has_map(abfd) ((abfd)->has_armap)
#define bfd_is_thin_archive(abfd) ((abfd)->is_thin_archive)
#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
#define bfd_usrdata(abfd) ((abfd)->usrdata)
@ -4659,6 +4660,13 @@ struct bfd
origin, with origin set to 0 for non archive files. */
ufile_ptr origin;
/* The origin in the archive of the proxy entry. This will
normally be the same as origin, except for thin archives,
when it will contain the current offset of the proxy in the
thin archive rather than the offset of the bfd in its actual
container. */
ufile_ptr proxy_origin;
/* A hash table for section names. */
struct bfd_hash_table section_htab;
@ -4692,6 +4700,8 @@ struct bfd
struct bfd *my_archive; /* The containing archive BFD. */
struct bfd *archive_next; /* The next BFD in the archive. */
struct bfd *archive_head; /* The first BFD in the archive. */
struct bfd *nested_archives; /* List of nested archive in a flattened
thin archive. */
/* A chain of BFD structures involved in a link. */
struct bfd *link_next;
@ -4774,6 +4784,9 @@ struct bfd
/* Have archive map. */
unsigned int has_armap : 1;
/* Set if this is a thin archive. */
unsigned int is_thin_archive : 1;
};
typedef enum bfd_error

View File

@ -150,6 +150,13 @@ CODE_FRAGMENT
. origin, with origin set to 0 for non archive files. *}
. ufile_ptr origin;
.
. {* The origin in the archive of the proxy entry. This will
. normally be the same as origin, except for thin archives,
. when it will contain the current offset of the proxy in the
. thin archive rather than the offset of the bfd in its actual
. container. *}
. ufile_ptr proxy_origin;
.
. {* A hash table for section names. *}
. struct bfd_hash_table section_htab;
.
@ -183,6 +190,8 @@ CODE_FRAGMENT
. struct bfd *my_archive; {* The containing archive BFD. *}
. struct bfd *archive_next; {* The next BFD in the archive. *}
. struct bfd *archive_head; {* The first BFD in the archive. *}
. struct bfd *nested_archives; {* List of nested archive in a flattened
. thin archive. *}
.
. {* A chain of BFD structures involved in a link. *}
. struct bfd *link_next;
@ -265,6 +274,9 @@ CODE_FRAGMENT
.
. {* Have archive map. *}
. unsigned int has_armap : 1;
.
. {* Set if this is a thin archive. *}
. unsigned int is_thin_archive : 1;
.};
.
*/

View File

@ -91,6 +91,7 @@ struct areltdata {
char * arch_header; /* it's actually a string */
unsigned int parsed_size; /* octets of filesize not including ar_hdr */
char *filename; /* null-terminated */
file_ptr origin; /* for element of a thin archive */
};
#define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size)

View File

@ -96,6 +96,7 @@ struct areltdata {
char * arch_header; /* it's actually a string */
unsigned int parsed_size; /* octets of filesize not including ar_hdr */
char *filename; /* null-terminated */
file_ptr origin; /* for element of a thin archive */
};
#define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size)

View File

@ -647,6 +647,8 @@ bfd_boolean
bfd_close (bfd *abfd)
{
bfd_boolean ret;
bfd *nbfd;
bfd *next;
if (bfd_write_p (abfd))
{
@ -654,6 +656,13 @@ bfd_close (bfd *abfd)
return FALSE;
}
/* Close nested archives (if this bfd is a thin archive). */
for (nbfd = abfd->nested_archives; nbfd; nbfd = next)
{
next = nbfd->archive_next;
bfd_close (nbfd);
}
if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
return FALSE;

View File

@ -1,3 +1,25 @@
2008-03-27 Cary Coutant <ccoutant@google.com>
Add support for thin archives.
* ar.c (make_thin_archive): New global flag.
(map_over_members): Deal with full pathnames in thin archives.
(usage, main): Add 'T' option for building thin archives.
(replace_members): Pass thin archive flag to ar_emul_append.
* arsup.c (ar_open): Initialize new flag.
* binemul.c (ar_emul_append): Add new parameter for
flattening nested archives.
(do_ar_emul_default_append): New function.
(ar_emul_default_append): Factored out recursive code.
* binutils/binemul.h (ar_emul_default_append): Add new parameter.
(struct bin_emulation_xfer_struct): New parameter for ar_append.
* dlltool.c (gen_lib_file): Initialize thin archive flag.
* emul_aix.c (ar_emul_aix_internal): Add new flatten
parameter, currently unimplemented.
All callers changed.
* objcopy.c (copy_archive): Preserve thin archive flag.
* doc/binutils.texi: Update ar documentation.
* NEWS: Mention the new feature.
2008-03-20 H.J. Lu <hongjiu.lu@intel.com>
* readelf.c (process_mips_specific): Declare addr_size as int.

View File

@ -1,4 +1,9 @@
-*- text -*-
* Added support for "thin" archives which contain pathnames pointing to
object files rather than the files themselves and which contain a
flattened symbol index for all objects, and archives, which have been
added to the archive.
* Added -F switch to objdump to include file offsets in the disassembly.
* Added -c switch to readelf to allow string dumps of archive symbol index.

View File

@ -40,9 +40,9 @@
#include <sys/stat.h>
#ifdef __GO32___
#define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */
#define EXT_NAME_LEN 3 /* Bufflen of addition to name if it's MS-DOS. */
#else
#define EXT_NAME_LEN 6 /* ditto for *NIX */
#define EXT_NAME_LEN 6 /* Ditto for *NIX. */
#endif
/* We need to open files in binary modes on system where that makes a
@ -51,12 +51,12 @@
#define O_BINARY 0
#endif
/* Kludge declaration from BFD! This is ugly! FIXME! XXX */
/* Kludge declaration from BFD! This is ugly! FIXME! XXX */
struct ar_hdr *
bfd_special_undocumented_glue (bfd * abfd, const char *filename);
/* Static declarations */
/* Static declarations. */
static void mri_emul (void);
static const char *normalize (const char *, bfd *);
@ -74,7 +74,7 @@ static int ranlib_only (const char *archname);
static int ranlib_touch (const char *archname);
static void usage (int);
/** Globals and flags */
/** Globals and flags. */
static int mri_mode;
@ -134,6 +134,9 @@ static bfd_boolean ar_truncate = FALSE;
program. */
static bfd_boolean full_pathname = FALSE;
/* Whether to create a "thin" archive (symbol index only -- no files). */
static bfd_boolean make_thin_archive = FALSE;
int interactive = 0;
static void
@ -176,16 +179,25 @@ map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
match_count = 0;
for (head = arch->archive_next; head; head = head->archive_next)
{
const char * filename;
PROGRESS (1);
if (head->filename == NULL)
filename = head->filename;
if (filename == NULL)
{
/* Some archive formats don't get the filenames filled in
until the elements are opened. */
struct stat buf;
bfd_stat_arch_elt (head, &buf);
}
if ((head->filename != NULL) &&
(!FILENAME_CMP (normalize (*files, arch), head->filename)))
else if (bfd_is_thin_archive (arch))
{
/* Thin archives store full pathnames. Need to normalize. */
filename = normalize (filename, arch);
}
if ((filename != NULL) &&
(!FILENAME_CMP (normalize (*files, arch), filename)))
{
++match_count;
if (counted_name_mode
@ -200,6 +212,7 @@ map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
function (head);
}
}
if (!found)
/* xgettext:c-format */
fprintf (stderr, _("no entry %s in archive\n"), *files);
@ -242,10 +255,11 @@ usage (int help)
fprintf (s, _(" [c] - do not warn if the library had to be created\n"));
fprintf (s, _(" [s] - create an archive index (cf. ranlib)\n"));
fprintf (s, _(" [S] - do not build a symbol table\n"));
fprintf (s, _(" [T] - make a thin archive\n"));
fprintf (s, _(" [v] - be verbose\n"));
fprintf (s, _(" [V] - display the version number\n"));
fprintf (s, _(" @<file> - read options from <file>\n"));
ar_emul_usage (s);
}
else
@ -284,6 +298,7 @@ normalize (const char *file, bfd *abfd)
{
/* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
char *bslash = strrchr (file, '\\');
if (filename == NULL || (bslash != NULL && bslash > filename))
filename = bslash;
if (filename == NULL && file[0] != '\0' && file[1] == ':')
@ -302,7 +317,7 @@ normalize (const char *file, bfd *abfd)
char *s;
/* Space leak. */
s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
s = xmalloc (abfd->xvec->ar_max_namelen + 1);
memcpy (s, filename, abfd->xvec->ar_max_namelen);
s[abfd->xvec->ar_max_namelen] = '\0';
filename = s;
@ -376,6 +391,7 @@ main (int argc, char **argv)
{
/* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
char *bslash = strrchr (program_name, '\\');
if (temp == NULL || (bslash != NULL && bslash > temp))
temp = bslash;
if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
@ -559,6 +575,9 @@ main (int argc, char **argv)
case 'P':
full_pathname = TRUE;
break;
case 'T':
make_thin_archive = TRUE;
break;
default:
/* xgettext:c-format */
non_fatal (_("illegal option -- %c"), c);
@ -629,6 +648,9 @@ main (int argc, char **argv)
arch = open_inarch (inarch_filename,
files == NULL ? (char *) NULL : files[0]);
if (operation == extract && bfd_is_thin_archive (arch))
fatal (_("`x' cannot be used on thin archives."));
switch (operation)
{
case print_table:
@ -933,7 +955,7 @@ write_archive (bfd *iarch)
if (new_name == NULL)
bfd_fatal ("could not create temporary file whilst writing archive");
output_filename = new_name;
obfd = bfd_openw (new_name, bfd_get_target (iarch));
@ -956,6 +978,9 @@ write_archive (bfd *iarch)
obfd->flags |= BFD_TRADITIONAL_FORMAT;
}
if (make_thin_archive || bfd_is_thin_archive (iarch))
bfd_is_thin_archive (obfd) = 1;
if (!bfd_set_archive_head (obfd, contents_head))
bfd_fatal (old_name);
@ -1189,7 +1214,8 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
/* Add to the end of the archive. */
after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
if (ar_emul_append (after_bfd, *files_to_move, verbose))
if (ar_emul_append (after_bfd, *files_to_move, verbose,
make_thin_archive))
changed = TRUE;
next_file:;

View File

@ -1,6 +1,6 @@
/* arsup.c - Archive support for MRI compatibility
Copyright 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
2004, 2007 Free Software Foundation, Inc.
2004, 2007, 2008 Free Software Foundation, Inc.
This file is part of GNU Binutils.
@ -207,6 +207,7 @@ ar_open (char *name, int t)
bfd_set_format (obfd, bfd_archive);
obfd->has_armap = 1;
obfd->is_thin_archive = 0;
}
}

View File

@ -1,5 +1,5 @@
/* Binutils emulation layer.
Copyright 2002, 2003, 2007 Free Software Foundation, Inc.
Copyright 2002, 2003, 2007, 2008 Free Software Foundation, Inc.
Written by Tom Rix, Red Hat Inc.
This file is part of GNU Binutils.
@ -39,31 +39,60 @@ ar_emul_default_usage (FILE *fp)
}
bfd_boolean
ar_emul_append (bfd **after_bfd, char *file_name, bfd_boolean verbose)
ar_emul_append (bfd **after_bfd, char *file_name, bfd_boolean verbose,
bfd_boolean flatten)
{
if (bin_dummy_emulation.ar_append)
return bin_dummy_emulation.ar_append (after_bfd, file_name, verbose);
return bin_dummy_emulation.ar_append (after_bfd, file_name, verbose,
flatten);
return FALSE;
}
bfd_boolean
ar_emul_default_append (bfd **after_bfd, char *file_name,
bfd_boolean verbose)
{
bfd *temp;
static bfd_boolean
do_ar_emul_default_append (bfd **after_bfd, bfd *new_bfd,
bfd_boolean verbose, bfd_boolean flatten)
{
/* When flattening, add the members of an archive instead of the
archive itself. */
if (flatten && bfd_check_format (new_bfd, bfd_archive))
{
bfd *elt;
bfd_boolean added = FALSE;
temp = *after_bfd;
*after_bfd = bfd_openr (file_name, NULL);
for (elt = bfd_openr_next_archived_file (new_bfd, NULL);
elt;
elt = bfd_openr_next_archived_file (new_bfd, elt))
{
if (do_ar_emul_default_append (after_bfd, elt, verbose, TRUE))
{
added = TRUE;
after_bfd = &((*after_bfd)->archive_next);
}
}
AR_EMUL_ELEMENT_CHECK (*after_bfd, file_name);
AR_EMUL_APPEND_PRINT_VERBOSE (verbose, file_name);
return added;
}
(*after_bfd)->archive_next = temp;
AR_EMUL_APPEND_PRINT_VERBOSE (verbose, new_bfd->filename);
new_bfd->archive_next = *after_bfd;
*after_bfd = new_bfd;
return TRUE;
}
bfd_boolean
ar_emul_default_append (bfd **after_bfd, char *file_name,
bfd_boolean verbose, bfd_boolean flatten)
{
bfd *new_bfd;
new_bfd = bfd_openr (file_name, NULL);
AR_EMUL_ELEMENT_CHECK (new_bfd, file_name);
return do_ar_emul_default_append (after_bfd, new_bfd, verbose, flatten);
}
bfd_boolean
ar_emul_replace (bfd **after_bfd, char *file_name, bfd_boolean verbose)
{

View File

@ -1,5 +1,5 @@
/* Binutils emulation layer.
Copyright 2002, 2003, 2007 Free Software Foundation, Inc.
Copyright 2002, 2003, 2007, 2008 Free Software Foundation, Inc.
Written by Tom Rix, Red Hat Inc.
This file is part of GNU Binutils.
@ -28,8 +28,9 @@
extern void ar_emul_usage (FILE *);
extern void ar_emul_default_usage (FILE *);
extern bfd_boolean ar_emul_append (bfd **, char *, bfd_boolean);
extern bfd_boolean ar_emul_default_append (bfd **, char *, bfd_boolean);
extern bfd_boolean ar_emul_append (bfd **, char *, bfd_boolean, bfd_boolean);
extern bfd_boolean ar_emul_default_append (bfd **, char *, bfd_boolean,
bfd_boolean);
extern bfd_boolean ar_emul_replace (bfd **, char *, bfd_boolean);
extern bfd_boolean ar_emul_default_replace (bfd **, char *, bfd_boolean);
extern bfd_boolean ar_emul_parse_arg (char *);
@ -54,7 +55,7 @@ typedef struct bin_emulation_xfer_struct
{
/* Print out the extra options. */
void (* ar_usage) (FILE *fp);
bfd_boolean (* ar_append) (bfd **, char *, bfd_boolean);
bfd_boolean (* ar_append) (bfd **, char *, bfd_boolean, bfd_boolean);
bfd_boolean (* ar_replace) (bfd **, char *, bfd_boolean);
bfd_boolean (* ar_parse_arg) (char *);
}

View File

@ -2813,6 +2813,7 @@ gen_lib_file (void)
bfd_set_format (outarch, bfd_archive);
outarch->has_armap = 1;
outarch->is_thin_archive = 0;
/* Work out a reasonable size of things to put onto one line. */
ar_head = make_head ();

View File

@ -211,6 +211,18 @@ You may use @samp{nm -s} or @samp{nm --print-armap} to list this index
table. If an archive lacks the table, another form of @command{ar} called
@command{ranlib} can be used to add just the table.
@cindex thin archives
@sc{gnu} @command{ar} can optionally create a @emph{thin} archive,
which contains a symbol index and references to the original copies
of the member files of the archives. Such an archive is useful
for building libraries for use within a local build, where the
relocatable objects are expected to remain available, and copying the
contents of each object would only waste time and space. Thin archives
are also @emph{flattened}, so that adding one or more archives to a
thin archive will add the elements of the nested archive individually.
The paths to the elements of the archive are stored relative to the
archive itself.
@cindex compatibility, @command{ar}
@cindex @command{ar} compatibility
@sc{gnu} @command{ar} is designed to be compatible with two different
@ -356,6 +368,8 @@ use the @samp{v} modifier with this operation, to request that
If you do not specify a @var{member}, all files in the archive
are extracted.
Files cannot be extracted from a thin archive.
@end table
A number of modifiers (@var{mod}) may immediately follow the @var{p}
@ -434,6 +448,12 @@ with the linker. In order to build a symbol table, you must omit the
@samp{S} modifier on the last execution of @samp{ar}, or you must run
@samp{ranlib} on the archive.
@item T
@cindex creating thin archive
Make the specified @var{archive} a @emph{thin} archive. If it already
exists and is a regular archive, the existing members must be present
in the same directory as @var{archive}.
@item u
@cindex updating an archive
Normally, @samp{ar r}@dots{} inserts all files

View File

@ -1,5 +1,5 @@
/* Binutils emulation layer.
Copyright 2002, 2003, 2006, 2007 Free Software Foundation, Inc.
Copyright 2002, 2003, 2006, 2007, 2008 Free Software Foundation, Inc.
Written by Tom Rix, Red Hat Inc.
This file is part of GNU Binutils.
@ -35,15 +35,6 @@ static bfd_boolean X32 = TRUE;
/* Whether to include 64 bit objects. */
static bfd_boolean X64 = FALSE;
static void ar_emul_aix_usage (FILE *);
static bfd_boolean ar_emul_aix_append (bfd **, char *, bfd_boolean);
static bfd_boolean ar_emul_aix5_append (bfd **, char *, bfd_boolean);
static bfd_boolean ar_emul_aix_replace (bfd **, char *, bfd_boolean);
static bfd_boolean ar_emul_aix5_replace (bfd **, char *, bfd_boolean);
static bfd_boolean ar_emul_aix_parse_arg (char *);
static bfd_boolean ar_emul_aix_internal
(bfd **, char *, bfd_boolean, const char *, bfd_boolean);
static void
ar_emul_aix_usage (FILE *fp)
{
@ -56,8 +47,12 @@ ar_emul_aix_usage (FILE *fp)
}
static bfd_boolean
ar_emul_aix_internal (bfd **after_bfd, char *file_name, bfd_boolean verbose,
const char * target_name, bfd_boolean is_append)
ar_emul_aix_internal (bfd ** after_bfd,
char * file_name,
bfd_boolean verbose,
const char * target_name,
bfd_boolean is_append,
bfd_boolean flatten ATTRIBUTE_UNUSED)
{
bfd *temp;
bfd *try_bfd;
@ -97,31 +92,33 @@ ar_emul_aix_internal (bfd **after_bfd, char *file_name, bfd_boolean verbose,
static bfd_boolean
ar_emul_aix_append (bfd **after_bfd, char *file_name, bfd_boolean verbose)
ar_emul_aix_append (bfd **after_bfd, char *file_name, bfd_boolean verbose,
bfd_boolean flatten)
{
return ar_emul_aix_internal (after_bfd, file_name, verbose,
"aixcoff64-rs6000", TRUE);
"aixcoff64-rs6000", TRUE, flatten);
}
static bfd_boolean
ar_emul_aix5_append (bfd **after_bfd, char *file_name, bfd_boolean verbose)
ar_emul_aix5_append (bfd **after_bfd, char *file_name, bfd_boolean verbose,
bfd_boolean flatten)
{
return ar_emul_aix_internal (after_bfd, file_name, verbose,
"aix5coff64-rs6000", TRUE);
"aix5coff64-rs6000", TRUE, flatten);
}
static bfd_boolean
ar_emul_aix_replace (bfd **after_bfd, char *file_name, bfd_boolean verbose)
{
return ar_emul_aix_internal (after_bfd, file_name, verbose,
"aixcoff64-rs6000", FALSE);
"aixcoff64-rs6000", FALSE, FALSE);
}
static bfd_boolean
ar_emul_aix5_replace (bfd **after_bfd, char *file_name, bfd_boolean verbose)
{
return ar_emul_aix_internal (after_bfd, file_name, verbose,
"aix5coff64-rs6000", FALSE);
"aix5coff64-rs6000", FALSE, FALSE);
}
static bfd_boolean

View File

@ -1,6 +1,6 @@
/* objcopy.c -- copy object file from input to output, optionally massaging it.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GNU Binutils.
@ -1830,6 +1830,7 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
strerror (errno));
obfd->has_armap = ibfd->has_armap;
obfd->is_thin_archive = ibfd->is_thin_archive;
list = NULL;

View File

@ -1,3 +1,7 @@
2008-03-27 Cary Coutant <ccoutant@google.com>
* binutils-all/ar.exp: Add thin archive tests.
2008-02-26 Joseph Myers <joseph@codesourcery.com>
* config/default.exp (gcc_gas_flag, dlltool_gas_flag): Define to

View File

@ -1,4 +1,4 @@
# Copyright 1995, 1997, 2002, 2004, 2007 Free Software Foundation, Inc.
# Copyright 1995, 1997, 2002, 2004, 2007, 2008 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@ -215,6 +215,110 @@ proc symbol_table { } {
pass $testname
}
# Test building a thin archive.
proc thin_archive { } {
global AR
global AS
global NM
global srcdir
global subdir
set testname "ar thin archive"
if ![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o] {
unresolved $testname
return
}
if [is_remote host] {
set archive artest.a
set objfile [remote_download host tmpdir/bintest.o]
remote_file host delete $archive
} else {
set archive tmpdir/artest.a
set objfile tmpdir/bintest.o
}
remote_file build delete tmpdir/artest.a
set got [binutils_run $AR "rcT $archive ${objfile}"]
if ![string match "" $got] {
fail $testname
return
}
set got [binutils_run $NM "--print-armap $archive"]
if { ![string match "*text_symbol in *bintest.o*" $got] \
|| ![string match "*data_symbol in *bintest.o*" $got] \
|| ![string match "*common_symbol in *bintest.o*" $got] \
|| [string match "*static_text_symbol in *bintest.o*" $got] \
|| [string match "*static_data_symbol in *bintest.o*" $got] \
|| [string match "*external_symbol in *bintest.o*" $got] } {
fail $testname
return
}
pass $testname
}
# Test building a thin archive with a nested archive.
proc thin_archive_with_nested { } {
global AR
global AS
global NM
global srcdir
global subdir
set testname "ar thin archive with nested archive"
if ![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o] {
unresolved $testname
return
}
if [is_remote host] {
set archive artest.a
set archive2 artest2.a
set objfile [remote_download host tmpdir/bintest.o]
remote_file host delete $archive
} else {
set archive tmpdir/artest.a
set archive2 tmpdir/artest2.a
set objfile tmpdir/bintest.o
}
remote_file build delete tmpdir/artest.a
set got [binutils_run $AR "rc $archive ${objfile}"]
if ![string match "" $got] {
fail $testname
return
}
remote_file build delete tmpdir/artest2.a
set got [binutils_run $AR "rcT $archive2 ${archive}"]
if ![string match "" $got] {
fail $testname
return
}
set got [binutils_run $NM "--print-armap $archive"]
if { ![string match "*text_symbol in *bintest.o*" $got] \
|| ![string match "*data_symbol in *bintest.o*" $got] \
|| ![string match "*common_symbol in *bintest.o*" $got] \
|| [string match "*static_text_symbol in *bintest.o*" $got] \
|| [string match "*static_data_symbol in *bintest.o*" $got] \
|| [string match "*external_symbol in *bintest.o*" $got] } {
fail $testname
return
}
pass $testname
}
# Test POSIX-compatible argument parsing.
proc argument_parsing { } {
@ -254,4 +358,6 @@ proc argument_parsing { } {
long_filenames
symbol_table
thin_archive
thin_archive_with_nested
argument_parsing

View File

@ -1,3 +1,7 @@
2008-03-27 Cary Coutant <ccoutant@google.com>
* ar.h (ARMAGT): New magic string for thin archives.
2005-05-10 Nick Clifton <nickc@redhat.com>
* Update the address and phone number of the FSF organization in

View File

@ -1,6 +1,6 @@
/* archive file definition for GNU software
Copyright 2001 Free Software Foundation, Inc.
Copyright 2001, 2008 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -26,8 +26,9 @@
characters, as allowed by ANSI. '\012' has a fixed value, and remains
compatible with existing BSDish archives. */
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
#define ARMAGB "!<bout>\012" /* For b.out archives */
#define ARMAG "!<arch>\012" /* For COFF and a.out archives. */
#define ARMAGB "!<bout>\012" /* For b.out archives. */
#define ARMAGT "!<thin>\012" /* For thin archives. */
#define SARMAG 8
#define ARFMAG "`\012"
@ -39,14 +40,15 @@
#define ARMAP_TIME_OFFSET 60
struct ar_hdr {
char ar_name[16]; /* name of this member */
char ar_date[12]; /* file mtime */
char ar_uid[6]; /* owner uid; printed as decimal */
char ar_gid[6]; /* owner gid; printed as decimal */
char ar_mode[8]; /* file mode, printed as octal */
char ar_size[10]; /* file size, printed as decimal */
char ar_fmag[2]; /* should contain ARFMAG */
struct ar_hdr
{
char ar_name[16]; /* Name of this member. */
char ar_date[12]; /* File mtime. */
char ar_uid[6]; /* Owner uid; printed as decimal. */
char ar_gid[6]; /* Owner gid; printed as decimal. */
char ar_mode[8]; /* File mode, printed as octal. */
char ar_size[10]; /* File size, printed as decimal. */
char ar_fmag[2]; /* Should contain ARFMAG. */
};
#endif /* __GNU_AR_H__ */