summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>1993-04-26 20:43:32 +0000
committerRoland McGrath <roland@redhat.com>1993-04-26 20:43:32 +0000
commit683e4a5de9c796b2fe3f6f7b7921904fb8ac0d54 (patch)
tree44633389a55c111f15d2cc0d088c11524e70d5c2
parent548b4c9bf1b7758ed349428ae002a31c63cbe0ad (diff)
downloadgunmake-683e4a5de9c796b2fe3f6f7b7921904fb8ac0d54.tar.gz
Formerly arscan.c.~28~
-rw-r--r--arscan.c87
1 files changed, 83 insertions, 4 deletions
diff --git a/arscan.c b/arscan.c
index 41c50c1..7def695 100644
--- a/arscan.c
+++ b/arscan.c
@@ -82,6 +82,7 @@ ar_scan (archive, function, arg)
#ifdef AIAMAG
FL_HDR fl_header;
#endif
+ char *namemap = 0;
register int desc = open (archive, O_RDONLY, 0);
if (desc < 0)
return -1;
@@ -153,7 +154,9 @@ ar_scan (archive, function, arg)
int uidval, gidval;
long int data_offset;
#else
- char name[sizeof member_header.ar_name + 1];
+ char namebuf[sizeof member_header.ar_name + 1];
+ char *name;
+ int is_namemap; /* Nonzero if this entry maps long names. */
#endif
long int eltsize;
int eltmode;
@@ -216,15 +219,54 @@ ar_scan (archive, function, arg)
return -2;
}
+ name = namebuf;
bcopy (member_header.ar_name, name, sizeof member_header.ar_name);
{
register char *p = name + sizeof member_header.ar_name;
- while (p > name && *--p == ' ')
+ do
*p = '\0';
-
+ while (p > name && *--p == ' ');
+
+#ifndef AIAMAG
+ /* If the member name is "//" or "ARFILENAMES/" this may be
+ a list of file name mappings. The maximum file name
+ length supported by the standard archive format is 14
+ characters. This member will actually always be the
+ first or second entry in the archive, but we don't check
+ that. */
+ is_namemap = (!strcmp (name, "//")
+ || !strcmp (name, "ARFILENAMES/"));
+#endif /* Not AIAMAG. */
/* On some systems, there is a slash after each member name. */
if (*p == '/')
*p = '\0';
+
+#ifndef AIAMAG
+ /* If the member name starts with a space or a slash, this
+ is an index into the file name mappings (used by GNU ar).
+ Otherwise if the member name looks like #1/NUMBER the
+ real member name appears in the element data (used by
+ 4.4BSD). */
+ if (! is_namemap
+ && (name[0] == ' ' || name[0] == '/')
+ && namemap != 0)
+ name = namemap + atoi (name + 1);
+ else if (name[0] == '#'
+ && name[1] == '1'
+ && name[2] == '/')
+ {
+ int namesize = atoi (name + 3);
+
+ name = (char *) alloca (namesize + 1);
+ nread = read (desc, name, namesize);
+ if (nread != namesize)
+ {
+ close (desc);
+ return -2;
+ }
+ name[namesize] = '\0';
+ }
+#endif /* Not AIAMAG. */
}
#ifndef M_XENIX
@@ -270,6 +312,40 @@ ar_scan (archive, function, arg)
return -2;
}
#else
+
+ /* If this member maps archive names, we must read it in. The
+ name map will always precede any members whose names must
+ be mapped. */
+ if (is_namemap)
+ {
+ char *clear;
+ char *limit;
+
+ namemap = (char *) alloca (eltsize);
+ nread = read (desc, namemap, eltsize);
+ if (nread != eltsize)
+ {
+ (void) close (desc);
+ return -2;
+ }
+
+ /* The names are separated by newlines. Some formats have
+ a trailing slash. Null terminate the strings for
+ convenience. */
+ limit = namemap + eltsize;
+ for (clear = namemap; clear < limit; clear++)
+ {
+ if (*clear == '\n')
+ {
+ *clear = '\0';
+ if (clear[-1] == '/')
+ clear[-1] = '\0';
+ }
+ }
+
+ is_namemap = 0;
+ }
+
member_offset += AR_HDR_SIZE + eltsize;
if (member_offset % 2 != 0)
member_offset++;
@@ -294,7 +370,10 @@ ar_name_equal (name, mem)
if (p != 0)
name = p + 1;
-#if !defined (AIAMAG) && !defined (APOLLO)
+ /* We no longer use this kludge, since we
+ now support long archive member names. */
+
+#if 0 && !defined (AIAMAG) && !defined (APOLLO)
{
/* `reallylongname.o' matches `reallylongnam.o'.