Skip to content

Commit

Permalink
[librpfile] RpFile_stdio.cpp, RpFile_win32.cpp: Use SEEK_END/FILE_END…
Browse files Browse the repository at this point in the history
… with offset -4 to read the gzip uncompressed size.

Instead of first seeking to the end of the file (SEEK_END with offset 0),
getting the offset, and then seeking to the offset minus 4, just seek to
-4 with SEEK_END. It's effectively the same thing and saves one syscall.

Tested on both Linux and Windows.

Interestingly, RpFile_IStream already did this.
  • Loading branch information
GerbilSoft committed Jan 5, 2025
1 parent 0bfe6ee commit 86a54c8
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 19 deletions.
14 changes: 6 additions & 8 deletions src/librpfile/RpFile_stdio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,24 +259,22 @@ RpFile::RpFile(const char *filename, FileMode mode)
if (tryGzip) { do {
uint16_t gzmagic;
size_t size = fread(&gzmagic, 1, sizeof(gzmagic), d->file);
if (size != sizeof(gzmagic) || gzmagic != be16_to_cpu(0x1F8B))
if (size != sizeof(gzmagic) || gzmagic != be16_to_cpu(0x1F8B)) {
break;
}

// This is a gzipped file.
// Get the uncompressed size at the end of the file.
fseeko(d->file, 0, SEEK_END);
off64_t real_sz = ftello(d->file);
if (real_sz <= 10+8)
break;

if (fseeko(d->file, real_sz-4, SEEK_SET) != 0)
if (fseeko(d->file, -4, SEEK_END) != 0) {
break;
}

uint32_t uncomp_sz;
size = fread(&uncomp_sz, 1, sizeof(uncomp_sz), d->file);
uncomp_sz = le32_to_cpu(uncomp_sz);
if (size != sizeof(uncomp_sz) /*|| uncomp_sz < real_sz-(10+8)*/)
if (size != sizeof(uncomp_sz) /*|| uncomp_sz < real_sz-(10+8)*/) {
break;
}

// NOTE: Uncompressed size might be smaller than the real filesize
// in cases where gzip doesn't help much.
Expand Down
21 changes: 10 additions & 11 deletions src/librpfile/win32/RpFile_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,26 +349,24 @@ RpFile::RpFile(const wchar_t *filenameW, FileMode mode)
DWORD bytesRead;
uint16_t gzmagic;
BOOL bRet = ReadFile(d->file, &gzmagic, sizeof(gzmagic), &bytesRead, nullptr);
if (!bRet || bytesRead != sizeof(gzmagic) || gzmagic != be16_to_cpu(0x1F8B))
if (!bRet || bytesRead != sizeof(gzmagic) || gzmagic != be16_to_cpu(0x1F8B)) {
break;
}

// This is a gzipped file.
// Get the uncompressed size at the end of the file.
LARGE_INTEGER liFileSize;
bRet = GetFileSizeEx(d->file, &liFileSize);
if (!bRet || liFileSize.QuadPart <= 10+8)
break;

LARGE_INTEGER liSeekPos;
liSeekPos.QuadPart = liFileSize.QuadPart - 4;
if (!SetFilePointerEx(d->file, liSeekPos, nullptr, FILE_BEGIN))
liSeekPos.QuadPart = -4;
if (!SetFilePointerEx(d->file, liSeekPos, nullptr, FILE_END)) {
break;
}

uint32_t uncomp_sz;
bRet = ReadFile(d->file, &uncomp_sz, sizeof(uncomp_sz), &bytesRead, nullptr);
uncomp_sz = le32_to_cpu(uncomp_sz);
if (!bRet || bytesRead != sizeof(uncomp_sz) /*|| uncomp_sz < liFileSize.QuadPart-(10+8)*/)
if (!bRet || bytesRead != sizeof(uncomp_sz) /*|| uncomp_sz < liFileSize.QuadPart-(10+8)*/) {
break;
}

// NOTE: Uncompressed size might be smaller than the real filesize
// in cases where gzip doesn't help much.
Expand All @@ -390,12 +388,13 @@ RpFile::RpFile(const wchar_t *filenameW, FileMode mode)
0, // dwDesiredAccess
FALSE, // bInheritHandle
DUPLICATE_SAME_ACCESS); // dwOptions
if (!bRet)
if (!bRet) {
break;
}

// NOTE: close() on gzfd_dup() will close the
// underlying Windows handle.
int gzfd_dup = _open_osfhandle((intptr_t)hGzDup, _O_RDONLY);
int gzfd_dup = _open_osfhandle(reinterpret_cast<intptr_t>(hGzDup), _O_RDONLY);
if (gzfd_dup >= 0) {
d->gzfd = gzdopen(gzfd_dup, "r");
if (d->gzfd) {
Expand Down

0 comments on commit 86a54c8

Please sign in to comment.