version 1.39, 2000/11/27 18:43:52 |
version 1.40, 2000/11/27 18:58:10 |
|
|
#include <stddef.h> |
#include <stddef.h> |
#include <ctype.h> |
#include <ctype.h> |
#include <ar.h> |
#include <ar.h> |
|
#include <assert.h> |
#include <utime.h> |
#include <utime.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
|
|
typedef struct Arch_ { |
typedef struct Arch_ { |
struct hash members; /* All the members of this archive, as |
struct hash members; /* All the members of this archive, as |
* struct arch_member entries. */ |
* struct arch_member entries. */ |
char *fnametab; /* Extended name table strings */ |
|
size_t fnamesize; /* Size of the string table */ |
|
char name[1]; /* Archive name */ |
char name[1]; /* Archive name */ |
} Arch; |
} Arch; |
|
|
|
|
(defined(__OpenBSD__) && defined(__mips__)) || \ |
(defined(__OpenBSD__) && defined(__mips__)) || \ |
(defined(__OpenBSD__) && defined(__powerpc)) |
(defined(__OpenBSD__) && defined(__powerpc)) |
#define SVR4ARCHIVES |
#define SVR4ARCHIVES |
static int ArchSVR4Entry __P((Arch *, char *, size_t, FILE *)); |
|
#endif |
#endif |
|
|
|
#ifdef SVR4ARCHIVES |
|
struct SVR4namelist { |
|
char *fnametab; /* Extended name table strings */ |
|
size_t fnamesize; /* Size of the string table */ |
|
}; |
|
|
|
static const char *svr4list = "Archive list"; |
|
|
|
static char *ArchSVR4Entry __P((struct SVR4namelist *, char *, size_t, FILE *)); |
|
#endif |
|
|
static struct arch_member * |
static struct arch_member * |
new_arch_member(hdr, name) |
new_arch_member(hdr, name) |
struct ar_hdr *hdr; |
struct ar_hdr *hdr; |
|
|
mem = hash_next(&a->members, &i)) |
mem = hash_next(&a->members, &i)) |
free(mem); |
free(mem); |
|
|
efree(a->fnametab); |
|
hash_delete(&a->members); |
hash_delete(&a->members); |
free(a); |
free(a); |
} |
} |
|
|
const char *archive; |
const char *archive; |
const char *end; |
const char *end; |
{ |
{ |
FILE * arch; /* Stream to archive */ |
FILE *arch; /* Stream to archive */ |
char magic[SARMAG]; |
char magic[SARMAG]; |
Arch *ar; |
Arch *ar; |
struct ar_hdr arh; /* archive-member header for reading archive */ |
struct ar_hdr arh; /* archive-member header for reading archive */ |
int size; /* Size of archive member */ |
char *cp; |
char memName[MAXPATHLEN+1]; |
|
/* Current member name while hashing. */ |
|
char *cp; |
|
|
|
|
#ifdef SVR4ARCHIVES |
|
struct SVR4namelist list; |
|
|
|
list.fnametab = NULL; |
|
#endif |
|
|
#define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1) |
#define AR_MAX_NAME_LEN (sizeof(arh.ar_name)-1) |
|
|
/* When we encounter an archive for the first time, we read its |
/* When we encounter an archive for the first time, we read its |
|
|
} |
} |
|
|
ar = hash_create_entry(&arch_info, archive, &end); |
ar = hash_create_entry(&arch_info, archive, &end); |
ar->fnametab = NULL; |
|
ar->fnamesize = 0; |
|
hash_init(&ar->members, 8, &members_info); |
hash_init(&ar->members, 8, &members_info); |
|
|
memName[AR_MAX_NAME_LEN] = '\0'; |
|
|
|
while (fread((char *)&arh, sizeof (struct ar_hdr), 1, arch) == 1) { |
while (fread((char *)&arh, sizeof (struct ar_hdr), 1, arch) == 1) { |
|
int size; /* Size of archive member */ |
|
char buffer[MAXPATHLEN+1]; |
|
char *memName; |
|
/* Current member name while hashing. */ |
|
memName = buffer; |
|
memName[AR_MAX_NAME_LEN] = '\0'; |
|
|
if (strncmp( arh.ar_fmag, ARFMAG, sizeof (arh.ar_fmag)) != 0) { |
if (strncmp( arh.ar_fmag, ARFMAG, sizeof (arh.ar_fmag)) != 0) { |
/* |
/* |
* The header is bogus, so the archive is bad |
* The header is bogus, so the archive is bad |
|
|
cp[1] = '\0'; |
cp[1] = '\0'; |
|
|
#ifdef SVR4ARCHIVES |
#ifdef SVR4ARCHIVES |
/* |
/* SVR4 names are slash terminated. Also svr4 extended AR format. |
* svr4 names are slash terminated. Also svr4 extended AR format. |
|
*/ |
*/ |
if (memName[0] == '/') { |
if (memName[0] == '/') { |
/* |
/* SVR4 magic mode. */ |
* svr4 magic mode; handle it |
memName = ArchSVR4Entry(&list, memName, size, arch); |
*/ |
if (memName == NULL) /* Invalid data */ |
switch (ArchSVR4Entry(ar, memName, size, arch)) { |
|
case -1: /* Invalid data */ |
|
goto badarch; |
|
case 0: /* List of files entry */ |
|
continue; |
|
default: /* Got the entry */ |
|
break; |
break; |
} |
else if (memName == svr4list) /* List of files entry */ |
|
continue; |
|
/* Got the entry. */ |
|
/* XXX this assumes further processing, such as AR_EFMT1, |
|
* also applies to SVR4ARCHIVES. */ |
} |
} |
else { |
else { |
if (cp[0] == '/') |
if (cp[0] == '/') |
|
|
badarch: |
badarch: |
fclose(arch); |
fclose(arch); |
hash_delete(&ar->members); |
hash_delete(&ar->members); |
efree(ar->fnametab); |
#ifdef SVR4ARCHIVES |
|
efree(list.fnametab); |
|
#endif |
free(ar); |
free(ar); |
return NULL; |
return NULL; |
} |
} |
|
|
* from offset of a table previously read. |
* from offset of a table previously read. |
* |
* |
* Results: |
* Results: |
* -1: Bad data in archive |
* svr4list: just read a list of names |
* 0: A table was loaded from the file |
* NULL: error occured |
* 1: Name was successfully substituted from table |
* extended name |
* 2: Name was not successfully substituted from table |
|
* |
* |
* Side Effects: |
* Side-effect: |
* If a table is read, the file pointer is moved to the next archive |
* For a list of names, store the list in l. |
* member |
|
* |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
static int |
static char * |
ArchSVR4Entry(ar, name, size, arch) |
ArchSVR4Entry(l, name, size, arch) |
Arch *ar; |
struct SVR4namelist *l; |
char *name; |
char *name; |
size_t size; |
size_t size; |
FILE *arch; |
FILE *arch; |
{ |
{ |
#define ARLONGNAMES1 "//" |
#define ARLONGNAMES1 "/" |
#define ARLONGNAMES2 "/ARFILENAMES" |
#define ARLONGNAMES2 "ARFILENAMES" |
size_t entry; |
size_t entry; |
char *ptr, *eptr; |
char *ptr, *eptr; |
|
|
if (strncmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 || |
assert(name[0] == '/'); |
strncmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) { |
name++; |
|
|
if (ar->fnametab != NULL) { |
/* First comes a table of archive names, to be used by subsequent calls. */ |
if (DEBUG(ARCH)) { |
if (memcmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 || |
|
memcmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) { |
|
|
|
if (l->fnametab != NULL) { |
|
if (DEBUG(ARCH)) |
printf("Attempted to redefine an SVR4 name table\n"); |
printf("Attempted to redefine an SVR4 name table\n"); |
} |
return NULL; |
return -1; |
|
} |
} |
|
|
/* |
l->fnametab = emalloc(size); |
* This is a table of archive names, so we build one for |
l->fnamesize = size; |
* ourselves |
|
*/ |
|
ar->fnametab = emalloc(size); |
|
ar->fnamesize = size; |
|
|
|
if (fread(ar->fnametab, size, 1, arch) != 1) { |
if (fread(l->fnametab, size, 1, arch) != 1) { |
if (DEBUG(ARCH)) { |
if (DEBUG(ARCH)) |
printf("Reading an SVR4 name table failed\n"); |
printf("Reading an SVR4 name table failed\n"); |
} |
return NULL; |
return -1; |
|
} |
} |
eptr = ar->fnametab + size; |
eptr = l->fnametab + size; |
for (entry = 0, ptr = ar->fnametab; ptr < eptr; ptr++) |
for (entry = 0, ptr = l->fnametab; ptr < eptr; ptr++) |
switch (*ptr) { |
switch (*ptr) { |
case '/': |
case '/': |
entry++; |
entry++; |
|
|
default: |
default: |
break; |
break; |
} |
} |
if (DEBUG(ARCH)) { |
if (DEBUG(ARCH)) |
printf("Found svr4 archive name table with %lu entries\n", |
printf("Found svr4 archive name table with %lu entries\n", |
(u_long)entry); |
(u_long)entry); |
} |
return (char *)svr4list; |
return 0; |
|
} |
} |
|
|
if (name[1] == ' ' || name[1] == '\0') |
/* Then the names themselves are given as offsets in this table. */ |
return 2; |
if (*name == ' ' || *name == '\0') |
|
return NULL; |
|
|
entry = (size_t) strtol(&name[1], &eptr, 0); |
entry = (size_t) strtol(name, &eptr, 0); |
if ((*eptr != ' ' && *eptr != '\0') || eptr == &name[1]) { |
if ((*eptr != ' ' && *eptr != '\0') || eptr == name) { |
if (DEBUG(ARCH)) { |
if (DEBUG(ARCH)) |
printf("Could not parse SVR4 name %s\n", name); |
printf("Could not parse SVR4 name %s\n", name); |
} |
return NULL; |
return 2; |
|
} |
} |
if (entry >= ar->fnamesize) { |
if (entry >= l->fnamesize) { |
if (DEBUG(ARCH)) { |
if (DEBUG(ARCH)) |
printf("SVR4 entry offset %s is greater than %lu\n", |
printf("SVR4 entry offset %s is greater than %lu\n", |
name, (u_long)ar->fnamesize); |
name, (u_long)l->fnamesize); |
} |
return NULL; |
return 2; |
|
} |
} |
|
|
if (DEBUG(ARCH)) { |
if (DEBUG(ARCH)) |
printf("Replaced %s with %s\n", name, &ar->fnametab[entry]); |
printf("Replaced %s with %s\n", name, l->fnametab + entry); |
} |
|
|
|
(void) strncpy(name, &ar->fnametab[entry], MAXPATHLEN); |
return l->fnametab + entry; |
name[MAXPATHLEN] = '\0'; |
|
return 1; |
|
} |
} |
#endif |
#endif |
|
|