On Thursday 06 March 2025 21:40:55 Lasse Collin wrote: > On 2025-03-05 Pali Rohár wrote: > > As the discussion started, I decided to I looked at these issues. I > > have some WIP changes which defines 4 variants of each > > fstat/stat/wstat function, then provides also fstat, stat and wstat > > function declaration in header file via __MINGW_ASM_CALL redirect and > > also exports symbols from import library. With this way it behaves in > > the same way as ms _fstat/_stat/_wstat symbols and functions. This > > should address also the autoconf issue which is trying to use > > functions without including header file, and also ensure that > > "stat()" call will be 64-bit + 64-bit if both -D_TIME_BITS=64 and > > -D_FILE_OFFSET_BITS=64 are defined. At the same time I added > > emulation wrapper for _fstat64/_stat64/_wstat64 function via WinAPI > > fallback for older msvcrt libraries which do not have them. > > Sounds great. :-) > > > Do you want to look at my changes or test them? > > Yes, I'm interested. It might take a few days depending on how I have > time.
Ok. I'm sending 10 patches in the attachment. > > What I have not addressed is the bug in the _mingw_no_trailing_slash > > function which you described in the other email. > > Earlier I tried adding a check for malloc() failure and making stat() > fail with ENOTDIR if a slash had been removed and the result wasn't a > directory. These were fairly simple changes, so if you didn't implement > those, I can try on top of your patches. I let the whole slash function as is. Just I moved it into separate file as it was duplicated on more places Feel free to fix / improve it. > I'm not sure if it is worth adding support for removing more than one > slash at this point. It would need some care since the code has to keep > one slash in some cases (I don't want add new bugs). > > There's also one more tiny bug in the slash removal: with double-byte > code pages, the second byte of a double-byte character can be \. The > correct way to handle it would be using IsDBCSLeadByteEx like in > mingw-w64-crt/misc/dirname.c. That makes things more complicated. Or > one could maybe convert to wide char and call wstat(), but that's more > complicated too. I don't know if it's worth it in practice at this > point (UCRT doesn't need this code). > > One more tiny bug: mingw-w64-crt/misc/dirname.c calls AreFileApisANSI to > determine the filename code page, but it doesn't handle the UCRT UTF-8 > locale case. I wonder if it made sense to have a separate file for > "DWORD __mingw64_filesystem_cp(void)" which dirname.c and dirent.c > could use. The UTF-8 locale without UTF-8 manifest is hopefully not a > common use case though. > > -- > Lasse Collin
>From 7d1ffbf5a023e20a54bccac4b3e1beeb099a921b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Thu, 24 Oct 2024 21:09:47 +0200 Subject: [PATCH 01/10] crt: Provide emulation of _fstat64, _stat64 and _wstat64 functions 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 7ebbd7c306d8..1c0ea244bd0e 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -521,11 +521,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 @@ -773,10 +776,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 0d1223af5adb..fe1c8164234c 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 >From e39dbc4bbd4c7af869170c0cfaa7757f7602eefa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Sun, 2 Mar 2025 20:29:23 +0100 Subject: [PATCH 02/10] crt: Fix mingw-w64 emulation of _fstat64i32, _stat64i32 and _wstat64i32 functions All 64-bit CRT import libraries already provides _fstat64i32, _stat64i32 and _wstat64i32 function symbols. These symbols are either directly exported from 64-bit CRT DLL library or def file contains alias to other ABI compatible symbols (_fstat, _stat and _wstat). Also all functions _fstat64i32, _stat64i32 and _wstat64i32 are provided by msvcr80+ and UCRT, so ensure that mingw-w64 does not provide any replacement for msvcr80+ import libraries. And ensure that libmingwex.a library does not provide duplication of these symbols. For 32-bit pre-msvcr80 CRT import libraries provides mingw-w64 emulation via _fstat64, _stat64 and _wstat64, which just truncates 64-bit st_size (returned by _*stat64 function) to 32-bit st_size (which is ABI of _*stat64i32). Do not use any _mingw_no_trailing_slash workaround as for all these functions with underscore prefix, it is expected that behavior is same as for other stat functions with underscore prefix. --- mingw-w64-crt/Makefile.am | 10 +++- mingw-w64-crt/stdio/_fstat64i32.c | 18 ++++--- mingw-w64-crt/stdio/_stat64i32.c | 81 +++++-------------------------- mingw-w64-crt/stdio/_wstat64i32.c | 81 +++++-------------------------- 4 files changed, 41 insertions(+), 149 deletions(-) diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 1c0ea244bd0e..44ed43d48b79 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -526,9 +526,11 @@ src_msvcrt32=\ stdio/_scprintf.c \ stdio/_scwprintf.c \ stdio/_stat64.c \ + stdio/_stat64i32.c \ stdio/_vscprintf.c \ stdio/_vscwprintf.c \ stdio/_wstat64.c \ + stdio/_wstat64i32.c \ string/wcstok.c # Files included in libmsvcrt-os.a (for msvcrt.dll) on x86_64 @@ -610,6 +612,8 @@ src_msvcrtarm32=\ misc/__winitenv.c \ stdio/_fstat64i32.c \ stdio/_setmaxstdio.c \ + stdio/_stat64i32.c \ + stdio/_wstat64i32.c \ stdio/gets.c if !ENABLE_SOFTMATH @@ -809,6 +813,8 @@ src_pre_msvcr80=\ stdio/_fseeki64.c \ stdio/_fstat64i32.c \ stdio/_ftelli64.c \ + stdio/_stat64i32.c \ + stdio/_wstat64i32.c \ stdio/mingw_lock.c \ string/wcstok.c @@ -1005,8 +1011,8 @@ src_libmingwex=\ \ stdio/strtok_r.c \ stdio/_Exit.c stdio/_findfirst64i32.c stdio/_findnext64i32.c \ - stdio/_stat.c stdio/_stat64i32.c stdio/_wfindfirst64i32.c stdio/_wfindnext64i32.c \ - stdio/_wstat.c stdio/_wstat64i32.c stdio/asprintf.c \ + stdio/_stat.c stdio/_wfindfirst64i32.c stdio/_wfindnext64i32.c \ + stdio/_wstat.c stdio/asprintf.c \ stdio/fopen64.c stdio/fseeko32.c stdio/fseeko64.c stdio/ftello.c \ stdio/ftello64.c stdio/ftruncate64.c stdio/lltoa.c stdio/lltow.c stdio/lseek64.c \ \ diff --git a/mingw-w64-crt/stdio/_fstat64i32.c b/mingw-w64-crt/stdio/_fstat64i32.c index 57cc492d7731..93871c2f4717 100644 --- a/mingw-w64-crt/stdio/_fstat64i32.c +++ b/mingw-w64-crt/stdio/_fstat64i32.c @@ -1,3 +1,9 @@ +/** + * 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> @@ -5,10 +11,8 @@ int __cdecl _fstat64i32(int _FileDes,struct _stat64i32 *_Stat) { struct _stat64 st; int ret=_fstat64(_FileDes,&st); - if (ret == -1) { - memset(_Stat,0,sizeof(struct _stat64i32)); - return -1; - } + if (ret != 0) + return ret; _Stat->st_dev=st.st_dev; _Stat->st_ino=st.st_ino; _Stat->st_mode=st.st_mode; @@ -16,10 +20,10 @@ int __cdecl _fstat64i32(int _FileDes,struct _stat64i32 *_Stat) _Stat->st_uid=st.st_uid; _Stat->st_gid=st.st_gid; _Stat->st_rdev=st.st_rdev; - _Stat->st_size=(_off_t) st.st_size; /* 32bit size */ + _Stat->st_size=(_off_t) st.st_size; /* truncate 64-bit st_size to 32-bit */ _Stat->st_atime=st.st_atime; _Stat->st_mtime=st.st_mtime; _Stat->st_ctime=st.st_ctime; - return ret; + return 0; } - +int (__cdecl *__MINGW_IMP_SYMBOL(_fstat64i32))(int, struct _stat64i32 *) = _fstat64i32; diff --git a/mingw-w64-crt/stdio/_stat64i32.c b/mingw-w64-crt/stdio/_stat64i32.c index 19adf5b0ee19..90e5ee6a644f 100644 --- a/mingw-w64-crt/stdio/_stat64i32.c +++ b/mingw-w64-crt/stdio/_stat64i32.c @@ -1,77 +1,18 @@ -#define __CRT__NO_INLINE -#include <sys/stat.h> -#include <stdlib.h> - /** - * Returns _path without trailing slash if any - * - * - if _path has no trailing slash, the function returns it - * - if _path has a trailing slash, but is of the form C:/, then it returns it - * - otherwise, the function creates a new string, which is a copy of _path - * without the trailing slash. It is then the responsibility of the caller - * to free it. + * 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 char* -_mingw_no_trailing_slash (const char* _path) -{ - int len; - char *p; - - p = (char*)_path; - - if (_path && *_path) { - len = strlen (_path); - - /* Ignore X:\ */ - - if (len <= 1 || ((len == 2 || len == 3) && _path[1] == ':')) - return p; - - /* Check UNC \\abc\<name>\ */ - if ((_path[0] == '\\' || _path[0] == '/') - && (_path[1] == '\\' || _path[1] == '/')) - { - const char *r = &_path[2]; - while (*r != 0 && *r != '\\' && *r != '/') - ++r; - if (*r != 0) - ++r; - if (*r == 0) - return p; - while (*r != 0 && *r != '\\' && *r != '/') - ++r; - if (*r != 0) - ++r; - if (*r == 0) - return p; - } - - if (_path[len - 1] == '/' || _path[len - 1] == '\\') - { - p = (char*)malloc (len); - memcpy (p, _path, len - 1); - p[len - 1] = '\0'; - } - } - - return p; -} +#define __CRT__NO_INLINE +#include <sys/stat.h> int __cdecl _stat64i32(const char *_Name,struct _stat64i32 *_Stat) { struct _stat64 st; - char *_path = _mingw_no_trailing_slash(_Name); - - int ret=_stat64(_path,&st); - - if (_path != _Name) - free(_path); - - if (ret == -1) { - memset(_Stat,0,sizeof(struct _stat64i32)); - return -1; - } + int ret=_stat64(_Name,&st); + if (ret != 0) + return ret; _Stat->st_dev=st.st_dev; _Stat->st_ino=st.st_ino; _Stat->st_mode=st.st_mode; @@ -79,10 +20,10 @@ int __cdecl _stat64i32(const char *_Name,struct _stat64i32 *_Stat) _Stat->st_uid=st.st_uid; _Stat->st_gid=st.st_gid; _Stat->st_rdev=st.st_rdev; - _Stat->st_size=(_off_t) st.st_size; + _Stat->st_size=(_off_t) st.st_size; /* truncate 64-bit st_size to 32-bit */ _Stat->st_atime=st.st_atime; _Stat->st_mtime=st.st_mtime; _Stat->st_ctime=st.st_ctime; - return ret; + return 0; } - +int (__cdecl *__MINGW_IMP_SYMBOL(_stat64i32))(const char *, struct _stat64i32 *) = _stat64i32; diff --git a/mingw-w64-crt/stdio/_wstat64i32.c b/mingw-w64-crt/stdio/_wstat64i32.c index d6ee07a3d52e..846ed576bdc9 100644 --- a/mingw-w64-crt/stdio/_wstat64i32.c +++ b/mingw-w64-crt/stdio/_wstat64i32.c @@ -1,77 +1,18 @@ -#define __CRT__NO_INLINE -#include <sys/stat.h> -#include <stdlib.h> - /** - * Returns _path without trailing slash if any - * - * - if _path has no trailing slash, the function returns it - * - if _path has a trailing slash, but is of the form C:/, then it returns it - * - otherwise, the function creates a new string, which is a copy of _path - * without the trailing slash. It is then the responsibility of the caller - * to free it. + * 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 wchar_t* -_mingw_no_trailing_slash (const wchar_t* _path) -{ - int len; - wchar_t *p; - - p = (wchar_t*)_path; - - if (_path && *_path) { - len = wcslen (_path); - - /* Ignore X:\ */ - - if (len <= 1 || ((len == 2 || len == 3) && _path[1] == L':')) - return p; - - /* Check UNC \\abc\<name>\ */ - if ((_path[0] == L'\\' || _path[0] == L'/') - && (_path[1] == L'\\' || _path[1] == L'/')) - { - const wchar_t *r = &_path[2]; - while (*r != 0 && *r != L'\\' && *r != L'/') - ++r; - if (*r != 0) - ++r; - if (*r == 0) - return p; - while (*r != 0 && *r != L'\\' && *r != L'/') - ++r; - if (*r != 0) - ++r; - if (*r == 0) - return p; - } - - if (_path[len - 1] == L'/' || _path[len - 1] == L'\\') - { - p = (wchar_t*)malloc (len * sizeof(wchar_t)); - memcpy (p, _path, (len - 1) * sizeof(wchar_t)); - p[len - 1] = L'\0'; - } - } - - return p; -} +#define __CRT__NO_INLINE +#include <sys/stat.h> int __cdecl _wstat64i32(const wchar_t *_Name,struct _stat64i32 *_Stat) { struct _stat64 st; - wchar_t *_path = _mingw_no_trailing_slash(_Name); - - int ret=_wstat64(_path,&st); - - if (_path != _Name) - free(_path); - - if (ret == -1) { - memset(_Stat,0,sizeof(struct _stat64i32)); - return -1; - } + int ret=_wstat64(_Name,&st); + if (ret != 0) + return ret; _Stat->st_dev=st.st_dev; _Stat->st_ino=st.st_ino; _Stat->st_mode=st.st_mode; @@ -79,10 +20,10 @@ int __cdecl _wstat64i32(const wchar_t *_Name,struct _stat64i32 *_Stat) _Stat->st_uid=st.st_uid; _Stat->st_gid=st.st_gid; _Stat->st_rdev=st.st_rdev; - _Stat->st_size=(_off_t) st.st_size; + _Stat->st_size=(_off_t) st.st_size; /* truncate 64-bit st_size to 32-bit */ _Stat->st_atime=st.st_atime; _Stat->st_mtime=st.st_mtime; _Stat->st_ctime=st.st_ctime; - return ret; + return 0; } - +int (__cdecl *__MINGW_IMP_SYMBOL(_wstat64i32))(const wchar_t *, struct _stat64i32 *) = _wstat64i32; -- 2.20.1 >From d94e04c869a1b2014320e4da1e1d6f965615f842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Wed, 5 Mar 2025 23:10:39 +0100 Subject: [PATCH 03/10] crt: Provide emulation of _fstat32i64, _stat32i64 and _wstat32i64 functions Functions _fstat32i64 (alias of _fstati64), _stat32i64 (alias of _stati64) and _wstat32i64 (alias of _wstati64) are available since msvcrt40.dll. These functions returns 64-bit st_size and 32-bit file timestamps. For pre-msvcrt40 CRT import libraries provides mingw-w64 emulation of those functions via the _fstat64, _stat64 and _stat64 functions, which returns both st_size and file timestamps in 64-bit precision. --- mingw-w64-crt/Makefile.am | 3 +++ mingw-w64-crt/stdio/_fstat32i64.c | 33 +++++++++++++++++++++++++++++++ mingw-w64-crt/stdio/_stat32i64.c | 33 +++++++++++++++++++++++++++++++ mingw-w64-crt/stdio/_wstat32i64.c | 33 +++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 mingw-w64-crt/stdio/_fstat32i64.c create mode 100644 mingw-w64-crt/stdio/_stat32i64.c create mode 100644 mingw-w64-crt/stdio/_wstat32i64.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 44ed43d48b79..db3f0d565e89 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -762,6 +762,9 @@ src_pre_msvcrt40=\ misc/_dstbias.c \ misc/dummy__setusermatherr.c \ stdio/_filelengthi64.c \ + stdio/_fstat32i64.c \ + stdio/_stat32i64.c \ + stdio/_wstat32i64.c \ stdio/fgetpos.c \ stdio/fsetpos.c diff --git a/mingw-w64-crt/stdio/_fstat32i64.c b/mingw-w64-crt/stdio/_fstat32i64.c new file mode 100644 index 000000000000..a30dee49d47f --- /dev/null +++ b/mingw-w64-crt/stdio/_fstat32i64.c @@ -0,0 +1,33 @@ +/** + * 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> + +int __cdecl _fstat32i64(int _FileDes,struct _stat32i64 *_Stat) +{ + struct _stat64 st; + int ret=_fstat64(_FileDes,&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; + _Stat->st_size=st.st_size; + _Stat->st_atime=(__time32_t) st.st_atime; /* truncate 64-bit st_atime to 32-bit */ + _Stat->st_mtime=(__time32_t) st.st_mtime; /* truncate 64-bit st_mtime to 32-bit */ + _Stat->st_ctime=(__time32_t) st.st_ctime; /* truncate 64-bit st_ctime to 32-bit */ + return 0; +} +int (__cdecl *__MINGW_IMP_SYMBOL(_fstat32i64))(int, struct _stat32i64 *) = _fstat32i64; + +#undef _fstati64 +int __attribute__ ((alias ("_fstat32i64"))) __cdecl _fstati64(int, struct _stat32i64 *); +extern int __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_fstat32i64))))) (__cdecl *__MINGW_IMP_SYMBOL(_fstati64))(int, struct _stat32i64 *); diff --git a/mingw-w64-crt/stdio/_stat32i64.c b/mingw-w64-crt/stdio/_stat32i64.c new file mode 100644 index 000000000000..b83142f2a1df --- /dev/null +++ b/mingw-w64-crt/stdio/_stat32i64.c @@ -0,0 +1,33 @@ +/** + * 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> + +int __cdecl _stat32i64(const char *_Name,struct _stat32i64 *_Stat) +{ + struct _stat64 st; + int ret=_stat64(_Name,&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; + _Stat->st_size=st.st_size; + _Stat->st_atime=(__time32_t) st.st_atime; /* truncate 64-bit st_atime to 32-bit */ + _Stat->st_mtime=(__time32_t) st.st_mtime; /* truncate 64-bit st_mtime to 32-bit */ + _Stat->st_ctime=(__time32_t) st.st_ctime; /* truncate 64-bit st_ctime to 32-bit */ + return 0; +} +int (__cdecl *__MINGW_IMP_SYMBOL(_stat32i64))(const char *, struct _stat32i64 *) = _stat32i64; + +#undef _stati64 +int __attribute__ ((alias ("_stat32i64"))) __cdecl _stati64(const char *, struct _stat32i64 *); +extern int __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_stat32i64))))) (__cdecl *__MINGW_IMP_SYMBOL(_stati64))(const char *, struct _stat32i64 *); diff --git a/mingw-w64-crt/stdio/_wstat32i64.c b/mingw-w64-crt/stdio/_wstat32i64.c new file mode 100644 index 000000000000..a584363f0ce9 --- /dev/null +++ b/mingw-w64-crt/stdio/_wstat32i64.c @@ -0,0 +1,33 @@ +/** + * 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> + +int __cdecl _wstat32i64(const wchar_t *_Name,struct _stat32i64 *_Stat) +{ + struct _stat64 st; + int ret=_wstat64(_Name,&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; + _Stat->st_size=st.st_size; + _Stat->st_atime=(__time32_t) st.st_atime; /* truncate 64-bit st_atime to 32-bit */ + _Stat->st_mtime=(__time32_t) st.st_mtime; /* truncate 64-bit st_mtime to 32-bit */ + _Stat->st_ctime=(__time32_t) st.st_ctime; /* truncate 64-bit st_ctime to 32-bit */ + return 0; +} +int (__cdecl *__MINGW_IMP_SYMBOL(_wstat32i64))(const wchar_t *, struct _stat32i64 *) = _wstat32i64; + +#undef _wstati64 +int __attribute__ ((alias ("_wstat32i64"))) __cdecl _wstati64(const wchar_t *, struct _stat32i64 *); +extern int __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_wstat32i64))))) (__cdecl *__MINGW_IMP_SYMBOL(_wstati64))(const wchar_t *, struct _stat32i64 *); -- 2.20.1 >From 716b162cbba5de29b25c54aabe88555e8f5257c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Thu, 6 Mar 2025 23:42:39 +0100 Subject: [PATCH 04/10] headers: Remove broken inline stat() and fstat() functions Correct versions are provided by non-inline variants. To prevent code duplication and maintenance, remove those inline definitions completely instead of fixing them. --- mingw-w64-headers/crt/sys/stat.h | 84 -------------------------------- 1 file changed, 84 deletions(-) diff --git a/mingw-w64-headers/crt/sys/stat.h b/mingw-w64-headers/crt/sys/stat.h index 5a85c2c483b5..343bd1178a01 100644 --- a/mingw-w64-headers/crt/sys/stat.h +++ b/mingw-w64-headers/crt/sys/stat.h @@ -185,90 +185,6 @@ int __cdecl fstat(int _Desc,struct stat *_Stat); int __cdecl stat(const char *_Filename,struct stat *_Stat); int __cdecl wstat(const wchar_t *_Filename,struct stat *_Stat); #endif - -#ifndef __CRT__NO_INLINE -#ifdef _USE_32BIT_TIME_T -__CRT_INLINE int __cdecl - fstat(int _Desc,struct stat *_Stat) { - struct _stat32 st; - int __ret=_fstat32(_Desc,&st); - if (__ret == -1) { - memset(_Stat,0,sizeof(struct stat)); - return -1; - } - /* struct stat and struct _stat32 - are the same for this case. */ - memcpy(_Stat, &st, sizeof(struct _stat32)); - return __ret; -} -/* Disable it for making sure trailing slash issue is fixed. */ -#if 0 -__CRT_INLINE int __cdecl - stat(const char *_Filename,struct stat *_Stat) { - struct _stat32 st; - int __ret=_stat32(_Filename,&st); - if (__ret == -1) { - memset(_Stat,0,sizeof(struct stat)); - return -1; - } - /* struct stat and struct _stat32 - are the same for this case. */ - memcpy(_Stat, &st, sizeof(struct _stat32)); - return __ret; -} -#endif -#else -__CRT_INLINE int __cdecl - fstat(int _Desc,struct stat *_Stat) { - struct _stat64 st; - int __ret=_fstat64(_Desc,&st); - if (__ret == -1) { - memset(_Stat,0,sizeof(struct stat)); - return -1; - } - /* struct stat and struct _stat64i32 - are the same for this case. */ - _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; - _Stat->st_size=(_off_t) st.st_size; - _Stat->st_atime=st.st_atime; - _Stat->st_mtime=st.st_mtime; - _Stat->st_ctime=st.st_ctime; - return __ret; -} -/* Disable it for making sure trailing slash issue is fixed. */ -#if 0 -__CRT_INLINE int __cdecl - stat(const char *_Filename,struct stat *_Stat) { - struct _stat64 st; - int __ret=_stat64(_Filename,&st); - if (__ret == -1) { - memset(_Stat,0,sizeof(struct stat)); - return -1; - } - /* struct stat and struct _stat64i32 - are the same for this case. */ - _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; - _Stat->st_size=(_off_t) st.st_size; - _Stat->st_atime=st.st_atime; - _Stat->st_mtime=st.st_mtime; - _Stat->st_ctime=st.st_ctime; - return __ret; -} -#endif -#endif /* _USE_32BIT_TIME_T */ -#endif /* __CRT__NO_INLINE */ #endif /* !RC_INVOKED && !NO_OLDNAMES */ #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) -- 2.20.1 >From a3232dba329b2cefc3ffd27655b9e429ec5b3a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Mon, 3 Mar 2025 19:39:16 +0100 Subject: [PATCH 05/10] headers: Remove inline definition of _fstat64i32() and _stat64i32() functions These functions in sys/stat.h are defined as wrappers around _fstat64() and _stat64() functions. But msvcr80+ and UCRT DLL libraries provides native _fstat64i32() and _stat64i32() functions and so it is not needed to use inline fallback wrappers. For pre-msvcr80 builds, mingw-w64 already provides fallback implementations in all CRT import libraries. So remove inline definition of _fstat64i32() and _stat64i32() functions as they are not needed and for msvcr80+ just prevents using them natively. --- mingw-w64-headers/crt/sys/stat.h | 46 -------------------------------- 1 file changed, 46 deletions(-) diff --git a/mingw-w64-headers/crt/sys/stat.h b/mingw-w64-headers/crt/sys/stat.h index 343bd1178a01..7f2ab7ab0d03 100644 --- a/mingw-w64-headers/crt/sys/stat.h +++ b/mingw-w64-headers/crt/sys/stat.h @@ -71,55 +71,9 @@ extern "C" { _CRTIMP int __cdecl _fstat64(int _FileDes,struct _stat64 *_Stat); _CRTIMP int __cdecl _fstat32i64(int _FileDes,struct _stat32i64 *_Stat); int __cdecl _fstat64i32(int _FileDes,struct _stat64i32 *_Stat); -#ifndef __CRT__NO_INLINE - __CRT_INLINE int __cdecl _fstat64i32(int _FileDes,struct _stat64i32 *_Stat) - { - struct _stat64 st; - int __ret=_fstat64(_FileDes,&st); - if (__ret == -1) { - memset(_Stat,0,sizeof(struct _stat64i32)); - return -1; - } - _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; - _Stat->st_size=(_off_t) st.st_size; - _Stat->st_atime=st.st_atime; - _Stat->st_mtime=st.st_mtime; - _Stat->st_ctime=st.st_ctime; - return __ret; - } -#endif /* __CRT__NO_INLINE */ _CRTIMP int __cdecl _stat64(const char *_Name,struct _stat64 *_Stat); _CRTIMP int __cdecl _stat32i64(const char *_Name,struct _stat32i64 *_Stat); int __cdecl _stat64i32(const char *_Name,struct _stat64i32 *_Stat); -#ifndef __CRT__NO_INLINE - __CRT_INLINE int __cdecl _stat64i32(const char *_Name,struct _stat64i32 *_Stat) - { - struct _stat64 st; - int __ret=_stat64(_Name,&st); - if (__ret == -1) { - memset(_Stat,0,sizeof(struct _stat64i32)); - return -1; - } - _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; - _Stat->st_size=(_off_t) st.st_size; - _Stat->st_atime=st.st_atime; - _Stat->st_mtime=st.st_mtime; - _Stat->st_ctime=st.st_ctime; - return __ret; - } -#endif /* __CRT__NO_INLINE */ #ifndef _WSTAT_DEFINED #define _WSTAT_DEFINED -- 2.20.1 >From fd906099b973dee21b5b452708fa539eced53394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Mon, 3 Mar 2025 19:44:12 +0100 Subject: [PATCH 06/10] headers: Add missing _CRTIMP for _fstat64i32/_stat64i32/_wstat64i32 functions All other _*stat* functions are already marked with _CRTIMP, so add it also for missing 3 functions. --- mingw-w64-headers/crt/sys/stat.h | 6 +++--- mingw-w64-headers/crt/wchar.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mingw-w64-headers/crt/sys/stat.h b/mingw-w64-headers/crt/sys/stat.h index 7f2ab7ab0d03..b972a0af4444 100644 --- a/mingw-w64-headers/crt/sys/stat.h +++ b/mingw-w64-headers/crt/sys/stat.h @@ -70,16 +70,16 @@ extern "C" { _CRTIMP int __cdecl _stat32(const char *_Name,struct _stat32 *_Stat); _CRTIMP int __cdecl _fstat64(int _FileDes,struct _stat64 *_Stat); _CRTIMP int __cdecl _fstat32i64(int _FileDes,struct _stat32i64 *_Stat); - int __cdecl _fstat64i32(int _FileDes,struct _stat64i32 *_Stat); + _CRTIMP int __cdecl _fstat64i32(int _FileDes,struct _stat64i32 *_Stat); _CRTIMP int __cdecl _stat64(const char *_Name,struct _stat64 *_Stat); _CRTIMP int __cdecl _stat32i64(const char *_Name,struct _stat32i64 *_Stat); - int __cdecl _stat64i32(const char *_Name,struct _stat64i32 *_Stat); + _CRTIMP int __cdecl _stat64i32(const char *_Name,struct _stat64i32 *_Stat); #ifndef _WSTAT_DEFINED #define _WSTAT_DEFINED _CRTIMP int __cdecl _wstat32(const wchar_t *_Name,struct _stat32 *_Stat); _CRTIMP int __cdecl _wstat32i64(const wchar_t *_Name,struct _stat32i64 *_Stat); - int __cdecl _wstat64i32(const wchar_t *_Name,struct _stat64i32 *_Stat); + _CRTIMP int __cdecl _wstat64i32(const wchar_t *_Name,struct _stat64i32 *_Stat); _CRTIMP int __cdecl _wstat64(const wchar_t *_Name,struct _stat64 *_Stat); #endif diff --git a/mingw-w64-headers/crt/wchar.h b/mingw-w64-headers/crt/wchar.h index a5821e4bd3d6..1b61f9d33f8f 100644 --- a/mingw-w64-headers/crt/wchar.h +++ b/mingw-w64-headers/crt/wchar.h @@ -258,7 +258,7 @@ _CRTIMP FILE *__cdecl __acrt_iob_func(unsigned index); _CRTIMP int __cdecl _wstat32(const wchar_t *_Name,struct _stat32 *_Stat); _CRTIMP int __cdecl _wstat32i64(const wchar_t *_Name,struct _stat32i64 *_Stat); - int __cdecl _wstat64i32(const wchar_t *_Name,struct _stat64i32 *_Stat); + _CRTIMP int __cdecl _wstat64i32(const wchar_t *_Name,struct _stat64i32 *_Stat); _CRTIMP int __cdecl _wstat64(const wchar_t *_Name,struct _stat64 *_Stat); #endif #endif -- 2.20.1 >From caefb1c5cc3be7e26fec94dbc771b18e0a9c3f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Tue, 4 Mar 2025 00:34:08 +0100 Subject: [PATCH 07/10] crt: Fix mingw-w64 emulation of POSIX stat* functions POSIX struct stat has 4 variants in mingw-w64 based on the _FILE_OFFSET_BITS and _USE_32BIT_TIME_T settings. st_size can be either 32-bit or 64-bit, and st_atime/st_mtime/st_ctime can also be 32-bit or 64-bit. So for each ABI of struct stat there has to be separate POSIX stat function which correctly fills either 32-bit or 64-bit st_* values. To follow existing msvcrt/UCRT symbol naming convention, provide 4 symbols for stat function: stat32, stat32i64, stat64i32 and stat64. And also provide stat symbol as alias to stat32 on 32-bit systems or to stat64i32 on 64-bit systems. Same as existing msvcrt/UCRT ABI for _stat function. Note that stat64 function is part of the Large File Specification but it does not describe if the st_atime/st_mtime/st_ctime should be also 64-bit or only 32-bit. msvcrt/UCRT ABI expects them to be also 64-bit. Do same for wstat symbol, wide UTF-16 variant of stat. At the same time remove old and broken stat and wstat symbols, they are replaced by the new alias. Extract existing and duplicated function _mingw_no_trailing_slash into new file and rename it to __mingw_fix_stat_path which better describe its purpose. Do same for wide variant __mingw_fix_wstat_path. These two functions have some known bugs and will be fixed later. This change is not fixing bugs in these functions, it is only fixing the API/ABI incompatibility which comes from the _FILE_OFFSET_BITS and _USE_32BIT_TIME_T settings. --- mingw-w64-crt/Makefile.am | 14 +++- mingw-w64-crt/def-include/crt-aliases.def.in | 28 +++++++- .../api-ms-win-crt-filesystem-l1-1-0.def.in | 13 ++++ .../{_stat.c => __mingw_fix_stat_path.c} | 71 +++---------------- .../{_wstat.c => __mingw_fix_wstat_path.c} | 70 +++--------------- mingw-w64-crt/stdio/stat32.c | 29 ++++++++ mingw-w64-crt/stdio/stat32i64.c | 22 ++++++ mingw-w64-crt/stdio/stat64.c | 23 ++++++ mingw-w64-crt/stdio/stat64i32.c | 29 ++++++++ mingw-w64-crt/stdio/wstat32.c | 30 ++++++++ mingw-w64-crt/stdio/wstat32i64.c | 22 ++++++ mingw-w64-crt/stdio/wstat64.c | 22 ++++++ mingw-w64-crt/stdio/wstat64i32.c | 30 ++++++++ 13 files changed, 273 insertions(+), 130 deletions(-) rename mingw-w64-crt/stdio/{_stat.c => __mingw_fix_stat_path.c} (42%) rename mingw-w64-crt/stdio/{_wstat.c => __mingw_fix_wstat_path.c} (45%) create mode 100644 mingw-w64-crt/stdio/stat32.c create mode 100644 mingw-w64-crt/stdio/stat32i64.c create mode 100644 mingw-w64-crt/stdio/stat64.c create mode 100644 mingw-w64-crt/stdio/stat64i32.c create mode 100644 mingw-w64-crt/stdio/wstat32.c create mode 100644 mingw-w64-crt/stdio/wstat32i64.c create mode 100644 mingw-w64-crt/stdio/wstat64.c create mode 100644 mingw-w64-crt/stdio/wstat64i32.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index db3f0d565e89..3f75c8958b71 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -181,6 +181,14 @@ src_msvcrt_common=\ stdio/vsnwprintf_alias.c \ stdio/vswprintf.c \ stdio/vswprintf_alias.c \ + stdio/stat32.c \ + stdio/stat32i64.c \ + stdio/stat64.c \ + stdio/stat64i32.c \ + stdio/wstat32.c \ + stdio/wstat32i64.c \ + stdio/wstat64.c \ + stdio/wstat64i32.c \ math/cbrt.c math/cbrtf.c \ math/copysign.c math/copysignf.c \ math/coshf.c \ @@ -1013,11 +1021,11 @@ src_libmingwex=\ ssp/stpcpy_chk.c ssp/strcpy_chk.c ssp/strncat_chk.c ssp/strncpy_chk.c \ \ stdio/strtok_r.c \ - stdio/_Exit.c stdio/_findfirst64i32.c stdio/_findnext64i32.c \ - stdio/_stat.c stdio/_wfindfirst64i32.c stdio/_wfindnext64i32.c \ - stdio/_wstat.c stdio/asprintf.c \ + stdio/_Exit.c stdio/_findfirst64i32.c stdio/_findnext64i32.c stdio/_wfindfirst64i32.c stdio/_wfindnext64i32.c \ + stdio/asprintf.c \ stdio/fopen64.c stdio/fseeko32.c stdio/fseeko64.c stdio/ftello.c \ stdio/ftello64.c stdio/ftruncate64.c stdio/lltoa.c stdio/lltow.c stdio/lseek64.c \ + stdio/__mingw_fix_stat_path.c stdio/__mingw_fix_wstat_path.c \ \ stdio/mingw_pformat.h mingw_sformat.h mingw_swformat.h \ stdio/mingw_fprintf.c stdio/mingw_fwprintf.c stdio/mingw_fscanf.c stdio/mingw_fwscanf.c stdio/mingw_pformat.c \ diff --git a/mingw-w64-crt/def-include/crt-aliases.def.in b/mingw-w64-crt/def-include/crt-aliases.def.in index be873c0df376..e4a401c1ef3c 100644 --- a/mingw-w64-crt/def-include/crt-aliases.def.in +++ b/mingw-w64-crt/def-include/crt-aliases.def.in @@ -137,8 +137,11 @@ ADD_UNDERSCORE(spawnve) ADD_UNDERSCORE(spawnvp) ADD_UNDERSCORE(spawnvpe) #endif -#ifndef CRTDLL -; stat is provided by mingw to workaround trailing slash issue in _stat +#ifdef UCRTBASE +F32(stat == _stat32) +F64(stat == _stat64i32) +#else +; stat for non-UCRT is provided by mingw to workaround trailing slash issue in _stat #endif #ifdef NO_STRCMPI_ALIAS ; Symbol _strcmpi is natively present and defined in the library def file @@ -290,6 +293,18 @@ ADD_UNDERSCORE(popen) fgetpos64 == fgetpos fsetpos64 == fsetpos #endif +#ifdef UCRTBASE +stat64 == _stat64 +#else +; stat for non-UCRT is provided by mingw to workaround trailing slash issue in _stat +#endif +#ifdef FIXED_SIZE_SYMBOLS +#if !defined(NO_I64_FIXED_SIZE) && !defined(NO_FIXED_SIZE_64_ALIAS) +F64(fstat64 == _fstati64) +#endif +#else +fstat64 == _fstat64 +#endif ; This is list of symbol aliases for GNU functions which are not part of POSIX or ISO C strcasecmp == _stricmp @@ -558,6 +573,15 @@ __ms_vwscanf == vwscanf ; This is list of additional symbol aliases not available in any library as neither native symbols nor aliases ; FIXME: check if these really are needed +; This is wstat and wstat64 symbol available only in mingw but for a long time +#ifdef UCRTBASE +F32(wstat == _wstat32) +F64(wstat == _wstat64i32) +wstat64 == _wstat64 +#else +; wstat for non-UCRT is provided by mingw to workaround trailing slash issue in _wstat +#endif + ; Origin of the symbol wcscmpi is unknown. This symbol is not present in ; crtdll.dll and neither in any msvcr* version. The only source of wcscmpi is ; wcstr.h header file from the Microsoft Visual C++ 1.0 (32-bit for NT) and diff --git a/mingw-w64-crt/lib-common/api-ms-win-crt-filesystem-l1-1-0.def.in b/mingw-w64-crt/lib-common/api-ms-win-crt-filesystem-l1-1-0.def.in index 684baf712dcf..a0665a3a3d31 100644 --- a/mingw-w64-crt/lib-common/api-ms-win-crt-filesystem-l1-1-0.def.in +++ b/mingw-w64-crt/lib-common/api-ms-win-crt-filesystem-l1-1-0.def.in @@ -39,6 +39,7 @@ F64(_fstati64 == _fstat64) _fstat32 _fstat32i64 _fstat64 +fstat64 == _fstat64 _fstat64i32 _fullpath _getdiskfree @@ -53,14 +54,20 @@ _rmdir rmdir == _rmdir _splitpath _splitpath_s +F32(stat == _stat32) +F64(stat == _stat64i32) F32(_stat == _stat32) F64(_stat == _stat64i32) F32(_stati64 == _stat32i64) F64(_stati64 == _stat64) _stat32 +stat32 == _stat32 _stat32i64 +stat32i64 == _stat32i64 _stat64 +stat64 == _stat64 _stat64i32 +stat64i32 == _stat64i32 _umask umask == _umask _umask_s @@ -96,14 +103,20 @@ _wrename _wrmdir _wsplitpath _wsplitpath_s +F32(wstat == _wstat32) +F64(wstat == _wstat64i32) F32(_wstat == _wstat32) F64(_wstat == _wstat64i32) F32(_wstati64 == _wstat32i64) F64(_wstati64 == _wstat64) _wstat32 +wstat32 == _wstat32 _wstat32i64 +wstat32i64 == _wstat32i64 _wstat64 +wstat64 == _wstat64 _wstat64i32 +wstat64i32 == _wstat64i32 _wunlink remove rename diff --git a/mingw-w64-crt/stdio/_stat.c b/mingw-w64-crt/stdio/__mingw_fix_stat_path.c similarity index 42% rename from mingw-w64-crt/stdio/_stat.c rename to mingw-w64-crt/stdio/__mingw_fix_stat_path.c index fbb985e389e9..1efb3fea3da9 100644 --- a/mingw-w64-crt/stdio/_stat.c +++ b/mingw-w64-crt/stdio/__mingw_fix_stat_path.c @@ -1,3 +1,9 @@ +/** + * 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 <stdlib.h> @@ -12,8 +18,8 @@ * to free it. */ -static char* -_mingw_no_trailing_slash (const char* _path) +char* __mingw_fix_stat_path (const char* _path); +char* __mingw_fix_stat_path (const char* _path) { int len; char *p; @@ -57,64 +63,3 @@ _mingw_no_trailing_slash (const char* _path) return p; } -/* FIXME: Relying on _USE_32BIT_TIME_T, which is a user-macro, -during CRT compilation is plainly broken. Need an appropriate -implementation to provide users the ability of compiling the -CRT only with 32-bit time_t behavior. */ -#if defined(_USE_32BIT_TIME_T) -int __cdecl -stat(const char *_Filename,struct stat *_Stat) -{ - struct _stat32 st; - char *_path = _mingw_no_trailing_slash(_Filename); - - int ret=_stat32(_path,&st); - - if (_path != _Filename) - free (_path); - - if (ret == -1) { - memset(_Stat,0,sizeof(struct stat)); - return -1; - } - /* struct stat and struct _stat32 - are the same for this case. */ - memcpy(_Stat, &st, sizeof(struct _stat32)); - return ret; -} -#else -int __cdecl -stat(const char *_Filename,struct stat *_Stat) -{ - struct _stat64 st; - char *_path = _mingw_no_trailing_slash(_Filename); - - int ret=_stat64(_path,&st); - - if (_path != _Filename) - free (_path); - - if (ret == -1) { - memset(_Stat,0,sizeof(struct stat)); - return -1; - } - /* struct stat and struct _stat64i32 - are the same for this case. */ - _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; - _Stat->st_size=(_off_t) st.st_size; - _Stat->st_atime=st.st_atime; - _Stat->st_mtime=st.st_mtime; - _Stat->st_ctime=st.st_ctime; - return ret; -} -#endif - -/* Add __imp__fstat and __imp__stat symbols. */ -int (*__MINGW_IMP_SYMBOL(stat))(const char *,struct stat *) = &stat; - diff --git a/mingw-w64-crt/stdio/_wstat.c b/mingw-w64-crt/stdio/__mingw_fix_wstat_path.c similarity index 45% rename from mingw-w64-crt/stdio/_wstat.c rename to mingw-w64-crt/stdio/__mingw_fix_wstat_path.c index 08566168fbe5..a121911faf6c 100644 --- a/mingw-w64-crt/stdio/_wstat.c +++ b/mingw-w64-crt/stdio/__mingw_fix_wstat_path.c @@ -1,7 +1,12 @@ +/** + * 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 <stdlib.h> -#include <malloc.h> /** * Returns _path without trailing slash if any @@ -13,8 +18,8 @@ * to free it. */ -static wchar_t* -_mingw_no_trailing_slash (const wchar_t* _path) +wchar_t* __mingw_fix_stat_path (wchar_t* _path); +wchar_t* __mingw_fix_stat_path (wchar_t* _path) { int len; wchar_t *p; @@ -58,62 +63,3 @@ _mingw_no_trailing_slash (const wchar_t* _path) return p; } - -/* FIXME: Relying on _USE_32BIT_TIME_T, which is a user-macro, -during CRT compilation is plainly broken. Need an appropriate -implementation to provide users the ability of compiling the -CRT only with 32-bit time_t behavior. */ -#if defined(_USE_32BIT_TIME_T) -int __cdecl -wstat(const wchar_t *_Filename,struct stat *_Stat) -{ - struct _stat32 st; - wchar_t *_path = _mingw_no_trailing_slash(_Filename); - - int ret=_wstat32(_path,&st); - - if (_path != _Filename) - free (_path); - - if (ret == -1) { - memset(_Stat,0,sizeof(struct stat)); - return -1; - } - /* struct stat and struct _stat32 - are the same for this case. */ - memcpy(_Stat, &st, sizeof(struct _stat32)); - return ret; -} -#else -int __cdecl -wstat(const wchar_t *_Filename,struct stat *_Stat) -{ - struct _stat64 st; - wchar_t *_path = _mingw_no_trailing_slash(_Filename); - - int ret=_wstat64(_path,&st); - - if (_path != _Filename) - free (_path); - - if (ret == -1) { - memset(_Stat,0,sizeof(struct stat)); - return -1; - } - /* struct stat and struct _stat64i32 - are the same for this case. */ - _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; - _Stat->st_size=(_off_t) st.st_size; - _Stat->st_atime=st.st_atime; - _Stat->st_mtime=st.st_mtime; - _Stat->st_ctime=st.st_ctime; - return ret; -} -#endif - diff --git a/mingw-w64-crt/stdio/stat32.c b/mingw-w64-crt/stdio/stat32.c new file mode 100644 index 000000000000..be3e4694b83f --- /dev/null +++ b/mingw-w64-crt/stdio/stat32.c @@ -0,0 +1,29 @@ +/** + * 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 <stdlib.h> + +char *__mingw_fix_stat_path(const char *_path); + +int __cdecl stat32(const char *_Filename, struct _stat32 *_Stat); +int __cdecl stat32(const char *_Filename, struct _stat32 *_Stat) +{ + char *_path = __mingw_fix_stat_path(_Filename); + int ret = _stat32(_path, _Stat); + if (_path != _Filename) + free(_path); + return ret; +} +int (__cdecl *__MINGW_IMP_SYMBOL(stat32))(const char *, struct _stat32 *) = stat32; + +/* On 32-bit systems is stat() function ABI compatible with stat32() function */ +#ifndef _WIN64 +#undef stat +int __attribute__ ((alias ("stat32"))) __cdecl stat(const char *name, struct stat *stat); +extern int __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(stat32))))) (__cdecl *__MINGW_IMP_SYMBOL(stat))(const char *name, struct stat *stat); +#endif diff --git a/mingw-w64-crt/stdio/stat32i64.c b/mingw-w64-crt/stdio/stat32i64.c new file mode 100644 index 000000000000..f853d7a3f25f --- /dev/null +++ b/mingw-w64-crt/stdio/stat32i64.c @@ -0,0 +1,22 @@ +/** + * 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 <stdlib.h> + +char *__mingw_fix_stat_path(const char *_path); + +int __cdecl stat32i64(const char *_Filename, struct _stat32i64 *_Stat); +int __cdecl stat32i64(const char *_Filename, struct _stat32i64 *_Stat) +{ + char *_path = __mingw_fix_stat_path(_Filename); + int ret = _stat32i64(_path, _Stat); + if (_path != _Filename) + free(_path); + return ret; +} +int (__cdecl *__MINGW_IMP_SYMBOL(stat32i64))(const char *, struct _stat32i64 *) = stat32i64; diff --git a/mingw-w64-crt/stdio/stat64.c b/mingw-w64-crt/stdio/stat64.c new file mode 100644 index 000000000000..2e1d66ebc3fd --- /dev/null +++ b/mingw-w64-crt/stdio/stat64.c @@ -0,0 +1,23 @@ +/** + * 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 <stdlib.h> + +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) +{ + char *_path = __mingw_fix_stat_path(_Filename); + int ret = _stat64(_path, _Stat); + if (_path != _Filename) + free(_path); + return ret; +} +int (__cdecl *__MINGW_IMP_SYMBOL(stat64))(const char *, struct _stat64 *) = stat64; diff --git a/mingw-w64-crt/stdio/stat64i32.c b/mingw-w64-crt/stdio/stat64i32.c new file mode 100644 index 000000000000..66f069722f12 --- /dev/null +++ b/mingw-w64-crt/stdio/stat64i32.c @@ -0,0 +1,29 @@ +/** + * 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 <stdlib.h> + +char *__mingw_fix_stat_path(const char *_path); + +int __cdecl stat64i32(const char *_Filename, struct _stat64i32 *_Stat); +int __cdecl stat64i32(const char *_Filename, struct _stat64i32 *_Stat) +{ + char *_path = __mingw_fix_stat_path(_Filename); + int ret = _stat64i32(_path, _Stat); + if (_path != _Filename) + free(_path); + return ret; +} +int (__cdecl *__MINGW_IMP_SYMBOL(stat64i32))(const char *, struct _stat64i32 *) = stat64i32; + +/* On 64-bit systems is stat() function ABI compatible with stat64i32() function */ +#ifdef _WIN64 +#undef stat +int __attribute__ ((alias ("stat64i32"))) __cdecl stat(const char *name, struct stat *stat); +extern int __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(stat64i32))))) (__cdecl *__MINGW_IMP_SYMBOL(stat))(const char *name, struct stat *stat); +#endif diff --git a/mingw-w64-crt/stdio/wstat32.c b/mingw-w64-crt/stdio/wstat32.c new file mode 100644 index 000000000000..41e3b1c85550 --- /dev/null +++ b/mingw-w64-crt/stdio/wstat32.c @@ -0,0 +1,30 @@ +/** + * 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 <stdlib.h> + +wchar_t *__mingw_fix_wstat_path(const wchar_t *_path); + +int __cdecl wstat32(const wchar_t *_Filename, struct _stat32 *_Stat); +int __cdecl wstat32(const wchar_t *_Filename, struct _stat32 *_Stat) +{ + wchar_t *_path = __mingw_fix_wstat_path(_Filename); + int ret = _wstat32(_path, _Stat); + if (_path != _Filename) + free(_path); + return ret; +} +int (__cdecl *__MINGW_IMP_SYMBOL(wstat32))(const wchar_t *, struct _stat32 *) = wstat32; + +/* On 32-bit systems is wstat() function ABI compatible with wstat32() function */ +#ifndef _WIN64 +#undef stat +#undef wstat +int __attribute__ ((alias ("wstat32"))) __cdecl wstat(const wchar_t *name, struct stat *stat); +extern int __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(wstat32))))) (__cdecl *__MINGW_IMP_SYMBOL(wstat))(const wchar_t *name, struct stat *stat); +#endif diff --git a/mingw-w64-crt/stdio/wstat32i64.c b/mingw-w64-crt/stdio/wstat32i64.c new file mode 100644 index 000000000000..15acacb532ce --- /dev/null +++ b/mingw-w64-crt/stdio/wstat32i64.c @@ -0,0 +1,22 @@ +/** + * 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 <stdlib.h> + +wchar_t *__mingw_fix_wstat_path(const wchar_t *_path); + +int __cdecl wstat32i64(const wchar_t *_Filename, struct _stat32i64 *_Stat); +int __cdecl wstat32i64(const wchar_t *_Filename, struct _stat32i64 *_Stat) +{ + wchar_t *_path = __mingw_fix_wstat_path(_Filename); + int ret = _wstat32i64(_path, _Stat); + if (_path != _Filename) + free(_path); + return ret; +} +int (__cdecl *__MINGW_IMP_SYMBOL(wstat32i64))(const wchar_t *, struct _stat32i64 *) = wstat32i64; diff --git a/mingw-w64-crt/stdio/wstat64.c b/mingw-w64-crt/stdio/wstat64.c new file mode 100644 index 000000000000..a24d81cd244e --- /dev/null +++ b/mingw-w64-crt/stdio/wstat64.c @@ -0,0 +1,22 @@ +/** + * 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 <stdlib.h> + +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) +{ + wchar_t *_path = __mingw_fix_wstat_path(_Filename); + int ret = _wstat64(_path, _Stat); + if (_path != _Filename) + free(_path); + return ret; +} +int (__cdecl *__MINGW_IMP_SYMBOL(wstat64))(const wchar_t *, struct _stat64 *) = wstat64; diff --git a/mingw-w64-crt/stdio/wstat64i32.c b/mingw-w64-crt/stdio/wstat64i32.c new file mode 100644 index 000000000000..5821cc464c38 --- /dev/null +++ b/mingw-w64-crt/stdio/wstat64i32.c @@ -0,0 +1,30 @@ +/** + * 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 <stdlib.h> + +wchar_t *__mingw_fix_wstat_path(const wchar_t *_path); + +int __cdecl wstat64i32(const wchar_t *_Filename, struct _stat64i32 *_Stat); +int __cdecl wstat64i32(const wchar_t *_Filename, struct _stat64i32 *_Stat) +{ + wchar_t *_path = __mingw_fix_wstat_path(_Filename); + int ret = _wstat64i32(_path, _Stat); + if (_path != _Filename) + free(_path); + return ret; +} +int (__cdecl *__MINGW_IMP_SYMBOL(wstat64i32))(const wchar_t *, struct _stat64i32 *) = wstat64i32; + +/* On 64-bit systems is wstat() function ABI compatible with wstat64i32() function */ +#ifdef _WIN64 +#undef stat +#undef wstat +int __attribute__ ((alias ("wstat64i32"))) __cdecl wstat(const wchar_t *name, struct stat *stat); +extern int __attribute__ ((alias (__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(wstat64i32))))) (__cdecl *__MINGW_IMP_SYMBOL(wstat))(const wchar_t *name, struct stat *stat); +#endif -- 2.20.1 >From a4d02cd446a7a168c3388120e3d9abeede403589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Mon, 3 Mar 2025 01:13:07 +0100 Subject: [PATCH 08/10] 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. Additionaly define struct stat64 for LFS functions stat64(), fstat64() and mingw-w64 function wstat64(). And again declare them as a functions instead of macro. stat has to be declared as a function, not as a macro because it would override effect of struct stat. --- mingw-w64-crt/misc/crtdll_fstat.c | 1 + mingw-w64-crt/misc/crtdll_stat.c | 1 + mingw-w64-crt/stdio/_fstat64.c | 5 +- mingw-w64-crt/stdio/stat64.c | 8 ++- mingw-w64-crt/stdio/wstat64.c | 7 ++- mingw-w64-headers/crt/_mingw_stat64.h | 23 ++------- mingw-w64-headers/crt/sys/stat.h | 74 +++++++++++++++++++-------- 7 files changed, 66 insertions(+), 53 deletions(-) diff --git a/mingw-w64-crt/misc/crtdll_fstat.c b/mingw-w64-crt/misc/crtdll_fstat.c index f0b3b748b0eb..cf51ffb6a760 100644 --- a/mingw-w64-crt/misc/crtdll_fstat.c +++ b/mingw-w64-crt/misc/crtdll_fstat.c @@ -4,6 +4,7 @@ * No warranty is given; refer to the file DISCLAIMER.PD within this package. */ +#define __CRT__NO_INLINE #include <sys/stat.h> #include "crtdll_stat.h" diff --git a/mingw-w64-crt/misc/crtdll_stat.c b/mingw-w64-crt/misc/crtdll_stat.c index f17bfbe93488..944596556f44 100644 --- a/mingw-w64-crt/misc/crtdll_stat.c +++ b/mingw-w64-crt/misc/crtdll_stat.c @@ -4,6 +4,7 @@ * No warranty is given; refer to the file DISCLAIMER.PD within this package. */ +#define __CRT__NO_INLINE #include <sys/stat.h> #include "crtdll_stat.h" diff --git a/mingw-w64-crt/stdio/_fstat64.c b/mingw-w64-crt/stdio/_fstat64.c index 0c059499b7e7..b8032ef7ace3 100644 --- a/mingw-w64-crt/stdio/_fstat64.c +++ b/mingw-w64-crt/stdio/_fstat64.c @@ -45,6 +45,5 @@ static int __cdecl emu__fstat64(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 *); +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 2e1d66ebc3fd..096bae132d35 100644 --- a/mingw-w64-crt/stdio/stat64.c +++ b/mingw-w64-crt/stdio/stat64.c @@ -10,14 +10,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 a24d81cd244e..399efcf72c3b 100644 --- a/mingw-w64-crt/stdio/wstat64.c +++ b/mingw-w64-crt/stdio/wstat64.c @@ -10,13 +10,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 8ce097561116..84eabba9698b 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 b972a0af4444..b7884d89fae4 100644 --- a/mingw-w64-headers/crt/sys/stat.h +++ b/mingw-w64-headers/crt/sys/stat.h @@ -124,31 +124,63 @@ extern "C" { #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) + +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; +}; + +#ifndef __CRT__NO_INLINE #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 -- 2.20.1 >From 9b4920eab24d82f88847949327972a4d0a60ad17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Thu, 6 Mar 2025 23:26:57 +0100 Subject: [PATCH 09/10] crt: Provide emulation of _time64 function Function _time64 is avaulable since msvcr70.dll. For older msvcrt versions provide emulation via WinAPI GetSystemTime() function which is available on all Windows versions and returns native value in SYSTEMTIME format. --- mingw-w64-crt/Makefile.am | 2 ++ mingw-w64-crt/lib-common/msvcrt.def.in | 2 +- mingw-w64-crt/misc/_time64.c | 31 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 mingw-w64-crt/misc/_time64.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 3f75c8958b71..fadac4c61b0e 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -512,6 +512,7 @@ src_msvcrt32=\ misc/_free_locale.c \ misc/_get_current_locale.c \ misc/_initterm_e.c \ + misc/_time64.c \ misc/btowc.c \ misc/imaxabs.c \ misc/lc_locale_func.c \ @@ -786,6 +787,7 @@ src_pre_msvcr70=\ misc/___mb_cur_max_func.c \ misc/__pctype_func.c \ misc/__pwctype_func.c \ + misc/_time64.c \ misc/lc_locale_func.c \ misc/strtoimax.c \ misc/strtoumax.c \ diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in b/mingw-w64-crt/lib-common/msvcrt.def.in index fe1c8164234c..9204c53526bb 100644 --- a/mingw-w64-crt/lib-common/msvcrt.def.in +++ b/mingw-w64-crt/lib-common/msvcrt.def.in @@ -1161,7 +1161,7 @@ _localtime64 _mktime64 F_X86_ANY(_osplatform DATA) F_NON_I386(_stat64) ; i386 _stat64 replaced by emu -_time64 +F_NON_I386(_time64) ; i386 _time64 replaced by emu _utime64 _wctime64 _wfindfirst64 diff --git a/mingw-w64-crt/misc/_time64.c b/mingw-w64-crt/misc/_time64.c new file mode 100644 index 000000000000..0eb9a9988a2d --- /dev/null +++ b/mingw-w64-crt/misc/_time64.c @@ -0,0 +1,31 @@ +/** + * 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. + */ + +#include <windows.h> +#include <time.h> + +#include "filetime_to_time64.h" + +static __time64_t __cdecl emu__time64(__time64_t *timeptr) +{ + SYSTEMTIME systemtime; + FILETIME filetime; + __time64_t time64; + GetSystemTime(&systemtime); + if (SystemTimeToFileTime(&systemtime, &filetime)) + time64 = filetime_to_time64(&filetime); + else + time64 = -1; + if (timeptr) + *timeptr = time64; + return time64; +} + +#define RETT __time64_t +#define FUNC _time64 +#define ARGS __time64_t *timeptr +#define CALL timeptr +#include "msvcrt_or_emu_glue.h" -- 2.20.1 >From 0ac97fa5c26de5dad8f3993ac826ffbe3ba7f69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali.ro...@gmail.com> Date: Wed, 1 May 2024 02:28:14 +0200 Subject: [PATCH 10/10] headers: Add support for -D_TIME_BITS=64 Currently all 32-bit non-UCRT builds are forced to use time_t type as 32-bit and also all time_t functions in 32-bit form. With this change, any msvcrt.dll based 32-bit application can use 64-bit time_t functions by defining -D_TIME_BITS=64 flag during compilation. Flag -D_TIME_BITS=64 is recognized also by GNU C library header files for the same purpose. When both _USE_32BIT_TIME_T and _TIME_BITS are defined by application then _USE_32BIT_TIME_T override effect of _TIME_BITS. --- mingw-w64-headers/crt/_mingw.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mingw-w64-headers/crt/_mingw.h.in b/mingw-w64-headers/crt/_mingw.h.in index 0752993f31d2..8e5944a8374f 100644 --- a/mingw-w64-headers/crt/_mingw.h.in +++ b/mingw-w64-headers/crt/_mingw.h.in @@ -384,7 +384,7 @@ typedef int __int128 __attribute__ ((__mode__ (TI))); #ifndef __WIDL__ -#if defined (_WIN32) && !defined (_WIN64) && !defined (__MINGW_USE_VC2005_COMPAT) && !defined (_UCRT) +#if defined (_WIN32) && !defined (_WIN64) && !defined (__MINGW_USE_VC2005_COMPAT) && !defined (_UCRT) && !(defined (_TIME_BITS) && _TIME_BITS == 64) #ifndef _USE_32BIT_TIME_T #define _USE_32BIT_TIME_T #endif -- 2.20.1
_______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public