UEFIのパーティションや、パーティションテーブル、なんならMBRも消して作り直したいのだが、どうにもできない。
Windowsも少しずつ変わっている。私が昔のやり方しか知らないためかもしれない。
悩んでいてもしょうがないので、Ubuntuでやることにした。
UbuntuのInstallのための後始末を、Ubuntuでやるのは当然であるとも言える。
fdiskでMBRのパーティションテーブルを作り直して、mkfs.vfatでフォーマットを行った。
昔とほとんど変わらない。
これでWindowsで使えるようになる。
ふと「わかりやすいボリュームラベルでも付けておこうかな。」と、思った。
昔のことを色々思い出していた。そのせいか、PC-9801のMS-DOSのころ"dir"と打つたときの「ボリュームラベルは”xxxx”です。」が頭に浮かんだ。
mkfs.vfatでは、-n <ボリュームラベル> と --codepage <コードページ番号> を指定すれば、BPB上のボリュームラベル領域にセットできる様子。
コードページを指定するということは、OEM文字セット、すなわち日本語も正しく指定すれば使えるようだ。
実際に使おうとしたら、以下のように、エラーになる。
$ mkfs.vfat -n "試験用" --codepage 932 /dev/sdc1 mkfs.fat 4.2 (2021-01-31) mkfs.vfat: Labels with characters below 0x20 are not allowed0x20より小さいって、CP932(Shift_JIS)の半角カナや漢字の第一バイトを符号付き8bitで扱っている?
ソースパッケージ(dosfstools)をダウンロードして、確認した。
src/common.cの最後の、関数validate_volume_label()で、エラーチェックを行っている。
引数doslabel[]はOEMコードページで書かれたボリュームラベル文字列だ。
char型であり、そのまま0x20と比較していた。
312 /* 313 * Validate volume label 314 * 315 * @param[in] doslabel Label stored according to current DOS codepage 316 * 317 * @return bitmask of errors 318 * 0x01 - lowercase character 319 * 0x02 - character below 0x20 320 * 0x04 - character in disallowed set 321 * 0x08 - empty or space-only label 322 * 0x10 - space at beginning 323 */ 324 int validate_volume_label(char *doslabel) 325 { 326 int i; 327 int ret = 0; 328 wchar_t wlabel[12]; 329 330 if (dos_string_to_wchar_string(wlabel, doslabel, sizeof(wlabel))) { 331 for (i = 0; wlabel[i]; i++) { 332 /* FAT specification: Lower case characters are not allowed in DIR_Name 333 (what these characters are is country specific) 334 Original label is stored in DOS OEM code page, so islower() function 335 cannot be used. Therefore convert original label to locale independent 336 wchar_t* and then use iswlower() function for it. 337 */ 338 if (iswlower(wlabel[i])) { 339 ret |= 0x01; 340 break; 341 } 342 } 343 } 344 345 /* According to FAT specification those bytes (after conversion to DOS OEM 346 code page) are not allowed. 347 */ 348 for (i = 0; i < 11; i++) { 349 if (doslabel[i] < 0x20) 350 ret |= 0x02; 351 if (doslabel[i] == 0x22 || 352 (doslabel[i] >= 0x2A && doslabel[i] <= 0x2C) || 353 doslabel[i] == 0x2E || 354 doslabel[i] == 0x2F || 355 (doslabel[i] >= 0x3A && doslabel[i] <= 0x3F) || 356 (doslabel[i] >= 0x5B && doslabel[i] <= 0x5D) || 357 doslabel[i] == 0x7C) 358 ret |= 0x04; 359 } 360 361 if (memcmp(doslabel, " ", 11) == 0) 362 ret |= 0x08; 363 364 if (doslabel[0] == ' ') 365 ret |= 0x10; 366 367 return ret; 368 }他のOEM文字セットでは、8bit文字を使わないのかな?
符号なし8bitで比較するように直して、バイナリパッケージをリビルドして、インストール。
それで、mkfs.vfatをしたら、日本語ボリュームラベルを付けることができた。
ここまではいい。
ボリュームラベルは、ルートディレクトリ上に特別な属性をもつディレクトリエントリを作ることでも表現できる。
本来、この文字列とBPB内のボリュームラベルは同じものを示すはずだ。
そして、CP932ではディレクトリエントリで特別な考慮が必要になる。
CP932の文字セットには、0xE5で始まる文字がいくつか存在している。
ファイル名が0xE5で始まるディレクトリエントリは、削除されたエントリとして扱われる。そのため、ファイル名の先頭で0xE5を使いたい場合、0x05に置き換えるというルールがMS-DOSのころから存在している。
このルールは、どうなるんだろう?
BPBのボリュームラベルは、ディレクトリエントリの一部ではない。
しかし、両方同じボリュームラベルであることは違いない。
試しに0xE5で始まる文字列"蛆虫"(「うじむし」こんな名前普通は使わないけど)を、mkfs.vfatでボリュームラベルにしてみた。
WindowsにUSBメモリを挿入すると、"蛆虫"の"蛆"が文字化けした。
やっぱ、0xE5がダメだったのかな?と思って、ddを使って無理やり0xE5を0x05にしてみた。
それでも、Windowsでは、文字化けしてしまう。
Windowsは、何を求めているんだろう?
Windowsでボリュームラベルに"蛆虫"を指定してフォーマットしようとした。
エラーになって、フォーマットできない。
今度は試しに、ボリュームラベルに”良い蛆虫”を指定した。
すると、エラーなしにフォーマットできた。
なんと! Windows では、0xE5 で始まる文字列をボリュームラベルに使えないのだ。
なんか微妙に違っているがやっぱり、BPBでもダメってことだ。
そんなのあり?
とはいえ、0xE5で始まる文字は、JIS第2水準であり、使えなくても多くの場合問題にならない。
ま、いいか。
2022/12/23 ソースコードの色が悪く、読みにくかったので直した。ついでに細かく修正。
0 件のコメント:
コメントを投稿