On Thu, 4 Dec 2025, Pali Rohár wrote:
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 d46f26c4d665..28443c73771a 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 1846a0f06855..d10c9f897a76 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..f9be2336bdef 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:
FWIW I wasn't familiar with this language extension. It's probably fine (and Clang seems to support it as well), but maybe it'd be worth pointing out that this isn't proper C in itself?
// Martin _______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
