xref: /openbsd-src/gnu/usr.bin/binutils/bfd/archive.c (revision f3d2a372a924371acc2cba30d1ef1c71908d2fe8)
12159047fSniklas /* BFD back-end for archive files (libraries).
2b55d4692Sfgsch    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3007c2a45Smiod    2000, 2001, 2002, 2003
4b305b0f1Sespie    Free Software Foundation, Inc.
52159047fSniklas    Written by Cygnus Support.  Mostly Gumby Henkel-Wallace's fault.
62159047fSniklas 
72159047fSniklas This file is part of BFD, the Binary File Descriptor library.
82159047fSniklas 
92159047fSniklas This program is free software; you can redistribute it and/or modify
102159047fSniklas it under the terms of the GNU General Public License as published by
112159047fSniklas the Free Software Foundation; either version 2 of the License, or
122159047fSniklas (at your option) any later version.
132159047fSniklas 
142159047fSniklas This program is distributed in the hope that it will be useful,
152159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
162159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
172159047fSniklas GNU General Public License for more details.
182159047fSniklas 
192159047fSniklas You should have received a copy of the GNU General Public License
202159047fSniklas along with this program; if not, write to the Free Software
212159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
222159047fSniklas 
232159047fSniklas /*
242159047fSniklas @setfilename archive-info
252159047fSniklas SECTION
262159047fSniklas 	Archives
272159047fSniklas 
282159047fSniklas DESCRIPTION
292159047fSniklas 	An archive (or library) is just another BFD.  It has a symbol
302159047fSniklas 	table, although there's not much a user program will do with it.
312159047fSniklas 
322159047fSniklas 	The big difference between an archive BFD and an ordinary BFD
332159047fSniklas 	is that the archive doesn't have sections.  Instead it has a
342159047fSniklas 	chain of BFDs that are considered its contents.  These BFDs can
352159047fSniklas 	be manipulated like any other.  The BFDs contained in an
362159047fSniklas 	archive opened for reading will all be opened for reading.  You
372159047fSniklas 	may put either input or output BFDs into an archive opened for
382159047fSniklas 	output; they will be handled correctly when the archive is closed.
392159047fSniklas 
402159047fSniklas 	Use <<bfd_openr_next_archived_file>> to step through
412159047fSniklas 	the contents of an archive opened for input.  You don't
422159047fSniklas 	have to read the entire archive if you don't want
432159047fSniklas 	to!  Read it until you find what you want.
442159047fSniklas 
452159047fSniklas 	Archive contents of output BFDs are chained through the
462159047fSniklas 	<<next>> pointer in a BFD.  The first one is findable through
472159047fSniklas 	the <<archive_head>> slot of the archive.  Set it with
482159047fSniklas 	<<bfd_set_archive_head>> (q.v.).  A given BFD may be in only one
492159047fSniklas 	open output archive at a time.
502159047fSniklas 
512159047fSniklas 	As expected, the BFD archive code is more general than the
522159047fSniklas 	archive code of any given environment.  BFD archives may
532159047fSniklas 	contain files of different formats (e.g., a.out and coff) and
542159047fSniklas 	even different architectures.  You may even place archives
552159047fSniklas 	recursively into archives!
562159047fSniklas 
572159047fSniklas 	This can cause unexpected confusion, since some archive
582159047fSniklas 	formats are more expressive than others.  For instance, Intel
592159047fSniklas 	COFF archives can preserve long filenames; SunOS a.out archives
602159047fSniklas 	cannot.  If you move a file from the first to the second
612159047fSniklas 	format and back again, the filename may be truncated.
622159047fSniklas 	Likewise, different a.out environments have different
632159047fSniklas 	conventions as to how they truncate filenames, whether they
642159047fSniklas 	preserve directory names in filenames, etc.  When
652159047fSniklas 	interoperating with native tools, be sure your files are
662159047fSniklas 	homogeneous.
672159047fSniklas 
682159047fSniklas 	Beware: most of these formats do not react well to the
692159047fSniklas 	presence of spaces in filenames.  We do the best we can, but
702159047fSniklas 	can't always handle this case due to restrictions in the format of
712159047fSniklas 	archives.  Many Unix utilities are braindead in regards to
722159047fSniklas 	spaces and such in filenames anyway, so this shouldn't be much
732159047fSniklas 	of a restriction.
742159047fSniklas 
752159047fSniklas 	Archives are supported in BFD in <<archive.c>>.
762159047fSniklas 
772159047fSniklas */
782159047fSniklas 
792159047fSniklas /* Assumes:
802159047fSniklas    o - all archive elements start on an even boundary, newline padded;
812159047fSniklas    o - all arch headers are char *;
822159047fSniklas    o - all arch headers are the same size (across architectures).
832159047fSniklas */
842159047fSniklas 
852159047fSniklas /* Some formats provide a way to cram a long filename into the short
862159047fSniklas    (16 chars) space provided by a BSD archive.  The trick is: make a
872159047fSniklas    special "file" in the front of the archive, sort of like the SYMDEF
882159047fSniklas    entry.  If the filename is too long to fit, put it in the extended
892159047fSniklas    name table, and use its index as the filename.  To prevent
902159047fSniklas    confusion prepend the index with a space.  This means you can't
912159047fSniklas    have filenames that start with a space, but then again, many Unix
922159047fSniklas    utilities can't handle that anyway.
932159047fSniklas 
942159047fSniklas    This scheme unfortunately requires that you stand on your head in
952159047fSniklas    order to write an archive since you need to put a magic file at the
962159047fSniklas    front, and need to touch every entry to do so.  C'est la vie.
972159047fSniklas 
982159047fSniklas    We support two variants of this idea:
992159047fSniklas    The SVR4 format (extended name table is named "//"),
1002159047fSniklas    and an extended pseudo-BSD variant (extended name table is named
1012159047fSniklas    "ARFILENAMES/").  The origin of the latter format is uncertain.
1022159047fSniklas 
1032159047fSniklas    BSD 4.4 uses a third scheme:  It writes a long filename
1042159047fSniklas    directly after the header.  This allows 'ar q' to work.
1052159047fSniklas    We currently can read BSD 4.4 archives, but not write them.
1062159047fSniklas */
1072159047fSniklas 
1082159047fSniklas /* Summary of archive member names:
1092159047fSniklas 
1102159047fSniklas  Symbol table (must be first):
1112159047fSniklas  "__.SYMDEF       " - Symbol table, Berkeley style, produced by ranlib.
1122159047fSniklas  "/               " - Symbol table, system 5 style.
1132159047fSniklas 
1142159047fSniklas  Long name table (must be before regular file members):
1152159047fSniklas  "//              " - Long name table, System 5 R4 style.
1162159047fSniklas  "ARFILENAMES/    " - Long name table, non-standard extended BSD (not BSD 4.4).
1172159047fSniklas 
1182159047fSniklas  Regular file members with short names:
1192159047fSniklas  "filename.o/     " - Regular file, System 5 style (embedded spaces ok).
1202159047fSniklas  "filename.o      " - Regular file, Berkeley style (no embedded spaces).
1212159047fSniklas 
1222159047fSniklas  Regular files with long names (or embedded spaces, for BSD variants):
1232159047fSniklas  "/18             " - SVR4 style, name at offset 18 in name table.
1242159047fSniklas  "#1/23           " - Long name (or embedded paces) 23 characters long,
1252159047fSniklas 		      BSD 4.4 style, full name follows header.
1262159047fSniklas 		      Implemented for reading, not writing.
1272159047fSniklas  " 18             " - Long name 18 characters long, extended pseudo-BSD.
1282159047fSniklas  */
1292159047fSniklas 
1302159047fSniklas #include "bfd.h"
1312159047fSniklas #include "sysdep.h"
1322159047fSniklas #include "libbfd.h"
1332159047fSniklas #include "aout/ar.h"
1342159047fSniklas #include "aout/ranlib.h"
135c074d1c9Sdrahn #include "safe-ctype.h"
1362159047fSniklas 
1372159047fSniklas #ifndef errno
1382159047fSniklas extern int errno;
1392159047fSniklas #endif
1402159047fSniklas 
1412159047fSniklas #ifdef GNU960
1422159047fSniklas #define BFD_GNU960_ARMAG(abfd)	(BFD_COFF_FILE_P((abfd)) ? ARMAG : ARMAGB)
1432159047fSniklas #endif
1442159047fSniklas 
1452159047fSniklas /* We keep a cache of archive filepointers to archive elements to
1462159047fSniklas    speed up searching the archive by filepos.  We only add an entry to
1472159047fSniklas    the cache when we actually read one.  We also don't sort the cache;
1482159047fSniklas    it's generally short enough to search linearly.
1492159047fSniklas    Note that the pointers here point to the front of the ar_hdr, not
150b55d4692Sfgsch    to the front of the contents!  */
151b55d4692Sfgsch struct ar_cache {
1522159047fSniklas   file_ptr ptr;
1532159047fSniklas   bfd *arelt;
1542159047fSniklas   struct ar_cache *next;
1552159047fSniklas };
1562159047fSniklas 
1572159047fSniklas #define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
1582159047fSniklas #define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
1592159047fSniklas 
1602159047fSniklas #define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
1612159047fSniklas #define arch_hdr(bfd) ((struct ar_hdr *) arch_eltdata(bfd)->arch_header)
1622159047fSniklas 
1632159047fSniklas 
164c074d1c9Sdrahn bfd_boolean
_bfd_generic_mkarchive(bfd * abfd)165007c2a45Smiod _bfd_generic_mkarchive (bfd *abfd)
1662159047fSniklas {
167c074d1c9Sdrahn   bfd_size_type amt = sizeof (struct artdata);
1682159047fSniklas 
169007c2a45Smiod   abfd->tdata.aout_ar_data = bfd_zalloc (abfd, amt);
1702159047fSniklas   if (bfd_ardata (abfd) == NULL)
171c074d1c9Sdrahn     return FALSE;
1722159047fSniklas 
1732159047fSniklas   bfd_ardata (abfd)->cache = NULL;
1742159047fSniklas   bfd_ardata (abfd)->archive_head = NULL;
1752159047fSniklas   bfd_ardata (abfd)->symdefs = NULL;
1762159047fSniklas   bfd_ardata (abfd)->extended_names = NULL;
1772159047fSniklas   bfd_ardata (abfd)->tdata = NULL;
1782159047fSniklas 
179c074d1c9Sdrahn   return TRUE;
1802159047fSniklas }
1812159047fSniklas 
1822159047fSniklas /*
1832159047fSniklas FUNCTION
1842159047fSniklas 	bfd_get_next_mapent
1852159047fSniklas 
1862159047fSniklas SYNOPSIS
187007c2a45Smiod 	symindex bfd_get_next_mapent
188007c2a45Smiod 	  (bfd *abfd, symindex previous, carsym **sym);
1892159047fSniklas 
1902159047fSniklas DESCRIPTION
1912159047fSniklas 	Step through archive @var{abfd}'s symbol table (if it
1922159047fSniklas 	has one).  Successively update @var{sym} with the next symbol's
1932159047fSniklas 	information, returning that symbol's (internal) index into the
1942159047fSniklas 	symbol table.
1952159047fSniklas 
1962159047fSniklas 	Supply <<BFD_NO_MORE_SYMBOLS>> as the @var{previous} entry to get
1972159047fSniklas 	the first one; returns <<BFD_NO_MORE_SYMBOLS>> when you've already
1982159047fSniklas 	got the last one.
1992159047fSniklas 
2002159047fSniklas 	A <<carsym>> is a canonical archive symbol.  The only
2012159047fSniklas 	user-visible element is its name, a null-terminated string.
2022159047fSniklas */
2032159047fSniklas 
2042159047fSniklas symindex
bfd_get_next_mapent(bfd * abfd,symindex prev,carsym ** entry)205007c2a45Smiod bfd_get_next_mapent (bfd *abfd, symindex prev, carsym **entry)
2062159047fSniklas {
2072159047fSniklas   if (!bfd_has_map (abfd))
2082159047fSniklas     {
2092159047fSniklas       bfd_set_error (bfd_error_invalid_operation);
2102159047fSniklas       return BFD_NO_MORE_SYMBOLS;
2112159047fSniklas     }
2122159047fSniklas 
2132159047fSniklas   if (prev == BFD_NO_MORE_SYMBOLS)
2142159047fSniklas     prev = 0;
2152159047fSniklas   else
2162159047fSniklas     ++prev;
2172159047fSniklas   if (prev >= bfd_ardata (abfd)->symdef_count)
2182159047fSniklas     return BFD_NO_MORE_SYMBOLS;
2192159047fSniklas 
2202159047fSniklas   *entry = (bfd_ardata (abfd)->symdefs + prev);
2212159047fSniklas   return prev;
2222159047fSniklas }
2232159047fSniklas 
2242159047fSniklas /* To be called by backends only */
2252159047fSniklas 
2262159047fSniklas bfd *
_bfd_create_empty_archive_element_shell(bfd * obfd)227007c2a45Smiod _bfd_create_empty_archive_element_shell (bfd *obfd)
2282159047fSniklas {
229c88b1d6cSniklas   return _bfd_new_bfd_contained_in (obfd);
2302159047fSniklas }
2312159047fSniklas 
2322159047fSniklas /*
2332159047fSniklas FUNCTION
2342159047fSniklas 	bfd_set_archive_head
2352159047fSniklas 
2362159047fSniklas SYNOPSIS
237c074d1c9Sdrahn 	bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head);
2382159047fSniklas 
2392159047fSniklas DESCRIPTION
2402159047fSniklas 	Set the head of the chain of
2412159047fSniklas 	BFDs contained in the archive @var{output} to @var{new_head}.
2422159047fSniklas */
2432159047fSniklas 
244c074d1c9Sdrahn bfd_boolean
bfd_set_archive_head(bfd * output_archive,bfd * new_head)245007c2a45Smiod bfd_set_archive_head (bfd *output_archive, bfd *new_head)
2462159047fSniklas {
2472159047fSniklas   output_archive->archive_head = new_head;
248c074d1c9Sdrahn   return TRUE;
2492159047fSniklas }
2502159047fSniklas 
2512159047fSniklas bfd *
_bfd_look_for_bfd_in_cache(bfd * arch_bfd,file_ptr filepos)252007c2a45Smiod _bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos)
2532159047fSniklas {
2542159047fSniklas   struct ar_cache *current;
2552159047fSniklas 
2562159047fSniklas   for (current = bfd_ardata (arch_bfd)->cache; current != NULL;
2572159047fSniklas        current = current->next)
2582159047fSniklas     if (current->ptr == filepos)
2592159047fSniklas       return current->arelt;
2602159047fSniklas 
2612159047fSniklas   return NULL;
2622159047fSniklas }
2632159047fSniklas 
2642159047fSniklas /* Kind of stupid to call cons for each one, but we don't do too many */
265c074d1c9Sdrahn bfd_boolean
_bfd_add_bfd_to_archive_cache(bfd * arch_bfd,file_ptr filepos,bfd * new_elt)266007c2a45Smiod _bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt)
2672159047fSniklas {
268c074d1c9Sdrahn   bfd_size_type amt = sizeof (struct ar_cache);
2692159047fSniklas 
270007c2a45Smiod   struct ar_cache *new_cache = bfd_zalloc (arch_bfd, amt);
2712159047fSniklas   if (new_cache == NULL)
272c074d1c9Sdrahn     return FALSE;
2732159047fSniklas 
2742159047fSniklas   new_cache->ptr = filepos;
2752159047fSniklas   new_cache->arelt = new_elt;
276007c2a45Smiod   new_cache->next = NULL;
2772159047fSniklas   if (bfd_ardata (arch_bfd)->cache == NULL)
2782159047fSniklas     bfd_ardata (arch_bfd)->cache = new_cache;
2792159047fSniklas   else
2802159047fSniklas     {
2812159047fSniklas       struct ar_cache *current = bfd_ardata (arch_bfd)->cache;
2822159047fSniklas 
2832159047fSniklas       while (current->next != NULL)
2842159047fSniklas 	current = current->next;
2852159047fSniklas       current->next = new_cache;
2862159047fSniklas     }
2872159047fSniklas 
288c074d1c9Sdrahn   return TRUE;
2892159047fSniklas }
2902159047fSniklas 
2912159047fSniklas /* The name begins with space.  Hence the rest of the name is an index into
2922159047fSniklas    the string table.  */
2932159047fSniklas 
2942159047fSniklas static char *
get_extended_arelt_filename(bfd * arch,const char * name)295007c2a45Smiod get_extended_arelt_filename (bfd *arch, const char *name)
2962159047fSniklas {
2972159047fSniklas   unsigned long index = 0;
2982159047fSniklas 
2992159047fSniklas   /* Should extract string so that I can guarantee not to overflow into
3002159047fSniklas      the next region, but I'm too lazy.  */
3012159047fSniklas   errno = 0;
3022159047fSniklas   /* Skip first char, which is '/' in SVR4 or ' ' in some other variants.  */
3032159047fSniklas   index = strtol (name + 1, NULL, 10);
3042159047fSniklas   if (errno != 0)
3052159047fSniklas     {
3062159047fSniklas       bfd_set_error (bfd_error_malformed_archive);
3072159047fSniklas       return NULL;
3082159047fSniklas     }
3092159047fSniklas 
3102159047fSniklas   return bfd_ardata (arch)->extended_names + index;
3112159047fSniklas }
3122159047fSniklas 
3132159047fSniklas /* This functions reads an arch header and returns an areltdata pointer, or
3142159047fSniklas    NULL on error.
3152159047fSniklas 
3162159047fSniklas    Presumes the file pointer is already in the right place (ie pointing
3172159047fSniklas    to the ar_hdr in the file).   Moves the file pointer; on success it
3182159047fSniklas    should be pointing to the front of the file contents; on failure it
3192159047fSniklas    could have been moved arbitrarily.
3202159047fSniklas */
3212159047fSniklas 
322007c2a45Smiod void *
_bfd_generic_read_ar_hdr(bfd * abfd)323007c2a45Smiod _bfd_generic_read_ar_hdr (bfd *abfd)
3242159047fSniklas {
325007c2a45Smiod   return _bfd_generic_read_ar_hdr_mag (abfd, NULL);
326c88b1d6cSniklas }
3272159047fSniklas 
328c88b1d6cSniklas /* Alpha ECOFF uses an optional different ARFMAG value, so we have a
329c88b1d6cSniklas    variant of _bfd_generic_read_ar_hdr which accepts a magic string.  */
330c88b1d6cSniklas 
331007c2a45Smiod void *
_bfd_generic_read_ar_hdr_mag(bfd * abfd,const char * mag)332007c2a45Smiod _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
333c88b1d6cSniklas {
3342159047fSniklas   struct ar_hdr hdr;
3352159047fSniklas   char *hdrp = (char *) &hdr;
336c074d1c9Sdrahn   size_t parsed_size;
3372159047fSniklas   struct areltdata *ared;
3382159047fSniklas   char *filename = NULL;
339c074d1c9Sdrahn   bfd_size_type namelen = 0;
340c074d1c9Sdrahn   bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
3412159047fSniklas   char *allocptr = 0;
3422159047fSniklas 
343007c2a45Smiod   if (bfd_bread (hdrp, sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr))
3442159047fSniklas     {
3452159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
3462159047fSniklas 	bfd_set_error (bfd_error_no_more_archived_files);
3472159047fSniklas       return NULL;
3482159047fSniklas     }
349c88b1d6cSniklas   if (strncmp (hdr.ar_fmag, ARFMAG, 2) != 0
350c88b1d6cSniklas       && (mag == NULL
351c88b1d6cSniklas 	  || strncmp (hdr.ar_fmag, mag, 2) != 0))
3522159047fSniklas     {
3532159047fSniklas       bfd_set_error (bfd_error_malformed_archive);
3542159047fSniklas       return NULL;
3552159047fSniklas     }
3562159047fSniklas 
3572159047fSniklas   errno = 0;
3582159047fSniklas   parsed_size = strtol (hdr.ar_size, NULL, 10);
3592159047fSniklas   if (errno != 0)
3602159047fSniklas     {
3612159047fSniklas       bfd_set_error (bfd_error_malformed_archive);
3622159047fSniklas       return NULL;
3632159047fSniklas     }
3642159047fSniklas 
3652159047fSniklas   /* Extract the filename from the archive - there are two ways to
366b305b0f1Sespie      specify an extended name table, either the first char of the
3672159047fSniklas      name is a space, or it's a slash.  */
3682159047fSniklas   if ((hdr.ar_name[0] == '/'
3692159047fSniklas        || (hdr.ar_name[0] == ' '
3702159047fSniklas 	   && memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL))
3712159047fSniklas       && bfd_ardata (abfd)->extended_names != NULL)
3722159047fSniklas     {
3732159047fSniklas       filename = get_extended_arelt_filename (abfd, hdr.ar_name);
3742159047fSniklas       if (filename == NULL)
3752159047fSniklas 	{
3762159047fSniklas 	  bfd_set_error (bfd_error_malformed_archive);
3772159047fSniklas 	  return NULL;
3782159047fSniklas 	}
3792159047fSniklas     }
3802159047fSniklas   /* BSD4.4-style long filename.
3812159047fSniklas      Only implemented for reading, so far!  */
382b305b0f1Sespie   else if (hdr.ar_name[0] == '#'
383b305b0f1Sespie 	   && hdr.ar_name[1] == '1'
384b305b0f1Sespie 	   && hdr.ar_name[2] == '/'
385c074d1c9Sdrahn 	   && ISDIGIT (hdr.ar_name[3]))
3862159047fSniklas     {
3872159047fSniklas       /* BSD-4.4 extended name */
3882159047fSniklas       namelen = atoi (&hdr.ar_name[3]);
3892159047fSniklas       allocsize += namelen + 1;
3902159047fSniklas       parsed_size -= namelen;
3912159047fSniklas 
3922159047fSniklas       allocptr = bfd_zalloc (abfd, allocsize);
3932159047fSniklas       if (allocptr == NULL)
3942159047fSniklas 	return NULL;
3952159047fSniklas       filename = (allocptr
3962159047fSniklas 		  + sizeof (struct areltdata)
3972159047fSniklas 		  + sizeof (struct ar_hdr));
398c074d1c9Sdrahn       if (bfd_bread (filename, namelen, abfd) != namelen)
3992159047fSniklas 	{
4002159047fSniklas 	  if (bfd_get_error () != bfd_error_system_call)
4012159047fSniklas 	    bfd_set_error (bfd_error_no_more_archived_files);
4022159047fSniklas 	  return NULL;
4032159047fSniklas 	}
4042159047fSniklas       filename[namelen] = '\0';
4052159047fSniklas     }
4062159047fSniklas   else
4072159047fSniklas     {
4082159047fSniklas       /* We judge the end of the name by looking for '/' or ' '.
4092159047fSniklas 	 Note:  The SYSV format (terminated by '/') allows embedded
4102159047fSniklas 	 spaces, so only look for ' ' if we don't find '/'.  */
4112159047fSniklas 
412b305b0f1Sespie       char *e;
413007c2a45Smiod       e = memchr (hdr.ar_name, '\0', ar_maxnamelen (abfd));
414b305b0f1Sespie       if (e == NULL)
4152159047fSniklas 	{
416007c2a45Smiod 	  e = memchr (hdr.ar_name, '/', ar_maxnamelen (abfd));
417b305b0f1Sespie 	  if (e == NULL)
418007c2a45Smiod 	    e = memchr (hdr.ar_name, ' ', ar_maxnamelen (abfd));
4192159047fSniklas 	}
420b305b0f1Sespie 
421b305b0f1Sespie       if (e != NULL)
422b305b0f1Sespie 	namelen = e - hdr.ar_name;
423b305b0f1Sespie       else
424b305b0f1Sespie 	{
425b305b0f1Sespie 	  /* If we didn't find a termination character, then the name
426b305b0f1Sespie 	     must be the entire field.  */
427b305b0f1Sespie 	  namelen = ar_maxnamelen (abfd);
4282159047fSniklas 	}
4292159047fSniklas 
4302159047fSniklas       allocsize += namelen + 1;
4312159047fSniklas     }
4322159047fSniklas 
4332159047fSniklas   if (!allocptr)
4342159047fSniklas     {
4352159047fSniklas       allocptr = bfd_zalloc (abfd, allocsize);
4362159047fSniklas       if (allocptr == NULL)
4372159047fSniklas 	return NULL;
4382159047fSniklas     }
4392159047fSniklas 
4402159047fSniklas   ared = (struct areltdata *) allocptr;
4412159047fSniklas 
4422159047fSniklas   ared->arch_header = allocptr + sizeof (struct areltdata);
443007c2a45Smiod   memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr));
4442159047fSniklas   ared->parsed_size = parsed_size;
4452159047fSniklas 
4462159047fSniklas   if (filename != NULL)
4472159047fSniklas     ared->filename = filename;
4482159047fSniklas   else
4492159047fSniklas     {
4502159047fSniklas       ared->filename = allocptr + (sizeof (struct areltdata) +
4512159047fSniklas 				   sizeof (struct ar_hdr));
4522159047fSniklas       if (namelen)
453007c2a45Smiod 	memcpy (ared->filename, hdr.ar_name, namelen);
4542159047fSniklas       ared->filename[namelen] = '\0';
4552159047fSniklas     }
4562159047fSniklas 
457007c2a45Smiod   return ared;
4582159047fSniklas }
4592159047fSniklas 
4602159047fSniklas /* This is an internal function; it's mainly used when indexing
4612159047fSniklas    through the archive symbol table, but also used to get the next
4622159047fSniklas    element, since it handles the bookkeeping so nicely for us.  */
4632159047fSniklas 
4642159047fSniklas bfd *
_bfd_get_elt_at_filepos(bfd * archive,file_ptr filepos)465007c2a45Smiod _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
4662159047fSniklas {
4672159047fSniklas   struct areltdata *new_areldata;
4682159047fSniklas   bfd *n_nfd;
4692159047fSniklas 
4702159047fSniklas   n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
4712159047fSniklas   if (n_nfd)
4722159047fSniklas     return n_nfd;
4732159047fSniklas 
4742159047fSniklas   if (0 > bfd_seek (archive, filepos, SEEK_SET))
4752159047fSniklas     return NULL;
4762159047fSniklas 
477007c2a45Smiod   if ((new_areldata = _bfd_read_ar_hdr (archive)) == NULL)
4782159047fSniklas     return NULL;
4792159047fSniklas 
4802159047fSniklas   n_nfd = _bfd_create_empty_archive_element_shell (archive);
4812159047fSniklas   if (n_nfd == NULL)
4822159047fSniklas     {
483007c2a45Smiod       bfd_release (archive, new_areldata);
4842159047fSniklas       return NULL;
4852159047fSniklas     }
4862159047fSniklas 
4872159047fSniklas   n_nfd->origin = bfd_tell (archive);
488007c2a45Smiod   n_nfd->arelt_data = new_areldata;
4892159047fSniklas   n_nfd->filename = new_areldata->filename;
4902159047fSniklas 
4912159047fSniklas   if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
4922159047fSniklas     return n_nfd;
4932159047fSniklas 
494b55d4692Sfgsch   /* Huh?  */
495007c2a45Smiod   bfd_release (archive, n_nfd);
496007c2a45Smiod   bfd_release (archive, new_areldata);
4972159047fSniklas   return NULL;
4982159047fSniklas }
4992159047fSniklas 
500c88b1d6cSniklas /* Return the BFD which is referenced by the symbol in ABFD indexed by
501c88b1d6cSniklas    INDEX.  INDEX should have been returned by bfd_get_next_mapent.  */
5022159047fSniklas 
5032159047fSniklas bfd *
_bfd_generic_get_elt_at_index(bfd * abfd,symindex index)504007c2a45Smiod _bfd_generic_get_elt_at_index (bfd *abfd, symindex index)
5052159047fSniklas {
5062159047fSniklas   carsym *entry;
5072159047fSniklas 
5082159047fSniklas   entry = bfd_ardata (abfd)->symdefs + index;
5092159047fSniklas   return _bfd_get_elt_at_filepos (abfd, entry->file_offset);
5102159047fSniklas }
5112159047fSniklas 
5122159047fSniklas /*
5132159047fSniklas FUNCTION
5142159047fSniklas 	bfd_openr_next_archived_file
5152159047fSniklas 
5162159047fSniklas SYNOPSIS
5172159047fSniklas 	bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous);
5182159047fSniklas 
5192159047fSniklas DESCRIPTION
5202159047fSniklas 	Provided a BFD, @var{archive}, containing an archive and NULL, open
5212159047fSniklas 	an input BFD on the first contained element and returns that.
5222159047fSniklas 	Subsequent calls should pass
5232159047fSniklas 	the archive and the previous return value to return a created
5242159047fSniklas 	BFD to the next contained element. NULL is returned when there
5252159047fSniklas 	are no more.
5262159047fSniklas */
5272159047fSniklas 
5282159047fSniklas bfd *
bfd_openr_next_archived_file(bfd * archive,bfd * last_file)529007c2a45Smiod bfd_openr_next_archived_file (bfd *archive, bfd *last_file)
5302159047fSniklas {
5312159047fSniklas   if ((bfd_get_format (archive) != bfd_archive) ||
5322159047fSniklas       (archive->direction == write_direction))
5332159047fSniklas     {
5342159047fSniklas       bfd_set_error (bfd_error_invalid_operation);
5352159047fSniklas       return NULL;
5362159047fSniklas     }
5372159047fSniklas 
5382159047fSniklas   return BFD_SEND (archive,
539007c2a45Smiod 		   openr_next_archived_file, (archive, last_file));
5402159047fSniklas }
5412159047fSniklas 
5422159047fSniklas bfd *
bfd_generic_openr_next_archived_file(bfd * archive,bfd * last_file)543007c2a45Smiod bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
5442159047fSniklas {
5452159047fSniklas   file_ptr filestart;
5462159047fSniklas 
5472159047fSniklas   if (!last_file)
5482159047fSniklas     filestart = bfd_ardata (archive)->first_file_filepos;
5492159047fSniklas   else
5502159047fSniklas     {
5512159047fSniklas       unsigned int size = arelt_size (last_file);
5522159047fSniklas       /* Pad to an even boundary...
5532159047fSniklas 	 Note that last_file->origin can be odd in the case of
5542159047fSniklas 	 BSD-4.4-style element with a long odd size.  */
5552159047fSniklas       filestart = last_file->origin + size;
5562159047fSniklas       filestart += filestart % 2;
5572159047fSniklas     }
5582159047fSniklas 
5592159047fSniklas   return _bfd_get_elt_at_filepos (archive, filestart);
5602159047fSniklas }
5612159047fSniklas 
5622159047fSniklas const bfd_target *
bfd_generic_archive_p(bfd * abfd)563007c2a45Smiod bfd_generic_archive_p (bfd *abfd)
5642159047fSniklas {
5652159047fSniklas   struct artdata *tdata_hold;
5662159047fSniklas   char armag[SARMAG + 1];
567c074d1c9Sdrahn   bfd_size_type amt;
5682159047fSniklas 
569007c2a45Smiod   if (bfd_bread (armag, SARMAG, abfd) != SARMAG)
5702159047fSniklas     {
5712159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
5722159047fSniklas 	bfd_set_error (bfd_error_wrong_format);
5732159047fSniklas       return NULL;
5742159047fSniklas     }
5752159047fSniklas 
5762159047fSniklas #ifdef GNU960
5772159047fSniklas   if (strncmp (armag, BFD_GNU960_ARMAG (abfd), SARMAG) != 0)
5782159047fSniklas     return 0;
5792159047fSniklas #else
5802159047fSniklas   if (strncmp (armag, ARMAG, SARMAG) != 0 &&
5812159047fSniklas       strncmp (armag, ARMAGB, SARMAG) != 0)
5822159047fSniklas     return 0;
5832159047fSniklas #endif
5842159047fSniklas 
585c074d1c9Sdrahn   tdata_hold = bfd_ardata (abfd);
5862159047fSniklas 
587c074d1c9Sdrahn   amt = sizeof (struct artdata);
588007c2a45Smiod   bfd_ardata (abfd) = bfd_zalloc (abfd, amt);
5892159047fSniklas   if (bfd_ardata (abfd) == NULL)
590c074d1c9Sdrahn     {
591c074d1c9Sdrahn       bfd_ardata (abfd) = tdata_hold;
5922159047fSniklas       return NULL;
593c074d1c9Sdrahn     }
5942159047fSniklas 
5952159047fSniklas   bfd_ardata (abfd)->first_file_filepos = SARMAG;
5962159047fSniklas   bfd_ardata (abfd)->cache = NULL;
5972159047fSniklas   bfd_ardata (abfd)->archive_head = NULL;
5982159047fSniklas   bfd_ardata (abfd)->symdefs = NULL;
5992159047fSniklas   bfd_ardata (abfd)->extended_names = NULL;
6002159047fSniklas   bfd_ardata (abfd)->tdata = NULL;
6012159047fSniklas 
602c074d1c9Sdrahn   if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))
603c074d1c9Sdrahn       || !BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd)))
6042159047fSniklas     {
605b305b0f1Sespie       if (bfd_get_error () != bfd_error_system_call)
606b305b0f1Sespie 	bfd_set_error (bfd_error_wrong_format);
6072159047fSniklas       bfd_release (abfd, bfd_ardata (abfd));
608c074d1c9Sdrahn       bfd_ardata (abfd) = tdata_hold;
6092159047fSniklas       return NULL;
6102159047fSniklas     }
6112159047fSniklas 
6122159047fSniklas   if (bfd_has_map (abfd))
6132159047fSniklas     {
6142159047fSniklas       bfd *first;
6152159047fSniklas 
6162159047fSniklas       /* This archive has a map, so we may presume that the contents
617c88b1d6cSniklas 	 are object files.  Make sure that if the first file in the
618c88b1d6cSniklas 	 archive can be recognized as an object file, it is for this
619c88b1d6cSniklas 	 target.  If not, assume that this is the wrong format.  If
620c88b1d6cSniklas 	 the first file is not an object file, somebody is doing
621c88b1d6cSniklas 	 something weird, and we permit it so that ar -t will work.
6222159047fSniklas 
6232159047fSniklas 	 This is done because any normal format will recognize any
6242159047fSniklas 	 normal archive, regardless of the format of the object files.
6252159047fSniklas 	 We do accept an empty archive.  */
6262159047fSniklas 
627007c2a45Smiod       first = bfd_openr_next_archived_file (abfd, NULL);
6282159047fSniklas       if (first != NULL)
6292159047fSniklas 	{
630c074d1c9Sdrahn 	  bfd_boolean fail;
6312159047fSniklas 
632c074d1c9Sdrahn 	  first->target_defaulted = FALSE;
633c074d1c9Sdrahn 	  fail = FALSE;
634c88b1d6cSniklas 	  if (bfd_check_format (first, bfd_object)
635c88b1d6cSniklas 	      && first->xvec != abfd->xvec)
6362159047fSniklas 	    {
637c074d1c9Sdrahn #if 0
638c074d1c9Sdrahn 	      /* We ought to close `first' here, but we can't, because
639c074d1c9Sdrahn 		 we have no way to remove it from the archive cache.
640c074d1c9Sdrahn 		 It's close to impossible to figure out when we can
641c074d1c9Sdrahn 		 release bfd_ardata.  FIXME.  */
642007c2a45Smiod 	      bfd_close (first);
6432159047fSniklas 	      bfd_release (abfd, bfd_ardata (abfd));
644c074d1c9Sdrahn #endif
645c074d1c9Sdrahn 	      bfd_set_error (bfd_error_wrong_object_format);
646c074d1c9Sdrahn 	      bfd_ardata (abfd) = tdata_hold;
6472159047fSniklas 	      return NULL;
6482159047fSniklas 	    }
649c074d1c9Sdrahn 	  /* And we ought to close `first' here too.  */
6502159047fSniklas 	}
6512159047fSniklas     }
6522159047fSniklas 
6532159047fSniklas   return abfd->xvec;
6542159047fSniklas }
6552159047fSniklas 
6562159047fSniklas /* Some constants for a 32 bit BSD archive structure.  We do not
6572159047fSniklas    support 64 bit archives presently; so far as I know, none actually
6582159047fSniklas    exist.  Supporting them would require changing these constants, and
659c074d1c9Sdrahn    changing some H_GET_32 to H_GET_64.  */
6602159047fSniklas 
6612159047fSniklas /* The size of an external symdef structure.  */
6622159047fSniklas #define BSD_SYMDEF_SIZE 8
6632159047fSniklas 
6642159047fSniklas /* The offset from the start of a symdef structure to the file offset.  */
6652159047fSniklas #define BSD_SYMDEF_OFFSET_SIZE 4
6662159047fSniklas 
6672159047fSniklas /* The size of the symdef count.  */
6682159047fSniklas #define BSD_SYMDEF_COUNT_SIZE 4
6692159047fSniklas 
6702159047fSniklas /* The size of the string count.  */
6712159047fSniklas #define BSD_STRING_COUNT_SIZE 4
6722159047fSniklas 
673c074d1c9Sdrahn /* Returns FALSE on error, TRUE otherwise */
6742159047fSniklas 
675c074d1c9Sdrahn static bfd_boolean
do_slurp_bsd_armap(bfd * abfd)676007c2a45Smiod do_slurp_bsd_armap (bfd *abfd)
6772159047fSniklas {
6782159047fSniklas   struct areltdata *mapdata;
6792159047fSniklas   unsigned int counter;
6802159047fSniklas   bfd_byte *raw_armap, *rbase;
6812159047fSniklas   struct artdata *ardata = bfd_ardata (abfd);
6822159047fSniklas   char *stringbase;
683c074d1c9Sdrahn   bfd_size_type parsed_size, amt;
6842159047fSniklas   carsym *set;
6852159047fSniklas 
686007c2a45Smiod   mapdata = _bfd_read_ar_hdr (abfd);
6872159047fSniklas   if (mapdata == NULL)
688c074d1c9Sdrahn     return FALSE;
6892159047fSniklas   parsed_size = mapdata->parsed_size;
690007c2a45Smiod   bfd_release (abfd, mapdata);	/* Don't need it any more.  */
6912159047fSniklas 
692007c2a45Smiod   raw_armap = bfd_zalloc (abfd, parsed_size);
693007c2a45Smiod   if (raw_armap == NULL)
694c074d1c9Sdrahn     return FALSE;
6952159047fSniklas 
696007c2a45Smiod   if (bfd_bread (raw_armap, parsed_size, abfd) != parsed_size)
6972159047fSniklas     {
6982159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
6992159047fSniklas 	bfd_set_error (bfd_error_malformed_archive);
7002159047fSniklas     byebye:
701007c2a45Smiod       bfd_release (abfd, raw_armap);
702c074d1c9Sdrahn       return FALSE;
7032159047fSniklas     }
7042159047fSniklas 
705c074d1c9Sdrahn   ardata->symdef_count = H_GET_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE;
7062159047fSniklas 
7072159047fSniklas   if (ardata->symdef_count * BSD_SYMDEF_SIZE >
7082159047fSniklas       parsed_size - BSD_SYMDEF_COUNT_SIZE)
7092159047fSniklas     {
7102159047fSniklas       /* Probably we're using the wrong byte ordering.  */
7112159047fSniklas       bfd_set_error (bfd_error_wrong_format);
7122159047fSniklas       goto byebye;
7132159047fSniklas     }
7142159047fSniklas 
7152159047fSniklas   ardata->cache = 0;
7162159047fSniklas   rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE;
7172159047fSniklas   stringbase = ((char *) rbase
7182159047fSniklas 		+ ardata->symdef_count * BSD_SYMDEF_SIZE
7192159047fSniklas 		+ BSD_STRING_COUNT_SIZE);
720007c2a45Smiod   amt = ardata->symdef_count * sizeof (carsym);
721007c2a45Smiod   ardata->symdefs = bfd_alloc (abfd, amt);
7222159047fSniklas   if (!ardata->symdefs)
723c074d1c9Sdrahn     return FALSE;
7242159047fSniklas 
7252159047fSniklas   for (counter = 0, set = ardata->symdefs;
7262159047fSniklas        counter < ardata->symdef_count;
7272159047fSniklas        counter++, set++, rbase += BSD_SYMDEF_SIZE)
7282159047fSniklas     {
729c074d1c9Sdrahn       set->name = H_GET_32 (abfd, rbase) + stringbase;
730c074d1c9Sdrahn       set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
7312159047fSniklas     }
7322159047fSniklas 
7332159047fSniklas   ardata->first_file_filepos = bfd_tell (abfd);
734b55d4692Sfgsch   /* Pad to an even boundary if you have to.  */
7352159047fSniklas   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
7362159047fSniklas   /* FIXME, we should provide some way to free raw_ardata when
7372159047fSniklas      we are done using the strings from it.  For now, it seems
738b305b0f1Sespie      to be allocated on an objalloc anyway...  */
739c074d1c9Sdrahn   bfd_has_map (abfd) = TRUE;
740c074d1c9Sdrahn   return TRUE;
7412159047fSniklas }
7422159047fSniklas 
743c074d1c9Sdrahn /* Returns FALSE on error, TRUE otherwise.  */
744b55d4692Sfgsch 
745c074d1c9Sdrahn static bfd_boolean
do_slurp_coff_armap(bfd * abfd)746007c2a45Smiod do_slurp_coff_armap (bfd *abfd)
7472159047fSniklas {
7482159047fSniklas   struct areltdata *mapdata;
7492159047fSniklas   int *raw_armap, *rawptr;
7502159047fSniklas   struct artdata *ardata = bfd_ardata (abfd);
7512159047fSniklas   char *stringbase;
752c074d1c9Sdrahn   bfd_size_type stringsize;
7532159047fSniklas   unsigned int parsed_size;
7542159047fSniklas   carsym *carsyms;
755c074d1c9Sdrahn   bfd_size_type nsymz;		/* Number of symbols in armap.  */
756007c2a45Smiod   bfd_vma (*swap) (const void *);
7572159047fSniklas   char int_buf[sizeof (long)];
758c074d1c9Sdrahn   bfd_size_type carsym_size, ptrsize;
759c074d1c9Sdrahn   unsigned int i;
7602159047fSniklas 
761007c2a45Smiod   mapdata = _bfd_read_ar_hdr (abfd);
7622159047fSniklas   if (mapdata == NULL)
763c074d1c9Sdrahn     return FALSE;
7642159047fSniklas   parsed_size = mapdata->parsed_size;
765007c2a45Smiod   bfd_release (abfd, mapdata);	/* Don't need it any more.  */
7662159047fSniklas 
767007c2a45Smiod   if (bfd_bread (int_buf, 4, abfd) != 4)
7682159047fSniklas     {
7692159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
7702159047fSniklas 	bfd_set_error (bfd_error_malformed_archive);
771c074d1c9Sdrahn       return FALSE;
7722159047fSniklas     }
7732159047fSniklas   /* It seems that all numeric information in a coff archive is always
7742159047fSniklas      in big endian format, nomatter the host or target.  */
7752159047fSniklas   swap = bfd_getb32;
776007c2a45Smiod   nsymz = bfd_getb32 (int_buf);
7772159047fSniklas   stringsize = parsed_size - (4 * nsymz) - 4;
7782159047fSniklas 
7792159047fSniklas #if 1
7802159047fSniklas   /* ... except that some archive formats are broken, and it may be our
7812159047fSniklas      fault - the i960 little endian coff sometimes has big and sometimes
7822159047fSniklas      little, because our tools changed.  Here's a horrible hack to clean
7832159047fSniklas      up the crap.  */
7842159047fSniklas 
785e93f7393Sniklas   if (stringsize > 0xfffff
786e93f7393Sniklas       && bfd_get_arch (abfd) == bfd_arch_i960
787e93f7393Sniklas       && bfd_get_flavour (abfd) == bfd_target_coff_flavour)
7882159047fSniklas     {
789b55d4692Sfgsch       /* This looks dangerous, let's do it the other way around.  */
790007c2a45Smiod       nsymz = bfd_getl32 (int_buf);
7912159047fSniklas       stringsize = parsed_size - (4 * nsymz) - 4;
7922159047fSniklas       swap = bfd_getl32;
7932159047fSniklas     }
7942159047fSniklas #endif
7952159047fSniklas 
7962159047fSniklas   /* The coff armap must be read sequentially.  So we construct a
7972159047fSniklas      bsd-style one in core all at once, for simplicity.  */
7982159047fSniklas 
7992159047fSniklas   carsym_size = (nsymz * sizeof (carsym));
8002159047fSniklas   ptrsize = (4 * nsymz);
8012159047fSniklas 
802007c2a45Smiod   ardata->symdefs = bfd_zalloc (abfd, carsym_size + stringsize + 1);
8032159047fSniklas   if (ardata->symdefs == NULL)
804c074d1c9Sdrahn     return FALSE;
8052159047fSniklas   carsyms = ardata->symdefs;
8062159047fSniklas   stringbase = ((char *) ardata->symdefs) + carsym_size;
8072159047fSniklas 
8082159047fSniklas   /* Allocate and read in the raw offsets.  */
809007c2a45Smiod   raw_armap = bfd_alloc (abfd, ptrsize);
8102159047fSniklas   if (raw_armap == NULL)
8112159047fSniklas     goto release_symdefs;
812007c2a45Smiod   if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
813007c2a45Smiod       || (bfd_bread (stringbase, stringsize, abfd) != stringsize))
8142159047fSniklas     {
8152159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
8162159047fSniklas 	bfd_set_error (bfd_error_malformed_archive);
8172159047fSniklas       goto release_raw_armap;
8182159047fSniklas     }
8192159047fSniklas 
820b55d4692Sfgsch   /* OK, build the carsyms.  */
8212159047fSniklas   for (i = 0; i < nsymz; i++)
8222159047fSniklas     {
8232159047fSniklas       rawptr = raw_armap + i;
824007c2a45Smiod       carsyms->file_offset = swap ((bfd_byte *) rawptr);
8252159047fSniklas       carsyms->name = stringbase;
8262159047fSniklas       stringbase += strlen (stringbase) + 1;
8272159047fSniklas       carsyms++;
8282159047fSniklas     }
8292159047fSniklas   *stringbase = 0;
8302159047fSniklas 
8312159047fSniklas   ardata->symdef_count = nsymz;
8322159047fSniklas   ardata->first_file_filepos = bfd_tell (abfd);
833b55d4692Sfgsch   /* Pad to an even boundary if you have to.  */
8342159047fSniklas   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
8352159047fSniklas 
836c074d1c9Sdrahn   bfd_has_map (abfd) = TRUE;
837007c2a45Smiod   bfd_release (abfd, raw_armap);
8382159047fSniklas 
839b55d4692Sfgsch   /* Check for a second archive header (as used by PE).  */
8402159047fSniklas   {
8412159047fSniklas     struct areltdata *tmp;
8422159047fSniklas 
8432159047fSniklas     bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET);
844007c2a45Smiod     tmp = _bfd_read_ar_hdr (abfd);
8452159047fSniklas     if (tmp != NULL)
8462159047fSniklas       {
8472159047fSniklas 	if (tmp->arch_header[0] == '/'
8482159047fSniklas 	    && tmp->arch_header[1] == ' ')
8492159047fSniklas 	  {
8502159047fSniklas 	    ardata->first_file_filepos +=
851c074d1c9Sdrahn 	      (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1;
8522159047fSniklas 	  }
8532159047fSniklas 	bfd_release (abfd, tmp);
8542159047fSniklas       }
8552159047fSniklas   }
8562159047fSniklas 
857c074d1c9Sdrahn   return TRUE;
8582159047fSniklas 
8592159047fSniklas release_raw_armap:
860007c2a45Smiod   bfd_release (abfd, raw_armap);
8612159047fSniklas release_symdefs:
862007c2a45Smiod   bfd_release (abfd, (ardata)->symdefs);
863c074d1c9Sdrahn   return FALSE;
8642159047fSniklas }
8652159047fSniklas 
8662159047fSniklas /* This routine can handle either coff-style or bsd-style armaps.
867c074d1c9Sdrahn    Returns FALSE on error, TRUE otherwise */
8682159047fSniklas 
869c074d1c9Sdrahn bfd_boolean
bfd_slurp_armap(bfd * abfd)870007c2a45Smiod bfd_slurp_armap (bfd *abfd)
8712159047fSniklas {
8722159047fSniklas   char nextname[17];
873007c2a45Smiod   int i = bfd_bread (nextname, 16, abfd);
8742159047fSniklas 
8752159047fSniklas   if (i == 0)
876c074d1c9Sdrahn     return TRUE;
8772159047fSniklas   if (i != 16)
878c074d1c9Sdrahn     return FALSE;
8792159047fSniklas 
8802159047fSniklas   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
881c074d1c9Sdrahn     return FALSE;
8822159047fSniklas 
8832159047fSniklas   if (!strncmp (nextname, "__.SYMDEF       ", 16)
8842159047fSniklas       || !strncmp (nextname, "__.SYMDEF/      ", 16)) /* old Linux archives */
8852159047fSniklas     return do_slurp_bsd_armap (abfd);
8862159047fSniklas   else if (!strncmp (nextname, "/               ", 16))
8872159047fSniklas     return do_slurp_coff_armap (abfd);
8880c6d0228Sniklas   else if (!strncmp (nextname, "/SYM64/         ", 16))
8890c6d0228Sniklas     {
890c074d1c9Sdrahn       /* 64bit ELF (Irix 6) archive.  */
891c074d1c9Sdrahn #ifdef BFD64
892007c2a45Smiod       extern bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
893c074d1c9Sdrahn       return bfd_elf64_archive_slurp_armap (abfd);
894c074d1c9Sdrahn #else
8950c6d0228Sniklas       bfd_set_error (bfd_error_wrong_format);
896c074d1c9Sdrahn       return FALSE;
897c074d1c9Sdrahn #endif
8980c6d0228Sniklas     }
8992159047fSniklas 
900c074d1c9Sdrahn   bfd_has_map (abfd) = FALSE;
901c074d1c9Sdrahn   return TRUE;
9022159047fSniklas }
9032159047fSniklas 
904c074d1c9Sdrahn /* Returns FALSE on error, TRUE otherwise */
9052159047fSniklas /* flavor 2 of a bsd armap, similar to bfd_slurp_bsd_armap except the
9062159047fSniklas    header is in a slightly different order and the map name is '/'.
9072159047fSniklas    This flavour is used by hp300hpux.  */
9082159047fSniklas 
9092159047fSniklas #define HPUX_SYMDEF_COUNT_SIZE 2
9102159047fSniklas 
911c074d1c9Sdrahn bfd_boolean
bfd_slurp_bsd_armap_f2(bfd * abfd)912007c2a45Smiod bfd_slurp_bsd_armap_f2 (bfd *abfd)
9132159047fSniklas {
9142159047fSniklas   struct areltdata *mapdata;
9152159047fSniklas   char nextname[17];
9162159047fSniklas   unsigned int counter;
9172159047fSniklas   bfd_byte *raw_armap, *rbase;
9182159047fSniklas   struct artdata *ardata = bfd_ardata (abfd);
9192159047fSniklas   char *stringbase;
9202159047fSniklas   unsigned int stringsize;
921c074d1c9Sdrahn   bfd_size_type amt;
9222159047fSniklas   carsym *set;
923007c2a45Smiod   int i = bfd_bread (nextname, 16, abfd);
9242159047fSniklas 
9252159047fSniklas   if (i == 0)
926c074d1c9Sdrahn     return TRUE;
9272159047fSniklas   if (i != 16)
928c074d1c9Sdrahn     return FALSE;
9292159047fSniklas 
930b55d4692Sfgsch   /* The archive has at least 16 bytes in it.  */
931c074d1c9Sdrahn   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
932c074d1c9Sdrahn     return FALSE;
9332159047fSniklas 
9342159047fSniklas   if (!strncmp (nextname, "__.SYMDEF       ", 16)
9352159047fSniklas       || !strncmp (nextname, "__.SYMDEF/      ", 16)) /* old Linux archives */
9362159047fSniklas     return do_slurp_bsd_armap (abfd);
9372159047fSniklas 
9382159047fSniklas   if (strncmp (nextname, "/               ", 16))
9392159047fSniklas     {
940c074d1c9Sdrahn       bfd_has_map (abfd) = FALSE;
941c074d1c9Sdrahn       return TRUE;
9422159047fSniklas     }
9432159047fSniklas 
944007c2a45Smiod   mapdata = _bfd_read_ar_hdr (abfd);
9452159047fSniklas   if (mapdata == NULL)
946c074d1c9Sdrahn     return FALSE;
9472159047fSniklas 
948c074d1c9Sdrahn   amt = mapdata->parsed_size;
949007c2a45Smiod   raw_armap = bfd_zalloc (abfd, amt);
9502159047fSniklas   if (raw_armap == NULL)
9512159047fSniklas     {
9522159047fSniklas     byebye:
953007c2a45Smiod       bfd_release (abfd, mapdata);
954c074d1c9Sdrahn       return FALSE;
9552159047fSniklas     }
9562159047fSniklas 
957007c2a45Smiod   if (bfd_bread (raw_armap, amt, abfd) != amt)
9582159047fSniklas     {
9592159047fSniklas       if (bfd_get_error () != bfd_error_system_call)
9602159047fSniklas 	bfd_set_error (bfd_error_malformed_archive);
9612159047fSniklas     byebyebye:
962007c2a45Smiod       bfd_release (abfd, raw_armap);
9632159047fSniklas       goto byebye;
9642159047fSniklas     }
9652159047fSniklas 
966007c2a45Smiod   ardata->symdef_count = H_GET_16 (abfd, raw_armap);
9672159047fSniklas 
9682159047fSniklas   if (ardata->symdef_count * BSD_SYMDEF_SIZE
9692159047fSniklas       > mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE)
9702159047fSniklas     {
9712159047fSniklas       /* Probably we're using the wrong byte ordering.  */
9722159047fSniklas       bfd_set_error (bfd_error_wrong_format);
9732159047fSniklas       goto byebyebye;
9742159047fSniklas     }
9752159047fSniklas 
9762159047fSniklas   ardata->cache = 0;
9772159047fSniklas 
978c074d1c9Sdrahn   stringsize = H_GET_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE);
979b55d4692Sfgsch   /* Skip sym count and string sz.  */
9802159047fSniklas   stringbase = ((char *) raw_armap
9812159047fSniklas 		+ HPUX_SYMDEF_COUNT_SIZE
9822159047fSniklas 		+ BSD_STRING_COUNT_SIZE);
9832159047fSniklas   rbase = (bfd_byte *) stringbase + stringsize;
984007c2a45Smiod   amt = ardata->symdef_count * BSD_SYMDEF_SIZE;
985007c2a45Smiod   ardata->symdefs = bfd_alloc (abfd, amt);
9862159047fSniklas   if (!ardata->symdefs)
987c074d1c9Sdrahn     return FALSE;
9882159047fSniklas 
9892159047fSniklas   for (counter = 0, set = ardata->symdefs;
9902159047fSniklas        counter < ardata->symdef_count;
9912159047fSniklas        counter++, set++, rbase += BSD_SYMDEF_SIZE)
9922159047fSniklas     {
993c074d1c9Sdrahn       set->name = H_GET_32 (abfd, rbase) + stringbase;
994c074d1c9Sdrahn       set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
9952159047fSniklas     }
9962159047fSniklas 
9972159047fSniklas   ardata->first_file_filepos = bfd_tell (abfd);
998b55d4692Sfgsch   /* Pad to an even boundary if you have to.  */
9992159047fSniklas   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
10002159047fSniklas   /* FIXME, we should provide some way to free raw_ardata when
10012159047fSniklas      we are done using the strings from it.  For now, it seems
1002b305b0f1Sespie      to be allocated on an objalloc anyway...  */
1003c074d1c9Sdrahn   bfd_has_map (abfd) = TRUE;
1004c074d1c9Sdrahn   return TRUE;
10052159047fSniklas }
10062159047fSniklas 
10072159047fSniklas /** Extended name table.
10082159047fSniklas 
10092159047fSniklas   Normally archives support only 14-character filenames.
10102159047fSniklas 
10112159047fSniklas   Intel has extended the format: longer names are stored in a special
10122159047fSniklas   element (the first in the archive, or second if there is an armap);
10132159047fSniklas   the name in the ar_hdr is replaced by <space><index into filename
10142159047fSniklas   element>.  Index is the P.R. of an int (decimal).  Data General have
1015b55d4692Sfgsch   extended the format by using the prefix // for the special element.  */
10162159047fSniklas 
1017c074d1c9Sdrahn /* Returns FALSE on error, TRUE otherwise.  */
1018b55d4692Sfgsch 
1019c074d1c9Sdrahn bfd_boolean
_bfd_slurp_extended_name_table(bfd * abfd)1020007c2a45Smiod _bfd_slurp_extended_name_table (bfd *abfd)
10212159047fSniklas {
10222159047fSniklas   char nextname[17];
10232159047fSniklas   struct areltdata *namedata;
1024c074d1c9Sdrahn   bfd_size_type amt;
10252159047fSniklas 
10262159047fSniklas   /* FIXME:  Formatting sucks here, and in case of failure of BFD_READ,
1027c074d1c9Sdrahn      we probably don't want to return TRUE.  */
10282159047fSniklas   bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET);
1029007c2a45Smiod   if (bfd_bread (nextname, 16, abfd) == 16)
10302159047fSniklas     {
10312159047fSniklas       if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
1032c074d1c9Sdrahn 	return FALSE;
10332159047fSniklas 
10342159047fSniklas       if (strncmp (nextname, "ARFILENAMES/    ", 16) != 0 &&
10352159047fSniklas 	  strncmp (nextname, "//              ", 16) != 0)
10362159047fSniklas 	{
10372159047fSniklas 	  bfd_ardata (abfd)->extended_names = NULL;
1038c074d1c9Sdrahn 	  return TRUE;
10392159047fSniklas 	}
10402159047fSniklas 
1041007c2a45Smiod       namedata = _bfd_read_ar_hdr (abfd);
10422159047fSniklas       if (namedata == NULL)
1043c074d1c9Sdrahn 	return FALSE;
10442159047fSniklas 
1045c074d1c9Sdrahn       amt = namedata->parsed_size;
1046c074d1c9Sdrahn       bfd_ardata (abfd)->extended_names = bfd_zalloc (abfd, amt);
10472159047fSniklas       if (bfd_ardata (abfd)->extended_names == NULL)
10482159047fSniklas 	{
10492159047fSniklas 	byebye:
1050007c2a45Smiod 	  bfd_release (abfd, namedata);
1051c074d1c9Sdrahn 	  return FALSE;
10522159047fSniklas 	}
10532159047fSniklas 
1054007c2a45Smiod       if (bfd_bread (bfd_ardata (abfd)->extended_names, amt, abfd) != amt)
10552159047fSniklas 	{
10562159047fSniklas 	  if (bfd_get_error () != bfd_error_system_call)
10572159047fSniklas 	    bfd_set_error (bfd_error_malformed_archive);
1058007c2a45Smiod 	  bfd_release (abfd, (bfd_ardata (abfd)->extended_names));
10592159047fSniklas 	  bfd_ardata (abfd)->extended_names = NULL;
10602159047fSniklas 	  goto byebye;
10612159047fSniklas 	}
10622159047fSniklas 
10632159047fSniklas       /* Since the archive is supposed to be printable if it contains
10642159047fSniklas 	 text, the entries in the list are newline-padded, not null
10652159047fSniklas 	 padded. In SVR4-style archives, the names also have a
10662159047fSniklas 	 trailing '/'.  DOS/NT created archive often have \ in them
10672159047fSniklas 	 We'll fix all problems here..  */
10682159047fSniklas       {
10692159047fSniklas 	char *temp = bfd_ardata (abfd)->extended_names;
10702159047fSniklas 	char *limit = temp + namedata->parsed_size;
1071b55d4692Sfgsch 	for (; temp < limit; ++temp)
1072b55d4692Sfgsch 	  {
10732159047fSniklas 	    if (*temp == '\012')
10742159047fSniklas 	      temp[temp[-1] == '/' ? -1 : 0] = '\0';
10752159047fSniklas 	    if (*temp == '\\')
10762159047fSniklas 	      *temp = '/';
10772159047fSniklas 	  }
10782159047fSniklas       }
10792159047fSniklas 
1080b55d4692Sfgsch       /* Pad to an even boundary if you have to.  */
10812159047fSniklas       bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
10822159047fSniklas       bfd_ardata (abfd)->first_file_filepos +=
10832159047fSniklas 	(bfd_ardata (abfd)->first_file_filepos) % 2;
10842159047fSniklas 
10852159047fSniklas       /* FIXME, we can't release namedata here because it was allocated
1086b305b0f1Sespie 	 below extended_names on the objalloc...  */
1087b55d4692Sfgsch #if 0
1088b55d4692Sfgsch       bfd_release (abfd, namedata);
1089b55d4692Sfgsch #endif
10902159047fSniklas     }
1091c074d1c9Sdrahn   return TRUE;
10922159047fSniklas }
10932159047fSniklas 
10942159047fSniklas #ifdef VMS
10952159047fSniklas 
10962159047fSniklas /* Return a copy of the stuff in the filename between any :]> and a
1097b55d4692Sfgsch    semicolon.  */
1098b55d4692Sfgsch 
10992159047fSniklas static const char *
normalize(bfd * abfd,const char * file)1100007c2a45Smiod normalize (bfd *abfd, const char *file)
11012159047fSniklas {
1102c074d1c9Sdrahn   const char *first;
1103c074d1c9Sdrahn   const char *last;
11042159047fSniklas   char *copy;
11052159047fSniklas 
11062159047fSniklas   first = file + strlen (file) - 1;
11072159047fSniklas   last = first + 1;
11082159047fSniklas 
11092159047fSniklas   while (first != file)
11102159047fSniklas     {
11112159047fSniklas       if (*first == ';')
11122159047fSniklas 	last = first;
11132159047fSniklas       if (*first == ':' || *first == ']' || *first == '>')
11142159047fSniklas 	{
11152159047fSniklas 	  first++;
11162159047fSniklas 	  break;
11172159047fSniklas 	}
11182159047fSniklas       first--;
11192159047fSniklas     }
11202159047fSniklas 
1121007c2a45Smiod   copy = bfd_alloc (abfd, last - first + 1);
11222159047fSniklas   if (copy == NULL)
11232159047fSniklas     return NULL;
11242159047fSniklas 
11252159047fSniklas   memcpy (copy, first, last - first);
11262159047fSniklas   copy[last - first] = 0;
11272159047fSniklas 
11282159047fSniklas   return copy;
11292159047fSniklas }
11302159047fSniklas 
11312159047fSniklas #else
11322159047fSniklas static const char *
normalize(bfd * abfd ATTRIBUTE_UNUSED,const char * file)1133007c2a45Smiod normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
11342159047fSniklas {
11352159047fSniklas   const char *filename = strrchr (file, '/');
11362159047fSniklas 
1137b305b0f1Sespie #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1138b305b0f1Sespie   {
1139b305b0f1Sespie     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
1140b305b0f1Sespie     char *bslash = strrchr (file, '\\');
1141b55d4692Sfgsch     if (filename == NULL || (bslash != NULL && bslash > filename))
1142b305b0f1Sespie       filename = bslash;
1143b305b0f1Sespie     if (filename == NULL && file[0] != '\0' && file[1] == ':')
1144b305b0f1Sespie       filename = file + 1;
1145b305b0f1Sespie   }
1146b305b0f1Sespie #endif
1147007c2a45Smiod   if (filename != NULL)
11482159047fSniklas     filename++;
11492159047fSniklas   else
11502159047fSniklas     filename = file;
11512159047fSniklas   return filename;
11522159047fSniklas }
11532159047fSniklas #endif
11542159047fSniklas 
11552159047fSniklas /* Build a BFD style extended name table.  */
11562159047fSniklas 
1157c074d1c9Sdrahn bfd_boolean
_bfd_archive_bsd_construct_extended_name_table(bfd * abfd,char ** tabloc,bfd_size_type * tablen,const char ** name)1158007c2a45Smiod _bfd_archive_bsd_construct_extended_name_table (bfd *abfd,
1159007c2a45Smiod 						char **tabloc,
1160007c2a45Smiod 						bfd_size_type *tablen,
1161007c2a45Smiod 						const char **name)
11622159047fSniklas {
11632159047fSniklas   *name = "ARFILENAMES/";
1164c074d1c9Sdrahn   return _bfd_construct_extended_name_table (abfd, FALSE, tabloc, tablen);
11652159047fSniklas }
11662159047fSniklas 
11672159047fSniklas /* Build an SVR4 style extended name table.  */
11682159047fSniklas 
1169c074d1c9Sdrahn bfd_boolean
_bfd_archive_coff_construct_extended_name_table(bfd * abfd,char ** tabloc,bfd_size_type * tablen,const char ** name)1170007c2a45Smiod _bfd_archive_coff_construct_extended_name_table (bfd *abfd,
1171007c2a45Smiod 						 char **tabloc,
1172007c2a45Smiod 						 bfd_size_type *tablen,
1173007c2a45Smiod 						 const char **name)
11742159047fSniklas {
11752159047fSniklas   *name = "//";
1176c074d1c9Sdrahn   return _bfd_construct_extended_name_table (abfd, TRUE, tabloc, tablen);
11772159047fSniklas }
11782159047fSniklas 
11792159047fSniklas /* Follows archive_head and produces an extended name table if
11802159047fSniklas    necessary.  Returns (in tabloc) a pointer to an extended name
11812159047fSniklas    table, and in tablen the length of the table.  If it makes an entry
11822159047fSniklas    it clobbers the filename so that the element may be written without
1183c074d1c9Sdrahn    further massage.  Returns TRUE if it ran successfully, FALSE if
11842159047fSniklas    something went wrong.  A successful return may still involve a
11852159047fSniklas    zero-length tablen!  */
11862159047fSniklas 
1187c074d1c9Sdrahn bfd_boolean
_bfd_construct_extended_name_table(bfd * abfd,bfd_boolean trailing_slash,char ** tabloc,bfd_size_type * tablen)1188007c2a45Smiod _bfd_construct_extended_name_table (bfd *abfd,
1189007c2a45Smiod 				    bfd_boolean trailing_slash,
1190007c2a45Smiod 				    char **tabloc,
1191007c2a45Smiod 				    bfd_size_type *tablen)
11922159047fSniklas {
11932159047fSniklas   unsigned int maxname = abfd->xvec->ar_max_namelen;
1194c074d1c9Sdrahn   bfd_size_type total_namelen = 0;
11952159047fSniklas   bfd *current;
11962159047fSniklas   char *strptr;
11972159047fSniklas 
11982159047fSniklas   *tablen = 0;
11992159047fSniklas 
1200b55d4692Sfgsch   /* Figure out how long the table should be.  */
12012159047fSniklas   for (current = abfd->archive_head; current != NULL; current = current->next)
12022159047fSniklas     {
12032159047fSniklas       const char *normal;
12042159047fSniklas       unsigned int thislen;
12052159047fSniklas 
12062159047fSniklas       normal = normalize (current, current->filename);
12072159047fSniklas       if (normal == NULL)
1208c074d1c9Sdrahn 	return FALSE;
12092159047fSniklas 
12102159047fSniklas       thislen = strlen (normal);
12112159047fSniklas 
12122159047fSniklas       if (thislen > maxname
12132159047fSniklas 	  && (bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
12142159047fSniklas 	thislen = maxname;
12152159047fSniklas 
12162159047fSniklas       if (thislen > maxname)
12172159047fSniklas 	{
12182159047fSniklas 	  /* Add one to leave room for \n.  */
12192159047fSniklas 	  total_namelen += thislen + 1;
12202159047fSniklas 	  if (trailing_slash)
12212159047fSniklas 	    {
12222159047fSniklas 	      /* Leave room for trailing slash.  */
12232159047fSniklas 	      ++total_namelen;
12242159047fSniklas 	    }
12252159047fSniklas 	}
12262159047fSniklas       else
12272159047fSniklas 	{
12282159047fSniklas 	  struct ar_hdr *hdr = arch_hdr (current);
12292159047fSniklas 	  if (strncmp (normal, hdr->ar_name, thislen) != 0
12302159047fSniklas 	      || (thislen < sizeof hdr->ar_name
12312159047fSniklas 		  && hdr->ar_name[thislen] != ar_padchar (current)))
12322159047fSniklas 	    {
12332159047fSniklas 	      /* Must have been using extended format even though it
12342159047fSniklas 	         didn't need to.  Fix it to use normal format.  */
12352159047fSniklas 	      memcpy (hdr->ar_name, normal, thislen);
12362159047fSniklas 	      if (thislen < maxname
12372159047fSniklas 		  || (thislen == maxname && thislen < sizeof hdr->ar_name))
12382159047fSniklas 		hdr->ar_name[thislen] = ar_padchar (current);
12392159047fSniklas 	    }
12402159047fSniklas 	}
12412159047fSniklas     }
12422159047fSniklas 
12432159047fSniklas   if (total_namelen == 0)
1244c074d1c9Sdrahn     return TRUE;
12452159047fSniklas 
12462159047fSniklas   *tabloc = bfd_zalloc (abfd, total_namelen);
12472159047fSniklas   if (*tabloc == NULL)
1248c074d1c9Sdrahn     return FALSE;
12492159047fSniklas 
12502159047fSniklas   *tablen = total_namelen;
12512159047fSniklas   strptr = *tabloc;
12522159047fSniklas 
12532159047fSniklas   for (current = abfd->archive_head; current != NULL; current =
12542159047fSniklas        current->next)
12552159047fSniklas     {
12562159047fSniklas       const char *normal;
12572159047fSniklas       unsigned int thislen;
12582159047fSniklas 
12592159047fSniklas       normal = normalize (current, current->filename);
12602159047fSniklas       if (normal == NULL)
1261c074d1c9Sdrahn 	return FALSE;
12622159047fSniklas 
12632159047fSniklas       thislen = strlen (normal);
12642159047fSniklas       if (thislen > maxname)
12652159047fSniklas 	{
12662159047fSniklas 	  /* Works for now; may need to be re-engineered if we
12672159047fSniklas 	     encounter an oddball archive format and want to
12682159047fSniklas 	     generalise this hack.  */
12692159047fSniklas 	  struct ar_hdr *hdr = arch_hdr (current);
12702159047fSniklas 	  strcpy (strptr, normal);
12712159047fSniklas 	  if (! trailing_slash)
12722159047fSniklas 	    strptr[thislen] = '\012';
12732159047fSniklas 	  else
12742159047fSniklas 	    {
12752159047fSniklas 	      strptr[thislen] = '/';
12762159047fSniklas 	      strptr[thislen + 1] = '\012';
12772159047fSniklas 	    }
12782159047fSniklas 	  hdr->ar_name[0] = ar_padchar (current);
12792159047fSniklas 	  /* We know there will always be enough room (one of the few
12802159047fSniklas 	     cases where you may safely use sprintf).  */
12812159047fSniklas 	  sprintf ((hdr->ar_name) + 1, "%-d", (unsigned) (strptr - *tabloc));
12822159047fSniklas 	  /* Kinda Kludgy.  We should just use the returned value of
1283b55d4692Sfgsch 	     sprintf but not all implementations get this right.  */
12842159047fSniklas 	  {
12852159047fSniklas 	    char *temp = hdr->ar_name + 2;
12862159047fSniklas 	    for (; temp < hdr->ar_name + maxname; temp++)
12872159047fSniklas 	      if (*temp == '\0')
12882159047fSniklas 		*temp = ' ';
12892159047fSniklas 	  }
12902159047fSniklas 	  strptr += thislen + 1;
12912159047fSniklas 	  if (trailing_slash)
12922159047fSniklas 	    ++strptr;
12932159047fSniklas 	}
12942159047fSniklas     }
12952159047fSniklas 
1296c074d1c9Sdrahn   return TRUE;
12972159047fSniklas }
12982159047fSniklas 
12992159047fSniklas /** A couple of functions for creating ar_hdrs */
13002159047fSniklas 
1301b55d4692Sfgsch #ifdef HPUX_LARGE_AR_IDS
1302b55d4692Sfgsch /* Function to encode large UID/GID values according to HP.  */
1303b55d4692Sfgsch 
1304b55d4692Sfgsch static void
hpux_uid_gid_encode(char str[6],long int id)1305007c2a45Smiod hpux_uid_gid_encode (char str[6], long int id)
1306b55d4692Sfgsch {
1307b55d4692Sfgsch   int cnt;
1308b55d4692Sfgsch 
1309b55d4692Sfgsch   str[5] = '@' + (id & 3);
1310b55d4692Sfgsch   id >>= 2;
1311b55d4692Sfgsch 
1312b55d4692Sfgsch   for (cnt = 4; cnt >= 0; ++cnt, id >>= 6)
1313b55d4692Sfgsch     str[cnt] = ' ' + (id & 0x3f);
1314b55d4692Sfgsch }
1315b55d4692Sfgsch #endif	/* HPUX_LARGE_AR_IDS */
1316b55d4692Sfgsch 
1317b305b0f1Sespie #ifndef HAVE_GETUID
1318b305b0f1Sespie #define getuid() 0
1319b305b0f1Sespie #endif
1320b305b0f1Sespie 
1321b305b0f1Sespie #ifndef HAVE_GETGID
1322b305b0f1Sespie #define getgid() 0
1323b305b0f1Sespie #endif
1324b305b0f1Sespie 
13252159047fSniklas /* Takes a filename, returns an arelt_data for it, or NULL if it can't
13262159047fSniklas    make one.  The filename must refer to a filename in the filesystem.
1327b305b0f1Sespie    The filename field of the ar_hdr will NOT be initialized.  If member
1328b305b0f1Sespie    is set, and it's an in-memory bfd, we fake it.  */
13292159047fSniklas 
13302159047fSniklas static struct areltdata *
bfd_ar_hdr_from_filesystem(bfd * abfd,const char * filename,bfd * member)1331007c2a45Smiod bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member)
13322159047fSniklas {
13332159047fSniklas   struct stat status;
13342159047fSniklas   struct areltdata *ared;
13352159047fSniklas   struct ar_hdr *hdr;
13362159047fSniklas   char *temp, *temp1;
1337c074d1c9Sdrahn   bfd_size_type amt;
13382159047fSniklas 
1339b305b0f1Sespie   if (member && (member->flags & BFD_IN_MEMORY) != 0)
1340b305b0f1Sespie     {
1341b55d4692Sfgsch       /* Assume we just "made" the member, and fake it.  */
1342007c2a45Smiod       struct bfd_in_memory *bim = member->iostream;
1343b305b0f1Sespie       time (&status.st_mtime);
1344b305b0f1Sespie       status.st_uid = getuid ();
1345b305b0f1Sespie       status.st_gid = getgid ();
1346b305b0f1Sespie       status.st_mode = 0644;
1347b305b0f1Sespie       status.st_size = bim->size;
1348b305b0f1Sespie     }
1349b305b0f1Sespie   else if (stat (filename, &status) != 0)
13502159047fSniklas     {
13512159047fSniklas       bfd_set_error (bfd_error_system_call);
13522159047fSniklas       return NULL;
13532159047fSniklas     }
13542159047fSniklas 
1355c074d1c9Sdrahn   amt = sizeof (struct ar_hdr) + sizeof (struct areltdata);
1356007c2a45Smiod   ared = bfd_zalloc (abfd, amt);
13572159047fSniklas   if (ared == NULL)
13582159047fSniklas     return NULL;
13592159047fSniklas   hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
13602159047fSniklas 
13612159047fSniklas   /* ar headers are space padded, not null padded!  */
1362007c2a45Smiod   memset (hdr, ' ', sizeof (struct ar_hdr));
13632159047fSniklas 
13642159047fSniklas   strncpy (hdr->ar_fmag, ARFMAG, 2);
13652159047fSniklas 
1366b55d4692Sfgsch   /* Goddamned sprintf doesn't permit MAXIMUM field lengths.  */
1367d04417c8Smiod   sprintf ((hdr->ar_date), "%-12lld", (long long) status.st_mtime);
1368b55d4692Sfgsch #ifdef HPUX_LARGE_AR_IDS
1369b55d4692Sfgsch   /* HP has a very "special" way to handle UID/GID's with numeric values
1370b55d4692Sfgsch      > 99999.  */
1371b55d4692Sfgsch   if (status.st_uid > 99999)
1372b55d4692Sfgsch     hpux_uid_gid_encode (hdr->ar_gid, (long) status.st_uid);
1373b55d4692Sfgsch   else
1374b55d4692Sfgsch #endif
13752159047fSniklas     sprintf ((hdr->ar_uid), "%ld", (long) status.st_uid);
1376b55d4692Sfgsch #ifdef HPUX_LARGE_AR_IDS
1377b55d4692Sfgsch   /* HP has a very "special" way to handle UID/GID's with numeric values
1378b55d4692Sfgsch      > 99999.  */
1379b55d4692Sfgsch   if (status.st_gid > 99999)
1380b55d4692Sfgsch     hpux_uid_gid_encode (hdr->ar_uid, (long) status.st_gid);
1381b55d4692Sfgsch   else
1382b55d4692Sfgsch #endif
13832159047fSniklas   sprintf ((hdr->ar_gid), "%ld", (long) status.st_gid);
13842159047fSniklas   sprintf ((hdr->ar_mode), "%-8o", (unsigned int) status.st_mode);
13852159047fSniklas   sprintf ((hdr->ar_size), "%-10ld", (long) status.st_size);
13862159047fSniklas   /* Correct for a lossage in sprintf whereby it null-terminates.  I cannot
13872159047fSniklas      understand how these C losers could design such a ramshackle bunch of
1388b55d4692Sfgsch      IO operations.  */
13892159047fSniklas   temp = (char *) hdr;
13902159047fSniklas   temp1 = temp + sizeof (struct ar_hdr) - 2;
13912159047fSniklas   for (; temp < temp1; temp++)
13922159047fSniklas     {
13932159047fSniklas       if (*temp == '\0')
13942159047fSniklas 	*temp = ' ';
13952159047fSniklas     }
13962159047fSniklas   strncpy (hdr->ar_fmag, ARFMAG, 2);
13972159047fSniklas   ared->parsed_size = status.st_size;
13982159047fSniklas   ared->arch_header = (char *) hdr;
13992159047fSniklas 
14002159047fSniklas   return ared;
14012159047fSniklas }
14022159047fSniklas 
14032159047fSniklas /* This is magic required by the "ar" program.  Since it's
14042159047fSniklas    undocumented, it's undocumented.  You may think that it would take
14052159047fSniklas    a strong stomach to write this, and it does, but it takes even a
14062159047fSniklas    stronger stomach to try to code around such a thing!  */
14072159047fSniklas 
1408007c2a45Smiod struct ar_hdr *bfd_special_undocumented_glue (bfd *, const char *);
1409b305b0f1Sespie 
14102159047fSniklas struct ar_hdr *
bfd_special_undocumented_glue(bfd * abfd,const char * filename)1411007c2a45Smiod bfd_special_undocumented_glue (bfd *abfd, const char *filename)
14122159047fSniklas {
1413b305b0f1Sespie   struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename, 0);
14142159047fSniklas   if (ar_elt == NULL)
14152159047fSniklas     return NULL;
14162159047fSniklas   return (struct ar_hdr *) ar_elt->arch_header;
14172159047fSniklas }
14182159047fSniklas 
1419b55d4692Sfgsch /* Analogous to stat call.  */
14202159047fSniklas 
14212159047fSniklas int
bfd_generic_stat_arch_elt(bfd * abfd,struct stat * buf)1422007c2a45Smiod bfd_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
14232159047fSniklas {
14242159047fSniklas   struct ar_hdr *hdr;
14252159047fSniklas   char *aloser;
14262159047fSniklas 
14272159047fSniklas   if (abfd->arelt_data == NULL)
14282159047fSniklas     {
14292159047fSniklas       bfd_set_error (bfd_error_invalid_operation);
14302159047fSniklas       return -1;
14312159047fSniklas     }
14322159047fSniklas 
14332159047fSniklas   hdr = arch_hdr (abfd);
14342159047fSniklas 
14352159047fSniklas #define foo(arelt, stelt, size)				\
14362159047fSniklas   buf->stelt = strtol (hdr->arelt, &aloser, size);	\
1437b55d4692Sfgsch   if (aloser == hdr->arelt)	      			\
1438b55d4692Sfgsch     return -1;
1439b55d4692Sfgsch 
1440d04417c8Smiod #define fooll(arelt, stelt, size)			\
1441d04417c8Smiod   buf->stelt = strtoll (hdr->arelt, &aloser, size);	\
1442d04417c8Smiod   if (aloser == hdr->arelt)	      			\
1443d04417c8Smiod     return -1;
1444d04417c8Smiod 
1445b55d4692Sfgsch   /* Some platforms support special notations for large IDs.  */
1446b55d4692Sfgsch #ifdef HPUX_LARGE_AR_IDS
1447b55d4692Sfgsch # define foo2(arelt, stelt, size)					\
1448b55d4692Sfgsch   if (hdr->arelt[5] == ' ')						\
1449b55d4692Sfgsch     {									\
1450b55d4692Sfgsch       foo (arelt, stelt, size);						\
1451b55d4692Sfgsch     }									\
1452b55d4692Sfgsch   else									\
1453b55d4692Sfgsch     {									\
1454b55d4692Sfgsch       int cnt;								\
1455b55d4692Sfgsch       for (buf->stelt = cnt = 0; cnt < 5; ++cnt)			\
1456b55d4692Sfgsch 	{								\
1457b55d4692Sfgsch 	  if (hdr->arelt[cnt] < ' ' || hdr->arelt[cnt] > ' ' + 0x3f)	\
1458b55d4692Sfgsch 	    return -1;							\
1459b55d4692Sfgsch 	  buf->stelt <<= 6;						\
1460b55d4692Sfgsch 	  buf->stelt += hdr->arelt[cnt] - ' ';				\
1461b55d4692Sfgsch 	}								\
1462b55d4692Sfgsch       if (hdr->arelt[5] < '@' || hdr->arelt[5] > '@' + 3)		\
1463b55d4692Sfgsch 	return -1;							\
1464b55d4692Sfgsch       buf->stelt <<= 2;							\
1465b55d4692Sfgsch       buf->stelt += hdr->arelt[5] - '@';				\
1466b55d4692Sfgsch     }
1467b55d4692Sfgsch #else
1468b55d4692Sfgsch # define foo2(arelt, stelt, size) foo (arelt, stelt, size)
1469b55d4692Sfgsch #endif
14702159047fSniklas 
1471d04417c8Smiod   fooll (ar_date, st_mtime, 10);
1472b55d4692Sfgsch   foo2 (ar_uid, st_uid, 10);
1473b55d4692Sfgsch   foo2 (ar_gid, st_gid, 10);
14742159047fSniklas   foo (ar_mode, st_mode, 8);
14752159047fSniklas 
14762159047fSniklas   buf->st_size = arch_eltdata (abfd)->parsed_size;
14772159047fSniklas 
14782159047fSniklas   return 0;
14792159047fSniklas }
14802159047fSniklas 
14812159047fSniklas void
bfd_dont_truncate_arname(bfd * abfd,const char * pathname,char * arhdr)1482007c2a45Smiod bfd_dont_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
14832159047fSniklas {
14842159047fSniklas   /* FIXME: This interacts unpleasantly with ar's quick-append option.
14852159047fSniklas      Fortunately ic960 users will never use that option.  Fixing this
14862159047fSniklas      is very hard; fortunately I know how to do it and will do so once
14872159047fSniklas      intel's release is out the door.  */
14882159047fSniklas 
14892159047fSniklas   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
14902159047fSniklas   size_t length;
14912159047fSniklas   const char *filename;
14922159047fSniklas   size_t maxlen = ar_maxnamelen (abfd);
14932159047fSniklas 
14942159047fSniklas   if ((bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
14952159047fSniklas     {
14962159047fSniklas       bfd_bsd_truncate_arname (abfd, pathname, arhdr);
14972159047fSniklas       return;
14982159047fSniklas     }
14992159047fSniklas 
15002159047fSniklas   filename = normalize (abfd, pathname);
15012159047fSniklas   if (filename == NULL)
15022159047fSniklas     {
15032159047fSniklas       /* FIXME */
15042159047fSniklas       abort ();
15052159047fSniklas     }
15062159047fSniklas 
15072159047fSniklas   length = strlen (filename);
15082159047fSniklas 
15092159047fSniklas   if (length <= maxlen)
15102159047fSniklas     memcpy (hdr->ar_name, filename, length);
15112159047fSniklas 
15122159047fSniklas   /* Add the padding character if there is room for it.  */
15132159047fSniklas   if (length < maxlen
15142159047fSniklas       || (length == maxlen && length < sizeof hdr->ar_name))
15152159047fSniklas     (hdr->ar_name)[length] = ar_padchar (abfd);
15162159047fSniklas }
15172159047fSniklas 
15182159047fSniklas void
bfd_bsd_truncate_arname(bfd * abfd,const char * pathname,char * arhdr)1519007c2a45Smiod bfd_bsd_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
15202159047fSniklas {
15212159047fSniklas   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
1522c074d1c9Sdrahn   size_t length;
1523c074d1c9Sdrahn   const char *filename = strrchr (pathname, '/');
1524c074d1c9Sdrahn   size_t maxlen = ar_maxnamelen (abfd);
15252159047fSniklas 
1526b305b0f1Sespie #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1527b305b0f1Sespie   {
1528b305b0f1Sespie     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
1529b305b0f1Sespie     char *bslash = strrchr (pathname, '\\');
1530b55d4692Sfgsch     if (filename == NULL || (bslash != NULL && bslash > filename))
1531b305b0f1Sespie       filename = bslash;
1532b305b0f1Sespie     if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':')
1533b305b0f1Sespie       filename = pathname + 1;
1534b305b0f1Sespie   }
1535b305b0f1Sespie #endif
1536b305b0f1Sespie 
15372159047fSniklas   if (filename == NULL)
15382159047fSniklas     filename = pathname;
15392159047fSniklas   else
15402159047fSniklas     ++filename;
15412159047fSniklas 
15422159047fSniklas   length = strlen (filename);
15432159047fSniklas 
15442159047fSniklas   if (length <= maxlen)
15452159047fSniklas     memcpy (hdr->ar_name, filename, length);
15462159047fSniklas   else
15472159047fSniklas     {
15482159047fSniklas       /* pathname: meet procrustes */
15492159047fSniklas       memcpy (hdr->ar_name, filename, maxlen);
15502159047fSniklas       length = maxlen;
15512159047fSniklas     }
15522159047fSniklas 
15532159047fSniklas   if (length < maxlen)
15542159047fSniklas     (hdr->ar_name)[length] = ar_padchar (abfd);
15552159047fSniklas }
15562159047fSniklas 
15572159047fSniklas /* Store name into ar header.  Truncates the name to fit.
15582159047fSniklas    1> strip pathname to be just the basename.
15592159047fSniklas    2> if it's short enuf to fit, stuff it in.
15602159047fSniklas    3> If it doesn't end with .o, truncate it to fit
15612159047fSniklas    4> truncate it before the .o, append .o, stuff THAT in.  */
15622159047fSniklas 
15632159047fSniklas /* This is what gnu ar does.  It's better but incompatible with the
15642159047fSniklas    bsd ar.  */
15652159047fSniklas 
15662159047fSniklas void
bfd_gnu_truncate_arname(bfd * abfd,const char * pathname,char * arhdr)1567007c2a45Smiod bfd_gnu_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
15682159047fSniklas {
15692159047fSniklas   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
1570c074d1c9Sdrahn   size_t length;
1571c074d1c9Sdrahn   const char *filename = strrchr (pathname, '/');
1572c074d1c9Sdrahn   size_t maxlen = ar_maxnamelen (abfd);
15732159047fSniklas 
1574b305b0f1Sespie #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1575b305b0f1Sespie   {
1576b305b0f1Sespie     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
1577b305b0f1Sespie     char *bslash = strrchr (pathname, '\\');
1578b55d4692Sfgsch     if (filename == NULL || (bslash != NULL && bslash > filename))
1579b305b0f1Sespie       filename = bslash;
1580b305b0f1Sespie     if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':')
1581b305b0f1Sespie       filename = pathname + 1;
1582b305b0f1Sespie   }
1583b305b0f1Sespie #endif
1584b305b0f1Sespie 
15852159047fSniklas   if (filename == NULL)
15862159047fSniklas     filename = pathname;
15872159047fSniklas   else
15882159047fSniklas     ++filename;
15892159047fSniklas 
15902159047fSniklas   length = strlen (filename);
15912159047fSniklas 
15922159047fSniklas   if (length <= maxlen)
15932159047fSniklas     memcpy (hdr->ar_name, filename, length);
15942159047fSniklas   else
15952159047fSniklas     {				/* pathname: meet procrustes */
15962159047fSniklas       memcpy (hdr->ar_name, filename, maxlen);
15972159047fSniklas       if ((filename[length - 2] == '.') && (filename[length - 1] == 'o'))
15982159047fSniklas 	{
15992159047fSniklas 	  hdr->ar_name[maxlen - 2] = '.';
16002159047fSniklas 	  hdr->ar_name[maxlen - 1] = 'o';
16012159047fSniklas 	}
16022159047fSniklas       length = maxlen;
16032159047fSniklas     }
16042159047fSniklas 
16052159047fSniklas   if (length < 16)
16062159047fSniklas     (hdr->ar_name)[length] = ar_padchar (abfd);
16072159047fSniklas }
16082159047fSniklas 
1609b55d4692Sfgsch /* The BFD is open for write and has its format set to bfd_archive.  */
16102159047fSniklas 
1611c074d1c9Sdrahn bfd_boolean
_bfd_write_archive_contents(bfd * arch)1612007c2a45Smiod _bfd_write_archive_contents (bfd *arch)
16132159047fSniklas {
16142159047fSniklas   bfd *current;
16152159047fSniklas   char *etable = NULL;
16162159047fSniklas   bfd_size_type elength = 0;
16172159047fSniklas   const char *ename = NULL;
1618c074d1c9Sdrahn   bfd_boolean makemap = bfd_has_map (arch);
1619c074d1c9Sdrahn   /* If no .o's, don't bother to make a map.  */
1620c074d1c9Sdrahn   bfd_boolean hasobjects = FALSE;
16212159047fSniklas   bfd_size_type wrote;
16222159047fSniklas   unsigned int i;
16232159047fSniklas   int tries;
16242159047fSniklas 
16252159047fSniklas   /* Verify the viability of all entries; if any of them live in the
16262159047fSniklas      filesystem (as opposed to living in an archive open for input)
16272159047fSniklas      then construct a fresh ar_hdr for them.  */
16282159047fSniklas   for (current = arch->archive_head; current; current = current->next)
16292159047fSniklas     {
1630b55d4692Sfgsch       /* This check is checking the bfds for the objects we're reading
1631b55d4692Sfgsch 	 from (which are usually either an object file or archive on
1632b55d4692Sfgsch 	 disk), not the archive entries we're writing to.  We don't
1633b55d4692Sfgsch 	 actually create bfds for the archive members, we just copy
1634b55d4692Sfgsch 	 them byte-wise when we write out the archive.  */
16352159047fSniklas       if (bfd_write_p (current))
16362159047fSniklas 	{
16372159047fSniklas 	  bfd_set_error (bfd_error_invalid_operation);
1638c074d1c9Sdrahn 	  return FALSE;
16392159047fSniklas 	}
16402159047fSniklas       if (!current->arelt_data)
16412159047fSniklas 	{
16422159047fSniklas 	  current->arelt_data =
1643007c2a45Smiod 	    bfd_ar_hdr_from_filesystem (arch, current->filename, current);
16442159047fSniklas 	  if (!current->arelt_data)
1645c074d1c9Sdrahn 	    return FALSE;
16462159047fSniklas 
1647b55d4692Sfgsch 	  /* Put in the file name.  */
1648007c2a45Smiod 	  BFD_SEND (arch, _bfd_truncate_arname,
1649007c2a45Smiod 		    (arch, current->filename, (char *) arch_hdr (current)));
16502159047fSniklas 	}
16512159047fSniklas 
16522159047fSniklas       if (makemap && ! hasobjects)
1653b55d4692Sfgsch 	{			/* Don't bother if we won't make a map!  */
16542159047fSniklas 	  if ((bfd_check_format (current, bfd_object))
16552159047fSniklas #if 0				/* FIXME -- these are not set correctly */
16562159047fSniklas 	      && ((bfd_get_file_flags (current) & HAS_SYMS))
16572159047fSniklas #endif
16582159047fSniklas 	    )
1659c074d1c9Sdrahn 	    hasobjects = TRUE;
16602159047fSniklas 	}
16612159047fSniklas     }
16622159047fSniklas 
16632159047fSniklas   if (!BFD_SEND (arch, _bfd_construct_extended_name_table,
16642159047fSniklas 		 (arch, &etable, &elength, &ename)))
1665c074d1c9Sdrahn     return FALSE;
16662159047fSniklas 
16672159047fSniklas   if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0)
1668c074d1c9Sdrahn     return FALSE;
16692159047fSniklas #ifdef GNU960
1670007c2a45Smiod   wrote = bfd_bwrite (BFD_GNU960_ARMAG (arch), SARMAG, arch);
16712159047fSniklas #else
1672007c2a45Smiod   wrote = bfd_bwrite (ARMAG, SARMAG, arch);
16732159047fSniklas #endif
16742159047fSniklas   if (wrote != SARMAG)
1675c074d1c9Sdrahn     return FALSE;
16762159047fSniklas 
16772159047fSniklas   if (makemap && hasobjects)
16782159047fSniklas     {
1679c074d1c9Sdrahn       if (! _bfd_compute_and_write_armap (arch, (unsigned int) elength))
1680c074d1c9Sdrahn 	return FALSE;
16812159047fSniklas     }
16822159047fSniklas 
16832159047fSniklas   if (elength != 0)
16842159047fSniklas     {
16852159047fSniklas       struct ar_hdr hdr;
16862159047fSniklas 
1687007c2a45Smiod       memset (&hdr, 0, sizeof (struct ar_hdr));
16882159047fSniklas       strcpy (hdr.ar_name, ename);
16892159047fSniklas       /* Round size up to even number in archive header.  */
16902159047fSniklas       sprintf (&(hdr.ar_size[0]), "%-10d",
1691c074d1c9Sdrahn 	       (int) ((elength + 1) & ~(bfd_size_type) 1));
16922159047fSniklas       strncpy (hdr.ar_fmag, ARFMAG, 2);
16932159047fSniklas       for (i = 0; i < sizeof (struct ar_hdr); i++)
16942159047fSniklas 	if (((char *) (&hdr))[i] == '\0')
16952159047fSniklas 	  (((char *) (&hdr))[i]) = ' ';
1696007c2a45Smiod       if ((bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
16972159047fSniklas 	   != sizeof (struct ar_hdr))
1698c074d1c9Sdrahn 	  || bfd_bwrite (etable, elength, arch) != elength)
1699c074d1c9Sdrahn 	return FALSE;
17002159047fSniklas       if ((elength % 2) == 1)
17012159047fSniklas 	{
1702007c2a45Smiod 	  if (bfd_bwrite ("\012", 1, arch) != 1)
1703c074d1c9Sdrahn 	    return FALSE;
17042159047fSniklas 	}
17052159047fSniklas     }
17062159047fSniklas 
17072159047fSniklas   for (current = arch->archive_head; current; current = current->next)
17082159047fSniklas     {
17092159047fSniklas       char buffer[DEFAULT_BUFFERSIZE];
17102159047fSniklas       unsigned int remaining = arelt_size (current);
17112159047fSniklas       struct ar_hdr *hdr = arch_hdr (current);
17122159047fSniklas 
1713b55d4692Sfgsch       /* Write ar header.  */
1714007c2a45Smiod       if (bfd_bwrite (hdr, sizeof (*hdr), arch)
1715c074d1c9Sdrahn 	  != sizeof (*hdr))
1716c074d1c9Sdrahn 	return FALSE;
17172159047fSniklas       if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0)
1718c074d1c9Sdrahn 	return FALSE;
17192159047fSniklas       while (remaining)
17202159047fSniklas 	{
17212159047fSniklas 	  unsigned int amt = DEFAULT_BUFFERSIZE;
17222159047fSniklas 	  if (amt > remaining)
17232159047fSniklas 	    amt = remaining;
17242159047fSniklas 	  errno = 0;
1725007c2a45Smiod 	  if (bfd_bread (buffer, amt, current) != amt)
17262159047fSniklas 	    {
17272159047fSniklas 	      if (bfd_get_error () != bfd_error_system_call)
17282159047fSniklas 		bfd_set_error (bfd_error_malformed_archive);
1729c074d1c9Sdrahn 	      return FALSE;
17302159047fSniklas 	    }
1731007c2a45Smiod 	  if (bfd_bwrite (buffer, amt, arch) != amt)
1732c074d1c9Sdrahn 	    return FALSE;
17332159047fSniklas 	  remaining -= amt;
17342159047fSniklas 	}
17352159047fSniklas       if ((arelt_size (current) % 2) == 1)
17362159047fSniklas 	{
1737007c2a45Smiod 	  if (bfd_bwrite ("\012", 1, arch) != 1)
1738c074d1c9Sdrahn 	    return FALSE;
17392159047fSniklas 	}
17402159047fSniklas     }
17412159047fSniklas 
17422159047fSniklas   if (makemap && hasobjects)
17432159047fSniklas     {
17442159047fSniklas       /* Verify the timestamp in the archive file.  If it would not be
17452159047fSniklas 	 accepted by the linker, rewrite it until it would be.  If
17462159047fSniklas 	 anything odd happens, break out and just return.  (The
17472159047fSniklas 	 Berkeley linker checks the timestamp and refuses to read the
17482159047fSniklas 	 table-of-contents if it is >60 seconds less than the file's
17492159047fSniklas 	 modified-time.  That painful hack requires this painful hack.  */
17502159047fSniklas       tries = 1;
17512159047fSniklas       do
17522159047fSniklas 	{
17532159047fSniklas 	  if (bfd_update_armap_timestamp (arch))
17542159047fSniklas 	    break;
17552159047fSniklas 	  (*_bfd_error_handler)
1756b305b0f1Sespie 	    (_("Warning: writing archive was slow: rewriting timestamp\n"));
17572159047fSniklas 	}
17582159047fSniklas       while (++tries < 6);
17592159047fSniklas     }
17602159047fSniklas 
1761c074d1c9Sdrahn   return TRUE;
17622159047fSniklas }
17632159047fSniklas 
1764b55d4692Sfgsch /* Note that the namidx for the first symbol is 0.  */
17652159047fSniklas 
1766c074d1c9Sdrahn bfd_boolean
_bfd_compute_and_write_armap(bfd * arch,unsigned int elength)1767007c2a45Smiod _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
17682159047fSniklas {
17692159047fSniklas   char *first_name = NULL;
17702159047fSniklas   bfd *current;
17712159047fSniklas   file_ptr elt_no = 0;
17722159047fSniklas   struct orl *map = NULL;
1773c074d1c9Sdrahn   unsigned int orl_max = 1024;		/* fine initial default */
1774c074d1c9Sdrahn   unsigned int orl_count = 0;
17752159047fSniklas   int stridx = 0;		/* string index */
17762159047fSniklas   asymbol **syms = NULL;
17772159047fSniklas   long syms_max = 0;
1778c074d1c9Sdrahn   bfd_boolean ret;
1779c074d1c9Sdrahn   bfd_size_type amt;
17802159047fSniklas 
17812159047fSniklas   /* Dunno if this is the best place for this info...  */
17822159047fSniklas   if (elength != 0)
17832159047fSniklas     elength += sizeof (struct ar_hdr);
17842159047fSniklas   elength += elength % 2;
17852159047fSniklas 
1786007c2a45Smiod   amt = orl_max * sizeof (struct orl);
1787007c2a45Smiod   map = bfd_malloc (amt);
17882159047fSniklas   if (map == NULL)
1789c88b1d6cSniklas     goto error_return;
17902159047fSniklas 
1791b305b0f1Sespie   /* We put the symbol names on the arch objalloc, and then discard
17922159047fSniklas      them when done.  */
1793007c2a45Smiod   first_name = bfd_alloc (arch, 1);
17942159047fSniklas   if (first_name == NULL)
1795c88b1d6cSniklas     goto error_return;
17962159047fSniklas 
1797b55d4692Sfgsch   /* Drop all the files called __.SYMDEF, we're going to make our own.  */
17982159047fSniklas   while (arch->archive_head &&
17992159047fSniklas 	 strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
18002159047fSniklas     arch->archive_head = arch->archive_head->next;
18012159047fSniklas 
1802b55d4692Sfgsch   /* Map over each element.  */
18032159047fSniklas   for (current = arch->archive_head;
1804007c2a45Smiod        current != NULL;
18052159047fSniklas        current = current->next, elt_no++)
18062159047fSniklas     {
1807c074d1c9Sdrahn       if (bfd_check_format (current, bfd_object)
1808c074d1c9Sdrahn 	  && (bfd_get_file_flags (current) & HAS_SYMS) != 0)
18092159047fSniklas 	{
18102159047fSniklas 	  long storage;
18112159047fSniklas 	  long symcount;
18122159047fSniklas 	  long src_count;
18132159047fSniklas 
18142159047fSniklas 	  storage = bfd_get_symtab_upper_bound (current);
18152159047fSniklas 	  if (storage < 0)
18162159047fSniklas 	    goto error_return;
18172159047fSniklas 
18182159047fSniklas 	  if (storage != 0)
18192159047fSniklas 	    {
18202159047fSniklas 	      if (storage > syms_max)
18212159047fSniklas 		{
18222159047fSniklas 		  if (syms_max > 0)
18232159047fSniklas 		    free (syms);
18242159047fSniklas 		  syms_max = storage;
1825007c2a45Smiod 		  syms = bfd_malloc (syms_max);
18262159047fSniklas 		  if (syms == NULL)
1827c88b1d6cSniklas 		    goto error_return;
18282159047fSniklas 		}
18292159047fSniklas 	      symcount = bfd_canonicalize_symtab (current, syms);
18302159047fSniklas 	      if (symcount < 0)
18312159047fSniklas 		goto error_return;
18322159047fSniklas 
1833b55d4692Sfgsch 	      /* Now map over all the symbols, picking out the ones we
1834b55d4692Sfgsch                  want.  */
18352159047fSniklas 	      for (src_count = 0; src_count < symcount; src_count++)
18362159047fSniklas 		{
18372159047fSniklas 		  flagword flags = (syms[src_count])->flags;
18382159047fSniklas 		  asection *sec = syms[src_count]->section;
18392159047fSniklas 
18402159047fSniklas 		  if ((flags & BSF_GLOBAL ||
18412159047fSniklas 		       flags & BSF_WEAK ||
18422159047fSniklas 		       flags & BSF_INDIRECT ||
18432159047fSniklas 		       bfd_is_com_section (sec))
18442159047fSniklas 		      && ! bfd_is_und_section (sec))
18452159047fSniklas 		    {
1846c074d1c9Sdrahn 		      bfd_size_type namelen;
18472159047fSniklas 		      struct orl *new_map;
18482159047fSniklas 
1849b55d4692Sfgsch 		      /* This symbol will go into the archive header.  */
18502159047fSniklas 		      if (orl_count == orl_max)
18512159047fSniklas 			{
18522159047fSniklas 			  orl_max *= 2;
1853007c2a45Smiod 			  amt = orl_max * sizeof (struct orl);
1854007c2a45Smiod 			  new_map = bfd_realloc (map, amt);
1855007c2a45Smiod 			  if (new_map == NULL)
1856c88b1d6cSniklas 			    goto error_return;
18572159047fSniklas 
18582159047fSniklas 			  map = new_map;
18592159047fSniklas 			}
18602159047fSniklas 
18612159047fSniklas 		      namelen = strlen (syms[src_count]->name);
1862c074d1c9Sdrahn 		      amt = sizeof (char *);
1863007c2a45Smiod 		      map[orl_count].name = bfd_alloc (arch, amt);
18642159047fSniklas 		      if (map[orl_count].name == NULL)
1865c88b1d6cSniklas 			goto error_return;
18662159047fSniklas 		      *(map[orl_count].name) = bfd_alloc (arch, namelen + 1);
18672159047fSniklas 		      if (*(map[orl_count].name) == NULL)
1868c88b1d6cSniklas 			goto error_return;
18692159047fSniklas 		      strcpy (*(map[orl_count].name), syms[src_count]->name);
1870c074d1c9Sdrahn 		      map[orl_count].u.abfd = current;
1871c074d1c9Sdrahn 		      map[orl_count].namidx = stridx;
18722159047fSniklas 
18732159047fSniklas 		      stridx += namelen + 1;
18742159047fSniklas 		      ++orl_count;
18752159047fSniklas 		    }
18762159047fSniklas 		}
18772159047fSniklas 	    }
18782159047fSniklas 
18792159047fSniklas 	  /* Now ask the BFD to free up any cached information, so we
18802159047fSniklas 	     don't fill all of memory with symbol tables.  */
18812159047fSniklas 	  if (! bfd_free_cached_info (current))
18822159047fSniklas 	    goto error_return;
18832159047fSniklas 	}
18842159047fSniklas     }
18852159047fSniklas 
1886b55d4692Sfgsch   /* OK, now we have collected all the data, let's write them out.  */
18872159047fSniklas   ret = BFD_SEND (arch, write_armap,
18882159047fSniklas 		  (arch, elength, map, orl_count, stridx));
18892159047fSniklas 
18902159047fSniklas   if (syms_max > 0)
18912159047fSniklas     free (syms);
18922159047fSniklas   if (map != NULL)
18932159047fSniklas     free (map);
18942159047fSniklas   if (first_name != NULL)
18952159047fSniklas     bfd_release (arch, first_name);
18962159047fSniklas 
18972159047fSniklas   return ret;
18982159047fSniklas 
18992159047fSniklas  error_return:
19002159047fSniklas   if (syms_max > 0)
19012159047fSniklas     free (syms);
19022159047fSniklas   if (map != NULL)
19032159047fSniklas     free (map);
19042159047fSniklas   if (first_name != NULL)
19052159047fSniklas     bfd_release (arch, first_name);
19062159047fSniklas 
1907c074d1c9Sdrahn   return FALSE;
19082159047fSniklas }
19092159047fSniklas 
1910c074d1c9Sdrahn bfd_boolean
bsd_write_armap(bfd * arch,unsigned int elength,struct orl * map,unsigned int orl_count,int stridx)1911007c2a45Smiod bsd_write_armap (bfd *arch,
1912007c2a45Smiod 		 unsigned int elength,
1913007c2a45Smiod 		 struct orl *map,
1914007c2a45Smiod 		 unsigned int orl_count,
1915007c2a45Smiod 		 int stridx)
19162159047fSniklas {
19172159047fSniklas   int padit = stridx & 1;
19182159047fSniklas   unsigned int ranlibsize = orl_count * BSD_SYMDEF_SIZE;
19192159047fSniklas   unsigned int stringsize = stridx + padit;
19202159047fSniklas   /* Include 8 bytes to store ranlibsize and stringsize in output.  */
19212159047fSniklas   unsigned int mapsize = ranlibsize + stringsize + 8;
19222159047fSniklas   file_ptr firstreal;
19232159047fSniklas   bfd *current = arch->archive_head;
19242159047fSniklas   bfd *last_elt = current;	/* last element arch seen */
19252159047fSniklas   bfd_byte temp[4];
19262159047fSniklas   unsigned int count;
19272159047fSniklas   struct ar_hdr hdr;
19282159047fSniklas   struct stat statbuf;
19292159047fSniklas   unsigned int i;
19302159047fSniklas 
19312159047fSniklas   firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
19322159047fSniklas 
19332159047fSniklas   stat (arch->filename, &statbuf);
1934007c2a45Smiod   memset (&hdr, 0, sizeof (struct ar_hdr));
19352159047fSniklas   sprintf (hdr.ar_name, RANLIBMAG);
19362159047fSniklas   /* Remember the timestamp, to keep it holy.  But fudge it a little.  */
19372159047fSniklas   bfd_ardata (arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET;
19382159047fSniklas   bfd_ardata (arch)->armap_datepos = (SARMAG
19392159047fSniklas 				      + offsetof (struct ar_hdr, ar_date[0]));
1940*f3d2a372Sguenther   sprintf (hdr.ar_date, "%lld", (long long)bfd_ardata (arch)->armap_timestamp);
19412159047fSniklas   sprintf (hdr.ar_uid, "%ld", (long) getuid ());
19422159047fSniklas   sprintf (hdr.ar_gid, "%ld", (long) getgid ());
19432159047fSniklas   sprintf (hdr.ar_size, "%-10d", (int) mapsize);
19442159047fSniklas   strncpy (hdr.ar_fmag, ARFMAG, 2);
19452159047fSniklas   for (i = 0; i < sizeof (struct ar_hdr); i++)
19462159047fSniklas     if (((char *) (&hdr))[i] == '\0')
19472159047fSniklas       (((char *) (&hdr))[i]) = ' ';
1948007c2a45Smiod   if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
19492159047fSniklas       != sizeof (struct ar_hdr))
1950c074d1c9Sdrahn     return FALSE;
1951c074d1c9Sdrahn   H_PUT_32 (arch, ranlibsize, temp);
1952007c2a45Smiod   if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
1953c074d1c9Sdrahn     return FALSE;
19542159047fSniklas 
19552159047fSniklas   for (count = 0; count < orl_count; count++)
19562159047fSniklas     {
19572159047fSniklas       bfd_byte buf[BSD_SYMDEF_SIZE];
19582159047fSniklas 
1959c074d1c9Sdrahn       if (map[count].u.abfd != last_elt)
19602159047fSniklas 	{
19612159047fSniklas 	  do
19622159047fSniklas 	    {
19632159047fSniklas 	      firstreal += arelt_size (current) + sizeof (struct ar_hdr);
19642159047fSniklas 	      firstreal += firstreal % 2;
19652159047fSniklas 	      current = current->next;
19662159047fSniklas 	    }
1967c074d1c9Sdrahn 	  while (current != map[count].u.abfd);
19682159047fSniklas 	}			/* if new archive element */
19692159047fSniklas 
19702159047fSniklas       last_elt = current;
1971c074d1c9Sdrahn       H_PUT_32 (arch, map[count].namidx, buf);
1972c074d1c9Sdrahn       H_PUT_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE);
1973007c2a45Smiod       if (bfd_bwrite (buf, BSD_SYMDEF_SIZE, arch)
1974c074d1c9Sdrahn 	  != BSD_SYMDEF_SIZE)
1975c074d1c9Sdrahn 	return FALSE;
19762159047fSniklas     }
19772159047fSniklas 
1978b55d4692Sfgsch   /* Now write the strings themselves.  */
1979c074d1c9Sdrahn   H_PUT_32 (arch, stringsize, temp);
1980007c2a45Smiod   if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
1981c074d1c9Sdrahn     return FALSE;
19822159047fSniklas   for (count = 0; count < orl_count; count++)
19832159047fSniklas     {
19842159047fSniklas       size_t len = strlen (*map[count].name) + 1;
19852159047fSniklas 
1986007c2a45Smiod       if (bfd_bwrite (*map[count].name, len, arch) != len)
1987c074d1c9Sdrahn 	return FALSE;
19882159047fSniklas     }
19892159047fSniklas 
19902159047fSniklas   /* The spec sez this should be a newline.  But in order to be
19912159047fSniklas      bug-compatible for sun's ar we use a null.  */
19922159047fSniklas   if (padit)
19932159047fSniklas     {
1994007c2a45Smiod       if (bfd_bwrite ("", 1, arch) != 1)
1995c074d1c9Sdrahn 	return FALSE;
19962159047fSniklas     }
19972159047fSniklas 
1998c074d1c9Sdrahn   return TRUE;
19992159047fSniklas }
20002159047fSniklas 
20012159047fSniklas /* At the end of archive file handling, update the timestamp in the
20022159047fSniklas    file, so the linker will accept it.
20032159047fSniklas 
2004c074d1c9Sdrahn    Return TRUE if the timestamp was OK, or an unusual problem happened.
2005c074d1c9Sdrahn    Return FALSE if we updated the timestamp.  */
20062159047fSniklas 
2007c074d1c9Sdrahn bfd_boolean
_bfd_archive_bsd_update_armap_timestamp(bfd * arch)2008007c2a45Smiod _bfd_archive_bsd_update_armap_timestamp (bfd *arch)
20092159047fSniklas {
20102159047fSniklas   struct stat archstat;
20112159047fSniklas   struct ar_hdr hdr;
20122159047fSniklas   unsigned int i;
20132159047fSniklas 
20142159047fSniklas   /* Flush writes, get last-write timestamp from file, and compare it
20152159047fSniklas      to the timestamp IN the file.  */
20162159047fSniklas   bfd_flush (arch);
20172159047fSniklas   if (bfd_stat (arch, &archstat) == -1)
20182159047fSniklas     {
2019c074d1c9Sdrahn       bfd_perror (_("Reading archive file mod timestamp"));
2020b55d4692Sfgsch 
2021b55d4692Sfgsch       /* Can't read mod time for some reason.  */
2022c074d1c9Sdrahn       return TRUE;
20232159047fSniklas     }
20242159047fSniklas   if (archstat.st_mtime <= bfd_ardata (arch)->armap_timestamp)
2025b55d4692Sfgsch     /* OK by the linker's rules.  */
2026c074d1c9Sdrahn     return TRUE;
20272159047fSniklas 
20282159047fSniklas   /* Update the timestamp.  */
20292159047fSniklas   bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET;
20302159047fSniklas 
20312159047fSniklas   /* Prepare an ASCII version suitable for writing.  */
20322159047fSniklas   memset (hdr.ar_date, 0, sizeof (hdr.ar_date));
2033*f3d2a372Sguenther   sprintf (hdr.ar_date, "%lld", (long long)bfd_ardata (arch)->armap_timestamp);
20342159047fSniklas   for (i = 0; i < sizeof (hdr.ar_date); i++)
20352159047fSniklas     if (hdr.ar_date[i] == '\0')
20362159047fSniklas       (hdr.ar_date)[i] = ' ';
20372159047fSniklas 
20382159047fSniklas   /* Write it into the file.  */
20392159047fSniklas   bfd_ardata (arch)->armap_datepos = (SARMAG
20402159047fSniklas 				      + offsetof (struct ar_hdr, ar_date[0]));
20412159047fSniklas   if (bfd_seek (arch, bfd_ardata (arch)->armap_datepos, SEEK_SET) != 0
2042007c2a45Smiod       || (bfd_bwrite (hdr.ar_date, sizeof (hdr.ar_date), arch)
20432159047fSniklas 	  != sizeof (hdr.ar_date)))
20442159047fSniklas     {
2045c074d1c9Sdrahn       bfd_perror (_("Writing updated armap timestamp"));
2046b55d4692Sfgsch 
2047b55d4692Sfgsch       /* Some error while writing.  */
2048c074d1c9Sdrahn       return TRUE;
20492159047fSniklas     }
20502159047fSniklas 
2051b55d4692Sfgsch   /* We updated the timestamp successfully.  */
2052c074d1c9Sdrahn   return FALSE;
20532159047fSniklas }
20542159047fSniklas 
20552159047fSniklas /* A coff armap looks like :
20562159047fSniklas    lARMAG
20572159047fSniklas    struct ar_hdr with name = '/'
20582159047fSniklas    number of symbols
20592159047fSniklas    offset of file for symbol 0
20602159047fSniklas    offset of file for symbol 1
20612159047fSniklas 
20622159047fSniklas    offset of file for symbol n-1
20632159047fSniklas    symbol name 0
20642159047fSniklas    symbol name 1
20652159047fSniklas 
20662159047fSniklas    symbol name n-1
20672159047fSniklas */
20682159047fSniklas 
2069c074d1c9Sdrahn bfd_boolean
coff_write_armap(bfd * arch,unsigned int elength,struct orl * map,unsigned int symbol_count,int stridx)2070007c2a45Smiod coff_write_armap (bfd *arch,
2071007c2a45Smiod 		  unsigned int elength,
2072007c2a45Smiod 		  struct orl *map,
2073007c2a45Smiod 		  unsigned int symbol_count,
2074007c2a45Smiod 		  int stridx)
20752159047fSniklas {
20762159047fSniklas   /* The size of the ranlib is the number of exported symbols in the
2077c074d1c9Sdrahn      archive * the number of bytes in an int, + an int for the count.  */
20782159047fSniklas   unsigned int ranlibsize = (symbol_count * 4) + 4;
20792159047fSniklas   unsigned int stringsize = stridx;
20802159047fSniklas   unsigned int mapsize = stringsize + ranlibsize;
2081c074d1c9Sdrahn   unsigned int archive_member_file_ptr;
20822159047fSniklas   bfd *current = arch->archive_head;
20832159047fSniklas   unsigned int count;
20842159047fSniklas   struct ar_hdr hdr;
20852159047fSniklas   unsigned int i;
20862159047fSniklas   int padit = mapsize & 1;
20872159047fSniklas 
20882159047fSniklas   if (padit)
20892159047fSniklas     mapsize++;
20902159047fSniklas 
2091b55d4692Sfgsch   /* Work out where the first object file will go in the archive.  */
20922159047fSniklas   archive_member_file_ptr = (mapsize
20932159047fSniklas 			     + elength
20942159047fSniklas 			     + sizeof (struct ar_hdr)
20952159047fSniklas 			     + SARMAG);
20962159047fSniklas 
2097007c2a45Smiod   memset (&hdr, 0, sizeof (struct ar_hdr));
20982159047fSniklas   hdr.ar_name[0] = '/';
20992159047fSniklas   sprintf (hdr.ar_size, "%-10d", (int) mapsize);
21002159047fSniklas   sprintf (hdr.ar_date, "%ld", (long) time (NULL));
2101b55d4692Sfgsch   /* This, at least, is what Intel coff sets the values to.  */
21022159047fSniklas   sprintf ((hdr.ar_uid), "%d", 0);
21032159047fSniklas   sprintf ((hdr.ar_gid), "%d", 0);
21042159047fSniklas   sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0);
21052159047fSniklas   strncpy (hdr.ar_fmag, ARFMAG, 2);
21062159047fSniklas 
21072159047fSniklas   for (i = 0; i < sizeof (struct ar_hdr); i++)
21082159047fSniklas     if (((char *) (&hdr))[i] == '\0')
21092159047fSniklas       (((char *) (&hdr))[i]) = ' ';
21102159047fSniklas 
2111b55d4692Sfgsch   /* Write the ar header for this item and the number of symbols.  */
21122159047fSniklas 
2113007c2a45Smiod   if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
21142159047fSniklas       != sizeof (struct ar_hdr))
2115c074d1c9Sdrahn     return FALSE;
21162159047fSniklas 
2117c074d1c9Sdrahn   if (!bfd_write_bigendian_4byte_int (arch, symbol_count))
2118c074d1c9Sdrahn     return FALSE;
21192159047fSniklas 
21202159047fSniklas   /* Two passes, first write the file offsets for each symbol -
21212159047fSniklas      remembering that each offset is on a two byte boundary.  */
21222159047fSniklas 
21232159047fSniklas   /* Write out the file offset for the file associated with each
21242159047fSniklas      symbol, and remember to keep the offsets padded out.  */
21252159047fSniklas 
21262159047fSniklas   current = arch->archive_head;
21272159047fSniklas   count = 0;
2128007c2a45Smiod   while (current != NULL && count < symbol_count)
21292159047fSniklas     {
2130b55d4692Sfgsch       /* For each symbol which is used defined in this object, write
2131b55d4692Sfgsch 	 out the object file's address in the archive.  */
21322159047fSniklas 
2133c074d1c9Sdrahn       while (count < symbol_count && map[count].u.abfd == current)
21342159047fSniklas 	{
2135c074d1c9Sdrahn 	  if (!bfd_write_bigendian_4byte_int (arch, archive_member_file_ptr))
2136c074d1c9Sdrahn 	    return FALSE;
21372159047fSniklas 	  count++;
21382159047fSniklas 	}
2139b55d4692Sfgsch       /* Add size of this archive entry.  */
2140007c2a45Smiod       archive_member_file_ptr += arelt_size (current) + sizeof (struct ar_hdr);
2141b55d4692Sfgsch       /* Remember aboout the even alignment.  */
21422159047fSniklas       archive_member_file_ptr += archive_member_file_ptr % 2;
21432159047fSniklas       current = current->next;
21442159047fSniklas     }
21452159047fSniklas 
2146b55d4692Sfgsch   /* Now write the strings themselves.  */
21472159047fSniklas   for (count = 0; count < symbol_count; count++)
21482159047fSniklas     {
21492159047fSniklas       size_t len = strlen (*map[count].name) + 1;
21502159047fSniklas 
2151007c2a45Smiod       if (bfd_bwrite (*map[count].name, len, arch) != len)
2152c074d1c9Sdrahn 	return FALSE;
21532159047fSniklas     }
21542159047fSniklas 
21552159047fSniklas   /* The spec sez this should be a newline.  But in order to be
21562159047fSniklas      bug-compatible for arc960 we use a null.  */
21572159047fSniklas   if (padit)
21582159047fSniklas     {
2159007c2a45Smiod       if (bfd_bwrite ("", 1, arch) != 1)
2160c074d1c9Sdrahn 	return FALSE;
21612159047fSniklas     }
21622159047fSniklas 
2163c074d1c9Sdrahn   return TRUE;
21642159047fSniklas }
2165