version 1.40, 2000/11/27 18:58:10 |
version 1.41, 2000/11/27 20:35:27 |
|
|
|
|
static struct arch_member *new_arch_member __P((struct ar_hdr *, const char *)); |
static struct arch_member *new_arch_member __P((struct ar_hdr *, const char *)); |
static TIMESTAMP mtime_of_member __P((struct arch_member *)); |
static TIMESTAMP mtime_of_member __P((struct arch_member *)); |
|
static long field2long __P((const char *, size_t)); |
static Arch *read_archive __P((const char *, const char *)); |
static Arch *read_archive __P((const char *, const char *)); |
|
|
#ifdef CLEANUP |
#ifdef CLEANUP |
|
|
return (SUCCESS); |
return (SUCCESS); |
} |
} |
|
|
|
/* Helper function: ar fields are not null terminated. */ |
|
static long |
|
field2long(field, len) |
|
const char *field; |
|
size_t len; |
|
{ |
|
static char enough[32]; |
|
|
|
assert(len < sizeof(enough)); |
|
memcpy(enough, field, len); |
|
enough[len] = '\0'; |
|
return strtol(enough, NULL, 10); |
|
} |
|
|
static Arch * |
static Arch * |
read_archive(archive, end) |
read_archive(archive, end) |
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 */ |
|
char *cp; |
|
|
|
#ifdef SVR4ARCHIVES |
#ifdef SVR4ARCHIVES |
struct SVR4namelist list; |
struct SVR4namelist list; |
|
|
list.fnametab = NULL; |
list.fnametab = NULL; |
#endif |
#endif |
|
|
#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 |
* whole contents, to place it in the cache. */ |
* whole contents, to place it in the cache. */ |
arch = fopen(archive, "r"); |
arch = fopen(archive, "r"); |
|
|
|
|
/* Make sure this is an archive we can handle. */ |
/* Make sure this is an archive we can handle. */ |
if ((fread(magic, SARMAG, 1, arch) != 1) || |
if ((fread(magic, SARMAG, 1, arch) != 1) || |
(strncmp(magic, ARMAG, SARMAG) != 0)) { |
(strncmp(magic, ARMAG, SARMAG) != 0)) { |
fclose(arch); |
fclose(arch); |
return NULL; |
return NULL; |
} |
} |
|
|
ar = hash_create_entry(&arch_info, archive, &end); |
ar = hash_create_entry(&arch_info, archive, &end); |
hash_init(&ar->members, 8, &members_info); |
hash_init(&ar->members, 8, &members_info); |
|
|
|
for (;;) { |
while (fread((char *)&arh, sizeof (struct ar_hdr), 1, arch) == 1) { |
size_t n; |
int size; /* Size of archive member */ |
struct ar_hdr arh; /* Archive-member header for reading archive */ |
|
off_t size; /* Size of archive member */ |
char buffer[MAXPATHLEN+1]; |
char buffer[MAXPATHLEN+1]; |
char *memName; |
char *memName; |
/* Current member name while hashing. */ |
/* Current member name while hashing. */ |
|
char *cp; /* Useful character pointer */ |
|
|
memName = buffer; |
memName = buffer; |
memName[AR_MAX_NAME_LEN] = '\0'; |
n = fread(&arh, 1, sizeof(struct ar_hdr), arch); |
|
|
if (strncmp( arh.ar_fmag, ARFMAG, sizeof (arh.ar_fmag)) != 0) { |
/* Whole archive read ok. */ |
/* |
if (n == 0 && feof(arch)) { |
* The header is bogus, so the archive is bad |
#ifdef SVR4ARCHIVES |
* and there's no way we can recover... |
efree(list.fnametab); |
*/ |
#endif |
goto badarch; |
fclose(arch); |
|
return ar; |
|
} |
|
if (n < sizeof(struct ar_hdr)) |
|
break; |
|
|
|
if (memcmp(arh.ar_fmag, ARFMAG, sizeof(arh.ar_fmag)) != 0) { |
|
/* The header is bogus. */ |
|
break; |
} else { |
} else { |
/* |
/* We need to advance the stream's pointer to the start of the |
* We need to advance the stream's pointer to the start of the |
* next header. Records are padded with newlines to an even-byte |
* next header. Files are padded with newlines to an even-byte |
* boundary, so we need to extract the size of the record and |
* boundary, so we need to extract the size of the file from the |
* round it up during the seek. */ |
* 'size' field of the header and round it up during the seek. |
size = (off_t) field2long(arh.ar_size, sizeof(arh.ar_size)); |
*/ |
|
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)); |
(void)memcpy(memName, arh.ar_name, AR_NAME_SIZE); |
for (cp = &memName[AR_MAX_NAME_LEN]; *cp == ' '; cp--) { |
/* Find real end of name (strip extranous ' ') */ |
continue; |
for (cp = memName + AR_NAME_SIZE - 1; *cp == ' ';) |
} |
cp--; |
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. */ |
|
|
#endif |
#endif |
|
|
#ifdef AR_EFMT1 |
#ifdef AR_EFMT1 |
/* |
/* BSD 4.4 extended AR format: #1/<namelen>, with name as the |
* BSD 4.4 extended AR format: #1/<namelen>, with name as the |
* first <namelen> bytes of the file. */ |
* first <namelen> bytes of the file |
if (memcmp(memName, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 && |
*/ |
|
if (strncmp(memName, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 && |
|
isdigit(memName[sizeof(AR_EFMT1) - 1])) { |
isdigit(memName[sizeof(AR_EFMT1) - 1])) { |
|
|
unsigned int elen = atoi(&memName[sizeof(AR_EFMT1)-1]); |
int elen = atoi(memName + sizeof(AR_EFMT1)-1); |
|
|
if (elen > MAXPATHLEN) |
if (elen <= 0 || elen > MAXPATHLEN) |
goto badarch; |
break; |
if (fread (memName, elen, 1, arch) != 1) |
memName = buffer; |
goto badarch; |
if (fread(memName, elen, 1, arch) != 1) |
|
break; |
memName[elen] = '\0'; |
memName[elen] = '\0'; |
fseek(arch, -elen, SEEK_CUR); |
if (fseek(arch, -elen, SEEK_CUR) != 0) |
if (DEBUG(ARCH) || DEBUG(MAKE)) { |
break; |
|
if (DEBUG(ARCH) || DEBUG(MAKE)) |
printf("ArchStat: Extended format entry for %s\n", memName); |
printf("ArchStat: Extended format entry for %s\n", memName); |
} |
|
} |
} |
#endif |
#endif |
|
|
|
|
hash_qlookup(&ar->members, memName), |
hash_qlookup(&ar->members, memName), |
new_arch_member(&arh, memName)); |
new_arch_member(&arh, memName)); |
} |
} |
fseek(arch, (size + 1) & ~1, SEEK_CUR); |
if (fseek(arch, (size + 1) & ~1, SEEK_CUR) != 0) |
|
break; |
} |
} |
|
|
fclose(arch); |
|
|
|
return ar; |
|
|
|
badarch: |
|
fclose(arch); |
fclose(arch); |
hash_delete(&ar->members); |
hash_delete(&ar->members); |
#ifdef SVR4ARCHIVES |
#ifdef SVR4ARCHIVES |