msvcrt _fstat function is broken and for directory fd it returns S_ISREG
type. 32-bit pre-msvcr110 _fstat does not properly signal size overflow.
UCRT seems to work correctly.
Add mingw-w64 fstat wrappers around msvcrt _fstat functions which change
S_IFMT to S_IFDIR if winapi filehandle has FILE_ATTRIBUTE_DIRECTORY
attribute set. Provide wrapper for all 4 fstat size_t/time_t variants.
For 32-bit pre-msvcr110 builds, adds similar workaround like for existing
mingw-w64 stat functions.
Currently our mingw-w64 header files defines non-underscore fstat and
fstat64 functions as __MINGW_ASM_CALL redirects to underscore _fstat32,
_fstat32i64, _fstat64i32, _fstat64 functions based on _FILE_OFFSET_BITS and
_TIME_BITS macros. So every one of these 4 functions needs its own fixup
wrapper. This change introduce 4 new non-underscore symbols fstat32,
fstat32i64, fstat64i32, fstat64 which provides necessary fixup and to which
mingw-w64 sys/stat.h header file redirects existing fstat and fstat64
functions. UCRT does not need any fixup, so new symbols are added as
aliases in def files.
---
This change depends on "crt: Implement POSIX mkdtemp() function".
---
mingw-w64-crt/Makefile.am | 10 +++-
mingw-w64-crt/def-include/crt-aliases.def.in | 18 +++----
.../api-ms-win-crt-filesystem-l1-1-0.def.in | 3 ++
mingw-w64-crt/lib-common/msvcrt.def.in | 4 --
mingw-w64-crt/misc/crtdll_fstat.c | 5 --
.../stdio/__mingw_fix_fstat_finish.c | 18 +++++++
mingw-w64-crt/stdio/__mingw_fix_stat.h | 7 +++
mingw-w64-crt/stdio/_fstat64.c | 3 --
mingw-w64-crt/stdio/fstat32i64.c | 16 ++++++
mingw-w64-crt/stdio/fstat64.c | 15 ++++++
mingw-w64-crt/stdio/msvcr110plus_fstat32.c | 24 +++++++++
mingw-w64-crt/stdio/msvcr110plus_fstat64i32.c | 24 +++++++++
mingw-w64-crt/stdio/msvcr110pre_fstat32.c | 50 +++++++++++++++++++
mingw-w64-crt/stdio/msvcr110pre_fstat64i32.c | 50 +++++++++++++++++++
mingw-w64-crt/testcases/t_fstat.c | 48 ++++++++++++++++--
mingw-w64-headers/crt/sys/stat.h | 8 +--
16 files changed, 271 insertions(+), 32 deletions(-)
create mode 100644 mingw-w64-crt/stdio/__mingw_fix_fstat_finish.c
create mode 100644 mingw-w64-crt/stdio/fstat32i64.c
create mode 100644 mingw-w64-crt/stdio/fstat64.c
create mode 100644 mingw-w64-crt/stdio/msvcr110plus_fstat32.c
create mode 100644 mingw-w64-crt/stdio/msvcr110plus_fstat64i32.c
create mode 100644 mingw-w64-crt/stdio/msvcr110pre_fstat32.c
create mode 100644 mingw-w64-crt/stdio/msvcr110pre_fstat64i32.c
diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 7b025d213242..d6e049baaeed 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -190,6 +190,8 @@ src_msvcrt_common=\
stdio/_strtof_l.c \
stdio/_wcstof_l.c \
stdio/acrt_iob_func.c \
+ stdio/fstat32i64.c \
+ stdio/fstat64.c \
stdio/strtof.c \
stdio/snprintf_alias.c \
stdio/snwprintf_alias.c \
@@ -372,6 +374,8 @@ src_msvcrt=\
stdio/_getc_nolock.c \
stdio/mingw_lock.c \
stdio/msvcrtos_ftruncate64.c \
+ stdio/msvcr110pre_fstat32.c \
+ stdio/msvcr110pre_fstat64i32.c \
stdio/msvcr110pre_stat32.c \
stdio/msvcr110pre_stat64i32.c \
stdio/msvcr110pre_wstat32.c \
@@ -1022,6 +1026,8 @@ src_pre_msvcr100=\
misc/imaxdiv.c
src_pre_msvcr110=\
+ stdio/msvcr110pre_fstat32.c \
+ stdio/msvcr110pre_fstat64i32.c \
stdio/msvcr110pre_stat32.c \
stdio/msvcr110pre_stat64i32.c \
stdio/msvcr110pre_wstat32.c \
@@ -1050,6 +1056,8 @@ src_post_msvcr80=\
misc/__p__osver_emul.c
src_post_msvcr100=\
+ stdio/msvcr110plus_fstat32.c \
+ stdio/msvcr110plus_fstat64i32.c \
stdio/msvcr110plus_stat32.c \
stdio/msvcr110plus_stat64i32.c \
stdio/msvcr110plus_wstat32.c \
@@ -1268,7 +1276,7 @@ src_libmingwex=\
stdio/_Exit.c \
stdio/asprintf.c \
stdio/mingw_ftruncate64.c stdio/lltoa.c stdio/lltow.c \
- stdio/__mingw_fix_stat.h stdio/__mingw_fix_stat_finish.c \
+ stdio/__mingw_fix_stat.h stdio/__mingw_fix_stat_finish.c
stdio/__mingw_fix_fstat_finish.c \
stdio/__mingw_fix_stat_path.c stdio/__mingw_fix_wstat_path.c \
\
stdio/mingw_pformat.h stdio/mingw_sformat.h stdio/mingw_swformat.h \
diff --git a/mingw-w64-crt/def-include/crt-aliases.def.in
b/mingw-w64-crt/def-include/crt-aliases.def.in
index 8f9ee2e09c46..2b88b699c0fc 100644
--- a/mingw-w64-crt/def-include/crt-aliases.def.in
+++ b/mingw-w64-crt/def-include/crt-aliases.def.in
@@ -64,13 +64,11 @@ ADD_UNDERSCORE(filelength)
ADD_UNDERSCORE(fileno)
; ADD_UNDERSCORE(flushall)
ADD_UNDERSCORE(fputchar)
-#ifdef FIXED_SIZE_SYMBOLS
-#ifndef CRTDLL
-ADD_UNDERSCORE(fstat)
-#endif
-#else
+#if defined(UCRTBASE)
F32(fstat == _fstat32)
F64(fstat == _fstat64i32)
+#else
+; fstat for non-UCRT is provided by mingw to workaround S_IFDIR issue in _fstat
#endif
; ftime is provided in misc/ftime32.c or misc/ftime64.c as MS _ftime is not
ABI compatible with POSIX ftime
#if defined(UCRTBASE)
@@ -305,23 +303,23 @@ fsetpos64 == fsetpos
lseek64 == _lseeki64
#endif
#ifdef UCRTBASE
+fstat32 == _fstat32
+fstat32i64 == _fstat32i64
+fstat64 == _fstat64
+fstat64i32 == _fstat64i32
stat32 == _stat32
stat32i64 == _stat32i64
stat64 == _stat64
stat64i32 == _stat64i32
#else
+; fstat for non-UCRT is provided by mingw to workaround S_IFDIR issue in _fstat
; stat for non-UCRT is provided by mingw to workaround trailing slash issue in
_stat
#endif
#ifdef FIXED_SIZE_SYMBOLS
-// NO_FIXED_SIZE_64_ALIAS means that DLL provides the native _fstat64 symbol
-#if defined(NO_FIXED_SIZE_64_ALIAS) && !defined(NO_FSTAT64_ALIAS)
-fstat64 == _fstat64
-#endif
#ifdef WITH_FSEEKO64_ALIAS
fseeko64 == _fseeki64
#endif
#else
-fstat64 == _fstat64
fseeko64 == _fseeki64
ftello64 == _ftelli64
#endif
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 a0665a3a3d31..bdaa9bcd8dc5 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
@@ -37,10 +37,13 @@ F64(_fstat == _fstat64i32)
F32(_fstati64 == _fstat32i64)
F64(_fstati64 == _fstat64)
_fstat32
+fstat32 == _fstat32
_fstat32i64
+fstat32i64 == _fstat32i64
_fstat64
fstat64 == _fstat64
_fstat64i32
+fstat64i32 == _fstat64i32
_fullpath
_getdiskfree
_getdrive
diff --git a/mingw-w64-crt/lib-common/msvcrt.def.in
b/mingw-w64-crt/lib-common/msvcrt.def.in
index a4343bb765e0..979157d4e8bf 100644
--- a/mingw-w64-crt/lib-common/msvcrt.def.in
+++ b/mingw-w64-crt/lib-common/msvcrt.def.in
@@ -1907,10 +1907,6 @@ F_I386(_libm_sse2_tan_precise)
; This includes list of some symbol alises for compatibility with C99 and
POSIX functions and symbols from other msvcr* libraries
#define FIXED_SIZE_SYMBOLS
#define NO_FIXED_SIZE_64_ALIAS
-#ifdef __i386__
-; i386 fstat64 alias provided by emu
-#define NO_FSTAT64_ALIAS
-#endif
#define NO_TIME_ALIAS
#define NO_TMPFILE_ALIAS
#define NO_STRCMPI_ALIAS
diff --git a/mingw-w64-crt/misc/crtdll_fstat.c
b/mingw-w64-crt/misc/crtdll_fstat.c
index 2fe5b1e9c342..5441e322f38c 100644
--- a/mingw-w64-crt/misc/crtdll_fstat.c
+++ b/mingw-w64-crt/misc/crtdll_fstat.c
@@ -22,8 +22,3 @@ int (__cdecl *__MINGW_IMP_SYMBOL(_fstat32))(int fd, struct
_stat32 *stat) = _fst
#undef _fstat
int __attribute__ ((alias ("_fstat32"))) __cdecl _fstat(int fd, struct _stat32
*stat);
extern int __attribute__ ((alias
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_fstat32))))) (__cdecl
*__MINGW_IMP_SYMBOL(_fstat))(int fd, struct _stat32 *stat);
-
-#undef fstat
-struct stat;
-int __attribute__ ((alias ("_fstat32"))) __cdecl fstat(int fd, struct stat
*stat);
-extern int __attribute__ ((alias
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(_fstat32))))) (__cdecl
*__MINGW_IMP_SYMBOL(fstat))(int fd, struct stat *stat);
diff --git a/mingw-w64-crt/stdio/__mingw_fix_fstat_finish.c
b/mingw-w64-crt/stdio/__mingw_fix_fstat_finish.c
new file mode 100644
index 000000000000..724b9607657d
--- /dev/null
+++ b/mingw-w64-crt/stdio/__mingw_fix_fstat_finish.c
@@ -0,0 +1,18 @@
+/**
+ * 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 "__mingw_fix_stat.h"
+
+int __mingw_fix_fstat_finish(int ret, int fd, unsigned short *mode)
+{
+ /* msvcrt's _fstat fills S_IFREG for directories. Fix it to S_IFDIR. */
+ BY_HANDLE_FILE_INFORMATION fi;
+ if (ret == 0 && S_ISREG(*mode) &&
GetFileInformationByHandle((HANDLE)_get_osfhandle(fd), &fi) &&
(fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ *mode = (*mode & ~S_IFMT) | S_IFDIR;
+ return ret;
+}
diff --git a/mingw-w64-crt/stdio/__mingw_fix_stat.h
b/mingw-w64-crt/stdio/__mingw_fix_stat.h
index 909606204b4d..1317dbffe2e8 100644
--- a/mingw-w64-crt/stdio/__mingw_fix_stat.h
+++ b/mingw-w64-crt/stdio/__mingw_fix_stat.h
@@ -11,5 +11,12 @@ char* __mingw_fix_stat_path (const char* _path);
wchar_t* __mingw_fix_wstat_path (const wchar_t* _path);
int __mingw_fix_stat_finish(int ret, const void *orig_path, void *used_path,
unsigned short mode);
+int __mingw_fix_fstat_finish(int ret, int fd, unsigned short *mode);
+
+#define __MINGW_FIXED_FSTAT(fstat_func, fd, obj) ({ \
+ int _fstat_ret = fstat_func(fd, obj); \
+ _fstat_ret = __mingw_fix_fstat_finish(_fstat_ret, fd, &(obj)->st_mode); \
+ _fstat_ret; \
+})
#endif
diff --git a/mingw-w64-crt/stdio/_fstat64.c b/mingw-w64-crt/stdio/_fstat64.c
index 28c5d73c1f55..9386dd909c71 100644
--- a/mingw-w64-crt/stdio/_fstat64.c
+++ b/mingw-w64-crt/stdio/_fstat64.c
@@ -43,6 +43,3 @@ static int __cdecl emu__fstat64(int fd, struct _stat64 *stat)
#define ARGS int fd, struct _stat64 *stat
#define CALL fd, stat
#include "msvcrt_or_emu_glue.h"
-
-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/fstat32i64.c b/mingw-w64-crt/stdio/fstat32i64.c
new file mode 100644
index 000000000000..8ba257de481a
--- /dev/null
+++ b/mingw-w64-crt/stdio/fstat32i64.c
@@ -0,0 +1,16 @@
+/**
+ * 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 <stdlib.h>
+#include "__mingw_fix_stat.h"
+
+int __cdecl fstat32i64(int fd, struct _stat32i64 *stat);
+int __cdecl fstat32i64(int fd, struct _stat32i64 *stat)
+{
+ return __MINGW_FIXED_FSTAT(_fstat32i64, fd, stat);
+}
+int (__cdecl *__MINGW_IMP_SYMBOL(fstat32i64))(int, struct _stat32i64 *) =
fstat32i64;
diff --git a/mingw-w64-crt/stdio/fstat64.c b/mingw-w64-crt/stdio/fstat64.c
new file mode 100644
index 000000000000..442409c34dd6
--- /dev/null
+++ b/mingw-w64-crt/stdio/fstat64.c
@@ -0,0 +1,15 @@
+/**
+ * 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 <stdlib.h>
+#include "__mingw_fix_stat.h"
+
+int __cdecl fstat64(int fd, struct stat64 *stat)
+{
+ return __MINGW_FIXED_FSTAT(_fstat64, fd, (struct _stat64 *)stat);
+}
+int (__cdecl *__MINGW_IMP_SYMBOL(fstat64))(int, struct stat64 *) = fstat64;
diff --git a/mingw-w64-crt/stdio/msvcr110plus_fstat32.c
b/mingw-w64-crt/stdio/msvcr110plus_fstat32.c
new file mode 100644
index 000000000000..e33d0d5e302f
--- /dev/null
+++ b/mingw-w64-crt/stdio/msvcr110plus_fstat32.c
@@ -0,0 +1,24 @@
+/**
+ * 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 <stdlib.h>
+#include "__mingw_fix_stat.h"
+
+int __cdecl fstat32(int fd, struct _stat32 *stat);
+int __cdecl fstat32(int fd, struct _stat32 *stat)
+{
+ return __MINGW_FIXED_FSTAT(_fstat32, fd, stat);
+}
+int (__cdecl *__MINGW_IMP_SYMBOL(fstat32))(int, struct _stat32 *) = fstat32;
+
+/* On 32-bit systems is fstat() function ABI compatible with fstat32()
function */
+#ifndef _WIN64
+#undef stat
+struct stat;
+int __attribute__ ((alias ("fstat32"))) __cdecl fstat(int fd, struct stat
*stat);
+extern int __attribute__ ((alias
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(fstat32))))) (__cdecl
*__MINGW_IMP_SYMBOL(fstat))(int fd, struct stat *stat);
+#endif
diff --git a/mingw-w64-crt/stdio/msvcr110plus_fstat64i32.c
b/mingw-w64-crt/stdio/msvcr110plus_fstat64i32.c
new file mode 100644
index 000000000000..971c3c820ed9
--- /dev/null
+++ b/mingw-w64-crt/stdio/msvcr110plus_fstat64i32.c
@@ -0,0 +1,24 @@
+/**
+ * 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 <stdlib.h>
+#include "__mingw_fix_stat.h"
+
+int __cdecl fstat64i32(int fd, struct _stat64i32 *stat);
+int __cdecl fstat64i32(int fd, struct _stat64i32 *stat)
+{
+ return __MINGW_FIXED_FSTAT(_fstat64i32, fd, stat);
+}
+int (__cdecl *__MINGW_IMP_SYMBOL(fstat64i32))(int fd, struct _stat64i32 *) =
fstat64i32;
+
+/* On 64-bit systems is fstat() function ABI compatible with fstat64i32()
function */
+#ifdef _WIN64
+#undef stat
+struct stat;
+int __attribute__ ((alias ("fstat64i32"))) __cdecl fstat(int fd, struct stat
*stat);
+extern int __attribute__ ((alias
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(fstat64i32))))) (__cdecl
*__MINGW_IMP_SYMBOL(fstat))(int fd, struct stat *stat);
+#endif
diff --git a/mingw-w64-crt/stdio/msvcr110pre_fstat32.c
b/mingw-w64-crt/stdio/msvcr110pre_fstat32.c
new file mode 100644
index 000000000000..8fc841fa86d1
--- /dev/null
+++ b/mingw-w64-crt/stdio/msvcr110pre_fstat32.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.
+ */
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include "__mingw_fix_stat.h"
+
+/* For pre-msvcr110 builds, we cannot use _fstat32() function as it does
+ * not signal EOVERFLOW when file size does not fit into the st_size field,
+ * as it is required by POSIX fstat() function.
+ * This file is used only for pre-msvcr110 builds.
+ */
+int __cdecl fstat32(int fd, struct _stat32 *stat);
+int __cdecl fstat32(int fd, struct _stat32 *stat)
+{
+ struct _stat32i64 st;
+ int ret = __MINGW_FIXED_FSTAT(_fstat32i64, fd, &st);
+ if (ret != 0)
+ return ret;
+ if (st.st_size > UINT32_MAX) {
+ errno = EOVERFLOW;
+ 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 0;
+}
+int (__cdecl *__MINGW_IMP_SYMBOL(fstat32))(int, struct _stat32 *) = fstat32;
+
+/* On 32-bit systems is fstat() function ABI compatible with fstat32()
function */
+#ifndef _WIN64
+#undef stat
+struct stat;
+int __attribute__ ((alias ("fstat32"))) __cdecl fstat(int fd, struct stat
*stat);
+extern int __attribute__ ((alias
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(fstat32))))) (__cdecl
*__MINGW_IMP_SYMBOL(fstat))(int fd, struct stat *stat);
+#endif
diff --git a/mingw-w64-crt/stdio/msvcr110pre_fstat64i32.c
b/mingw-w64-crt/stdio/msvcr110pre_fstat64i32.c
new file mode 100644
index 000000000000..8068cf4746e7
--- /dev/null
+++ b/mingw-w64-crt/stdio/msvcr110pre_fstat64i32.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.
+ */
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include "__mingw_fix_stat.h"
+
+/* For pre-msvcr110 builds, we cannot use _fstat64i32() function as it does
+ * not signal EOVERFLOW when file size does not fit into the st_size field,
+ * as it is required by POSIX fstat() function.
+ * This file is used only for pre-msvcr110 builds.
+ */
+int __cdecl fstat64i32(int fd, struct _stat64i32 *stat);
+int __cdecl fstat64i32(int fd, struct _stat64i32 *stat)
+{
+ struct _stat64 st;
+ int ret = __MINGW_FIXED_FSTAT(_fstat64, fd, &st);
+ if (ret != 0)
+ return ret;
+ if (st.st_size > UINT32_MAX) {
+ errno = EOVERFLOW;
+ 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 0;
+}
+int (__cdecl *__MINGW_IMP_SYMBOL(fstat64i32))(int, struct _stat64i32 *) =
fstat64i32;
+
+/* On 64-bit systems is stat() function ABI compatible with stat64i32()
function */
+#ifdef _WIN64
+#undef stat
+struct stat;
+int __attribute__ ((alias ("fstat64i32"))) __cdecl fstat(int fd, struct stat
*stat);
+extern int __attribute__ ((alias
(__MINGW64_STRINGIFY(__MINGW_IMP_SYMBOL(fstat64i32))))) (__cdecl
*__MINGW_IMP_SYMBOL(fstat))(int fd, struct stat *stat);
+#endif
diff --git a/mingw-w64-crt/testcases/t_fstat.c
b/mingw-w64-crt/testcases/t_fstat.c
index 0e85bd57d39f..0622b9e4ad5c 100644
--- a/mingw-w64-crt/testcases/t_fstat.c
+++ b/mingw-w64-crt/testcases/t_fstat.c
@@ -1,15 +1,53 @@
#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <windows.h>
-int main(int argc, char *argv[])
+#define TMPTMPL "mingw-w64-fstat-XXXXXX"
+static char dirpath[MAX_PATH + sizeof(TMPTMPL)];
+
+static void remove_dirpath(void) { rmdir(dirpath); }
+
+int main()
{
struct stat st;
struct stat64 st64;
- if (0 == fstat(0, &st))
- printf("mode = %x\n", st.st_mode);
- if (0 == fstat64(0, &st64))
- printf("mode = %x\n", st64.st_mode);
+ HANDLE handle;
+ int dirfd;
+
+ assert(fstat(0, &st) == 0);
+ printf("fstat(0): mode = %08o\n", st.st_mode);
+ assert(!S_ISDIR(st.st_mode));
+
+ assert(fstat64(0, &st64) == 0);
+ printf("fstat64(0): mode = %08o\n", st64.st_mode);
+ assert(!S_ISDIR(st64.st_mode));
+
+ assert(GetTempPathA(MAX_PATH, dirpath));
+ printf("GetTempPathA(): path=%s\n", dirpath);
+
+ strcat(dirpath, TMPTMPL);
+ assert(mkdtemp(dirpath));
+ atexit(remove_dirpath);
+ printf("mkdtemp(): path=%s\n", dirpath);
+
+ handle = CreateFileA(dirpath, FILE_READ_ATTRIBUTES | DELETE,
FILE_SHARE_VALID_FLAGS, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS |
FILE_FLAG_DELETE_ON_CLOSE, NULL);
+ assert(handle != INVALID_HANDLE_VALUE);
+
+ dirfd = _open_osfhandle((intptr_t)handle, O_RDONLY);
+ assert(dirfd >= 0);
+
+ assert(fstat(dirfd, &st) == 0);
+ printf("fstat(dirfd): mode = %08o\n", st.st_mode);
+ assert(S_ISDIR(st.st_mode));
+
+ assert(fstat64(dirfd, &st64) == 0);
+ printf("fstat64(dirfd): mode = %08o\n", st64.st_mode);
+ assert(S_ISDIR(st64.st_mode));
+
return 0;
}
diff --git a/mingw-w64-headers/crt/sys/stat.h b/mingw-w64-headers/crt/sys/stat.h
index 5d2e6dfaf031..347f66eef77b 100644
--- a/mingw-w64-headers/crt/sys/stat.h
+++ b/mingw-w64-headers/crt/sys/stat.h
@@ -149,21 +149,21 @@ struct stat {
};
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
#ifdef _USE_32BIT_TIME_T
-int __cdecl fstat(int _Desc, struct stat *_Stat) __MINGW_ASM_CALL(_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
-int __cdecl fstat(int _Desc, struct stat *_Stat) __MINGW_ASM_CALL(_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 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 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
--
2.20.1
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public