PythonのちょっとマニアックかもしれないTips
バッファローのHD-PSGU2シリーズという、2.5インチHDDを内蔵したUSB外付けポータブルHDDがありまして、そのHD-PSGU2には仮想 CD機能がついてます。
仮想CD機能とはどういうものかというと、CDイメージ(isoファイル)をHD-PSGU2のHDDに保存して付属のツールで設定すると、あたかもそのCDイメージと同じ内容を持ったCDが入ったCDドライブが存在するかのごとくBIOSレベルで認識されるというものです。(説明下手や・・・)
年中PCにOSをインストールしまくったりしてる自分にとっては、OSのインストールCDを焼く必要がなく、時間の節約ができ(一般的にCD焼くよりHDDにコピーする方がはるかに早い)さらにメディアを消費しなくて済むからエコかつ財布にやさしいという素晴らしいメリットをこの仮想CD機能はもたらしてくれるのです。
ただ一つ大きな問題があって、仮想CD機能で利用するCDイメージの選択ツールがWindows専用なんです。しかも出来が悪い。
自分はMacユーザーなのでCDイメージを切り替えるためだけにWindowsを立ち上げなきゃならんという非常にめんどくさい事になってました。
(その点、本体だけでイメージの切り替えができるUMA-ISOは非常に素晴らしいのですが、HDD別売なのに割高で、基本的に楽天やAmazonのマケプレに出店してるハンファ・ジャパンのショップからしか買えないという、ハンとかファとかついてる会社には直接住所氏名メアドを渡して取引したくない自分にとっては、選択肢たえりえませんでした。)
それでMacでもなんとかならんかね?と思って調べてみたところ、HD-PSGU2のHDDの中にSYSTEM.BINという隠しファイルがあって、その中の特定の箇所にCDイメージのファイル名を書き込むと、CDイメージの指定ができるようでした。
純正イメージ切り替えツールは、それを書き換えてただけっぽいです。
一瞬Mac用のツールを作るのは楽勝かと思ったんですが、SYSTEM.BINに書き込まれているファイル名をよく見ると、8.3のDOS形式のSFN(Short File Name)なんです。
LFN(Long File Name、いわゆる普通のファイル名)からSFNを生成するアルゴリズム自体はシンプルなんですが、実際はファイルを作成したタイミングによってSFNは変わってしまうため、HD-PSGU2のデフォルトフォーマットであるFAT32を解析して保存されてるSFNを直接見ない限りは正確なところが分かりません。
例えば単にファイルを生成しただけの場合LFNとSFNの対応は以下のようになるのですが、
LFN → SFN
testtestA.txt → testte~1.txt
testtestB.txt → testte~2.txt
testtestC.txt → testte~3.txt
このあとtesttestA.txtを綺麗さっぱり削除した後に、純粋にSFN生成アルゴリズムによってtesttestC.txtのSFNを求めるとtestte~2.txtとなってズレが生じてしまう訳です。
(この後、testtestD.txtを生成するとSFNはどうなるんだろう。調べてないや)
で、Mac + Pythonという縛りで(commandでシェル実行しても構わない)SFNを取得したりFAT32を解析したりできるライブラリとかを探したんですが見つけられなかったので自分で作ってしまいました。そんでCDイメージ切り替えツールも作ってしまいました。
コマンドラインツールなので純正ツールには見劣りしますが、遥かに使い易いです。なんせ出来がいいのでw
FAT32の仕様や、解析するプログラムのソースを説明すると超長くなってしまうのでここには書きませんが、それを作る過程で個人的に勉強になったなぁと思ったPythonのTipsを書いとこうと思います。
環境はMac OS X 10.6とPython 2.6.5なので違うと使えないかも。
あるファイルがどのマウントポイントの配下にあるか調べる方法
pathにファイル名が入ってるとして、
path = os.path.abspath(os.path.join(path, os.pardir))
でどんどん上の階層をたどりながら、
os.path.ismount(path)
で調べるだけで分かります。
最初はpathはファイル名じゃなくてディレクトリ名で始めないとマズくね?と思ったりもしますがその辺はabspath先生がよしなにやってくれるようです。
マウントポイントからブロックデバイスのパスを取得する方法
commandsモジュールを使ってオプションなしのmountコマンドを実行( commands.getstatusoutput(‘mount’) )し、その実行結果から調べたいマウントポイントを含む行を抽出すればその行にブロックデバイス名が含まれてるので正規表現などでうまい具合に抽出すればOK。
ブロックデバイスのパスを受け取ってマウント・アンマウントする方法
これもcommandsを使えば簡単。
deviceにデバイスのパスが入ってるとして、
commands.getstatusoutput(‘diskutil mount ‘ + device)
もしくは
commands.getstatusoutput(‘diskutil umount ‘ + device)
とするだけです。オプションをつけてファイルシステムを指定することも当然できます。
上のもそうですが実際にcommands使うときはリターンコードはきちんとチェックすべき。
またマウント系の操作はsudoでスクリプトを実行するかSUIDを付加しないと多分そんな権限はないよ的なエラーが出るはず。
なんか、前振りが長いわりに本題がしょぼくてすいませんw