Unmotivated

やる気はない

ファイル名に特定の記号が使用できる場合とできない場合がある

Android のバージョンは同じなのに、端末によってファイルの移動(renameTo())に失敗してしまうことがあって悩まされたが、オチは移動先のファイル名にクエスチョンマーク(“?”)が含まれていたことが原因だった。

クエスチョンマークが入ってしまっていたこと自体がバグだったのだけれど、そもそも何で端末によってこのようなことが起きるのかを軽く追ってみた。

原因はファイルシステム(っぽい)

成功する端末では内部ストレージに書き込みを行っており、失敗する端末では外部ストレージに書き込みを行っていた。

ファイルシステムを見てみると、内部ストレージは FUSE でマウントされているのに対し、外部ストレージは VFAT でマウントされていた。

mount の状態
1
2
3
4
5
# 内部ストレージとして認識されているディレクトリ
/dev/fuse /storage/sdcard0 fuse rw,nosuid,nodev,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0

# 外部ストレージとして認識されているディレクトリ
/dev/block/vold/179:33 /storage/sdcard0/external_sd vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0602,dmask=0602,allow_utime=0020,codepage=cp437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0

正式な出典が見つからなかったけれど、 VFAT ではファイル名に以下の文字の使用を禁止しているようなので、恐らくこれが原因っぽい。
試しにその他の記号を含めたファイル名を作成してみたところ、全て失敗した。

1
\ : * ? < > | / ;

参考 : ファイル名とフォルダ名で使用できない文字

というわけで、環境によって(サンプル数は少ないが、恐らく外部SDカードでは)一部の記号がファイル名に使えなくなることがある、ということが分かった。

メモ

Android のファイルシステム周りについては全く調べられていないが、いくつか気になることがあったのでメモ。

  • エミュレータでは FUSE ではなく YAFFS2 でマウントされていた(どこのレイヤーで変わってるのか不明)
  • ここを見ると、 Android 4.4 からは外部ストレージも FUSE 経由でマウントするようになるっぽい?が、4.4 のエミュレータが起動せず、実機も外部メモリがマウントできない端末しかなく確認できず (raw storage をラップしているとあるので、今回の件は実体の方でこけそう)

Comments