ubuntuでexFAT
ubuntu11.10のリポジトリにはexfatが含まれていなかったので、
本家exfat - Free exFAT file system implementation - Google Project Hosting
より、subbersionリポジトリからソースツリーを引っ張り出してセルビルドする。
http://code.google.com/p/exfat/wiki/HOWTO に説明されているように、てきとーなディレクトリで
svn co http://exfat.googlecode.com/svn/trunk/ exfat-read-only
というふうに、ソースツリーを引っ張り出す。
そしてsconsというビルドツールを用いてビルドするのであるが、sconsはubuntuのリポジトリからapt-getなどで取得する。あと、Fuseの開発パッケージもビルドに必要となる。
apt-get install scons libfuse-dev
のようにすると、sconsとfuseの開発パッケージがインストールされる。sconsが要求する依存関係らPerlのライブラリー関係が若干入れ替えに成る場合があるので、sconsをインストールことで消されては困るパッケージがないことをよく確認してsconsをインストールする。
cd exfat-read-only scons
のようにすると、コンパイルされる。
インストールは、ドキュメントにあるとおりに
sudo scons install
とすればよいのだが、/sbinにいきなりコピーされるだけなので、アンインストールの手順というのがほぼ皆無に近いことを記憶に留めておこう。
マウントは、gnomeなどのデスクトップにログオンしているならば nautilusをひらいて、ドライブのアイコンをクリックすればよい。もしX11のないコンソールのみであるならばドキュメントに記載されているように、
sudo mount.exfat-fuse /dev/sdXn /mnt/exfat
とかすればよいだろう。
ということで、
Dec 21 23:31:09 onion999 kernel: [85500.405230] ISO 9660 Extensions: Microsoft Joliet Level 3 Dec 21 23:31:09 onion999 kernel: [85500.406715] ISO 9660 Extensions: RRIP_1991A Dec 21 23:32:39 onion999 kernel: [85591.072134] usb 1-5: new high speed USB device number 6 using ehci_hcd Dec 21 23:32:39 onion999 mtp-probe: checking bus 1, device 6: "/sys/devices/pci0000:00/0000:00:02.1/usb1/1-5" Dec 21 23:32:39 onion999 kernel: [85591.210439] scsi8 : usb-storage 1-5:1.0 Dec 21 23:32:40 onion999 mtp-probe: bus: 1, device: 6 was not an MTP device Dec 21 23:32:40 onion999 kernel: [85592.223632] scsi 8:0:0:0: Direct-Access I-O DATA HDCR-U PQ: 0 ANSI: 2 CCS Dec 21 23:32:41 onion999 kernel: [85592.230365] sd 8:0:0:0: Attached scsi generic sg3 type 0 Dec 21 23:32:41 onion999 kernel: [85592.231341] sd 8:0:0:0: [sdc] 2930277168 512-byte logical blocks: (1.50 TB/1.36 TiB) Dec 21 23:32:41 onion999 kernel: [85592.233839] sd 8:0:0:0: [sdc] Write Protect is off Dec 21 23:32:41 onion999 kernel: [85592.233846] sd 8:0:0:0: [sdc] Mode Sense: 3c 00 00 00 Dec 21 23:32:41 onion999 kernel: [85592.235836] sd 8:0:0:0: [sdc] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA Dec 21 23:32:41 onion999 kernel: [85592.329766] sdc: sdc1 Dec 21 23:32:41 onion999 kernel: [85592.335836] sd 8:0:0:0: [sdc] Attached SCSI disk Dec 21 23:32:41 onion999 ata_id[4614]: HDIO_GET_IDENTITY failed for '/dev/sdc': Invalid argument Dec 21 23:44:43 onion999 mount.exfat: illegal UTF-8 sequence Dec 21 23:44:43 mount.exfat: last message repeated 199 times
をつなげてみた。
nautilusから、しばらくの間あっちこっちのアイコンをクリックしていたら、ドライブからの応答がなくなって、エラーダイアログがポップアップするだけになっていた。
syslogをかくにんしてみると
Dec 21 20:30:44 onion999 mount.exfat: name is too long Dec 21 20:30:44 onion999 mount.exfat: failed to convert name to UTF-8 Dec 21 20:33:16 onion999 mount.exfat: volume was not unmounted cleanly
てなことで、FuseFSがハングアップしてしまったようだ。
とりあえずソースコートを確認ということで・・・
grep -e 'name is too long' -r .
エラーメッセージのある箇所を確認すると、
./libexfat/utf.c: exfat_error("name is too long");
とかヒットしたので ./libexfat/utf.c をエディタで眺めてみる。
int utf16_to_utf8(char* output, const le16_t* input, size_t outsize, size_t insize) { const le16_t* inp = input; char* outp = output; wchar_t wc; while (inp - input < insize && le16_to_cpu(*inp)) { inp = utf16_to_wchar(inp, &wc, insize - (inp - input)); if (inp == NULL) { exfat_error("illegal UTF-16 sequence"); return -EILSEQ; } outp = wchar_to_utf8(outp, wc, outsize - (outp - output)); if (outp == NULL) { exfat_error("name is too long"); return -ENAMETOOLONG; } } *outp = '\0'; return 0; }
つぎに utf16_to_utf8 を呼び出している箇所を
grep -e 'utf16_to_utf8' -r . |grep -E '\.c'
とかして、確認する
./libexfat/node.c: if (utf16_to_utf8(ef->label, label->name, ./libexfat/utf.c:int utf16_to_utf8(char* output, const le16_t* input, size_t outsize, ./libexfat/utils.c: if (utf16_to_utf8(buffer, node->name, n, EXFAT_NAME_MAX) != 0)
そーいうことで、とりあえず ./libexfat/node.c をエディタで開いて、呼び出しているところを眺めてみる。
case EXFAT_ENTRY_LABEL: label = (const struct exfat_entry_label*) entry; if (label->length > EXFAT_ENAME_MAX) { exfat_error("too long label (%hhu chars)", label->length); goto error; } if (utf16_to_utf8(ef->label, label->name, sizeof(ef->label), EXFAT_ENAME_MAX) != 0) goto error; break;
どうやら、EXFAT_NAME_MAXで、ファイルネームの長さを決めているようだ。とりあえずバッファサイズを大きく設定してみれば当面のエラーは回避できそうな感じがする。
ということで、再び検索してみる。
grep -e 'EXFAT_NAME_MAX' -r . |grep -e '#.*EXFAT_NAME_MAX'
とかして、EXFAT_NAME_MAXが定義されている場所を探す。
./exfat-read-only/libexfat/.svn/text-base/exfat.h.svn-base:#define EXFAT_NAME_MAX 256 ./exfat-read-only/libexfat/exfat.h:#define EXFAT_NAME_MAX 256
ふむ。./libexfat/exfat.h をいじくってあげればよさげだなぁ。
ちなみにマイクロソフトの資料*1を参考にすると、ファイルネームの長さの最大はフルパス名の長さの最大であると説明されており、そのながさは、「通常の場合、Windows ではファイル名が 260 文字までに制限されています。」と明記されているので、おそらくEXFAT_NAME_MAXは260と定義すべきであろう。
=================================================================== --- libexfat/exfat.h (リビジョン 315) +++ libexfat/exfat.h (作業コピー) @@ -1,3 +1,4 @@ + /* exfat.h (29.08.09) Definitions of structures and constants used in exFAT file system @@ -31,7 +32,7 @@ #include "exfatfs.h" #include "version.h" -#define EXFAT_NAME_MAX 256 +#define EXFAT_NAME_MAX 260 // issued `name is too long` at 256. #define EXFAT_ATTRIB_CONTIGUOUS 0x10000 #define EXFAT_ATTRIB_CACHED 0x20000 #define EXFAT_ATTRIB_DIRTY 0x40000
本当は、もう少しよく考えて検討しないと、記憶喪失なドライブや削除できないファイルとか作ってしまうかもしれない。ということで、毎度ながらオープンソースを使うのに「バグは愛嬌。使うは度胸。」を肝に据え置いて人柱するべし。