These functions are available since msvcr70.dll. For older msvcrt versions provide emulation via _fstat32(), _stat32() and _wstat32() functions. These functions in all pre-msvcr100 CRT libraries provides only truncated 32-bit file size and invalid value -1 as timestamp.
The real 64-bit non-truncated file size and valid timestamp information is retrieved via the WinAPI calls. For _stat64() and _wstat64() use WinAPI FindFirstFile() call. And for _fstat64() use WinAPI GetFileInformationByHandle() call. Same thing is doing msvcrt DLL library for other stat functions. Note that both WinAPI functions are available in all Windows version (since the Windows NT 3.1 and the Windows 95). 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 | 9 +++- mingw-w64-crt/include/filetime_to_time64.h | 13 ++++++ mingw-w64-crt/lib-common/msvcrt.def.in | 6 +-- mingw-w64-crt/stdio/_fstat64.c | 49 ++++++++++++++++++++++ mingw-w64-crt/stdio/_stat64.c | 47 +++++++++++++++++++++ mingw-w64-crt/stdio/_wstat64.c | 47 +++++++++++++++++++++ 6 files changed, 167 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 ec06e5ed0040..6987e6a93873 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -543,11 +543,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 @@ -802,10 +805,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 @@ -4258,6 +4264,7 @@ EXTRA_DIST += revstamp.h \ $(top_srcdir)/lib64/*.def.in \ $(top_srcdir)/libarm32/*.def.in \ $(top_srcdir)/def-include/*.def.in \ + include/filetime_to_time64.h \ crt/binmode.c \ crt/crtbegin.c \ crt/crtdll.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 681b491867f5..2df0c026a7d0 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..8df51a42aad9 --- /dev/null +++ b/mingw-w64-crt/stdio/_fstat64.c @@ -0,0 +1,49 @@ +/** + * 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 <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; /* invalid value -1 */ + stat->st_mtime = st.st_mtime; /* invalid value -1 */ + stat->st_ctime = st.st_ctime; /* invalid value -1 */ + } + 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..2edab1e4e1f2 --- /dev/null +++ b/mingw-w64-crt/stdio/_stat64.c @@ -0,0 +1,47 @@ +/** + * 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 <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; /* invalid value -1 */ + stat->st_mtime = st.st_mtime; /* invalid value -1 */ + stat->st_ctime = st.st_ctime; /* invalid value -1 */ + } + 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..1ffaf6227a5b --- /dev/null +++ b/mingw-w64-crt/stdio/_wstat64.c @@ -0,0 +1,47 @@ +/** + * 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 <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; /* invalid value -1 */ + stat->st_mtime = st.st_mtime; /* invalid value -1 */ + stat->st_ctime = st.st_ctime; /* invalid value -1 */ + } + 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 _______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public