[ruby-dev:47894] [ruby-trunk - Bug #9409] Cygwin で "filesystem" の encoding が正しくないケース
From:
ganaware+ruby-lang-issue-tracking@...
Date:
2014-01-15 02:01:02 UTC
List:
ruby-dev #47894
チケット #9409 が Nayuta Taga によって更新されました。
ファイル test.c を追加
Usaku NAKAMURA wrote:
> Nayuta Taga wrote:
> > Windows ネイティブ環境ならばそうかもしれませんが、
> > Cygwin 環境ですので LANG に設定されている
> > エンコーディングに従うべきではないのでしょうか?
>
> Cygwinだろうがなんだろうが、Windowsにおいて、ファイルシステムの保持する
> エンコーディングをRubyが勝手に違うものとみなすことはできません。
まず、Cygwin 特有の事情をご説明いたします。
http://cygwin.com/cygwin-ug-net/setup-locale.html
> Cygwin uses the setting of the locale environment variables LC_ALL,
> LC_CTYPE, and LANG, to determine how to convert Windows filenames
> from their UTF-16 representation to the singlebyte or multibyte
> character set used by Cygwin.
>
> The setting of the locale environment variables at process startup
> is effective for Cygwin's internal conversions to and from the
> Windows UTF-16 object names for the entire lifetime of the current
> process. Changing the environment variables to another value changes
> the way filenames are converted in subsequently started child
> processes, but not within the same process.
つまり Cygwin のファイル名のエンコーディングは、
Cygwin プロセス起動時に設定されていた LANG に左右されます。
(これは一般的なUnixとは異なる挙動だと思います)
例えば、添付ファイル test.c を以下の手順で実行するとします。
1. gcc test.c
1. cygwin プロセスを全て終了させる
1. cmd.exe を起動する
1. c:\\> echo test > 日本語.txt
1. c:\\> set LANG=ja_JP.SJIS
1. c:\\> a.exe > result_sjis.txt
1. c:\\> set LANG=ja_JP.UTF-8
1. c:\\> a.exe > result_utf8.txt
この結果は以下のようになります。
* result_sjis.txt は SJIS で「日本語.txt」という文字列が含まれる。
* result_utf8.txt は UTF-8 で「日本語.txt」という文字列が含まれる。
ですから、ファイルシステムの保持するエンコーディングはLANG によって決定
されるエンコーディングだとみなしてよいと思われます。
また、コメント1の出力で
<pre>
#<Encoding:Windows-31J>
"\x{E697}\xA5\x{E69C}\xAC\x{E8AA}\x9E.txt"
</pre>
というものがありますが、これは UTF-8 の文字列に誤って Windows-31J とい
うエンコーディングが付加されている状態となります。したがって
item.force_encoding('locale') などとしなければ利用できませんのでかなり
予想外の挙動となります。
----------------------------------------
Bug #9409: Cygwin で "filesystem" の encoding が正しくないケース
https://bugs.ruby-lang.org/issues/9409#change-44308
* 作成者: Nayuta Taga
* ステータス: Open
* 優先度: Normal
* 担当者:
* カテゴリ:
* 対象バージョン:
* ruby -v: -
* Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN, 2.1: UNKNOWN
----------------------------------------
Cygwin で環境変数 LANG に設定されているエンコーディングと
システムのコードページが異なる場合
"filesystem" の encoding が正しく設定されないようです。
例えば、
* Windows 7 (日本語)
* Cygwin 環境 (CYGWIN_NT-6.1-WOW64 ****** 1.7.27(0.271/5/3) 2013-12-09 11:57 i686 Cygwin)
* 環境変数 LANG は ja_JP.UTF-8
* カレントディレクトリに「`日本語.txt`」という名前のファイルが存在
という状態で以下のコードを実行すると
```
print "LANG=#{ENV['LANG']}\n"
print "\n"
Dir.open('.').each{|item|
p item.encoding
p item
}
print "\n"
Dir.open('.',encoding: 'locale').each{|item|
p item.encoding
p item
}
print "\n"
```
例えば以下のような出力が得られます。
```
LANG=ja_JP.UTF-8
#<Encoding:Windows-31J>
"."
#<Encoding:Windows-31J>
".."
#<Encoding:Windows-31J>
"test.rb"
#<Encoding:Windows-31J>
"\x{E697}\xA5\x{E69C}\xAC\x{E8AA}\x9E.txt"
#<Encoding:UTF-8>
"."
#<Encoding:UTF-8>
".."
#<Encoding:UTF-8>
"test.rb"
#<Encoding:UTF-8>
"日本語.txt"
```
本来ならば全ての Encoding が UTF-8 であるべきだと思います。
`Init_enc_set_filesystem_encoding()` を以下のように修正すれば修正可能です。
```
Index: localeinit.c
===================================================================
--- localeinit.c (revision 44594)
+++ localeinit.c (working copy)
@@ -53,7 +53,7 @@
int idx;
#if defined NO_LOCALE_CHARMAP
# error NO_LOCALE_CHARMAP defined
-#elif defined _WIN32 || defined __CYGWIN__
+#elif defined _WIN32 && !defined __CYGWIN__
char cp[sizeof(int) * 8 / 3 + 4];
snprintf(cp, sizeof cp, "CP%d", AreFileApisANSI() ? GetACP() : GetOEMCP());
idx = rb_enc_find_index(cp);
```
---ファイル---------------------------------
test.c (189 Bytes)
--
http://bugs.ruby-lang.org/