On Saturday 22 February 2025 18:12:36 Lasse Collin wrote:
> On 2025-02-22 Pali Rohár wrote:
> > On Saturday 22 February 2025 16:03:42 Lasse Collin wrote:
> > > On 2025-02-18 Pali Rohár wrote:  
> > > > On Tuesday 18 February 2025 23:32:54 Lasse Collin wrote:  
> > > > > On 2025-02-18 Pali Rohár wrote:    
> > > > > > Just one test case, can you check that your new readdir()
> > > > > > function is working correctly on these two paths?
> > > > > > 
> > > > > > \\?\GLOBALROOT\Device\Harddisk0\Partition1\
> > > > > > \\?\GLOBALROOT\Device\HardiskVolume1\  
> > > > > 
> > > > > These paths don't work with the old dirent. opendir fails with
> > > > > ENOENT.    
> > > > 
> > > > Perfect, this is then nice improvement, that in new version it is
> > > > working.  
> > > 
> > > I had made a mistake. I had tested the new code with and without \
> > > at the end, but I had tested the old code only without. The old
> > > code does work when there is \ at the end. I hope it is OK that the
> > > new code works without \ too, even though I guess it's not strictly
> > > correct.  
> > 
> > Uff, I'm not sure. As without the trailing \ the above path is not
> > directory.
> 
> Right, it's not a directory.
> 
> The old dirent code calls GetFileAttributes on the path first and only
> then proceeds to append \* for _findfirst. The new code doesn't call
> GetFileAttributes at all, so FindFirstFileW is called with \* appended
> when there isn't a \ or / at the end already.
> 
> If GetFileAttributes was called, maybe FindFirstFileW wouldn't need to
> check for as many Windows error codes, but one has to check for a few
> codes from GetAttributes still. Also, something in the file system can
> in theory change before FindFirstFileW is called (a race condition).
> 
> Are there other situations where a path isn't a directory if there isn't
> a \ at the end?

It can be anything within NT object system which represents some top
level filesystem object or NT object symlink to filesystem directory.

> > > (1)
> > > I tested on a directory that has an unsupported reparse tag.
> > > FindFirstFileW fails with ERROR_CANT_ACCESS_FILE (1920) which
> > > currently becomes EIO. The old dirent code fails with EINVAL at
> > > readdir (not at opendir).  
> > 
> > That is fine.
> 
> Thanks!
> 
> > > MSVCRT's strerror(ELOOP) returns "Unknown error". UCRT has a proper
> > > message for ELOOP.  
> > 
> > Older msvcr* versions probably do not support ELOOP. It could be fixed
> > by introducing a wrapper into mingw-w64 which adds the missing
> > translation.
> 
> Since ELOOP should be uncommon, "Unknown error" should be fine. The
> message from UCRT is correct only for symlink loop; it's misleading if
> the reason is invalid data in a reparse point.
> 
> That is, if ELOOP feels otherwise better than ENOENT for
> ERROR_CANT_RESOLVE_FILENAME, the lack of message in MSVCRT shouldn't
> matter. It was just one tiny thing I happened to spot.
> 
> > > (3)
> > > I found old Microsoft docs on the web which, if they can trusted,
> > > say that WC_NO_BEST_FIT_CHARS isn't available on Win95 and NT4.  
> > 
> > That is truth. I think that I have already mentioned it. Official doc:
> > https://web.archive.org/web/20070224052921/http://msdn.microsoft.com/library/en-us/intl/unicode_17si.asp
> > https://web.archive.org/web/20070320075443/http://msdn.microsoft.com/library/en-us/intl/unicode_2bj9.asp
> 
> Sorry, you might have. Thanks!
> 
> > For detection if WC_NO_BEST_FIT_CHARS is not supported, you can do:
> > 
> > #ifdef __i386__
> >   WORD version = LOWORD(GetVersion());
> [...]
> > App-local deployment should be possible. Just would require to prepare
> > manifest and copy all DLLs. More work but I think nothing which
> > mingw-w64 could prevent or could disallow.
> 
> OK. Since _wopendir already catches 95/98/ME, it's fine to assume WinNT
> in readdir. WinXP had a x86-64 version too, so the CP_UTF8 case would
> need to be checked even outside i386.
> 
>   DWORD version = GetVersion () & 0xFF;
>   DWORD flags = (cp == CP_UTF8)
>                 ? (version >= 6 ? WC_ERR_INVALID_CHARS : 0)
>                 : (version >= 5 ? WC_NO_BEST_FIT_CHARS : 0);
> 
> This doesn't seem to make a performance difference, so caching the
> values doesn't seem worth any extra code. I attached this (without much
> testing). Preventing lossy conversion on those OSes would require more
> code, and that doesn't feel worth it.
> 
> An alternative would be to call GetLastError() == ERROR_INVALID_FLAGS
> if WideCharToMultiByte fails and retry with flags = 0.

That is too complicated.

> I wonder if NT4 i386 and XP x64 really are worth even these short extra
> bits of code. But since performance doesn't get worse, maybe it's OK as
> long as the code is correct for sure. (For example, compatibility
> settings can make GetVersion lie to some extent.)

Well, all AMD64 binaries produced by ld.bfd by default are marked as
compatible with XP x64 (which is de-facto Windows Server 2003 x64 SP1).


_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to