headers: Fix declaration of POSIX stat/fstat and LFS stat64/fstat64 functions

Move LFS defines of stat64/fstat64 from _mingw_stat64.h to sys/stat.h.
Move struct stat from _mingw_stat64.h to sys/stat.h.

Fix definition of POSIX struct stat to follow both _FILE_OFFSET_BITS and
_USE_32BIT_TIME_T settings.

Fix declaration of POSIX stat(), fstat() and mingw-w64 wstat() functions to
follow all combinations of _FILE_OFFSET_BITS and _USE_32BIT_TIME_T settings.

Declare fstat() as a function instead of macro. Define it as alias via
__MINGW_ASM_CALL to one of the CRT _fstat* function based on
_FILE_OFFSET_BITS and _USE_32BIT_TIME_T settings.

In the same way declare stat() and wstat() as functions. But as alias to
one of the mingw-w64 (w)stat* function. This is needed because msvcrt
_(w)stat* functions have issue with trailing slash and requires mingw-w64
wrapper for POSIX compatibility.

Additionally define struct stat64 for LFS functions stat64(), fstat64() and
mingw-w64 function wstat64(). And again declare them as a functions instead
of macro.

Keyword stat has to be declared as a function, not as a macro because it
would override effect of struct stat.

Do not declare these stat/fstat/wstat functions when building the mingw-w64
runtime itself as it is not clear which of those stat[size] / fstat[size] /
wstat[size] symbol should be used. Instead the mingw-w64 source file should
call the appropriate ABI compatible *stat[size] function with corresponding
ABI compatible struct _stat[size].

Signed-off-by: Martin Storsjö <martin@martin.st>
diff --git a/mingw-w64-crt/misc/crtdll_fstat.c b/mingw-w64-crt/misc/crtdll_fstat.c
index f0b3b74..2fe5b1e 100644
--- a/mingw-w64-crt/misc/crtdll_fstat.c
+++ b/mingw-w64-crt/misc/crtdll_fstat.c
@@ -24,5 +24,6 @@
 extern int __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_fstat32))))) (__cdecl *__MINGW_IMP_SYMBOL(_fstat))(int fd, struct _stat32 *stat);
 
 #undef fstat
+struct stat;
 int __attribute__ ((alias ("_fstat32"))) __cdecl fstat(int fd, struct stat *stat);
 extern int __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_fstat32))))) (__cdecl *__MINGW_IMP_SYMBOL(fstat))(int fd, struct stat *stat);
diff --git a/mingw-w64-crt/misc/ftw.c b/mingw-w64-crt/misc/ftw.c
index e87ab5e..f520ef6 100644
--- a/mingw-w64-crt/misc/ftw.c
+++ b/mingw-w64-crt/misc/ftw.c
@@ -15,10 +15,8 @@
 #include <dirent.h>
 #include <ftw.h>
 
-#undef stat64
 int __cdecl stat32(const char *_Filename, struct _stat32 *_Stat);
 int __cdecl stat32i64(const char *_Filename, struct _stat32i64 *_Stat);
-int __cdecl stat64(const char *_Filename, struct _stat64 *_Stat);
 int __cdecl stat64i32(const char *_Filename, struct _stat64i32 *_Stat);
 
 typedef struct dir_data_t {
diff --git a/mingw-w64-crt/misc/ftw64.c b/mingw-w64-crt/misc/ftw64.c
index 5595e76..72e22a2 100644
--- a/mingw-w64-crt/misc/ftw64.c
+++ b/mingw-w64-crt/misc/ftw64.c
@@ -6,5 +6,5 @@
 #define FUNC_FTW ftw64
 #define FUNC_NFTW nftw64
 #define FUNC_STAT stat64
-#define STRUCT_STAT struct _stat64
+#define STRUCT_STAT struct stat64
 #include "ftw.c"
diff --git a/mingw-w64-crt/stdio/_fstat64.c b/mingw-w64-crt/stdio/_fstat64.c
index 8df51a4..28c5d73 100644
--- a/mingw-w64-crt/stdio/_fstat64.c
+++ b/mingw-w64-crt/stdio/_fstat64.c
@@ -44,6 +44,5 @@
 #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 *);
+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
index 0f1c73f..930696f 100644
--- a/mingw-w64-crt/stdio/stat64.c
+++ b/mingw-w64-crt/stdio/stat64.c
@@ -9,14 +9,12 @@
 
 char *__mingw_fix_stat_path(const char *_path);
 
-#undef stat64
-int __cdecl stat64(const char *_Filename, struct _stat64 *_Stat);
-int __cdecl stat64(const char *_Filename, struct _stat64 *_Stat)
+int __cdecl stat64(const char *_Filename, struct stat64 *_Stat)
 {
   char *_path = __mingw_fix_stat_path(_Filename);
-  int ret = _stat64(_path, _Stat);
+  int ret = _stat64(_path, (struct _stat64 *)_Stat);
   if (_path != _Filename)
     free(_path);
   return ret;
 }
-int (__cdecl *__MINGW_IMP_SYMBOL(stat64))(const char *, struct _stat64 *) = stat64;
+int (__cdecl *__MINGW_IMP_SYMBOL(stat64))(const char *, struct stat64 *) = stat64;
diff --git a/mingw-w64-crt/stdio/wstat64.c b/mingw-w64-crt/stdio/wstat64.c
index 96b0475..a496a54 100644
--- a/mingw-w64-crt/stdio/wstat64.c
+++ b/mingw-w64-crt/stdio/wstat64.c
@@ -9,13 +9,12 @@
 
 wchar_t *__mingw_fix_wstat_path(const wchar_t *_path);
 
-int __cdecl wstat64(const wchar_t *_Filename, struct _stat64 *_Stat);
-int __cdecl wstat64(const wchar_t *_Filename, struct _stat64 *_Stat)
+int __cdecl wstat64(const wchar_t *_Filename, struct stat64 *_Stat)
 {
   wchar_t *_path = __mingw_fix_wstat_path(_Filename);
-  int ret = _wstat64(_path, _Stat);
+  int ret = _wstat64(_path, (struct _stat64 *)_Stat);
   if (_path != _Filename)
     free(_path);
   return ret;
 }
-int (__cdecl *__MINGW_IMP_SYMBOL(wstat64))(const wchar_t *, struct _stat64 *) = wstat64;
+int (__cdecl *__MINGW_IMP_SYMBOL(wstat64))(const wchar_t *, struct stat64 *) = wstat64;
diff --git a/mingw-w64-headers/crt/_mingw_stat64.h b/mingw-w64-headers/crt/_mingw_stat64.h
index 8ce0975..84eabba 100644
--- a/mingw-w64-headers/crt/_mingw_stat64.h
+++ b/mingw-w64-headers/crt/_mingw_stat64.h
@@ -1,5 +1,8 @@
 #ifndef _STAT_DEFINED
 
+/* __stat64 is needed for compatibility with msvc */
+#define __stat64 _stat64
+
 #ifdef _USE_32BIT_TIME_T
 #define _fstat _fstat32
 #define _fstati64 _fstat32i64
@@ -30,22 +33,6 @@
     __time32_t st_ctime;
   };
 
-#ifndef	NO_OLDNAMES
-  struct stat {
-    _dev_t st_dev;
-    _ino_t st_ino;
-    unsigned short st_mode;
-    short st_nlink;
-    short st_uid;
-    short st_gid;
-    _dev_t st_rdev;
-    _off_t st_size;
-    time_t st_atime;
-    time_t st_mtime;
-    time_t st_ctime;
-  };
-#endif /* NO_OLDNAMES */
-
   struct _stat32i64 {
     _dev_t st_dev;
     _ino_t st_ino;
@@ -88,9 +75,5 @@
     __time64_t st_ctime;
   };
 
-#define __stat64 _stat64
-#define stat64   _stat64  /* for POSIX */
-#define fstat64  _fstat64 /* for POSIX */
-
 #define _STAT_DEFINED
 #endif /* _STAT_DEFINED */
diff --git a/mingw-w64-headers/crt/sys/stat.h b/mingw-w64-headers/crt/sys/stat.h
index 0c133cd..5d2e6df 100644
--- a/mingw-w64-headers/crt/sys/stat.h
+++ b/mingw-w64-headers/crt/sys/stat.h
@@ -124,31 +124,69 @@
 
 #endif
 
-#if !defined (RC_INVOKED) && !defined (NO_OLDNAMES)
-int __cdecl fstat(int _Desc,struct stat *_Stat);
-#ifdef _UCRT
-  __mingw_ovr int __cdecl stat(const char *_Filename,struct stat *_Stat)
-  {
-    return _stat(_Filename, (struct _stat *)_Stat);
-  }
-  __mingw_ovr int __cdecl wstat(const wchar_t *_Filename,struct stat *_Stat)
-  {
-    return _wstat(_Filename, (struct _stat *)_Stat);
-  }
-#else
-int __cdecl stat(const char *_Filename,struct stat *_Stat);
-int __cdecl wstat(const wchar_t *_Filename,struct stat *_Stat);
-#endif
-#endif /* !RC_INVOKED && !NO_OLDNAMES */
+#if !defined(NO_OLDNAMES) || defined(_POSIX)
 
+/*
+ * When building mingw-w64 CRT files it is required that the fstat, stat and
+ * wstat functions are not declared with __MINGW_ASM_CALL redirection.
+ * Otherwise the mingw-w64 would provide broken fstat, stat and wstat symbols.
+ * To prevent ABI issues, the mingw-w64 runtime should not call the fstat,
+ * stat and wstat functions, instead it should call the fixed-size variants.
+ */
+#ifndef _CRTBLD
+struct stat {
+  _dev_t st_dev;
+  _ino_t st_ino;
+  unsigned short st_mode;
+  short st_nlink;
+  short st_uid;
+  short st_gid;
+  _dev_t st_rdev;
+  off_t st_size; /* off_t follows _FILE_OFFSET_BITS */
+  time_t st_atime; /* time_t follows _USE_32BIT_TIME_T */
+  time_t st_mtime;
+  time_t st_ctime;
+};
 #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
 #ifdef _USE_32BIT_TIME_T
-#define stat _stat32i64
-#define fstat _fstat32i64
+int __cdecl fstat(int _Desc, struct stat *_Stat) __MINGW_ASM_CALL(_fstat32i64);
+int __cdecl stat(const char *_Filename, struct stat *_Stat) __MINGW_ASM_CALL(stat32i64);
+int __cdecl wstat(const wchar_t *_Filename, struct stat *_Stat) __MINGW_ASM_CALL(wstat32i64);
 #else
-#define stat _stat64
-#define fstat _fstat64
+int __cdecl fstat(int _Desc, struct stat *_Stat) __MINGW_ASM_CALL(_fstat64);
+int __cdecl stat(const char *_Filename, struct stat *_Stat) __MINGW_ASM_CALL(stat64);
+int __cdecl wstat(const wchar_t *_Filename, struct stat *_Stat) __MINGW_ASM_CALL(wstat64);
 #endif
+#else
+#ifdef _USE_32BIT_TIME_T
+int __cdecl fstat(int _Desc, struct stat *_Stat) __MINGW_ASM_CALL(_fstat32);
+int __cdecl stat(const char *_Filename, struct stat *_Stat) __MINGW_ASM_CALL(stat32);
+int __cdecl wstat(const wchar_t *_Filename, struct stat *_Stat) __MINGW_ASM_CALL(wstat32);
+#else
+int __cdecl fstat(int _Desc, struct stat *_Stat) __MINGW_ASM_CALL(_fstat64i32);
+int __cdecl stat(const char *_Filename, struct stat *_Stat) __MINGW_ASM_CALL(stat64i32);
+int __cdecl wstat(const wchar_t *_Filename, struct stat *_Stat) __MINGW_ASM_CALL(wstat64i32);
+#endif
+#endif
+#endif
+
+struct stat64 {
+  _dev_t st_dev;
+  _ino_t st_ino;
+  unsigned short st_mode;
+  short st_nlink;
+  short st_uid;
+  short st_gid;
+  _dev_t st_rdev;
+  __MINGW_EXTENSION __int64 st_size;
+  __time64_t st_atime;
+  __time64_t st_mtime;
+  __time64_t st_ctime;
+};
+int __cdecl fstat64(int _Desc, struct stat64 *_Stat);
+int __cdecl stat64(const char *_Filename, struct stat64 *_Stat);
+int __cdecl wstat64(const wchar_t *_Filename, struct stat64 *_Stat);
+
 #endif
 
 #ifdef __cplusplus