728
* VD async I/O interface open callback.
730
static int vdAsyncIOOpen(void *pvUser, const char *pszLocation, unsigned uOpenFlags,
731
PFNVDCOMPLETED pfnCompleted, void **ppStorage)
733
PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)RTMemAllocZ(sizeof(VDIASYNCIOSTORAGE));
736
return VERR_NO_MEMORY;
738
pStorage->pfnCompleted = pfnCompleted;
742
if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY)
743
fOpen |= RTFILE_O_READ | RTFILE_O_DENY_NONE;
745
fOpen |= RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
747
if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE)
748
fOpen |= RTFILE_O_CREATE;
750
fOpen |= RTFILE_O_OPEN;
753
int rc = RTFileOpen(&pStorage->File, pszLocation, fOpen);
756
*ppStorage = pStorage;
765
* VD async I/O interface close callback.
767
static int vdAsyncIOClose(void *pvUser, void *pvStorage)
769
PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
771
RTFileClose(pStorage->File);
777
* VD async I/O interface callback for retrieving the file size.
779
static int vdAsyncIOGetSize(void *pvUser, void *pvStorage, uint64_t *pcbSize)
781
PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
783
return RTFileGetSize(pStorage->File, pcbSize);
787
* VD async I/O interface callback for setting the file size.
789
static int vdAsyncIOSetSize(void *pvUser, void *pvStorage, uint64_t cbSize)
791
PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
793
return RTFileSetSize(pStorage->File, cbSize);
797
* VD async I/O interface callback for a synchronous write to the file.
799
static int vdAsyncIOWriteSync(void *pvUser, void *pvStorage, uint64_t uOffset,
800
size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
802
PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
804
return RTFileWriteAt(pStorage->File, uOffset, pvBuf, cbWrite, pcbWritten);
808
* VD async I/O interface callback for a synchronous read from the file.
810
static int vdAsyncIOReadSync(void *pvUser, void *pvStorage, uint64_t uOffset,
811
size_t cbRead, void *pvBuf, size_t *pcbRead)
813
PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
815
return RTFileReadAt(pStorage->File, uOffset, pvBuf, cbRead, pcbRead);
819
* VD async I/O interface callback for a synchronous flush of the file data.
821
static int vdAsyncIOFlushSync(void *pvUser, void *pvStorage)
823
PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
825
return RTFileFlush(pStorage->File);
829
* VD async I/O interface callback for a asynchronous read from the file.
831
static int vdAsyncIOReadAsync(void *pvUser, void *pStorage, uint64_t uOffset,
832
PCPDMDATASEG paSegments, size_t cSegments,
833
size_t cbRead, void *pvCompletion,
836
return VERR_NOT_IMPLEMENTED;
840
* VD async I/O interface callback for a asynchronous write to the file.
842
static int vdAsyncIOWriteAsync(void *pvUser, void *pStorage, uint64_t uOffset,
843
PCPDMDATASEG paSegments, size_t cSegments,
844
size_t cbWrite, void *pvCompletion,
847
return VERR_NOT_IMPLEMENTED;
851
* VD async I/O interface callback for a asynchronous flush of the file data.
853
static int vdAsyncIOFlushAsync(void *pvUser, void *pStorage,
854
void *pvCompletion, void **ppTask)
856
return VERR_NOT_IMPLEMENTED;
860
* internal: send output to the log (unconditionally).
862
int vdLogMessage(void *pvUser, const char *pszFormat, ...)
866
va_start(args, pszFormat);
867
RTLogPrintf(pszFormat, args);
708
874
* Initializes HDD backends.
710
876
* @returns VBox status code.
877
1043
pDisk->pInterfaceError = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_ERROR);
878
1044
if (pDisk->pInterfaceError)
879
1045
pDisk->pInterfaceErrorCallbacks = VDGetInterfaceError(pDisk->pInterfaceError);
1047
/* Use the fallback async I/O interface if the caller doesn't provide one. */
1048
PVDINTERFACE pVDIfAsyncIO = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
1051
pDisk->VDIAsyncIOCallbacks.cbSize = sizeof(VDINTERFACEASYNCIO);
1052
pDisk->VDIAsyncIOCallbacks.enmInterface = VDINTERFACETYPE_ASYNCIO;
1053
pDisk->VDIAsyncIOCallbacks.pfnOpen = vdAsyncIOOpen;
1054
pDisk->VDIAsyncIOCallbacks.pfnClose = vdAsyncIOClose;
1055
pDisk->VDIAsyncIOCallbacks.pfnGetSize = vdAsyncIOGetSize;
1056
pDisk->VDIAsyncIOCallbacks.pfnSetSize = vdAsyncIOSetSize;
1057
pDisk->VDIAsyncIOCallbacks.pfnReadSync = vdAsyncIOReadSync;
1058
pDisk->VDIAsyncIOCallbacks.pfnWriteSync = vdAsyncIOWriteSync;
1059
pDisk->VDIAsyncIOCallbacks.pfnFlushSync = vdAsyncIOFlushSync;
1060
pDisk->VDIAsyncIOCallbacks.pfnReadAsync = vdAsyncIOReadAsync;
1061
pDisk->VDIAsyncIOCallbacks.pfnWriteAsync = vdAsyncIOWriteAsync;
1062
pDisk->VDIAsyncIOCallbacks.pfnFlushAsync = vdAsyncIOFlushAsync;
1063
rc = VDInterfaceAdd(&pDisk->VDIAsyncIO, "VD_AsyncIO", VDINTERFACETYPE_ASYNCIO,
1064
&pDisk->VDIAsyncIOCallbacks, pDisk, &pDisk->pVDIfsDisk);
880
1068
*ppDisk = pDisk;
917
1105
* VINF_SUCCESS if a plugin was found.
918
1106
* ppszFormat contains the string which can be used as backend name.
919
1107
* VERR_NOT_SUPPORTED if no backend was found.
1108
* @param pVDIfsDisk Pointer to the per-disk VD interface list.
920
1109
* @param pszFilename Name of the image file for which the backend is queried.
921
1110
* @param ppszFormat Receives pointer of the UTF-8 string which contains the format name.
922
1111
* The returned pointer must be freed using RTStrFree().
924
VBOXDDU_DECL(int) VDGetFormat(const char *pszFilename, char **ppszFormat)
1113
VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, const char *pszFilename, char **ppszFormat)
926
1115
int rc = VERR_NOT_SUPPORTED;
1116
PVDINTERFACE pVDIfAsyncIO;
1117
VDINTERFACEASYNCIO VDIAsyncIOCallbacks;
1118
VDINTERFACE VDIAsyncIO;
928
1120
LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
929
1121
/* Check arguments. */
937
1129
if (!g_apBackends)
1132
/* Use the fallback async I/O interface if the caller doesn't provide one. */
1133
pVDIfAsyncIO = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
1136
VDIAsyncIOCallbacks.cbSize = sizeof(VDINTERFACEASYNCIO);
1137
VDIAsyncIOCallbacks.enmInterface = VDINTERFACETYPE_ASYNCIO;
1138
VDIAsyncIOCallbacks.pfnOpen = vdAsyncIOOpen;
1139
VDIAsyncIOCallbacks.pfnClose = vdAsyncIOClose;
1140
VDIAsyncIOCallbacks.pfnGetSize = vdAsyncIOGetSize;
1141
VDIAsyncIOCallbacks.pfnSetSize = vdAsyncIOSetSize;
1142
VDIAsyncIOCallbacks.pfnReadSync = vdAsyncIOReadSync;
1143
VDIAsyncIOCallbacks.pfnWriteSync = vdAsyncIOWriteSync;
1144
VDIAsyncIOCallbacks.pfnFlushSync = vdAsyncIOFlushSync;
1145
VDIAsyncIOCallbacks.pfnReadAsync = vdAsyncIOReadAsync;
1146
VDIAsyncIOCallbacks.pfnWriteAsync = vdAsyncIOWriteAsync;
1147
VDIAsyncIOCallbacks.pfnFlushAsync = vdAsyncIOFlushAsync;
1148
rc = VDInterfaceAdd(&VDIAsyncIO, "VD_AsyncIO", VDINTERFACETYPE_ASYNCIO,
1149
&VDIAsyncIOCallbacks, NULL, &pVDIfsDisk);
940
1153
/* Find the backend supporting this file format. */
941
1154
for (unsigned i = 0; i < g_cBackends; i++)
943
1156
if (g_apBackends[i]->pfnCheckIfValid)
945
rc = g_apBackends[i]->pfnCheckIfValid(pszFilename);
1158
rc = g_apBackends[i]->pfnCheckIfValid(pszFilename, pVDIfsDisk);
946
1159
if ( RT_SUCCESS(rc)
947
1160
/* The correct backend has been found, but there is a small
948
1161
* incompatibility so that the file cannot be used. Stop here
2029
2243
if (!RTStrICmp(pszBackend, "RAW"))
2030
2244
uImageFlags |= VD_IMAGE_FLAGS_FIXED;
2246
/* Fix broken PCHS geometry. Can happen for two reasons: either
2247
* the backend mixes up PCHS and LCHS, or the application used
2248
* to create the source image has put garbage in it. */
2249
/** @todo double-check if the VHD backend correctly handles
2250
* PCHS and LCHS geometry. also reconsider our current paranoia
2251
* level when it comes to geometry settings here and in the
2253
if (PCHSGeometryFrom.cHeads > 16 || PCHSGeometryFrom.cSectors > 63)
2255
Assert(RT_MIN(cbSize / 512 / 16 / 63, 16383) - (uint32_t)RT_MIN(cbSize / 512 / 16 / 63, 16383));
2256
PCHSGeometryFrom.cCylinders = (uint32_t)RT_MIN(cbSize / 512 / 16 / 63, 16383);
2257
PCHSGeometryFrom.cHeads = 16;
2258
PCHSGeometryFrom.cSectors = 63;
2032
2261
rc = VDCreateBase(pDiskTo, pszBackend, pszFilename, cbSize,
2033
2262
uImageFlags, szComment,
2034
2263
&PCHSGeometryFrom, &LCHSGeometryFrom,
3472
3704
AssertPtrBreak(pDisk);
3473
3705
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
3475
RTLogPrintf("--- Dumping VD Disk, Images=%u\n", pDisk->cImages);
3707
int (*pfnMessage)(void *, const char *, ...) = NULL;
3708
void *pvUser = pDisk->pInterfaceError->pvUser;
3710
if (pDisk->pInterfaceErrorCallbacks && VALID_PTR(pDisk->pInterfaceErrorCallbacks->pfnMessage))
3711
pfnMessage = pDisk->pInterfaceErrorCallbacks->pfnMessage;
3714
pDisk->pInterfaceErrorCallbacks->pfnMessage = vdLogMessage;
3715
pfnMessage = vdLogMessage;
3718
pfnMessage(pvUser, "--- Dumping VD Disk, Images=%u\n", pDisk->cImages);
3476
3719
for (PVDIMAGE pImage = pDisk->pBase; pImage; pImage = pImage->pNext)
3478
RTLogPrintf("Dumping VD image \"%s\" (Backend=%s)\n",
3479
pImage->pszFilename, pImage->Backend->pszBackendName);
3721
pfnMessage(pvUser, "Dumping VD image \"%s\" (Backend=%s)\n",
3722
pImage->pszFilename, pImage->Backend->pszBackendName);
3480
3723
pImage->Backend->pfnDump(pImage->pvBackendData);