Dir.glob('../*') shows unexpected result if current directory is a symbolic linked directory on Windows.
This issue seems to be introduced by r44802.
The following is a test case.
C:\foo>mklink /D bar V:\
symbolic link created for bar <<===>> V:\
C:\foo>cd bar
C:\foo\bar>ruby -ve "p Dir.glob('../*')"
ruby 1.9.3p392 (2013-02-22) [i386-mingw32]
["../a", "../bar"]
C:\foo\bar>\rubyinstaller\sandbox\ruby21_build\miniruby.exe -ve "p Dir.glob('../*')"
ruby 2.2.0dev (2014-02-04 trunk 45356) [x64-mingw32]
[]
C:\foo\bar>dir ..
Volume in drive C is OS
Volume Serial Number is 6629-B36B
Directory of C:\foo
2014/03/17 18:58 <DIR> .
2014/03/17 18:58 <DIR> ..
2014/03/17 18:45 6 a
2014/03/17 18:58 <SYMLINKD> bar [V:\]
1 File(s) 6 bytes
3 Dir(s) 81,915,052,032 bytes free
In message "[ruby-core:62170] [ruby-trunk - Bug #9648] Dir.glob('../*') shows unexpected result in a symbolic linked directory on Windows"
on Apr.26,2014 16:22:34, nobu@ruby-lang.org wrote:
'ok' means it globs as if it is a real directory but not a symlink?
If current directory is C:\foo\bar (linked to V:), READDIR of '.' (i.e. FindFirstFile(".\\*", &d)) globs linked directory (V:/), but the result doesn't have '..'.
So we cannot trace parent directory.
Skipping READDIR usage for this case solves the bug.
diff --git a/dir.c b/dir.c
index f456e8b..91a8495 100644
--- a/dir.c
+++ b/dir.c
@@ -1397,6 +1397,14 @@ glob_helper(
if (exist == NO || isdir == NO) return 0;
+ if (!(magical || recursive) && (FNM_SYSCASE && plain)) {
+ /* READDIR will not return '..' at a directory which is symbolic linked to
+ a root directory on Windows. We don't use READDIR to get '..'. */
+ struct glob_pattern *p = *beg;
+ if (p && strcmp(p->str, "..") == 0)
+ goto literally;
+ }
+
if (magical || recursive || ((FNM_SYSCASE || HAVE_HFS) && plain)) {
struct dirent *dp;
DIR *dirp;
If current directory is C:\foo\bar (linked to V:), READDIR of '.' (i.e. FindFirstFile(".\\*", &d)) globs linked directory (V:/), but the result doesn't have '..'.
So we cannot trace parent directory.
In that case, what should it return?
ignores it and globs as if it were not a symlink
matches nothing, since there is no parent directory of a root directory
treat the parent directory same as the root directory, like unixen systems
Skipping READDIR usage for this case solves the bug.
I'm not sure what is a "bug" yet.
+ if (!(magical || recursive) && (FNM_SYSCASE && plain)) {
This "super-root" issue is not common to all case-insensitive systems,
but seems a DOSISH centric probably.