From: Keith Marshall Date: Sun, 25 Nov 2018 17:51:48 +0000 (+0000) Subject: Emulate _fseeki64()/_ftelli64() API on legacy platforms. X-Git-Tag: wsl-5.2-release~8 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=09fb4c40cbb1a2cdf51fd587e8c121289d914303;p=mingw%2Fmingw-org-wsl.git Emulate _fseeki64()/_ftelli64() API on legacy platforms. --- diff --git a/mingwrt/ChangeLog b/mingwrt/ChangeLog index 5562610..481e07f 100644 --- a/mingwrt/ChangeLog +++ b/mingwrt/ChangeLog @@ -1,3 +1,28 @@ +2018-11-25 Keith Marshall + + 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 Update and header files. diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in index 514f395..c752b6a 100644 --- a/mingwrt/Makefile.in +++ b/mingwrt/Makefile.in @@ -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. diff --git a/mingwrt/include/stdio.h b/mingwrt/include/stdio.h index ab03057..91ea4a1 100644 --- a/mingwrt/include/stdio.h +++ b/mingwrt/include/stdio.h @@ -7,7 +7,7 @@ * $Id$ * * Written by Colin Peters - * 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 namespace with declarations, such as that + * for _lseeki64(), which properly belongs in ). + */ +#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 index 0000000..70263d6 --- /dev/null +++ b/mingwrt/mingwex/stdio/fseeki64.c @@ -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 + * 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 +#include + +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 index aba0fed..0000000 --- a/mingwrt/mingwex/stdio/fseeko64.c +++ /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 - * and Danny Smith - * 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 -#include -#include - -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 index 0000000..e919ff0 --- /dev/null +++ b/mingwrt/mingwex/stdio/ftelli64.c @@ -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 + * 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 +#include + +__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 */