Logo Search packages:      
Sourcecode: virtualbox-ose version File versions  Download package

VBoxHDD-new.h

Go to the documentation of this file.
/** @file
 * VBox HDD Container API.
 * Will replace VBoxHDD.h.
 */

/*
 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
 * VirtualBox OSE distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 USA or visit http://www.sun.com if you need
 * additional information or have any questions.
 */

#ifndef ___VBox_VD_h
#define ___VBox_VD_h

#include <iprt/assert.h>
#include <iprt/string.h>
#include <iprt/mem.h>
#include <VBox/cdefs.h>
#include <VBox/types.h>
#include <VBox/err.h>
/** @todo eliminate this dependency by moving data type definitions to the
 * right place. PFNVMPROGRESS and P*PDMMEDIAGEOMETRY are affected. */
#include <VBox/pdm.h>

__BEGIN_DECLS

#ifdef IN_RING0
# error "There are no VBox HDD Container APIs available in Ring-0 Host Context!"
#endif

/** @defgroup grp_vd            VBox HDD Container
 * @{
 */

/** Current VMDK image version. */
00055 #define VMDK_IMAGE_VERSION          (0x0001)

/** Current VDI image major version. */
00058 #define VDI_IMAGE_VERSION_MAJOR     (0x0001)
/** Current VDI image minor version. */
00060 #define VDI_IMAGE_VERSION_MINOR     (0x0001)
/** Current VDI image version. */
00062 #define VDI_IMAGE_VERSION           ((VDI_IMAGE_VERSION_MAJOR << 16) | VDI_IMAGE_VERSION_MINOR)

/** Get VDI major version from combined version. */
00065 #define VDI_GET_VERSION_MAJOR(uVer)    ((uVer) >> 16)
/** Get VDI minor version from combined version. */
00067 #define VDI_GET_VERSION_MINOR(uVer)    ((uVer) & 0xffff)

/** Placeholder for specifying the last opened image. */
00070 #define VD_LAST_IMAGE               0xffffffffU

/** @name VBox HDD container image types
 * @{ */
00074 typedef enum VDIMAGETYPE
{
    /** Invalid image type. Should never be returned/passed through the API. */
00077     VD_IMAGE_TYPE_INVALID   = 0,
    /** Normal dynamically growing base image file. */
00079     VD_IMAGE_TYPE_NORMAL,
    /** Preallocated base image file of a fixed size. */
00081     VD_IMAGE_TYPE_FIXED,
    /** Dynamically growing image file for undo/commit changes support. */
00083     VD_IMAGE_TYPE_UNDO,
    /** Dynamically growing image file for differencing support. */
00085     VD_IMAGE_TYPE_DIFF,

    /** First valid image type value. */
00088     VD_IMAGE_TYPE_FIRST     = VD_IMAGE_TYPE_NORMAL,
    /** Last valid image type value. */
00090     VD_IMAGE_TYPE_LAST      = VD_IMAGE_TYPE_DIFF
} VDIMAGETYPE;
/** Pointer to VBox HDD container image type. */
00093 typedef VDIMAGETYPE *PVDIMAGETYPE;
/** @} */

/** @name VBox HDD container image flags
 * @{
 */
/** No flags. */
00100 #define VD_IMAGE_FLAGS_NONE                 (0)
/** VMDK: Split image into 2GB extents. */
00102 #define VD_VMDK_IMAGE_FLAGS_SPLIT_2G        (0x0001)
/** VMDK: Raw disk image (giving access to a number of host partitions). */
00104 #define VD_VMDK_IMAGE_FLAGS_RAWDISK         (0x0002)
/** VDI: Fill new blocks with zeroes while expanding image file. Only valid
 * for newly created images, never set for opened existing images. */
00107 #define VD_VDI_IMAGE_FLAGS_ZERO_EXPAND      (0x0100)

/** Mask of valid image flags for VMDK. */
00110 #define VD_VMDK_IMAGE_FLAGS_MASK            (VD_IMAGE_FLAGS_NONE | VD_VMDK_IMAGE_FLAGS_SPLIT_2G | VD_VMDK_IMAGE_FLAGS_RAWDISK)

/** Mask of valid image flags for VDI. */
00113 #define VD_VDI_IMAGE_FLAGS_MASK             (VD_IMAGE_FLAGS_NONE | VD_VDI_IMAGE_FLAGS_ZERO_EXPAND)

/** Mask of all valid image flags for all formats. */
00116 #define VD_IMAGE_FLAGS_MASK                 (VD_VMDK_IMAGE_FLAGS_MASK | VD_VDI_IMAGE_FLAGS_MASK)

/** Default image flags. */
00119 #define VD_IMAGE_FLAGS_DEFAULT              (VD_IMAGE_FLAGS_NONE)
/** @} */


/**
 * Auxiliary type for describing partitions on raw disks.
 */
00126 typedef struct VBOXHDDRAWPART
{
    /** Device to use for this partition. Can be the disk device if the offset
     * field is set appropriately. If this is NULL, then this partition will
     * not be accessible to the guest. The size of the partition must still
     * be set correctly. */
00132     const char      *pszRawDevice;
    /** Offset where the partition data starts in this device. */
00134     uint64_t        uPartitionStartOffset;
    /** Offset where the partition data starts in the disk. */
00136     uint64_t        uPartitionStart;
    /** Size of the partition. */
00138     uint64_t        cbPartition;
    /** Size of the partitioning info to prepend. */
00140     uint64_t        cbPartitionData;
    /** Offset where the partitioning info starts in the disk. */
00142     uint64_t        uPartitionDataStart;
    /** Pointer to the partitioning info to prepend. */
00144     const void      *pvPartitionData;
} VBOXHDDRAWPART, *PVBOXHDDRAWPART;

/**
 * Auxiliary data structure for creating raw disks.
 */
00150 typedef struct VBOXHDDRAW
{
    /** Signature for structure. Must be 'R', 'A', 'W', '\0'. Actually a trick
     * to make logging of the comment string produce sensible results. */
00154     char            szSignature[4];
    /** Flag whether access to full disk should be given (ignoring the
     * partition information below). */
00157     bool            fRawDisk;
    /** Filename for the raw disk. Ignored for partitioned raw disks.
     * For Linux e.g. /dev/sda, and for Windows e.g. \\.\PhysicalDisk0. */
00160     const char      *pszRawDisk;
    /** Number of entries in the partitions array. */
00162     unsigned        cPartitions;
    /** Pointer to the partitions array. */
00164     PVBOXHDDRAWPART pPartitions;
} VBOXHDDRAW, *PVBOXHDDRAW;

/** @name VBox HDD container image open mode flags
 * @{
 */
/** Try to open image in read/write exclusive access mode if possible, or in read-only elsewhere. */
00171 #define VD_OPEN_FLAGS_NORMAL        0
/** Open image in read-only mode with sharing access with others. */
00173 #define VD_OPEN_FLAGS_READONLY      RT_BIT(0)
/** Honor zero block writes instead of ignoring them whenever possible.
 * This is not supported by all formats. It is silently ignored in this case. */
00176 #define VD_OPEN_FLAGS_HONOR_ZEROES  RT_BIT(1)
/** Honor writes of the same data instead of ignoring whenever possible.
 * This is handled generically, and is only meaningful for differential image
 * formats. It is silently ignored otherwise. */
00180 #define VD_OPEN_FLAGS_HONOR_SAME    RT_BIT(2)
/** Do not perform the base/diff image check on open. This does NOT imply
 * opening the image as readonly (would break e.g. adding UUIDs to VMDK files
 * created by other products). Images opened with this flag should only be
 * used for querying information, and nothing else. */
00185 #define VD_OPEN_FLAGS_INFO          RT_BIT(3)
/** Open image for asynchronous access.
 *  Only available if VD_CAP_ASYNC_IO is set
 *  Check with VDIsAsynchonousIoSupported wether
 *  asynchronous I/O is really supported for this file.
 */
00191 #define VD_OPEN_FLAGS_ASYNC_IO      RT_BIT(4)
/** Mask of valid flags. */
00193 #define VD_OPEN_FLAGS_MASK          (VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_HONOR_ZEROES | VD_OPEN_FLAGS_HONOR_SAME | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO)
/** @}*/


/** @name VBox HDD container backend capability flags
 * @{
 */
/** Supports UUIDs as expected by VirtualBox code. */
00201 #define VD_CAP_UUID                 RT_BIT(0)
/** Supports creating fixed size images, allocating all space instantly. */
00203 #define VD_CAP_CREATE_FIXED         RT_BIT(1)
/** Supports creating dynamically growing images, allocating space on demand. */
00205 #define VD_CAP_CREATE_DYNAMIC       RT_BIT(2)
/** Supports creating images split in chunks of a bit less than 2GBytes. */
00207 #define VD_CAP_CREATE_SPLIT_2G      RT_BIT(3)
/** Supports being used as differencing image format backend. */
00209 #define VD_CAP_DIFF                 RT_BIT(4)
/** Supports asynchronous I/O operations for at least some configurations. */
00211 #define VD_CAP_ASYNC                RT_BIT(5)
/** The backend operates on files. The caller needs to know to handle the
 * location appropriately. */
00214 #define VD_CAP_FILE                 RT_BIT(6)
/** The backend uses the config interface. The caller needs to know how to
 * provide the mandatory configuration parts this way. */
00217 #define VD_CAP_CONFIG               RT_BIT(7)
/** @}*/

/**
 * Supported interface types.
 */
00223 typedef enum VDINTERFACETYPE
{
    /** First valid interface. */
00226     VDINTERFACETYPE_FIRST = 0,
    /** Interface to pass error message to upper layers. Per-disk. */
00228     VDINTERFACETYPE_ERROR = VDINTERFACETYPE_FIRST,
    /** Interface for asynchronous I/O operations. Per-disk. */
00230     VDINTERFACETYPE_ASYNCIO,
    /** Interface for progress notification. Per-operation. */
00232     VDINTERFACETYPE_PROGRESS,
    /** Interface for configuration information. Per-image. */
00234     VDINTERFACETYPE_CONFIG,
    /** invalid interface. */
00236     VDINTERFACETYPE_INVALID
} VDINTERFACETYPE;

/**
 * Common structure for all interfaces.
 */
00242 typedef struct VDINTERFACE
{
    /** Human readable interface name. */
00245     const char         *pszInterfaceName;
    /** The size of the struct. */
00247     uint32_t            cbSize;
    /** Pointer to the next common interface structure. */
00249     struct VDINTERFACE *pNext;
    /** Interface type. */
00251     VDINTERFACETYPE     enmInterface;
    /** Opaque user data which is passed on every call. */
00253     void               *pvUser;
    /** Pointer to the function call table of the interface. 
     *  As this is opaque this must be casted to the right interface
     *  struct defined below based on the interface type in enmInterface. */
00257     void               *pCallbacks;
} VDINTERFACE, *PVDINTERFACE;
/** Pointer to a const PVDINTERFACE. */
00260 typedef const PVDINTERFACE PCVDINTERFACE;

/**
 * Helper functions to handle interface lists.
 *
 * @note These interface lists are used consistently to pass per-disk,
 * per-image and/or per-operation callbacks. Those three purposes are strictly
 * separate. See the individual interface declarations for what context they
 * apply to. The caller is responsible for ensuring that the lifetime of the
 * interface descriptors is appropriate for the category of interface.
 */

/**
 * Get a specific interface from a list of interfaces specified by the type.
 *
 * @return  Pointer to the matching interface or NULL if none was found.
 * @param   pVDIfs          Pointer to the VD interface list.
 * @param   enmInterface    Interface to search for.
 */
DECLINLINE(PVDINTERFACE) VDInterfaceGet(PVDINTERFACE pVDIfs, VDINTERFACETYPE enmInterface)
{
    AssertMsgReturn(   (enmInterface >= VDINTERFACETYPE_FIRST)
                    && (enmInterface < VDINTERFACETYPE_INVALID),
                    ("enmInterface=%u", enmInterface), NULL);

    while (pVDIfs)
    {
        /* Sanity checks. */
        AssertMsgBreak(pVDIfs->cbSize == sizeof(VDINTERFACE),
                       ("cbSize=%u\n", pVDIfs->cbSize));
                       
        if (pVDIfs->enmInterface == enmInterface)
            return pVDIfs;
        pVDIfs = pVDIfs->pNext;
    }

    /* No matching interface was found. */
    return NULL;
}

/**
 * Add an interface to a list of interfaces.
 *
 * @return VBox status code.
 * @param  pInterface   Pointer to an unitialized common interface structure.
 * @param  pszName      Name of the interface.
 * @param  enmInterface Type of the interface.
 * @param  pCallbacks   The callback table of the interface.
 * @param  pvUser       Opaque user data passed on every function call.
 * @param  ppVDIfs      Pointer to the VD interface list.
 */
DECLINLINE(int) VDInterfaceAdd(PVDINTERFACE pInterface, const char *pszName,
                               VDINTERFACETYPE enmInterface, void *pCallbacks,
                               void *pvUser, PVDINTERFACE *ppVDIfs)
{

    /** Argument checks. */
    AssertMsgReturn(   (enmInterface >= VDINTERFACETYPE_FIRST)
                    && (enmInterface < VDINTERFACETYPE_INVALID),
                    ("enmInterface=%u", enmInterface), VERR_INVALID_PARAMETER);

    AssertMsgReturn(VALID_PTR(pCallbacks),
                    ("pCallbacks=%#p", pCallbacks),
                    VERR_INVALID_PARAMETER);

    AssertMsgReturn(VALID_PTR(ppVDIfs),
                    ("pInterfaceList=%#p", ppVDIfs),
                    VERR_INVALID_PARAMETER);

    /* Fill out interface descriptor. */
    pInterface->cbSize           = sizeof(VDINTERFACE);
    pInterface->pszInterfaceName = pszName;
    pInterface->enmInterface     = enmInterface;
    pInterface->pCallbacks       = pCallbacks;
    pInterface->pvUser           = pvUser;
    pInterface->pNext            = *ppVDIfs;

    /* Remember the new start of the list. */
    *ppVDIfs = pInterface;

    return VINF_SUCCESS;
}

/**
 * Interface to deliver error messages to upper layers.
 *
 * Per disk interface. Optional, but think twice if you want to miss the
 * opportunity of reporting better human-readable error messages.
 */
typedef struct VDINTERFACEERROR
{
    /**
     * Size of the error interface.
     */
    uint32_t    cbSize;

    /**
     * Interface type.
     */
    VDINTERFACETYPE enmInterface;

    /**
     * Error message callback.
     *
     * @param   pvUser          The opaque data passed on container creation.
     * @param   rc              The VBox error code.
     * @param   RT_SRC_POS_DECL Use RT_SRC_POS.
     * @param   pszFormat       Error message format string.
     * @param   va              Error message arguments.
     */
    DECLR3CALLBACKMEMBER(void, pfnError, (void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va));

} VDINTERFACEERROR, *PVDINTERFACEERROR;

/**
 * Get error interface from opaque callback table.
 *
 * @return Pointer to the callback table.
 * @param  pInterface Pointer to the interface descriptor.
 */
00380 DECLINLINE(PVDINTERFACEERROR) VDGetInterfaceError(PVDINTERFACE pInterface)
{
    /* Check that the interface descriptor is a error interface. */
    AssertMsgReturn(   (pInterface->enmInterface == VDINTERFACETYPE_ERROR)
                    && (pInterface->cbSize == sizeof(VDINTERFACE)),
                    ("Not an error interface"), NULL);

    PVDINTERFACEERROR pInterfaceError = (PVDINTERFACEERROR)pInterface->pCallbacks;

    /* Do basic checks. */
    AssertMsgReturn(   (pInterfaceError->cbSize == sizeof(VDINTERFACEERROR))
                    && (pInterfaceError->enmInterface == VDINTERFACETYPE_ERROR),
                    ("A non error callback table attached to a error interface descriptor\n"), NULL);

    return pInterfaceError;
}

/** 
 * Completion callback which is called by the interface owner
 * to inform the backend that a task finished.
 *
 * @return  VBox status code.
 * @param   pvUser          Opaque user data which is passed on request submission.
 */
typedef DECLCALLBACK(int) FNVDCOMPLETED(void *pvUser);
/** Pointer to FNVDCOMPLETED() */
00406 typedef FNVDCOMPLETED *PFNVDCOMPLETED;


/**
 * Support interface for asynchronous I/O
 *
 * Per-disk. Optional.
 */
00414 typedef struct VDINTERFACEASYNCIO
{
    /**
     * Size of the async interface.
     */
00419     uint32_t    cbSize;

    /**
     * Interface type.
     */
00424     VDINTERFACETYPE enmInterface;

    /**
     * Open callback
     *
     * @return  VBox status code.
     * @param   pvUser          The opaque data passed on container creation.
     * @param   pszLocation     Name of the location to open.
     * @param   fReadonly       Whether to open the storage medium read only.
     * @param   ppStorage       Where to store the opaque storage handle.
     */
    DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation, bool fReadonly, void **ppStorage));

    /**
     * Close callback.
     *
     * @return  VBox status code.
     * @param   pvUser          The opaque data passed on container creation.
     * @param   pStorage        The opaque storage handle to close.
     */
    DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvUser, void *pStorage));

    /**
     * Synchronous write callback.
     *
     * @return  VBox status code.
     * @param   pvUser          The opaque data passed on container creation.
     * @param   pStorage        The storage handle to use.
     * @param   uOffset         The offset to start from.
     * @├żaram   cbWrite         How many bytes to write.
     * @param   pvBuf           Pointer to the bits need to be written.
     * @param   pcbWritten      Where to store how many bytes where actually written.
     */
    DECLR3CALLBACKMEMBER(int, pfnWrite, (void *pvUser, void *pStorage, uint64_t uOffset, 
                                         size_t cbWrite, const void *pvBuf, size_t *pcbWritten));

    /**
     * Synchronous read callback.
     *
     * @return  VBox status code.
     * @param   pvUser          The opaque data passed on container creation.
     * @param   pStorage        The storage handle to use.
     * @param   uOffset         The offset to start from.
     * @├żaram   cbRead          How many bytes to read.
     * @param   pvBuf           Where to store the read bits.
     * @param   pcbRead         Where to store how many bytes where actually read.
     */
    DECLR3CALLBACKMEMBER(int, pfnRead, (void *pvUser, void *pStorage, uint64_t uOffset, 
                                        size_t cbRead, void *pvBuf, size_t *pcbRead));

    /**
     * Flush data to the storage backend.
     *
     * @return  VBox statis code.
     * @param   pvUser          The opaque data passed on container creation.
     * @param   pStorage        The storage handle to flush.
     */
    DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pvUser, void *pStorage));

    /**
     * Prepare an asynchronous read task.
     *
     * @return  VBox status code.
     * @param   pvUser         The opqaue user data passed on container creation.
     * @param   pStorage       The storage handle.
     * @param   uOffset        The offset to start reading from.
     * @param   pvBuf          Where to store read bits.
     * @param   cbRead         How many bytes to read.
     * @param   ppTask         Where to store the opaque task handle.
     */
    DECLR3CALLBACKMEMBER(int, pfnPrepareRead, (void *pvUser, void *pStorage, uint64_t uOffset, 
                                               void *pvBuf, size_t cbRead, void **ppTask));

    /**
     * Prepare an asynchronous write task.
     *
     * @return  VBox status code.
     * @param   pvUser         The opaque user data passed on conatiner creation.
     * @param   pStorage       The storage handle.
     * @param   uOffset        The offset to start writing to.
     * @param   pvBuf          Where to read the data from.
     * @param   cbWrite        How many bytes to write.
     * @param   ppTask         Where to store the opaque task handle.
     */
    DECLR3CALLBACKMEMBER(int, pfnPrepareWrite, (void *pvUser, void *pStorage, uint64_t uOffset, 
                                                void *pvBuf, size_t cbWrite, void **ppTask));

    /**
     * Submit an array of tasks for processing
     *
     * @return  VBox status code.
     * @param   pvUser        The opaque user data passed on container creation.
     * @param   apTasks       Array of task handles to submit.
     * @param   cTasks        How many tasks to submit.
     * @param   pvUser2       User data which is passed on completion.
     * @param   pvUserCaller  Opaque user data the caller of VDAsyncWrite/Read passed.
     * @param   pfnTasksCompleted Pointer to callback which is called on request completion.
     */
    DECLR3CALLBACKMEMBER(int, pfnTasksSubmit, (void *pvUser, void *apTasks[], unsigned cTasks, void *pvUser2,
                                               void *pvUserCaller, PFNVDCOMPLETED pfnTasksCompleted));

} VDINTERFACEASYNCIO, *PVDINTERFACEASYNCIO;

/**
 * Get async I/O interface from opaque callback table.
 *
 * @return Pointer to the callback table.
 * @param  pInterface Pointer to the interface descriptor.
 */
00533 DECLINLINE(PVDINTERFACEASYNCIO) VDGetInterfaceAsyncIO(PVDINTERFACE pInterface)
{
    /* Check that the interface descriptor is a async I/O interface. */
    AssertMsgReturn(   (pInterface->enmInterface == VDINTERFACETYPE_ASYNCIO)
                    && (pInterface->cbSize == sizeof(VDINTERFACE)),
                    ("Not an async I/O interface"), NULL);

    PVDINTERFACEASYNCIO pInterfaceAsyncIO = (PVDINTERFACEASYNCIO)pInterface->pCallbacks;

    /* Do basic checks. */
    AssertMsgReturn(   (pInterfaceAsyncIO->cbSize == sizeof(VDINTERFACEASYNCIO))
                    && (pInterfaceAsyncIO->enmInterface == VDINTERFACETYPE_ASYNCIO),
                    ("A non async I/O callback table attached to a async I/O interface descriptor\n"), NULL);

    return pInterfaceAsyncIO;
}

/**
 * Progress notification interface
 * 
 * Per-operation. Optional.
 */
00555 typedef struct VDINTERFACEPROGRESS
{
    /**
     * Size of the progress interface.
     */
00560     uint32_t    cbSize;

    /**
     * Interface type.
     */
00565     VDINTERFACETYPE enmInterface;

    /**
     * Progress notification callbacks.
     */
00570     PFNVMPROGRESS   pfnProgress;
} VDINTERFACEPROGRESS, *PVDINTERFACEPROGRESS;

/**
 * Get progress interface from opaque callback table.
 *
 * @return Pointer to the callback table.
 * @param  pInterface Pointer to the interface descriptor.
 */
00579 DECLINLINE(PVDINTERFACEPROGRESS) VDGetInterfaceProgress(PVDINTERFACE pInterface)
{
    /* Check that the interface descriptor is a progress interface. */
    AssertMsgReturn(   (pInterface->enmInterface == VDINTERFACETYPE_PROGRESS)
                    && (pInterface->cbSize == sizeof(VDINTERFACE)),
                    ("Not a progress interface"), NULL);


    PVDINTERFACEPROGRESS pInterfaceProgress = (PVDINTERFACEPROGRESS)pInterface->pCallbacks;

    /* Do basic checks. */
    AssertMsgReturn(   (pInterfaceProgress->cbSize == sizeof(VDINTERFACEPROGRESS))
                    && (pInterfaceProgress->enmInterface == VDINTERFACETYPE_PROGRESS),
                    ("A non progress callback table attached to a progress interface descriptor\n"), NULL);

    return pInterfaceProgress;
}

/** Configuration node for configuration information interface. */
00598 typedef struct VDCFGNODE *PVDCFGNODE;

/**
 * Configuration value type for configuration information interface.
 */
00603 typedef enum VDCFGVALUETYPE
{
    /** Integer value. */
00606     VDCFGVALUETYPE_INTEGER = 1,
    /** String value. */
00608     VDCFGVALUETYPE_STRING,
    /** Bytestring value. */
00610     VDCFGVALUETYPE_BYTES
} VDCFGVALUETYPE;
/** Pointer to configuration value type for configuration information interface. */
00613 typedef VDCFGVALUETYPE *PVDCFGVALUETYPE;

/**
 * Configuration value. This is not identical to CFGMVALUE.
 */
00618 typedef union VDCFGVALUE
{
    /** Integer value. */
00621     struct VDCFGVALUE_INTEGER
    {
        /** The integer represented as 64-bit unsigned. */
00624         uint64_t    u64;
    } Integer;

    /** String value. (UTF-8 of course) */
00628     struct VDCFGVALUE_STRING
    {
        /** Pointer to the string. */
00631         char        *psz;
    } String;

    /** Byte string value. */
00635     struct VDCFGVALUE_BYTES
    {
        /** Length of byte string. (in bytes) */
00638         RTUINT      cb;
        /** Pointer to the byte string. */
00640         void        *pv;
    } Bytes;
} VDCFGVALUE, *PVDCFGVALUE;

/**
 * Configuration information interface
 *
 * Per-image. Optional for most backends, but mandatory for images which do
 * not operate on files (including standard block or character devices).
 */
00650 typedef struct VDINTERFACECONFIG
{
    /**
     * Size of the configuration interface.
     */
00655     uint32_t    cbSize;

    /**
     * Interface type.
     */
00660     VDINTERFACETYPE enmInterface;

    /**
     * Validates that the values are within a set of valid names.
     *
     * @return  true if all names are found in pszzAllowed.
     * @return  false if not.
     * @param   pNode           The node which values should be examined.
     * @param   pszzValid       List of valid names separated by '\\0' and ending with
     *                          a double '\\0'.
     */
    DECLR3CALLBACKMEMBER(bool, pfnAreValuesValid, (PVDCFGNODE pNode, const char *pszzValid));
    DECLR3CALLBACKMEMBER(int, pfnQueryType, (PVDCFGNODE pNode, const char *pszName, PVDCFGVALUETYPE penmType));
    DECLR3CALLBACKMEMBER(int, pfnQuerySize, (PVDCFGNODE pNode, const char *pszName, size_t *pcb));
    DECLR3CALLBACKMEMBER(int, pfnQueryInteger, (PVDCFGNODE pNode, const char *pszName, uint64_t *pu64));
    DECLR3CALLBACKMEMBER(int, pfnQueryIntegerDef, (PVDCFGNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def));
    DECLR3CALLBACKMEMBER(int, pfnQueryString, (PVDCFGNODE pNode, const char *pszName, char *pszString, size_t cchString));
    DECLR3CALLBACKMEMBER(int, pfnQueryStringDef, (PVDCFGNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef));
    DECLR3CALLBACKMEMBER(int, pfnQueryBytes, (PVDCFGNODE pNode, const char *pszName, void *pvData, size_t cbData));
} VDINTERFACECONFIG, *PVDINTERFACECONFIG;

/**
 * Get configuration information interface from opaque callback table.
 *
 * @return Pointer to the callback table.
 * @param  pInterface Pointer to the interface descriptor.
 */
00687 DECLINLINE(PVDINTERFACECONFIG) VDGetInterfaceConfig(PVDINTERFACE pInterface)
{
    /* Check that the interface descriptor is a progress interface. */
    AssertMsgReturn(   (pInterface->enmInterface == VDINTERFACETYPE_CONFIG)
                    && (pInterface->cbSize == sizeof(VDINTERFACE)),
                    ("Not a config interface"), NULL);

    PVDINTERFACECONFIG pInterfaceConfig = (PVDINTERFACECONFIG)pInterface->pCallbacks;

    /* Do basic checks. */
    AssertMsgReturn(   (pInterfaceConfig->cbSize == sizeof(VDINTERFACECONFIG))
                    && (pInterfaceConfig->enmInterface == VDINTERFACETYPE_CONFIG),
                    ("A non config callback table attached to a config interface descriptor\n"), NULL);

    return pInterfaceConfig;
}

/**
 * Query configuration, validates that the values are within a set of valid names.
 *
 * @returns true if all names are found in pszzAllowed.
 * @returns false if not.
 * @param   pCfgIf      Pointer to configuration callback table.
 * @param   pNode       The node which values should be examined.
 * @param   pszzValid   List of valid names separated by '\\0' and ending with
 *                      a double '\\0'.
 */
DECLINLINE(bool) VDCFGAreValuesValid(PVDINTERFACECONFIG pCfgIf,
00715                                      PVDCFGNODE pNode,
                                     const char *pszzValid)
{
    return pCfgIf->pfnAreValuesValid(pNode, pszzValid);
}

/**
 * Query configuration, unsigned 64-bit integer value with default.
 * 
 * @return  VBox status code.
 * @param   pCfgIf      Pointer to configuration callback table.
 * @param   pNode       Which node to search for pszName in.
 * @param   pszName     Name of an integer value
 * @param   pu64        Where to store the value. Set to default on failure.
 * @param   u64Def      The default value.
 */
DECLINLINE(int) VDCFGQueryU64Def(PVDINTERFACECONFIG pCfgIf, PVDCFGNODE pNode,
                                 const char *pszName, uint64_t *pu64,
                                 uint64_t u64Def)
{
    return pCfgIf->pfnQueryIntegerDef(pNode, pszName, pu64, u64Def);
}

/**
 * Query configuration, unsigned 32-bit integer value with default.
 * 
 * @return  VBox status code.
 * @param   pCfgIf      Pointer to configuration callback table.
 * @param   pNode       Which node to search for pszName in.
 * @param   pszName     Name of an integer value
 * @param   pu32        Where to store the value. Set to default on failure.
 * @param   u32Def      The default value.
 */
DECLINLINE(int) VDCFGQueryU32Def(PVDINTERFACECONFIG pCfgIf, PVDCFGNODE pNode,
                                 const char *pszName, uint32_t *pu32,
                                 uint32_t u32Def)
{
    uint64_t u64;
    int rc = pCfgIf->pfnQueryIntegerDef(pNode, pszName, &u64, u32Def);
    if (VBOX_SUCCESS(rc))
    {
        if (!(u64 & UINT64_C(0xffffffff00000000)))
            *pu32 = (uint32_t)u64;
        else
            rc = VERR_CFGM_INTEGER_TOO_BIG;
    }
    return rc;
}

/**
 * Query configuration, bool value with default.
 * 
 * @return  VBox status code.
 * @param   pCfgIf      Pointer to configuration callback table.
 * @param   pNode       Which node to search for pszName in.
 * @param   pszName     Name of an integer value
 * @param   pf          Where to store the value. Set to default on failure.
 * @param   fDef        The default value.
 */
DECLINLINE(int) VDCFGQueryBoolDef(PVDINTERFACECONFIG pCfgIf, PVDCFGNODE pNode,
                                  const char *pszName, bool *pf,
                                  bool fDef)
{
    uint64_t u64;
    int rc = pCfgIf->pfnQueryIntegerDef(pNode, pszName, &u64, fDef);
    if (VBOX_SUCCESS(rc))
        *pf = u64 ? true : false;
    return rc;
}

/**
 * Query configuration, dynamically allocated (RTMemAlloc) zero terminated
 * character value.
 * 
 * @return  VBox status code.
 * @param   pCfgIf      Pointer to configuration callback table.
 * @param   pNode       Which node to search for pszName in.
 * @param   pszName     Name of an zero terminated character value
 * @param   ppszString  Where to store the string pointer. Not set on failure.
 *                      Free this using RTMemFree().
 */
DECLINLINE(int) VDCFGQueryStringAlloc(PVDINTERFACECONFIG pCfgIf,
                                      PVDCFGNODE pNode,
                                      const char *pszName,
                                      char **ppszString)
{
    size_t cch;
    int rc = pCfgIf->pfnQuerySize(pNode, pszName, &cch);
    if (VBOX_SUCCESS(rc))
    {
        char *pszString = (char *)RTMemAlloc(cch);
        if (pszString)
        {
            rc = pCfgIf->pfnQueryString(pNode, pszName, pszString, cch);
            if (VBOX_SUCCESS(rc))
                *ppszString = pszString;
            else
                RTMemFree(pszString);
        }
        else
            rc = VERR_NO_MEMORY;
    }
    return rc;
}

/**
 * Query configuration, dynamically allocated (RTMemAlloc) zero terminated
 * character value with default.
 * 
 * @return  VBox status code.
 * @param   pCfgIf      Pointer to configuration callback table.
 * @param   pNode       Which node to search for pszName in.
 * @param   pszName     Name of an zero terminated character value
 * @param   ppszString  Where to store the string pointer. Not set on failure.
 *                      Free this using RTMemFree().
 * @param   pszDef      The default value.
 */
DECLINLINE(int) VDCFGQueryStringAllocDef(PVDINTERFACECONFIG pCfgIf,
                                         PVDCFGNODE pNode,
                                         const char *pszName,
                                         char **ppszString,
                                         const char *pszDef)
{
    size_t cch;
    int rc = pCfgIf->pfnQuerySize(pNode, pszName, &cch);
    if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
    {
        cch = strlen(pszDef) + 1;
        rc = VINF_SUCCESS;
    }
    if (VBOX_SUCCESS(rc))
    {
        char *pszString = (char *)RTMemAlloc(cch);
        if (pszString)
        {
            rc = pCfgIf->pfnQueryStringDef(pNode, pszName, pszString, cch, pszDef);
            if (VBOX_SUCCESS(rc))
                *ppszString = pszString;
            else
                RTMemFree(pszString);
        }
        else
            rc = VERR_NO_MEMORY;
    }
    return rc;
}

/**
 * Query configuration, dynamically allocated (RTMemAlloc) byte string value.
 * 
 * @return  VBox status code.
 * @param   pCfgIf      Pointer to configuration callback table.
 * @param   pNode       Which node to search for pszName in.
 * @param   pszName     Name of an zero terminated character value
 * @param   ppvData     Where to store the byte string pointer. Not set on failure.
 *                      Free this using RTMemFree().
 * @param   pcbData     Where to store the byte string length.
 */
DECLINLINE(int) VDCFGQueryBytesAlloc(PVDINTERFACECONFIG pCfgIf,
                                     PVDCFGNODE pNode, const char *pszName,
                                     void **ppvData, size_t *pcbData)
{
    size_t cb;
    int rc = pCfgIf->pfnQuerySize(pNode, pszName, &cb);
    if (VBOX_SUCCESS(rc))
    {
        char *pvData = (char *)RTMemAlloc(cb);
        if (pvData)
        {
            rc = pCfgIf->pfnQueryBytes(pNode, pszName, pvData, cb);
            if (VBOX_SUCCESS(rc))
            {
                *ppvData = pvData;
                *pcbData = cb;
            }
            else
                RTMemFree(pvData);
        }
        else
            rc = VERR_NO_MEMORY;
    }
    return rc;
}


/** @name Configuration interface key handling flags.
 * @{
 */
/** Mandatory config key. Not providing a value for this key will cause
 * the backend to fail. */
#define VD_CFGKEY_MANDATORY         RT_BIT(0)
/** Expert config key. Not showing it by default in the GUI is is probably
 * a good idea, as the average user won't understand it easily. */
#define VD_CFGKEY_EXPERT            RT_BIT(1)
/** @}*/

/**
 * Structure describing configuration keys required/supported by a backend
 * through the config interface.
 */
typedef struct VDCONFIGINFO
{
    /** Key name of the configuration. */
    const char *pszKey;
    /** Pointer to default value (descriptor). NULL if no useful default value
     * can be specified. */
    const PVDCFGVALUE pDefaultValue;
    /** Value type for this key. */
    VDCFGVALUETYPE enmValueType;
    /** Key handling flags (a combination of VD_CFGKEY_* flags). */
    uint64_t uKeyFlags;
} VDCONFIGINFO;

/** Pointer to structure describing configuration keys. */
typedef VDCONFIGINFO *PVDCONFIGINFO;

/** Pointer to const structure describing configuration keys. */
00932 typedef const VDCONFIGINFO *PCVDCONFIGINFO;

/**
 * Data structure for returning a list of backend capabilities.
 */
00937 typedef struct VDBACKENDINFO
{
    /** Name of the backend. */
00940     char *pszBackend;
    /** Capabilities of the backend (a combination of the VD_CAP_* flags). */
00942     uint64_t uBackendCaps;
    /** Pointer to a NULL-terminated array of strings, containing the supported
     * file extensions. Note that some backends do not work on files, so this
     * pointer may just contain NULL. */
00946     const char * const *papszFileExtensions;
    /** Pointer to an array of structs describing each supported config key.
     * Terminated by a NULL config key. Note that some backends do not support
     * the configuration interface, so this pointer may just contain NULL.
     * Mandatory if the backend sets VD_CAP_CONFIG. */
00951     PCVDCONFIGINFO paConfigInfo;
} VDBACKENDINFO, *PVDBACKENDINFO;


/**
 * VBox HDD Container main structure.
 */
/* Forward declaration, VBOXHDD structure is visible only inside VBox HDD module. */
struct VBOXHDD;
typedef struct VBOXHDD VBOXHDD;
typedef VBOXHDD *PVBOXHDD;


/**
 * Lists all HDD backends and their capabilities in a caller-provided buffer.
 * Free all returned names with RTStrFree() when you no longer need them.
 *
 * @return  VBox status code.
 *          VERR_BUFFER_OVERFLOW if not enough space is passed.
 * @param   cEntriesAlloc   Number of list entries available.
 * @param   pEntries        Pointer to array for the entries.
 * @param   pcEntriesUsed   Number of entries returned.
 */
VBOXDDU_DECL(int) VDBackendInfo(unsigned cEntriesAlloc, PVDBACKENDINFO pEntries,
                                unsigned *pcEntriesUsed);

/**
 * Lists the capablities of a backend indentified by its name.
 * Free all returned names with RTStrFree() when you no longer need them.
 *
 * @return  VBox status code.
 * @param   pszBackend      The backend name.
 * @param   pEntries        Pointer to an entry.
 */
VBOXDDU_DECL(int) VDBackendInfoOne(const char *pszBackend, PVDBACKENDINFO pEntry);

/**
 * Allocates and initializes an empty HDD container.
 * No image files are opened.
 *
 * @return  VBox status code.
 * @param   pVDIfsDisk      Pointer to the per-disk VD interface list.
 * @param   ppDisk          Where to store the reference to HDD container.
 */
VBOXDDU_DECL(int) VDCreate(PVDINTERFACE pVDIfsDisk, PVBOXHDD *ppDisk);

/**
 * Destroys HDD container.
 * If container has opened image files they will be closed.
 *
 * @param   pDisk           Pointer to HDD container.
 */
VBOXDDU_DECL(void) VDDestroy(PVBOXHDD pDisk);

/**
 * Try to get the backend name which can use this image.
 *
 * @return  VBox status code.
 * @param   pszFilename     Name of the image file for which the backend is queried.
 * @param   ppszFormat      Receives pointer of the UTF-8 string which contains the format name.
 *                          The returned pointer must be freed using RTStrFree().
 */
VBOXDDU_DECL(int) VDGetFormat(const char *pszFilename, char **ppszFormat);

/**
 * Opens an image file.
 *
 * The first opened image file in HDD container must have a base image type,
 * others (next opened images) must be differencing or undo images.
 * Linkage is checked for differencing image to be consistent with the previously opened image.
 * When another differencing image is opened and the last image was opened in read/write access
 * mode, then the last image is reopened in read-only with deny write sharing mode. This allows
 * other processes to use images in read-only mode too.
 *
 * Note that the image is opened in read-only mode if a read/write open is not possible.
 * Use VDIsReadOnly to check open mode.
 *
 * @return  VBox status code.
 * @param   pDisk           Pointer to HDD container.
 * @param   pszBackend      Name of the image file backend to use.
 * @param   pszFilename     Name of the image file to open.
 * @param   uOpenFlags      Image file open mode, see VD_OPEN_FLAGS_* constants.
 * @param   pVDIfsImage     Pointer to the per-image VD interface list.
 */
VBOXDDU_DECL(int) VDOpen(PVBOXHDD pDisk, const char *pszBackend,
                         const char *pszFilename, unsigned uOpenFlags,
                         PVDINTERFACE pVDIfsImage);

/**
 * Creates and opens a new base image file.
 *
 * @return  VBox status code.
 * @param   pDisk           Pointer to HDD container.
 * @param   pszBackend      Name of the image file backend to use.
 * @param   pszFilename     Name of the image file to create.
 * @param   enmType         Image type, only base image types are acceptable.
 * @param   cbSize          Image size in bytes.
 * @param   uImageFlags     Flags specifying special image features.
 * @param   pszComment      Pointer to image comment. NULL is ok.
 * @param   pPCHSGeometry   Pointer to physical disk geometry <= (16383,16,63). Not NULL.
 * @param   pLCHSGeometry   Pointer to logical disk geometry <= (1024,255,63). Not NULL.
 * @param   pUuid           New UUID of the image. If NULL, a new UUID is created.
 * @param   uOpenFlags      Image file open mode, see VD_OPEN_FLAGS_* constants.
 * @param   pVDIfsImage     Pointer to the per-image VD interface list.
 * @param   pVDIfsOperation Pointer to the per-operation VD interface list.
 */
VBOXDDU_DECL(int) VDCreateBase(PVBOXHDD pDisk, const char *pszBackend,
                               const char *pszFilename, VDIMAGETYPE enmType,
                               uint64_t cbSize, unsigned uImageFlags,
                               const char *pszComment,
                               PCPDMMEDIAGEOMETRY pPCHSGeometry,
                               PCPDMMEDIAGEOMETRY pLCHSGeometry,
                               PCRTUUID pUuid, unsigned uOpenFlags,
                               PVDINTERFACE pVDIfsImage,
                               PVDINTERFACE pVDIfsOperation);

/**
 * Creates and opens a new differencing image file in HDD container.
 * See comments for VDOpen function about differencing images.
 *
 * @return  VBox status code.
 * @param   pDisk           Pointer to HDD container.
 * @param   pszBackend      Name of the image file backend to use.
 * @param   pszFilename     Name of the differencing image file to create.
 * @param   uImageFlags     Flags specifying special image features.
 * @param   pszComment      Pointer to image comment. NULL is ok.
 * @param   pUuid           New UUID of the image. If NULL, a new UUID is created.
 * @param   uOpenFlags      Image file open mode, see VD_OPEN_FLAGS_* constants.
 * @param   pVDIfsImage     Pointer to the per-image VD interface list.
 * @param   pVDIfsOperation Pointer to the per-operation VD interface list.
 */
VBOXDDU_DECL(int) VDCreateDiff(PVBOXHDD pDisk, const char *pszBackend,
                               const char *pszFilename, unsigned uImageFlags,
                               const char *pszComment, PCRTUUID pUuid,
                               unsigned uOpenFlags, PVDINTERFACE pVDIfsImage,
                               PVDINTERFACE pVDIfsOperation);

/**
 * Merges two images (not necessarily with direct parent/child relationship).
 * As a side effect the source image and potentially the other images which
 * are also merged to the destination are deleted from both the disk and the
 * images in the HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImageFrom      Name of the image file to merge from.
 * @param   nImageTo        Name of the image file to merge to.
 * @param   pVDIfsOperation Pointer to the per-operation VD interface list.
 */
VBOXDDU_DECL(int) VDMerge(PVBOXHDD pDisk, unsigned nImageFrom,
                          unsigned nImageTo, PVDINTERFACE pVDIfsOperation);

/**
 * Copies an image from one HDD container to another.
 * The copy is opened in the target HDD container.
 * It is possible to convert between different image formats, because the
 * backend for the destination may be different from the source.
 * If both the source and destination reference the same HDD container,
 * then the image is moved (by copying/deleting or renaming) to the new location.
 * The source container is unchanged if the move operation fails, otherwise
 * the image at the new location is opened in the same way as the old one was.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDiskFrom       Pointer to source HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pDiskTo         Pointer to destination HDD container.
 * @param   pszBackend      Name of the image file backend to use (may be NULL to use the same as the source).
 * @param   pszFilename     New name of the image (may be NULL if pDiskFrom == pDiskTo).
 * @param   fMoveByRename   If true, attempt to perform a move by renaming (if successful the new size is ignored).
 * @param   cbSize          New image size (0 means leave unchanged).
 * @param   pVDIfsOperation Pointer to the per-operation VD interface list.
 * @param   pDstVDIfsImage  Pointer to the per-image VD interface list, for the
 *                          destination image.
 * @param   pDstVDIfsOperation Pointer to the per-operation VD interface list,
 *                          for the destination operation.
 */
VBOXDDU_DECL(int) VDCopy(PVBOXHDD pDiskFrom, unsigned nImage, PVBOXHDD pDiskTo,
                         const char *pszBackend, const char *pszFilename,
                         bool fMoveByRename, uint64_t cbSize,
                         PVDINTERFACE pVDIfsOperation,
                         PVDINTERFACE pDstVDIfsImage,
                         PVDINTERFACE pDstVDIfsOperation);

/**
 * Closes the last opened image file in HDD container.
 * If previous image file was opened in read-only mode (that is normal) and closing image
 * was opened in read-write mode (the whole disk was in read-write mode) - the previous image
 * will be reopened in read/write mode.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_NOT_OPENED if no image is opened in HDD container.
 * @param   pDisk           Pointer to HDD container.
 * @param   fDelete         If true, delete the image from the host disk.
 */
VBOXDDU_DECL(int) VDClose(PVBOXHDD pDisk, bool fDelete);

/**
 * Closes all opened image files in HDD container.
 *
 * @return  VBox status code.
 * @param   pDisk           Pointer to HDD container.
 */
VBOXDDU_DECL(int) VDCloseAll(PVBOXHDD pDisk);

/**
 * Read data from virtual HDD.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_NOT_OPENED if no image is opened in HDD container.
 * @param   pDisk           Pointer to HDD container.
 * @param   uOffset         Offset of first reading byte from start of disk.
 * @param   pvBuf           Pointer to buffer for reading data.
 * @param   cbRead          Number of bytes to read.
 */
VBOXDDU_DECL(int) VDRead(PVBOXHDD pDisk, uint64_t uOffset, void *pvBuf, size_t cbRead);

/**
 * Write data to virtual HDD.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_NOT_OPENED if no image is opened in HDD container.
 * @param   pDisk           Pointer to HDD container.
 * @param   uOffset         Offset of first writing byte from start of disk.
 * @param   pvBuf           Pointer to buffer for writing data.
 * @param   cbWrite         Number of bytes to write.
 */
VBOXDDU_DECL(int) VDWrite(PVBOXHDD pDisk, uint64_t uOffset, const void *pvBuf, size_t cbWrite);

/**
 * Make sure the on disk representation of a virtual HDD is up to date.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_NOT_OPENED if no image is opened in HDD container.
 * @param   pDisk           Pointer to HDD container.
 */
VBOXDDU_DECL(int) VDFlush(PVBOXHDD pDisk);

/**
 * Get number of opened images in HDD container.
 *
 * @return  Number of opened images for HDD container. 0 if no images have been opened.
 * @param   pDisk           Pointer to HDD container.
 */
VBOXDDU_DECL(unsigned) VDGetCount(PVBOXHDD pDisk);

/**
 * Get read/write mode of HDD container.
 *
 * @return  Virtual disk ReadOnly status.
 * @return  true if no image is opened in HDD container.
 * @param   pDisk           Pointer to HDD container.
 */
VBOXDDU_DECL(bool) VDIsReadOnly(PVBOXHDD pDisk);

/**
 * Get total capacity of an image in HDD container.
 *
 * @return  Virtual disk size in bytes.
 * @return  0 if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 */
VBOXDDU_DECL(uint64_t) VDGetSize(PVBOXHDD pDisk, unsigned nImage);

/**
 * Get total file size of an image in HDD container.
 *
 * @return  Virtual disk size in bytes.
 * @return  0 if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 */
VBOXDDU_DECL(uint64_t) VDGetFileSize(PVBOXHDD pDisk, unsigned nImage);

/**
 * Get virtual disk PCHS geometry of an image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @return  VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pPCHSGeometry   Where to store PCHS geometry. Not NULL.
 */
VBOXDDU_DECL(int) VDGetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
                                    PPDMMEDIAGEOMETRY pPCHSGeometry);

/**
 * Store virtual disk PCHS geometry of an image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pPCHSGeometry   Where to load PCHS geometry from. Not NULL.
 */
VBOXDDU_DECL(int) VDSetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
                                    PCPDMMEDIAGEOMETRY pPCHSGeometry);

/**
 * Get virtual disk LCHS geometry of an image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @return  VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pLCHSGeometry   Where to store LCHS geometry. Not NULL.
 */
VBOXDDU_DECL(int) VDGetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
                                    PPDMMEDIAGEOMETRY pLCHSGeometry);

/**
 * Store virtual disk LCHS geometry of an image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pLCHSGeometry   Where to load LCHS geometry from. Not NULL.
 */
VBOXDDU_DECL(int) VDSetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
                                    PCPDMMEDIAGEOMETRY pLCHSGeometry);

/**
 * Get version of image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   puVersion       Where to store the image version.
 */
VBOXDDU_DECL(int) VDGetVersion(PVBOXHDD pDisk, unsigned nImage,
                               unsigned *puVersion);

/**
 * Get type of image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   penmType        Where to store the image type.
 */
VBOXDDU_DECL(int) VDGetImageType(PVBOXHDD pDisk, unsigned nImage,
                                 PVDIMAGETYPE penmType);

/**
 * List the capabilities of image backend in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to the HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pbackendInfo    Where to store the backend information.
 */
VBOXDDU_DECL(int) VDBackendInfoSingle(PVBOXHDD pDisk, unsigned nImage,
                                      PVDBACKENDINFO pBackendInfo);

/**
 * Get flags of image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   puImageFlags    Where to store the image flags.
 */
VBOXDDU_DECL(int) VDGetImageFlags(PVBOXHDD pDisk, unsigned nImage, unsigned *puImageFlags);

/**
 * Get open flags of image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   puOpenFlags     Where to store the image open flags.
 */
VBOXDDU_DECL(int) VDGetOpenFlags(PVBOXHDD pDisk, unsigned nImage,
                                 unsigned *puOpenFlags);

/**
 * Set open flags of image in HDD container.
 * This operation may cause file locking changes and/or files being reopened.
 * Note that in case of unrecoverable error all images in HDD container will be closed.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   uOpenFlags      Image file open mode, see VD_OPEN_FLAGS_* constants.
 */
VBOXDDU_DECL(int) VDSetOpenFlags(PVBOXHDD pDisk, unsigned nImage,
                                 unsigned uOpenFlags);

/**
 * Get base filename of image in HDD container. Some image formats use
 * other filenames as well, so don't use this for anything but informational
 * purposes.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @return  VERR_BUFFER_OVERFLOW if pszFilename buffer too small to hold filename.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pszFilename     Where to store the image file name.
 * @param   cbFilename      Size of buffer pszFilename points to.
 */
VBOXDDU_DECL(int) VDGetFilename(PVBOXHDD pDisk, unsigned nImage,
                                char *pszFilename, unsigned cbFilename);

/**
 * Get the comment line of image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @return  VERR_BUFFER_OVERFLOW if pszComment buffer too small to hold comment text.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pszComment      Where to store the comment string of image. NULL is ok.
 * @param   cbComment       The size of pszComment buffer. 0 is ok.
 */
VBOXDDU_DECL(int) VDGetComment(PVBOXHDD pDisk, unsigned nImage,
                               char *pszComment, unsigned cbComment);

/**
 * Changes the comment line of image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pszComment      New comment string (UTF-8). NULL is allowed to reset the comment.
 */
VBOXDDU_DECL(int) VDSetComment(PVBOXHDD pDisk, unsigned nImage,
                               const char *pszComment);

/**
 * Get UUID of image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pUuid           Where to store the image UUID.
 */
VBOXDDU_DECL(int) VDGetUuid(PVBOXHDD pDisk, unsigned nImage, PRTUUID pUuid);

/**
 * Set the image's UUID. Should not be used by normal applications.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pUuid           New UUID of the image. If NULL, a new UUID is created.
 */
VBOXDDU_DECL(int) VDSetUuid(PVBOXHDD pDisk, unsigned nImage, PCRTUUID pUuid);

/**
 * Get last modification UUID of image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pUuid           Where to store the image modification UUID.
 */
VBOXDDU_DECL(int) VDGetModificationUuid(PVBOXHDD pDisk, unsigned nImage,
                                        PRTUUID pUuid);

/**
 * Set the image's last modification UUID. Should not be used by normal applications.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pUuid           New modification UUID of the image. If NULL, a new UUID is created.
 */
VBOXDDU_DECL(int) VDSetModificationUuid(PVBOXHDD pDisk, unsigned nImage,
                                        PCRTUUID pUuid);

/**
 * Get parent UUID of image in HDD container.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of the container.
 * @param   pUuid           Where to store the parent image UUID.
 */
VBOXDDU_DECL(int) VDGetParentUuid(PVBOXHDD pDisk, unsigned nImage,
                                  PRTUUID pUuid);

/**
 * Set the image's parent UUID. Should not be used by normal applications.
 *
 * @return  VBox status code.
 * @param   pDisk           Pointer to HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pUuid           New parent UUID of the image. If NULL, a new UUID is created.
 */
VBOXDDU_DECL(int) VDSetParentUuid(PVBOXHDD pDisk, unsigned nImage,
                                  PCRTUUID pUuid);


/**
 * Debug helper - dumps all opened images in HDD container into the log file.
 *
 * @param   pDisk           Pointer to HDD container.
 */
VBOXDDU_DECL(void) VDDumpImages(PVBOXHDD pDisk);


/**
 * Query if asynchronous operations are supported for this disk.
 *
 * @return  VBox status code.
 * @return  VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened.
 * @param   pDisk           Pointer to the HDD container.
 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
 * @param   pfAIOSupported  Where to store if async IO is supported.
 */
VBOXDDU_DECL(int) VDImageIsAsyncIOSupported(PVBOXHDD pDisk, unsigned nImage, bool *pfAIOSupported);


/**
 * Start a asynchronous read request.
 *
 * @return  VBox status code.
 * @param   pDisk           Pointer to the HDD container.
 * @param   uOffset         The offset of the virtual disk to read from.
 * @param   cbRead          How many bytes to read.
 * @param   paSeg           Pointer to an array of segments.
 * @param   cSeg            Number of segments in the array.
 * @param   pvUser          User data which is passed on completion
 */
VBOXDDU_DECL(int) VDAsyncRead(PVBOXHDD pDisk, uint64_t uOffset, size_t cbRead, 
                              PPDMDATASEG paSeg, unsigned cSeg,
                              void *pvUser);


/**
 * Start a asynchronous write request.
 *
 * @return  VBox status code.
 * @param   pDisk           Pointer to the HDD container.
 * @param   uOffset         The offset of the virtual disk to write to.
 * @param   cbWrtie         How many bytes to write.
 * @param   paSeg           Pointer to an array of segments.
 * @param   cSeg            Number of segments in the array.
 * @param   pvUser          User data which is passed on completion.
 */
VBOXDDU_DECL(int) VDAsyncWrite(PVBOXHDD pDisk, uint64_t uOffset, size_t cbWrite,
                               PPDMDATASEG paSeg, unsigned cSeg,
                               void *pvUser);


__END_DECLS

/** @} */

#endif

Generated by  Doxygen 1.6.0   Back to index