maybe GetFileInformationByHandle instead of stat ?

Vincent Torri


On Thu, Feb 27, 2025 at 8:47 PM Lasse Collin <[email protected]> wrote:
>
> On 2025-02-25 Pali Rohár wrote:
> > On Tuesday 25 February 2025 20:11:12 Lasse Collin wrote:
> > > MSVCRT's _stat() fails with "directory/", but in POSIX a trailing
> > > slash should work for directories (and only for directories).
> > > mingw-w64-crt/stdio/_stat.c provides stat() that, with some
> > > exceptions, removes *one* trailing / or \ and then calls _stat().
> > > This hack is often enough, but as a side effect it then makes
> > > "file/" succeed while it shouldn't. And "directory//" still fails
> > > while it shouldn't.
> > >
> > > On UCRT, stat() simply calls _stat(). UCRT's _stat() has eerily
> > > similar behavior with trailing slashes as mingw-w64's replacement
> > > stat() has in MSVCRT builds. It's as if UCRT was made bug-for-bug
> > > compatible with mingw-w64 instead of thinking what is the correct
> > > but more complex thing to do.
> > >
> > > MSVCRT's _stat() doesn't work on \\.\ or \\?\ paths. UCRT's does,
> > > but the buggy trailing slash removal means that only the last line
> > > below succeeds with UCRT's _stat():
> > >
> > >     \\?\GLOBALROOT\Device\Harddisk0\Partition3
> > >     \\?\GLOBALROOT\Device\Harddisk0\Partition3\
> > >     \\?\GLOBALROOT\Device\Harddisk0\Partition3\\
> > >
> > > MSVCRT's _stat() doesn't follow reparse points. UCRT's _stat() does
> > > (on symlink or junction loops it fails with ENOENT, not ELOOP).
> >
> > MS _stat() function can do whatever it wants. It is not part of C or
> > POSIX.
>
> I agree.
>
> > But mingw-w64's stat() function should be consistent and returns
> > correct information. What you have figured out is another mess. It is
> > not nice.
>
> I apologize what I said about UCRT's _stat. It's fine. :-) It doesn't
> emulate any mingw-w64 bugs, and making stat == _stat is OK with UCRT.
> It's mingw-w64 that is broken.
>
> I had tested on MSYS2 in MINGW32 and UCRT64 environments. In the
> MINGW32 environment, _USE_32BIT_TIME_T is defined by default while in
> UCRT64 it's not defined.
>
> Earlier I had built a stat/_stat testing program with optimizations
> disabled. Building with optimizations enabled (-O2), the UCRT results
> changed for both _stat and stat. Now trailing slashes work the way they
> should.
>
> <sys/stat.h> provides __CRT_INLINE ("extern inline
> __attribute__((__gnu_inline__))") wrapper for these functions:
>
>     _fstat64i32
>     _stat64i32
>     fstat  (two versions depending on _USE_32BIT_TIME_T)
>
> There are also two versions of stat but they have been commented out:
>
>     /* Disable it for making sure trailing slash issue is fixed.  */
>
> The above inline functions are provided only when optimizations are
> enabled. Even in optimized builds, compiler may decide to not use the
> inline functions and instead may emit calls to the external functions.
> It's essential that the inline implementation in the header and the
> implementation in libmingwex have the same behavior. They are the same
> for _fstat64i32.
>
> _stat64i32 has a bug: The inline function doesn't remove a trailing
> slash but mingw-w64-crt/stdio/_stat64i32.c does. Thus the behavior of
> the function depends on compiler optimizations.
>
> In MSYS2's MINGW32 environment, stat is defined to _stat32, so calling
> _stat jumps into MSVCRT without any libmingwex code. A call to stat
> goes to libmingwex's wrapper that removes one trailing slash. In this
> case everything works the way I think it's intended to work.
>
> In the UCRT64 environment, _stat is defined to _stat64i32 in
> <_mingw_stat64.h>. UCRT builds of libmingwex include
> mingw-w64-crt/stdio/_stat64i32.c. This is wrong because UCRT's
> functions handle trailing slashes (MSVCRT's don't). This explains why I
> thought that UCRT had imitated mingw-w64's slash removal. Compiling
> with optimizations enabled made the compiler use the __CRT_INLINE
> version from <sys/stat.h>, skipping the slash removal version from
> libmingwex.
>
> For UCRT builds, <sys/stat.h> uses __mingw_ovr to make stat an alias for
> _stat. Thus stat and _stat behave the same.
>
> fstat __CRT_INLINE usage I didn't investigate much. At glance it looks
> suspicious because the definition of "struct stat" depends on
> time_t but there's only one non-inline fallback function. c0f06309823c
> ("crt: Provide fstat function symbol via alias") removed _fstat.c with a
> time_t related FIXME but left the inline functions in <sys/stat.h>. As
> the FIXME said, the old method was known to be incorrect.
>
> The same FIXME is in _stat.c and _wstat.c still, but due to the
> __mingw_ovr in <sys/stat.h> in UCRT builds, I suspect that the code
> from _stat.c and _wstat.c is never called in UCRT builds. Thus the
> time_t FIXME in these two files only matters to MSVCRT builds. (I don't
> know if Autoconf detection of stat and wstat still needs a symbol in
> libmingwex because AC_CHECK_FUNC doesn't look at headers.)
>
> --
> Lasse Collin
>
>
> _______________________________________________
> Mingw-w64-public mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/mingw-w64-public


_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to