Remove C4GroupEntryCore::(Has)CRC, calculate the CRC on demand

The CRC was basically only used to decide which files to include in update
groups, but calculated for every group and then stored in the file on disc.
And for some unknown reason, updates themself didn't produce the right
numbers in the file.

This means that c4groups with this change cannot reproduce groups written
by older c4groups and vice versa, but this isn't necessary for updates, and
reading is compatible both ways.

Except for the ways that C4Update fails to remove the CRCs.
Günther Brammer 2012-02-08 00:12:44 +01:00
parent bc1f569616
commit 0e65c78185
3 changed files with 41 additions and 81 deletions

View File

@ -727,7 +727,7 @@ bool C4Group::OpenRealGrpFile()
EntryOffset+=sizeof(C4GroupEntryCore);
if (!AddEntry(C4GRES_InGroup,!!corebuf.ChildGroup,
corebuf.FileName,corebuf.Size,
corebuf.HasCRC,corebuf.CRC,entryname.getData(),
entryname.getData(),
NULL, false, false,
!!corebuf.Executable))
return Error("OpenRealGrpFile: Cannot add entry");
@ -740,8 +740,6 @@ bool C4Group::AddEntry(int status,
bool childgroup,
const char *fname,
long size,
char cCRC,
unsigned int iCRC,
const char *entryname,
BYTE *membuf,
bool fDeleteOnDisk,
@ -808,8 +806,6 @@ bool C4Group::AddEntry(int status,
nentry->Size=size;
nentry->ChildGroup=childgroup;
nentry->Offset=0;
nentry->HasCRC=cCRC;
nentry->CRC=iCRC;
nentry->Executable=fExecutable;
nentry->DeleteOnDisk=fDeleteOnDisk;
nentry->HoldBuffer=fHoldBuffer;
@ -875,9 +871,6 @@ bool C4Group::Close()
// Automatic sort
SortByList(C4Group_SortList);
// Calculate all missing checksums
EntryCRC32(NULL);
// Save group contents to disk
bool fSuccess = Save(false);
@ -1350,8 +1343,6 @@ bool C4Group::View(const char *szFiles)
centry->FileName,
centry->Size);
if (centry->HasCRC)
printf(" %s%08X", (centry->HasCRC == C4GECS_New) ? "!" : "~", centry->CRC);
if (centry->ChildGroup)
printf(" (Group)");
if (centry->Executable)
@ -1442,7 +1433,6 @@ bool C4Group::AddEntryOnDisk(const char *szFilename,
fIsGroup,
szFilename,
iSize,
false, 0,
szAddAs,
NULL,
fMove,
@ -1807,7 +1797,6 @@ bool C4Group::OpenAsChild(C4Group *pMother,
EntryOffset+=sizeof(C4GroupEntryCore);
if (!AddEntry(C4GRES_InGroup,!!corebuf.ChildGroup,
corebuf.FileName,corebuf.Size,
corebuf.HasCRC, corebuf.CRC,
NULL, NULL, false, false,
!!corebuf.Executable))
{ CloseExclusiveMother(); Clear(); return Error("OpenAsChild: Insufficient memory"); }
@ -1917,8 +1906,6 @@ bool C4Group::Add(const char *szName, void *pBuffer, int iSize, bool fChild, boo
fChild,
szName,
iSize,
false,
0,
szName,
(BYTE*) pBuffer,
false,
@ -1932,8 +1919,6 @@ bool C4Group::Add(const char *szName, StdBuf &pBuffer, bool fChild, bool fHoldBu
fChild,
szName,
pBuffer.getSize(),
false,
0,
szName,
(BYTE*) pBuffer.getData(),
false,
@ -1951,8 +1936,6 @@ bool C4Group::Add(const char *szName, StdStrBuf &pBuffer, bool fChild, bool fHol
fChild,
szName,
pBuffer.getLength(),
false,
0,
szName,
(BYTE*) pBuffer.getData(),
false,
@ -2003,8 +1986,7 @@ unsigned int C4Group::EntryCRC32(const char *szWildCard)
ResetSearch();
while ((pEntry = SearchNextEntry(szWildCard)))
{
if (!CalcCRC32(pEntry)) return false;
iCRC ^= pEntry->CRC;
iCRC ^= CalcCRC32(pEntry);
}
// return
return iCRC;
@ -2217,11 +2199,9 @@ StdStrBuf C4Group::GetFullName() const
return sResult;
}
bool C4Group::CalcCRC32(C4GroupEntry *pEntry)
uint32_t C4Group::CalcCRC32(C4GroupEntry *pEntry)
{
// checksum already calculated?
if (pEntry->HasCRC == C4GECS_New)
return true;
uint32_t CRC;
// child group?
if (pEntry->ChildGroup || (pEntry->Status == C4GRES_OnDisk && (DirectoryExists(pEntry->DiskPath) || C4Group_IsGroup(pEntry->DiskPath))))
{
@ -2241,55 +2221,49 @@ bool C4Group::CalcCRC32(C4GroupEntry *pEntry)
return 0;
}
// get checksum
pEntry->CRC = Child.EntryCRC32();
CRC = Child.EntryCRC32();
}
else if (!pEntry->Size)
pEntry->CRC = 0;
CRC = 0;
else
{
// file checksum already calculated?
if (pEntry->HasCRC != C4GECS_Old)
BYTE *pData = NULL; bool fOwnData; CStdFile f;
// get data
switch (pEntry->Status)
{
BYTE *pData = NULL; bool fOwnData; CStdFile f;
// get data
switch (pEntry->Status)
{
case C4GRES_InGroup:
// create buffer
pData = new BYTE [pEntry->Size]; fOwnData = true;
// go to entry
if (!SetFilePtr2Entry(pEntry->FileName)) { delete [] pData; return false; }
// read
if (!Read(pData, pEntry->Size)) { delete [] pData; return false; }
break;
case C4GRES_OnDisk:
// create buffer
pData = new BYTE [pEntry->Size]; fOwnData = true;
// open
if (!f.Open(pEntry->DiskPath)) { delete [] pData; return false; }
// read
if (!f.Read(pData, pEntry->Size)) { delete [] pData; return false; }
break;
case C4GRES_InMemory:
// set
pData = pEntry->bpMemBuf; fOwnData = false;
break;
default:
return false;
}
if (!pData) return false;
// calc crc
pEntry->CRC = crc32(0, pData, pEntry->Size);
// discard buffer
if (fOwnData) delete [] pData;
case C4GRES_InGroup:
// create buffer
pData = new BYTE [pEntry->Size]; fOwnData = true;
// go to entry
if (!SetFilePtr2Entry(pEntry->FileName)) { delete [] pData; return false; }
// read
if (!Read(pData, pEntry->Size)) { delete [] pData; return false; }
break;
case C4GRES_OnDisk:
// create buffer
pData = new BYTE [pEntry->Size]; fOwnData = true;
// open
if (!f.Open(pEntry->DiskPath)) { delete [] pData; return false; }
// read
if (!f.Read(pData, pEntry->Size)) { delete [] pData; return false; }
break;
case C4GRES_InMemory:
// set
pData = pEntry->bpMemBuf; fOwnData = false;
break;
default:
return false;
}
if (!pData) return false;
// calc crc
CRC = crc32(0, pData, pEntry->Size);
// discard buffer
if (fOwnData) delete [] pData;
// add file name
pEntry->CRC = crc32(pEntry->CRC, reinterpret_cast<BYTE *>(pEntry->FileName), SLen(pEntry->FileName));
CRC = crc32(CRC, reinterpret_cast<BYTE *>(pEntry->FileName), SLen(pEntry->FileName));
}
// set flag
pEntry->HasCRC = C4GECS_New;
// ok
return true;
return CRC;
}
bool C4Group::OpenChild(const char* strEntry)
@ -2367,8 +2341,7 @@ void C4Group::PrintInternals(const char *szIndent)
printf("%s ChildGroup: %d\n", szIndent, p->ChildGroup);
printf("%s Size: %d\n", szIndent, p->Size);
printf("%s Offset: %d\n", szIndent, p->Offset);
printf("%s HasCRC: %d\n", szIndent, p->HasCRC);
printf("%s CRC: %08X\n", szIndent, p->CRC);
printf("%s Executable: %d\n", szIndent, p->Executable);
if (p->ChildGroup)
{
C4Group hChildGroup;

View File

@ -104,10 +104,6 @@ public:
void Init();
};
const char C4GECS_None = 0,
C4GECS_Old = 1,
C4GECS_New = 2;
class C4GroupEntryCore
{
public:
@ -117,7 +113,7 @@ public:
int32_t Packed,ChildGroup;
int32_t Size, reserved1, Offset;
int32_t reserved2;
char HasCRC; unsigned int CRC;
char reserved3; unsigned int reserved4;
char Executable;
BYTE fbuf[26];
};
@ -281,8 +277,6 @@ protected:
bool childgroup,
const char *fname,
long size,
char cCRC,
unsigned int iCRC,
const char *entryname = NULL,
BYTE *membuf = NULL,
bool fDeleteOnDisk = false,
@ -295,7 +289,7 @@ protected:
C4GroupEntry *GetEntry(const char *szName);
C4GroupEntry *SearchNextEntry(const char *szName);
C4GroupEntry *GetNextFolderEntry();
bool CalcCRC32(C4GroupEntry *pEntry);
uint32_t CalcCRC32(C4GroupEntry *pEntry);
};
#endif

View File

@ -211,16 +211,12 @@ public:
{
C4GroupEntryCore *pCore = ((C4GroupEx &)rByGrp).GetEntry(szEntry);
// copy core
SavedCore.HasCRC = pCore->HasCRC;
SavedCore.CRC = pCore->CRC;
SavedCore.Executable = pCore->Executable;
}
void SetSavedEntryCore(const char *szEntry)
{
C4GroupEntryCore *pCore = GetEntry(szEntry);
// copy core
pCore->HasCRC = SavedCore.HasCRC;
pCore->CRC = SavedCore.CRC;
pCore->Executable = SavedCore.Executable;
}
@ -576,9 +572,6 @@ bool C4UpdatePackage::DoGrpUpdate(C4Group *pUpdateData, C4GroupEx *pGrpTo)
// strip checksum/time (if given)
char *pTime = strchr(strItemName, '=');
if (pTime) *pTime = '\0';
// update EntryCRC32. This will make updates to old groups invalid
// however, it's needed so updates will update the EntryCRC of *unchanged* files correctly
pGrpTo->EntryCRC32(strItemName);
// copy to sort list
SAppend(strItemName, strSortList);
SAppendChar('|', strSortList);