OSDN Git Service

Emulate _fseeki64()/_ftelli64() API on legacy platforms.
authorKeith Marshall <keith@users.osdn.me>
Sun, 25 Nov 2018 17:51:48 +0000 (17:51 +0000)
committerKeith Marshall <keith@users.osdn.me>
Sun, 25 Nov 2018 17:51:48 +0000 (17:51 +0000)
mingwrt/ChangeLog
mingwrt/Makefile.in
mingwrt/include/stdio.h
mingwrt/mingwex/stdio/fseeki64.c [new file with mode: 0644]
mingwrt/mingwex/stdio/fseeko64.c [deleted file]
mingwrt/mingwex/stdio/ftelli64.c [new file with mode: 0644]

index 5562610..481e07f 100644 (file)
@@ -1,3 +1,28 @@
+2018-11-25  Keith Marshall  <keith@users.osdn.me>
+
+       Emulate _fseeki64()/_ftelli64() API on legacy platforms.
+
+       * mingwex/stdio/fseeki64.c: New file; it implements...
+       (__mingw_fseeki64, fseeko64): ...both of these functions, avoiding any
+       dependency on undocumented internal implementation details of...
+       (fpos_t): ...this opaque data type, and replacing...
+       * mingwex/stdio/fseeko64.c: ...this; delete it.
+
+       * mingwex/stdio/ftelli64.c: New file; it implements...
+       (_ftelli64, ftello64): ...both of these, again avoiding any dependency
+       on undocumented internal implementation details of...
+       (fpos_t): ...this opaque data type.
+
+       * include/stdio.h (fpos_t): Make it more effectively opaque.
+       (__mingw_fseeki64, __mingw_ftelli64): Declare them for legacy use.
+       [_WIN32_WINNT < VISTA && __MSVCRT_VERSION__ < MSVCR80_DLL] (_fseeki64)
+       (_ftelli64): Map inline emulations, to "__mingw" prefixed names.
+       (ftello64): Remove inline implementation.
+
+       * Makefile.in (libmingwex.a): Add references to...
+       (fseeki64.$OBJEXT, ftelli64.$OBJEXT): these; remove reference to...
+       (fseeko64.$OBJEXT): ...this.
+
 2018-10-21  Keith Marshall  <keith@users.osdn.me>
 
        Update <conio.h> and <wchar.h> header files.
index 514f395..c752b6a 100644 (file)
@@ -425,9 +425,9 @@ libmingwex.a: $(addsuffix .$(OBJEXT), cosf cosl acosf acosl sinf sinl asinf \
 # compatibility than their Microsoft equivalents.
 #
 vpath %.c ${mingwrt_srcdir}/mingwex/stdio
-libmingwex.a: $(addsuffix .$(OBJEXT), btowc fprintf fseeko64 ofmtctl pformat \
-  printf snprintf sprintf vfprintf vfscanf vfwscanf vprintf vscanf vsnprintf \
-  vsprintf vsscanf vswscanf vwscanf)
+libmingwex.a: $(addsuffix .$(OBJEXT), btowc fprintf fseeki64 ftelli64 \
+  ofmtctl pformat printf snprintf sprintf vfprintf vfscanf vfwscanf vprintf \
+  vscanf vsnprintf vsprintf vsscanf vswscanf vwscanf)
 
 # pformat.$(OBJEXT) needs an explicit build rule, since we need to
 # specify an additional header file path.
index ab03057..91ea4a1 100644 (file)
@@ -7,7 +7,7 @@
  * $Id$
  *
  * Written by Colin Peters <colin@bird.fu.is.saga-u.ac.jp>
- * Copyright (C) 1997-2005, 2007-2010, 2014-2017, MinGW.org Project.
+ * Copyright (C) 1997-2005, 2007-2010, 2014-2018, MinGW.org Project.
  *
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -740,6 +740,36 @@ _CRTIMP __cdecl __MINGW_NOTHROW  int    fseek (FILE *, long, int);
 _CRTIMP __cdecl __MINGW_NOTHROW  long   ftell (FILE *);
 _CRTIMP __cdecl __MINGW_NOTHROW  void   rewind (FILE *);
 
+#ifdef __USE_MINGW_FSEEK
+/* Workaround for a limitation on Win9x where a file is not zero padded
+ * on write, following a seek beyond the original end of file; these are
+ * implemented in libmingwex.a
+ */
+__cdecl __MINGW_NOTHROW  int    __mingw_fseek (FILE *, long, int);
+__cdecl __MINGW_NOTHROW  size_t __mingw_fwrite (const void *, size_t, size_t, FILE *);
+
+#define fwrite(buffer, size, count, fp)  __mingw_fwrite(buffer, size, count, fp)
+#define fseek(fp, offset, whence)        __mingw_fseek(fp, offset, whence)
+#endif /* __USE_MINGW_FSEEK */
+
+/* An opaque data type used for storing file positions...  The contents
+ * of this type are unknown, but we (the compiler) need to know the size
+ * because the programmer using fgetpos and fsetpos will be setting aside
+ * storage for fpos_t aggregates.  Actually I tested using a byte array and
+ * it is fairly evident that fpos_t is a 32-bit type in CRTDLL.DLL, but in
+ * MSVCRT.DLL, it is a 64-bit type.  Define it in terms of an int type of
+ * the appropriate size, encapsulated within an aggregate type, to make
+ * it opaque to casting, and so discourage abuse.
+ */
+#ifdef __MSVCRT__
+typedef union { __int64 __value; __off64_t __offset; } fpos_t;
+#else
+typedef union { __int32 __value; __off32_t __offset; } fpos_t;
+#endif
+
+_CRTIMP __cdecl __MINGW_NOTHROW  int fgetpos (FILE *, fpos_t *);
+_CRTIMP __cdecl __MINGW_NOTHROW  int fsetpos (FILE *, const fpos_t *);
+
 #if _WIN32_WINNT >= _WIN32_WINNT_VISTA || __MSVCRT_VERSION__ >= __MSVCR80_DLL
  /*
   * Microsoft introduced a number of variations on fseek() and ftell(),
@@ -761,36 +791,31 @@ _CRTIMP __cdecl __MINGW_NOTHROW  int    _fseeki64_nolock (FILE *, __int64, int);
 _CRTIMP __cdecl __MINGW_NOTHROW __int64 _ftelli64_nolock (FILE *);
 
 #endif  /* MSVCR80.DLL and later derivatives ONLY */
-#endif  /* MSVCR80.DLL and descendants, or MSVCRT.DLL since Vista */
-
-#ifdef __USE_MINGW_FSEEK
-/* Workaround for a limitation on Win9x where a file is not zero padded
- * on write, following a seek beyond the original end of file; these are
- * implemented in libmingwex.a
- */
-__cdecl __MINGW_NOTHROW  int    __mingw_fseek (FILE *, long, int);
-__cdecl __MINGW_NOTHROW  size_t __mingw_fwrite (const void *, size_t, size_t, FILE *);
-
-#define fwrite(buffer, size, count, fp)  __mingw_fwrite(buffer, size, count, fp)
-#define fseek(fp, offset, whence)        __mingw_fseek(fp, offset, whence)
-#endif /* __USE_MINGW_FSEEK */
 
-/* An opaque data type used for storing file positions... The contents of
- * this type are unknown, but we (the compiler) need to know the size
- * because the programmer using fgetpos and fsetpos will be setting aside
- * storage for fpos_t structres. Actually I tested using a byte array and
- * it is fairly evident that the fpos_t type is a long (in CRTDLL.DLL).
- * Perhaps an unsigned long? TODO? It's definitely a 64-bit number in
- * MSVCRT however, and for now `long long' will do.
- */
-#ifdef __MSVCRT__
-typedef long long  fpos_t;
-#else
-typedef long       fpos_t;
+#else  /* pre-MSVCR80.DLL or MSVCRT.DLL pre-Vista */
+/*
+ * The Microsoft DLLs don't provide either _fseeki64() or _ftelli64(), but
+ * they DO provide fgetpos(), fsetpos(), and _lseeki64(), which may be used
+ * to emulate the two missing functions.  (Note that we choose to provide
+ * these emulations in the form of MinGW external helper functions, rather
+ * than pollute the <stdio.h> namespace with declarations, such as that
+ * for _lseeki64(), which properly belongs in <io.h>).
+ */
+#ifndef __USE_MINGW_FSEEK
+/* If this option has been selected, an alternative emulation for _fseeki64()
+ * is provided later, to ensure that the call is wrapped in a MinGW specific
+ * fseek() handling API.
+ */
+int __cdecl __MINGW_NOTHROW __mingw_fseeki64 (FILE *, __int64, int);
+__CRT_ALIAS int __cdecl __MINGW_NOTHROW _fseeki64 (FILE *__f, __int64 __o, int __w)
+{ return __mingw_fseeki64 (__f, __o, __w); }
 #endif
 
-_CRTIMP __cdecl __MINGW_NOTHROW  int fgetpos (FILE *, fpos_t *);
-_CRTIMP __cdecl __MINGW_NOTHROW  int fsetpos (FILE *, const fpos_t *);
+__int64 __cdecl __MINGW_NOTHROW __mingw_ftelli64 (FILE *);
+__CRT_ALIAS __int64 __cdecl __MINGW_NOTHROW _ftelli64 (FILE *__file )
+{ return __mingw_ftelli64 (__file); }
+
+#endif /* pre-MSVCR80.DLL or MSVCRT.DLL pre-Vista */
 
 /* Error Functions
  */
@@ -808,7 +833,6 @@ inline __cdecl __MINGW_NOTHROW  int ferror (FILE * __F){ return __F->_flag & _IO
 _CRTIMP __cdecl __MINGW_NOTHROW  void clearerr (FILE *);
 _CRTIMP __cdecl __MINGW_NOTHROW  void perror (const char *);
 
-
 #ifndef __STRICT_ANSI__
 /*
  * Pipes
@@ -935,14 +959,21 @@ FILE * __cdecl __MINGW_NOTHROW  fopen64 (const char * filename, const char * mod
 int __cdecl __MINGW_NOTHROW  fseeko64 (FILE *, __off64_t, int);
 
 #ifdef __USE_MINGW_FSEEK
+/* When this option is selected, we need to redirect calls to _fseeki64()
+ * and fseeko64() through a MinGW specific wrapper.  Since the two functions
+ * are fundamentally identical, differing only in the type of the "offset"
+ * argument, (and both types are effectively 64-bit signed ints anyway),
+ * the same wrapper will suffice for both.
+ */
 int __cdecl __MINGW_NOTHROW __mingw_fseeko64 (FILE *, __off64_t, int);
-#define fseeko64(fp, offset, whence)  __mingw_fseeko64(fp, offset, whence)
+__CRT_ALIAS int __cdecl __MINGW_NOTHROW fseeko64 (FILE *__f, __off64_t __o, int __w)
+{ return __mingw_fseeko64 (__f, __o, __w); }
+
+__CRT_ALIAS int __cdecl __MINGW_NOTHROW _fseeki64 (FILE *__f, __off64_t __o, int __w)
+{ return __mingw_fseeko64 (__f, (__off64_t)(__o), __w); }
 #endif
 
-__CRT_ALIAS __off64_t __cdecl __MINGW_NOTHROW ftello64 (FILE *);
-__CRT_ALIAS __LIBIMPL__(( FUNCTION = ftello64 ))
-__off64_t __cdecl __MINGW_NOTHROW ftello64 (FILE * stream)
-{ fpos_t __pos; return (fgetpos(stream, &__pos)) ? -1LL : (__off64_t)(__pos); }
+__off64_t __cdecl __MINGW_NOTHROW ftello64 (FILE *);
 
 #endif /* __MSVCRT__ && !__NO_MINGW_LFS */
 #endif /* !__STRICT_ANSI__ */
diff --git a/mingwrt/mingwex/stdio/fseeki64.c b/mingwrt/mingwex/stdio/fseeki64.c
new file mode 100644 (file)
index 0000000..70263d6
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * fseeki64.c
+ *
+ * Provides a fall-back implementation of Microsoft's _fseeki64() function,
+ * suitable for deployment when linking with legacy MSVCRT.DLL versions, from
+ * which this API is not exported.
+ *
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keith@users.osdn.me>
+ * Copyright (C) 2018, MinGW.org Project
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include <io.h>
+#include <stdio.h>
+
+int __cdecl __mingw_fseeki64( FILE *stream, __int64 offset, int whence )
+{
+  /* Emulate _fseeki64() on the basis of the underlying OS data stream
+   * pointer, as manipulated by the _lseeki64() function, (which, unlike
+   * the _fseeki64() function, has been exported from all known versions
+   * of MSVCRT.DLL).  Note that, unlike a previous MinGW implementation of
+   * the effectively equivalent fseeko64() function, this does not rely on
+   * any undocumented assumptions regarding the (opaque) content of fpos_t
+   * data, returned by the fgetpos() function; however, it does first use
+   * fgetpos(), followed by fsetpos(), without moving the FILE stream
+   * pointer, to ensure that the internal buffer associated with the FILE
+   * stream is marked as "clean", and thus that the FILE stream pointer
+   * is synchronized with the underlying OS data stream pointer, before
+   * calling _lseeki64() to adjust the latter; (this has the effect of
+   * keeping the two pointers synchronized, following the adjustment
+   * resulting from the _lseeki64() call).
+   */
+  fpos_t pos;
+  return ((fgetpos( stream, &pos ) == 0) && (fsetpos( stream, &pos ) == 0))
+    ? ((_lseeki64( _fileno( stream ), offset, whence ) == -1LL) ? -1 : 0)
+    : -1;
+}
+
+/* Since __int64 and __off64_t are effectively congruent 64-bit integer
+ * types, the preceding implementation is also suitable as an implementation
+ * for a variation of the POSIX.1 fseeko() function, in which the offset is
+ * specified in terms of the __off64_t data type.
+ */
+int __cdecl fseeko64
+( FILE *, __off64_t, int )__attribute__((alias("__mingw_fseeki64")));
+
+/* $RCSfile$: end of file */
diff --git a/mingwrt/mingwex/stdio/fseeko64.c b/mingwrt/mingwex/stdio/fseeko64.c
deleted file mode 100644 (file)
index aba0fed..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * fseeko64.c
- *
- * Seek to 64-offset within a file stream; uses same reference bases
- * as fseek(), but offset is an implementation specific __off64_t type.
- *
- * $Id$
- *
- * Written by Kees Zeelenberg <kzlg@users.sourceforge.net>
- * and Danny Smith <dannysmith@users.sourceforge.net>
- * Copyright (C) 2004, 2005, 2015, MinGW.org Project
- *
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice, this permission notice, and the following
- * disclaimer shall be included in all copies or substantial portions of
- * the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-#include <io.h>
-#include <stdio.h>
-#include <errno.h>
-
-int __cdecl
-fseeko64 (FILE* stream, __off64_t offset, int whence)
-{
-  fpos_t pos;
-  if (whence == SEEK_CUR)
-    {
-      /* If stream is invalid, fgetpos sets errno. */
-      if (fgetpos (stream, &pos))
-        return (-1);
-      pos += (fpos_t)(offset);
-    }
-  else if (whence == SEEK_END)
-    {
-      /* If writing, we need to flush before getting file length.  */
-      fflush (stream);
-      pos = (fpos_t)(_filelengthi64 (_fileno (stream)) + offset);
-    }
-  else if (whence == SEEK_SET)
-    pos = (fpos_t)(offset);
-  else
-    {
-      errno = EINVAL;
-      return (-1);
-    }
-  return fsetpos (stream, &pos);
-}
-
-/* $RCSfile$: end of file */
diff --git a/mingwrt/mingwex/stdio/ftelli64.c b/mingwrt/mingwex/stdio/ftelli64.c
new file mode 100644 (file)
index 0000000..e919ff0
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * ftelli64.c
+ *
+ * Provides a fall-back implementation of Microsoft's _ftelli64() function,
+ * suitable for deployment when linking with legacy MSVCRT.DLL versions, from
+ * which this API is not exported.
+ *
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keith@users.osdn.me>
+ * Copyright (C) 2018, MinGW.org Project
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include <io.h>
+#include <stdio.h>
+
+__int64 __cdecl __mingw_ftelli64( FILE *stream )
+{
+  /* Emulate _ftelli64() on the basis of the underlying OS data stream
+   * pointer, as returned by the _telli64() function, (which, unlike the
+   * _ftelli64() function, has been exported from all known versions of
+   * MSVCRT.DLL).  Note that, unlike a previous MinGW implementation of
+   * the effectively equivalent ftello64() function, this does not rely
+   * on any undocumented assumptions regarding the content of the opaque
+   * fpos_t data, returned by the fgetpos() function; however, it does
+   * still require the use of fgetpos(), followed by fsetpos(), without
+   * moving the FILE stream pointer, to ensure that the internal buffer
+   * associated with the FILE stream is marked as "clean", and thus that
+   * the FILE stream pointer is synchronized with the underlying OS data
+   * stream pointer, before reading the latter.
+   */
+  fpos_t pos;
+  return ((fgetpos( stream, &pos ) == 0) && (fsetpos( stream, &pos ) == 0))
+    ? _telli64( _fileno( stream )) : -1;
+}
+
+/* Since return types __int64 and __off64_t are effectively congruent
+ * 64-bit integer types, the preceding implementation is also suitable
+ * as an implementation for an __off64_t returning variation of the
+ * POSIX.1 ftello() function.
+ */
+__off64_t __cdecl ftello64( FILE * )__attribute__((alias("__mingw_ftelli64")));
+
+/* $RCSfile$: end of file */