I've recently been working extensively with disk image files (actually Compact Flash images, but that's not a useful differentiation). The first time I tried to mount one to work on, with a simple "mount -o loop hd.img /mnt", I was confronted with "mount: you must specify the filesystem type". Okay, then -- "mount -o loop hd.img /mnt -t ext2". Still no love. What gives? A couple of seconds of actually thinking about it gives the answer -- mount mounts partitions -- not disks.
The solution is straightforward enough, but somewhat burdensome. I'll present a shell script to make it easy.
Since mount wants to mount a partition lying somewhere within the image, you can mount with an "offset" option where the offset points to the beginning of the partition. You can find this offset by using an fdisk. I like to use "sfdisk -d", which gives the offsets of the partitions in sectors. Multiply the "start" value of the desired partition by 512 to convert it to a byte offset, and there's your offset for mount. This lets you do, say, "mount -o loop,offset=12345 hd.img /mnt".
But what do you run fdisk on? You can't just fdisk the image file! Of course, you could fdisk the original drive that the image comes from. However, this is often either a pain or impossible (e.g., when there was no original drive because you created the image file from scratch). The better solution is to manually set up a loopback device on the image file using losetup. Then fdisk that. Then detach the loopback. Then do some math and mount the partition.
When you're doing this constantly for hour after hour, you get bored of it. So I wrote the following (somewhat quick and dirty) script to do it for me. Feel free to send back improvements.
#!/bin/bash -
TOOLNAME=${0##*/}
IMGFILE=
RO=
PARTNUM=1
MOUNTPOINT=
LOOPDEVS=$(ls -1 /dev/loop?*)
LOOPDEV=
function show_help {
echo "$TOOLNAME v1.0"
echo "Usage:"
echo " $1 [OPTIONS] <image file> <mount point>"
echo " $1 <image file>"
echo " When invoked without a mount point, prints info about the image file"
echo "Options:"
echo " -p | --partition <number> Specifies a partition number to mount"
echo " -r | --readonly Mounts readonly"
}
function handle_option {
case "$1" in
-p|--partition)
return 1
;;
-r|--readonly)
RO=",ro"
return 0
;;
esac
show_help
exit 1
}
function handle_option_with_arg {
case "$1" in
-p|--partition)
PARTNUM="$2"
return
;;
esac
show_help
exit 1
}
OPTION=0
function handle_value {
case "$OPTION" in
0)
IMGFILE="$1"
((OPTION++))
return
;;
1)
MOUNTPOINT="$1"
((OPTION++))
return
;;
esac
show_help
exit 1
}
function handle_options {
local OPT
local WANT_ARG=0
local CUR
local VALUES=0
for CUR in "$@"; do
if [ "$VALUES" == 1 ]; then
handle_value $CUR
else
if [ "$WANT_ARG" == 1 ]; then
handle_option_with_arg $OPT $CUR
WANT_ARG=0
else
case $CUR in
-q) QUIET=1;VERBOSE=0;;
-v) VERBOSE=1;QUIET=0;;
-V|--version) show_version; exit 0;;
-h|--help) show_help; exit 0;;
--) VALUES=1;;
-*=*)
local K=${CUR%%=*}
local V=${CUR#*=}
handle_option_with_arg $K $V
;;
-*)
handle_option $CUR
if [ "$?" == 1 ]; then
WANT_ARG=1
else
WANT_ARG=0
fi
if [ "$WANT_ARG" == 1 ]; then
OPT=$CUR
fi
;;
*)
handle_value $CUR
;;
esac
fi
fi
done
if [ $WANT_ARG == 1 ]; then
show_help
exit 1
fi
}
handle_options "$@"
if [ "$OPTION" == 0 ]; then
show_help
exit 1
fi
if [ ! -e "$IMGFILE" ]; then
echo "No such file: $IMGFILE"
exit 2
fi
for EACH in $LOOPDEVS; do
losetup "$EACH" > /dev/null 2> /dev/null
if [ "$?" == 1 ]; then
LOOPDEV="$EACH"
break
fi
done
if [ -z "$LOOPDEV" ]; then
echo "No loopback device available (maybe you are not root?)"
exit 3
fi
losetup $LOOPDEV $IMGFILE
if [ "$?" != 0 ]; then
echo "Could not mount $IMGFILE for inspection"
exit 4
fi
if [ "$OPTION" == 1 ]; then
# Query mode
#sfdisk -d $LOOPDEV | sed -n "s_^${LOOPDEV}p\([0-9]+\) : start\s*\([^,]\+\).\+
echo "# partition table of $IMGFILE"
sfdisk -d $LOOPDEV | tail -n+2 | sed "s_^${LOOPDEV}p[0-9]\+\(.*\)_image\1_"
losetup -d $LOOPDEV
exit 5
fi
OFFSET=$(sfdisk -d $LOOPDEV | sed -n "s_^${LOOPDEV}p$PARTNUM : start=\s*\([^,]\+\).\+_\1_ p")
R="$?"
SIZE=$(sfdisk -d $LOOPDEV | sed -n "s_^${LOOPDEV}p$PARTNUM : .\+size=\s*\([^,]\+\).\+_\1_ p")
losetup -d $LOOPDEV
if [ "$R" != 0 ]; then
echo "Error determining partition offset"
exit 6
fi
if [ -z "$OFFSET" ]; then
echo "Could not determine partition offset (no such partition?)"
exit 7
fi
if [ "$SIZE" == 0 ]; then
echo "Parition is empty"
exit 8
fi
OFFSET=$(($OFFSET * 512))
if [ ! -d "$MOUNTPOINT" ]; then
echo "Mount point is not a directory"
exit 9
fi
MOUNTPOINT=$(cd "$MOUNTPOINT";pwd)
cat /proc/mounts | cut -d' ' -f 2 | grep "$MOUNTPOINT" 2> /dev/null > /dev/null
if [ "$?" == 0 ]; then
echo "Mount point busy"
exit 10
fi
mount -o loop,offset=$OFFSET$RO "$IMGFILE" "$MOUNTPOINT"