玩式草子─ソフトウェアとたわむれる日々

第45回Nexus 7とMTP[その2]

前回紹介したように、gmtpに文字コード回りのパッチをあてることで、無事Plamo Linux環境とNexus 7の間でファイルをやりとりできるようになりました。しかしながら、あれこれ使っているとgmtpの欠点も目についてきました。

まず最初に気になったのは、gmtpを起動してからNexus 7側のデータが表示されるまでにずいぶん時間がかかることです。しばらく待っていれば表示はされるものの、どれくらい待たされるのかが分からないのはちょっと苦痛です。

またgmtpには、ファイルの転送のみならず、ファイルの削除や移動といった機能も用意されてはいるものの、Nexus 7上ではそれらの処理は機能しないようで、操作しようとすると多数のエラーメッセージが出力されます。

前回紹介したように、EUC-JPを利用可能にするための修正も、ファイル名の文字コードしか直していないので、途中のパス名に日本語があるとエラーダイアログが表示されるのも見苦しいところです。

そのようなわけで、gmtp以外に何かいいツールはないか、と探してみることにしました。

FUSEとjmtpfs

そうして見つけたのがjmtpfsです。mtpfsはgmtpとは全く異なる視点から開発されたソフトウェアです。すなわち、gmtpがMTPデバイス上のファイルを操作するための、いわゆるファイル管理ツールとして設計されているのに対し、jmtpfsはMTPデバイスを従来のUSBマス・ストレージクラスと同じように、ファイルシステムとしてマウントする機能を提供するように設計されています。

しかし前回にも触れたように、自律的にファイルを管理しているMTPデバイスでは、単純なUSBストレージデバイスとは異なり、ファイルシステムそのものは外部に公開せず、データのやりとりはMTPプロトコルを介することになっています。そこでjmtpfsでは、MTPデバイスへのアクセスはlibmtpを用い、その結果をカーネルへFUSEの機能を用いて提供することで、MTPデバイスを仮想的なファイルシステムとして見せるような設計になっています。

FUSE(Filesystem in USErspace)は、本来カーネル内部の処理であるファイルシステムに関する操作をユーザ領域で実行可能にする機能です。

HDD等の記憶装置とデータをやりとりするファイルシステムは、速度と信頼性を要求される重要かつ複雑な機能で、たいていのOSでは専用に設計された標準ファイルシステムがカーネルの構成要素として不可分に組み込まれています。

一方、伝統的なUNIXに比べてずっと遅れて誕生したLinuxでは、専用のファイルシステムを開発する一方で、他のOS用に普及している各種ファイルシステムにも積極的に対応してきました。その結果、モジュールドライバ化された多数のファイルシステムが利用可能で、それらを必要に応じて組み込んだり取り外したりできるようになっています。

Linuxのファイルシステムはこのように柔軟性に富んだ設計になっているので、新しいファイルシステムはカーネルの他の部分とは独立したモジュールドライバとして開発することができます。しかし、他の部分とは独立に開発できると言っても、カーネル内部で動作するドライバを書くにはカーネルプログラムに関する知識が必要で、コーディングやデバッグもユーザ領域で動作する通常のソフトウェアに比べて大変です。そこで考案されたのがFUSEです。

FUSEは他のファイルシステム用のドライバ同様、モジュールとしてカーネルに組み込まれるものの、HDD等の記憶装置用のデバイスドライバを操作するのではなく、ユーザ領域で動作するソフトウェアからのデータを受け取り、あたかも記憶装置からのデータのように見せることができます。

図1 通常のファイルアクセスとFUSEを使ったアクセス
図1 通常のファイルアクセスとFUSEを使ったアクセス

すなわち、FUSEのAPIを利用して必要な情報をやりとりするようなソフトウェア(FUSE用サービス)さえ書けば、ファイルがどこにあっても、極論すればファイルの実体は存在しなくても、他のファイル操作コマンドからはHDD上の通常ファイルと同様に扱えるわけです。

このようなFUSEの特徴を利用して、tarやzipでまとめた書庫ファイルを展開せずに読み書きしたり、sshやhttp経由で利用しているネットワークサービスをローカルなファイルシステムと同様に見せたり、ファイルやディレクトリを透過的に暗号化したり、NTFSやZFSといったLinux以外のOS用のファイルシステムを利用したりするサービスが多数開発されています。

今回紹介するjmtpfsもそのようなサービスの一種で、libmtp経由でMTPデバイスにアクセスした結果をFUSE経由で他のアプリケーションに提供するように設計されているわけです。

jmtpfsとFDclone

jmtpfsのビルドは簡単で、ソースコードを展開し、configure && make installだけで済みます。作成されるのはjmtpfsというコマンドだけで、MTPデバイスをマウントしたいディレクトリを引数に指定して、このコマンドを実行すればいいだけのようです。一般ユーザとして自分のホームディレクトリ以下にマウントすることも可能なようなので、さっそく試してみました。

$ mkdir ~/Mtp
$ jmtpfs ~/Mtp
Error: Unable to open ~/.mtpz-data for reading.
Device 0 (VID=18d1 and PID=4e41) is a Google Inc (for Asus) Nexus 7 (MTP).
Android device detected, assigning default bug flags

gmtpではずいぶん時間がかかるMTPデバイスとの接続作業が、jmtpfsではあっと言う間に完了しました。dfで確認してもちゃんと見えます。

$ df -h
ファイルシス                     サイズ  使用  残り 使用% マウント位置
/dev/sdb2                           46G   28G   16G   65% /
none                               7.9G  916K  7.9G    1% /dev
/media                             7.9G     0  7.9G    0% /media
/tmp                               7.9G   72K  7.9G    1% /tmp
192.168.1.6:/share/Srcs/           299G  280G   19G   94% /share/Srcs
..
jmtpfs                              28G   14G   14G   50% /home/kojima/Mtp

これはいけるかも、と思って~/Mtp以下をのぞいてみましたが、残念ながら文字コードが合っていないようです。

$ ls ~/Mtp/
????????鴻???????若??/

NKFを使って文字コードを調べると、想像通りUTF-8になっていました。

$ ls ~/Mtp/ | nkf -g
UTF-8
$ ls ~/Mtp/ | nkf -e
内部ストレージ/

普段使っているKDEのファイルマネージャdolphinでは、ファイルシステム上の文字コードはEUC-JPだと思っているので、文字化けして使いものになりません。

図2 Dolphineから見たMTPデバイス
図2 Dolphineから見たMTPデバイス

一方、Xfce4用のファイルマネージャであるThunarには文字コードの自動認識機能があるようで、~/Mtp/以下のファイル名を正しく表示することはできるものの、別ディレクトリにあるEUC-JPなファイルを転送しようとするとエラーになってしまいます。

図3 Thunarから見たMTPデバイス
図3 Thunarから見たMTPデバイス

jmtpfsはMTPデバイスの操作には優れているようだけど、文字コードのことを考えるとgmtpを使い続けるしかないか……、そう考えている時にFDcloneというファイル管理ソフトを思い出しました。

FDcloneは、MS-DOS環境で普及していたFDというファイル管理ソフトを参考に、UNIX環境向けに開発されたCUIなファイル管理ソフトで、白井隆氏が1995年ごろから開発を続けている国内最古参のフリーソフトウェアの一つです。

FDcloneはそのような長い歴史を持つソフトウェアなだけあって、さまざまなUNIX環境、さまざまな文字コードの元で使われることが想定されていて、ディレクトリごとに異なる文字コードを指定するような機能も持っています。

具体的には、/etc/fd2rcあるいは~/.fd2rcという設定ファイルで、UTF-8を使っているディレクトリのリストをUTF8PATHという変数に指定してやれば、そのディレクトリ以下ではファイル名の文字コードにUTF-8を使っていると見なし、別のディレクトリからファイルをコピーする際も自動的に文字コードを変換してくれます。

493  # directories on which Kanji code in filename is UTF-8
494  #       Default: none
495  UTF8PATH="~/Mtp"
496

試してみると、FDcloneを動かしているターミナルのタイトルは文字化けするものの、FDclone自体は文字コードを正しく認識して表示できます。また、文字コードが異なるファイル名の補完も問題なく行えるようです。

図4 FDcloneを使ったファイルコピー
図4 FDcloneを使ったファイルコピー

どうやらFDcloneを使えば、jmtpfsの安定したMTPデバイス操作を、文字コードを気にせず利用できそうです。

この組み合わせを見つけた時は、かつての文字コード混在時代のノウハウを、その当時から使われてきたFDcloneで活用するのは、温故知新なPlamoらしいな、と思わずほくそ笑んでしまったのでした。

ちなみにjmtpfsでマウントしたMTPデバイスをアンマウントする際は、fusermountに -u オプションを指定します。

$ fusermount -u ~/Mtp

jmtpfsとiconv

jmtpfsが使いものになりそうだ、ということをチェックして数日後、再度Nexus 7にファイルを転送しようとしてjmtpfsをイジっていると、あれこれオプションが指定できることに気づきました。その中には文字コードを指定するためのオプションもあるようです。

$ jmtpfs -h
Error: Unable to open ~/.mtpz-data for reading.
usage: jmtpfs mountpoint [options]

general options:
    -o opt,[opt...]        mount options
    -h   --help            print help
    -V   --version         print version
...
Module options:

[iconv]
    -o from_code=CHARSET   original encoding of file names (default: UTF-8)
    -o to_code=CHARSET	    new encoding of the file names (default: EUC-JP)
[subdir]
    -o subdir=DIR	    prepend this directory to all paths (mandatory)
    -o [no]rellinks	    transform absolute symlinks to relative

jmtpfs options:
    -l    --listDevices         list available mtp devices and then exit
    -device=,   Device to mount. It not specified the first device found is used

これを使えば文字コードの変換も可能かも、と試してみましたが、オプション指定がうまく行きません。

$ jmtpfs -o from_code=UTF-8 -o to_code=EUC-JP  ~/Mtp
...
fuse: unknown option `from_code=UTF-8'

"Module options:"として紹介されているので、FUSEモジュールをロードする際に指定するのかな、と試しましたが、そうでもなさそうです。

$ sudo modprobe fuse -o from_code=UTF-8,to_code=EUC-JP
modprobe: invalid option -- 'o'
$ sudo modprobe fuse from_code=UTF-8,to_code=EUC-JP
modprobe: ERROR: could not insert 'fuse': Invalid argument

さて、このオプションはどう指定するのだろう……、と調べてみたところ、モジュールとしてiconvを指定した上で、文字コードの変換を指定するという形式でした。

$ jmtpfs -o modules=iconv,from_code=UTF-8,to_code=EUC-JP ~/Mtp
Error: Unable to open ~/.mtpz-data for reading.
Device 0 (VID=18d1 and PID=4e41) is a Google Inc (for Asus) Nexus 7 (MTP).
Android device detected, assigning default bug flags

こうしてマウントすれば ~/Mtp 以下の文字コードは自動的に変換されて表示されます。

$ ls ~/Mtp
内部ストレージ/
$ ls ~/Mtp/内部ストレージ/MyBookshelf/青空文庫/
09hokkyokuseigono_sencho.txt                ジンジャー&ブレッドのお話/
19_14618.html                               ドグラ・マグラ(夢野久作).txt
975_15935.html                              悪魔(芥川竜之介).txt
...

bashのTabキーによるファイル名の補完も効きますし、dolphin等のファイルマネージャからも問題なく操作できます。

図5 FUSEレベルで文字コードを変換
図5 FUSEレベルで文字コードを変換

前節で紹介した設定はFDclone自身にしか効きませんが、jmtpfsで指定した設定はカーネルと同じレベルで機能するので、全てのアプリケーションから利用可能です。jmtpfsでこのオプションを指定することが、Plamo Linux環境でMTPデバイスを利用する際のファイナル・アンサーということになりました。


さて、去年の暮れから5ヵ月ほど、Nexus 7を主に自炊電子書籍と青空文庫のリーダーとして使ってみました。

革製カバーを付けたNexus 7は約480gほどあります。480gというと500mlのペットボトル飲料程度なので、そう大した重さではないだろうと高をくくっていましたが、ベッドに寝ころがって読んでると、思ったよりも腕がツラくなります。

この重さは本だと何ページくらいになるだろう、と思って、手元にある文庫本を調べてみたところ、京極夏彦の「魍魎の匣」1060pで510gほどでした。

図6 Nexus 7と「魍魎の匣」の重さ比較
図6 Nexus 7と「魍魎の匣」の重さ比較

さすがに「魍魎の匣」ほどのページ数になると寝ころがっての片手読みなんてことはできないので、膝に置くなりして重さを分散するからそれほど気にならないものの、Nexus 7の場合は片手持ちでページめくりもできてしまう分、余計重さが効いてくるようです。

マニアの性(さが)として、この手のガジェットを選択する際は、画面解像度や記憶容量などを優先しがちですが、⁠重量」というのも決して無視できない要素だなぁ…、と改めて思い知った次第です。

おすすめ記事

記事・ニュース一覧