summaryrefslogtreecommitdiffstats
path: root/usr.bin/make/arch.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/make/arch.c')
-rw-r--r--usr.bin/make/arch.c213
1 files changed, 177 insertions, 36 deletions
diff --git a/usr.bin/make/arch.c b/usr.bin/make/arch.c
index a015eab..8a21380 100644
--- a/usr.bin/make/arch.c
+++ b/usr.bin/make/arch.c
@@ -94,7 +94,7 @@ static char sccsid[] = "@(#)arch.c 8.2 (Berkeley) 1/2/94";
#include <sys/param.h>
#include <ctype.h>
#include <ar.h>
-#include <ranlib.h>
+#include <utime.h>
#include <stdio.h>
#include <stdlib.h>
#include "make.h"
@@ -108,12 +108,18 @@ typedef struct Arch {
char *name; /* Name of archive */
Hash_Table members; /* All the members of the archive described
* by <name, struct ar_hdr *> key/value pairs */
+ char *fnametab; /* Extended name table strings */
+ size_t fnamesize; /* Size of the string table */
} Arch;
static int ArchFindArchive __P((ClientData, ClientData));
static void ArchFree __P((ClientData));
static struct ar_hdr *ArchStatMember __P((char *, char *, Boolean));
static FILE *ArchFindMember __P((char *, char *, struct ar_hdr *, char *));
+#if defined(__svr4__) || defined(__SVR4)
+#define SVR4ARCHIVES
+static int ArchSVR4Entry __P((Arch *, char *, size_t, FILE *));
+#endif
/*-
*-----------------------------------------------------------------------
@@ -143,6 +149,8 @@ ArchFree(ap)
free((Address) Hash_GetValue (entry));
free(a->name);
+ if (a->fnametab)
+ free(a->fnametab);
Hash_DeleteTable(&a->members);
free((Address) a);
}
@@ -486,7 +494,7 @@ ArchStatMember (archive, member, hash)
strncpy(copy, member, AR_MAX_NAME_LEN);
copy[AR_MAX_NAME_LEN] = '\0';
}
- if ( (he = Hash_FindEntry (&ar->members, copy)) )
+ if ((he = Hash_FindEntry (&ar->members, copy)) != NULL)
return ((struct ar_hdr *) Hash_GetValue (he));
return ((struct ar_hdr *) NULL);
}
@@ -532,27 +540,58 @@ ArchStatMember (archive, member, hash)
}
ar = (Arch *)emalloc (sizeof (Arch));
- ar->name = strdup (archive);
+ ar->name = estrdup (archive);
+ ar->fnametab = NULL;
+ ar->fnamesize = 0;
Hash_InitTable (&ar->members, -1);
memName[AR_MAX_NAME_LEN] = '\0';
while (fread ((char *)&arh, sizeof (struct ar_hdr), 1, arch) == 1) {
if (strncmp ( arh.ar_fmag, ARFMAG, sizeof (arh.ar_fmag)) != 0) {
- /*
- * The header is bogus, so the archive is bad
- * and there's no way we can recover...
- */
- fclose (arch);
- Hash_DeleteTable (&ar->members);
- free ((Address)ar);
- return ((struct ar_hdr *) NULL);
+ /*
+ * The header is bogus, so the archive is bad
+ * and there's no way we can recover...
+ */
+ goto badarch;
} else {
+ /*
+ * We need to advance the stream's pointer to the start of the
+ * next header. Files are padded with newlines to an even-byte
+ * boundary, so we need to extract the size of the file from the
+ * 'size' field of the header and round it up during the seek.
+ */
+ arh.ar_size[sizeof(arh.ar_size)-1] = '\0';
+ size = (int) strtol(arh.ar_size, NULL, 10);
+
(void) strncpy (memName, arh.ar_name, sizeof(arh.ar_name));
for (cp = &memName[AR_MAX_NAME_LEN]; *cp == ' '; cp--) {
continue;
}
cp[1] = '\0';
+#ifdef SVR4ARCHIVES
+ /*
+ * svr4 names are slash terminated. Also svr4 extended AR format.
+ */
+ if (memName[0] == '/') {
+ /*
+ * svr4 magic mode; handle it
+ */
+ switch (ArchSVR4Entry(ar, memName, size, arch)) {
+ case -1: /* Invalid data */
+ goto badarch;
+ case 0: /* List of files entry */
+ continue;
+ default: /* Got the entry */
+ break;
+ }
+ }
+ else {
+ if (cp[0] == '/')
+ cp[0] = '\0';
+ }
+#endif
+
#ifdef AR_EFMT1
/*
* BSD 4.4 extended AR format: #1/<namelen>, with name as the
@@ -563,18 +602,10 @@ ArchStatMember (archive, member, hash)
unsigned int elen = atoi(&memName[sizeof(AR_EFMT1)-1]);
- if (elen > MAXPATHLEN) {
- fclose (arch);
- Hash_DeleteTable (&ar->members);
- free ((Address)ar);
- return ((struct ar_hdr *) NULL);
- }
- if (fread (memName, elen, 1, arch) != 1) {
- fclose (arch);
- Hash_DeleteTable (&ar->members);
- free ((Address)ar);
- return ((struct ar_hdr *) NULL);
- }
+ if (elen > MAXPATHLEN)
+ goto badarch;
+ if (fread (memName, elen, 1, arch) != 1)
+ goto badarch;
memName[elen] = '\0';
fseek (arch, -elen, 1);
if (DEBUG(ARCH) || DEBUG(MAKE)) {
@@ -588,14 +619,6 @@ ArchStatMember (archive, member, hash)
memcpy ((Address)Hash_GetValue (he), (Address)&arh,
sizeof (struct ar_hdr));
}
- /*
- * We need to advance the stream's pointer to the start of the
- * next header. Files are padded with newlines to an even-byte
- * boundary, so we need to extract the size of the file from the
- * 'size' field of the header and round it up during the seek.
- */
- arh.ar_size[sizeof(arh.ar_size)-1] = '\0';
- size = (int) strtol(arh.ar_size, NULL, 10);
fseek (arch, (size + 1) & ~1, 1);
}
@@ -614,8 +637,121 @@ ArchStatMember (archive, member, hash)
} else {
return ((struct ar_hdr *) NULL);
}
+
+badarch:
+ fclose (arch);
+ Hash_DeleteTable (&ar->members);
+ if (ar->fnametab)
+ free(ar->fnametab);
+ free ((Address)ar);
+ return ((struct ar_hdr *) NULL);
}
+#ifdef SVR4ARCHIVES
+/*-
+ *-----------------------------------------------------------------------
+ * ArchSVR4Entry --
+ * Parse an SVR4 style entry that begins with a slash.
+ * If it is "//", then load the table of filenames
+ * If it is "/<offset>", then try to substitute the long file name
+ * from offset of a table previously read.
+ *
+ * Results:
+ * -1: Bad data in archive
+ * 0: A table was loaded from the file
+ * 1: Name was successfully substituted from table
+ * 2: Name was not successfully substituted from table
+ *
+ * Side Effects:
+ * If a table is read, the file pointer is moved to the next archive
+ * member
+ *
+ *-----------------------------------------------------------------------
+ */
+static int
+ArchSVR4Entry(ar, name, size, arch)
+ Arch *ar;
+ char *name;
+ size_t size;
+ FILE *arch;
+{
+#define ARLONGNAMES1 "//"
+#define ARLONGNAMES2 "/ARFILENAMES"
+ size_t entry;
+ char *ptr, *eptr;
+
+ if (strncmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 ||
+ strncmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) {
+
+ if (ar->fnametab != NULL) {
+ if (DEBUG(ARCH)) {
+ printf("Attempted to redefine an SVR4 name table\n");
+ }
+ return -1;
+ }
+
+ /*
+ * This is a table of archive names, so we build one for
+ * ourselves
+ */
+ ar->fnametab = emalloc(size);
+ ar->fnamesize = size;
+
+ if (fread(ar->fnametab, size, 1, arch) != 1) {
+ if (DEBUG(ARCH)) {
+ printf("Reading an SVR4 name table failed\n");
+ }
+ return -1;
+ }
+ eptr = ar->fnametab + size;
+ for (entry = 0, ptr = ar->fnametab; ptr < eptr; ptr++)
+ switch (*ptr) {
+ case '/':
+ entry++;
+ *ptr = '\0';
+ break;
+
+ case '\n':
+ break;
+
+ default:
+ break;
+ }
+ if (DEBUG(ARCH)) {
+ printf("Found svr4 archive name table with %d entries\n", entry);
+ }
+ return 0;
+ }
+
+ if (name[1] == ' ' || name[1] == '\0')
+ return 2;
+
+ entry = (size_t) strtol(&name[1], &eptr, 0);
+ if ((*eptr != ' ' && *eptr != '\0') || eptr == &name[1]) {
+ if (DEBUG(ARCH)) {
+ printf("Could not parse SVR4 name %s\n", name);
+ }
+ return 2;
+ }
+ if (entry >= ar->fnamesize) {
+ if (DEBUG(ARCH)) {
+ printf("SVR4 entry offset %s is greater than %d\n",
+ name, ar->fnamesize);
+ }
+ return 2;
+ }
+
+ if (DEBUG(ARCH)) {
+ printf("Replaced %s with %s\n", name, &ar->fnametab[entry]);
+ }
+
+ (void) strncpy(name, &ar->fnametab[entry], MAXPATHLEN);
+ name[MAXPATHLEN] = '\0';
+ return 1;
+}
+#endif
+
+
/*-
*-----------------------------------------------------------------------
* ArchFindMember --
@@ -820,9 +956,10 @@ void
Arch_TouchLib (gn)
GNode *gn; /* The node of the library to touch */
{
+#ifdef RANLIBMAG
FILE * arch; /* Stream open to archive */
struct ar_hdr arh; /* Header describing table of contents */
- struct timeval times[2]; /* Times for utimes() call */
+ struct utimbuf times; /* Times for utime() call */
arch = ArchFindMember (gn->path, RANLIBMAG, &arh, "r+");
sprintf(arh.ar_date, "%-12ld", (long) now);
@@ -831,10 +968,10 @@ Arch_TouchLib (gn)
(void)fwrite ((char *)&arh, sizeof (struct ar_hdr), 1, arch);
fclose (arch);
- times[0].tv_sec = times[1].tv_sec = now;
- times[0].tv_usec = times[1].tv_usec = 0;
- utimes(gn->path, times);
+ times.actime = times.modtime = now;
+ utime(gn->path, &times);
}
+#endif
}
/*-
@@ -975,7 +1112,7 @@ Arch_FindLib (gn, path)
Var_Set (TARGET, gn->name, gn);
#else
Var_Set (TARGET, gn->path == (char *) NULL ? gn->name : gn->path, gn);
-#endif LIBRARIES
+#endif /* LIBRARIES */
}
/*-
@@ -1025,6 +1162,7 @@ Arch_LibOODate (gn)
} else if ((gn->mtime > now) || (gn->mtime < gn->cmtime)) {
oodate = TRUE;
} else {
+#ifdef RANLIBMAG
struct ar_hdr *arhPtr; /* Header for __.SYMDEF */
int modTimeTOC; /* The table-of-contents's mod time */
@@ -1046,6 +1184,9 @@ Arch_LibOODate (gn)
}
oodate = TRUE;
}
+#else
+ oodate = FALSE;
+#endif
}
return (oodate);
}
OpenPOWER on IntegriCloud