crt: Fix ABI of POSIX ftw() and nftw() functions There are 4 POSIX stat functions (stat32, stat32i64, stat64, stat64i32) which differs in the stat structure point size. And there is additional stat symbol which alias to one of those based on the _FILE_OFFSET_BITS and _USE_32BIT_TIME_T settings. As POSIX ftw() and nftw() functions takes also struct stat in its function callback argument, it is required to properly provide for each settings of _FILE_OFFSET_BITS and _USE_32BIT_TIME_T configuration, the appropriate struct stat ABI compatible ftw and nftw symbol. This change provides 4 new ftw function symbols: ftw32, ftw32i64, ftw64 and ftw64i32. And same for nftw symbols: nftw32, nftw32i64, nftw64, nftw64i32. So with this change, the call to the ftw() or nftw() function will respect the _FILE_OFFSET_BITS and _USE_32BIT_TIME_T settings and provide correct size of stat structure. Function symbols for ftw and nftw are aliases to one of the fixed-size symbol based on the _FILE_OFFSET_BITS and _USE_32BIT_TIME_T settings. Signed-off-by: Martin Storsjö <martin@martin.st>
diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index a049274..195251a 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am
@@ -1063,7 +1063,8 @@ misc/wcstold.c \ misc/wdirent.c misc/winbs_uint64.c misc/winbs_ulong.c misc/winbs_ushort.c \ misc/wmemchr.c misc/wmemcmp.c misc/wmemcpy.c misc/wmemmove.c misc/wmempcpy.c \ - misc/wmemset.c misc/ftw.c misc/ftw64.c misc/mingw-access.c \ + misc/wmemset.c misc/mingw-access.c \ + misc/ftw32.c misc/ftw32i64.c misc/ftw64.c misc/ftw64i32.c \ \ ssp/chk_fail.c ssp/gets_chk.c ssp/memcpy_chk.c ssp/memmove_chk.c \ ssp/mempcpy_chk.c \ @@ -4314,6 +4315,7 @@ crt/CRT_noglob.c \ crt/txtmode.c \ crt/ucrtexe.c \ + misc/ftw.c \ profile/gcrt0.c \ profile/COPYING \ profile/CYGWIN_LICENSE \
diff --git a/mingw-w64-crt/misc/ftw.c b/mingw-w64-crt/misc/ftw.c index 74d05aa..e87ab5e 100644 --- a/mingw-w64-crt/misc/ftw.c +++ b/mingw-w64-crt/misc/ftw.c
@@ -15,11 +15,11 @@ #include <dirent.h> #include <ftw.h> -#ifdef IMPL_FTW64 -#define stat stat64 -#define nftw nftw64 -#define ftw ftw64 -#endif +#undef stat64 +int __cdecl stat32(const char *_Filename, struct _stat32 *_Stat); +int __cdecl stat32i64(const char *_Filename, struct _stat32i64 *_Stat); +int __cdecl stat64(const char *_Filename, struct _stat64 *_Stat); +int __cdecl stat64i32(const char *_Filename, struct _stat64i32 *_Stat); typedef struct dir_data_t { DIR *h; @@ -36,14 +36,14 @@ dir_data_t **dirs; char *buf; struct FTW ftw; - int (*fcb) (const char *, const struct stat *, int , struct FTW *); + int (*fcb) (const char *, const STRUCT_STAT *, int , struct FTW *); size_t cur_dir, msz_dir, buf_sz; int flags; dev_t dev; } ctx_t; static int add_object (ctx_t *); -static int do_dir (ctx_t *, struct stat *, dir_data_t *); +static int do_dir (ctx_t *, STRUCT_STAT *, dir_data_t *); static int do_entity (ctx_t *, dir_data_t *, const char *, size_t); static int do_it (const char *, int, void *, int, int); @@ -225,7 +225,7 @@ static int do_entity (ctx_t *ctx, dir_data_t *dir, const char *name, size_t namlen) { - struct stat st; + STRUCT_STAT st; char *h; size_t cnt_sz; int ret = 0, flag = 0; @@ -249,7 +249,7 @@ name = ctx->buf; - if (stat (name, &st) < 0) + if (FUNC_STAT (name, &st) < 0) { if (errno != EACCES && errno != ENOENT) ret = -1; @@ -257,7 +257,7 @@ flag = FTW_NS; if (!(ctx->flags & FTW_PHYS)) - stat (name, &st); + FUNC_STAT (name, &st); } else flag = (S_ISDIR (st.st_mode) ? FTW_D : FTW_F); @@ -281,7 +281,7 @@ static int -do_dir (ctx_t *ctx, struct stat *st, __UNUSED_PARAM(dir_data_t *old_dir)) +do_dir (ctx_t *ctx, STRUCT_STAT *st, __UNUSED_PARAM(dir_data_t *old_dir)) { dir_data_t dir; struct dirent *d; @@ -378,7 +378,7 @@ do_it (const char *dir, __UNUSED_PARAM(int is_nftw), void *fcb, int descriptors, int flags) { struct ctx_t ctx; - struct stat st; + STRUCT_STAT st; int ret = 0; int sv_e; char *cp; @@ -417,12 +417,12 @@ ctx.ftw.level = 0; ctx.ftw.base = cp - ctx.buf; ctx.flags = flags; - ctx.fcb = (int (*) (const char *, const struct stat *, int , struct FTW *)) fcb; + ctx.fcb = (int (*) (const char *, const STRUCT_STAT *, int , struct FTW *)) fcb; ctx.objs = NULL; if (!ret) { - if (stat (ctx.buf, &st) < 0) + if (FUNC_STAT (ctx.buf, &st) < 0) ret = -1; else if (S_ISDIR (st.st_mode)) { @@ -451,13 +451,17 @@ } int -ftw (const char *path, int (*fcb) (const char *, const struct stat *, int), int descriptors) +FUNC_FTW (const char *path, int (*fcb) (const char *, const STRUCT_STAT *, int), int descriptors); +int +FUNC_FTW (const char *path, int (*fcb) (const char *, const STRUCT_STAT *, int), int descriptors) { return do_it (path, 0, fcb, descriptors, 0); } int -nftw (const char *path, int (*fcb) (const char *, const struct stat *, int , struct FTW *), int descriptors, int flags) +FUNC_NFTW (const char *path, int (*fcb) (const char *, const STRUCT_STAT *, int , struct FTW *), int descriptors, int flags); +int +FUNC_NFTW (const char *path, int (*fcb) (const char *, const STRUCT_STAT *, int , struct FTW *), int descriptors, int flags) { return do_it (path, 1, fcb, descriptors, flags); }
diff --git a/mingw-w64-crt/misc/ftw32.c b/mingw-w64-crt/misc/ftw32.c new file mode 100644 index 0000000..5eb9e37 --- /dev/null +++ b/mingw-w64-crt/misc/ftw32.c
@@ -0,0 +1,19 @@ +/** + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ + +#define FUNC_FTW ftw32 +#define FUNC_NFTW nftw32 +#define FUNC_STAT stat32 +#define STRUCT_STAT struct _stat32 +#include "ftw.c" + +/* On 32-bit systems is stat ABI compatible with stat32 */ +#ifndef _WIN64 +#undef nftw +#undef ftw +struct stat; +int __attribute__ ((alias ("nftw32"))) __cdecl nftw(const char *, int (*) (const char *, const struct stat *, int, struct FTW *), int, int); +int __attribute__ ((alias ("ftw32"))) __cdecl ftw(const char *, int (*) (const char *, const struct stat *, int), int); +#endif
diff --git a/mingw-w64-crt/misc/ftw32i64.c b/mingw-w64-crt/misc/ftw32i64.c new file mode 100644 index 0000000..20985fb --- /dev/null +++ b/mingw-w64-crt/misc/ftw32i64.c
@@ -0,0 +1,10 @@ +/** + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ + +#define FUNC_FTW ftw32i64 +#define FUNC_NFTW nftw32i64 +#define FUNC_STAT stat32i64 +#define STRUCT_STAT struct _stat32i64 +#include "ftw.c"
diff --git a/mingw-w64-crt/misc/ftw64.c b/mingw-w64-crt/misc/ftw64.c index 3e45847..5595e76 100644 --- a/mingw-w64-crt/misc/ftw64.c +++ b/mingw-w64-crt/misc/ftw64.c
@@ -3,6 +3,8 @@ * No warranty is given; refer to the file DISCLAIMER within this package. */ -#define IMPL_FTW64 1 - +#define FUNC_FTW ftw64 +#define FUNC_NFTW nftw64 +#define FUNC_STAT stat64 +#define STRUCT_STAT struct _stat64 #include "ftw.c"
diff --git a/mingw-w64-crt/misc/ftw64i32.c b/mingw-w64-crt/misc/ftw64i32.c new file mode 100644 index 0000000..2ded6ec --- /dev/null +++ b/mingw-w64-crt/misc/ftw64i32.c
@@ -0,0 +1,19 @@ +/** + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ + +#define FUNC_FTW ftw64i32 +#define FUNC_NFTW nftw64i32 +#define FUNC_STAT stat64i32 +#define STRUCT_STAT struct _stat64i32 +#include "ftw.c" + +/* On 64-bit systems is stat ABI compatible with stat64i32 */ +#ifdef _WIN64 +#undef nftw +#undef ftw +struct stat; +int __attribute__ ((alias ("nftw64i32"))) __cdecl nftw(const char *, int (*) (const char *, const struct stat *, int, struct FTW *), int, int); +int __attribute__ ((alias ("ftw64i32"))) __cdecl ftw(const char *, int (*) (const char *, const struct stat *, int), int); +#endif