These two 32-bit DLL libraries do not provide those wide stat and find
functions. Enable mingw-w64 emulation of them in import libraries.
For 32-bit builds these functions have also alternative names without
the "*32" suffix. Add also those symbol aliases.
---
 mingw-w64-crt/Makefile.am           |  3 ++
 mingw-w64-crt/stdio/_wfindfirst32.c |  6 +++
 mingw-w64-crt/stdio/_wfindnext32.c  |  6 +++
 mingw-w64-crt/stdio/_wstat32.c      | 58 ++++++++++++++++++++++++++++-
 4 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 6f6ac57fc60d..599cf21adea2 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -893,6 +893,9 @@ src_pre_msvcrt20=\
   misc/__timezone.c \
   misc/__tzname.c \
   stdio/_telli64.c \
+  stdio/_wfindfirst32.c \
+  stdio/_wfindnext32.c \
+  stdio/_wstat32.c \
   stdio/fgetws.c \
   stdio/fputws.c \
   stdio/iob_func.c
diff --git a/mingw-w64-crt/stdio/_wfindfirst32.c 
b/mingw-w64-crt/stdio/_wfindfirst32.c
index ea463acfc9d5..a22a97998357 100644
--- a/mingw-w64-crt/stdio/_wfindfirst32.c
+++ b/mingw-w64-crt/stdio/_wfindfirst32.c
@@ -17,3 +17,9 @@ intptr_t __cdecl _wfindfirst32(const wchar_t *_Filename, 
struct _wfinddata32_t *
   return ret;
 }
 intptr_t (__cdecl *__MINGW_IMP_SYMBOL(_wfindfirst32))(const wchar_t *, struct 
_wfinddata32_t *) = _wfindfirst32;
+
+#ifndef _WIN64
+#undef _wfindfirst
+intptr_t __attribute__ ((alias ("_wfindfirst32"))) __cdecl _wfindfirst(const 
char *, struct _wfinddata32_t *);
+extern intptr_t __attribute__ ((alias 
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_wfindfirst32))))) (__cdecl 
*__MINGW_IMP_SYMBOL(_wfindfirst))(const char *, struct _wfinddata32_t *);
+#endif
diff --git a/mingw-w64-crt/stdio/_wfindnext32.c 
b/mingw-w64-crt/stdio/_wfindnext32.c
index a84177ff767c..10cb39beda09 100644
--- a/mingw-w64-crt/stdio/_wfindnext32.c
+++ b/mingw-w64-crt/stdio/_wfindnext32.c
@@ -17,3 +17,9 @@ int __cdecl _wfindnext32(intptr_t _FindHandle, struct 
_wfinddata32_t *_FindData)
   return 0;
 }
 int (__cdecl *__MINGW_IMP_SYMBOL(_wfindnext32))(intptr_t, struct 
_wfinddata32_t *) = _wfindnext32;
+
+#ifndef _WIN64
+#undef _wfindnext
+int __attribute__ ((alias ("_wfindnext32"))) __cdecl _wfindnext(intptr_t, 
struct _wfinddata32_t *);
+extern int __attribute__ ((alias 
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_wfindnext32))))) (__cdecl 
*__MINGW_IMP_SYMBOL(_wfindnext))(intptr_t, struct _wfinddata32_t *);
+#endif
diff --git a/mingw-w64-crt/stdio/_wstat32.c b/mingw-w64-crt/stdio/_wstat32.c
index 8ef681a429c1..e9270809c06f 100644
--- a/mingw-w64-crt/stdio/_wstat32.c
+++ b/mingw-w64-crt/stdio/_wstat32.c
@@ -8,6 +8,11 @@
 #include <stdint.h>
 #include <errno.h>
 
+#ifndef _WIN64
+#include <fcntl.h>
+#include <windows.h>
+#endif
+
 /* When the file time does not fit into the st_Xtime field:
  *           crtdll-msvcr71   msvcr80+
  * st_Xtime       -1             -1
@@ -20,12 +25,12 @@
  * errno       no change     no change   EOVERFLOW
  * returns         0            -1          -1
  *
- * This file is used only for 64-bit msvcrt.dll builds.
  * The stat function on 32-bit system os msvcrt.dll behaves
  * like the msvcr80/msvcr90, so use this behavior.
  */
 int __cdecl _wstat32(const wchar_t *_Name,struct _stat32 *_Stat)
 {
+#ifdef _WIN64
   struct _stat64 st;
   int ret=_wstat64(_Name,&st);
   if (ret != 0)
@@ -44,5 +49,56 @@ int __cdecl _wstat32(const wchar_t *_Name,struct _stat32 
*_Stat)
   if (_Stat->st_atime == -1 || _Stat->st_mtime == -1 || _Stat->st_ctime == -1)
     errno = EINVAL;
   return 0;
+#else
+  /* mingw-w64 _wstat64() on 32-bit systems is implemented as wrapper around 
the _wstat32().
+   * Therefore mingw-w64 _wstat32() implementation cannot call _wstat64().
+   * This _wstat32 implementation uses _fstat32() with handle obtained from 
CreateFileW().
+   * _fstat requires only FILE_READ_ATTRIBUTES access and 
FILE_FLAG_BACKUP_SEMANTICS is
+   * required for opening directory via CreateFileW().
+   * Using just FILE_READ_ATTRIBUTES access allows to open also path which is 
was denied for
+   * reading by another process. msvcrt.dll _wstat32() also allows to be 
called on such path.
+   */
+  int fd;
+  int ret;
+  int err;
+  HANDLE handle;
+  handle = CreateFileW(_Name, FILE_READ_ATTRIBUTES, FILE_SHARE_VALID_FLAGS, 
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+  if (handle == INVALID_HANDLE_VALUE) {
+    switch (GetLastError()) {
+    case ERROR_PATH_NOT_FOUND:
+    case ERROR_FILE_NOT_FOUND:
+      errno = ENOENT;
+      break;
+    case ERROR_ACCESS_DENIED:
+    case ERROR_WRITE_PROTECT...ERROR_SHARING_BUFFER_EXCEEDED: /* gcc extension 
for case ranges: https://gcc.gnu.org/onlinedocs/gcc-3.0.4/gcc/Case-Ranges.html 
*/
+      errno = EACCES;
+      break;
+    case ERROR_NOT_ENOUGH_MEMORY:
+      errno = ENOMEM;
+      break;
+    default:
+      errno = EINVAL;
+      break;
+    }
+    return -1;
+  }
+  fd = _open_osfhandle((intptr_t)handle, O_RDONLY);
+  if (fd < 0) {
+    CloseHandle(handle);
+    return -1;
+  }
+  ret = _fstat32(fd, _Stat);
+  err = errno;
+  close(fd);
+  errno = err;
+  return ret;
+#endif
 }
 int (__cdecl *__MINGW_IMP_SYMBOL(_wstat32))(const wchar_t *, struct _stat32 *) 
= _wstat32;
+
+/* On 32-bit systems is _wstat ABI using 32-bit time_t and 32-bit off_t */
+#ifndef _WIN64
+#undef _wstat
+int __attribute__((alias("_wstat32"))) __cdecl _wstat(const wchar_t 
*_Name,struct _stat32 *_Stat);
+extern int 
__attribute__((alias(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_wstat32))))) 
(__cdecl *__MINGW_IMP_SYMBOL(_wstat))(const wchar_t *, struct _stat32 *);
+#endif
-- 
2.20.1



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

Reply via email to