2009年7月7日火曜日

Dokan Ruby 0.1.4 のパッチ

Windows用の仮想ファイルシステムドライバDokanライブラリを使ってみた。
Dokan Rubyを使うとRubyで手軽にファイルシステムを書けてしまうという
素晴らしいライブラリだ。

そのサンプルにmirror.rbというものがある。
任意のフォルダを指定して、ドライブにマウントするサンプルだ。
SUBSTコマンドのようなもの。

しかし、このmirror.rbでマウントしたドライブは、
Explorerでファイルを見ることはできるものの、
コマンドプロンプトで cd FolderName を実行しても
「指定されたパスが見つかりません。」と言われる。

ばぐ?

Dokanライブラリのreadme.ja.txtに答えが書いてあった。

ディレクトリに対するアクセスで有るのにも関わらず,CreateFile が呼ばれることもあります.その場合は,DokanFileInfo->IsDirectory は FALSE がセットされています.ディレクトリの属性を取得する場合などに OpenDirectory ではなく,CreateFileが呼ばれるようです.ディレクトリに対するアクセスなのにも関わらず,CreateFile が呼ばれた場合は,必ず DokanFileInfo->IsDirectory にTRUEをセットしてからreturnしてください.正しくセットされていないと,Dokanライブラリは,そのアクセスがディレクトリに対するアクセスかどうか判断できず,Dokanファイルシステムで Windows に対して正確な情報を返すことが出来なくなります.

mirror.rbはopenでFile.file?(path)の結果を返していて、ディレクトリの場合に対応できていない。
そもそも、dokan_lib.soでFileInfo#directory=が定義されていないし、instans_eval等で無理矢理値を変えたとしても、FileInfoをDokanFileInfoに書き戻すコードは無かった。

dokan_lib.cとmirror.rbを少しだけ書き換えたらうまくいった。めでたしめでたし♪

dokan_lib.c.patch
110a111,118
> static VALUE
> DR_FileInfo_set_directory_p(
> VALUE self,
> VALUE value)
> {
> rb_iv_set(self, "@is_directory", value);
> return self;
> }
151a160
> VALUE is_dir;
154a164,166
>
> is_dir = rb_iv_get(FileInfo, "@is_directory");
> DokanFileInfo->IsDirectory = (Qfalse != is_dir && Qnil != is_dir);
> /* DokanFileInfo->IsDirectory = RTEST(is_dir); */ /* 普通はこう書くのかな? */
173c185,186
< rb_define_method(g_cFileInfo, "directory?", DR_FileInfo_directory_p, 0);
---
> rb_define_method(g_cFileInfo, "directory?", DR_FileInfo_directory_p, 0);
> rb_define_method(g_cFileInfo, "directory=", DR_FileInfo_set_directory_p, 1);
mirror.rb.patch
19c19,24
< File.file?(get_path(path))
---
> s = File.stat(get_path(path)) rescue nil
> if s
> fileinfo.directory = s.directory?
> true
> else
> false
> end

0 件のコメント:

コメントを投稿