彷徨えるフジワラ

年がら年中さまよってます

cygwin 環境での case insensitive 性

※ 2011/12/12 追記分あり

Mercurial の case insensitive なファイルシステム上での cp932 符号化に関する挙動を正すパッチをアレコレ始めたら、一言に case insensitive と言っても、ファイルシステム毎に色々な癖と言うか固有挙動があるために、単に各種文字コードを通すだけでは駄目だということで、四苦八苦な今日この頃。

case insensitive ファイルシステム文字コードに関する話は、別途詳しく書きたいと思うのだが、とりあえず cygwin のアレな挙動についてメモしておく。

cygwin 環境における任意のファイル/ディレクトリへの絶対パスは、基本的に "/cygdrive/" で始まるのだが、例えば Windows 表記で "C:\hoge/hage" ファイルが存在する場合に:

  • /cygdrive/c/hoge/hage はアクセス可能
  • /cygdrive/C/HOGE/HAGE はアクセス可能
  • /CYGDRIVE/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 追記分: ここまで