VBoxHDD.cpp revision caf54c14752060b187e3fca12a6f71f4b13126b8
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * VBoxHDD - VBox HDD Container implementation.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Copyright (C) 2006-2008 Sun Microsystems, Inc.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * available from http://www.virtualbox.org. This file is free software;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * you can redistribute it and/or modify it under the terms of the GNU
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * General Public License (GPL) as published by the Free Software
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * additional information or have any questions.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync/*******************************************************************************
e99772f9bf09219c532812c859fbeea513c67e65vboxsync* Header Files *
62b88df0b51ed81807d485b371b90aff7dfd7beevboxsync*******************************************************************************/
e99772f9bf09219c532812c859fbeea513c67e65vboxsync/** Buffer size used for merging images. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * VBox HDD Container image descriptor.
e99772f9bf09219c532812c859fbeea513c67e65vboxsynctypedef struct VDIMAGE
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Link to parent image descriptor, if any. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Link to child image descriptor, if any. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Container base filename. (UTF-8) */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Data managed by the backend which keeps the actual info. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Cached sanitized image flags. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Image open flags (only those handled generically in this code and which
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * the backends will never ever see). */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Function pointers for the various backend methods. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Pointer to list of VD interfaces, per-image. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * uModified bit flags.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync#define VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE RT_BIT(2)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * VBox HDD Container main structure, private part.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Structure signature (VBOXHDDDISK_SIGNATURE). */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Number of opened images. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Base image. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Last opened image in the chain.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * The same as pBase if only one image is used. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Flags representing the modification state. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Cached size of this disk. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Cached PCHS geometry for this disk. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Cached LCHS geometry for this disk. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Pointer to list of VD interfaces, per-disk. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Pointer to the common interface structure for error reporting. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Pointer to the error interface we use if available. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * VBox parent read descriptor, used internally for compaction.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Pointer to disk descriptor. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** Pointer to image descriptor. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic unsigned g_cBackends = 0;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: add several backends.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic int vdAddBackends(PVBOXHDDBACKEND *ppBackends, unsigned cBackends)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync PVBOXHDDBACKEND *pTmp = (PVBOXHDDBACKEND*)RTMemRealloc(g_apBackends,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync (g_cBackends + cBackends) * sizeof(PVBOXHDDBACKEND));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync memcpy(&g_apBackends[g_cBackends], ppBackends, cBackends * sizeof(PVBOXHDDBACKEND));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: add single backend.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncDECLINLINE(int) vdAddBackend(PVBOXHDDBACKEND pBackend)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: issue error message.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic int vdError(PVBOXHDD pDisk, int rc, RT_SRC_POS_DECL,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync const char *pszFormat, ...)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pDisk->pInterfaceErrorCallbacks->pfnError(pDisk->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS, pszFormat, va);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: find image format backend.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic int vdFindBackend(const char *pszBackend, PCVBOXHDDBACKEND *ppBackend)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync for (unsigned i = 0; i < g_cBackends; i++)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync if (!RTStrICmp(pszBackend, g_apBackends[i]->pszBackendName))
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: add image structure to the end of images list.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic void vdAddImageToList(PVBOXHDD pDisk, PVDIMAGE pImage)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: remove image structure from the images list.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic void vdRemoveImageFromList(PVBOXHDD pDisk, PVDIMAGE pImage)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: find image by index into the images list.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic PVDIMAGE vdGetImageByNumber(PVBOXHDD pDisk, unsigned nImage)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: read the specified amount of data in whatever blocks the backend
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * will give us.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic int vdReadHelper(PVBOXHDD pDisk, PVDIMAGE pImage, uint64_t uOffset,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Loop until all read. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Search for image with allocated block. Do not attempt to read more
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * than the previous reads marked as valid. Otherwise this would return
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * stale data when different block sizes are used for the images. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = pCurrImage->Backend->pfnRead(pCurrImage->pvBackendData,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* No image in the chain contains the data for the block. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: parent image read wrapper for compacting.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic int vdParentRead(void *pvUser, uint64_t uOffset, void *pvBuf,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync PVDPARENTSTATEDESC pParentState = (PVDPARENTSTATEDESC)pvUser;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync return vdReadHelper(pParentState->pDisk, pParentState->pImage, uOffset,
62b88df0b51ed81807d485b371b90aff7dfd7beevboxsync * internal: mark the disk as not modified.
62b88df0b51ed81807d485b371b90aff7dfd7beevboxsync /* generate new last-modified uuid */
62b88df0b51ed81807d485b371b90aff7dfd7beevboxsync if (!(pDisk->uModified & VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE))
62b88df0b51ed81807d485b371b90aff7dfd7beevboxsync pDisk->pLast->Backend->pfnSetModificationUuid(pDisk->pLast->pvBackendData,
62b88df0b51ed81807d485b371b90aff7dfd7beevboxsync * internal: mark the disk as modified.
62b88df0b51ed81807d485b371b90aff7dfd7beevboxsync /* First modify, so create a UUID and ensure it's written to disk. */
62b88df0b51ed81807d485b371b90aff7dfd7beevboxsync if (!(pDisk->uModified | VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE))
62b88df0b51ed81807d485b371b90aff7dfd7beevboxsync pDisk->pLast->Backend->pfnFlush(pDisk->pLast->pvBackendData);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: write a complete block (only used for diff images), taking the
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * remaining data from parent images. This implementation does not optimize
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * anything (except that it tries to read only that portions from parent
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * images that are really needed).
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic int vdWriteHelperStandard(PVBOXHDD pDisk, PVDIMAGE pImage,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Read the data that goes before the write to fill the block. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = vdReadHelper(pDisk, pImage, uOffset - cbPreRead, pvTmp,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Copy the data to the right place in the buffer. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync memcpy((char *)pvTmp + cbPreRead, pvBuf, cbThisWrite);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Read the data that goes after the write to fill the block. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* If we have data to be written, use that instead of reading
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * data from the image. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync cbWriteCopy = RT_MIN(cbWrite - cbThisWrite, cbPostRead);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Figure out how much we cannnot read from the image, because
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * the last block to write might exceed the nominal size of the
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * image for technical reasons. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync if (uOffset + cbThisWrite + cbPostRead > pDisk->cbSize)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync cbFill = uOffset + cbThisWrite + cbPostRead - pDisk->cbSize;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* The rest must be read from the image. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync size_t cbReadImage = cbPostRead - cbWriteCopy - cbFill;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Now assemble the remaining data. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync (char *)pvTmp + cbPreRead + cbThisWrite + cbWriteCopy,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Zero out the remainder of this block. Will never be visible, as this
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * is beyond the limit of the image. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync memset((char *)pvTmp + cbPreRead + cbThisWrite + cbWriteCopy + cbReadImage,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Write the full block to the virtual disk. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = pImage->Backend->pfnWrite(pImage->pvBackendData,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: write a complete block (only used for diff images), taking the
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * remaining data from parent images. This implementation optimizes out writes
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * that do not change the data relative to the state as of the parent images.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * All backends which support differential/growing images support this.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic int vdWriteHelperOptimized(PVBOXHDD pDisk, PVDIMAGE pImage,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Figure out how much we cannnot read from the image, because
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * the last block to write might exceed the nominal size of the
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * image for technical reasons. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync if (uOffset + cbThisWrite + cbPostRead > pDisk->cbSize)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync cbFill = uOffset + cbThisWrite + cbPostRead - pDisk->cbSize;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* If we have data to be written, use that instead of reading
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * data from the image. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync cbWriteCopy = RT_MIN(cbWrite - cbThisWrite, cbPostRead);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* The rest must be read from the image. */
b20cc298c1a3191a4e6ce780c19313117902675dvboxsync /* Read the entire data of the block so that we can compare whether it will
b20cc298c1a3191a4e6ce780c19313117902675dvboxsync * be modified by the write or not. */
b20cc298c1a3191a4e6ce780c19313117902675dvboxsync rc = vdReadHelper(pDisk, pImage, uOffset - cbPreRead, pvTmp,
b20cc298c1a3191a4e6ce780c19313117902675dvboxsync /* Check if the write would modify anything in this block. */
b20cc298c1a3191a4e6ce780c19313117902675dvboxsync if ( !memcmp((char *)pvTmp + cbPreRead, pvBuf, cbThisWrite)
b20cc298c1a3191a4e6ce780c19313117902675dvboxsync && (!cbWriteCopy || !memcmp((char *)pvTmp + cbPreRead + cbThisWrite,
b20cc298c1a3191a4e6ce780c19313117902675dvboxsync /* Block is completely unchanged, so no need to write anything. */
b20cc298c1a3191a4e6ce780c19313117902675dvboxsync /* Copy the data to the right place in the buffer. */
b20cc298c1a3191a4e6ce780c19313117902675dvboxsync memcpy((char *)pvTmp + cbPreRead, pvBuf, cbThisWrite);
b20cc298c1a3191a4e6ce780c19313117902675dvboxsync /* Handle the data that goes after the write to fill the block. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Now assemble the remaining data. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Zero out the remainder of this block. Will never be visible, as this
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * is beyond the limit of the image. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync memset((char *)pvTmp + cbPreRead + cbThisWrite + cbWriteCopy + cbReadImage,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Write the full block to the virtual disk. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = pImage->Backend->pfnWrite(pImage->pvBackendData,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: write buffer to the image, taking care of block boundaries and
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * write optimizations.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncstatic int vdWriteHelper(PVBOXHDD pDisk, PVDIMAGE pImage, uint64_t uOffset,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Loop until all written. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Try to write the possibly partial block to the last opened image.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * This works when the block is already allocated in this image or
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * if it is a full-block write (and allocation isn't suppressed below).
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * For image formats which don't support zero blocks, it's beneficial
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * to avoid unnecessarily allocating unchanged blocks. This prevents
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * unwanted expanding of images. VMDK is an example. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync fWrite = (pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = pImage->Backend->pfnWrite(pImage->pvBackendData, uOffset, pvBuf,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync void *pvTmp = RTMemTmpAlloc(cbPreRead + cbThisWrite + cbPostRead);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync AssertBreakStmt(VALID_PTR(pvTmp), rc = VERR_NO_MEMORY);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME))
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Optimized write, suppress writing to a so far unallocated
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * block if the data is in fact not changed. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = vdWriteHelperOptimized(pDisk, pImage, uOffset, cbWrite,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Normal write, not optimized in any way. The block will
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * be written no matter what. This will usually (unless the
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * backend has some further optimization enabled) cause the
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * block to be allocated. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = vdWriteHelperStandard(pDisk, pImage, uOffset, cbWrite,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: scans plugin directory and loads the backends have been found.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Enumerate plugin backends. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* To get all entries with VBoxHDD as prefix. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = RTStrAPrintf(&pszPluginFilter, "%s/%s*", szPath,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* The plugins are in the same directory as the other shared libs. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = RTDirOpenFiltered(&pPluginDir, pszPluginFilter, RTDIRFILTER_WINNT);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* On Windows the above immediately signals that there are no
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * files matching, while on other platforms enumerating the
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * files below fails. Either way: no plugins. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(sizeof(RTDIRENTRYEX));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync while ((rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING)) != VERR_NO_MORE_FILES)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* allocate new buffer. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pPluginDirEntry = (PRTDIRENTRYEX)RTMemAllocZ(cbPluginDirEntry);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Retry. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = RTDirReadEx(pPluginDir, pPluginDirEntry, &cbPluginDirEntry, RTFSOBJATTRADD_NOTHING);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* We got the new entry. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync if (!RTFS_IS_FILE(pPluginDirEntry->Info.Attr.fMode))
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Prepend the path to the libraries. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = RTStrAPrintf(&pszPluginPath, "%s/%s", szPath, pPluginDirEntry->szName);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = SUPR3HardenedLdrLoad(pszPluginPath, &hPlugin);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = RTLdrGetSymbol(hPlugin, VBOX_HDDFORMAT_LOAD_NAME, (void**)&pfnHDDFormatLoad);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync LogFunc(("error resolving the entry point %s in plugin %s, rc=%Rrc, pfnHDDFormat=%#p\n", VBOX_HDDFORMAT_LOAD_NAME, pPluginDirEntry->szName, rc, pfnHDDFormatLoad));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Get the function table. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync if (RT_SUCCESS(rc) && pBackend->cbSize == sizeof(VBOXHDDBACKEND))
e99772f9bf09219c532812c859fbeea513c67e65vboxsync LogFunc(("ignored plugin '%s': pBackend->cbSize=%d rc=%Rrc\n", pszPluginPath, pBackend->cbSize, rc));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync LogFunc(("ignored plugin '%s': rc=%Rrc\n", pszPluginPath, rc));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * internal: send output to the log (unconditionally).
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncint vdLogMessage(void *pvUser, const char *pszFormat, ...)
768888227f95954ce8676ae279645fae10e24ba2vboxsync * Initializes HDD backends.
768888227f95954ce8676ae279645fae10e24ba2vboxsync * @returns VBox status code.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync int rc = vdAddBackends(aStaticBackends, RT_ELEMENTS(aStaticBackends));
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync * Destroys loaded HDD backends.
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync * @returns VBox status code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for (unsigned i = 0; i < cBackends; i++)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Lists all HDD backends and their capabilities in a caller-provided buffer.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @todo this code contains memory leaks, inconsistent (and probably buggy)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * allocation, and it lacks documentation what the caller needs to free.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns VBox status code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * VERR_BUFFER_OVERFLOW if not enough space is passed.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param cEntriesAlloc Number of list entries available.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pEntries Pointer to array for the entries.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pcEntriesUsed Number of entries returned.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncVBOXDDU_DECL(int) VDBackendInfo(unsigned cEntriesAlloc, PVDBACKENDINFO pEntries,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync unsigned cEntries = 0;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync LogFlowFunc(("cEntriesAlloc=%u pEntries=%#p pcEntriesUsed=%#p\n", cEntriesAlloc, pEntries, pcEntriesUsed));
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Check arguments. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for (unsigned i = 0; i < g_cBackends; i++)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync pEntries[i].pszBackend = g_apBackends[i]->pszBackendName;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pEntries[i].uBackendCaps = g_apBackends[i]->uBackendCaps;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pEntries[i].papszFileExtensions = g_apBackends[i]->papszFileExtensions;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pEntries[i].paConfigInfo = g_apBackends[i]->paConfigInfo;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pEntries[i].pfnComposeLocation = g_apBackends[i]->pfnComposeLocation;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pEntries[i].pfnComposeName = g_apBackends[i]->pfnComposeName;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync LogFlowFunc(("returns %Rrc *pcEntriesUsed=%u\n", rc, cEntries));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Lists the capablities of a backend indentified by its name.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Free all returned names with RTStrFree() when you no longer need them.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @returns VBox status code.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pszBackend The backend name.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pEntries Pointer to an entry.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncVBOXDDU_DECL(int) VDBackendInfoOne(const char *pszBackend, PVDBACKENDINFO pEntry)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync LogFlowFunc(("pszBackend=%#p pEntry=%#p\n", pszBackend, pEntry));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Check arguments. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Go through loaded backends. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync for (unsigned i = 0; i < g_cBackends; i++)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync if (!RTStrICmp(pszBackend, g_apBackends[i]->pszBackendName))
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pEntry->pszBackend = g_apBackends[i]->pszBackendName;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pEntry->uBackendCaps = g_apBackends[i]->uBackendCaps;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pEntry->papszFileExtensions = g_apBackends[i]->papszFileExtensions;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pEntry->paConfigInfo = g_apBackends[i]->paConfigInfo;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Allocates and initializes an empty HDD container.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * No image files are opened.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @returns VBox status code.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pVDIfsDisk Pointer to the per-disk VD interface list.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param ppDisk Where to store the reference to HDD container.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncVBOXDDU_DECL(int) VDCreate(PVDINTERFACE pVDIfsDisk, PVBOXHDD *ppDisk)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Check arguments. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pDisk->pInterfaceError = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_ERROR);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pDisk->pInterfaceErrorCallbacks = VDGetInterfaceError(pDisk->pInterfaceError);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync } while (0);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync LogFlowFunc(("returns %Rrc (pDisk=%#p)\n", rc, pDisk));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Destroys HDD container.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * If container has opened image files they will be closed.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pDisk Pointer to HDD container.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* sanity check */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync } while (0);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Try to get the backend name which can use this image.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @returns VBox status code.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * VINF_SUCCESS if a plugin was found.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * ppszFormat contains the string which can be used as backend name.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * VERR_NOT_SUPPORTED if no backend was found.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pszFilename Name of the image file for which the backend is queried.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param ppszFormat Receives pointer of the UTF-8 string which contains the format name.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * The returned pointer must be freed using RTStrFree().
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncVBOXDDU_DECL(int) VDGetFormat(const char *pszFilename, char **ppszFormat)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Check arguments. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync AssertMsgReturn(VALID_PTR(pszFilename) && *pszFilename,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename),
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Find the backend supporting this file format. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync for (unsigned i = 0; i < g_cBackends; i++)
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = g_apBackends[i]->pfnCheckIfValid(pszFilename);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* The correct backend has been found, but there is a small
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * incompatibility so that the file cannot be used. Stop here
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * and signal success - the actual open will of course fail,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * but that will create a really sensible error message. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Copy the name into the new string. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync char *pszFormat = RTStrDup(g_apBackends[i]->pszBackendName);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync LogFlowFunc(("returns %Rrc *ppszFormat=\"%s\"\n", rc, *ppszFormat));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Opens an image file.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * The first opened image file in HDD container must have a base image type,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * others (next opened images) must be a differencing or undo images.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Linkage is checked for differencing image to be in consistence with the previously opened image.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * When another differencing image is opened and the last image was opened in read/write access
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * mode, then the last image is reopened in read-only with deny write sharing mode. This allows
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * other processes to use images in read-only mode too.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Note that the image is opened in read-only mode if a read/write open is not possible.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Use VDIsReadOnly to check open mode.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @returns VBox status code.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pDisk Pointer to HDD container.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pszBackend Name of the image file backend to use.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pszFilename Name of the image file to open.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pVDIfsImage Pointer to the per-image VD interface list.
e99772f9bf09219c532812c859fbeea513c67e65vboxsyncVBOXDDU_DECL(int) VDOpen(PVBOXHDD pDisk, const char *pszBackend,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync LogFlowFunc(("pDisk=%#p pszBackend=\"%s\" pszFilename=\"%s\" uOpenFlags=%#x, pVDIfsImage=%#p\n",
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pDisk, pszBackend, pszFilename, uOpenFlags, pVDIfsImage));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* sanity check */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Check arguments. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync AssertMsgBreakStmt(VALID_PTR(pszBackend) && *pszBackend,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync ("pszBackend=%#p \"%s\"\n", pszBackend, pszBackend),
e99772f9bf09219c532812c859fbeea513c67e65vboxsync AssertMsgBreakStmt(VALID_PTR(pszFilename) && *pszFilename,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename),
e99772f9bf09219c532812c859fbeea513c67e65vboxsync AssertMsgBreakStmt((uOpenFlags & ~VD_OPEN_FLAGS_MASK) == 0,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Set up image descriptor. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc = vdError(pDisk, VERR_INVALID_PARAMETER, RT_SRC_POS,
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pImage->uOpenFlags = uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME;
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* If the open in read-write mode failed, retry in read-only mode. */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync N_("VD: error opening image file '%s'"), pszFilename);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync uImageFlags = pImage->Backend->pfnGetImageFlags(pImage->pvBackendData);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Check image type. As the image itself has only partial knowledge
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * whether it's a base image or not, this info is derived here. The
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * base image can be fixed or normal, all others must be normal or
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * diff images. Some image formats don't distinguish between normal
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * and diff images, so this must be corrected here. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Force sane optimization settings. It's not worth avoiding writes
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * to fixed size images. The overhead would have almost no payback. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /** @todo optionally check UUIDs */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Cache disk information. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->pvBackendData);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Cache PCHS geometry. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pvBackendData,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* Make sure the PCHS geometry is properly clipped. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync pDisk->PCHSGeometry.cCylinders = RT_MIN(pDisk->PCHSGeometry.cCylinders, 16383);
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync pDisk->PCHSGeometry.cHeads = RT_MIN(pDisk->PCHSGeometry.cHeads, 16);
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync pDisk->PCHSGeometry.cSectors = RT_MIN(pDisk->PCHSGeometry.cSectors, 63);
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* Cache LCHS geometry. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pvBackendData,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* Make sure the LCHS geometry is properly clipped. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync pDisk->LCHSGeometry.cHeads = RT_MIN(pDisk->LCHSGeometry.cHeads, 255);
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync pDisk->LCHSGeometry.cSectors = RT_MIN(pDisk->LCHSGeometry.cSectors, 63);
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* Switch previous image to read-only mode. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync uOpenFlagsPrevImg = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pvBackendData);
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync rc = pDisk->pLast->Backend->pfnSetOpenFlags(pDisk->pLast->pvBackendData, uOpenFlagsPrevImg);
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* Image successfully opened, make it the last image. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync /* Error detected, but image opened. Close image. */
e99772f9bf09219c532812c859fbeea513c67e65vboxsync rc2 = pImage->Backend->pfnClose(pImage->pvBackendData, false);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync } while (0);
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * Creates and opens a new base image file.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @returns VBox status code.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pDisk Pointer to HDD container.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pszBackend Name of the image file backend to use.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param pszFilename Name of the image file to create.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param cbSize Image size in bytes.
e99772f9bf09219c532812c859fbeea513c67e65vboxsync * @param uImageFlags Flags specifying special image features.
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync * @param pszComment Pointer to image comment. NULL is ok.
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync * @param pPCHSGeometry Pointer to physical disk geometry <= (16383,16,63). Not NULL.
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync * @param pLCHSGeometry Pointer to logical disk geometry <= (x,255,63). Not NULL.
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync * @param pUuid New UUID of the image. If NULL, a new UUID is created.
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync * @param pVDIfsImage Pointer to the per-image VD interface list.
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync * @param pVDIfsOperation Pointer to the per-operation VD interface list.
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsyncVBOXDDU_DECL(int) VDCreateBase(PVBOXHDD pDisk, const char *pszBackend,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync LogFlowFunc(("pDisk=%#p pszBackend=\"%s\" pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" PCHS=%u/%u/%u LCHS=%u/%u/%u Uuid=%RTuuid uOpenFlags=%#x pVDIfsImage=%#p pVDIfsOperation=%#p\n",
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync pDisk, pszBackend, pszFilename, cbSize, uImageFlags, pszComment,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync pPCHSGeometry->cSectors, pLCHSGeometry->cCylinders,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync pLCHSGeometry->cHeads, pLCHSGeometry->cSectors, pUuid,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync PVDINTERFACE pIfProgress = VDInterfaceGet(pVDIfsOperation,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* sanity check */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER);
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* Check arguments. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync AssertMsgBreakStmt(VALID_PTR(pszBackend) && *pszBackend,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync ("pszBackend=%#p \"%s\"\n", pszBackend, pszBackend),
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync AssertMsgBreakStmt(VALID_PTR(pszFilename) && *pszFilename,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename),
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync AssertMsgBreakStmt( ((uImageFlags & ~VD_IMAGE_FLAGS_MASK) == 0)
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync || ((uImageFlags & (VD_IMAGE_FLAGS_FIXED | VD_IMAGE_FLAGS_DIFF)) != VD_IMAGE_FLAGS_FIXED),
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* The PCHS geometry fields may be 0 to leave it for later. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync ("pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pPCHSGeometry,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* The LCHS geometry fields may be 0 to leave it to later autodetection. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync ("pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pLCHSGeometry,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* The UUID may be NULL. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync AssertMsgBreakStmt(pUuid == NULL || VALID_PTR(pUuid),
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync AssertMsgBreakStmt((uOpenFlags & ~VD_OPEN_FLAGS_MASK) == 0,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* Check state. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync ("Create base image cannot be done with other images open\n"),
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* Set up image descriptor. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync rc = vdError(pDisk, VERR_INVALID_PARAMETER, RT_SRC_POS,
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync /* Create UUID if the caller didn't specify one. */
b07b4216b07447c916723417ee9b44f69c2fc11fvboxsync pImage->uOpenFlags = uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME;
int rc2;
int rc2;
if (pImage)
return rc;
LogFlowFunc(("pDisk=%#p pszBackend=\"%s\" pszFilename=\"%s\" uImageFlags=%#x pszComment=\"%s\" Uuid=%RTuuid ParentUuid=%RTuuid uOpenFlags=%#x pVDIfsImage=%#p pVDIfsOperation=%#p\n",
if (pIfProgress)
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
if (!pImage)
if (!pUuid)
unsigned uOpenFlagsPrevImg;
int rc2;
&Uuid);
&Uuid);
&Uuid);
&ts);
int rc2;
if (pImage)
return rc;
if (pIfProgress)
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
if (!pvBuf)
&cbThisRead);
&cbThisRead);
&Uuid);
&Uuid);
&Uuid);
&Uuid);
if (pvBuf)
return rc;
* @param fMoveByRename If true, attempt to perform a move by renaming (if successful the new size is ignored).
LogFlowFunc(("pDiskFrom=%#p nImage=%u pDiskTo=%#p pszBackend=\"%s\" pszFilename=\"%s\" fMoveByRename=%d cbSize=%llu pVDIfsOperation=%#p pDstVDIfsImage=%#p pDstVDIfsOperation=%#p\n",
pDiskFrom, nImage, pDiskTo, pszBackend, pszFilename, fMoveByRename, cbSize, pVDIfsOperation, pDstVDIfsImage, pDstVDIfsOperation));
if (pIfProgress)
if (pDstIfProgress)
if ( fMoveByRename
rc = pImageFrom->Backend->pfnRename(pImageFrom->pvBackendData, pszFilename ? pszFilename : pImageFrom->pszFilename);
if (cbSizeFrom == 0)
if (pDstUuid)
rc = pImageFrom->Backend->pfnGetModificationUuid(pImageFrom->pvBackendData, &ImageModificationUuid);
rc = pImageFrom->Backend->pfnGetParentModificationUuid(pImageFrom->pvBackendData, &ParentModificationUuid);
unsigned uOpenFlagsFrom;
if (pszFilename)
if (cbSize == 0)
/** @todo replace the VDCreateDiff/VDCreateBase calls by direct
if (cbSizeTo == 0)
if (cbSize == 0)
if (!pvBuf)
if (pvBuf)
return rc;
int rc;
if (pIfProgress)
if (pvBuf)
if (pvTmp)
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
if (!pImage)
if (!pImage)
int rc2;
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
int rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
unsigned cImages;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return cImages;
bool fReadOnly;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
unsigned uOpenFlags;
return fReadOnly;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return cbSize;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return cbSize;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
&PCHS);
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
&LCHS);
return rc;
unsigned *puVersion)
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
unsigned *puImageFlags)
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
unsigned *puOpenFlags)
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
unsigned uOpenFlags)
int rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
int rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
int rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
const char *pszComment)
int rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
int rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
int rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
if (!pUuid)
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
pUuid);
return rc;
int rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
if (!pUuid)
pUuid);
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
int rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
if (!pUuid)
return rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
*pfAIOSupported = false;
return rc;
void *pvUser)
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
pvUser);
return rc;
void *pvUser)
int rc;
AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
return rc;
return NULL;
return NULL;