How to mount a QEMU virtual disk image

0
1293

Let’s say you discover critical business data in a legacy DOS spreadsheet file, and Excel can’t read the file. If the legacy program originally ran on DOS, you might boot a copy of FreeDOS, and install the legacy program there to extract or export the data to a common file format, like a comma-separated CSV file.

You can follow our instructions to install and boot FreeDOS using the QEMU virtual machine. But having installed FreeDOS, how do you then install and run the legacy program in QEMU?

You can mount a QEMU disk image using two basic methods: using an offset to mount the image directly, or using the libguestfs-tools  package.

Using an Offset

Linux can mount QEMU’s raw disk image format, assuming it knows where to find the start of the C: drive partition on the virtual disk. The virtual disk can contain multiple partitions, but for most legacy operating system installations like DOS, you probably only have one partition. This is the C: drive.

Let’s look at output from the Linux fdisk program. Using the -l option will list the partitions on the virtual disk:

$ fdisk -l image.img
Disk image.img: 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: 0x00000000

Device Boot Start End Sectors Size Id Type
image.img1 * 63 204623 204561 99.9M 6 FAT16

Here, the C: drive is the first and only partition on the virtual drive, listed as image.img1 .To determine the offset of the C: drive, you need to know the starting sector of that partition. The output from fdisk shows this as 63.

To calculate the offset, you also need to know the sector size. This virtual disk image has sectors of 512 bytes. You calculate the offset as the product of the offset and the sector size: 63 × 512 = 32256.

Use this offset value to mount the virtual C: drive from Linux:

$ mkdir /tmp/dos
$ sudo mount -o loop,offset=32256 image.img /tmp/dos
$ ls /tmp/dos
AUTOEXEC.BAT  COMMAND.COM  FDCONFIG.SYS  FDOS  KERNEL.SYS
$ sudo umount /tmp/dos

You can automate the calculation using a Bash script. The script first needs to gather the values in an easily-parsable format. On my Linux system, I use the -o option with fdisk to specify which columns to print. Since I only need to match the partition (Device) and the Start value, I use this fdisk command to list the columns I need:

$ fdisk -l -o Device,Start image.img
Disk image.img: 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: 0x00000000

Device Start
image.img1 63

And a Bash script can parse that output using Gawk to calculate the offset on its own:

#!/bin/bash
# usage: qemu-mount {imagefile}
# 1st argument: QEMU raw image file

if [ $# -ne 1 ] ; then
echo ‘usage: qemu-mount imagefile’
echo ‘Mounts a QEMU raw image file to /tmp/dos’
exit 1
fi

start=$( fdisk -l -o Device,Start ${1} | grep “^${1}1” | gawk ‘{print $2}’ )
sectors=$( fdisk -l ${1} | grep ‘^Units: sectors of’ | gawk ‘{print $(NF-1)}’ )
offset=$(( $start * $sectors ))

[ -d /tmp/dos ] || mkdir /tmp/dos
sudo mount -o loop,offset=$offset ${1} /tmp/dos

After mounting the QEMU virtual disk image to the /tmp/dos temporary mount point, you can read and write data on the virtual C: drive. This is a handy way to copy a legacy program installer to the virtual machine, or copy data out of the virtual machine. However, you should only mount the virtual disk image when QEMU is not running. If you attempt to mount a QEMU disk image while it is in use, you may corrupt the virtual disk.

When you have finished accessing the virtual disk image from Linux, don’t forget to unmount the image with the umount command.

Using libguestfs-tools

The libguestfs-tools package provides a set of tools to access virtual machine disk images. Included in this toolkit is guestmount , which makes it really easy to mount a QEMU disk image from Linux. If your distribution does not include this package by default, you may need to install the libguestfs software separately. However, many Linux distributions including Fedora, Red Hat Enterprise Linux, Debian, and Ubuntu provide a libguestfs-tools package you can install via your package manager.

Two options tell guestmount how to access the QEMU disk image. The –add imagefile option specifies the virtual disk image to work with, and the –mount device option tells guestmount which partition to use from the disk image. You need to indicate the device using a standard Linux path, such as /dev/sda1  for the first partition in the virtual disk image.

With these two options, mounting the virtual disk image from Linux is a single-line command:

guestmount –add image.img –mount /dev/sda1 /tmp/dos

After a moment, this mounts the virtual C: drive to the /tmp/dos temporary mount point. You can access files on the virtual disk image /tmp/dos using standard Linux tools, such as cp and mv, to copy data into and out of the virtual disk. Be careful to only mount the disk image when QEMU is not running, or you may corrupt the virtual disk.

When you have finished with the virtual C: drive, you can unmount the filesystem using the guestunmount command.