Skip to content

Commit f2a3887

Browse files
author
Ladislav Zezula
committed
+ Bug fixes in SFileGetFileInfo, SAttrFileSaveToMpq, SListFileSaveToMpq
+ FileStream now handles files over 2GB properly + Test under Linux
1 parent c34c37b commit f2a3887

9 files changed

+306
-168
lines changed

Publish.bat

+16-14
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,23 @@
22
rem This BAT file updates the ZIP file that is to be uploaded to web
33
rem Only use when both 32-bit and 64-bit are properly compiled
44

5-
echo Creating stormlib.zip ...
5+
set STORMLIB_NAME=stormlib-9.00
6+
7+
echo Creating %STORMLIB_NAME%.zip ...
68
cd \Ladik\Appdir
7-
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\doc\*
8-
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\src\*
9-
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\storm_dll\*
10-
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\StormLib.xcodeproj\*
11-
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\stormlib_dll\*
12-
zip.exe -ur9 ..\WWW\web\download\stormlib.zip StormLib\test\*
13-
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\CMakeLists.txt
14-
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\makefile.*
15-
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\Info.plist
16-
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\*.bat
17-
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\*.sln
18-
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\*.vcproj
19-
zip.exe -u9 ..\WWW\web\download\stormlib.zip StormLib\*.vcxproj
9+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\doc\*
10+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\src\*
11+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\storm_dll\*
12+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\StormLib.xcodeproj\*
13+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\stormlib_dll\*
14+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\test\*
15+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\CMakeLists.txt
16+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\makefile.*
17+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\Info.plist
18+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\*.bat
19+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\*.sln
20+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\*.vcproj
21+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%.zip StormLib\*.vcxproj
2022
echo.
2123

2224
echo Press any key to exit ...

Publish_beta.bat

+16-14
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,23 @@
22
rem This BAT file updates the ZIP file that is to be uploaded to web
33
rem Only use when both 32-bit and 64-bit are properly compiled
44

5-
echo Creating stormlib_beta.zip ...
5+
set STORMLIB_NAME=stormlib-9.00
6+
7+
echo Creating %STORMLIB_NAME%-beta.zip ...
68
cd \Ladik\Appdir
7-
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\doc\*
8-
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\src\*
9-
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\storm_dll\*
10-
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\StormLib.xcodeproj\*
11-
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\stormlib_dll\*
12-
zip.exe -ur9 ..\WWW\web\download\stormlib_beta.zip StormLib\test\*
13-
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\CMakeLists.txt
14-
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\makefile.*
15-
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\Info.plist
16-
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\*.bat
17-
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\*.sln
18-
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\*.vcproj
19-
zip.exe -u9 ..\WWW\web\download\stormlib_beta.zip StormLib\*.vcxproj
9+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\doc\*
10+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\src\*
11+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\storm_dll\*
12+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\StormLib.xcodeproj\*
13+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\stormlib_dll\*
14+
zip.exe -ur9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\test\*
15+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\CMakeLists.txt
16+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\makefile.*
17+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\Info.plist
18+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\*.bat
19+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\*.sln
20+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\*.vcproj
21+
zip.exe -u9 ..\WWW\web\download\%STORMLIB_NAME%-beta.zip StormLib\*.vcxproj
2022
echo.
2123

2224
echo Press any key to exit ...

src/FileStream.cpp

+9-9
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ static bool BaseFile_Read(
182182
// we have to update the file position
183183
if(ByteOffset != pStream->Base.File.FilePos)
184184
{
185-
lseek((intptr_t)pStream->Base.File.hFile, (off_t)(ByteOffset), SEEK_SET);
185+
lseek64((intptr_t)pStream->Base.File.hFile, (__off64_t)(ByteOffset), SEEK_SET);
186186
pStream->Base.File.FilePos = ByteOffset;
187187
}
188188

@@ -271,7 +271,7 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const
271271
// we have to update the file position
272272
if(ByteOffset != pStream->Base.File.FilePos)
273273
{
274-
lseek((intptr_t)pStream->Base.File.hFile, (off_t)(ByteOffset), SEEK_SET);
274+
lseek64((intptr_t)pStream->Base.File.hFile, (__off64_t)(ByteOffset), SEEK_SET);
275275
pStream->Base.File.FilePos = ByteOffset;
276276
}
277277

@@ -346,7 +346,7 @@ static bool BaseFile_SetSize(TFileStream * pStream, ULONGLONG NewFileSize)
346346

347347
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
348348
{
349-
if(ftruncate((intptr_t)pStream->Base.File.hFile, (off_t)NewFileSize) == -1)
349+
if(ftruncate64((intptr_t)pStream->Base.File.hFile, (__off64_t)NewFileSize) == -1)
350350
{
351351
nLastError = errno;
352352
return false;
@@ -429,7 +429,7 @@ static bool BaseFile_Create(
429429
{
430430
intptr_t handle;
431431

432-
handle = open(szFileName, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
432+
handle = open(szFileName, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
433433
if(handle == -1)
434434
{
435435
nLastError = errno;
@@ -489,20 +489,20 @@ static bool BaseFile_Open(
489489

490490
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
491491
{
492-
struct stat fileinfo;
492+
struct stat64 fileinfo;
493493
int oflag = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? O_RDONLY : O_RDWR;
494494
intptr_t handle;
495495

496496
// Open the file
497-
handle = open(szFileName, oflag);
497+
handle = open(szFileName, oflag | O_LARGEFILE);
498498
if(handle == -1)
499499
{
500500
nLastError = errno;
501501
return false;
502502
}
503503

504504
// Get the file size
505-
if(fstat(handle, &fileinfo) == -1)
505+
if(fstat64(handle, &fileinfo) == -1)
506506
{
507507
nLastError = errno;
508508
return false;
@@ -650,7 +650,7 @@ static bool BaseMap_Open(
650650
#endif
651651

652652
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
653-
struct stat fileinfo;
653+
struct stat64 fileinfo;
654654
intptr_t handle;
655655
bool bResult = false;
656656

@@ -659,7 +659,7 @@ static bool BaseMap_Open(
659659
if(handle != -1)
660660
{
661661
// Get the file size
662-
if(fstat(handle, &fileinfo) != -1)
662+
if(fstat64(handle, &fileinfo) != -1)
663663
{
664664
pStream->Base.Map.pbFile = (LPBYTE)mmap(NULL, (size_t)fileinfo.st_size, PROT_READ, MAP_PRIVATE, handle, 0);
665665
if(pStream->Base.Map.pbFile != NULL)

src/SFileAttributes.cpp

+16-17
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ static DWORD GetSizeOfAttributesFile(DWORD dwAttrFlags, DWORD dwFileTableSize)
4141
if(dwAttrFlags & MPQ_ATTRIBUTE_MD5)
4242
cbAttrFile += dwFileTableSize * MD5_DIGEST_SIZE;
4343

44-
// Weird: When there's 1 extra bit in the patch bit array, it's ignored
45-
// wow-update-13164.MPQ: BlockTableSize = 0x62E1, but there's only 0xC5C bytes
44+
// The bit array has been create without the last bit belonging to (attributes)
45+
// When the number of files is a multiplier of 8 plus one, then the size of (attributes)
46+
// if 1 byte less than expected.
47+
// Example: wow-update-13164.MPQ: BlockTableSize = 0x62E1, but there's only 0xC5C bytes
4648
if(dwAttrFlags & MPQ_ATTRIBUTE_PATCH_BIT)
4749
cbAttrFile += (dwFileTableSize + 6) / 8;
4850

@@ -165,7 +167,7 @@ static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile)
165167
LPBYTE pbAttrFile;
166168
LPBYTE pbAttrPtr;
167169
size_t cbAttrFile;
168-
DWORD dwFinalEntries = ha->dwFileTableSize + ha->dwReservedFiles;
170+
DWORD dwFinalEntries = ha->dwFileTableSize + ha->dwReservedFiles + 1;
169171

170172
// Check if we need patch bits in the (attributes) file
171173
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
@@ -202,7 +204,7 @@ static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile)
202204
*pArrayCRC32++ = BSWAP_INT32_UNSIGNED(pFileEntry->dwCrc32);
203205

204206
// Skip the reserved entries
205-
pbAttrPtr = (LPBYTE)(pArrayCRC32 + ha->dwReservedFiles);
207+
pbAttrPtr = (LPBYTE)(pArrayCRC32 + ha->dwReservedFiles + 1);
206208
}
207209

208210
// Write the array of file time
@@ -215,7 +217,7 @@ static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile)
215217
*pArrayFileTime++ = BSWAP_INT64_UNSIGNED(pFileEntry->FileTime);
216218

217219
// Skip the reserved entries
218-
pbAttrPtr = (LPBYTE)(pArrayFileTime + ha->dwReservedFiles);
220+
pbAttrPtr = (LPBYTE)(pArrayFileTime + ha->dwReservedFiles + 1);
219221
}
220222

221223
// Write the array of MD5s
@@ -231,16 +233,15 @@ static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile)
231233
}
232234

233235
// Skip the reserved items
234-
pbAttrPtr = pbArrayMD5 + (ha->dwReservedFiles * MD5_DIGEST_SIZE);
236+
pbAttrPtr = pbArrayMD5 + ((ha->dwReservedFiles + 1) * MD5_DIGEST_SIZE);
235237
}
236238

237239
// Write the array of patch bits
238240
if(ha->dwAttrFlags & MPQ_ATTRIBUTE_PATCH_BIT)
239241
{
240242
LPBYTE pbBitArray = pbAttrPtr;
241-
DWORD dwByteSize = (dwFinalEntries + 7) / 8;
242243
DWORD dwByteIndex = 0;
243-
DWORD dwBitMask = 0x80;
244+
BYTE dwBitMask = 0x80;
244245

245246
// Copy from file table
246247
for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
@@ -254,14 +255,18 @@ static LPBYTE CreateAttributesFile(TMPQArchive * ha, DWORD * pcbAttrFile)
254255
dwBitMask = (dwBitMask << 0x07) | (dwBitMask >> 0x01);
255256
}
256257

258+
// Note: Do not increment the array by the last bit that belongs to (attributes).
259+
// This might create the array one byte less (if the number of files a multiplier of 8).
260+
// Blizzard MPQs have the same feature.
261+
257262
// Move past the bit array
258-
pbAttrPtr = (pbBitArray + dwByteSize);
263+
pbAttrPtr = (pbBitArray + dwByteIndex) + ((dwBitMask & 0x7F) ? 1 : 0);
259264
}
260265

261266
// Now we expect that current position matches the estimated size
262267
// Note that if there is 1 extra bit above the byte size,
263268
// the table is actually 1 byte shorted in Blizzard MPQs. See GetSizeOfAttributesFile
264-
assert((size_t)(pbAttrPtr - pbAttrFile) == cbAttrFile + ((dwFinalEntries & 0x07) == 1) ? 1 : 0);
269+
assert((size_t)(pbAttrPtr - pbAttrFile) == cbAttrFile);
265270
}
266271

267272
// Give away the attributes file
@@ -329,18 +334,12 @@ int SAttrFileSaveToMpq(TMPQArchive * ha)
329334

330335
// We expect at least one reserved entry to be there
331336
assert(ha->dwReservedFiles >= 1);
337+
ha->dwReservedFiles--;
332338

333339
// Create the raw data that is to be written to (attributes)
334340
// Note: Blizzard MPQs have entries for (listfile) and (attributes),
335341
// but they are filled empty
336342
pbAttrFile = CreateAttributesFile(ha, &cbAttrFile);
337-
338-
// Now we decrement the number of reserved files.
339-
// This frees one slot in the file table, so the subsequent file create operation should succeed
340-
// This must happen even if CreateAttributesFile failed
341-
ha->dwReservedFiles--;
342-
343-
// If we created something, write the attributes to the MPQ
344343
if(pbAttrFile != NULL)
345344
{
346345
// We expect it to be nonzero size

0 commit comments

Comments
 (0)