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;
+    return 0;
+  }
+  else
+  {
+    return fsetpos32(_File, &(long){*_Pos});
+  }
 }
 int (__cdecl *__MINGW_IMP_SYMBOL(fsetpos))(FILE *__restrict__ _File, const 
fpos_t *__restrict__ _Pos) = fsetpos;
 
-- 
2.20.1



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

Reply via email to