On Wednesday 19 November 2025 15:35:30 Martin Storsjö wrote:
> On Sat, 15 Nov 2025, Pali Rohár wrote:
> 
> > Currently the fsetpos emulation supports only 32-bit offsets.
> > 
> > When the new position does not fit into fsetpos32 argument then call
> > fd-based _lseeki64() function. To ensure that FILE* stream does not have
> > in-use buffers, call fflush() and fsetpos32() functions which should drop
> > remaining write and read buffers.
> > 
> > With this change mingw-w64 should fully support for all CRT builds the
> > fsetpos function with 64-bit offset. It also proves _fseeki64 and fseeko64
> > emulations which call fsetpos.
> > ---
> > mingw-w64-crt/stdio/fsetpos.c | 28 ++++++++++++++++++++--------
> > 1 file changed, 20 insertions(+), 8 deletions(-)
> > 
> > diff --git a/mingw-w64-crt/stdio/fsetpos.c b/mingw-w64-crt/stdio/fsetpos.c
> > index 4bb9e5cb7e47..4d56648d12d9 100644
> > --- a/mingw-w64-crt/stdio/fsetpos.c
> > +++ b/mingw-w64-crt/stdio/fsetpos.c
> > @@ -7,21 +7,33 @@
> > #include <stdio.h>
> > #include <errno.h>
> > #include <limits.h>
> > +#include <io.h>
> > 
> > -/* Define 64-bit fsetpos() function via 32-bit fsetpos32() function */
> > +/* Define 64-bit fsetpos() function via 32-bit fsetpos32() and 64-bit 
> > _lseeki64() functions */
> > _CRTIMP int __cdecl fsetpos32(FILE *__restrict__ _File, long *__restrict__ 
> > _Pos);
> > int __cdecl fsetpos(FILE *__restrict__ _File, const fpos_t *__restrict__ 
> > _Pos)
> > {
> > -  long pos32;
> > -
> > -  if (*_Pos < LONG_MIN || *_Pos > LONG_MAX)
> > +  if (*_Pos < LONG_MIN)
> >   {
> > -    errno = EOVERFLOW;
> > +    errno = EINVAL;
> >     return -1;
> >   }
> > -
> > -  pos32 = *_Pos;
> > -  return fsetpos32(_File, &pos32);
> > +  else if (*_Pos > LONG_MAX)
> > +  {
> > +    /* fflush() and fsetpos32() clear read and write buffers, so the 
> > followup
> > +     * _lseeki64() call correctly change offset of the FILE* stream too. */
> > +    if (fflush(_File) != 0)
> > +      return -1;
> > +    if (fsetpos32(_File, &(long){LONG_MAX}) != 0)
> > +      return -1;
> > +    if (_lseeki64(fileno(_File), *_Pos, SEEK_SET) == -1)
> > +      return -1;
> 
> So there's no FILE* level caching of the file offset, which this bypasses?
> E.g. a ftell() after this won't give the wrong result?
> 
> If there's no such issue, then this looks fine.
> 
> // Martin

I did some tests and seems that the successful fsetpo32 call flushes
those caches. So when I called lseek64 between fsetpos32 and
fgetpos32/ftell32, I got from the fgetpos32/ftell32 correct result of
the lseek64 change.

That is why there is fsetpos32(_File, &(long){LONG_MAX}) call, it
flushes those FILE* caches and makes the fd-_lseeki64 be in sync with FILE*.

But we do not have full emulation of fgetpos64/ftell64. So I checked
that only for offsets which fits into 32-bit number.


_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to