Project

General

Profile

Bug #13489

"make test-all" fails on macOS with case-sensitive filesystem

Added by watson1978 (Shizuo Fujita) 2 months ago. Updated about 2 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-dev:50088]

Description

普段使用している macOS は HFS+ case-sensitive でフォーマットしています。
"make test-all" をそのマシン上で実行すると以下のようなエラーが発生し、
どうやら conftest.c でのコンパイルエラーが原因のようです。

conftest.c には

#include <Ruby/Ruby.h>

という行が生成されるらしいのですが、
case-sensitive なファイルシステムではそのファイルパスを見つけることができません。

#include <ruby/ruby.h>

と生成されるべきかと思います。

https://github.com/ruby/ruby/blob/3e92b635fb5422207b7bbdc924e292e51e21f040/test/mkmf/test_framework.rb#L24-L33
の have_framework("Ruby") でinclude文が生成されているのかと思われます。

エラーログ

$ make test-all -j 8

... snip ...

# Running tests:


Retrying...
[  3/121] TestMkmf::TestHaveFramework#test_multi_frameworks = 0.10 s
  1) Failure:
TestMkmf::TestHaveFramework#test_multi_frameworks [/Users/watson/src/ruby/test/mkmf/test_framework.rb:29]:
have_framework: checking for Ruby... -------------------- no

"clang -o conftest -I. -I/Users/watson/src/ruby/.ext/include/x86_64-darwin16 -I/Users/watson/src/ruby/include -I./test  -I/usr/local/opt/openssl/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT   -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wno-tautological-compare -Wno-parentheses-equality -Wno-constant-logical-operand -Wno-self-assign -Wunused-variable -Wimplicit-int -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -Wdivision-by-zero -Wdeprecated-declarations -Wextra-tokens  -pipe conftest.c  -L. -L/Users/watson/src/ruby -L/usr/local/opt/openssl/lib -L. -fstack-protector -L/usr/local/lib -L/usr/local/opt/openssl/lib     -lruby.2.5.0-static -framework CoreFoundation  -framework Ruby -lpthread -lgmp -ldl -lobjc "
conftest.c:3:10: fatal error: 'Ruby/Ruby.h' file not found
#include <Ruby/Ruby.h>
         ^
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <Ruby/Ruby.h>
4:
5: int main(void){return 0;}
/* end */

"clang -o conftest -I. -I/Users/watson/src/ruby/.ext/include/x86_64-darwin16 -I/Users/watson/src/ruby/include -I./test  -I/usr/local/opt/openssl/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT   -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wno-tautological-compare -Wno-parentheses-equality -Wno-constant-logical-operand -Wno-self-assign -Wunused-variable -Wimplicit-int -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -Wdivision-by-zero -Wdeprecated-declarations -Wextra-tokens  -pipe conftest.c  -L. -L/Users/watson/src/ruby -L/usr/local/opt/openssl/lib -L. -fstack-protector -L/usr/local/lib -L/usr/local/opt/openssl/lib     -lruby.2.5.0-static -framework CoreFoundation -ObjC -framework Ruby -lpthread -lgmp -ldl -lobjc "
conftest.c:3:10: fatal error: 'Ruby/Ruby.h' file not found
#include <Ruby/Ruby.h>
         ^
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <Ruby/Ruby.h>
4:
5: int main(void){return 0;}
/* end */

--------------------

try as Objective-C

[  4/121] TestMkmf::TestHaveFramework#test_single_framework = 0.10 s
  2) Failure:
TestMkmf::TestHaveFramework#test_single_framework [/Users/watson/src/ruby/test/mkmf/test_framework.rb:25]:
have_framework: checking for Ruby... -------------------- no

"clang -o conftest -I. -I/Users/watson/src/ruby/.ext/include/x86_64-darwin16 -I/Users/watson/src/ruby/include -I./test  -I/usr/local/opt/openssl/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT   -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wno-tautological-compare -Wno-parentheses-equality -Wno-constant-logical-operand -Wno-self-assign -Wunused-variable -Wimplicit-int -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -Wdivision-by-zero -Wdeprecated-declarations -Wextra-tokens  -pipe conftest.c  -L. -L/Users/watson/src/ruby -L/usr/local/opt/openssl/lib -L. -fstack-protector -L/usr/local/lib -L/usr/local/opt/openssl/lib     -lruby.2.5.0-static -framework CoreFoundation  -framework Ruby -lpthread -lgmp -ldl -lobjc "
conftest.c:3:10: fatal error: 'Ruby/Ruby.h' file not found
#include <Ruby/Ruby.h>
         ^
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <Ruby/Ruby.h>
4:
5: int main(void){return 0;}
/* end */

"clang -o conftest -I. -I/Users/watson/src/ruby/.ext/include/x86_64-darwin16 -I/Users/watson/src/ruby/include -I./test  -I/usr/local/opt/openssl/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT   -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wno-tautological-compare -Wno-parentheses-equality -Wno-constant-logical-operand -Wno-self-assign -Wunused-variable -Wimplicit-int -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wshorten-64-to-32 -Wimplicit-function-declaration -Wdivision-by-zero -Wdeprecated-declarations -Wextra-tokens  -pipe conftest.c  -L. -L/Users/watson/src/ruby -L/usr/local/opt/openssl/lib -L. -fstack-protector -L/usr/local/lib -L/usr/local/opt/openssl/lib     -lruby.2.5.0-static -framework CoreFoundation -ObjC -framework Ruby -lpthread -lgmp -ldl -lobjc "
conftest.c:3:10: fatal error: 'Ruby/Ruby.h' file not found
#include <Ruby/Ruby.h>
         ^
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <Ruby/Ruby.h>
4:
5: int main(void){return 0;}
/* end */

--------------------

try as Objective-C

[ 20/121] TestFileExhaustive#test_expand_path = 0.00 s
  3) Failure:
TestFileExhaustive#test_expand_path [/Users/watson/src/ruby/test/ruby/test_file_exhaustive.rb:750]:
"\uFEFF".
<"/var/folders/fs/gltv6wcd3m70hcgqcp2njt_80000gn/T/rubytest-file20170420-79876-gvlo69/file.test"> expected but was
<"/var/folders/fs/gltv6wcd3m70hcgqcp2njt_80000gn/T/rubytest-file20170420-79876-gvlo69/file.test">.

Finished tests in 223.305106s, 75.8290 tests/s, 9835.1132 assertions/s.
16933 tests, 2196231 assertions, 3 failures, 0 errors, 80 skips

ruby -v: ruby 2.5.0dev (2017-04-20 trunk 58401) [x86_64-darwin16]
make: *** [yes-test-all] Error 3
[trunk][~/src/ruby]$                                                                                                           rbenv:2.4.1

Associated revisions

Revision 58431
Added by nobu (Nobuyoshi Nakada) 2 months ago

test_framework.rb: for case-sensitive filesystem

  • test/mkmf/test_framework.rb (test_single_framework): fix header
    file name for case-sensitive filesystem. it may not be same as
    the framework name, but should be the actual file name.
    [Bug #13489]

  • test/mkmf/test_framework.rb (test_multi_frameworks): ditto.

Revision 58447
Added by nobu (Nobuyoshi Nakada) 2 months ago

test_file_exhaustive.rb: check case-sensitive fs

  • test/ruby/test_file_exhaustive.rb (test_expand_path): dump expanded file name, not only appended char, for case-sensitive filesystem. [Bug #13489]

History

#1 [ruby-dev:50089] Updated by nobu (Nobuyoshi Nakada) 2 months ago

  • Status changed from Open to Feedback

Frameworkが有効な場合は <Foo/bar.h>$(FRAMEWORKSDIR)/Foo.framework/Headers/bar.h が読まれるものと理解しているのですが、以下のソースは clang -ObjC でコンパイルできるでしょうか。

#include <ruby/ruby.h>

int main(void) {return 0;}

#2 [ruby-dev:50090] Updated by watson1978 (Shizuo Fujita) 2 months ago

nobu (Nobuyoshi Nakada) wrote:

Frameworkが有効な場合は <Foo/bar.h>$(FRAMEWORKSDIR)/Foo.framework/Headers/bar.h が読まれるものと理解しているのですが

正しいと思います。

conftest.c:3:10: fatal error: 'Ruby/Ruby.h' file not found
#include <Ruby/Ruby.h>
         ^
1 error generated.

というエラーを見て、include/ruby/ruby.h のファイルを参照しているのかと誤解しておりました。

#3 [ruby-dev:50091] Updated by watson1978 (Shizuo Fujita) 2 months ago

clang はデフォルトで
- /System/Library/Frameworks
- /Library/Frameworks
の中からフレームワークを探索します。(以下のように確認できます)

$ clang -x c -v -E /dev/null
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.6.0

... snip ...

 /System/Library/Frameworks (framework directory)
 /Library/Frameworks (framework directory)

問題は、/System/Library/FrameworksRuby.framework があり Ruby.framework/Headers/ruby.h が存在しています。
conftest.c をコンパイルする際には、テストで生成した Ruby.framework ではなく、

/System/Library/Frameworks/Ruby.framework/Headers/ruby.h

を参照しているものと思われます。
そのため、case sensitive ではない Filesystem では Ruby.framework/Headers/ruby.h が include でき動いているのかと
推測します。

https://github.com/ruby/ruby/blob/3e92b635fb5422207b7bbdc924e292e51e21f040/test/mkmf/test_framework.rb#L19
-Fパス のようにフレームワークが置かれている場所を適切に指定して頂けると良いかと思います。

#4 [ruby-dev:50092] Updated by watson1978 (Shizuo Fujita) 2 months ago

まだテスト内容を誤解しているようで

/System/Library/Frameworks/Ruby.framework/Headers/ruby.h

を include することは意図されていて、#include <Ruby/Ruby.h> となっているのが問題だっただけなのでしょうか?

#include <Ruby/ruby.h>

と conftest.c に書かれていれば良いだけのような気がしてきました。

#5 [ruby-dev:50093] Updated by watson1978 (Shizuo Fujita) 2 months ago

以下の変更をテストに加え #include <Ruby/ruby.h> を生成することで、conftest.c のコンパイルエラーは解消しました。

diff --git a/test/mkmf/test_framework.rb b/test/mkmf/test_framework.rb
index ae05b0cffc..9959437f6f 100644
--- a/test/mkmf/test_framework.rb
+++ b/test/mkmf/test_framework.rb
@@ -22,11 +22,11 @@ def create_framework(fw, hdrname = "#{fw}.h")
     end

     def test_single_framework
-      assert(have_framework("Ruby"), mkmflog("try as Objective-C"))
+      assert(have_framework(["Ruby", "ruby.h"]), mkmflog("try as Objective-C"))
     end

     def test_multi_frameworks
-      assert(have_framework("Ruby"), mkmflog("try as Objective-C"))
+      assert(have_framework(["Ruby", "ruby.h"]), mkmflog("try as Objective-C"))
       create_framework("MkmfTest") do |fw|
         assert(have_framework(fw), MKMFLOG)
       end

テスト結果は以下のようになりました。case sensitive ではない Filesystem を利用している macOS では、
上記の変更を加えてもエラーは無かったので、まだ何か問題があるようです。

$ make test-all -j 8

... snip ...

# Running tests:


Retrying...
[ 16/117] TestFileExhaustive#test_expand_path = 0.00 s
  1) Failure:
TestFileExhaustive#test_expand_path [/Users/watson/src/ruby/test/ruby/test_file_exhaustive.rb:750]:
"\uFEFF".
<"/var/folders/fs/gltv6wcd3m70hcgqcp2njt_80000gn/T/rubytest-file20170421-96294-zcv8tx/file.test"> expected but was
<"/var/folders/fs/gltv6wcd3m70hcgqcp2njt_80000gn/T/rubytest-file20170421-96294-zcv8tx/file.test">.

Finished tests in 222.421277s, 75.9415 tests/s, 9876.3168 assertions/s.
16891 tests, 2196703 assertions, 1 failures, 0 errors, 80 skips

ruby -v: ruby 2.5.0dev (2017-04-20 trunk 58401) [x86_64-darwin16]
make: *** [yes-test-all] Error 1

#6 [ruby-dev:50094] Updated by nobu (Nobuyoshi Nakada) 2 months ago

watson1978 (Shizuo Fujita) wrote:

以下の変更をテストに加え #include <Ruby/ruby.h> を生成することで、conftest.c のコンパイルエラーは解消しました。

気になるのは、macOSの"framework"としてはどちらが本来意図されたものなのかというところですね。

  1. framework名とヘッダ名に直接の関係はない
  2. framework名とヘッダ名は一致しているべきであり、そうでないものはバグ

El Capitanで探してみると、Ruby.framework以外にも同様に大文字小文字だけが一致しないヘッダがいくつかありました。

$ ruby -e 'ARGV.each{|fw| File.exist?(h="#{fw}/Headers/#{File.basename(fw, ".*")}.h") && (f=Dir.glob(h)[0])!=h && puts(f)}' /System/Library/Frameworks/*.framework
/System/Library/Frameworks/AGL.framework/Headers/agl.h
/System/Library/Frameworks/GLUT.framework/Headers/glut.h
/System/Library/Frameworks/LDAP.framework/Headers/ldap.h
/System/Library/Frameworks/OpenCL.framework/Headers/opencl.h
/System/Library/Frameworks/Ruby.framework/Headers/ruby.h
/System/Library/Frameworks/Tcl.framework/Headers/tcl.h
/System/Library/Frameworks/Tk.framework/Headers/tk.h

これで検索したところ、同じ理由でエラーになるという話が見つかりました。
https://trac.macports.org/ticket/26612

ここでは、OpenCL/OpenCL.hをOpenCL/opencl.hに変えたそうで、「直接の関係はない」としたようです。

#7 Updated by nobu (Nobuyoshi Nakada) 2 months ago

  • Status changed from Feedback to Closed

Applied in changeset trunk|r58431.


test_framework.rb: for case-sensitive filesystem

  • test/mkmf/test_framework.rb (test_single_framework): fix header
    file name for case-sensitive filesystem. it may not be same as
    the framework name, but should be the actual file name.
    [Bug #13489]

  • test/mkmf/test_framework.rb (test_multi_frameworks): ditto.

#8 [ruby-dev:50095] Updated by watson1978 (Shizuo Fujita) 2 months ago

  • Status changed from Closed to Open

まだ、以下のテストが case-sensitive filesystem で通らないのでチケットを再オープンいたします。
(該当箇所は https://github.com/ruby/ruby/blob/9c5c31c8b70106989a218e41935c0ab75f631b34/test/ruby/test_file_exhaustive.rb#L743-L757 です)

$ make test-all -j 8

... snip ...

# Running tests:


Retrying...
[ 16/117] TestFileExhaustive#test_expand_path = 0.00 s
  1) Failure:
TestFileExhaustive#test_expand_path [/Users/watson/src/ruby/test/ruby/test_file_exhaustive.rb:752]:
"file.test".
<"/var/folders/fs/gltv6wcd3m70hcgqcp2njt_80000gn/T/rubytest-file20170422-77354-1htb141/file.test"> expected but was
<"/var/folders/fs/gltv6wcd3m70hcgqcp2njt_80000gn/T/rubytest-file20170422-77354-1htb141/file.test">.

Finished tests in 222.140321s, 75.6999 tests/s, 9906.4861 assertions/s.
16816 tests, 2200630 assertions, 1 failures, 0 errors, 82 skips

ruby -v: ruby 2.5.0dev (2017-04-22 trunk 58448) [x86_64-darwin16]
make: *** [yes-test-all] Error 1

どうやら Kernel.open の振る舞いが case-sensitive と非 case-sensitive で違うようです。

regular_file = "file.test"
system "touch #{regular_file}"

c = "\u{feff}"
file = regular_file + c
begin
  open(file) {}
  puts "** Success **"
rescue
  puts "** Exception **"
end

外付けのドライブを 非 case-sensitive でフォーマットしそこで実行すると、以下のようにファイルがオープンできています。

$ ruby -v test_file.rb
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]
** Success **

case-sensitive な内蔵ディスク上で実行すると、以下のようにファイルに失敗しています。

$ ruby -v test_file.rb
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]
** Exception **

この振る舞いの違いは Kernel.open の不具合なのかと推測しておりますが、いかがでしょうか。

#9 [ruby-dev:50096] Updated by watson1978 (Shizuo Fujita) 2 months ago

Kernel.open で使用している POSIX open が case-sensitive と非 case-sensitive で振る舞いが違うようです。Kernel.open の処理を抜き出したもので試してみました。

#include <stdio.h>
#include <string.h>
#include <fcntl.h>

int main()
{
    const char *file = "file.test";
    char pathname[128] = {0};
    unsigned char sufix[] = { 0xef, 0xbb, 0xbf };
    int flags = O_CLOEXEC;
    mode_t mode = O_NOFOLLOW | O_FSYNC | O_EXLOCK | O_SHLOCK | O_NONBLOCK | O_RDWR;
    int ret;

    strcpy(pathname, file);
    memcpy(&pathname[strlen(file)], sufix, sizeof(sufix));

    ret = open(pathname, flags, mode);
    printf("ret = %d\n", ret);
    return 0;
}

非 case-sensitive では以下のような結果になります。

$ touch file.test
$ clang file.c
$ ./a.out
ret = 3

case-sensitive では以下のような結果になり、ファイルのオープンに失敗します。

$ touch file.test
$ clang file.c
$ ./a.out
ret = -1

該当のテストが、非 case-sensitive での振る舞いに依存しているように見受けられるので、
以下のように 非 case-sensitive のときだけ実行するようにしてはいかがでしょう?

diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb
index a3c2a4018a..07b58878e5 100644
--- a/test/ruby/test_file_exhaustive.rb
+++ b/test/ruby/test_file_exhaustive.rb
@@ -742,16 +742,26 @@ def test_expand_path
     end
     case RUBY_PLATFORM
     when /darwin/
-      ["\u{feff}", *"\u{2000}"..."\u{2100}"].each do |c|
-        file = regular_file + c
-        full_path = File.expand_path(file)
-        mesg = proc {File.basename(full_path).dump}
-        begin
-          open(file) {}
-        rescue
-          assert_equal(file, full_path, mesg)
-        else
-          assert_equal(regular_file, full_path, mesg)
+      case_sensitive_filesystem = false
+      begin
+        open(regular_file.upcase) {}
+      rescue
+        # if Kernel.open cannot open upcased file path, the test is running under case-sensitive filesystem
+        case_sensitive_filesystem = true
+      end
+
+      unless case_sensitive_filesystem
+        ["\u{feff}", *"\u{2000}"..."\u{2100}"].each do |c|
+          file = regular_file + c
+          full_path = File.expand_path(file)
+          mesg = proc {File.basename(full_path).dump}
+          begin
+            open(file) {}
+          rescue
+            assert_equal(file, full_path, mesg)
+          else
+            assert_equal(regular_file, full_path, mesg)
+          end
         end
       end
     end

#10 [ruby-dev:50098] Updated by nobu (Nobuyoshi Nakada) 2 months ago

これでどうでしょうか。

diff --git i/dir.c w/dir.c
index e3099f4973..b02640e912 100644
--- i/dir.c
+++ w/dir.c
@@ -1528,34 +1528,52 @@ join_path(const char *path, long len, int dirsep, const char *name, size_t namle

 #ifdef HAVE_GETATTRLIST
 # if defined HAVE_FGETATTRLIST
-#   define is_case_sensitive(dirp, path) is_case_sensitive(dirp)
+#   define is_case_sensitive(dirp, path) ruby_dir_case_sensitive_p(dirp)
 # else
-#   define is_case_sensitive(dirp, path) is_case_sensitive(path)
+#   define is_case_sensitive(dirp, path) ruby_path_case_sensitive_p(path)
 # endif
-static int
-is_case_sensitive(DIR *dirp, const char *path)
-{
+typedef struct {
+    struct attrlist list;
     struct {
    u_int32_t length;
    vol_capabilities_attr_t cap[1];
-    } __attribute__((aligned(4), packed)) attrbuf[1];
-    struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, 0, ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES};
-    const vol_capabilities_attr_t *const cap = attrbuf[0].cap;
+    } __attribute__((aligned(4), packed)) attr;
+} vol_case_sensitive_attr_t;
+#define vol_case_sensitive_attr_init \
+    {{ATTR_BIT_MAP_COUNT, 0, 0, ATTR_VOL_INFO|ATTR_VOL_CAPABILITIES}}
+
+static inline int
+vol_case_sensitive_p(const vol_capabilities_attr_t *const cap)
+{
     const int idx = VOL_CAPABILITIES_FORMAT;
     const uint32_t mask = VOL_CAP_FMT_CASE_SENSITIVE;
-
-#   if defined HAVE_FGETATTRLIST
-    if (fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
-   return -1;
-#   else
-    if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
-   return -1;
-#   endif
     if (!(cap->valid[idx] & mask))
    return -1;
     return (cap->capabilities[idx] & mask) != 0;
 }

+# if defined HAVE_FGETATTRLIST
+static int
+ruby_dir_case_sensitive_p(DIR *dirp)
+{
+    vol_case_sensitive_attr_t a = vol_case_sensitive_attr_init;
+
+    if (fgetattrlist(dirfd(dirp), &a.list, &a.attr, sizeof(a.attr), FSOPT_NOFOLLOW))
+   return -1;
+    return vol_case_sensitive_p(a.attr.cap);
+}
+# endif
+
+int
+ruby_path_case_sensitive_p(const char *path)
+{
+    vol_case_sensitive_attr_t a = vol_case_sensitive_attr_init;
+
+    if (getattrlist(path, &a.list, &a.attr, sizeof(a.attr), FSOPT_NOFOLLOW))
+   return -1;
+    return vol_case_sensitive_p(a.attr.cap);
+}
+
 static char *
 replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int flags, rb_pathtype_t *type)
 {
diff --git i/file.c w/file.c
index c576c85c0a..be528fee1b 100644
--- i/file.c
+++ w/file.c
@@ -242,6 +242,8 @@ rb_str_encode_ospath(VALUE path)

 #ifdef __APPLE__
 # define NORMALIZE_UTF8PATH 1
+int ruby_path_case_sensitive_p(const char *path);
+
 static VALUE
 rb_str_append_normalized_ospath(VALUE str, const char *ptr, long len)
 {
@@ -272,10 +274,12 @@ rb_str_normalize_ospath(const char *ptr, long len)
     const char *p = ptr;
     const char *e = ptr + len;
     const char *p1 = p;
-    VALUE str = rb_str_buf_new(len);
     rb_encoding *enc = rb_utf8_encoding();
-    rb_enc_associate(str, enc);
+    VALUE str = rb_enc_str_new(ptr, len, enc);

+    if (ruby_path_case_sensitive_p(RSTRING_PTR(str)) == 1)
+   return str;
+    rb_str_set_len(str, 0);
     while (p < e) {
    int l, c;
    int r = rb_enc_precise_mbclen(p, e, enc);

#11 [ruby-dev:50099] Updated by watson1978 (Shizuo Fujita) about 2 months ago

パッチをあててみましたが、状況は変わらないようです。

Kernel.open が呼び出す rb_file_open_generic() の rb_sysopen() で「例外が発生する/発生しない」というのが
問題なのかと思っておりましたが、パッチで変更があった File.expand_path や Dir.glob の問題なのでしょうか?

Also available in: Atom PDF