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