DrvRawFile.cpp revision ad48e47654d22f79b025dc4b21cb162cb123801a
c366016ffe1788c6847d0a967a954713725cab5evboxsync/* $Id$ */
c366016ffe1788c6847d0a967a954713725cab5evboxsync/** @file
c366016ffe1788c6847d0a967a954713725cab5evboxsync * VBox stream drivers - Raw file output.
c366016ffe1788c6847d0a967a954713725cab5evboxsync */
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync/*
c366016ffe1788c6847d0a967a954713725cab5evboxsync * Copyright (C) 2006-2010 Oracle Corporation
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync *
c366016ffe1788c6847d0a967a954713725cab5evboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
c366016ffe1788c6847d0a967a954713725cab5evboxsync * available from http://www.virtualbox.org. This file is free software;
c366016ffe1788c6847d0a967a954713725cab5evboxsync * you can redistribute it and/or modify it under the terms of the GNU
c366016ffe1788c6847d0a967a954713725cab5evboxsync * General Public License (GPL) as published by the Free Software
c366016ffe1788c6847d0a967a954713725cab5evboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
c366016ffe1788c6847d0a967a954713725cab5evboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
c366016ffe1788c6847d0a967a954713725cab5evboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
c366016ffe1788c6847d0a967a954713725cab5evboxsync */
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync/*******************************************************************************
c366016ffe1788c6847d0a967a954713725cab5evboxsync* Header Files *
c366016ffe1788c6847d0a967a954713725cab5evboxsync*******************************************************************************/
c366016ffe1788c6847d0a967a954713725cab5evboxsync#define LOG_GROUP LOG_GROUP_DEFAULT
c366016ffe1788c6847d0a967a954713725cab5evboxsync#include <VBox/vmm/pdmdrv.h>
c366016ffe1788c6847d0a967a954713725cab5evboxsync#include <iprt/assert.h>
c366016ffe1788c6847d0a967a954713725cab5evboxsync#include <iprt/file.h>
c366016ffe1788c6847d0a967a954713725cab5evboxsync#include <iprt/mem.h>
c366016ffe1788c6847d0a967a954713725cab5evboxsync#include <iprt/semaphore.h>
c366016ffe1788c6847d0a967a954713725cab5evboxsync#include <iprt/stream.h>
c366016ffe1788c6847d0a967a954713725cab5evboxsync#include <iprt/string.h>
c366016ffe1788c6847d0a967a954713725cab5evboxsync#include <iprt/uuid.h>
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c1b76913eb226361b0f57efd4dc45072db194218vboxsync#include "VBoxDD.h"
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync/*******************************************************************************
c366016ffe1788c6847d0a967a954713725cab5evboxsync* Defined Constants And Macros *
c366016ffe1788c6847d0a967a954713725cab5evboxsync*******************************************************************************/
c366016ffe1788c6847d0a967a954713725cab5evboxsync/** Converts a pointer to DRVRAWFILE::IMedia to a PDRVRAWFILE. */
c366016ffe1788c6847d0a967a954713725cab5evboxsync#define PDMISTREAM_2_DRVRAWFILE(pInterface) ( (PDRVRAWFILE)((uintptr_t)pInterface - RT_OFFSETOF(DRVRAWFILE, IStream)) )
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync/*******************************************************************************
715e49c31b15c23c17a9ce3be42a75e7c48d4b78vboxsync* Structures and Typedefs *
c366016ffe1788c6847d0a967a954713725cab5evboxsync*******************************************************************************/
c366016ffe1788c6847d0a967a954713725cab5evboxsync/**
c366016ffe1788c6847d0a967a954713725cab5evboxsync * Raw file output driver instance data.
c366016ffe1788c6847d0a967a954713725cab5evboxsync *
c366016ffe1788c6847d0a967a954713725cab5evboxsync * @implements PDMISTREAM
c366016ffe1788c6847d0a967a954713725cab5evboxsync */
c366016ffe1788c6847d0a967a954713725cab5evboxsynctypedef struct DRVRAWFILE
c366016ffe1788c6847d0a967a954713725cab5evboxsync{
c366016ffe1788c6847d0a967a954713725cab5evboxsync /** The stream interface. */
c366016ffe1788c6847d0a967a954713725cab5evboxsync PDMISTREAM IStream;
c366016ffe1788c6847d0a967a954713725cab5evboxsync /** Pointer to the driver instance. */
c366016ffe1788c6847d0a967a954713725cab5evboxsync PPDMDRVINS pDrvIns;
c366016ffe1788c6847d0a967a954713725cab5evboxsync /** Pointer to the file name. (Freed by MM) */
c366016ffe1788c6847d0a967a954713725cab5evboxsync char *pszLocation;
c366016ffe1788c6847d0a967a954713725cab5evboxsync /** Flag whether VirtualBox represents the server or client side. */
783c5efe04be621d9edbe07f2a41ea9a9a35cdcevboxsync RTFILE hOutputFile;
c366016ffe1788c6847d0a967a954713725cab5evboxsync} DRVRAWFILE, *PDRVRAWFILE;
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync/* -=-=-=-=- PDMISTREAM -=-=-=-=- */
c366016ffe1788c6847d0a967a954713725cab5evboxsync
6dd8f5023a9ba7588212331db90059553136fe33vboxsync/** @copydoc PDMISTREAM::pfnWrite */
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsyncstatic DECLCALLBACK(int) drvRawFileWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite)
c366016ffe1788c6847d0a967a954713725cab5evboxsync{
c366016ffe1788c6847d0a967a954713725cab5evboxsync int rc = VINF_SUCCESS;
c366016ffe1788c6847d0a967a954713725cab5evboxsync PDRVRAWFILE pThis = PDMISTREAM_2_DRVRAWFILE(pInterface);
715e49c31b15c23c17a9ce3be42a75e7c48d4b78vboxsync LogFlow(("%s: pvBuf=%p *pcbWrite=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbWrite, pThis->pszLocation));
c366016ffe1788c6847d0a967a954713725cab5evboxsync
c366016ffe1788c6847d0a967a954713725cab5evboxsync Assert(pvBuf);
c366016ffe1788c6847d0a967a954713725cab5evboxsync if (pThis->hOutputFile != NIL_RTFILE)
c366016ffe1788c6847d0a967a954713725cab5evboxsync {
c366016ffe1788c6847d0a967a954713725cab5evboxsync size_t cbWritten;
c366016ffe1788c6847d0a967a954713725cab5evboxsync rc = RTFileWrite(pThis->hOutputFile, pvBuf, *pcbWrite, &cbWritten);
c366016ffe1788c6847d0a967a954713725cab5evboxsync#if 0
c366016ffe1788c6847d0a967a954713725cab5evboxsync /* don't flush here, takes too long and we will loose characters */
c366016ffe1788c6847d0a967a954713725cab5evboxsync if (RT_SUCCESS(rc))
c366016ffe1788c6847d0a967a954713725cab5evboxsync RTFileFlush(pThis->hOutputFile);
81abf6f533300bfe7c2109e9db1029b7a0274598vboxsync#endif
c366016ffe1788c6847d0a967a954713725cab5evboxsync *pcbWrite = cbWritten;
c366016ffe1788c6847d0a967a954713725cab5evboxsync }
LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
return rc;
}
/* -=-=-=-=- PDMIBASE -=-=-=-=- */
/**
* @interface_method_impl{PDMIBASE,pfnQueryInterface}
*/
static DECLCALLBACK(void *) drvRawFileQueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
PDRVRAWFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWFILE);
PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
PDMIBASE_RETURN_INTERFACE(pszIID, PDMISTREAM, &pThis->IStream);
return NULL;
}
/* -=-=-=-=- PDMDRVREG -=-=-=-=- */
/**
* Power off a raw output stream driver instance.
*
* This does most of the destruction work, to avoid ordering dependencies.
*
* @param pDrvIns The driver instance data.
*/
static DECLCALLBACK(void) drvRawFilePowerOff(PPDMDRVINS pDrvIns)
{
PDRVRAWFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWFILE);
LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
RTFileClose(pThis->hOutputFile);
pThis->hOutputFile = NIL_RTFILE;
}
/**
* Destruct a raw output stream driver instance.
*
* Most VM resources are freed by the VM. This callback is provided so that
* any non-VM resources can be freed correctly.
*
* @param pDrvIns The driver instance data.
*/
static DECLCALLBACK(void) drvRawFileDestruct(PPDMDRVINS pDrvIns)
{
PDRVRAWFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWFILE);
LogFlow(("%s: %s\n", __FUNCTION__, pThis->pszLocation));
PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
if (pThis->pszLocation)
MMR3HeapFree(pThis->pszLocation);
RTFileClose(pThis->hOutputFile);
pThis->hOutputFile = NIL_RTFILE;
}
/**
* Construct a raw output stream driver instance.
*
* @copydoc FNPDMDRVCONSTRUCT
*/
static DECLCALLBACK(int) drvRawFileConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
PDRVRAWFILE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWFILE);
PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
/*
* Init the static parts.
*/
pThis->pDrvIns = pDrvIns;
pThis->pszLocation = NULL;
pThis->hOutputFile = NIL_RTFILE;
/* IBase */
pDrvIns->IBase.pfnQueryInterface = drvRawFileQueryInterface;
/* IStream */
pThis->IStream.pfnWrite = drvRawFileWrite;
/*
* Read the configuration.
*/
if (!CFGMR3AreValuesValid(pCfg, "Location\0"))
AssertFailedReturn(VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES);
int rc = CFGMR3QueryStringAlloc(pCfg, "Location", &pThis->pszLocation);
if (RT_FAILURE(rc))
AssertMsgFailedReturn(("Configuration error: query \"Location\" resulted in %Rrc.\n", rc), rc);
/*
* Open the raw file.
*/
rc = RTFileOpen(&pThis->hOutputFile, pThis->pszLocation, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_NONE);
if (RT_FAILURE(rc))
{
LogRel(("RawFile%d: CreateFile failed rc=%Rrc\n", pDrvIns->iInstance));
return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("RawFile#%d failed to create the raw output file %s"), pDrvIns->iInstance, pThis->pszLocation);
}
LogFlow(("drvRawFileConstruct: location %s\n", pThis->pszLocation));
LogRel(("RawFile#%u: location %s\n", pDrvIns->iInstance, pThis->pszLocation));
return VINF_SUCCESS;
}
/**
* Raw file driver registration record.
*/
const PDMDRVREG g_DrvRawFile =
{
/* u32Version */
PDM_DRVREG_VERSION,
/* szName */
"RawFile",
/* szRCMod */
"",
/* szR0Mod */
"",
/* pszDescription */
"RawFile stream driver.",
/* fFlags */
PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
/* fClass. */
PDM_DRVREG_CLASS_STREAM,
/* cMaxInstances */
~0U,
/* cbInstance */
sizeof(DRVRAWFILE),
/* pfnConstruct */
drvRawFileConstruct,
/* pfnDestruct */
drvRawFileDestruct,
/* pfnRelocate */
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
NULL,
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnPowerOff */
drvRawFilePowerOff,
/* pfnSoftReset */
NULL,
/* u32EndVersion */
PDM_DRVREG_VERSION
};