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

Reply via email to