Discuss: Mount any VBox-compatible disk image on the host

Discussions related to using VirtualBox on Linux hosts.
mlafauci
Posts: 5
Joined: 31. Mar 2009, 00:15
Primary OS: Ubuntu 8.10
VBox Version: PUEL
Guest OSses: Windows XP Ubuntu

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by mlafauci »

Hi all,
I have a dynamic VDI file containing an ext2 file system.
Executing the vdfuse command I cannot receive any error. But after the command
sudo mount -t ext2 ./mnt/Partition1 ./p -o loop=/dev/loop0
ls ./p
I receive the error:
ls: cannot access buildroot-read-only: Input/output error
ls: cannot access u-boot-avr32: Input/output error
ls: cannot access i2c-tools-3.0.2: Input/output error
...
for each directory on the filesystem.

I did chmod 0666 for /dev/fuse

Any other suggestion?

Thanks
h2o
Posts: 40
Joined: 9. Feb 2009, 04:46

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by h2o »

version 30 does have some problems, but they should be fixed with this patch (apply it with 'patch vdfuse.c vdfuse.patch'):

Code: Select all

--- a/vdfuse.c	2009-02-16 17:20:01.000000000 -0800
+++ b/vdfuse.c	2009-03-15 14:06:15.663444369 -0700
@@ -78,10 +78,48 @@
 
 #define IN_RING3
 
+#define PNAMESIZE 15
+
+// Partition table information
+
+typedef struct {                 // See http://en.wikipedia.org/wiki/Master_boot_record
+   uint8_t status;               // status[7] (0x80 = bootable, 0x00 = non-bootable,other = invalid[8])
+                                 // ** CHS address of first block **
+   uint8_t shead;                // first head
+   uint8_t ssector;              // first sector is in bits 5-0; bits 9-8 of cylinder are in bits 7-6
+   uint8_t sbits;                // first bits 7-0 of cylinder
+   uint8_t type;                 // partition type
+                                 // ** CHS address of last block **
+   uint8_t ehead;                // last head
+   uint8_t esector;              // last sector is in bits 5-0; bits 9-8 of cylinder are in bits 7-6
+   uint8_t ebits;                // last bits 7-0 of cylinder
+   uint32_t offset;              // LBA of first sector in the partition
+   uint32_t size;                // number of blocks in partition, in little-endian format
+} MBRentry;
+
+#define MBR_START 446
+#define EBR_START MBR_START
+
+typedef struct {                 // See http://en.wikipedia.org/wiki/Extended_boot_record for details
+  MBRentry     descriptor;
+  MBRentry     chain;
+  MBRentry     fill1, fill2;
+  uint16_t     signature;
+} EBRentry;
+
+typedef struct {
+   char        name[PNAMESIZE+1];// name of partition
+   off_t       offset;           // offset into disk in bytes
+   uint64_t    size;             // size of partiton in bytes
+   int         no;               // partition number
+   MBRentry    descriptor;       // copy of MBR / EBR descriptor that defines the partion
+} Partition;
+
 void usageAndExit (char *optFormat, ...);
 void vbprintf (const char *format, ...);
 void vdErrorCallback(void *pvUser, int rc, const char *file, unsigned iLine, const char *function, const char *format, va_list va);
 void initialisePartitionTable(void);
+void printPartition (Partition *p);
 int  findPartition (const char* filename);
 int  detectDiskType (char **disktype, char *filename);
 static int VD_open (const char *c, struct fuse_file_info *i);
@@ -122,41 +160,6 @@
 #define PARTTYPE_IS_EXTENDED(x) ((x) == 0x05 || (x) == 0x0f || (x) == 0x85)
 #define HOSTPARTITION_MAX 100
                                  // large enough for EntireDisk or Partition99
-#define PNAMESIZE 15
-
-// Partition table information
-
-typedef struct {                 // See http://en.wikipedia.org/wiki/Master_boot_record
-   uint8_t status;               // status[7] (0x80 = bootable, 0x00 = non-bootable,other = invalid[8])
-                                 // ** CHS address of first block **
-   uint8_t shead;                // first head
-   uint8_t ssector;              // first sector is in bits 5-0; bits 9-8 of cylinder are in bits 7-6
-   uint8_t sbits;                // first bits 7-0 of cylinder
-   uint8_t type;                 // partition type
-                                 // ** CHS address of last block **
-   uint8_t ehead;                // last head
-   uint8_t esector;              // last sector is in bits 5-0; bits 9-8 of cylinder are in bits 7-6
-   uint8_t ebits;                // last bits 7-0 of cylinder
-   uint32_t offset;              // LBA of first sector in the partition
-   uint32_t size;                // number of blocks in partition, in little-endian format
-} MBRentry;
-
-#define MBR_START 446
-typedef struct {
-   char        name[PNAMESIZE+1];// name of partition
-   off_t       offset;           // offset into disk in bytes
-   size_t      size;             // size of partiton in bytes
-   int         no;               // partition number
-   MBRentry    descriptor;       // copy of MBR / EBR descriptor that defines the partion
-} Partition;
-
-#define EBR_START 446
-typedef struct {                 // See http://en.wikipedia.org/wiki/Extended_boot_record for details
-  MBRentry     descriptor;
-  MBRentry     chain;
-  MBRentry     fill1, fill2;
-  uint16_t     signature;
-} EBRentry;
 
 Partition partitionTable[HOSTPARTITION_MAX+1]; // Note the partitionTable[0] is reserved for the EntireDisk descriptor
 static int lastPartition = 0;
@@ -230,7 +233,6 @@
    if (stat(imagefilename, &VDfile_stat)<0) usageAndExit("cannot access imagefile");
    if (access (imagefilename, F_OK | R_OK | ((!readonly) ? W_OK : 0))
        > 0) usageAndExit("cannot access imagefile");
-   if (!debug)         verbose = 0;
 
 #define IS_TYPE(s) (strcmp (s, diskType) == 0)
    if ( !(IS_TYPE("auto") || IS_TYPE("VDI" ) || IS_TYPE("VMDK") || IS_TYPE("VHD" ) ||
@@ -288,8 +290,8 @@
           "\t-a\tallow all users to read disk\n"
           "\t-w\tallow all users to read and write to disk\n"
           "\t-g\trun in foreground\n"
-          "\t-v\tverbose\n"
-          "\t-d\tdebug\n", processName);
+          "\t-v\tverbose output\n"
+          "\t-d\tdebug info from FUSE\n", processName);
    exit(1);
 }
 
@@ -336,6 +338,8 @@
    if (MBRsignature == 0x0000) return;  // an unformated disk is allowed but only EntireDisk is defined
    if (MBRsignature != 0xaa55) usageAndExit("Invalid MBR found on image with signature 0x%04hX", MBRsignature);
 
+   vbprintf (">>> Parsing Partition Table ...");
+
    //
    // Process the four physical partition entires in the MBR
    //
@@ -350,9 +354,12 @@
       } else {
          lastPartition = i;
          p->no         = i;
-         p->offset     = (off_t)((p->descriptor).offset) * BLOCKSIZE;
-         p->size       = (off_t)((p->descriptor).size)   * BLOCKSIZE;
+         p->offset     = (uint64_t)((p->descriptor).offset);
+         p->offset     *= BLOCKSIZE;
+         p->size       = (uint64_t)((p->descriptor).size);
+         p->size       *= BLOCKSIZE;
          sprintf(p->name, "Partition%d", i);
+         printPartition (p);
       }
    }
    //
@@ -381,12 +388,25 @@
          p->offset     = uStart + uOffset + (off_t)((ebr.descriptor).offset) * BLOCKSIZE;
          p->size       = (off_t)((ebr.descriptor).size)   * BLOCKSIZE;
          sprintf(p->name, "Partition%d", i);
+         printPartition (p);
 
          if (ebr.chain.type == 0) break;
          if (!PARTTYPE_IS_EXTENDED(ebr.chain.type)) usageAndExit("Logical partition chain broken");
          uOffset = (ebr.chain).offset;
       }
    }
+
+   vbprintf (">>> Done Parsing Partition Table.");
+}
+
+void printPartition (Partition *p) {
+  vbprintf (
+    "Partiton %d:\n"
+    "\tOffset: %lld\n"
+    "\tSize: %lld",
+
+    p->no, p->offset, p->size
+  );
 }
 
 int findPartition (const char* filename) {
@@ -411,7 +431,7 @@
    else if (strncmp (buf, "<<<",  3) == 0)  *disktype = "VDI";
    else usageAndExit("cannot autodetect disk type");
 
-   vbprintf ("disktype is %s", *disktype);
+   vbprintf (">>> Disk Type: %s", *disktype);
    return 0;
    close(fd);
 }
@@ -469,8 +489,8 @@
 static int VD_open(const char *cName, struct fuse_file_info *i) {
    vbprintf ("open: %s, %lld", cName, i->fh);
    int n = findPartition(cName);
-   if ((n == -1) || (entireDiskOpened && n > 0) || (partitionOpened & n == 0)) return -ENOENT;
-   if (readonly && ((i->flags & (O_WRONLY | O_RDWR) != 0))) return -EROFS;
+   if ((n == -1) || (entireDiskOpened && n > 0) || ((partitionOpened & n) == 0)) return -ENOENT;
+   if (readonly && (((i->flags & (O_WRONLY | O_RDWR)) != 0))) return -EROFS;
    
    if (n == 0) entireDiskOpened = 1;
    else        partitionOpened  = 1;
@@ -487,8 +507,8 @@
    Partition *p = &(partitionTable[n]);
 //   if (offset >= p->size) return 0;
 //   if (offset + len> p->size) len = p->size - offset;
-   if (offset >= p->size) return 0;
-   if ((offset + len) > p->size) len = p->size - offset;
+   if ((uint64_t)offset >= p->size) return 0;
+   if ((uint64_t)(offset + len) > p->size) len = p->size - offset;
 
    pthread_mutex_lock (&disk_mutex);
    int ret = DISKread(offset + p->offset, out, len);
@@ -516,8 +536,8 @@
    if (n<0) return -ENOENT;
    if ((n == 0) ? partitionOpened : entireDiskOpened) return -EIO;
    Partition *p = &(partitionTable[n]);
-   if (offset >= p->size) return 0;
-   if ((offset + len) > p->size) len = p->size - offset;
+   if ((uint64_t)offset >= p->size) return 0;
+   if ((uint64_t)(offset + len) > p->size) len = p->size - offset;
 
    pthread_mutex_lock (&disk_mutex);
    int ret = DISKwrite(offset + p->offset, in, len);
h2o
Posts: 40
Joined: 9. Feb 2009, 04:46

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by h2o »

and if you have vbox version 2.1 or later change VBoxHDD-new.h to VBoxHDD.h in the file.
mlafauci
Posts: 5
Joined: 31. Mar 2009, 00:15
Primary OS: Ubuntu 8.10
VBox Version: PUEL
Guest OSses: Windows XP Ubuntu

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by mlafauci »

I follow your suggestions, but now when I try to mount the Partition,
sudo mount -t ext2 ./mnt3/Partition1 ./p5 -o loop
I receive the following message:
./mnt3/Partition1: No such file or directory
stefan.becker
Volunteer
Posts: 7639
Joined: 7. Jun 2007, 21:53

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by stefan.becker »

Got same message at mount.

I use on Suse 11.1/4 the version 30 with the above patch.

vdifuse command works, but the mount gives the message "file not found", but the file is there.

Code: Select all

sudo mount /home/stefan/tmp/Partition1 /mnt -o loop
/home/stefan/tmp/Partition1: Datei oder Verzeichnis nicht gefunden
German message, in english: "file or directory not found".

Code: Select all

vdimount  -f  ./win2kprof.vdi /home/stefan/tmp/
ls -l /home/stefan/tmp/
-rw------- 1 stefan users 25769803776  1. Apr 20:55 EntireDisk
-rw------- 1 stefan users 25761544704  1. Apr 20:55 Partition1
TerryE
Volunteer
Posts: 3572
Joined: 28. May 2008, 08:40
Primary OS: Ubuntu other
VBox Version: PUEL
Guest OSses: Ubuntu 10.04 & 11.10, both Svr&Wstn, Debian, CentOS
Contact:

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by TerryE »

Sorry Stefan et al, my main Ubuntu test rig is unstable at the moment whenever I run VirtualBox. I suspect that is not VB by the way since I can also make it hang by hammering it with non-VBox tests. However, the downside is that I really only have my XP system for doing heavy VB work at the moment, so I did debug this and sort it out but I left it because I am up to my eye in other work at the moment. I'll drop H20 a PM because we've been colloborating on this privately and he can update you all with a new fix.
Read the Forum Posting Guide
Google your Q site:VirtualBox.org or search for the answer before posting.
h2o
Posts: 40
Joined: 9. Feb 2009, 04:46

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by h2o »

New release:

http://files.ellisons.org.uk/VBox/vdfuze_TE_40.tar.gz (yes the name is misspelled.)

This release fixes a 64-bit integer problem on 32-bit systems (EDIT it doesn't, see patch below), and quite a few other possible bugs.
Last edited by h2o on 5. Apr 2009, 21:22, edited 1 time in total.
TerryE
Volunteer
Posts: 3572
Joined: 28. May 2008, 08:40
Primary OS: Ubuntu other
VBox Version: PUEL
Guest OSses: Ubuntu 10.04 & 11.10, both Svr&Wstn, Debian, CentOS
Contact:

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by TerryE »

Oops sorry about the "brain fart". I've added a symlink so that the correct vdfuse spelling works as well.
Read the Forum Posting Guide
Google your Q site:VirtualBox.org or search for the answer before posting.
mlafauci
Posts: 5
Joined: 31. Mar 2009, 00:15
Primary OS: Ubuntu 8.10
VBox Version: PUEL
Guest OSses: Windows XP Ubuntu

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by mlafauci »

Hi all,
with the last version of vdfuse I can mount the Fuse filesystem.
But when I try to mount the file system for Partition1 (ext2) the following error appears for each subdirectory:
...
ls: cannot access mnt2/testproj: Input/output error
...
I cannot use any files on mi .vdi file.

Thanks in advance.
TerryE
Volunteer
Posts: 3572
Joined: 28. May 2008, 08:40
Primary OS: Ubuntu other
VBox Version: PUEL
Guest OSses: Ubuntu 10.04 & 11.10, both Svr&Wstn, Debian, CentOS
Contact:

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by TerryE »

Hi, I really need some more details on what you are doing. This is how I look at one of my LAMP system system partitions (s and sp are empty directories in my working directory that I use as mount points):

Code: Select all

terry@ellison4:~/fuse$ ./vdfuse -r -a -f /var/images/VirtualBox/VDIs/ub804jeosSys.vdi s
terry@ellison4:~/fuse$ ls -l s
total 2092738
-r--r--r-- 1 terry terry 1073741824 2009-04-04 19:53 EntireDisk
-r--r--r-- 1 terry terry  954100224 2009-04-04 19:53 Partition1
-r--r--r-- 1 terry terry  115121664 2009-04-04 19:53 Partition5
terry@ellison4:~/fuse$ sudo mount -t ext3 -o loop=/dev/loop0,ro s/Partition1 sp
terry@ellison4:~/fuse$ ls sp
app  boot   dev  home    initrd.img  lost+found  mnt  proc  sbin  sys  usr  vmlinuz
bin  cdrom  etc  initrd  lib         media       opt  root  srv   tmp  var
terry@ellison4:~/fuse$ cat sp/etc/hostname
ub804jeos
terry@ellison4:~/fuse$ 
Read the Forum Posting Guide
Google your Q site:VirtualBox.org or search for the answer before posting.
h2o
Posts: 40
Joined: 9. Feb 2009, 04:46

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by h2o »

I just figured out what the problem is: if the size of your disk is > 4GB and you are on a 32bit system, it won't work. Here's a patch to fix that and a bit of other stuff:

Code: Select all

Patch to fix up vdfuse v40
* virtualbox >= 2.1 renames VBoxHDD-new.h to VBoxHDD.h
* size MUST be 64 bits
* fix 'comparision between unsigned and signed' errors
--- vdfuse.c 2009-04-05 11:00:00.000000000 +0000
+++ vdfuse.c 2009-04-05 12:00:00.000000000 +0000
@@ -56,7 +56,7 @@
  *
  */
 #define FUSE_USE_VERSION 26
-#define FILE_OFFSET_BITS 64
+#define _FILE_OFFSET_BITS 64
 #include <limits.h>
 #include <fuse.h>
 #include <errno.h>
@@ -104,7 +104,11 @@
 // no longer test this, I've decided to remove this old API code, but I have left the abstraction in
 // I also used the ...testcase/tstVD.cpp as a coding template to work out how to call the VD routines.
 
+#ifdef OLDVBOXHDD // < v2.1
 #include <VBox/VBoxHDD-new.h>
+#else // >= v2.1
+#include <VBox/VBoxHDD.h>
+#endif
 #define DISKread(o,b,s) VDRead (hdDisk,o,b,s);
 #define DISKwrite(o,b,s) VDWrite (hdDisk,o,b,s);
 #define DISKclose VDClose(hdDisk, 0)
@@ -145,7 +149,7 @@
 typedef struct {
    char        name[PNAMESIZE+1];// name of partition
    off_t       offset;           // offset into disk in bytes
-   size_t      size;             // size of partiton in bytes
+   uint64_t    size;             // size of partiton in bytes
    int         no;               // partition number
    MBRentry    descriptor;       // copy of MBR / EBR descriptor that defines the partion
 } Partition;
@@ -503,8 +507,8 @@
    Partition *p = &(partitionTable[n]);
 //   if (offset >= p->size) return 0;
 //   if (offset + len> p->size) len = p->size - offset;
-   if (offset >= p->size) return 0;
-   if ((offset + len) > p->size) len = p->size - offset;
+   if ((uint64_t)offset >= p->size) return 0;
+   if ((uint64_t)(offset + len) > p->size) len = p->size - offset;
 
    pthread_mutex_lock (&disk_mutex);
    int ret = DISKread(offset + p->offset, out, len);
@@ -532,8 +536,8 @@
    if (n<0) return -ENOENT;
    if ((n == 0) ? partitionOpened : entireDiskOpened) return -EIO;
    Partition *p = &(partitionTable[n]);
-   if (offset >= p->size) return 0;
-   if ((offset + len) > p->size) len = p->size - offset;
+   if ((uint64_t)offset >= p->size) return 0;
+   if ((uint64_t)(offset + len) > p->size) len = p->size - offset;
 
    pthread_mutex_lock (&disk_mutex);
    int ret = DISKwrite(offset + p->offset, in, len);
This patch is for vdfuse v40.
Apply it with: patch vdfuse.c vdfuse.patch

IMPORTANT: If your vbox is older than 2.1 you are going have to add the -DOLDVBOXHDD flag to gcc.
mlafauci
Posts: 5
Joined: 31. Mar 2009, 00:15
Primary OS: Ubuntu 8.10
VBox Version: PUEL
Guest OSses: Windows XP Ubuntu

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by mlafauci »

You are right. My vdi image is big about 15GB, with the last patch It works.
Thank you very much!!!
fransiepansie
Posts: 3
Joined: 24. Apr 2009, 20:46
Primary OS: Ubuntu 8.10
VBox Version: OSE Debian
Guest OSses: winxp ubuntu810 more to try for cross compile farm

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by fransiepansie »

Hi Guys, nice work! I can not apply the patch, 'patch: **** malformed patch at line 16: @@ -104,7 +104,11 @@' and I think I need it: 'ERROR: Invalid EBR signature found on image'. May I have the latest version plz? Thanks from Frans
h2o
Posts: 40
Joined: 9. Feb 2009, 04:46

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by h2o »

I'm still waiting for Terry to make the next release, but it seems like he's busy with other stuff...
fransiepansie
Posts: 3
Joined: 24. Apr 2009, 20:46
Primary OS: Ubuntu 8.10
VBox Version: OSE Debian
Guest OSses: winxp ubuntu810 more to try for cross compile farm

Re: (Loop) mount any VBox disk type (VDI,VMDK,VHD) on Host

Post by fransiepansie »

Hi h20, I only need the latest .c file... Did you try to use 'parted' on the whole disk, and 'mke2fs' or ocfs2 on a partition? I am curious what is possible to setup the guest from the host, kind of unattended install.
Post Reply