Tuesday, August 6, 2013

How to mount a VirtualBox .VDI images on a Mac OS X host

Sometimes it is very useful to mount VirtualBox .VDI images on the host system. This allows us to browse file like other file on the system. I am describing the method I used to mount the VDI images in the Mac OS system. Mounting the VDI image in Linux system is similar and in fact much easier with the availability of some other tool.For mounting the VirtualBox .VDI file, I google a bit and found the way to do it.

Here is a Geeky way of Mounting VirtuaBox .VDI image to Unix like operating system like Mac OS. In Mac OS, we can use hdid tool and in Linux/Solaris, we can use losetup resp. lofiadm to do this. I carried out following steps for mounting .VDI to Mac OS. I have explained it with the places where I made mistakes and what I did to correct those mistakes.

First: I searched and found the VirtualBox.VDI image file, that I wanted to mount
  1. Close the virtual box. It cannot be done when VrrtualBox is running
  2. Find the folder where the image is stored. This is generally stored under BirtualBox folder. We can find .VDI files if unable to find the folder. The image file I found was named ubuntu.vdi
  3. I changed it to current directory in the terminal by using cd command
    $ cd /Users/Username/VirtualBox/ubuntu
    $ ls -l
    total 13123696
    drwx------ 6 Username staff        204 Aug 5 01:12 Logs
    -rw------- 1 Username staff       7969 Aug 5 11:03 ubuntu.vbox
    -rw------- 1 Username staff       7968 Aug 5 11:03 ubuntu.vbox-prev
    -rw------- 2 Username staff 3359657984 Aug 5 15:41 ubuntu.vdi
Second: I tried to mount the file with hdid utility
  1. I tried to use hdid utility to mount .VDI image file. The -nomount switch does not mount the image automatically, but makes it available under /dev folder
    $ hdid -nomount ubuntu.vdi
  2. But this returned an error. The .VDI format was not recognized by hdid utility
    $ hdid: attach failed - not recognized
  3. I tried to supply different extension (.IMG) to the hdid utility, by linking ubuntu.vdi to ubuntu.img 
    $ ln ubuntu.vdi ubuntu.img
  4. Now I tried to mount it again with different extension
    $ hdid -nomount ubuntu.img
    /dev/disk1
  5. Now, hdid recognized the image and it was available in /dev/disk2 but it could not be read properly due to unrecognized format in the file. The unrecognized format was due to the header information in the .VDI file 
Additional information about VDI image
hdid utility actually attaches raw disk image via a blockdevice. But .VDI image contains header information with partition information and raw disk image after that. hdid expects only raw disk image. So I had to find where the VirtualBox .VDI header stops and the raw disk image begins.

To find the starting position of raw disk image, we have to do some simple calculations with these facts in consideration
  1. It is decided by reading 4-byte, 32-bit integer at byte offset 0x158 (decimal 344) in the .VDI file.
  2. This value is divided by number of bytes per sector that is 0x200 (decimal 512)
  3. The final value can be used with --section parameter in hdid utility to mount the image.
  4. The mounted image can be used from cli or gui alike
Third: I found the position from which the raw disk image starts
  1. We can use the hexdump utility icluded with Mac OS to retrieve the value where the raw disk image begins. I used man hexdump to read more about it.
    $ hexdump -C -s 0x158 -n 4 ubuntu.vdi
  2. Here, the switches -C is canonical display, -s is skip offset byte from beginning, and -n is length bytes of input. Since I had to read 4-byte, I used -n 4; at the byte offset 0x158, I used -s 0x158. I got following result:
    00000158  00 50 00 00             |.P..|
    0000015c
  3. I got the byte position I need. it is 0x00005000. The color is used here to show the position of the number. It is read two digits at a time back to the front. The byte position I need is  0x5000 (omitting leading zeros). 
  4. But I need number of sectors, so I had to divide the number by 0x200 (decimal 512) to get the appropriate disk position. I used bc command to calculate this. You can optionally use calculator to get the number of sectors.
    I need the result of 5000 / 200 (in hex)
    $ echo "obase=16; ibase=16; 5000 / 200" | bc
    28
  5. The number of sectors to offset is 28. Now I can use hdid utility to safely mount this image.
Four: I Attached the image with hdid utility with -section switch, to offset 28 sectors
  1. Now I again used hdid utility to mount the image by offsetting 28 sectors.
    $ hdid -section 0x28 ubuntu.img
  2. This again returned an error
    hdiutil: attach failed - Resource temporarily unavailable
  3. This was because, i previously attached the ubuntu.img without supplying the -section switch. The image was currently mounted, but unrecognized by Mac OS.
  4. I unmounted the image and mounted it again with -section switch. 
    hdiutil detach /dev/disk1
  5. Mount this image again
    hdid -section 0x28 ubuntu.img
  6. This again returned an error
    vhdiutil: attach failed - no mountable file systems
  7. The automount failed so run hdid with -nomount switch
    hdid -section 0x28 -nomount ubuntu.img
    /dev/disk1
Mac OS primarily support HFS. In addition, it has extended support for FAT32, UDF, UFS, and NTFS (in read only mode). However, it has no support for ext2/ext3 filesystem popular in Linux. We need to do one further step to mount ext2/ext3 file systems.

Five: I installed driver softwares that made me able to mount ext2/3 filesystem and mount it again
  1. Install the latest release of MacFUSE from google: http://code.google.com/p/macfuse/ . This software is not currently being developed.
  2. This piece of software however does not support ext file systems. You have to download a separate module for that Install the ext2 FUSE module: http://sourceforge.net/projects/fuse-ext2/
  3. Now you can use the disk utility or following command to mount the image.
    fuse-ext2 /dev/disk1s1 /Volumes/tmpfolder
  4. We can use -o force command to make the disk writeable.
    fuse-ext2 -o force /dev/disk1s1 /Volumes/tmpfolder

13 comments:

  1. Thank for your detailed info, but I got this error at the last step

    dyld: Library not loaded: /usr/local/lib/libfuse.2.dylib
    Referenced from: /usr/local/bin/fuse-ext2
    Reason: image not found
    Trace/BPT trap: 5

    ReplyDelete
    Replies
    1. You could use OSXfuse as suggested by @Tom March

      Delete
  2. There might be some problem installing macfuse. try reading Macfuse readme file. You can alternatively install other ext2/ext3 driver into mac OS instead of Macfuse. Please do this and comment for further details.

    ReplyDelete
    Replies
    1. It worked for me with MacBook Air / OSX 10.7.5 using OSXFUSE with the macFUSE compatibility layer enabled and fuse-ext2.

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Thank you. I found a different approach to examine the offset with: "VBoxManage internalcommands dumphdinfo *.vdi", but its not geeky enough. I had another problem with the actual mount, nor fuse-ext nor ntfs-3g have an offset option. I don't want to "cut" my way out, because that would be bad style.

    ReplyDelete
    Replies
    1. The only (in)sane way would be to screw with the local filesystem, to do it effective. There must be something simple I have overlooked.

      Delete
  5. $ uname -a
    Darwin Otheus-Mac-Pro.home 14.3.0 Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64 x86_64

    $ hdid
    2015-04-13 12:52:00.567 hdiutil[11764:342499] Error loading /Library/Plug-ins/DiskImages/VirtualPCDiskImagePlugin.bundle/Contents/MacOS/VirtualPCDiskImagePlugin: dlopen(/Library/Plug-ins/DiskImages/VirtualPCDiskImagePlugin.bundle/Contents/MacOS/VirtualPCDiskImagePlugin, 262): no suitable image found. Did find:
    /Library/Plug-ins/DiskImages/VirtualPCDiskImagePlugin.bundle/Contents/MacOS/VirtualPCDiskImagePlugin: mach-o, but wrong architecture
    2015-04-13 12:52:00.568 hdiutil[11764:342499] Cannot find function pointer MacDiskImagePluginFactory for factory 7F1FD83E-6684-11D8-968F-000A957703C0 in CFBundle/CFPlugIn 0x7fbe3590f180 (bundle, not loaded)

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete