cygwin 環境での case insensitive 性
※ 2011/12/12 追記分あり
Mercurial の case insensitive なファイルシステム上での cp932 符号化に関する挙動を正すパッチをアレコレ始めたら、一言に case insensitive と言っても、ファイルシステム毎に色々な癖と言うか固有挙動があるために、単に各種文字コードを通すだけでは駄目だということで、四苦八苦な今日この頃。
case insensitive ファイルシステムと文字コードに関する話は、別途詳しく書きたいと思うのだが、とりあえず cygwin のアレな挙動についてメモしておく。
cygwin 環境における任意のファイル/ディレクトリへの絶対パスは、基本的に "/cygdrive/" で始まるのだが、例えば Windows 表記で "C:\hoge/hage" ファイルが存在する場合に:
という、中途半端な case insensitive 挙動 .... orz
パス冒頭の "/cygdrive/" 文字列と比較する内部処理が、文字大小を無視した文字列比較ではなく、単純文字列比較で実装されている模様。
まぁ、性能観点で見た場合、文字大小の無視は「塵も積もれば」的な劣化要因ではあるのだが、case insensitive なファイルシステム上の仮想環境実現として、case sensitive な実装ってのはどうなんだろう?という印象が。
これのお陰で、文字大小の標準化 (normalization) として upper をかました文字列だと、stat(2) がエラーを返してしまうことから、処理が継続出来なくなってしまう。
『それじゃぁ、標準化に lower を使えばいいんじゃね?』という話もあるのだけれど、各種 case insensitive なファイルシステムの挙動を見た場合、国際化対応を考えると upper の方がよさげ、という結論になってしまうのだ。
# 先述したように、これに関しては後日にでも
元々のパッチ作成動機が、『cygwin 上の Mercurial で cp932 なファイル名をきちんと通す』なので、cygwin 環境で通らない修正を入れたくは無いのだけれど、修正内容がちょっと不恰好になるから、Matt の採否が心配だなぁ。
パッチ対象の関数での処理を分割してしまえば、少しは綺麗なコードになるのだけれど、そうなると再利用的な点で嬉しくないし....
>>>> 2011/12/12 追記分: ここから
エントリ公開後に、twitter 経由での情報提供が:
で、マウントポイントに関して、色々追試してみたところ、例えば "/usr/bin" に関しては:
- "ls /usr/BIN" はアウト
- "ls /USR/bin" はアウト
という具合に、case 違いは軒並みアウト。
ここで "ls /USR" とかを実施すると、エラーメッセージ "/USR: No such file or directory" が出力されるので、一見アウトっぽいけど:
- "/USR" への stat(1) は通る ※ stat コマンドで確認
- bin 以外の /usr 配下の要素は表示される
という按配なので、"/USR/bin" の属性を取りに行って失敗しているっぽい。つまりは「マウントポイントだけは駄目」での一貫性が見られる。
マウントポイントが絡むと「ファイルシステム横断」の判定が必要、というのは確かにわからなくも無い。
とは言いつつ、"/CYGDRIVE/c" が駄目で "/cygdrive/C" は OK というのは、このルールには反するんだよなぁ....。まぁ、"/cygdrive" は特殊だから、と言えばそうなのだけれど。
単に「ドライブ文字は1文字だけ」で文字大小両方への対応が簡単だから、ちょっとだけ頑張った、とかいう落ちじゃないだろうな? > Cygwin
<<<< 2011/12/12 追記分: ここまで