Index: /trunk/include/VBox/vd-ifs.h
===================================================================
--- /trunk/include/VBox/vd-ifs.h	(revision 48848)
+++ /trunk/include/VBox/vd-ifs.h	(revision 48849)
@@ -621,4 +621,20 @@
  */
 VBOXDDU_DECL(int) VDIfCreateVfsStream(PVDINTERFACEIO pVDIfsIo, void *pvStorage, uint32_t fFlags, PRTVFSIOSTREAM phVfsIos);
+
+/**
+ * Create a VFS file handle around a VD I/O interface.
+ *
+ * The I/O interface will not be closed or free by the VFS file, the caller will
+ * do so after it is done with the VFS file and has released the instances of
+ * the VFS object returned by this API.
+ *
+ * @return  VBox status code.
+ * @param   pVDIfsIo        Pointer to the VD I/O interface.
+ * @param   pvStorage       The storage argument to pass to the interface
+ *                          methods.
+ * @param   fFlags          RTFILE_O_XXX, access mask requied.
+ * @param   phVfsFile       Where to return the VFS file handle on success.
+ */
+VBOXDDU_DECL(int) VDIfCreateVfsFile(PVDINTERFACEIO pVDIfsIo, void *pvStorage, uint32_t fFlags, PRTVFSFILE phVfsFile);
 
 
Index: /trunk/src/VBox/Storage/VDIfVfs.cpp
===================================================================
--- /trunk/src/VBox/Storage/VDIfVfs.cpp	(revision 48848)
+++ /trunk/src/VBox/Storage/VDIfVfs.cpp	(revision 48849)
@@ -37,7 +37,7 @@
 
 /**
- * The internal data of a DVM volume I/O stream.
- */
-typedef struct VDIFVFSIOS
+ * The internal data of an VD I/O to VFS file or I/O stream wrapper.
+ */
+typedef struct VDIFVFSIOSFILE
 {
     /** The VD I/O interface we wrap. */
@@ -45,9 +45,9 @@
     /** User pointer to pass to the VD I/O interface methods. */
     void           *pvStorage;
-    /** The current stream position relative to the VDIfCreateVfsStream call. */
-    uint64_t        offCurPos;
-} VDIFVFSIOS;
+    /** The current stream position. */
+    RTFOFF          offCurPos;
+} VDIFVFSIOSFILE;
 /** Pointer to a the internal data of a DVM volume file. */
-typedef VDIFVFSIOS *PVDIFVFSIOS;
+typedef VDIFVFSIOSFILE *PVDIFVFSIOSFILE;
 
 
@@ -80,6 +80,7 @@
 static DECLCALLBACK(int) vdIfVfsIos_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
 {
-    PVDIFVFSIOS pThis = (PVDIFVFSIOS)pvThis;
+    PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
     Assert(pSgBuf->cSegs == 1); NOREF(fBlocking);
+    Assert(off >= -1);
 
     /*
@@ -91,5 +92,5 @@
     if (RT_SUCCESS(rc))
     {
-        size_t cbAdvance = (pcbRead ? *pcbRead : pSgBuf->paSegs[0].cbSeg);
+        size_t cbAdvance = pcbRead ? *pcbRead : pSgBuf->paSegs[0].cbSeg;
         pThis->offCurPos = off + cbAdvance;
         if (pcbRead && !cbAdvance)
@@ -105,6 +106,7 @@
 static DECLCALLBACK(int) vdIfVfsIos_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
 {
-    PVDIFVFSIOS pThis = (PVDIFVFSIOS)pvThis;
+    PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
     Assert(pSgBuf->cSegs == 1); NOREF(fBlocking);
+    Assert(off >= -1);
 
     /*
@@ -125,5 +127,5 @@
 static DECLCALLBACK(int) vdIfVfsIos_Flush(void *pvThis)
 {
-    PVDIFVFSIOS pThis = (PVDIFVFSIOS)pvThis;
+    PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
     return vdIfIoFileFlushSync(pThis->pVDIfsIo, pThis->pvStorage);
 }
@@ -134,5 +136,5 @@
  */
 static DECLCALLBACK(int) vdIfVfsIos_PollOne(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
-                                              uint32_t *pfRetEvents)
+                                            uint32_t *pfRetEvents)
 {
     NOREF(pvThis);
@@ -154,13 +156,14 @@
 static DECLCALLBACK(int) vdIfVfsIos_Tell(void *pvThis, PRTFOFF poffActual)
 {
-    PVDIFVFSIOS pThis = (PVDIFVFSIOS)pvThis;
+    PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
     *poffActual = pThis->offCurPos;
     return VINF_SUCCESS;
 }
 
-/**
- * Standard file operations.
- */
-DECL_HIDDEN_CONST(const RTVFSIOSTREAMOPS) g_vdIfVfsStdIosOps =
+
+/**
+ * VFS I/O stream operations for a VD file or stream.
+ */
+DECL_HIDDEN_CONST(const RTVFSIOSTREAMOPS) g_vdIfVfsIosOps =
 {
     { /* Obj */
@@ -194,6 +197,6 @@
      */
     RTVFSIOSTREAM hVfsIos;
-    PVDIFVFSIOS pThis;
-    int rc = RTVfsNewIoStream(&g_vdIfVfsStdIosOps, sizeof(*pThis), fFlags,
+    PVDIFVFSIOSFILE pThis;
+    int rc = RTVfsNewIoStream(&g_vdIfVfsIosOps, sizeof(*pThis), fFlags,
                               NIL_RTVFS, NIL_RTVFSLOCK, &hVfsIos, (void **)&pThis);
     if (RT_SUCCESS(rc))
@@ -210,2 +213,165 @@
 }
 
+
+
+/**
+ * @interface_method_impl{RTVFSOBJSETOPS,pfnMode}
+ */
+static DECLCALLBACK(int) vdIfVfsFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask)
+{
+    NOREF(pvThis);
+    NOREF(fMode);
+    NOREF(fMask);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes}
+ */
+static DECLCALLBACK(int) vdIfVfsFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
+                                              PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
+{
+    NOREF(pvThis);
+    NOREF(pAccessTime);
+    NOREF(pModificationTime);
+    NOREF(pChangeTime);
+    NOREF(pBirthTime);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner}
+ */
+static DECLCALLBACK(int) vdIfVfsFile_SetOwner(void *pvThis, RTUID uid, RTGID gid)
+{
+    NOREF(pvThis);
+    NOREF(uid);
+    NOREF(gid);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * @interface_method_impl{RTVFSFILEOPS,pfnSeek}
+ */
+static DECLCALLBACK(int) vdIfVfsFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual)
+{
+    PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
+
+    uint64_t cbFile;
+    int rc = vdIfIoFileGetSize(pThis->pVDIfsIo, pThis->pvStorage, &cbFile);
+    if (RT_FAILURE(rc))
+        return rc;
+    if (cbFile >= (uint64_t)RTFOFF_MAX)
+        cbFile = RTFOFF_MAX;
+
+    /* Recalculate the request to RTFILE_SEEK_BEGIN. */
+    switch (uMethod)
+    {
+        case RTFILE_SEEK_BEGIN:
+            break;
+        case RTFILE_SEEK_CURRENT:
+            offSeek += pThis->offCurPos;
+            break;
+        case RTFILE_SEEK_END:
+            offSeek = cbFile + offSeek;
+            break;
+        default:
+            AssertFailedReturn(VERR_INVALID_PARAMETER);
+    }
+
+    /* Do limit checks. */
+    if (offSeek < 0)
+        offSeek = 0;
+    else if (offSeek > (RTFOFF)cbFile)
+        offSeek = cbFile;
+
+    /* Apply and return. */
+    pThis->offCurPos = offSeek;
+    if (poffActual)
+        *poffActual = offSeek;
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize}
+ */
+static DECLCALLBACK(int) vdIfVfsFile_QuerySize(void *pvThis, uint64_t *pcbFile)
+{
+    PVDIFVFSIOSFILE pThis = (PVDIFVFSIOSFILE)pvThis;
+    return vdIfIoFileGetSize(pThis->pVDIfsIo, pThis->pvStorage, pcbFile);
+}
+
+
+
+/**
+ * VFS file operations for a VD file.
+ */
+DECL_HIDDEN_CONST(const RTVFSFILEOPS) g_vdIfVfsFileOps =
+{
+    { /* I/O stream */
+        { /* Obj */
+            RTVFSOBJOPS_VERSION,
+            RTVFSOBJTYPE_FILE,
+            "VDIfFile",
+            vdIfVfsIos_Close,
+            vdIfVfsIos_QueryInfo,
+            RTVFSOBJOPS_VERSION
+        },
+        RTVFSIOSTREAMOPS_VERSION,
+        RTVFSIOSTREAMOPS_FEAT_NO_SG,
+        vdIfVfsIos_Read,
+        vdIfVfsIos_Write,
+        vdIfVfsIos_Flush,
+        vdIfVfsIos_PollOne,
+        vdIfVfsIos_Tell,
+        NULL /*Skip*/,
+        NULL /*ZeroFill*/,
+        RTVFSIOSTREAMOPS_VERSION,
+    },
+    RTVFSFILEOPS_VERSION,
+    0,
+    { /* ObjSet */
+        RTVFSOBJSETOPS_VERSION,
+        RT_OFFSETOF(RTVFSFILEOPS, Stream.Obj) - RT_OFFSETOF(RTVFSFILEOPS, ObjSet),
+        vdIfVfsFile_SetMode,
+        vdIfVfsFile_SetTimes,
+        vdIfVfsFile_SetOwner,
+        RTVFSOBJSETOPS_VERSION
+    },
+    vdIfVfsFile_Seek,
+    vdIfVfsFile_QuerySize,
+    RTVFSFILEOPS_VERSION,
+};
+
+
+VBOXDDU_DECL(int) VDIfCreateVfsFile(PVDINTERFACEIO pVDIfsIo, void *pvStorage, uint32_t fFlags, PRTVFSFILE phVfsFile)
+{
+    AssertPtrReturn(pVDIfsIo, VERR_INVALID_HANDLE);
+    AssertPtrReturn(phVfsFile, VERR_INVALID_POINTER);
+
+    /*
+     * Create the volume file.
+     */
+    RTVFSFILE hVfsFile;
+    PVDIFVFSIOSFILE pThis;
+    int rc = RTVfsNewFile(&g_vdIfVfsFileOps, sizeof(*pThis), fFlags,
+                          NIL_RTVFS, NIL_RTVFSLOCK, &hVfsFile, (void **)&pThis);
+    if (RT_SUCCESS(rc))
+    {
+        pThis->pVDIfsIo  = pVDIfsIo;
+        pThis->pvStorage = pvStorage;
+        pThis->offCurPos = 0;
+
+        *phVfsFile = hVfsFile;
+        return VINF_SUCCESS;
+    }
+
+    return rc;
+}
+
+
