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