From 123ae2e017d90fd18b291db3d76033781c1ead84 Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Wed, 2 Sep 2026 16:36:42 +0000 Subject: log: measure the debug log with a size type that can hold it GetFilesize() returned int while ftell() returns long, so a debug.log of 2 GiB or more came back negative. Its only caller is the -maxdebugfilesize roll added in ae1c6a7, which skips the roll on a negative size: the rotation written for issue #34 would have switched itself off permanently at exactly the size it exists to prevent. Production was at 1.95 GiB growing 51-129 MB/day, about a day short of crossing 2 GiB. The same truncation capped the comparison at INT_MAX (2047.99 MB), so -maxdebugfilesize=2048 or higher could never be exceeded and disabled rotation outright. Both failures were silent. Widen the return to int64 and seek with ftello/fseeko (_ftelli64 and _fseeki64 on Windows). The roll in util.h is the function's only caller in the tree, so no other behaviour changes. A 32-bit off_t would reintroduce the same truncation, so its width is now a compile-time assertion rather than a silent runtime surprise. --- src/util.cpp | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'src/util.cpp') diff --git a/src/util.cpp b/src/util.cpp index a5a4e80..60142be 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -415,13 +415,37 @@ bool FileExists(const char* psz) #endif } -int GetFilesize(FILE* file) +#ifndef _WIN32 +// If off_t is 32 bits wide, ftello() truncates exactly like the int this +// function used to return. Fail the build rather than ship the silent +// version of the bug (32-bit hosts need -D_FILE_OFFSET_BITS=64). +static_assert(sizeof(off_t) >= 8, "GetFilesize needs a 64-bit off_t"); +#endif + +// Returns the file's size in bytes, or -1 if it cannot be determined. +// +// This used to hold ftell()'s long in an int, so a file of 2 GiB or more came +// back negative. Its only caller is the debug.log roll in util.h, which skips +// the roll on a negative size -- i.e. rotation switched itself off for good at +// exactly the size the roll exists to prevent, and any cap of 2048 MB or more +// could never be exceeded at all. Both failures were silent. +int64 GetFilesize(FILE* file) { - int nSavePos = ftell(file); - int nFilesize = -1; - if (fseek(file, 0, SEEK_END) == 0) - nFilesize = ftell(file); - fseek(file, nSavePos, SEEK_SET); +#ifdef _WIN32 + __int64 nSavePos = _ftelli64(file); + int64 nFilesize = -1; + if (nSavePos >= 0 && _fseeki64(file, 0, SEEK_END) == 0) + nFilesize = _ftelli64(file); + if (nSavePos >= 0) + _fseeki64(file, nSavePos, SEEK_SET); +#else + off_t nSavePos = ftello(file); + int64 nFilesize = -1; + if (nSavePos >= 0 && fseeko(file, 0, SEEK_END) == 0) + nFilesize = ftello(file); + if (nSavePos >= 0) + fseeko(file, nSavePos, SEEK_SET); +#endif return nFilesize; } -- cgit v1.2.3