These functions are available since msvcr70.dll. For older msvcrt versions
provide emulation via _fstat32(), _stat32() and _wstat32() functions. These
functions have only truncated 32-bit file size and timestamp support. Real
64-bit non-truncated file size and timestamp information is retrieved via
the WinAPI calls. For _stat64() and _wstat64() use FindFirstFile() call and
for _fstat64() use GetFileInformationByHandle() call. Same thing is doing
msvcrt DLL library for other stat functions.

Functions _fstat64() and _stat64() are already used by mingw-w64 crt, so
ensure that they are present in every CRT import library.
---
 mingw-w64-crt/Makefile.am                  |  8 +++-
 mingw-w64-crt/include/filetime_to_time64.h | 13 ++++++
 mingw-w64-crt/lib-common/msvcrt.def.in     |  6 +--
 mingw-w64-crt/stdio/_fstat64.c             | 50 ++++++++++++++++++++++
 mingw-w64-crt/stdio/_stat64.c              | 48 +++++++++++++++++++++
 mingw-w64-crt/stdio/_wstat64.c             | 48 +++++++++++++++++++++
 6 files changed, 169 insertions(+), 4 deletions(-)
 create mode 100644 mingw-w64-crt/include/filetime_to_time64.h
 create mode 100644 mingw-w64-crt/stdio/_fstat64.c
 create mode 100644 mingw-w64-crt/stdio/_stat64.c
 create mode 100644 mingw-w64-crt/stdio/_wstat64.c

diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index f2f1e6f8160a..f37a25cb83c6 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -522,11 +522,14 @@ src_msvcrt32=\
   misc/wcstoumax.c \
   misc/wctob.c \
   stdio/_fseeki64.c \
+  stdio/_fstat64.c \
   stdio/_fstat64i32.c \
   stdio/_scprintf.c \
   stdio/_scwprintf.c \
+  stdio/_stat64.c \
   stdio/_vscprintf.c \
   stdio/_vscwprintf.c \
+  stdio/_wstat64.c \
   string/wcstok.c
 
 # Files included in libmsvcrt-os.a (for msvcrt.dll) on x86_64
@@ -774,10 +777,13 @@ src_pre_msvcr70=\
   misc/strtoumax.c \
   misc/wcstoimax.c \
   misc/wcstoumax.c \
+  stdio/_fstat64.c \
   stdio/_scprintf.c \
   stdio/_scwprintf.c \
+  stdio/_stat64.c \
   stdio/_vscprintf.c \
-  stdio/_vscwprintf.c
+  stdio/_vscwprintf.c \
+  stdio/_wstat64.c
 
 src_pre_msvcr71=\
   misc/_set_purecall_handler.c
diff --git a/mingw-w64-crt/include/filetime_to_time64.h 
b/mingw-w64-crt/include/filetime_to_time64.h
new file mode 100644
index 000000000000..2d8459844a5f
--- /dev/null
+++ b/mingw-w64-crt/include/filetime_to_time64.h
@@ -0,0 +1,13 @@
+/**
+ * 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.
+ */
+
+static inline __time64_t filetime_to_time64(FILETIME *filetime)
+{
+    unsigned long long value = ((unsigned long long)filetime->dwHighDateTime 
<< 32) | filetime->dwLowDateTime;
+    if (value == 0) return 0; /* 0 has special meaning - not set */
+    /* conversion from unsigned 64-bit FILETIME (1601-01-01 in 
100-nanoseconds) to signed 64-bit UNIX timestamp (1970-01-01 in seconds) */
+    return (value - 116444736000000000LL) / 10000000;
+}
diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in 
b/mingw-w64-crt/lib-common/msvcrt.def.in
index 7a029b8d423a..afc6092f5bdc 100644
--- a/mingw-w64-crt/lib-common/msvcrt.def.in
+++ b/mingw-w64-crt/lib-common/msvcrt.def.in
@@ -1153,20 +1153,20 @@ F_I386(_chkesp)
 _ctime64
 _findfirst64
 _findnext64
-_fstat64
+F_NON_I386(_fstat64) ; i386 _fstat64 replaced by emu
 _ftime64
 _futime64
 _gmtime64
 _localtime64
 _mktime64
 F_X86_ANY(_osplatform DATA)
-_stat64
+F_NON_I386(_stat64) ; i386 _stat64 replaced by emu
 _time64
 _utime64
 _wctime64
 _wfindfirst64
 _wfindnext64
-_wstat64
+F_NON_I386(_wstat64) ; i386 _wstat64 replaced by emu
 _wutime64
 
 ; These symbols were added in Windows 2000 SP4 OS system version of msvcrt.dll
diff --git a/mingw-w64-crt/stdio/_fstat64.c b/mingw-w64-crt/stdio/_fstat64.c
new file mode 100644
index 000000000000..0c059499b7e7
--- /dev/null
+++ b/mingw-w64-crt/stdio/_fstat64.c
@@ -0,0 +1,50 @@
+/**
+ * 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.
+ */
+
+#define __CRT__NO_INLINE
+#include <sys/stat.h>
+#include <io.h>
+#include <windows.h>
+
+#include "filetime_to_time64.h"
+
+static int __cdecl emu__fstat64(int fd, struct _stat64 *stat)
+{
+    BY_HANDLE_FILE_INFORMATION fi;
+    struct _stat32 st;
+    int ret = _fstat32(fd, &st);
+    if (ret != 0)
+        return ret;
+    stat->st_dev = st.st_dev;
+    stat->st_ino = st.st_ino;
+    stat->st_mode = st.st_mode;
+    stat->st_nlink = st.st_nlink;
+    stat->st_uid = st.st_uid;
+    stat->st_gid = st.st_gid;
+    stat->st_rdev = st.st_rdev;
+    if (GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &fi)) {
+        stat->st_size = ((_off64_t)fi.nFileSizeHigh << 32) | fi.nFileSizeLow;
+        stat->st_atime = filetime_to_time64(&fi.ftLastAccessTime);
+        stat->st_mtime = filetime_to_time64(&fi.ftLastWriteTime);
+        stat->st_ctime = filetime_to_time64(&fi.ftCreationTime);
+    } else {
+        stat->st_size = st.st_size; /* truncated value */
+        stat->st_atime = st.st_atime; /* truncated value */
+        stat->st_mtime = st.st_mtime; /* truncated value */
+        stat->st_ctime = st.st_ctime; /* truncated value */
+    }
+    return 0;
+}
+
+#define RETT int
+#define FUNC _fstat64
+#define ARGS int fd, struct _stat64 *stat
+#define CALL fd, stat
+#include "msvcrt_or_emu_glue.h"
+
+#undef fstat64
+int __attribute__ ((alias ("_fstat64"))) __cdecl fstat64(int, struct _stat64 
*);
+extern int __attribute__ ((alias 
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_fstat64))))) (__cdecl 
*__MINGW_IMP_SYMBOL(fstat64))(int, struct _stat64 *);
diff --git a/mingw-w64-crt/stdio/_stat64.c b/mingw-w64-crt/stdio/_stat64.c
new file mode 100644
index 000000000000..71247f0e4eab
--- /dev/null
+++ b/mingw-w64-crt/stdio/_stat64.c
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+#define __CRT__NO_INLINE
+#include <sys/stat.h>
+#include <windows.h>
+
+#include "filetime_to_time64.h"
+
+static int __cdecl emu__stat64(const char *path, struct _stat64 *stat)
+{
+    HANDLE handle;
+    WIN32_FIND_DATAA fi;
+    struct _stat32 st;
+    int ret = _stat32(path, &st);
+    if (ret != 0)
+        return ret;
+    stat->st_dev = st.st_dev;
+    stat->st_ino = st.st_ino;
+    stat->st_mode = st.st_mode;
+    stat->st_nlink = st.st_nlink;
+    stat->st_uid = st.st_uid;
+    stat->st_gid = st.st_gid;
+    stat->st_rdev = st.st_rdev;
+    handle = FindFirstFileA(path, &fi);
+    if (handle != INVALID_HANDLE_VALUE) {
+        FindClose(handle);
+        stat->st_size = ((_off64_t)fi.nFileSizeHigh << 32) | fi.nFileSizeLow;
+        stat->st_atime = filetime_to_time64(&fi.ftLastAccessTime);
+        stat->st_mtime = filetime_to_time64(&fi.ftLastWriteTime);
+        stat->st_ctime = filetime_to_time64(&fi.ftCreationTime);
+    } else {
+        stat->st_size = st.st_size; /* truncated value */
+        stat->st_atime = st.st_atime; /* truncated value */
+        stat->st_mtime = st.st_mtime; /* truncated value */
+        stat->st_ctime = st.st_ctime; /* truncated value */
+    }
+    return 0;
+}
+
+#define RETT int
+#define FUNC _stat64
+#define ARGS const char *path, struct _stat64 *stat
+#define CALL path, stat
+#include "msvcrt_or_emu_glue.h"
diff --git a/mingw-w64-crt/stdio/_wstat64.c b/mingw-w64-crt/stdio/_wstat64.c
new file mode 100644
index 000000000000..9d5a39ebc79d
--- /dev/null
+++ b/mingw-w64-crt/stdio/_wstat64.c
@@ -0,0 +1,48 @@
+/**
+ * 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.
+ */
+
+#define __CRT__NO_INLINE
+#include <sys/stat.h>
+#include <windows.h>
+
+#include "filetime_to_time64.h"
+
+static int __cdecl emu__wstat64(const wchar_t *path, struct _stat64 *stat)
+{
+    HANDLE handle;
+    WIN32_FIND_DATAW fi;
+    struct _stat32 st;
+    int ret = _wstat32(path, &st);
+    if (ret != 0)
+        return ret;
+    stat->st_dev = st.st_dev;
+    stat->st_ino = st.st_ino;
+    stat->st_mode = st.st_mode;
+    stat->st_nlink = st.st_nlink;
+    stat->st_uid = st.st_uid;
+    stat->st_gid = st.st_gid;
+    stat->st_rdev = st.st_rdev;
+    handle = FindFirstFileW(path, &fi);
+    if (handle != INVALID_HANDLE_VALUE) {
+        FindClose(handle);
+        stat->st_size = ((_off64_t)fi.nFileSizeHigh << 32) | fi.nFileSizeLow;
+        stat->st_atime = filetime_to_time64(&fi.ftLastAccessTime);
+        stat->st_mtime = filetime_to_time64(&fi.ftLastWriteTime);
+        stat->st_ctime = filetime_to_time64(&fi.ftCreationTime);
+    } else {
+        stat->st_size = st.st_size; /* truncated value */
+        stat->st_atime = st.st_atime; /* truncated value */
+        stat->st_mtime = st.st_mtime; /* truncated value */
+        stat->st_ctime = st.st_ctime; /* truncated value */
+    }
+    return 0;
+}
+
+#define RETT int
+#define FUNC _wstat64
+#define ARGS const wchar_t *path, struct _stat64 *stat
+#define CALL path, stat
+#include "msvcrt_or_emu_glue.h"
-- 
2.20.1



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

Reply via email to