aboutsummaryrefslogtreecommitdiff
path: root/bfd/archive.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/archive.c')
-rw-r--r--bfd/archive.c113
1 files changed, 86 insertions, 27 deletions
diff --git a/bfd/archive.c b/bfd/archive.c
index a968dd5..53de8fc 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -175,7 +175,7 @@ static char *get_extended_arelt_filename PARAMS ((bfd *arch,
const char *name));
static boolean do_slurp_bsd_armap PARAMS ((bfd *abfd));
static boolean do_slurp_coff_armap PARAMS ((bfd *abfd));
-static const char *normalize PARAMS ((const char *file));
+static const char *normalize PARAMS ((bfd *, const char *file));
static struct areltdata *bfd_ar_hdr_from_filesystem PARAMS ((bfd *abfd,
const char *));
static boolean compute_and_write_armap PARAMS ((bfd *arch,
@@ -871,8 +871,29 @@ do_slurp_coff_armap (abfd)
/* Pad to an even boundary if you have to */
ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
+
bfd_has_map (abfd) = true;
bfd_release (abfd, (PTR) raw_armap);
+
+
+ /* Check for a second archive header (as used by PE) */
+ {
+ struct areltdata *tmp;
+
+ bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET);
+ tmp = _bfd_snarf_ar_hdr (abfd);
+ if (tmp != NULL)
+ {
+ if (tmp->arch_header[0] == '/'
+ && tmp->arch_header[1] == ' ')
+ {
+ ardata->first_file_filepos +=
+ (tmp->parsed_size + sizeof(struct ar_hdr) + 1) & ~1;
+ }
+ bfd_release (abfd, tmp);
+ }
+ }
+
return true;
release_raw_armap:
@@ -1038,9 +1059,9 @@ _bfd_slurp_extended_name_table (abfd)
/* FIXME: Formatting sucks here, and in case of failure of BFD_READ,
we probably don't want to return true. */
+ bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET);
if (bfd_read ((PTR) nextname, 1, 16, abfd) == 16)
{
-
if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
return false;
@@ -1078,13 +1099,17 @@ _bfd_slurp_extended_name_table (abfd)
/* Since the archive is supposed to be printable if it contains
text, the entries in the list are newline-padded, not null
padded. In SVR4-style archives, the names also have a
- trailing '/'. We'll fix both problems here.. */
+ trailing '/'. DOS/NT created archive often have \ in them
+ We'll fix all problems here.. */
{
char *temp = bfd_ardata (abfd)->extended_names;
char *limit = temp + namedata->parsed_size;
- for (; temp < limit; ++temp)
+ for (; temp < limit; ++temp) {
if (*temp == '\012')
temp[temp[-1] == '/' ? -1 : 0] = '\0';
+ if (*temp == '\\')
+ *temp = '/';
+ }
}
/* Pad to an even boundary if you have to */
@@ -1104,7 +1129,8 @@ _bfd_slurp_extended_name_table (abfd)
/* Return a copy of the stuff in the filename between any :]> and a
semicolon */
static const char *
-normalize (file)
+normalize (abfd, file)
+ bfd *abfd;
const char *file;
{
CONST char *first;
@@ -1126,10 +1152,12 @@ normalize (file)
first--;
}
-
- copy = malloc (last - first + 1);
- if (!copy)
- return copy;
+ copy = (char *) bfd_alloc (abfd, last - first + 1);
+ if (copy == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
+ }
memcpy (copy, first, last - first);
copy[last - first] = 0;
@@ -1139,10 +1167,11 @@ normalize (file)
#else
static const char *
-normalize (file)
+normalize (abfd, file)
+ bfd *abfd;
const char *file;
{
- CONST char *filename = strrchr (file, '/');
+ const char *filename = strrchr (file, '/');
if (filename != (char *) NULL)
filename++;
@@ -1203,14 +1232,13 @@ _bfd_construct_extended_name_table (abfd, trailing_slash, tabloc, tablen)
/* Figure out how long the table should be */
for (current = abfd->archive_head; current != NULL; current = current->next)
{
- CONST char *normal = normalize (current->filename);
+ const char *normal;
unsigned int thislen;
- if (!normal)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ normal = normalize (current, current->filename);
+ if (normal == NULL)
+ return false;
+
thislen = strlen (normal);
if (thislen > maxname)
{
@@ -1222,6 +1250,21 @@ _bfd_construct_extended_name_table (abfd, trailing_slash, tabloc, tablen)
++total_namelen;
}
}
+ else
+ {
+ struct ar_hdr *hdr = arch_hdr (current);
+ if (strncmp (normal, hdr->ar_name, thislen) != 0
+ || (thislen < sizeof hdr->ar_name
+ && hdr->ar_name[thislen] != ar_padchar (current)))
+ {
+ /* Must have been using extended format even though it
+ didn't need to. Fix it to use normal format. */
+ memcpy (hdr->ar_name, normal, thislen);
+ if (thislen < maxname
+ || (thislen == maxname && thislen < sizeof hdr->ar_name))
+ hdr->ar_name[thislen] = ar_padchar (current);
+ }
+ }
}
if (total_namelen == 0)
@@ -1240,14 +1283,13 @@ _bfd_construct_extended_name_table (abfd, trailing_slash, tabloc, tablen)
for (current = abfd->archive_head; current != NULL; current =
current->next)
{
- CONST char *normal = normalize (current->filename);
+ const char *normal;
unsigned int thislen;
- if (!normal)
- {
- bfd_set_error (bfd_error_no_memory);
- return false;
- }
+ normal = normalize (current, current->filename);
+ if (normal == NULL)
+ return false;
+
thislen = strlen (normal);
if (thislen > maxname)
{
@@ -1404,9 +1446,16 @@ bfd_dont_truncate_arname (abfd, pathname, arhdr)
struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
int length;
- CONST char *filename = normalize (pathname);
+ const char *filename;
int maxlen = ar_maxnamelen (abfd);
+ filename = normalize (abfd, pathname);
+ if (filename == NULL)
+ {
+ /* FIXME */
+ abort ();
+ }
+
length = strlen (filename);
if (length <= maxlen)
@@ -1543,6 +1592,14 @@ _bfd_write_archive_contents (arch)
}
}
+ /* @@ This leads to archives that are incompatible with the native
+ AR on many systems, such as HP/UX and SunOS. [Cygnus PR
+ binutils/6888] It's a nice extension, but unless it can be made
+ optional, we shouldn't use it. This is a lame fix, but I don't
+ have time to fix it right just now. KR 1995/06/01 */
+ /* Turning it off is a disaster for the many people who rely upon
+ it. We should make it optional, but since that is evidently not
+ happening soon it needs to be used by default. ILT 1995/07/04. */
if (!BFD_SEND (arch, _bfd_construct_extended_name_table,
(arch, &etable, &elength, &ename)))
return false;
@@ -1569,7 +1626,9 @@ _bfd_write_archive_contents (arch)
memset ((char *) (&hdr), 0, sizeof (struct ar_hdr));
strcpy (hdr.ar_name, ename);
- sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength);
+ /* Round size up to even number in archive header. */
+ sprintf (&(hdr.ar_size[0]), "%-10d",
+ (int) ((elength + 1) & ~1));
strncpy (hdr.ar_fmag, ARFMAG, 2);
for (i = 0; i < sizeof (struct ar_hdr); i++)
if (((char *) (&hdr))[i] == '\0')
@@ -1824,8 +1883,8 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
bfd_ardata (arch)->armap_datepos = (SARMAG
+ offsetof (struct ar_hdr, ar_date[0]));
sprintf (hdr.ar_date, "%ld", bfd_ardata (arch)->armap_timestamp);
- sprintf (hdr.ar_uid, "%d", getuid ());
- sprintf (hdr.ar_gid, "%d", getgid ());
+ sprintf (hdr.ar_uid, "%ld", (long) getuid ());
+ sprintf (hdr.ar_gid, "%ld", (long) getgid ());
sprintf (hdr.ar_size, "%-10d", (int) mapsize);
strncpy (hdr.ar_fmag, ARFMAG, 2);
for (i = 0; i < sizeof (struct ar_hdr); i++)