usbfadm (USB Flashdrive ADMinistration tool) は、河豚板LiveUSBでUSBメモリを管理するためのユティリティツールです。
このツールは当初、河豚板LiveUSBもまだなかったころ、河豚板LiveCDでmfsの内容をUSBメモリに保存し次回の起動で読み込むための補助的な存在でした。
現在ではUSBメモリへのデータ保存以外にも、LiveUSBメディアのカスタマイズ・再構築やディスクデバイスの構成変更などを行える、河豚板LiveUSBの総合管理ツールとなっており、日本語デスクトップ環境構築、対話的ネットワーク設定、ライブアップデートなどを行うツールとならび、河豚板独自の機能を提供しています。
(なお、このツールには"USB Flashdrive"という名称が使われていますが、実際にはOpenBSDがマウントして読み書きできる全てのストレージデバイスに対して利用可能です)
今回は、このusbfadmについて見ていきます。
目次
コマンド名 | 機能 |
sync | メモリ上のファイルシステムの内容をUSBメモリへ保存(同期) |
newdrive | USBメモリに河豚板のシステムを作成(リマスタリング) |
expand | LiveUSBのデータ保存領域を拡張 |
archive | syncで保存したデータをアーカイブ化 |
target | sync,archive,expandするデバイス・パーティションを設定 |
saveas | USBメモリへの保存データ名を設定 |
info | targetで指定したパーティションの状況を表示 |
コマンド名クリックで「河豚板ガイド」の説明箇所へ |
以下のように、対話形式での利用が基本となっている。実行にはroot権限が必要。
demohost$ doas usbfadm doas (kaw@demohost.honjoji.local) password: Welcome to usbfadm. USB flash drive administration tool for FuguIta Version/Arch: 7.6/amd64 (FuguIta-7.6-amd64-202504091) Boot mode: usbflash Target device: /dev/sd2d Data saved as: demohost readline capability available TAB to complete the reserved words Type ? for help. sd2d : demohost ->? Interactive commands are; target - set the partition for sync, info and expand saveas - set the name of the data to be saved sync - sync the target with the current mfs archive - archive saved directory to *.cpio.gz info - show info about the target partition newdrive - make a new FuguIta LiveUSB expand - expand the target partition as large as possible bye, exit, quit - end of this utility Command line options are; -r : redo sync non-interactively (must run 'sync' at interactive mode before doing this) -i : show info about the persistent storage -q : quiet mode when redo sync -t : trace output (pass -x to shell) -d : debug output for newdrive to file 'usbf.debugout' -h : print this help sd2d : demohost ->
上の「sd2d : demohost ->」がコマンドプロンプト。この例では「sd2d」が操作対象のパーティション、「demohost」がsync, archiveを行う際の名称を表している。
メモリ上のファイルシステムの内容をUSBメモリへ保存(同期)する。
カスタマイズ項目 | 設定内容 | amd64でのデフォルト値 |
生成対象 | 実デバイス / イメージファイル | なし |
起動方法 | Legacy BIOS / UEFI / なし(データ保存専用) / Hybrid | UEFI |
パーティション テーブル | MBR / GPT | MBR |
/ramの ファイルシステム | MFS / TMPFS | MFS |
スワップのサイズ | (0で作成しない) | 16MB |
データ保存領域の サイズ | (0で作成しない) | 未使用部分全て |
データ保存領域の 暗号化 | なし / あり | なし |
未使用領域を FATにするか | しない / する | しない |
なお、上の図からわかるように、newdriveでは保存データのコピーは行わないため、元のシステムと同じ環境が必要な場合は、別途、targetを新デバイスに変更した上でsyncを実行する必要がある。
デバイスに未使用領域がある場合、データ保存用パーティションをデバイスのサイズ一杯まで拡張する。
河豚板LiveUSBのイメージファイルは、現在、2GBのサイズで作成され、配布されている。
よって、それ以上のサイズのUSBメモリにイメージを書き込んで使用することになるが、書き込んだだけでは使用するUSBメモリのサイズに関係なく2GBしか領域を使用できない。そして、河豚板のシステムが約1GBを占有しているので、usbfadmでデータを保存できるのは1ギガバイト程度となる。
expandコマンドは、データ保存用パーティションをデバイスのサイズ一杯まで拡張し、デバイスを有効に使用できるようにする。
saveasコマンドで指定し、syncコマンドで保存したファイルツリーから*.cpio.gz形式のアーカイブを作成する (パス名の最大長は、tarよりもcpioが長いため、cpioを採用した)。
このアーカイブファイルは、syncで保存したデータと同様、河豚板の起動モード3で指定して読み込むことができる。
test.cpio.gzのsaveasが再起動後、"test"に設定されていると... ----->archive---->sync...reboot...-->sync---> | | ^ | V V | V test.cpio.gz test/ | test/ "test"が、より古い | | test.cpio.gzで +------------------------+ 上書きされる危険あり!
usbfadmは、ディスクデバイスを管理するコマンドに対するwrapper scriptという見方もできる。
usbfadmが提供する機能は、fdisk, disklabel, newfs, bioctlなど、ディスクデバイスを扱うコマンドを直接使用することで実行できるが、usbfadmはそれらコマンドの詳細を知ることなく、河豚板LiveUSBの管理を安全かつ容易に実行可能。
usbfadmは、単一のkshスクリプトで、概ね以下のような構成になっている。
参考: usbfadmのソースコード (GitHub)
#ユティリティ関数群の定義 echoerr() { ... } clear_exit() { ...} ... #各コマンド関数群の定義 cmd_sync() { ... } cmd_archive() { ... } ... #ここからメイン処理 #初期化 大域変数の定義 実行環境のチェック デフォルト値の設定 設定ファイルの読込 コマンドラインオプションの解析 if コマンドラインオプションあり; then 非対話的処理 (usbfadm -rなど) clear_exit fi #対話的処理 while :; do プロンプトの表示 コマンドの読込 case コマンド in sync) cmd_sync;; archive) cmd_archive;; ... esac done clear_exit
→ ユーザがCtrl-Cなどでusbfadmを強制終了させても、安全に終了できること。副作用なくクリーンに終了すること。
コマンドの読込には、rlwrapコマンドを利用したrl_wread関数を定義。この関数により、以下の機能が実装されている。
rl_wread関数は、始めにrlwrapコマンドをダミーで起動し、rlwrapコマンドが正常に使えるか判定する。rlwrapが正常に使用できない場合は、単純なread文にフォールバックする。
#------------------- # read user's input with readline functionality # outputs echoed to stdout # # usage: rl_wread prompt-str default-str [completion words ....] # rl_wread () { local prompt="$1"; shift local default="$1"; shift local retval # check if rlwrap is available # When control tty is missing (in /etc/rc.shutdown for example), # rlwrap in command substitution "$(rlwrap ...) " fails. if retval=$(rlwrap true) 2>/dev/null 2>&1 ; then echo "$@" > $lockdir/rl_words rlwrap -b '' \ -f $lockdir/rl_words \ -P "$default" \ sh -f -c 'echo -n "'"$prompt"'->" >&2 ; read w || echo EOF; echo $w' || echo RL_ERR else #------------------- # fallback to dumb input # if [[ -z "$default" ]]; then echo -n "${prompt}->" >&2 read w else echo -n "$prompt [$default] -> " >&2 read w if [[ -z "$w" ]]; then w="$default" fi fi echo $w fi }
使用法: ユーザの入力値は標準出力に返されるので、シェルのコマンド置換でキャプチャする。
end of fileの場合は文字列「EOF」が、エラーが発生した場合は「RL_ERR」が返される。
cmd=$(rl_wread "$d : $u " '' quit bye exit sync archive info saveas target newdrive expand help ?) ↑ ↑ ↑ プロンプト ↑ TABで補完する単語群 デフォルト値
usbfadmは、OSによって抽象化されたデバイスやファイルを扱うので、処理の大部分はプラットフォーム非依存だが、newdrive機能では、起動廻りの処理を扱うのでプラットフォームに依存する部分が存在する。
この処理は、newdrive()関数内で/etc/fuguita/usbfadm_postproc.shを読み込む(sourceする)ことで対応している。
arm64アーキテクチャの例:
河豚板/arm64では、newdrive時にラズパイ3/4用にEFI/U-boot関連の設定が必要なので、その処理をusbfadm_postproc.sh.arm64で行っている。
# # post processing for Raspberry Pi 3/4 # This file is included in usbfadm # notice "Change partition ID and Boot flag for Raspberry Pi..." if [ "$instsys" = UEFI ]; then echo "e 0\n0C\n\n\n\nf 0\nq" | fdisk -e "$scandev" ← パーティションタイプの変更 fi # install Raspberry Pi Firmwares and U-Boot binaries # notice "Copying U-BOOT stuffs..." if mount -t msdos -o-l /dev/${scandev}i /mnt; then tar -xvz -C /mnt -f /usr/fuguita/mdec/bootstuff.$(uname -m).tar.gz ← ESPにブート関連の umount /mnt ファイルを配置 fi
expand機能は、従来、MBRパーティションにのみ対応していた。河豚板LiveUSBの配布イメージはMBR+UEFIで行っており、これで必要十分であったが、GPTの場合にもデータ保存領域の拡張が行えるようexpand機能の改良を行った。
usbfadmではパーティションの操作を行う際は、行いたい操作に操作するfdiskやdisklabelのコマンド文字列を生成し、これをパイプライン経由でそれらのコマンドに入力することで実現している。
コーディング例
fdisk_input="e ${partid_obsd}\nA6\nn\n\n*\nw\nq\n" ... echo -n "$fdisk_input" | fdisk -e "$scandev" >/dev/null
GPTのパーティション拡張の場合も、概ねこの方針でOKだが、新たに以下の問題が発生する。
GPTの再構成方法の概要は以下のとおり
Primary GPT: Disk: sd1 Usable LBA: 34 to 16777182 [16777216 Sectors] GUID: c535a72e-969c-4602-b77c-e7a162b549b0 #: type [ start: size ] guid name ------------------------------------------------------------------------ 1: EFI Sys [ 64: 1024 ] ←種別、位置、サイズ 3df0b410-40b7-47be-a406-20da01ece8e4 UEFI Boot ←UUID、コメント 2: Microsoft basic data [ 12860480: 3916672 ] ←以下同じ 8b830bfc-2d7f-4f00-9c1f-6c241aba9421 MSDOS FAT 3: OpenBSD [ 1088: 12859392 ] 83b8e6d4-e620-47aa-b1fc-04f7f827fa81 OpenBSD Area Secondary GPT: Disk: sd1 Usable LBA: 34 to 16777182 [16777216 Sectors] GUID: c535a72e-969c-4602-b77c-e7a162b549b0 #: type [ start: size ] guid name ------------------------------------------------------------------------ 1: EFI Sys [ 64: 1024 ] 3df0b410-40b7-47be-a406-20da01ece8e4 UEFI Boot 2: Microsoft basic data [ 12860480: 3916672 ] 8b830bfc-2d7f-4f00-9c1f-6c241aba9421 MSDOS FAT 3: OpenBSD [ 1088: 12859392 ] 83b8e6d4-e620-47aa-b1fc-04f7f827fa81 OpenBSD Area MBR: Disk: sd1 geometry: 1044/255/63 [16777216 Sectors] Offset: 0 Signature: 0xAA55 Starting Ending LBA Info: #: id C H S - C H S [ start: size ] ------------------------------------------------------------------------------- 0: EE 0 0 2 - 1044 85 1 [ 1: 16777215 ] EFI GPT ← 保護MBR 1: 00 0 0 0 - 0 0 0 [ 0: 0 ] Unused 2: 00 0 0 0 - 0 0 0 [ 0: 0 ] Unused 3: 00 0 0 0 - 0 0 0 [ 0: 0 ] Unusedcmd_expand関数内では、この出力を以下のようなfdisk編集モードのコマンド列に変換する。
reinit gpt ← GPTで初期化 edit 0 ← 初期化で作成されたパーティションを削除 0 edit 1 ← パーティション1の作成 c12a7328-f81f-11d2-ba4b-00a0c93ec93b ← UUID (パーティション種別) 64 ← 開始位置 1024 ← サイズ UEFI Boot ← コメント edit 2 ← パーティション2以下、同様 ebd0a0a2-b9e5-4433-87c0-68b6b72699c7 12860480 3916672 MSDOS FAT edit 3 824cc7a0-36a8-11e3-890a-952519ad3f61 1088 12859392 OpenBSD Area write quit変換されたコマンド列をfdisk -e sd1に入力し、GPTを修正する。
なお、この処理はGPTを全面的に書き換えるクリティカルな処理のため、以下のようなエラー対策を実施している。
GPT拡張後、disklabelコマンドを呼び出してデータ保存用パーティションの拡張を行う。この部分は従来のMBRパーティションの場合と同じ。
if [ 1 -le $(expr X"$(pwd)" : X$mntdir1) ]; then echo echoerr 'You are under $mntdir1. Please move to other directory.' exit 1 fiこのような古い形式のコードは、適時、修正してゆく。ただし、拙速な修正はエンバグを招きかねないため、今後の修正・開発作業に併せて、このようなコードのリファクタリングを行ってゆく予定
河豚板 7.7の「日本語デスクトップ環境デモ版」を作ってみたので、使ってみてください。
説明ページ