Virtual Box Disk Image Wrapper for sfdisk
The following script allows viewing properties of VirtualBox disks to mount them directly. Simple (and incomplete) syscalls interposition for accessing fixed-size Sun xVM VirtualBox Virtual Disk Images (.vdi files), especially using sfdisk.
Compile:
gcc -fPIC -c -o vdiwrap.o vdiwrap.c &&
gcc -nostdlib -shared -ldl -o vdiwrap.so vdiwrap.o
Use:
LD_PRELOAD="./vdiwrap.so" sfdisk -qluS image.vdi
/*
* Copyright (C) 2009 Przemyslaw Pawelczyk <przemoc@gmail.com>
* GNU General Public License v2, v3
*/
#define _GNU_SOURCE
#define _LARGEFILE64_SOURCE
#include <dlfcn.h>
#include <stdarg.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define LOAD(name) orig_##name = dlsym(RTLD_NEXT, #name)
#if __LP64__
# define N(name) name
# define O(name) orig_##name
# define OFF_T off_t
# define STAT stat
#else
# define N(name) name ## 64
# define O(name) orig_##name ## 64
# define OFF_T off64_t
# define STAT stat64
#endif
#define OPEN_SIGNATURE const char *__file, int __oflag, ...
#define LSEEK_SIGNATURE int __fd, OFF_T __offset, int __whence
#define FXSTAT_SIGNATURE int __ver, int __fd, struct STAT *__stat_buf
static int vdi_fd = -1;
static int vdi_type = 0;
static int vdi_offset = 0;
static int (*O(open))(OPEN_SIGNATURE);
static OFF_T (*O(lseek))(LSEEK_SIGNATURE);
static int (*O(__fxstat))(FXSTAT_SIGNATURE);
/* Functions' prototypes */
int N(open)(OPEN_SIGNATURE);
OFF_T N(lseek)(LSEEK_SIGNATURE);
int N(__fxstat)(FXSTAT_SIGNATURE);
/* Initialization */
void _init()
{
LOAD(open);
LOAD(lseek);
LOAD(__fxstat);
}
/* Functions' bodies */
int N(open)(OPEN_SIGNATURE)
{
int result;
int namelen;
unsigned mode;
va_list ap;
if (__oflag & O_CREAT) {
va_start(ap, __oflag);
mode = va_arg(ap, unsigned);
result = O(open)(__file, __oflag, mode);
va_end(ap);
return result;
}
result = O(open)(__file, __oflag);
if (result > 0 && (namelen = strlen(__file)) && !strncasecmp(&__file[namelen - 4], ".vdi", 4)) {
O(lseek)(result, 76, SEEK_SET);
read(result, &vdi_type, 4);
if (vdi_type == 2) {
O(lseek)(result, 344, SEEK_SET);
read(result, &vdi_offset, 4);
O(lseek)(result, vdi_offset, SEEK_SET);
vdi_fd = result;
dprintf(STDERR_FILENO, "--- VDI data offset == %d bytes ---\n", vdi_offset);
} else
vdi_fd = -1;
}
return result;
}
OFF_T N(lseek)(LSEEK_SIGNATURE)
{
OFF_T result;
if (__fd == vdi_fd && __whence == SEEK_SET)
__offset += vdi_offset;
result = O(lseek)(__fd, __offset, __whence);
if (__fd == vdi_fd && result > 0)
result -= vdi_offset;
return result;
}
int N(__fxstat)(FXSTAT_SIGNATURE)
{
int result = O(__fxstat)(__ver, __fd, __stat_buf);
if (__fd == vdi_fd && result == 0)
__stat_buf->st_size -= vdi_offset;
return result;
}
@Tools