Warning: group file extract is broken, depending on platform and compiler; this is on Linux Mint with GCC. Posting details here as the GitHub project seems to be abandoned.
In the code below, the
fwrite call uses the union member fileinfo Size, which is corrupted by the assignment to NameWithZero; recall that they share the same storage area. On little-endian platforms, this effectively zeros the LSB of the lump size DWORD. Thus the lump is not written out in full. If you compile this yourself, remember to store the fileinfo size in a separate variable before setting the string terminator in the name.
Original:
Code: Select all
void GrpExtract(const char* filename, FILE* f)
{
TArray<GrpLump> fileinfo;
GrpInfo header;
if (1 != fread(&header, sizeof(header), 1, f)) return;
fileinfo.Resize(header.NumLumps);
if (header.NumLumps != fread(&fileinfo[0], sizeof(GrpLump), header.NumLumps, f)) return;
if (memcmp(header.Magic, "KenSilverman", 12))
{
return;
}
auto name = ExtractFileBase(filename, false);
mkdir(name.c_str());
chdir(name.c_str());
TArray<char> buffer;
for (uint32_t i = 0; i < header.NumLumps; i++)
{
buffer.Resize(fileinfo[i].Size);
fileinfo[i].NameWithZero[12] = '\0'; // Be sure filename is null-terminated
if (buffer.Size() != fread(&buffer[0], 1, buffer.Size(), f)) return;
FILE* fout = fopen(fileinfo[i].NameWithZero, "wb");
if (fout)
{
fwrite(&buffer[0], 1, fileinfo[i].Size, fout);
fclose(fout);
}
}
exit(1);
}
Fixed:
Code: Select all
void GrpExtract(const char* filename, FILE* f)
{
TArray<GrpLump> fileinfo;
GrpInfo header;
if (1 != fread(&header, sizeof(header), 1, f)) return;
fileinfo.Resize(header.NumLumps);
if (header.NumLumps != fread(&fileinfo[0], sizeof(GrpLump), header.NumLumps, f)) return;
if (memcmp(header.Magic, "KenSilverman", 12))
{
return;
}
auto name = ExtractFileBase(filename, false);
mkdir(name.c_str());
chdir(name.c_str());
TArray<char> buffer;
for (uint32_t i = 0; i < header.NumLumps; i++)
{
uint32_t lumpsize = fileinfo[i].Size;
buffer.Resize(lumpsize);
fileinfo[i].NameWithZero[12] = '\0'; // Be sure filename is null-terminated
if (lumpsize != fread(&buffer[0], 1, lumpsize, f)) return;
FILE* fout = fopen(fileinfo[i].NameWithZero, "wb");
if (fout)
{
fwrite(&buffer[0], 1, lumpsize, fout);
fclose(fout);
}
}
exit(1);
}