On Sat, 15 Nov 2025, Pali Rohár wrote:
Currently the _lseeki64 emulation supports only 32-bit offsets.When the offset does not fit into the 32-bit integer (input parameter or return value) then use WinAPI SetFilePointer() function which supports 64-bit offsets and is available in every Windows version. With this change mingw-w64 should fully support for all CRT builds the _lseeki64 function and also other mingw-w64 functions which depends on it: _telli64, lseek64, ftruncate64, truncate64. And if _FILE_OFFSET_BITS == 64: lseek, ftruncate, truncate. --- mingw-w64-crt/stdio/_lseeki64.c | 51 ++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/mingw-w64-crt/stdio/_lseeki64.c b/mingw-w64-crt/stdio/_lseeki64.c index 6ead4a98e182..948320c1acf9 100644 --- a/mingw-w64-crt/stdio/_lseeki64.c +++ b/mingw-w64-crt/stdio/_lseeki64.c @@ -7,17 +7,60 @@ #include <io.h> #include <errno.h> #include <limits.h> +#include <windows.h> -/* Define 64-bit _lseeki64() function via 32-bit _lseek() function */ +/* Define 64-bit _lseeki64() function via 32-bit CRT _lseek() function and 64-bit WinAPI SetFilePointer() function */ __int64 __cdecl _lseeki64(int fd, __int64 offset, int whence) { - if (offset < LONG_MIN || offset > LONG_MAX) + const BOOL offset_overflowed = offset < LONG_MIN || offset > LONG_MAX; + + if (!offset_overflowed) + { + /* _lseek() takes only 32-bit offset value but can seek to file position + * which does not fit into 32-bit integer via SEEK_CUR / SEEK_END. + * Just the return value of new offset is truncated to 32 bits. + * _lseek() does not signal truncation, so check here just for offset + * overflow for SEEK_SET. For all other cases call SetFilePointer() + * to retrieve new 64-bit file offset. */ + errno = 0; + long ret = _lseek(fd, offset, whence); + if (whence == SEEK_SET || (ret == -1 && errno)) + return ret; + } + + HANDLE handle = (HANDLE)_get_osfhandle(fd); + if (handle == INVALID_HANDLE_VALUE) { - errno = EOVERFLOW; + errno = EBADF; return -1; } - return _lseek(fd, offset, whence); + /* If offset did not overflow then _lseek() was called and it already + * set new file position, so just read that new file position. + * If offset overflowed then _lseek() was not called at all, + * so move in the file and set new position. + * Note that FILE_* method and SEEK_* whence constants are same. */
Small extra wish: Could we add something to make this even clearer? Like static_assert(SEEK_SET == FILE_BEGIN) or so? That would also make it clearer what the other parameters (FILE_BEGIN, FILE_END) to this function even are, even if we can pass the value through.
Other than that, this patch seems fine. // Martin _______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
