aboutsummaryrefslogtreecommitdiff
path: root/bfd/archive.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2000-04-24 07:52:50 +0000
committerJeff Law <law@redhat.com>2000-04-24 07:52:50 +0000
commit23afc6f6722aa41d5eda6ea74c24201b13b8322c (patch)
treefad6c84383b18b5c965097e4a10812610c464640 /bfd/archive.c
parent7162c0cabe922de558b7f88b975ce9e587c8b69c (diff)
downloadbinutils-23afc6f6722aa41d5eda6ea74c24201b13b8322c.zip
binutils-23afc6f6722aa41d5eda6ea74c24201b13b8322c.tar.gz
binutils-23afc6f6722aa41d5eda6ea74c24201b13b8322c.tar.bz2
* archive.c (hpux_uid_gid_encode): New function.
(bfd_ar_hdr_from_filesystem): Use it if HPUX_LARGE_AR_IDS is defined and the ID is greater than 99999. (bfd_generic_stat_arch_elt): If HPUX_LARGE_AR_IDS is defined decode special uid/gid fields into 32 bit values.
Diffstat (limited to 'bfd/archive.c')
-rw-r--r--bfd/archive.c61
1 files changed, 56 insertions, 5 deletions
diff --git a/bfd/archive.c b/bfd/archive.c
index 19293af..1e1c9fa 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -894,10 +894,10 @@ do_slurp_coff_armap (abfd)
bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET);
tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd);
- if (tmp != NULL)
+ if (tmp != NULL)
{
if (tmp->arch_header[0] == '/'
- && tmp->arch_header[1] == ' ')
+ && tmp->arch_header[1] == ' ')
{
ardata->first_file_filepos +=
(tmp->parsed_size + sizeof(struct ar_hdr) + 1) & ~1;
@@ -1340,6 +1340,23 @@ _bfd_construct_extended_name_table (abfd, trailing_slash, tabloc, tablen)
/** A couple of functions for creating ar_hdrs */
+#ifdef HPUX_LARGE_AR_IDS
+/* Function to encode large UID/GID values according to HP. */
+static void
+hpux_uid_gid_encode (str, id)
+ char str[6];
+ long int id;
+{
+ int cnt;
+
+ str[5] = '@' + (id & 3);
+ id >>= 2;
+
+ for (cnt = 4; cnt >= 0; ++cnt, id >>= 6)
+ str[cnt] = ' ' + (id & 0x3f);
+}
+#endif /* HPUX_LARGE_AR_IDS */
+
#ifndef HAVE_GETUID
#define getuid() 0
#endif
@@ -1393,7 +1410,21 @@ bfd_ar_hdr_from_filesystem (abfd, filename, member)
/* Goddamned sprintf doesn't permit MAXIMUM field lengths */
sprintf ((hdr->ar_date), "%-12ld", (long) status.st_mtime);
- sprintf ((hdr->ar_uid), "%ld", (long) status.st_uid);
+#ifdef HPUX_LARGE_AR_IDS
+ /* HP has a very "special" way to handle UID/GID's with numeric values
+ > 99999. */
+ if (status.st_uid > 99999)
+ hpux_uid_gid_encode (hdr->ar_gid, (long) status.st_uid);
+ else
+#endif
+ sprintf ((hdr->ar_uid), "%ld", (long) status.st_uid);
+#ifdef HPUX_LARGE_AR_IDS
+ /* HP has a very "special" way to handle UID/GID's with numeric values
+ > 99999. */
+ if (status.st_gid > 99999)
+ hpux_uid_gid_encode (hdr->ar_uid, (long) status.st_gid);
+ else
+#endif
sprintf ((hdr->ar_gid), "%ld", (long) status.st_gid);
sprintf ((hdr->ar_mode), "%-8o", (unsigned int) status.st_mode);
sprintf ((hdr->ar_size), "%-10ld", (long) status.st_size);
@@ -1453,10 +1484,30 @@ bfd_generic_stat_arch_elt (abfd, buf)
#define foo(arelt, stelt, size) \
buf->stelt = strtol (hdr->arelt, &aloser, size); \
if (aloser == hdr->arelt) return -1;
+ /* Some platforms support special notations for large IDs. */
+#ifdef HPUX_LARGE_AR_IDS
+# define foo2(arelt, stelt, size) \
+ if (hdr->arelt[5] == ' ') { foo (arelt, stelt, size); } \
+ else { \
+ int cnt; \
+ for (buf->stelt = cnt = 0; cnt < 5; ++cnt) \
+ { \
+ if (hdr->arelt[cnt] < ' ' || hdr->arelt[cnt] > ' ' + 0x3f) \
+ return -1; \
+ buf->stelt <<= 6; \
+ buf->stelt += hdr->arelt[cnt] - ' '; \
+ } \
+ if (hdr->arelt[5] < '@' || hdr->arelt[5] > '@' + 3) return -1; \
+ buf->stelt <<= 2; \
+ buf->stelt += hdr->arelt[5] - '@'; \
+ }
+#else
+# define foo2(arelt, stelt, size) foo (arelt, stelt, size)
+#endif
foo (ar_date, st_mtime, 10);
- foo (ar_uid, st_uid, 10);
- foo (ar_gid, st_gid, 10);
+ foo2 (ar_uid, st_uid, 10);
+ foo2 (ar_gid, st_gid, 10);
foo (ar_mode, st_mode, 8);
buf->st_size = arch_eltdata (abfd)->parsed_size;