msvcrt and UCRT function _chsize() has same behavior and also ABI as POSIX
function ftruncate() with 32-bit length.
For 64-bit length msvcr80+ and UCRT provide function _chksize_s() but it
has slightly different usage as _chksize() / ftruncate() and so cannot be
directly aliased at symbol ABI level.
Function _chksize_s() calls invalid parameter exception handler and return
value is errno.
mingw-w64 currently provides its own ftruncate64() implementation which is
statically linked into every binary which calls ftruncate64().
For msvcr80+ and UCRT builds, provide a new ftruncate64() implementation as
a simple wrapper around the CRT _chksize_s() function. To prevent calling
invalid parameter exception handler, validate input parametes manually
before calling the function itself.
For pre-msvcr80 builds use the existing mingw-w64 implemenation of
ftruncate64() function.
And for OS-system msvcrt.dll builds use either the _chksize_s() or the
mingw-w64 implemation. Function symbol _chksize_s in msvcrt.dll is
available since Windows Vista, so for x86/x64 builds, resolve that symbol
at runtime.
Note that OS-system msvcrt.dll _chksize_s() does not call invalid parameter
exception handler, so call function directly without validation.
To prevent symbol conflicts between existing mingw-w64 implementation of
ftruncate64 and new wrapper implementation (around _chksize_s), rename the
existing mingw-w64 implementation to __mingw_ftruncate64.
With this change, calling the ftruncate64 function symbol results in using
the native _chksize_s CRT implementation for msvcr80+ and UCRT builds.
---
mingw-w64-crt/Makefile.am | 5 +-
.../{ftruncate64.c => mingw_ftruncate64.c} | 6 ++-
mingw-w64-crt/stdio/msvcr80plus_ftruncate64.c | 30 ++++++++++++
mingw-w64-crt/stdio/msvcrtos_ftruncate64.c | 47 +++++++++++++++++++
4 files changed, 86 insertions(+), 2 deletions(-)
rename mingw-w64-crt/stdio/{ftruncate64.c => mingw_ftruncate64.c} (98%)
create mode 100644 mingw-w64-crt/stdio/msvcr80plus_ftruncate64.c
create mode 100644 mingw-w64-crt/stdio/msvcrtos_ftruncate64.c
diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 705624635acf..ca3e85264172 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -363,6 +363,7 @@ src_msvcrt=\
secapi/wmemmove_s.c \
stdio/_ftelli64.c \
stdio/mingw_lock.c \
+ stdio/msvcrtos_ftruncate64.c \
stdio/msvcr110pre_stat32.c \
stdio/msvcr110pre_stat64i32.c \
stdio/msvcr110pre_wstat32.c \
@@ -933,6 +934,7 @@ src_pre_msvcr80=\
stdio/_stat64i32.c \
stdio/_wstat64i32.c \
stdio/mingw_lock.c \
+ stdio/msvcr80pre_ftruncate64.c \
string/msvcr80pre_wcstok.c
src_pre_msvcr100=\
@@ -959,6 +961,7 @@ src_pre_msvcr120_post_msvcr71=\
misc/_iswblank_l.c
src_post_msvcr71=\
+ stdio/msvcr80plus_ftruncate64.c \
string/msvcr80plus_wcstok.c
src_post_msvcr80=\
@@ -1170,7 +1173,7 @@ src_libmingwex=\
stdio/strtok_r.c \
stdio/_Exit.c stdio/_findfirst64i32.c stdio/_findnext64i32.c
stdio/_wfindfirst64i32.c stdio/_wfindnext64i32.c \
stdio/asprintf.c \
- stdio/ftruncate64.c stdio/lltoa.c stdio/lltow.c \
+ stdio/mingw_ftruncate64.c stdio/lltoa.c stdio/lltow.c \
stdio/__mingw_fix_stat.h stdio/__mingw_fix_stat_finish.c \
stdio/__mingw_fix_stat_path.c stdio/__mingw_fix_wstat_path.c \
\
diff --git a/mingw-w64-crt/stdio/ftruncate64.c
b/mingw-w64-crt/stdio/mingw_ftruncate64.c
similarity index 98%
rename from mingw-w64-crt/stdio/ftruncate64.c
rename to mingw-w64-crt/stdio/mingw_ftruncate64.c
index ab50ad763fed..57a6b8476261 100644
--- a/mingw-w64-crt/stdio/ftruncate64.c
+++ b/mingw-w64-crt/stdio/mingw_ftruncate64.c
@@ -239,7 +239,7 @@ checkfreespace (const HANDLE f, const ULONGLONG
requiredspace)
return 0;
}
-int ftruncate64(int __fd, _off64_t __length) {
+int __cdecl __mingw_ftruncate64(int __fd, _off64_t __length) {
HANDLE f;
LARGE_INTEGER quad;
DWORD check;
@@ -306,6 +306,10 @@ int ftruncate64(int __fd, _off64_t __length) {
return -1;
}
+#ifdef TEST_FTRUNCATE64
+#define ftruncate64 __mingw_ftruncate64
+#endif
+
#if (TEST_FTRUNCATE64 == 1)
int main(){
LARGE_INTEGER sz;
diff --git a/mingw-w64-crt/stdio/msvcr80plus_ftruncate64.c
b/mingw-w64-crt/stdio/msvcr80plus_ftruncate64.c
new file mode 100644
index 000000000000..f9f9c3753960
--- /dev/null
+++ b/mingw-w64-crt/stdio/msvcr80plus_ftruncate64.c
@@ -0,0 +1,30 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <errno.h>
+#include <io.h>
+#include <unistd.h>
+
+int __cdecl ftruncate64(int fd, _off64_t length)
+{
+ errno_t error;
+
+ /* _chsize_s calls invalid parameter exception handler, so validate input
parameters */
+ if (fd < 0) {
+ errno = EBADF;
+ return -1;
+ }
+ if (length < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ error = _chsize_s(fd, length);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
diff --git a/mingw-w64-crt/stdio/msvcrtos_ftruncate64.c
b/mingw-w64-crt/stdio/msvcrtos_ftruncate64.c
new file mode 100644
index 000000000000..4f7965e741d2
--- /dev/null
+++ b/mingw-w64-crt/stdio/msvcrtos_ftruncate64.c
@@ -0,0 +1,47 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+
+#include <errno.h>
+#include <io.h>
+#include <unistd.h>
+
+#if defined(__i386__) || defined(__x86_64__)
+#include <windows.h>
+#include <msvcrt.h>
+#endif
+
+int __cdecl ftruncate64(int fd, _off64_t length)
+{
+ errno_t error;
+
+ /* Function symbol _chsize_s is available since Windows Vista, so load it
dynamically on x86 systems */
+#if defined(__i386__) || defined(__x86_64__)
+ extern int __cdecl __mingw_ftruncate64(int fd, _off64_t length);
+
+ static errno_t (__cdecl *volatile chsize_s_ptr)(int, __int64);
+ static volatile long init = 0;
+
+ if (!init) {
+ HMODULE msvcrt = __mingw_get_msvcrt_handle();
+ FARPROC func = msvcrt ? GetProcAddress(msvcrt, "_chsize_s") : NULL;
+ (void)InterlockedExchangePointer((PVOID volatile *)&chsize_s_ptr,
func);
+ (void)InterlockedExchange(&init, 1);
+ }
+
+ if (!chsize_s_ptr)
+ return __mingw_ftruncate64(fd, length);
+
+ #define _chsize_s chsize_s_ptr
+#endif
+
+ /* msvcrt.dll's _chsize_s does not call invalid parameter exception
handler, so it is not needed to validate input parameters */
+ error = _chsize_s(fd, length);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
--
2.20.1
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public