Project

General

Profile

Actions

Bug #9648

closed

Dir.glob('../*') shows unexpected result in a symbolic linked directory on Windows

Added by h.shirosaki (Hiroshi Shirosaki) about 10 years ago. Updated almost 10 years ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 2.2.0dev (2014-03-17 trunk 45356) [x64-mingw32]
[ruby-core:61552]

Description

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

Updated by nobu (Nobuyoshi Nakada) almost 10 years ago

  • Status changed from Open to Feedback

Is there any files at V:/?

Updated by usa (Usaku NAKAMURA) almost 10 years ago

  • Backport changed from 2.0.0: UNKNOWN, 2.1: UNKNOWN to 2.0.0: DONTNEED, 2.1: DONTNEED

I've tested on 1.9.3-p545, 2.0.0-p451, 2.1.1 and found they are ok.
This problem is only with trunk.

Updated by nobu (Nobuyoshi Nakada) almost 10 years ago

Usaku NAKAMURA wrote:

I've tested on 1.9.3-p545, 2.0.0-p451, 2.1.1 and found they are ok.

‘OK’ means it globs as if it is a real directory but not a symlink?

This problem is only with trunk.

It doesn’t glob anything, neither the parent of the symlink, or the target?

Updated by usa (Usaku NAKAMURA) almost 10 years ago

Hi,

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, wrote:

'ok' means it globs as if it is a real directory but not a symlink?

It's too difficult for me to say it in English.

C:\foo に V:\ へのsymlinkである bar (つまり C:\foo\bar) を作り、
そこに chdir した後で Dir.glob('../*') するわけですが、結果は
期待通り C:\foo の中身(V:\ でなく)を返します。

This problem is only with trunk.

It doesn't glob anything, neither the parent of the symlink, or the target?

何も返しません。なお、targetである V:\ にはparentが存在しないことは
留意すべき事項かもしれません。
ちなみに、targetを適当なディレクトリ V:\baz に変更して実行すると、
なぜかtrunkでも正しい結果(C:\fooの中身)を返します。

Regards,

U.Nakamura

Updated by h.shirosaki (Hiroshi Shirosaki) almost 10 years ago

Nobuyoshi Nakada wrote:

Is there any files at V:/?

Yes, there are some files and directories at V:/.
If no files and directories exist at V:/, the result is same.

Updated by h.shirosaki (Hiroshi Shirosaki) almost 10 years ago

  • Status changed from Feedback to Assigned
  • Assignee set to nobu (Nobuyoshi Nakada)

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;

Updated by nobu (Nobuyoshi Nakada) almost 10 years ago

Hiroshi Shirosaki wrote:

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?

  1. ignores it and globs as if it were not a symlink
  2. matches nothing, since there is no parent directory of a root directory
  3. 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.

Updated by usa (Usaku NAKAMURA) almost 10 years ago

Nobuyoshi Nakada wrote:

In that case, what should it return?

  1. ignores it and globs as if it were not a symlink
  2. matches nothing, since there is no parent directory of a root directory
  3. treat the parent directory same as the root directory, like unixen systems

First I think it should returns the directory that the symlink exists (maybe 1 ?),
but now I think it should be 3.

Skipping READDIR usage for this case solves the bug.

I'm not sure what is a "bug" yet.

I've not tested the patch yet, but I think there are some bugs now.

  1. glob should return the root itself for the parent of the root, like unixen.
  2. glob should return the parent of the symlinked directory instead of the parent of the symlink, like unixen, too.

Updated by h.shirosaki (Hiroshi Shirosaki) almost 10 years ago

Usaku NAKAMURA wrote:

Nobuyoshi Nakada wrote:

In that case, what should it return?

  1. ignores it and globs as if it were not a symlink
  2. matches nothing, since there is no parent directory of a root directory
  3. treat the parent directory same as the root directory, like unixen systems

First I think it should returns the directory that the symlink exists (maybe 1 ?),
but now I think it should be 3.

I thought 1. is spec on Windows because old version ruby, dir command and FindFirstFile behavior is same.
I agree to change behavior unixen systems.

Updated by nobu (Nobuyoshi Nakada) almost 10 years ago

Unfortunately, it seems to need tools more than expected to deal with symbolic links on Windows.
So I'll fix only the empty result for the meantime.

Actions #11

Updated by nobu (Nobuyoshi Nakada) almost 10 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

Applied in changeset r45965.


dir.c: match plain names as-is

  • dir.c (glob_pattern_type): separate names with alphabet but no
    magical from plain.
  • dir.c (glob_helper): match plain names as-is to treat super-root
    same as the root. [ruby-core:61552] [Bug #9648]
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0