apt install kpartx
If you have util-linux v2.21 or higher, you can now do this with losetup. Use the -P (–partscan) option to read the partition table and create device nodes for each partition.
# losetup -P /dev/loop0 rpool.img
# ls /dev/loop0* -l brw-rw---- 1 root disk 7, 0 Mar 26 13:36 /dev/loop0 brw-rw---- 1 root disk 259, 2 Mar 26 13:36 /dev/loop0p1 brw-rw---- 1 root disk 259, 3 Mar 26 13:36 /dev/loop0p9
# losetup -d /dev/loop0
If you have a recent kernel, and pass loop.max_part=63 on boot (if loop is built-in) or to modprobe (if loop is a module).
# losetup /dev/loop0 rpool.img
# partprobe /dev/loop0
# ls /dev/loop0* -l brw-rw---- 1 root disk 7, 0 Mar 26 13:23 /dev/loop0 brw-rw---- 1 root disk 259, 0 Mar 26 13:23 /dev/loop0p1 brw-rw---- 1 root disk 259, 1 Mar 26 13:23 /dev/loop0p9
# losetup -d /dev/loop0
# losetup /dev/loop0 rpool.img
# kpartx -l /dev/loop0 loop0p1 : 0 44019712 /dev/loop0 2048 loop0p9 : 0 16384 /dev/loop0 44021760
# kpartx -av /dev/loop0 add map loop0p1 (252:0): 0 44019712 linear 7:0 2048 add map loop0p9 (252:1): 0 16384 linear 7:0 44021760
# ls /dev/mapper/loop0* -l lrwxrwxrwx 1 root root 7 Mar 26 13:16 loop0p1 -> ../dm-0 lrwxrwxrwx 1 root root 7 Mar 26 13:16 loop0p9 -> ../dm-1
# kpartx -dv /dev/loop0 del devmap : loop0p9 del devmap : loop0p1
# losetup -d /dev/loop0
# fdisk -l rpool.img Disk rpool.img: 21 GiB, 22548578304 bytes, 44040192 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: gpt Disk identifier: B37248EB-F1D7-DA47-A42D-4C42AF20D328 Device Start End Sectors Size Type rpool.img1 2048 44021759 44019712 21G Solaris /usr & Apple ZFS rpool.img9 44021760 44038143 16384 8M Solaris reserved 1
# losetup /dev/loop0 rpool.img --offset $((512 * 2048)) --sizelimit $((512 * 44019712))
# losetup -d /dev/loop0