version 1.68, 2007/09/16 12:30:35 |
version 1.69, 2007/09/17 09:28:36 |
|
|
* Once again, cacheing/hashing comes into play in the manipulation |
* Once again, cacheing/hashing comes into play in the manipulation |
* of archives. The first time an archive is referenced, all of its members' |
* of archives. The first time an archive is referenced, all of its members' |
* headers are read and hashed and the archive closed again. All hashed |
* headers are read and hashed and the archive closed again. All hashed |
* archives are kept in a hash (archives) which is searched each time |
* archives are kept in a hash (archives) which is searched each time |
* an archive member is referenced. |
* an archive member is referenced. |
* |
* |
*/ |
*/ |
|
|
mtime_of_member(struct arch_member *m) |
mtime_of_member(struct arch_member *m) |
{ |
{ |
if (is_out_of_date(m->mtime)) |
if (is_out_of_date(m->mtime)) |
ts_set_from_time_t((time_t) strtol(m->date, NULL, 10), |
ts_set_from_time_t((time_t) strtol(m->date, NULL, 10), |
m->mtime); |
m->mtime); |
return m->mtime; |
return m->mtime; |
} |
} |
|
|
|
|
snprintf(buf, length, "%s(%s)", libName, memberName); |
snprintf(buf, length, "%s(%s)", libName, memberName); |
|
|
if (strchr(memberName, '$') && |
if (strchr(memberName, '$') && |
strcmp(memberName, oldMemberName) == 0) { |
strcmp(memberName, oldMemberName) == 0) { |
/* Must contain dynamic sources, so we can't |
/* Must contain dynamic sources, so we can't |
* deal with it now. Just create an ARCHV node |
* deal with it now. Just create an ARCHV node |
|
|
gn->type |= OP_ARCHV; |
gn->type |= OP_ARCHV; |
Lst_AtEnd(nodeLst, gn); |
Lst_AtEnd(nodeLst, gn); |
} |
} |
} else if (!Arch_ParseArchive(&sacrifice, nodeLst, |
} else if (!Arch_ParseArchive(&sacrifice, nodeLst, |
ctxt)) { |
ctxt)) { |
/* Error in nested call -- free buffer and |
/* Error in nested call -- free buffer and |
* return false ourselves. */ |
* return false ourselves. */ |
|
|
Lst_Init(&members); |
Lst_Init(&members); |
|
|
Dir_Expand(memberName, defaultPath, &members); |
Dir_Expand(memberName, defaultPath, &members); |
while ((member = (char *)Lst_DeQueue(&members)) |
while ((member = (char *)Lst_DeQueue(&members)) |
!= NULL) { |
!= NULL) { |
snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", |
snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", |
libName, member); |
libName, member); |
free(member); |
free(member); |
gn = Targ_FindNode(nameBuf, TARG_CREATE); |
gn = Targ_FindNode(nameBuf, TARG_CREATE); |
|
|
Lst_AtEnd(nodeLst, gn); |
Lst_AtEnd(nodeLst, gn); |
} |
} |
} else { |
} else { |
snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", libName, |
snprintf(nameBuf, MAKE_BSIZE, "%s(%s)", libName, |
memberName); |
memberName); |
gn = Targ_FindNode(nameBuf, TARG_CREATE); |
gn = Targ_FindNode(nameBuf, TARG_CREATE); |
/* We've found the node, but have to make sure the rest |
/* We've found the node, but have to make sure the rest |
|
|
if (n < sizeof(struct ar_hdr)) |
if (n < sizeof(struct ar_hdr)) |
break; |
break; |
|
|
if (memcmp(arHeader.ar_fmag, ARFMAG, sizeof(arHeader.ar_fmag)) |
if (memcmp(arHeader.ar_fmag, ARFMAG, sizeof(arHeader.ar_fmag)) |
!= 0) { |
!= 0) { |
/* The header is bogus. */ |
/* The header is bogus. */ |
break; |
break; |
|
|
* newlines to an even-byte boundary, so we need to |
* newlines to an even-byte boundary, so we need to |
* extract the size of the record and round it up |
* extract the size of the record and round it up |
* during the seek. */ |
* during the seek. */ |
size = (off_t) field2long(arHeader.ar_size, |
size = (off_t) field2long(arHeader.ar_size, |
sizeof(arHeader.ar_size)); |
sizeof(arHeader.ar_size)); |
|
|
(void)memcpy(memberName, arHeader.ar_name, |
(void)memcpy(memberName, arHeader.ar_name, |
AR_NAME_SIZE); |
AR_NAME_SIZE); |
/* Find real end of name (strip extranous ' ') */ |
/* Find real end of name (strip extranous ' ') */ |
for (cp = memberName + AR_NAME_SIZE - 1; *cp == ' ';) |
for (cp = memberName + AR_NAME_SIZE - 1; *cp == ' ';) |
|
|
*/ |
*/ |
if (memberName[0] == '/') { |
if (memberName[0] == '/') { |
/* SVR4 magic mode. */ |
/* SVR4 magic mode. */ |
memberName = ArchSVR4Entry(&list, memberName, |
memberName = ArchSVR4Entry(&list, memberName, |
size, arch); |
size, arch); |
if (memberName == NULL) /* Invalid data */ |
if (memberName == NULL) /* Invalid data */ |
break; |
break; |
|
|
#ifdef AR_EFMT1 |
#ifdef AR_EFMT1 |
/* BSD 4.4 extended AR format: #1/<namelen>, with name |
/* BSD 4.4 extended AR format: #1/<namelen>, with name |
* as the first <namelen> bytes of the file. */ |
* as the first <namelen> bytes of the file. */ |
if (memcmp(memberName, AR_EFMT1, sizeof(AR_EFMT1) - 1) |
if (memcmp(memberName, AR_EFMT1, sizeof(AR_EFMT1) - 1) |
== 0 && isdigit(memberName[sizeof(AR_EFMT1) - 1])) { |
== 0 && isdigit(memberName[sizeof(AR_EFMT1) - 1])) { |
|
|
int elen = atoi(memberName + |
int elen = atoi(memberName + |
sizeof(AR_EFMT1)-1); |
sizeof(AR_EFMT1)-1); |
|
|
if (elen <= 0 || elen >= PATH_MAX) |
if (elen <= 0 || elen >= PATH_MAX) |
|
|
if (fseek(arch, -elen, SEEK_CUR) != 0) |
if (fseek(arch, -elen, SEEK_CUR) != 0) |
break; |
break; |
if (DEBUG(ARCH) || DEBUG(MAKE)) |
if (DEBUG(ARCH) || DEBUG(MAKE)) |
printf("ArchStat: Extended format entry for %s\n", |
printf("ArchStat: Extended format entry for %s\n", |
memberName); |
memberName); |
} |
} |
#endif |
#endif |
|
|
|
|
if (arch != NULL) { |
if (arch != NULL) { |
fclose(arch); |
fclose(arch); |
ts_set_from_time_t( |
ts_set_from_time_t( |
(time_t)strtol(arHeader.ar_date, NULL, 10), |
(time_t)strtol(arHeader.ar_date, NULL, 10), |
result); |
result); |
} |
} |
return result; |
return result; |
|
|
struct arch_member *he; |
struct arch_member *he; |
end = NULL; |
end = NULL; |
|
|
he = ohash_find(&ar->members, |
he = ohash_find(&ar->members, |
ohash_qlookupi(&ar->members, member, &end)); |
ohash_qlookupi(&ar->members, member, &end)); |
if (he != NULL) |
if (he != NULL) |
return mtime_of_member(he); |
return mtime_of_member(he); |
|
|
off_t size; /* Size of archive member */ |
off_t size; /* Size of archive member */ |
char *memberName; |
char *memberName; |
|
|
if (memcmp(arHeaderPtr->ar_fmag, ARFMAG, |
if (memcmp(arHeaderPtr->ar_fmag, ARFMAG, |
sizeof(arHeaderPtr->ar_fmag) ) != 0) |
sizeof(arHeaderPtr->ar_fmag) ) != 0) |
/* The header is bogus, so the archive is bad. */ |
/* The header is bogus, so the archive is bad. */ |
break; |
break; |
|
|
* string is anything but a space, this isn't the |
* string is anything but a space, this isn't the |
* member we sought. */ |
* member we sought. */ |
#ifdef SVR4ARCHIVES |
#ifdef SVR4ARCHIVES |
if (length < sizeof(arHeaderPtr->ar_name) && |
if (length < sizeof(arHeaderPtr->ar_name) && |
memberName[length] == '/') |
memberName[length] == '/') |
length++; |
length++; |
#endif |
#endif |
|
|
} |
} |
} |
} |
|
|
size = (off_t) field2long(arHeaderPtr->ar_size, |
size = (off_t) field2long(arHeaderPtr->ar_size, |
sizeof(arHeaderPtr->ar_size)); |
sizeof(arHeaderPtr->ar_size)); |
|
|
#ifdef SVR4ARCHIVES |
#ifdef SVR4ARCHIVES |
|
|
*/ |
*/ |
if (memberName[0] == '/') { |
if (memberName[0] == '/') { |
/* svr4 magic mode. */ |
/* svr4 magic mode. */ |
memberName = ArchSVR4Entry(&list, |
memberName = ArchSVR4Entry(&list, |
arHeaderPtr->ar_name, size, arch); |
arHeaderPtr->ar_name, size, arch); |
if (memberName == NULL) /* Invalid data */ |
if (memberName == NULL) /* Invalid data */ |
break; |
break; |
|
|
|
|
arch = ArchFindMember(archive, member, &arHeader, "r+"); |
arch = ArchFindMember(archive, member, &arHeader, "r+"); |
if (arch != NULL) { |
if (arch != NULL) { |
snprintf(arHeader.ar_date, sizeof(arHeader.ar_date), "%-12ld", |
snprintf(arHeader.ar_date, sizeof(arHeader.ar_date), "%-12ld", |
(long) timestamp2time_t(now)); |
(long) timestamp2time_t(now)); |
if (fseek(arch, -sizeof(struct ar_hdr), SEEK_CUR) == 0) |
if (fseek(arch, -sizeof(struct ar_hdr), SEEK_CUR) == 0) |
(void)fwrite(&arHeader, sizeof(struct ar_hdr), 1, arch); |
(void)fwrite(&arHeader, sizeof(struct ar_hdr), 1, arch); |
|
|
nameEnd = NULL; |
nameEnd = NULL; |
|
|
if (pgn->make && nameEnd != NULL && |
if (pgn->make && nameEnd != NULL && |
strncmp(nameStart, gn->name, nameEnd - nameStart) |
strncmp(nameStart, gn->name, nameEnd - nameStart) |
== 0 && gn->name[nameEnd-nameStart] == '\0') |
== 0 && gn->name[nameEnd-nameStart] == '\0') |
gn->mtime = Arch_MTime(pgn); |
gn->mtime = Arch_MTime(pgn); |
} else if (pgn->make) { |
} else if (pgn->make) { |
|
|
return gn->mtime; |
return gn->mtime; |
} |
} |
|
|
/* If the system can handle the -L flag when linking (or we cannot find |
/* If the system can handle the -L flag when linking (or we cannot find |
* the library), we assume that the user has placed the .LIBRARIES variable |
* the library), we assume that the user has placed the .LIBRARIES variable |
* in the final linking command (or the linker will know where to find it) |
* in the final linking command (or the linker will know where to find it) |
* and set the TARGET variable for this node to be the node's name. Otherwise, |
* and set the TARGET variable for this node to be the node's name. Otherwise, |
* we set the TARGET variable to be the full path of the library, |
* we set the TARGET variable to be the full path of the library, |
* as returned by Dir_FindFile. |
* as returned by Dir_FindFile. |
|
|
|
|
if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->children)) |
if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->children)) |
return false; |
return false; |
if (is_strictly_before(now, gn->mtime) || |
if (is_strictly_before(now, gn->mtime) || |
is_strictly_before(gn->mtime, gn->cmtime) || |
is_strictly_before(gn->mtime, gn->cmtime) || |
is_out_of_date(gn->mtime)) |
is_out_of_date(gn->mtime)) |
return true; |
return true; |
|
|
|
|
if (!is_out_of_date(modTimeTOC)) { |
if (!is_out_of_date(modTimeTOC)) { |
if (DEBUG(ARCH) || DEBUG(MAKE)) |
if (DEBUG(ARCH) || DEBUG(MAKE)) |
printf("%s modified %s...", RANLIBMAG, |
printf("%s modified %s...", RANLIBMAG, |
time_to_string(modTimeTOC)); |
time_to_string(modTimeTOC)); |
return is_strictly_before(modTimeTOC, gn->cmtime); |
return is_strictly_before(modTimeTOC, gn->cmtime); |
} |
} |