Discuss: Mount any VBox-compatible disk image on the host
Discuss: Mount any VBox-compatible disk image on the host
In this thread, you can discuss anything you have to say about this howto.
This used to be the main thread for the howto, but because it's hard for people to find downloads and updates with comments interspersed with release announcements, I decided to change this into a discussion thread and start a new thread for the tutorial and release. Hope you understand
This used to be the main thread for the howto, but because it's hard for people to find downloads and updates with comments interspersed with release announcements, I decided to change this into a discussion thread and start a new thread for the tutorial and release. Hope you understand
Last edited by h2o on 11. May 2009, 06:14, edited 10 times in total.
UPDATE 2/12/09: NEW, updated FUSE-based version available here: http://forums.virtualbox.org/viewtopic. ... 9679#59679
And here it is:
UPDATE 2/10/09: used the new VBoxHDD-new.h api, added -DOLDAPI for compatibility, plugged small memory leak, added new option for choosing image type, prevent mapping non-existent partitions
OBSOLETE, DON'T USE
And here it is:
UPDATE 2/10/09: used the new VBoxHDD-new.h api, added -DOLDAPI for compatibility, plugged small memory leak, added new option for choosing image type, prevent mapping non-existent partitions
OBSOLETE, DON'T USE
Code: Select all
/* Original author: h2o on forums.virtualbox.org *
* http://forums.virtualbox.org/viewtopic.php?p=59275 *
* vdimount.c - tool for mounting VDI files */
/* *
* Available compile flags: *
* -DNO_VBOX_HDRS: don't use the VBox headers *
* (useful if you don't have them) *
* -DOLDAPI: use old VBoxHDD.h api (default uses VBoxHDD-new.h) *
* */
/* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <endian.h>
#include <errno.h>
#include <pthread.h>
#include <linux/nbd.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#warning "This program is obsolete, use the fuse-based version (vdfuse) instead"
#ifdef __GNUC__
#define UNUSED __attribute__ ((unused))
#else
#define UNUSED
#endif
// macro to convert uint64_t's to network order
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ntohll __bswap_64
#else
#define ntohll
#endif
#define htonll ntohll
#ifdef NO_VBOX_HDRS
#define VBOX_SUCCESS(i) (__builtin_expect (i >= 0, 1))
#define VBOX_FAILURE(i) (!VBOX_SUCCESS (i))
#endif
#ifdef OLDAPI
#ifdef NO_VBOX_HDRS
// from VBoxHDD.h
// (P)VDIDISK
struct VDIDISK;
typedef struct VDIDISK VDIDISK;
typedef VDIDISK *PVDIDISK;
// Flags
#define VDI_OPEN_FLAGS_NORMAL (0)
#define VDI_OPEN_FLAGS_READONLY (1)
// Functions
extern PVDIDISK VDIDiskCreate (void);
extern int VDIDiskOpenImage (PVDIDISK, const char *, unsigned);
extern void VDIDiskCloseImage (PVDIDISK);
extern int VDIDiskRead (PVDIDISK, uint64_t, void *, size_t);
extern int VDIDiskWrite (PVDIDISK, uint64_t, const void *, size_t);
extern uint64_t VDIDiskGetSize (PVDIDISK);
#else // NO_VBOX_HDRS
#define IN_RING3
#include <VBox/VBoxHDD.h>
#endif // NO_VBOX_HDRS
#else // OLDAPI
#ifdef NO_VBOX_HDRS
// from VBoxHDD-new.h
// VDINTERFACETYPE
typedef enum VDINTERFACETYPE
{
VDINTERFACETYPE_FIRST = 0,
VDINTERFACETYPE_ERROR = VDINTERFACETYPE_FIRST,
VDINTERFACETYPE_ASYNCIO,
VDINTERFACETYPE_PROGRESS,
VDINTERFACETYPE_CONFIG,
VDINTERFACETYPE_INVALID
} VDINTERFACETYPE;
// (P)VDINTERFACE
typedef struct VDINTERFACE
{
const char *pszInterfaceName;
uint32_t cbSize;
struct VDINTERFACE *pNext;
VDINTERFACETYPE enmInterface;
void *pvUser;
void *pCallbacks;
} VDINTERFACE, *PVDINTERFACE;
// (P)VBOXHDD
struct VBOXHDD;
typedef struct VBOXHDD VBOXHDD;
typedef VBOXHDD *PVBOXHDD;
// Flags
#define VD_OPEN_FLAGS_NORMAL 0
#define VD_OPEN_FLAGS_READONLY 1
// Functions
extern int VDCreate(PVDINTERFACE, PVBOXHDD *);
extern int VDOpen(PVBOXHDD, const char *, const char *, unsigned, PVDINTERFACE);
extern uint64_t VDGetSize(PVBOXHDD, unsigned);
extern int VDRead(PVBOXHDD, uint64_t, void *, size_t);
extern int VDWrite(PVBOXHDD, uint64_t, const void *, size_t);
extern int VDClose(PVBOXHDD, int /* should be bool */);
#else // NO_VBOX_HDRS
#define IN_RING3
#include <VBox/VBoxHDD-new.h>
#endif // NO_VBOX_HDRS
#endif // OLDAPI
#define SINSIZE sizeof (struct sockaddr_in)
// taken from cliserv.h in nbd package
#define INIT_PASSWD "NBDMAGIC"
#define BUFSIZE 1048576
#define NBD_FLAG_HAS_FLAGS (1)
#define NBD_FLAG_READ_ONLY (2)
uint64_t clientmagic = 0x00420281861253LL;
typedef struct
{
int pn; // partition #
int port; // port #
int sock; // socket #
struct sockaddr_in sin;
uint64_t offset; // offset into disk
uint64_t size; // size of partiton
} abinding;
// MBR entry structure
struct mbri
{
uint8_t status;
uint8_t shead;
uint8_t ssector;
uint8_t sbits;
uint8_t type;
uint8_t ehead;
uint8_t esector;
uint8_t ebits;
uint32_t offset;
uint32_t size;
};
// own implementation of GList from GLib
typedef struct _dlist dlist;
struct _dlist
{
void *data;
dlist *next;
dlist *prev;
};
// struct to pass args to server thread
struct serverarg
{
dlist *dl;
abinding *bn;
};
struct sigaction siga;
void *server_main (void *);
void cleanup (int);
void start_server (int);
int vread (abinding *, uint64_t, uint32_t, void *);
int vwrite (abinding *, uint64_t, uint32_t, const void *);
void timeout (int);
dlist *list_start (dlist *list)
{
while (list && list->prev)
list = list->prev;
return list;
}
dlist *list_end (dlist *list)
{
while (list && list->next)
list = list->next;
return list;
}
int list_len (dlist *list)
{
int i = 0;
list = list_start (list);
do
{
i++;
}
while (list && (list = list->next));
return i;
}
dlist *list_add (dlist *list, void *data)
{
if (list)
list = list_end (list);
dlist *newlist = malloc (sizeof (dlist));
newlist->data = data;
newlist->next = NULL;
newlist->prev = list;
if (list)
list->next = newlist;
return list_start (newlist);
}
dlist *list_del (dlist *item)
{
dlist *next = item->next;
dlist *prev = item->prev;
if (next)
next->prev = prev;
if (prev)
prev->next = next;
free (item);
if (next)
return list_start (next);
else if (prev)
return list_start (prev);
else
return NULL;
}
// printf to stderr
const char *errout_pre = "ERROR: ";
void errout (const char *format, ...)
{
char *tmpfmt = malloc (strlen (errout_pre) + strlen (format) + 2);
strcpy (tmpfmt, errout_pre);
strcat (tmpfmt, format);
strcat (tmpfmt, "\n");
va_list ap;
va_start (ap, format);
vfprintf (stderr, tmpfmt, ap);
va_end (ap);
free (tmpfmt);
fflush (stderr);
}
int verbose = 0;
// verbose printf
void vbprintf (const char *format, ...)
{
if (!verbose)
return;
va_list ap;
va_start (ap, format);
vprintf (format, ap);
va_end (ap);
fflush (stdout);
}
dlist *maplist;
dlist *thrs;
#ifdef OLDAPI
PVDIDISK vdidisk;
#else
VDINTERFACE dInterface;
PVBOXHDD dDisk;
#endif
int readonly;
#define BLOCKSIZE 512
pthread_mutex_t disk_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t sock_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t sock_mutex = PTHREAD_MUTEX_INITIALIZER;
struct sigaction blocksig;
struct sigaction freesig;
// valid backends
char *validBackends[] = {"VDI", "VMDK", "VHD", "raw"};
// adds partition->port mapping
int add_map (char *v)
{
char *eqi = strchr (v, '=');
if (!eqi)
{
errout ("invalid argument \"%s\"", v);
return -1;
}
char *pn = v;
char *port = eqi + 1;
*eqi = 0;
int pni;
if (strcmp (pn, "raw") == 0)
pni = -1;
else
pni = strtol (pn, 0, 10);
int porti = strtol (port, 0, 10);
if (pni == 0 || porti == 0)
{
errout ("invalid partition number %d or port number %d", pni, porti);
return -1;
}
abinding *binding = malloc (sizeof (abinding));
binding->pn = pni;
binding->port = porti;
maplist = list_add (maplist, binding);
return 0;
}
// processes logical partitions (does this work???)
int pnse (uint64_t offset)
{
int pn = 5;
while (offset)
{
char buf[512];
#ifdef OLDAPI
VDIDiskRead (vdidisk, offset, buf, 512);
#else
VDRead (dDisk, offset, buf, 512);
#endif
struct mbri *entry_a = (struct mbri *)(buf + 446);
struct mbri *entry_b = (struct mbri *)(buf + 462);
uint16_t *sig = (uint16_t *)(buf + 510);
if (*sig != 0xaa55)
{
errout ("invalid ebr signature at offset %llx", offset);
return -1;
}
uint64_t offset64 = (uint64_t)entry_a->offset;
offset64 *= BLOCKSIZE;
uint64_t size64 = (uint64_t)entry_a->size;
size64 *= BLOCKSIZE;
dlist *mm = maplist;
while (mm)
{
abinding *bn = mm->data;
if (bn->pn == pn)
{
bn->offset = offset64;
bn->size = size64;
}
mm = mm->next;
}
offset = entry_b->offset;
pn++;
}
return 0;
}
// processes partiton table
int pns ()
{
char dmbr[512];
#ifdef OLDAPI
VDIDiskRead (vdidisk, 0, dmbr, 512);
#else
VDRead (dDisk, 0, dmbr, 512);
#endif
struct mbri *pts = (struct mbri *)(dmbr + 446);
uint16_t *sig;
sig = (uint16_t *)(dmbr + 510);
if (*sig != 0xaa55)
{
errout ("invalid mbr signature");
return -1;
}
int i = 0;
dlist *mm = maplist;
abinding *bn;
while (i < 4)
{
int pn = i + 1;
uint64_t offset64 = (uint64_t)pts[i].offset;
offset64 *= BLOCKSIZE;
uint64_t size64 = (uint64_t)pts[i].size;
size64 *= BLOCKSIZE;
while (mm)
{
bn = mm->data;
if (bn->pn == pn)
{
bn->offset = offset64;
bn->size = size64;
}
mm = mm->next;
}
if (pts[i].type == 5)
{
uint64_t extpart = (uint64_t) pts[i].offset;
extpart = extpart * BLOCKSIZE;
if (pnse (extpart) < 0)
return -1;
}
i++;
}
mm = maplist;
while (mm)
{
bn = mm->data;
if (bn->pn == -1)
{
bn->offset = 0;
#ifdef OLDAPI
bn->size = VDIDiskGetSize (vdidisk);
#else
bn->size = VDGetSize (dDisk, 0);
#endif
break;
}
mm = mm->next;
}
return 0;
}
int main (int c, char **v)
{
if (c < 4)
{
printf ("Usage: %s [-r] [-v] [-d] [-t type] -f image-file partiton-number=port-number "
"[partition-#=port-#] [...]\n"
"\t-r readonly\n"
"\t-f path to image file\n"
"\t-d daemonize\n"
#ifndef OLDAPI
"\t-t image type (VDI, VMDK, VHD, raw) (default: VDI)\n"
#endif
"\t-v verbose\n"
"To use the entire disk use \"raw\" as the partition number.\n\n"
"Partition 1 is first partiton; partition 5 is first logical partition.\n"
"Example:\tMap partition 1 to port 2001, partition 2 to port 2002:\n"
"\t%s -f /path/to/image/file 1=2001 2=2002\n", v[0], v[0]);
return 255;
}
char *imagefilename = NULL;
#ifndef OLDAPI
char *diskType = "VDI";
#endif
// parse args
int dofork = 0;
v++;
while (*v)
{
if (strcmp (*v, "-r") == 0)
readonly = 1;
else if (strcmp (*v, "-f") == 0)
imagefilename = *++v;
else if (strcmp (*v, "-d") == 0)
dofork = 1;
else if (strcmp (*v, "-v") == 0)
verbose = 1;
#ifndef OLDAPI
else if (strcmp (*v, "-t") == 0)
diskType = *++v;
#endif
else
{
if (add_map (*v) < 0)
return 1;
}
v++;
}
if (!maplist)
{
errout ("no partion->port mappings specified");
return 1;
}
if (!imagefilename)
{
errout ("no image file specified");
return 1;
}
#ifndef OLDAPI
unsigned int di = 0;
int invalidBackend = 1;
while (di < (sizeof (validBackends) / sizeof (char *)))
{
if (strcmp (validBackends[di], diskType) == 0)
{
invalidBackend = 0;
break;
}
di++;
}
if (invalidBackend)
{
errout ("invalid disk type specified, valid types are VDI, VMDK, VHD, and raw.");
return 1;
}
#endif
// open disk
#ifdef OLDAPI
vdidisk = VDIDiskCreate ();
int imageopen = VDI_OPEN_FLAGS_NORMAL;
if (readonly)
imageopen = VDI_OPEN_FLAGS_READONLY;
int ret = VDIDiskOpenImage (vdidisk, imagefilename, imageopen);
#else
dInterface.pszInterfaceName = "What's an interface?";
dInterface.enmInterface = VDINTERFACETYPE_FIRST;
VDCreate (&dInterface, &dDisk);
int imageopen = VD_OPEN_FLAGS_NORMAL;
if (readonly)
imageopen = VD_OPEN_FLAGS_READONLY;
int ret = VDOpen (dDisk, diskType, imagefilename, imageopen, &dInterface);
#endif
if (VBOX_FAILURE (ret))
{
errout ("opening vbox image failed, errno %d", ret);
return 1;
}
vbprintf ("image opened\n");
if (pns () < 0)
return 1;
// setup poll structures
struct pollfd *pfd = malloc (list_len (maplist) * sizeof (struct pollfd));
int pfdl = 0;
// bind / listen sockets
dlist *mm = maplist;
int i = 0;
while (mm)
{
abinding *bn = mm->data;
bn->sock = socket (AF_INET, SOCK_STREAM, 0);
pfd[pfdl].fd = bn->sock;
pfd[pfdl].events = POLLIN;
pfdl++;
memset (&bn->sin, 0, SINSIZE);
bn->sin.sin_family = AF_INET;
bn->sin.sin_port = htons (bn->port);
bn->sin.sin_addr.s_addr = htonl (0x7f000001); /* 127.0.0.1 */
ret = bind (bn->sock, (struct sockaddr *)&bn->sin, SINSIZE);
if (ret < 0)
{
errout ("Failed binding socket: %m", errno);
return 1;
}
listen (bn->sock, 1024);
vbprintf ("Binding %d:\n\tPartition #: %d\n\tPort: %d\n\tOffset: %lld\n\tSize: %lld\n\n", i++, bn->pn, bn->port, bn->offset, bn->size);
if (!bn->size)
{
errout ("Size of binding %d is zero, either partition %d does not exist, or the partition table is corrupt/not valid.", i, bn->pn);
return 1;
}
mm = mm->next;
}
siga.sa_handler = cleanup;
sigfillset (&siga.sa_mask);
siga.sa_flags = 0;
sigaction (SIGTERM, &siga, 0);
sigaction (SIGINT, &siga, 0);
blocksig.sa_handler = SIG_IGN;
// daemonize
if (dofork)
{
verbose = 0;
int forkrc = fork ();
if (forkrc < 0)
errout ("failed to daemonize: %m", errno);
else if (forkrc)
return 0;
else
{
int devnull = open ("/dev/null", O_RDWR);
dup2 (devnull, 0);
dup2 (devnull, 1);
dup2 (devnull, 2);
close (devnull);
}
}
// MAIN LOOP
int po;
while (1)
{
po = poll (pfd, pfdl, 1000);
if (po > 0)
{
i = 0;
while (i < pfdl)
{
if (pfd[i].revents & POLLIN)
{
pthread_mutex_lock (&sock_mutex);
start_server (pfd[i].fd);
// Keep from starting multiple threads for one connection
pthread_cond_wait (&sock_cond, &sock_mutex);
pthread_mutex_unlock (&sock_mutex);
}
i++;
}
}
}
}
void start_server (int fd)
{
dlist *mm = maplist;
abinding *bn;
int notfound = 1;
while (mm)
{
bn = mm->data;
if (bn->sock == fd)
{
notfound = 0;
break;
}
mm = mm->next;
}
if (notfound)
return;
vbprintf ("starting server for partition #%d\n", bn->pn);
pthread_t *thr = malloc (sizeof (pthread_t));
thrs = list_add (thrs, thr);
struct serverarg *sarg = malloc (sizeof (struct serverarg));
sarg->dl = list_end (thrs);
sarg->bn = bn;
pthread_create (thr, NULL, server_main, (void *)sarg);
}
// SIGPIPE-safe write
int swrite (int fd, const void *buf, int count)
{
sigaction (SIGPIPE, &blocksig, &freesig);
int ret = write (fd, buf, count);
int oerrno = errno;
sigaction (SIGPIPE, &freesig, &blocksig);
errno = oerrno;
return ret;
}
// negotiate function (taken from nbd-server)
int negotiate (int fd, abinding *bn)
{
sigaction (SIGPIPE, &blocksig, &freesig);
if (write (fd, INIT_PASSWD, 8) < 0)
{
errout ("negotiate: cannot write INIT_PASSWD: %m", errno);
return -1;
}
uint64_t clientmagicout = htonll (clientmagic);
if (write (fd, &clientmagicout, sizeof (clientmagic)) < 0)
{
errout ("negotiate: cannot write clientmagic: %m", errno);
return -1;
}
uint64_t sizeout = htonll (bn->size);
if (write (fd, &sizeout, sizeof (sizeout)) < 0)
{
errout ("negotiate: cannot write size: %m", errno);
return -1;
}
uint32_t flags = NBD_FLAG_HAS_FLAGS;
if (readonly)
flags |= NBD_FLAG_READ_ONLY;
flags = htonl (flags);
if (write (fd, &flags, sizeof (flags)) < 0)
{
errout ("negotiate: cannot write flags: %m", errno);
return -1;
}
char *nas[124];
memset (nas, 0, 124);
if (write (fd, nas, 124) < 0)
{
errout ("negotiate: cannot write zeroes: %m", errno);
return -1;
}
sigaction (SIGPIPE, &freesig, &blocksig);
return 0;
}
// macro for sending error packet
#define SERR(fd,reply,code) \
{ \
reply.error = htonl (code); \
swrite (fd, &reply, sizeof (reply)); \
reply.error = 0; \
if (errno == EPIPE) \
break;\
}
void *server_main (void *sarg)
{
struct serverarg *sargs = sarg;
abinding *bn = sargs->bn;
pthread_mutex_lock (&sock_mutex);
int mycon = accept (bn->sock, 0, 0);
pthread_cond_broadcast (&sock_cond);
pthread_mutex_unlock (&sock_mutex);
if (mycon < 0)
{
errout ("failed to accept connection on socket %d: %m", bn->sock, errno);
goto out;
}
struct nbd_request request;
struct nbd_reply reply;
if (negotiate (mycon, bn) < 0)
goto out;
reply.magic = htonl (NBD_REPLY_MAGIC);
reply.error = 0;
while (1)
{
char buf[BUFSIZE];
int reqread = read (mycon, &request, sizeof (request));
if (reqread < 0)
goto out;
else if (reqread != sizeof (request))
{
errout ("bad packet: packet is %d bytes instead of %d", reqread, sizeof (request));
SERR (mycon, reply, EINVAL);
continue;
}
request.magic = ntohl (request.magic);
request.type = ntohl (request.type);
request.from = ntohll (request.from);
request.len = ntohl (request.len);
if (request.type == NBD_CMD_DISC)
{
vbprintf ("got disconnect command\n");
break;
}
if (request.magic != NBD_REQUEST_MAGIC)
{
errout ("invalid request magic");
SERR (mycon, reply, EINVAL);
continue;
}
if (request.len > BUFSIZE + sizeof (reply))
{
errout ("request too big");
SERR (mycon, reply, ENOBUFS);
continue;
}
memcpy (reply.handle, request.handle, sizeof (reply.handle));
if (request.from + request.len > bn->offset + bn->size)
{
errout ("request beyond end of device");
SERR (mycon, reply, EINVAL);
continue;
}
if (request.type == NBD_CMD_WRITE)
{
vbprintf ("got write command to write %d bytes at offset %lld on partition %d\n", request.len, request.from, bn->pn);
if (readonly)
{
errout ("attempted write on readonly map");
SERR (mycon, reply, EPERM);
continue;
}
struct pollfd pfd;
pfd.fd = mycon;
pfd.events = POLLIN;
if (poll (&pfd, 1, 5000) == 0)
{
errout ("read data timed out");
SERR (mycon, reply, ETIMEDOUT);
continue;
}
read (mycon, buf, request.len);
if (vwrite (bn, request.from, request.len, buf) < 0)
{
errout ("problem writing to disk");
SERR (mycon, reply, EIO);
continue;
}
swrite (mycon, &reply, sizeof (reply));
continue;
}
else if (request.type == NBD_CMD_READ)
{
vbprintf ("got read command to read %d bytes at offset %lld on partition %d\n", request.len, request.from, bn->pn);
if (vread (bn, request.from, request.len, buf + sizeof (reply)) < 0)
{
errout ("problem reading from disk");
SERR (mycon, reply, EIO);
continue;
}
memcpy (buf, &reply, sizeof (reply));
swrite (mycon, buf, request.len + sizeof (reply));
continue;
}
else
{
errout ("invalid command");
SERR (mycon, reply, EINVAL);
continue;
}
}
out:
close (mycon);
free (sargs->dl->data); // free pthread_t
thrs = list_del (sargs->dl); // free list item
free (sarg); // free server args
vbprintf ("closing server for partition #%d\n", bn->pn);
pthread_exit (0);
}
int vread (abinding *bn, uint64_t from, uint32_t len, void *buf)
{
pthread_mutex_lock (&disk_mutex);
#ifdef OLDAPI
int ret = VDIDiskRead (vdidisk, from + bn->offset, buf, len);
#else
int ret = VDRead (dDisk, from + bn->offset, buf, len);
#endif
pthread_mutex_unlock (&disk_mutex);
if (VBOX_SUCCESS (ret))
return 0;
else
return -1;
}
int vwrite (abinding *bn, uint64_t from, uint32_t len, const void *buf)
{
pthread_mutex_lock (&disk_mutex);
#ifdef OLDAPI
int ret = VDIDiskWrite (vdidisk, from + bn->offset, buf, len);
#else
int ret = VDWrite (dDisk, from + bn->offset, buf, len);
#endif
pthread_mutex_unlock (&disk_mutex);
if (VBOX_SUCCESS (ret))
return 0;
else
return -1;
}
// called on SIGINT / SIGTERM
void cleanup (int s UNUSED)
{
#ifdef OLDAPI
VDIDiskCloseImage (vdidisk);
#else
VDClose (dDisk, 0);
#endif
dlist *mm = maplist;
while (mm)
{
abinding *bn = mm->data;
close (bn->sock);
mm = mm->next;
}
exit (0);
}
Last edited by h2o on 5. Nov 2009, 06:14, edited 5 times in total.
-
- 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:
AFAIK from 2.1 as part of the move to a more format neutral implementation, the public interface to VBoxDD.so VBoxHDD.h has been superceded by VBoxHDD-new.h (which also documents this API). This defines new entries and API so, for example, VDIDiskRead has been replaced by VDRead. The main difference with the VD* routines is that they work on all supported image formats (VDI, VMDK, raw VMDK, VHD).
So my recommendation would be to switch to using the new interface.
As far as the MBR decode that you include, it is just that; it does not decode the EBS. Why not just use the code in the routine VBoxInternalManage.cpp:partRead as a template?
Two niggles: (i) I see you belong to the school of programming: documentation and comments are for wusses; and (ii) I am not sure why you bother to code up your own list processing routines rather than just use the standard STL ones.
So my recommendation would be to switch to using the new interface.
As far as the MBR decode that you include, it is just that; it does not decode the EBS. Why not just use the code in the routine VBoxInternalManage.cpp:partRead as a template?
Two niggles: (i) I see you belong to the school of programming: documentation and comments are for wusses; and (ii) I am not sure why you bother to code up your own list processing routines rather than just use the standard STL ones.
Read the Forum Posting Guide
Google your Q site:VirtualBox.org or search for the answer before posting.
Google your Q site:VirtualBox.org or search for the answer before posting.
I get the following errors when trying to compile, I don't have the headers I'm not using the OSE version cause I need usb2 support.
Code: Select all
/tmp/ccjtlwWP.o: In function `pnse':
vdimount.c:(.text+0x3ba): undefined reference to `VDIDiskRead'
/tmp/ccjtlwWP.o: In function `pns':
vdimount.c:(.text+0x5ac): undefined reference to `VDIDiskRead'
vdimount.c:(.text+0x7ee): undefined reference to `VDIDiskGetSize'
/tmp/ccjtlwWP.o: In function `main':
vdimount.c:(.text+0x9c3): undefined reference to `VDIDiskCreate'
vdimount.c:(.text+0x9fb): undefined reference to `VDIDiskOpenImage'
/tmp/ccjtlwWP.o: In function `vread':
vdimount.c:(.text+0x18e6): undefined reference to `VDIDiskRead'
/tmp/ccjtlwWP.o: In function `vwrite':
vdimount.c:(.text+0x1970): undefined reference to `VDIDiskWrite'
/tmp/ccjtlwWP.o: In function `cleanup':
vdimount.c:(.text+0x19b7): undefined reference to `VDIDiskCloseImage'
collect2: ld returned 1 exit status
-
- 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:
That's because as I said, the current version of VBoxDD.so has retired the VBoxHDD.h interface, and VDRead replaces VDIDiskRead, etc.echo6 wrote:I get the following errors when trying to compile...
Read the Forum Posting Guide
Google your Q site:VirtualBox.org or search for the answer before posting.
Google your Q site:VirtualBox.org or search for the answer before posting.
I used vditool.cpp as a template.TerryE wrote:This defines new entries and API so, for example, VDIDiskRead has been replaced by VDRead. The main difference with the VD* routines is that they work on all supported image formats (VDI, VMDK, raw VMDK, VHD).
This was just a project I did out of boredom, and yes, I am a total beginner in C and I don't know a cent of C++. The list functions are based on GLib, and since I don't know C++, I had to use my own.TerryE wrote:Two niggles: (i) I see you belong to the school of programming: documentation and comments are for wusses; and (ii) I am not sure why you bother to code up your own list processing routines rather than just use the standard STL ones.
I updated it for the new api, and I added the comments that TerryE wanted:
http://forums.virtualbox.org/viewtopic. ... 9276#59276
http://forums.virtualbox.org/viewtopic. ... 9276#59276
-
- 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:
I am a bit buried at the moment, so I can't look at this now, but I've bookmarked it to come back to. If you've just learnt C, where did you come up with the idea of using NBD?
Read the Forum Posting Guide
Google your Q site:VirtualBox.org or search for the answer before posting.
Google your Q site:VirtualBox.org or search for the answer before posting.
OK, I have to admit, I didn't "just" learned C; I've gotten sort of good at it; it's just that I don't have good programming practices (comments, etc.) The NBD idea came from vmware-loop, and quite a lot of the code is based on nbd-server. I didn't want to learn kernel programming nor did I want to rewrite every file system with FUSE, so I chose NBD.
-
- 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:
I thought about using Fuse to create a file system which exposed the partitions as separate files Partition0, etc. within the root of the FS which are a block image of the virtualised partition on the disk and then just use a loop mount to mount the partition that you need. Writing a Fuse FS like this is pretty straight forward.
Read the Forum Posting Guide
Google your Q site:VirtualBox.org or search for the answer before posting.
Google your Q site:VirtualBox.org or search for the answer before posting.
I made another tool based on TerryE's idea.TerryE wrote:I thought about using Fuse to create a file system which exposed the partitions as separate files Partition0, etc. within the root of the FS which are a block image of the virtualised partition on the disk and then just use a loop mount to mount the partition that you need. Writing a Fuse FS like this is pretty straight forward.
Pre-1) Get the tools
On Ubuntu:
Code: Select all
apt-get install build-essential libfuse-dev
Download it, compile with:
Code: Select all
gcc vdifuse.c -o vdifuse `pkg-config --cflags --libs fuse` -l:/path/to/virtualbox/VBoxDD.so -Wl,-rpath,/path/to/virtualbox -pthread -I/path/to/virtualbox/headers/include
Code: Select all
gcc vdifuse.c -o vdifuse `pkg-config --cflags --libs fuse` -l:/path/to/virtualbox/VBoxDD.so -Wl,-rpath,/path/to/virtualbox -pthread -DNO_VBOX_HDRS
2) Mount the image
Code: Select all
vdifuse options -f image-file mountpoint
Code: Select all
-r: readonly mode
-t type: choose image type (auto, VDI, VMDK, VHD, raw)
-a: allow all users to use the disk
-aw: allow all users to modify the disk
-g: run in foreground
-v: verbose
-d: debug fuse
- EntireDisk: gives you the raw image of a disk. Useful for partitioning tools such as GParted or fdisk (but remember to restart vdifuse after modifying the partitions).
- Partition[1-4]: images of each primary partition.
- Partition[5+]: images of each logical partition.
Code: Select all
modprobe loop (if your loop is in a module)
mount -o loop /path/to/partitions/PartitionX /mount/point
Unlike the NBD based tool, this (supposedly) works with any operating system that supports FUSE.
And here's the FUSE version:
Update 2/13/09: fix things up for big endian systems
Update 2/13/09: fix things up for big endian systems
Code: Select all
/* Original author: h2o on forums.virtualbox.org *
* http://forums.virtualbox.org/viewtopic.php?p=59275 *
* vdifuse.c - tool for mounting VDI/VMDK/VHD files */
/* *
* Available compile flags: *
* -DNO_VBOX_HDRS: don't use the VBox headers *
* (useful if you don't have them) *
* -DOLDAPI: use old VBoxHDD.h api (default uses VBoxHDD-new.h) *
* */
/* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#define FUSE_USE_VERSION 26
#define FILE_OFFSET_BITS 64
#include <limits.h>
#include <fuse.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#define IN_RING3
#ifdef NO_VBOX_HDRS // don't use vbox headers
#define VBOX_SUCCESS(i) (__builtin_expect (i >= 0, 1))
#define VBOX_FAILURE(i) (!VBOX_SUCCESS (i))
#ifdef OLDAPI
// PVDIDISK
typedef struct VDIDISK *PVDIDISK;
// Flags
#define VDI_OPEN_FLAGS_NORMAL (0)
#define VDI_OPEN_FLAGS_READONLY (1)
// Functions
extern PVDIDISK VDIDiskCreate (void);
extern int VDIDiskOpenImage (PVDIDISK, const char *, unsigned);
extern void VDIDiskCloseImage (PVDIDISK);
extern int VDIDiskRead (PVDIDISK, uint64_t, void *, size_t);
extern int VDIDiskWrite (PVDIDISK, uint64_t, const void *, size_t);
extern uint64_t VDIDiskGetSize (PVDIDISK);
#else // OLDAPI
// Flags
#define VD_OPEN_FLAGS_NORMAL 0
#define VD_OPEN_FLAGS_READONLY 1
// (P)VDINTERFACE
typedef struct VDINTERFACE
{
const char *pszInterfaceName;
uint32_t cbSize;
struct VDINTERFACE *pNext;
enum { VDINTERFACETYPE_FIRST = 0 } enmInterface;
void *pvUser;
void *pCallbacks;
} VDINTERFACE, *PVDINTERFACE;
// PVBOXHDD
typedef struct VBOXHDD *PVBOXHDD;
extern int VDCreate(PVDINTERFACE, PVBOXHDD *);
extern int VDOpen(PVBOXHDD, const char *, const char *, unsigned, PVDINTERFACE);
extern uint64_t VDGetSize(PVBOXHDD, unsigned);
extern int VDRead(PVBOXHDD, uint64_t, void *, size_t);
extern int VDWrite(PVBOXHDD, uint64_t, const void *, size_t);
extern int VDClose(PVBOXHDD, int /* should be bool */);
#endif // OLDAPI
#else // NO_VBOX_HDRS
#ifdef OLDAPI
#include <VBox/VBoxHDD.h>
#else // OLDAPI
#include <VBox/VBoxHDD-new.h>
#endif
#endif // NO_VBOX_HDRS
#define BLOCKSIZE 512
#ifdef __GNUC__
#define UNUSED __attribute__ ((unused))
#else
#define UNUSED
#endif
// own version of GLib's GList
typedef struct _dlist dlist;
struct _dlist
{
void *data;
dlist *next;
dlist *prev;
};
// sort of like g_list_append
dlist *list_add (dlist *list, void *data)
{
if (list)
while (list && list->next)
list = list->next;
dlist *newlist = malloc (sizeof (dlist));
newlist->data = data;
newlist->next = NULL;
newlist->prev = list;
if (list)
list->next = newlist;
while (newlist && newlist->prev)
newlist = newlist->prev;
return newlist;
}
// printf to stderr
const char *errout_pre = "ERROR: ";
void errout (const char *format, ...)
{
char *tmpfmt = malloc (strlen (errout_pre) + strlen (format) + 2);
strcpy (tmpfmt, errout_pre);
strcat (tmpfmt, format);
strcat (tmpfmt, "\n");
va_list ap;
va_start (ap, format);
vfprintf (stderr, tmpfmt, ap);
va_end (ap);
free (tmpfmt);
fflush (stderr);
}
// verbose printf
int verbose = 0;
void vbprintf (const char *format, ...)
{
if (!verbose)
return;
char *tmpfmt = malloc (strlen (format) + 2);
strcpy (tmpfmt, format);
strcat (tmpfmt, "\n");
va_list ap;
va_start (ap, format);
vprintf (tmpfmt, ap);
va_end (ap);
free (tmpfmt);
fflush (stdout);
}
// partition table entry format
struct mbri
{
uint8_t status;
uint8_t shead;
uint8_t ssector;
uint8_t sbits;
uint8_t type;
uint8_t ehead;
uint8_t esector;
uint8_t ebits;
uint32_t offset;
uint32_t size;
};
typedef struct
{
int pn; // partition #
uint64_t offset; // offset into disk
uint64_t size; // size of partiton
} apart;
dlist *partlist = NULL;
int foreground = 0;
int readonly = 0;
int allowall = 0; // allow all users to read from disk
int allowallw = 0; // allow all users to write to disk
uid_t myuid = 0;
gid_t mygid = 0;
uint64_t disksize = 0;
char *validBackends[] = {"auto", "VDI", "VMDK", "VHD", "raw"};
#define WHOLEPART "EntireDisk"
#ifdef OLDAPI
PVDIDISK vdidisk;
#else
VDINTERFACE dInterface;
PVBOXHDD dDisk;
#endif
// parse extended partitions
int pnse (uint64_t offset)
{
int pn = 5;
while (1)
{
char buf[66];
#ifdef OLDAPI
VDIDiskRead (vdidisk, offset + 446, buf, 66);
#else
VDRead (dDisk, offset + 446, buf, 66);
#endif
struct mbri *entry_a = (struct mbri *)buf;
struct mbri *entry_b = (struct mbri *)(buf + 16);
char *sig = buf + 64;
if (sig[0] != (char)0x55 || sig[1] != (char)0xaa)
{
errout ("invalid ebr signature at offset %llx", offset);
return -1;
}
uint64_t offset64 = (uint64_t)entry_a->offset;
offset64 *= BLOCKSIZE;
uint64_t size64 = (uint64_t)entry_a->size;
size64 *= BLOCKSIZE;
apart *mypart = malloc (sizeof (apart));
mypart->pn = pn;
mypart->offset = offset + offset64;
mypart->size = size64;
partlist = list_add (partlist, mypart);
vbprintf ("Partition %d (logical parition %d):\n\tOffset: %lld bytes\n\tSize: %lld bytes\n", pn, pn - 4, offset64, size64);
uint64_t nextoffset = (uint64_t)entry_b->offset;
if (nextoffset == 0)
break;
nextoffset *= BLOCKSIZE;
offset += nextoffset;
pn++;
}
return 0;
}
// parse primary partitions
int pns ()
{
char dmbr[66];
#ifdef OLDAPI
VDIDiskRead (vdidisk, 446, dmbr, 66);
#else
VDRead (dDisk, 446, dmbr, 66);
#endif
struct mbri *pts = (struct mbri *)dmbr;
char *sig = dmbr + 64;
if (sig[0] != (char)0x55 || sig[1] != (char)0xaa)
{
errout ("invalid mbr signature");
return -1;
}
int i = 0;
while (i < 4)
{
int pn = i + 1;
uint64_t offset64 = (uint64_t)pts[i].offset;
offset64 *= BLOCKSIZE;
uint64_t size64 = (uint64_t)pts[i].size;
size64 *= BLOCKSIZE;
if (size64 == 0)
goto end;
apart *mypart = malloc (sizeof (apart));
mypart->pn = pn;
mypart->offset = offset64;
mypart->size = size64;
partlist = list_add (partlist, mypart);
if (pts[i].type == 5)
if (pnse (offset64) < 0)
return -1;
vbprintf ("Partition %d:\n\tOffset: %lld bytes\n\tSize: %lld bytes\n", pn, offset64, size64);
end:
i++;
}
return 0;
}
// detects type of virtual image
int detectDiskType (char **disktype, char *filename)
{
int fd = open (filename, O_RDONLY);
char buf[8];
read (fd, buf, sizeof (buf));
if (strcmp (buf, "conectix") == 0)
{
*disktype = "VHD";
vbprintf ("disktype is VHD");
return 0;
}
buf[4] = 0;
if (strcmp (buf, "VMDK") == 0 || strcmp (buf, "KDMV") == 0)
{
*disktype = "VMDK";
vbprintf ("disktype is VMDK");
return 0;
}
buf[3] = 0;
if (strcmp (buf, "<<<") == 0)
{
*disktype = "VDI";
vbprintf ("disktype is VDI");
return 0;
}
errout ("cannot autodetect disk type; please use the -t option.");
return -1;
}
// gets partition # from fuse filename
int getpn (const char *c)
{
int ret;
if (strcmp (c, "/" WHOLEPART) == 0)
return 0;
else if (sscanf (c, "/Partition%d", &ret) > 0)
return ret;
else
return -2;
}
// gets apart entry from fuse filename
apart *getpart (const char *c)
{
int pn = getpn (c);
if (pn == -2)
return NULL;
dlist *pm = partlist;
while (pm)
{
if (((apart *)(pm->data))->pn == pn)
return (apart *)pm->data;
pm = pm->next;
}
return NULL;
}
int my_access (const char *c, int i)
{
vbprintf ("access: %s, flags=%d", c, i);
if (strcmp ("/", c) == 0)
return 0;
int partnum = getpn (c);
if (partnum == -2)
return -ENOENT;
int wr = (i & W_OK) ? 1 : 0;
dlist *pm = partlist;
// check if partitions exists
int partexists = 0;
while (pm)
{
apart *mypart = (apart *)pm->data;
if (mypart->pn == partnum)
{
partexists = 1;
break;
}
pm = pm->next;
}
if (!partexists)
return -ENOENT;
struct fuse_context *ctxt = fuse_get_context ();
if (readonly && wr)
return -EROFS;
if
(
ctxt->uid == 0 ||
(allowall && !wr) ||
allowallw ||
ctxt->uid == myuid
)
return 0;
else
return -EACCES;
}
int my_open (const char *c, struct fuse_file_info *i)
{
vbprintf ("open: %s", c);
int aflags = F_OK;
if (i->flags & O_WRONLY)
aflags |= W_OK;
else if (i->flags & O_RDONLY)
aflags |= R_OK;
else if (i->flags & O_RDWR)
aflags |= (W_OK | R_OK);
int ret = my_access (c, aflags);
if (ret < 0)
return ret;
return ret;
}
enum ioop_cmd
{
IOOP_READ,
IOOP_WRITE
};
// function for io operations with disk
pthread_mutex_t disk_mutex = PTHREAD_MUTEX_INITIALIZER;
int ioop (enum ioop_cmd cmd, apart *mypart, off_t offset, void *buf, size_t len)
{
uint64_t totend = offset;
if (totend > disksize)
return -EINVAL;
totend += (uint64_t)len;
if (totend > disksize)
len = (size_t)disksize - (size_t)offset;
int ret;
pthread_mutex_lock (&disk_mutex);
if (cmd == IOOP_READ)
{
#ifdef OLDAPI
ret = VDIDiskRead (vdidisk, offset + mypart->offset, buf, len);
#else
ret = VDRead (dDisk, offset + mypart->offset, buf, len);
#endif
}
else if (cmd == IOOP_WRITE)
{
#ifdef OLDAPI
ret = VDIDiskWrite (vdidisk, offset + mypart->offset, buf, len);
#else
ret = VDWrite (dDisk, offset + mypart->offset, buf, len);
#endif
}
else
return -EINVAL;
pthread_mutex_unlock (&disk_mutex);
if (VBOX_SUCCESS (ret))
return len;
else
return -EIO;
}
int my_read (const char *c, char *out, size_t len, off_t offset, struct fuse_file_info *i UNUSED)
{
vbprintf ("read: %s, offset=%lld, length=%d", c, offset, len);
apart *mypart = getpart (c);
if (!mypart)
return -ENOENT;
return ioop (IOOP_READ, mypart, offset, out, len);
}
int my_write (const char *c, const char *in, size_t len, off_t offset, struct fuse_file_info *i UNUSED)
{
vbprintf ("write: %s, offset=%lld, length=%d", c, offset, len);
apart *mypart = getpart (c);
if (!mypart)
return -ENOENT;
if (readonly)
return -EROFS;
return ioop (IOOP_WRITE, mypart, offset, (char *)in /* avoid const warning*/, len);
}
int my_readdir (const char *p, void *buf, fuse_fill_dir_t filler, off_t offset UNUSED, struct fuse_file_info *i UNUSED)
{
vbprintf ("readdir");
if (strcmp ("/", p) != 0)
return -ENOENT;
dlist *pm = partlist;
filler (buf, ".", NULL, 0);
filler (buf, "..", NULL, 0);
filler (buf, WHOLEPART, NULL, 0);
while (pm)
{
apart *mypart = (apart *)pm->data;
if (mypart->pn == 0)
goto tnext;
char pbuf[PATH_MAX];
sprintf (pbuf, "Partition%d", mypart->pn);
filler (buf, pbuf, NULL, 0);
tnext:
pm = pm->next;
}
return 0;
}
int my_getattr (const char *p, struct stat *stbuf)
{
memset (stbuf, 0, sizeof (struct stat));
vbprintf ("getattr: %s", p);
if (strcmp ("/", p) == 0)
{
stbuf->st_mode = S_IFDIR | 0700;
if (allowall)
stbuf->st_mode |= 07;
}
else if (getpn (p) != -2)
{
stbuf->st_mode = S_IFREG | 0600;
stbuf->st_mode |= 060;
if (allowall)
stbuf->st_mode |= 04;
if (allowallw)
stbuf->st_mode |= 02;
stbuf->st_nlink = 1;
stbuf->st_size = getpart (p)->size;
stbuf->st_uid = myuid;
stbuf->st_gid = mygid;
}
else
return -ENOENT;
return 0;
}
// called when unmounted
void my_destroy (void *u UNUSED)
{
vbprintf ("destroy");
#ifdef OLDAPI
VDIDiskCloseImage (vdidisk);
#else
VDClose (dDisk, 0);
#endif
}
struct fuse_operations oper = {
.readdir = my_readdir,
.getattr = my_getattr,
.access = my_access,
.open = my_open,
.read = my_read,
.write = my_write,
.destroy = my_destroy,
};
void usage (char *p)
{
printf (
"Usage: %s [options] -f image-file mountpoint\n"
"\t-h help\n"
"\t-r readonly\n"
#ifndef OLDAPI
"\t-t specify type (VDI, VMDK, VHD, or raw; default: auto)\n"
#endif
"\t-a allow all users to read disk\n"
"\t-aw allow all users to read and write to disk\n"
"\t-g run in foreground\n"
"\t-v verbose\n"
"\t-d debug\n"
, p);
}
int main (int c, char **v)
{
char *pname = v[0];
if (c < 2)
{
usage (pname);
return 255;
}
#ifndef OLDAPI
char *diskType = "auto";
#endif
char *imagefilename = NULL;
char *mountpoint = NULL;
int debug = 0;
while (*v)
{
if (strcmp (*v, "--help") == 0 || strcmp (*v, "-h") == 0)
{
usage (pname);
return 0;
}
else if (strcmp (*v, "-r") == 0)
readonly = 1;
else if (strcmp (*v, "-g") == 0)
foreground = 1;
else if (strcmp (*v, "-v") == 0)
verbose = 1;
else if (strcmp (*v, "-a") == 0)
allowall = 1;
else if (strcmp (*v, "-aw") == 0)
{
allowall = 1;
allowallw = 1;
}
#ifndef OLDAPI
else if (strcmp (*v, "-t") == 0)
diskType = *++v;
#endif
else if (strcmp (*v, "-f") == 0)
imagefilename = *++v;
else if (strcmp (*v, "-d") == 0)
{
foreground = 1;
debug = 1;
}
else if (*v[0] == '-')
{
errout ("unknown option %s", *v);
return 255;
}
else
mountpoint = *v;
v++;
}
if (!mountpoint)
{
errout ("no mountpoint chosen");
return 1;
}
if (!imagefilename)
{
errout ("no image chosen");
return 1;
}
#ifndef OLDAPI
unsigned int di = 0;
int invalidBackend = 1;
while (di < (sizeof (validBackends) / sizeof (char *)))
{
if (strcmp (validBackends[di], diskType) == 0)
{
invalidBackend = 0;
break;
}
di++;
}
if (invalidBackend)
{
errout ("invalid disk type specified, valid types are VDI, VMDK, VHD, and raw.");
return 1;
}
if (access (imagefilename, F_OK | R_OK | ((!readonly) ? W_OK : 0)) < 0)
{
errout ("cannot access disk: %m", errno);
return 1;
}
if (strcmp ("auto", diskType) == 0)
{
if (detectDiskType (&diskType, imagefilename) < 0)
return 1;
}
#endif
// open disk
#ifdef OLDAPI
vdidisk = VDIDiskCreate ();
int imageopen = VDI_OPEN_FLAGS_NORMAL;
if (readonly)
imageopen = VDI_OPEN_FLAGS_READONLY;
int ret = VDIDiskOpenImage (vdidisk, imagefilename, imageopen);
#else
dInterface.pszInterfaceName = "What's an interface?";
dInterface.enmInterface = VDINTERFACETYPE_FIRST;
VDCreate (&dInterface, &dDisk);
int imageopen = VD_OPEN_FLAGS_NORMAL;
if (readonly)
imageopen = VD_OPEN_FLAGS_READONLY;
int ret = VDOpen (dDisk, diskType, imagefilename, imageopen, &dInterface);
#endif
if (VBOX_FAILURE (ret))
{
errout ("opening vbox image failed, errno %d", ret);
return 1;
}
#ifdef OLDAPI
disksize = VDIDiskGetSize (vdidisk);
#else
disksize = VDGetSize (dDisk, 0);
#endif
apart *rawpart = malloc (sizeof (apart));
rawpart->pn = 0;
rawpart->offset = 0;
rawpart->size = disksize;
partlist = list_add (partlist, rawpart);
if (pns () < 0)
return 1;
myuid = geteuid ();
mygid = getegid ();
struct fuse_args fargs = FUSE_ARGS_INIT (0, NULL);
fuse_opt_add_arg (&fargs, "");
fuse_opt_add_arg (&fargs, mountpoint);
fuse_opt_add_arg (&fargs, "-o");
if (allowall)
fuse_opt_add_arg (&fargs, "allow_other");
else
fuse_opt_add_arg (&fargs, "allow_root");
if (foreground)
fuse_opt_add_arg (&fargs, "-f");
else
verbose = 0;
if (debug)
fuse_opt_add_arg (&fargs, "-d");
#if FUSE_USE_VERSION >= 26
return fuse_main (fargs.argc, fargs.argv, &oper, NULL);
#else
return fuse_main (fargs.argc, fargs.argv, &oper);
#endif
}
Last edited by h2o on 14. Feb 2009, 08:29, edited 1 time in total.
-
- 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:
Thanks, I'll give it a whirl on my AMD64 system tomorrow. //Terry
Read the Forum Posting Guide
Google your Q site:VirtualBox.org or search for the answer before posting.
Google your Q site:VirtualBox.org or search for the answer before posting.
Tried with the fuse version which compiled fine but I can't mount the vdi image.
Code: Select all
root@toshiba:/home/echo6/.VirtualBox/VDI# /home/echo6/vdifuse -v -r -t VDI -f /home/echo6/.VirtualBox/VDI/disk1.vdi /media/test/
Partition 1:
Offset: 32256 bytes
Size: 106896384 bytes
Partition 2:
Offset: 106928640 bytes
Size: 1011709440 bytes
Partition 3:
Offset: 1118638080 bytes
Size: 4244244480 bytes
fuse: mount failed: Invalid argument
Code: Select all
./vdimount -v -f /home/echo6/.VirtualBox/VDI/disk1.vdi partition-number=raw /media/test
ERROR: invalid partition number 0 or port number 0