Re: [PATCH v2] lstat(mingw): correctly detect ENOTDIR scenarios
- From
Eric Sunshine <sunshine@sunshineco.com>
- Date
- Jul 28, 2022, 23:27 UTC
- Message-ID
- <CAPig+cSpjchBUMi9qjLTu_3B3BbVDFKueeTKJNOgR4BtA-8arQ@mail.gmail.com>
- In-Reply-To
- <pull.1291.v2.git.1659018558989.gitgitgadget@gmail.com>
On Thu, Jul 28, 2022 at 10:29 AM Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com> wrote:
> Files' attributes can indicate more than just whether they are files or > directories. It was reported in Git for Windows that on certain network > shares, this let to a nasty problem trying to create tags:
s/let/led/
(not worth a re-roll)
Show 41 quoted lines
> $ git tag -a -m "automatic tag creation" test_dir/test_tag > fatal: cannot lock ref 'refs/tags/test_dir/test_tag': unable to resolve reference 'refs/tags/test_dir/test_tag': Not a directory > > Note: This does not necessarily happen with all types of network shares. > One setup where it _did_ happen is a Windows Server 2019 VM, and as > hinted in > > http://woshub.com/slow-network-shared-folder-refresh-windows-server/ > > in the indicated instance the following commands worked around the bug: > > Set-SmbClientConfiguration -DirectoryCacheLifetime 0 > Set-SmbClientConfiguration -FileInfoCacheLifetime 0 > Set-SmbClientConfiguration -FileNotFoundCacheLifetime 0 > > This would impact performance negatively, though, as it essentially > turns off all caching, therefore we do not want to require users to do > that just to be able to use Git on Windows. > > The underlying bug is in the code added in 4b0abd5c695 (mingw: let > lstat() fail with errno == ENOTDIR when appropriate, 2016-01-26) that > emulates the POSIX behavior where `lstat()` should return `ENOENT` if > the file or directory simply does not exist but could be created, and > `ENOTDIR` if there is no file or directory nor could there be because a > leading path already exists and is not a directory. > > In that code, the return value of `GetFileAttributesW()` is interpreted > as an enum value, not as a bit field, so that a perfectly fine leading > directory can be misdetected as "not a directory". > > As a consequence, the `read_refs_internal()` function would return > `ENOTDIR`, suggesting not only that the tag in the `git tag` invocation > above does not exist, but that it cannot even be created. > > Let's fix the code so that it interprets the return value of the > `GetFileAtrtibutesW()` call correctly. > > This fixes https://github.com/git-for-windows/git/issues/3727 > > Reported-by: Pierre Garnier <pgarnier@mega.com> > Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>