Ubuntu / WSL2 でディスクイメージファイルを作成

Ubuntu でディスクイメージファイルを扱ってみます。

今回は、ネイティブの Ubuntu と、WSL 上の Ubuntu で試してみました。
WSL2 でできるのかな・・・
結論を先に述べると、ループバックマウント、fdisk、trancate、dd、mount、mkfs など今回使用したツールは何の問題もなく利用できました。

# 環境 

- Ubuntu 20.04.4 LTS (GNU/Linux 5.10.16.3-microsoft-standard-WSL2 x86_64)
- Ubuntu 22.04 LTS ja Desktop

# 作業

今回の作業は RaspberryPi で用いるための SD カードイメージを想定します。
RaspberryPi の SD カードは以下の構成になっています

- パーティションが2つ
- 第一パーティーション： /boot
  - vfat
  - 設定やブートなどに必要なファイル格納
  - サイズ小
- 第2パーティション： /
  - ext4
  - root file system
  - 一般的には /boot パーティションで使用する以外のすべての容量を割り当てることが多い

作業場所を作り、移動します

```
$ mkdir ~/working
$ cd ~/working
```
# イメージ作ってみる

dd を使うやり方

```

$ dd bs=1024k count=100 if=/dev/zero of=image.img
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.0015547 s, 674 MB/s
$ ls -al image.img
-rw-r--r-- 1 nanbuwks nanbuwks 1048576 Sep 23 11:53 image.img

```

trancate で作ってみる
```
$ truncate -s 100M image.img
$ ls -al image.img
-rw-r--r-- 1 nanbuwks nanbuwks 104857600 Sep 23 12:01 image.img
```
どちらも問題なく作れますね！

dd はいろいろ危険なので、 trancate がいいかも。

# ループバックマウント

イメージファイルをマウントします。

losetup で空きループバックデバイスを調べます

```
$ losetup -f
/dev/loop0
```

それに image.img を割り振ります。そのままだと Permission denied となったので sudo しました。

```

$ losetup /dev/loop0 image.img
losetup: /dev/loop0: failed to set up loop device: Permission denied
$ sudo losetup /dev/loop0 image.img
[sudo] password for nanbuwks:
```

fdisk でパーティションを作ります。
RaspberryPi のパーティションは /boot として小さい容量のVFATパーティション、/ として ext4 パーティションの構成となります。それに合わせて設定します。

```
$ sudo fdisk /dev/loop0

Welcome to fdisk (util-linux 2.34).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x56b28ef8.

Command (m for help): p
Disk /dev/loop0: 100 MiB, 104857600 bytes, 204800 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x56b28ef8

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-204799, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-204799, default 204799): +10M

Created a new partition 1 of type 'Linux' and of size 10 MiB.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (22528-204799, default 22528):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (22528-204799, default 204799):

Created a new partition 2 of type 'Linux' and of size 89 MiB.

Command (m for help): t
Partition number (1,2, default 2): 1
Hex code (type L to list all codes): c

Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'.

Command (m for help): t
Partition number (1,2, default 2): 2
Hex code (type L to list all codes): 83

Changed type of partition 'Linux' to 'Linux'.

Command (m for help): a
Partition number (1,2, default 2): 1

The bootable flag on partition 1 is enabled now.

Command (m for help): p
Disk /dev/loop0: 100 MiB, 104857600 bytes, 204800 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x56b28ef8

Device       Boot Start    End Sectors Size Id Type
/dev/loop0p1 *     2048  22527   20480  10M  c W95 FAT32 (LBA)
/dev/loop0p2      22528 204799  182272  89M 83 Linux

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Re-reading the partition table failed.: Invalid argument

The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8).

```

一旦、image.img の関連付けを削除

```
$ sudo losetup -d /dev/loop0
```

/dev/loop0p1 および /dev/loop0p2 をマウントするためには kpartx を使ったり オフセットを指定してマウントしたりする方法もありますが、今回は以下のようにしました。

```
$ sudo losetup -P -f --show image.img
/dev/loop0
```
デバイスファイルが自動的に作成されています。

```
$ ls /dev/loop0*
/dev/loop0  /dev/loop0p1  /dev/loop0p2
```

ファイルシステムを作ります。ボリュームラベルも一緒に指定します。

```
$ sudo mkfs.vfat -F 32 -n boot /dev/loop0p1
mkfs.fat 4.1 (2017-01-24)
mkfs.fat: warning - lowercase labels might not work properly with DOS or Windows
WARNING: Not enough clusters for a 32 bit FAT!
$ sudo mkfs.ext4 -L root /dev/loop0p2
mke2fs 1.45.5 (07-Jan-2020)
Discarding device blocks: done
Creating filesystem with 22784 4k blocks and 22784 inodes

Allocating group tables: done
Writing inode tables: done
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done
```

マウントポイントを作ってマウント、書き込めるようにします。

```
$ mkdir root
$ mkdir boot
$ sudo mount /dev/loop0p1 boot
$ sudo mount /dev/loop0p2 root
```
作業が終わったら、以下のようにして後始末します。

```
$ sudo umount root
$ sudo umount boot
$ sudo losetup -d /dev/loop0
```