58 lines
2.2 KiB
Diff
58 lines
2.2 KiB
Diff
From 6055cf10fa66f74732ec91b4e07e2f8415f2a412 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B5=D0=B8=CC=86=20=D0=9F?=
|
|
=?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=BE=D0=B2?= <alexey.pawlow@gmail.com>
|
|
Date: Sun, 14 Apr 2019 22:13:51 +0300
|
|
Subject: [PATCH 10/N] path_conv: special-case root directory to have trailing
|
|
slash
|
|
|
|
When converting `/c/` to `C:\`, the trailing slash is actually really
|
|
necessary, as `C:` is not an absolute path.
|
|
|
|
We must be very careful to do this only for root directories, though. If
|
|
we kept the trailing slash also for, say, `/y/directory/`, we would run
|
|
into the following issue: On FAT file systems, the normalized path is
|
|
used to fake inode numbers. As a result, `Y:\directory\` and
|
|
`Y:\directory` have different inode numbers!!!
|
|
|
|
This would result in very non-obvious symptoms. Back when we were too
|
|
careless about keeping the trailing slash, it was reported to the Git
|
|
for Windows project that the `find` and `rm` commands can error out on
|
|
FAT file systems with very confusing "No such file or directory" errors,
|
|
for no good reason.
|
|
|
|
During the original investigation, Vasil Minkov pointed out in
|
|
https://github.com/git-for-windows/git/issues/1497#issuecomment-372665870,
|
|
that this bug had been fixed in Cygwin as early as 1997... and the bug
|
|
was unfortunately reintroduced into early MSYS2 versions.
|
|
|
|
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
|
---
|
|
winsup/cygwin/path.cc | 7 +++++++
|
|
1 file changed, 7 insertions(+)
|
|
|
|
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
|
|
index 4a6157d..a84706e 100644
|
|
--- a/winsup/cygwin/path.cc
|
|
+++ b/winsup/cygwin/path.cc
|
|
@@ -709,6 +709,12 @@ path_conv::check (const char *src, unsigned opt,
|
|
need_directory = 1;
|
|
*--tail = '\0';
|
|
}
|
|
+ /* Special case for "/" must set need_directory, without removing
|
|
+ trailing slash */
|
|
+ else if (tail == path_copy + 1 && isslash (tail[-1]))
|
|
+ {
|
|
+ need_directory = 1;
|
|
+ }
|
|
path_end = tail;
|
|
|
|
/* Scan path_copy from right to left looking either for a symlink
|
|
@@ -1248,6 +1254,7 @@ path_conv::check (const char *src, unsigned opt,
|
|
cfree (wide_path);
|
|
wide_path = NULL;
|
|
}
|
|
+
|
|
if (need_directory)
|
|
{
|
|
size_t n = strlen (this->path);
|